Skip to content

Commit

Permalink
🐛 function should return the same reference while it always bindable (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
kuitos authored Jul 29, 2021
1 parent 1e4367c commit 9942fb1
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/sandbox/__tests__/common.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down
7 changes: 7 additions & 0 deletions src/sandbox/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,19 @@ 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.console、window.atob 这类,不然微应用中调用时会抛出 Illegal invocation 异常
目前没有完美的检测方式,这里通过 prototype 中是否还有可枚举的拓展方法的方式来判断
@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.
Expand All @@ -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;
}

Expand Down

1 comment on commit 9942fb1

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deploy preview for qiankun ready!

✅ Preview
https://qiankun-rhptup3s7-umijs.vercel.app

Built with commit 9942fb1.
This pull request is being automatically deployed with vercel-action

Please sign in to comment.