🏁 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
|
// window.field not be affected
|
||||||
expect(window.field).toEqual('123');
|
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];
|
boundValue[key] = value[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy prototype if bound function not have
|
// copy prototype if bound function not have but target one 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
|
// as prototype is non-enumerable mostly, we need to copy it from target function manually
|
||||||
if (value.hasOwnProperty('prototype') && !boundValue.hasOwnProperty('prototype')) {
|
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;
|
return boundValue;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ export function nextTick(cb: () => void): void {
|
||||||
|
|
||||||
const fnRegexCheckCacheMap = new WeakMap<any | FunctionConstructor, boolean>();
|
const fnRegexCheckCacheMap = new WeakMap<any | FunctionConstructor, boolean>();
|
||||||
export function isConstructable(fn: () => any | FunctionConstructor) {
|
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 =
|
const hasPrototypeMethods =
|
||||||
fn.prototype && fn.prototype.constructor === fn && Object.getOwnPropertyNames(fn.prototype).length > 1;
|
fn.prototype && fn.prototype.constructor === fn && Object.getOwnPropertyNames(fn.prototype).length > 1;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user