🏁 fix that it might throw a TypeError about reassign a readonly property error meesage in Safari (#1408)
This commit is contained in:
parent
7d534140fd
commit
60ce3982cc
|
|
@ -40,4 +40,21 @@ describe('getTargetValue', () => {
|
|||
// window.field not be affected
|
||||
expect(window.field).toEqual('123');
|
||||
});
|
||||
|
||||
it('should work well while value have a readonly prototype on its prototype chain', () => {
|
||||
function callableFunction() {}
|
||||
|
||||
const functionWithReadonlyPrototype = () => {};
|
||||
Object.defineProperty(functionWithReadonlyPrototype, 'prototype', {
|
||||
writable: false,
|
||||
enumerable: false,
|
||||
configurable: false,
|
||||
value: 123,
|
||||
});
|
||||
|
||||
Object.setPrototypeOf(callableFunction, functionWithReadonlyPrototype);
|
||||
|
||||
const boundFn = getTargetValue(window, callableFunction);
|
||||
expect(boundFn.prototype).toBe(callableFunction.prototype);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -29,10 +29,14 @@ export function getTargetValue(target: any, value: any): any {
|
|||
boundValue[key] = value[key];
|
||||
}
|
||||
|
||||
// copy prototype if bound function not have
|
||||
// mostly a bound function have no own prototype, but it not absolute in some old version browser, see https://github.com/umijs/qiankun/issues/1121
|
||||
// copy prototype if bound function not have but target one have
|
||||
// as prototype is non-enumerable mostly, we need to copy it from target function manually
|
||||
if (value.hasOwnProperty('prototype') && !boundValue.hasOwnProperty('prototype')) {
|
||||
boundValue.prototype = value.prototype;
|
||||
// we should not use assignment operator to set boundValue prototype like `boundValue.prototype = value.prototype`
|
||||
// as the assignment will also look up prototype chain while it hasn't own prototype property,
|
||||
// when the lookup succeed, the assignment will throw an TypeError like `Cannot assign to read only property 'prototype' of function` if its descriptor configured with writable false or just have a getter accessor
|
||||
// see https://github.com/umijs/qiankun/issues/1121
|
||||
Object.defineProperty(boundValue, 'prototype', { value: value.prototype, enumerable: false, writable: true });
|
||||
}
|
||||
|
||||
return boundValue;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ export function nextTick(cb: () => void): void {
|
|||
|
||||
const fnRegexCheckCacheMap = new WeakMap<any | FunctionConstructor, boolean>();
|
||||
export function isConstructable(fn: () => any | FunctionConstructor) {
|
||||
// prototype methods might be added while code running, so we need check it every time
|
||||
// prototype methods might be changed while code running, so we need check it every time
|
||||
const hasPrototypeMethods =
|
||||
fn.prototype && fn.prototype.constructor === fn && Object.getOwnPropertyNames(fn.prototype).length > 1;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user