⚡️ remove object spread operator for faster performance in big array iterator (#2812)
This commit is contained in:
parent
eff4306401
commit
e75952faed
|
|
@ -70,10 +70,15 @@ export function rebindTarget2Fn(target: any, fn: any): any {
|
||||||
'toString',
|
'toString',
|
||||||
);
|
);
|
||||||
|
|
||||||
Object.defineProperty(boundValue, 'toString', {
|
Object.defineProperty(
|
||||||
...originToStringDescriptor,
|
boundValue,
|
||||||
...(originToStringDescriptor?.get ? null : { value: () => fn.toString() }),
|
'toString',
|
||||||
});
|
Object.assign(
|
||||||
|
{},
|
||||||
|
originToStringDescriptor,
|
||||||
|
originToStringDescriptor?.get ? null : { value: () => fn.toString() },
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,27 @@ function uniq(array: Array<string | symbol>) {
|
||||||
}, Object.create(null));
|
}, Object.create(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
const cachedGlobalsInBrowser = globalsInBrowser
|
/**
|
||||||
.concat(process.env.NODE_ENV === 'test' ? ['mockNativeWindowFunction'] : [])
|
* transform array to object to enable faster element check with in operator
|
||||||
.reduce<Record<string, true>>((acc, key) => ({ ...acc, [key]: true }), Object.create(null));
|
* @param array
|
||||||
|
*/
|
||||||
|
function array2TruthyObject(array: string[]): Record<string, true> {
|
||||||
|
return array.reduce(
|
||||||
|
(acc, key) => {
|
||||||
|
acc[key] = true;
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
// Notes that babel will transpile spread operator to Object.assign({}, ...args), which will keep the prototype of Object in merged object,
|
||||||
|
// while this result used as Symbol.unscopables, it will make properties in Object.prototype always be escaped from proxy sandbox as unscopables check will look up prototype chain as well,
|
||||||
|
// such as hasOwnProperty, toString, valueOf, etc.
|
||||||
|
// so we should use Object.create(null) to create a pure object without prototype chain here.
|
||||||
|
Object.create(null),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const cachedGlobalsInBrowser = array2TruthyObject(
|
||||||
|
globalsInBrowser.concat(process.env.NODE_ENV === 'test' ? ['mockNativeWindowFunction'] : []),
|
||||||
|
);
|
||||||
function isNativeGlobalProp(prop: string): boolean {
|
function isNativeGlobalProp(prop: string): boolean {
|
||||||
return prop in cachedGlobalsInBrowser;
|
return prop in cachedGlobalsInBrowser;
|
||||||
}
|
}
|
||||||
|
|
@ -70,22 +88,14 @@ export const cachedGlobals = Array.from(
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// transform cachedGlobals to object for faster element check
|
const cachedGlobalObjects = array2TruthyObject(cachedGlobals);
|
||||||
const cachedGlobalObjects = cachedGlobals.reduce((acc, globalProp) => ({ ...acc, [globalProp]: true }), {});
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Variables who are impossible to be overwritten need to be escaped from proxy sandbox for performance reasons.
|
Variables who are impossible to be overwritten need to be escaped from proxy sandbox for performance reasons.
|
||||||
But overwritten globals must not be escaped, otherwise they will be leaked to the global scope.
|
But overwritten globals must not be escaped, otherwise they will be leaked to the global scope.
|
||||||
see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/unscopables
|
see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/unscopables
|
||||||
*/
|
*/
|
||||||
const unscopables = without(cachedGlobals, ...accessingSpiedGlobals.concat(overwrittenGlobals)).reduce(
|
const unscopables = array2TruthyObject(without(cachedGlobals, ...accessingSpiedGlobals.concat(overwrittenGlobals)));
|
||||||
(acc, key) => ({ ...acc, [key]: true }),
|
|
||||||
// Notes that babel will transpile spread operator to Object.assign({}, ...args), which will keep the prototype of Object in merged object,
|
|
||||||
// while this result used as Symbol.unscopables, it will make properties in Object.prototype always be escaped from proxy sandbox as unscopables check will look up prototype chain as well,
|
|
||||||
// such as hasOwnProperty, toString, valueOf, etc.
|
|
||||||
// so we should use Object.create(null) to create a pure object without prototype chain here.
|
|
||||||
Object.create(null),
|
|
||||||
);
|
|
||||||
|
|
||||||
const useNativeWindowForBindingsProps = new Map<PropertyKey, boolean>([
|
const useNativeWindowForBindingsProps = new Map<PropertyKey, boolean>([
|
||||||
['fetch', true],
|
['fetch', true],
|
||||||
|
|
@ -93,7 +103,7 @@ const useNativeWindowForBindingsProps = new Map<PropertyKey, boolean>([
|
||||||
]);
|
]);
|
||||||
|
|
||||||
function createFakeWindow(globalContext: Window, speedy: boolean) {
|
function createFakeWindow(globalContext: Window, speedy: boolean) {
|
||||||
// map always has the fastest performance in has check scenario
|
// map always has the fastest performance in has checked scenario
|
||||||
// see https://jsperf.com/array-indexof-vs-set-has/23
|
// see https://jsperf.com/array-indexof-vs-set-has/23
|
||||||
const propertiesWithGetter = new Map<PropertyKey, boolean>();
|
const propertiesWithGetter = new Map<PropertyKey, boolean>();
|
||||||
const fakeWindow = {} as FakeWindow;
|
const fakeWindow = {} as FakeWindow;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user