🐛 function should return the same reference while it always bindable (#1612)

This commit is contained in:
Kuitos 2021-07-29 10:21:44 +08:00 committed by GitHub
parent 761287ac3b
commit 1301e5b0af
2 changed files with 9 additions and 0 deletions

View File

@ -39,6 +39,8 @@ describe('getTargetValue', () => {
expect(result2).toStrictEqual({ field: '456' });
// window.field not be affected
expect(window.field).toEqual('123');
// reference should be stable after first running
expect(constructableFunction).toBe(getTargetValue(window, prototypeAddedAfterFirstInvocation));
});
it('should work well while value have a readonly prototype on its prototype chain', () => {

View File

@ -14,6 +14,7 @@ export function setCurrentRunningSandboxProxy(proxy: WindowProxy | null) {
currentRunningSandboxProxy = proxy;
}
const functionBoundedValueMap = new WeakMap<CallableFunction, CallableFunction>();
export function getTargetValue(target: any, value: any): any {
/*
isCallable && !isBoundedFunction && !isConstructable window.consolewindow.atob Illegal invocation
@ -21,6 +22,11 @@ export function getTargetValue(target: any, value: any): any {
@warning edge case lodash.isFunction iframe top window
*/
if (isCallable(value) && !isBoundedFunction(value) && !isConstructable(value)) {
const cachedBoundFunction = functionBoundedValueMap.get(value);
if (cachedBoundFunction) {
return cachedBoundFunction;
}
const boundValue = Function.prototype.bind.call(value, target);
// some callable function has custom fields, we need to copy the enumerable props to boundValue. such as moment function.
@ -40,6 +46,7 @@ export function getTargetValue(target: any, value: any): any {
Object.defineProperty(boundValue, 'prototype', { value: value.prototype, enumerable: false, writable: true });
}
functionBoundedValueMap.set(value, boundValue);
return boundValue;
}