mirror of
https://github.com/zebrajr/react.git
synced 2025-12-06 12:20:20 +01:00
React DevTools: Show symbols used as keys in state (#19786)
Co-authored-by: Brian Vaughn <bvaughn@fb.com>
This commit is contained in:
parent
11ee82df45
commit
917cb01a58
|
|
@ -208,6 +208,70 @@
|
||||||
return <ChildComponent customObject={new Custom()} />;
|
return <ChildComponent customObject={new Custom()} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const baseInheritedKeys = Object.create(Object.prototype, {
|
||||||
|
enumerableStringBase: {
|
||||||
|
value: 1,
|
||||||
|
writable: true,
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
[Symbol('enumerableSymbolBase')]: {
|
||||||
|
value: 1,
|
||||||
|
writable: true,
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
nonEnumerableStringBase: {
|
||||||
|
value: 1,
|
||||||
|
writable: true,
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
[Symbol('nonEnumerableSymbolBase')]: {
|
||||||
|
value: 1,
|
||||||
|
writable: true,
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const inheritedKeys = Object.create(baseInheritedKeys, {
|
||||||
|
enumerableString: {
|
||||||
|
value: 2,
|
||||||
|
writable: true,
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
nonEnumerableString: {
|
||||||
|
value: 3,
|
||||||
|
writable: true,
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
123: {
|
||||||
|
value: 3,
|
||||||
|
writable: true,
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
[Symbol('nonEnumerableSymbol')]: {
|
||||||
|
value: 2,
|
||||||
|
writable: true,
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
[Symbol('enumerableSymbol')]: {
|
||||||
|
value: 3,
|
||||||
|
writable: true,
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
function InheritedKeys() {
|
||||||
|
return <ChildComponent data={inheritedKeys} />;
|
||||||
|
}
|
||||||
|
|
||||||
const object = {
|
const object = {
|
||||||
string: "abc",
|
string: "abc",
|
||||||
longString: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKJLMNOPQRSTUVWXYZ1234567890",
|
longString: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKJLMNOPQRSTUVWXYZ1234567890",
|
||||||
|
|
@ -294,6 +358,7 @@
|
||||||
<ObjectProps />
|
<ObjectProps />
|
||||||
<UnserializableProps />
|
<UnserializableProps />
|
||||||
<CustomObject />
|
<CustomObject />
|
||||||
|
<InheritedKeys />
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -541,6 +541,9 @@ exports[`InspectedElementContext should support complex data types: 1: Inspected
|
||||||
"object_of_objects": {
|
"object_of_objects": {
|
||||||
"inner": {}
|
"inner": {}
|
||||||
},
|
},
|
||||||
|
"object_with_symbol": {
|
||||||
|
"Symbol(name)": "hello"
|
||||||
|
},
|
||||||
"proxy": {},
|
"proxy": {},
|
||||||
"react_element": {},
|
"react_element": {},
|
||||||
"regexp": {},
|
"regexp": {},
|
||||||
|
|
@ -612,6 +615,25 @@ exports[`InspectedElementContext should support objects with overridden hasOwnPr
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`InspectedElementContext should support objects with with inherited keys: 1: Inspected element 2 1`] = `
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"owners": null,
|
||||||
|
"context": null,
|
||||||
|
"hooks": null,
|
||||||
|
"props": {
|
||||||
|
"object": {
|
||||||
|
"123": 3,
|
||||||
|
"enumerableString": 2,
|
||||||
|
"Symbol(enumerableSymbol)": 3,
|
||||||
|
"enumerableStringBase": 1,
|
||||||
|
"Symbol(enumerableSymbolBase)": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"state": null
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`InspectedElementContext should support simple data types: 1: Initial inspection 1`] = `
|
exports[`InspectedElementContext should support simple data types: 1: Initial inspection 1`] = `
|
||||||
{
|
{
|
||||||
"id": 2,
|
"id": 2,
|
||||||
|
|
|
||||||
|
|
@ -537,6 +537,9 @@ describe('InspectedElementContext', () => {
|
||||||
const objectOfObjects = {
|
const objectOfObjects = {
|
||||||
inner: {string: 'abc', number: 123, boolean: true},
|
inner: {string: 'abc', number: 123, boolean: true},
|
||||||
};
|
};
|
||||||
|
const objectWithSymbol = {
|
||||||
|
[Symbol('name')]: 'hello',
|
||||||
|
};
|
||||||
const typedArray = Int8Array.from([100, -100, 0]);
|
const typedArray = Int8Array.from([100, -100, 0]);
|
||||||
const arrayBuffer = typedArray.buffer;
|
const arrayBuffer = typedArray.buffer;
|
||||||
const dataView = new DataView(arrayBuffer);
|
const dataView = new DataView(arrayBuffer);
|
||||||
|
|
@ -580,6 +583,7 @@ describe('InspectedElementContext', () => {
|
||||||
map={mapShallow}
|
map={mapShallow}
|
||||||
map_of_maps={mapOfMaps}
|
map_of_maps={mapOfMaps}
|
||||||
object_of_objects={objectOfObjects}
|
object_of_objects={objectOfObjects}
|
||||||
|
object_with_symbol={objectWithSymbol}
|
||||||
proxy={proxyInstance}
|
proxy={proxyInstance}
|
||||||
react_element={<span />}
|
react_element={<span />}
|
||||||
regexp={/abc/giu}
|
regexp={/abc/giu}
|
||||||
|
|
@ -633,6 +637,7 @@ describe('InspectedElementContext', () => {
|
||||||
map,
|
map,
|
||||||
map_of_maps,
|
map_of_maps,
|
||||||
object_of_objects,
|
object_of_objects,
|
||||||
|
object_with_symbol,
|
||||||
proxy,
|
proxy,
|
||||||
react_element,
|
react_element,
|
||||||
regexp,
|
regexp,
|
||||||
|
|
@ -737,6 +742,8 @@ describe('InspectedElementContext', () => {
|
||||||
);
|
);
|
||||||
expect(object_of_objects.inner[meta.preview_short]).toBe('{…}');
|
expect(object_of_objects.inner[meta.preview_short]).toBe('{…}');
|
||||||
|
|
||||||
|
expect(object_with_symbol['Symbol(name)']).toBe('hello');
|
||||||
|
|
||||||
expect(proxy[meta.inspectable]).toBe(false);
|
expect(proxy[meta.inspectable]).toBe(false);
|
||||||
expect(proxy[meta.name]).toBe('function');
|
expect(proxy[meta.name]).toBe('function');
|
||||||
expect(proxy[meta.type]).toBe('function');
|
expect(proxy[meta.type]).toBe('function');
|
||||||
|
|
@ -939,6 +946,111 @@ describe('InspectedElementContext', () => {
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should support objects with with inherited keys', async done => {
|
||||||
|
const Example = () => null;
|
||||||
|
|
||||||
|
const base = Object.create(Object.prototype, {
|
||||||
|
enumerableStringBase: {
|
||||||
|
value: 1,
|
||||||
|
writable: true,
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
[Symbol('enumerableSymbolBase')]: {
|
||||||
|
value: 1,
|
||||||
|
writable: true,
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
nonEnumerableStringBase: {
|
||||||
|
value: 1,
|
||||||
|
writable: true,
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
[Symbol('nonEnumerableSymbolBase')]: {
|
||||||
|
value: 1,
|
||||||
|
writable: true,
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const object = Object.create(base, {
|
||||||
|
enumerableString: {
|
||||||
|
value: 2,
|
||||||
|
writable: true,
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
nonEnumerableString: {
|
||||||
|
value: 3,
|
||||||
|
writable: true,
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
[123]: {
|
||||||
|
value: 3,
|
||||||
|
writable: true,
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
[Symbol('nonEnumerableSymbol')]: {
|
||||||
|
value: 2,
|
||||||
|
writable: true,
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
[Symbol('enumerableSymbol')]: {
|
||||||
|
value: 3,
|
||||||
|
writable: true,
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const container = document.createElement('div');
|
||||||
|
await utils.actAsync(() =>
|
||||||
|
ReactDOM.render(<Example object={object} />, container),
|
||||||
|
);
|
||||||
|
|
||||||
|
const id = ((store.getElementIDAtIndex(0): any): number);
|
||||||
|
|
||||||
|
let inspectedElement = null;
|
||||||
|
|
||||||
|
function Suspender({target}) {
|
||||||
|
const {getInspectedElement} = React.useContext(InspectedElementContext);
|
||||||
|
inspectedElement = getInspectedElement(id);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
await utils.actAsync(
|
||||||
|
() =>
|
||||||
|
TestRenderer.create(
|
||||||
|
<Contexts
|
||||||
|
defaultSelectedElementID={id}
|
||||||
|
defaultSelectedElementIndex={0}>
|
||||||
|
<React.Suspense fallback={null}>
|
||||||
|
<Suspender target={id} />
|
||||||
|
</React.Suspense>
|
||||||
|
</Contexts>,
|
||||||
|
),
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(inspectedElement).not.toBeNull();
|
||||||
|
expect(inspectedElement).toMatchSnapshot(`1: Inspected element ${id}`);
|
||||||
|
expect(inspectedElement.props.object).toEqual({
|
||||||
|
123: 3,
|
||||||
|
'Symbol(enumerableSymbol)': 3,
|
||||||
|
'Symbol(enumerableSymbolBase)': 1,
|
||||||
|
enumerableString: 2,
|
||||||
|
enumerableStringBase: 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
it('should not dehydrate nested values until explicitly requested', async done => {
|
it('should not dehydrate nested values until explicitly requested', async done => {
|
||||||
const Example = () => {
|
const Example = () => {
|
||||||
const [state] = React.useState({
|
const [state] = React.useState({
|
||||||
|
|
|
||||||
|
|
@ -236,6 +236,29 @@ Object {
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`InspectedElementContext should support objects with with inherited keys: 1: Initial inspection 1`] = `
|
||||||
|
Object {
|
||||||
|
"id": 2,
|
||||||
|
"type": "full-data",
|
||||||
|
"value": {
|
||||||
|
"id": 2,
|
||||||
|
"owners": null,
|
||||||
|
"context": {},
|
||||||
|
"hooks": null,
|
||||||
|
"props": {
|
||||||
|
"data": {
|
||||||
|
"123": 3,
|
||||||
|
"enumerableString": 2,
|
||||||
|
"Symbol(enumerableSymbol)": 3,
|
||||||
|
"enumerableStringBase": 1,
|
||||||
|
"Symbol(enumerableSymbolBase)": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"state": null
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`InspectedElementContext should support simple data types: 1: Initial inspection 1`] = `
|
exports[`InspectedElementContext should support simple data types: 1: Initial inspection 1`] = `
|
||||||
Object {
|
Object {
|
||||||
"id": 2,
|
"id": 2,
|
||||||
|
|
|
||||||
|
|
@ -432,6 +432,81 @@ describe('InspectedElementContext', () => {
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should support objects with with inherited keys', async done => {
|
||||||
|
const Example = () => null;
|
||||||
|
|
||||||
|
const base = Object.create(Object.prototype, {
|
||||||
|
enumerableStringBase: {
|
||||||
|
value: 1,
|
||||||
|
writable: true,
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
[Symbol('enumerableSymbolBase')]: {
|
||||||
|
value: 1,
|
||||||
|
writable: true,
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
nonEnumerableStringBase: {
|
||||||
|
value: 1,
|
||||||
|
writable: true,
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
[Symbol('nonEnumerableSymbolBase')]: {
|
||||||
|
value: 1,
|
||||||
|
writable: true,
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const object = Object.create(base, {
|
||||||
|
enumerableString: {
|
||||||
|
value: 2,
|
||||||
|
writable: true,
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
nonEnumerableString: {
|
||||||
|
value: 3,
|
||||||
|
writable: true,
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
[123]: {
|
||||||
|
value: 3,
|
||||||
|
writable: true,
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
[Symbol('nonEnumerableSymbol')]: {
|
||||||
|
value: 2,
|
||||||
|
writable: true,
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
[Symbol('enumerableSymbol')]: {
|
||||||
|
value: 3,
|
||||||
|
writable: true,
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
act(() =>
|
||||||
|
ReactDOM.render(<Example data={object} />, document.createElement('div')),
|
||||||
|
);
|
||||||
|
|
||||||
|
const id = ((store.getElementIDAtIndex(0): any): number);
|
||||||
|
const inspectedElement = await read(id);
|
||||||
|
|
||||||
|
expect(inspectedElement).toMatchSnapshot('1: Initial inspection');
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
it('should not dehydrate nested values until explicitly requested', async done => {
|
it('should not dehydrate nested values until explicitly requested', async done => {
|
||||||
const Example = () => null;
|
const Example = () => null;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
import {
|
import {
|
||||||
getDataType,
|
getDataType,
|
||||||
getDisplayNameForReactElement,
|
getDisplayNameForReactElement,
|
||||||
|
getAllEnumerableKeys,
|
||||||
getInObject,
|
getInObject,
|
||||||
formatDataForPreview,
|
formatDataForPreview,
|
||||||
setInObject,
|
setInObject,
|
||||||
|
|
@ -291,16 +292,17 @@ export function dehydrate(
|
||||||
return createDehydrated(type, true, data, cleaned, path);
|
return createDehydrated(type, true, data, cleaned, path);
|
||||||
} else {
|
} else {
|
||||||
const object = {};
|
const object = {};
|
||||||
for (const name in data) {
|
getAllEnumerableKeys(data).forEach(key => {
|
||||||
|
const name = key.toString();
|
||||||
object[name] = dehydrate(
|
object[name] = dehydrate(
|
||||||
data[name],
|
data[key],
|
||||||
cleaned,
|
cleaned,
|
||||||
unserializable,
|
unserializable,
|
||||||
path.concat([name]),
|
path.concat([name]),
|
||||||
isPathAllowed,
|
isPathAllowed,
|
||||||
isPathAllowedCheck ? 1 : level + 1,
|
isPathAllowedCheck ? 1 : level + 1,
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
38
packages/react-devtools-shared/src/utils.js
vendored
38
packages/react-devtools-shared/src/utils.js
vendored
|
|
@ -52,16 +52,41 @@ const cachedDisplayNames: WeakMap<Function, string> = new WeakMap();
|
||||||
// Try to reuse the already encoded strings.
|
// Try to reuse the already encoded strings.
|
||||||
const encodedStringCache = new LRU({max: 1000});
|
const encodedStringCache = new LRU({max: 1000});
|
||||||
|
|
||||||
export function alphaSortKeys(a: string, b: string): number {
|
export function alphaSortKeys(
|
||||||
if (a > b) {
|
a: string | number | Symbol,
|
||||||
|
b: string | number | Symbol,
|
||||||
|
): number {
|
||||||
|
if (a.toString() > b.toString()) {
|
||||||
return 1;
|
return 1;
|
||||||
} else if (b > a) {
|
} else if (b.toString() > a.toString()) {
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getAllEnumerableKeys(
|
||||||
|
obj: Object,
|
||||||
|
): Array<string | number | Symbol> {
|
||||||
|
const keys = [];
|
||||||
|
let current = obj;
|
||||||
|
while (current != null) {
|
||||||
|
const currentKeys = [
|
||||||
|
...Object.keys(current),
|
||||||
|
...Object.getOwnPropertySymbols(current),
|
||||||
|
];
|
||||||
|
const descriptors = Object.getOwnPropertyDescriptors(current);
|
||||||
|
currentKeys.forEach(key => {
|
||||||
|
// $FlowFixMe: key can be a Symbol https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyDescriptor
|
||||||
|
if (descriptors[key].enumerable) {
|
||||||
|
keys.push(key);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
current = Object.getPrototypeOf(current);
|
||||||
|
}
|
||||||
|
return keys;
|
||||||
|
}
|
||||||
|
|
||||||
export function getDisplayName(
|
export function getDisplayName(
|
||||||
type: Function,
|
type: Function,
|
||||||
fallbackName: string = 'Anonymous',
|
fallbackName: string = 'Anonymous',
|
||||||
|
|
@ -657,7 +682,7 @@ export function formatDataForPreview(
|
||||||
return data.toString();
|
return data.toString();
|
||||||
case 'object':
|
case 'object':
|
||||||
if (showFormattedValue) {
|
if (showFormattedValue) {
|
||||||
const keys = Object.keys(data).sort(alphaSortKeys);
|
const keys = getAllEnumerableKeys(data).sort(alphaSortKeys);
|
||||||
|
|
||||||
let formatted = '';
|
let formatted = '';
|
||||||
for (let i = 0; i < keys.length; i++) {
|
for (let i = 0; i < keys.length; i++) {
|
||||||
|
|
@ -665,7 +690,10 @@ export function formatDataForPreview(
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
formatted += ', ';
|
formatted += ', ';
|
||||||
}
|
}
|
||||||
formatted += `${key}: ${formatDataForPreview(data[key], false)}`;
|
formatted += `${key.toString()}: ${formatDataForPreview(
|
||||||
|
data[key],
|
||||||
|
false,
|
||||||
|
)}`;
|
||||||
if (formatted.length > MAX_PREVIEW_STRING_LENGTH) {
|
if (formatted.length > MAX_PREVIEW_STRING_LENGTH) {
|
||||||
// Prevent doing a lot of unnecessary iteration...
|
// Prevent doing a lot of unnecessary iteration...
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import CustomObject from './CustomObject';
|
||||||
import EdgeCaseObjects from './EdgeCaseObjects.js';
|
import EdgeCaseObjects from './EdgeCaseObjects.js';
|
||||||
import NestedProps from './NestedProps';
|
import NestedProps from './NestedProps';
|
||||||
import SimpleValues from './SimpleValues';
|
import SimpleValues from './SimpleValues';
|
||||||
|
import SymbolKeys from './SymbolKeys';
|
||||||
|
|
||||||
// TODO Add Immutable JS example
|
// TODO Add Immutable JS example
|
||||||
|
|
||||||
|
|
@ -32,6 +33,7 @@ export default function InspectableElements() {
|
||||||
<CustomObject />
|
<CustomObject />
|
||||||
<EdgeCaseObjects />
|
<EdgeCaseObjects />
|
||||||
<CircularReferences />
|
<CircularReferences />
|
||||||
|
<SymbolKeys />
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
78
packages/react-devtools-shell/src/app/InspectableElements/SymbolKeys.js
vendored
Normal file
78
packages/react-devtools-shell/src/app/InspectableElements/SymbolKeys.js
vendored
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*
|
||||||
|
* @flow
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as React from 'react';
|
||||||
|
|
||||||
|
const base = Object.create(Object.prototype, {
|
||||||
|
enumerableStringBase: {
|
||||||
|
value: 1,
|
||||||
|
writable: true,
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
[Symbol('enumerableSymbolBase')]: {
|
||||||
|
value: 1,
|
||||||
|
writable: true,
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
nonEnumerableStringBase: {
|
||||||
|
value: 1,
|
||||||
|
writable: true,
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
[Symbol('nonEnumerableSymbolBase')]: {
|
||||||
|
value: 1,
|
||||||
|
writable: true,
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = Object.create(base, {
|
||||||
|
enumerableString: {
|
||||||
|
value: 2,
|
||||||
|
writable: true,
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
nonEnumerableString: {
|
||||||
|
value: 3,
|
||||||
|
writable: true,
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
[123]: {
|
||||||
|
value: 3,
|
||||||
|
writable: true,
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
[Symbol('nonEnumerableSymbol')]: {
|
||||||
|
value: 2,
|
||||||
|
writable: true,
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
[Symbol('enumerableSymbol')]: {
|
||||||
|
value: 3,
|
||||||
|
writable: true,
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default function SymbolKeys() {
|
||||||
|
return <ChildComponent data={data} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ChildComponent(props: any) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user