🐛 keep toString always return original value for function in sandbox (#1785)
* fix: correct toString for functions * Update src/sandbox/common.ts * Update src/sandbox/common.ts * handle getter in toString descriptor * toString function predict Co-authored-by: Kuitos <kuitos.lau@gmail.com>
This commit is contained in:
parent
b86fffcdbe
commit
e807cbcfb6
|
|
@ -59,4 +59,24 @@ describe('getTargetValue', () => {
|
||||||
const boundFn = getTargetValue(window, callableFunction);
|
const boundFn = getTargetValue(window, callableFunction);
|
||||||
expect(boundFn.prototype).toBe(callableFunction.prototype);
|
expect(boundFn.prototype).toBe(callableFunction.prototype);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should work well while function's toString()'s return value keeps the same as the origin", () => {
|
||||||
|
function callableFunction1() {}
|
||||||
|
function callableFunction2() {}
|
||||||
|
function callableFunction3() {}
|
||||||
|
callableFunction2.toString = () => 'instance toString';
|
||||||
|
Object.defineProperty(callableFunction3, 'toString', {
|
||||||
|
get() {
|
||||||
|
return () => 'instance toString';
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const boundFn1 = getTargetValue(window, callableFunction1);
|
||||||
|
const boundFn2 = getTargetValue(window, callableFunction2);
|
||||||
|
const boundFn3 = getTargetValue(window, callableFunction3);
|
||||||
|
|
||||||
|
expect(boundFn1.toString()).toBe(callableFunction1.toString());
|
||||||
|
expect(boundFn2.toString()).toBe(callableFunction2.toString());
|
||||||
|
expect(boundFn3.toString()).toBe(callableFunction3.toString());
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,25 @@ export function getTargetValue(target: any, value: any): any {
|
||||||
Object.defineProperty(boundValue, 'prototype', { value: value.prototype, enumerable: false, writable: true });
|
Object.defineProperty(boundValue, 'prototype', { value: value.prototype, enumerable: false, writable: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Some util, like `function isNative() { return typeof Ctor === 'function' && /native code/.test(Ctor.toString()) }` relies on the original `toString()` result
|
||||||
|
// but bound functions will always return "function() {[native code]}" for `toString`, which is misleading
|
||||||
|
if (typeof value.toString === 'function') {
|
||||||
|
const valueHasInstanceToString = value.hasOwnProperty('toString') && !boundValue.hasOwnProperty('toString');
|
||||||
|
const boundValueHasPrototypeToString = boundValue.toString === Function.prototype.toString;
|
||||||
|
|
||||||
|
if (valueHasInstanceToString || boundValueHasPrototypeToString) {
|
||||||
|
const originToStringDescriptor = Object.getOwnPropertyDescriptor(
|
||||||
|
valueHasInstanceToString ? value : Function.prototype,
|
||||||
|
'toString',
|
||||||
|
);
|
||||||
|
|
||||||
|
Object.defineProperty(boundValue, 'toString', {
|
||||||
|
...originToStringDescriptor,
|
||||||
|
...(originToStringDescriptor?.get ? null : { value: () => value.toString() }),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
functionBoundedValueMap.set(value, boundValue);
|
functionBoundedValueMap.set(value, boundValue);
|
||||||
return boundValue;
|
return boundValue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user