⚡️ 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',
|
||||
);
|
||||
|
||||
Object.defineProperty(boundValue, 'toString', {
|
||||
...originToStringDescriptor,
|
||||
...(originToStringDescriptor?.get ? null : { value: () => fn.toString() }),
|
||||
});
|
||||
Object.defineProperty(
|
||||
boundValue,
|
||||
'toString',
|
||||
Object.assign(
|
||||
{},
|
||||
originToStringDescriptor,
|
||||
originToStringDescriptor?.get ? null : { value: () => fn.toString() },
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,9 +24,27 @@ function uniq(array: Array<string | symbol>) {
|
|||
}, Object.create(null));
|
||||
}
|
||||
|
||||
const cachedGlobalsInBrowser = globalsInBrowser
|
||||
.concat(process.env.NODE_ENV === 'test' ? ['mockNativeWindowFunction'] : [])
|
||||
.reduce<Record<string, true>>((acc, key) => ({ ...acc, [key]: true }), Object.create(null));
|
||||
/**
|
||||
* transform array to object to enable faster element check with in operator
|
||||
* @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 {
|
||||
return prop in cachedGlobalsInBrowser;
|
||||
}
|
||||
|
|
@ -70,22 +88,14 @@ export const cachedGlobals = Array.from(
|
|||
),
|
||||
);
|
||||
|
||||
// transform cachedGlobals to object for faster element check
|
||||
const cachedGlobalObjects = cachedGlobals.reduce((acc, globalProp) => ({ ...acc, [globalProp]: true }), {});
|
||||
const cachedGlobalObjects = array2TruthyObject(cachedGlobals);
|
||||
|
||||
/*
|
||||
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.
|
||||
see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/unscopables
|
||||
*/
|
||||
const unscopables = without(cachedGlobals, ...accessingSpiedGlobals.concat(overwrittenGlobals)).reduce(
|
||||
(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 unscopables = array2TruthyObject(without(cachedGlobals, ...accessingSpiedGlobals.concat(overwrittenGlobals)));
|
||||
|
||||
const useNativeWindowForBindingsProps = new Map<PropertyKey, boolean>([
|
||||
['fetch', true],
|
||||
|
|
@ -93,7 +103,7 @@ const useNativeWindowForBindingsProps = new Map<PropertyKey, 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
|
||||
const propertiesWithGetter = new Map<PropertyKey, boolean>();
|
||||
const fakeWindow = {} as FakeWindow;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user