@zstackui/qiankun 2.6.3-beta-5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +116 -0
- package/dist/index.umd.js +8681 -0
- package/dist/index.umd.js.map +1 -0
- package/dist/index.umd.min.js +4 -0
- package/dist/index.umd.min.js.map +1 -0
- package/dist/src/__tests__/globalState.test.d.ts +5 -0
- package/dist/src/__tests__/utils.test.d.ts +1 -0
- package/dist/src/addons/engineFlag.d.ts +6 -0
- package/dist/src/addons/index.d.ts +6 -0
- package/dist/src/addons/runtimePublicPath.d.ts +6 -0
- package/dist/src/apis.d.ts +7 -0
- package/dist/src/effects.d.ts +3 -0
- package/dist/src/error.d.ts +3 -0
- package/dist/src/errorHandler.d.ts +7 -0
- package/dist/src/globalState.d.ts +7 -0
- package/dist/src/index.d.ts +11 -0
- package/dist/src/interfaces.d.ts +107 -0
- package/dist/src/loader.d.ts +8 -0
- package/dist/src/prefetch.d.ts +14 -0
- package/dist/src/sandbox/__tests__/common.test.d.ts +5 -0
- package/dist/src/sandbox/__tests__/proxySandbox.test.d.ts +10 -0
- package/dist/src/sandbox/common.d.ts +21 -0
- package/dist/src/sandbox/index.d.ts +40 -0
- package/dist/src/sandbox/legacy/__tests__/sandbox.test.d.ts +5 -0
- package/dist/src/sandbox/legacy/sandbox.d.ts +28 -0
- package/dist/src/sandbox/patchers/__tests__/css.test.d.ts +5 -0
- package/dist/src/sandbox/patchers/__tests__/interval.test.d.ts +5 -0
- package/dist/src/sandbox/patchers/css.d.ts +17 -0
- package/dist/src/sandbox/patchers/dynamicAppend/__tests__/common.test.d.ts +1 -0
- package/dist/src/sandbox/patchers/dynamicAppend/common.d.ts +22 -0
- package/dist/src/sandbox/patchers/dynamicAppend/forLooseSandbox.d.ts +17 -0
- package/dist/src/sandbox/patchers/dynamicAppend/forStrictSandbox.d.ts +12 -0
- package/dist/src/sandbox/patchers/dynamicAppend/index.d.ts +6 -0
- package/dist/src/sandbox/patchers/historyListener.d.ts +5 -0
- package/dist/src/sandbox/patchers/index.d.ts +9 -0
- package/dist/src/sandbox/patchers/interval.d.ts +5 -0
- package/dist/src/sandbox/patchers/windowListener.d.ts +5 -0
- package/dist/src/sandbox/proxySandbox.d.ts +23 -0
- package/dist/src/sandbox/snapshotSandbox.d.ts +20 -0
- package/dist/src/utils.d.ts +44 -0
- package/dist/src/version.d.ts +1 -0
- package/es/addons/engineFlag.d.ts +6 -0
- package/es/addons/engineFlag.js +50 -0
- package/es/addons/index.d.ts +6 -0
- package/es/addons/index.js +13 -0
- package/es/addons/runtimePublicPath.d.ts +6 -0
- package/es/addons/runtimePublicPath.js +57 -0
- package/es/apis.d.ts +7 -0
- package/es/apis.js +278 -0
- package/es/effects.d.ts +3 -0
- package/es/effects.js +33 -0
- package/es/error.d.ts +3 -0
- package/es/error.js +16 -0
- package/es/errorHandler.d.ts +7 -0
- package/es/errorHandler.js +13 -0
- package/es/globalState.d.ts +7 -0
- package/es/globalState.js +101 -0
- package/es/index.d.ts +11 -0
- package/es/index.js +11 -0
- package/es/interfaces.d.ts +107 -0
- package/es/interfaces.js +8 -0
- package/es/loader.d.ts +8 -0
- package/es/loader.js +600 -0
- package/es/prefetch.d.ts +14 -0
- package/es/prefetch.js +125 -0
- package/es/sandbox/common.d.ts +21 -0
- package/es/sandbox/common.js +157 -0
- package/es/sandbox/index.d.ts +40 -0
- package/es/sandbox/index.js +105 -0
- package/es/sandbox/legacy/sandbox.d.ts +28 -0
- package/es/sandbox/legacy/sandbox.js +142 -0
- package/es/sandbox/patchers/css.d.ts +17 -0
- package/es/sandbox/patchers/css.js +186 -0
- package/es/sandbox/patchers/dynamicAppend/common.d.ts +22 -0
- package/es/sandbox/patchers/dynamicAppend/common.js +306 -0
- package/es/sandbox/patchers/dynamicAppend/forLooseSandbox.d.ts +17 -0
- package/es/sandbox/patchers/dynamicAppend/forLooseSandbox.js +77 -0
- package/es/sandbox/patchers/dynamicAppend/forStrictSandbox.d.ts +12 -0
- package/es/sandbox/patchers/dynamicAppend/forStrictSandbox.js +103 -0
- package/es/sandbox/patchers/dynamicAppend/index.d.ts +6 -0
- package/es/sandbox/patchers/dynamicAppend/index.js +6 -0
- package/es/sandbox/patchers/historyListener.d.ts +5 -0
- package/es/sandbox/patchers/historyListener.js +54 -0
- package/es/sandbox/patchers/index.d.ts +9 -0
- package/es/sandbox/patchers/index.js +45 -0
- package/es/sandbox/patchers/interval.d.ts +5 -0
- package/es/sandbox/patchers/interval.js +34 -0
- package/es/sandbox/patchers/windowListener.d.ts +5 -0
- package/es/sandbox/patchers/windowListener.js +34 -0
- package/es/sandbox/proxySandbox.d.ts +23 -0
- package/es/sandbox/proxySandbox.js +315 -0
- package/es/sandbox/snapshotSandbox.d.ts +20 -0
- package/es/sandbox/snapshotSandbox.js +59 -0
- package/es/utils.d.ts +44 -0
- package/es/utils.js +215 -0
- package/es/version.d.ts +1 -0
- package/es/version.js +1 -0
- package/lib/addons/engineFlag.d.ts +6 -0
- package/lib/addons/engineFlag.js +55 -0
- package/lib/addons/index.d.ts +6 -0
- package/lib/addons/index.js +21 -0
- package/lib/addons/runtimePublicPath.d.ts +6 -0
- package/lib/addons/runtimePublicPath.js +63 -0
- package/lib/apis.d.ts +7 -0
- package/lib/apis.js +288 -0
- package/lib/effects.d.ts +3 -0
- package/lib/effects.js +42 -0
- package/lib/error.d.ts +3 -0
- package/lib/error.js +23 -0
- package/lib/errorHandler.d.ts +7 -0
- package/lib/errorHandler.js +33 -0
- package/lib/globalState.d.ts +7 -0
- package/lib/globalState.js +110 -0
- package/lib/index.d.ts +11 -0
- package/lib/index.js +89 -0
- package/lib/interfaces.d.ts +107 -0
- package/lib/interfaces.js +14 -0
- package/lib/loader.d.ts +8 -0
- package/lib/loader.js +606 -0
- package/lib/prefetch.d.ts +14 -0
- package/lib/prefetch.js +132 -0
- package/lib/sandbox/common.d.ts +21 -0
- package/lib/sandbox/common.js +169 -0
- package/lib/sandbox/index.d.ts +40 -0
- package/lib/sandbox/index.js +123 -0
- package/lib/sandbox/legacy/sandbox.d.ts +28 -0
- package/lib/sandbox/legacy/sandbox.js +148 -0
- package/lib/sandbox/patchers/css.d.ts +17 -0
- package/lib/sandbox/patchers/css.js +193 -0
- package/lib/sandbox/patchers/dynamicAppend/common.d.ts +22 -0
- package/lib/sandbox/patchers/dynamicAppend/common.js +322 -0
- package/lib/sandbox/patchers/dynamicAppend/forLooseSandbox.d.ts +17 -0
- package/lib/sandbox/patchers/dynamicAppend/forLooseSandbox.js +84 -0
- package/lib/sandbox/patchers/dynamicAppend/forStrictSandbox.d.ts +12 -0
- package/lib/sandbox/patchers/dynamicAppend/forStrictSandbox.js +110 -0
- package/lib/sandbox/patchers/dynamicAppend/index.d.ts +6 -0
- package/lib/sandbox/patchers/dynamicAppend/index.js +19 -0
- package/lib/sandbox/patchers/historyListener.d.ts +5 -0
- package/lib/sandbox/patchers/historyListener.js +62 -0
- package/lib/sandbox/patchers/index.d.ts +9 -0
- package/lib/sandbox/patchers/index.js +57 -0
- package/lib/sandbox/patchers/interval.d.ts +5 -0
- package/lib/sandbox/patchers/interval.js +42 -0
- package/lib/sandbox/patchers/windowListener.d.ts +5 -0
- package/lib/sandbox/patchers/windowListener.js +42 -0
- package/lib/sandbox/proxySandbox.d.ts +23 -0
- package/lib/sandbox/proxySandbox.js +321 -0
- package/lib/sandbox/snapshotSandbox.d.ts +20 -0
- package/lib/sandbox/snapshotSandbox.js +65 -0
- package/lib/utils.d.ts +44 -0
- package/lib/utils.js +240 -0
- package/lib/version.d.ts +1 -0
- package/lib/version.js +7 -0
- package/package.json +137 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author Kuitos
|
|
3
|
+
* @since 2020-10-13
|
|
4
|
+
*/
|
|
5
|
+
import { nativeGlobal } from '../../../utils';
|
|
6
|
+
import { getCurrentRunningApp } from '../../common';
|
|
7
|
+
import { isHijackingTag, patchHTMLDynamicAppendPrototypeFunctions, rawHeadAppendChild, rebuildCSSRules, recordStyledComponentsCSSRules } from './common';
|
|
8
|
+
// Get native global window with a sandbox disgusted way, thus we could share it between qiankun instances🤪
|
|
9
|
+
Object.defineProperty(nativeGlobal, '__proxyAttachContainerConfigMap__', {
|
|
10
|
+
enumerable: false,
|
|
11
|
+
writable: true
|
|
12
|
+
});
|
|
13
|
+
// Share proxyAttachContainerConfigMap between multiple qiankun instance, thus they could access the same record
|
|
14
|
+
nativeGlobal.__proxyAttachContainerConfigMap__ = nativeGlobal.__proxyAttachContainerConfigMap__ || new WeakMap();
|
|
15
|
+
var proxyAttachContainerConfigMap = nativeGlobal.__proxyAttachContainerConfigMap__;
|
|
16
|
+
var elementAttachContainerConfigMap = new WeakMap();
|
|
17
|
+
var docCreatePatchedMap = new WeakMap();
|
|
18
|
+
function patchDocumentCreateElement() {
|
|
19
|
+
var docCreateElementFnBeforeOverwrite = docCreatePatchedMap.get(document.createElement);
|
|
20
|
+
if (!docCreateElementFnBeforeOverwrite) {
|
|
21
|
+
var rawDocumentCreateElement = document.createElement;
|
|
22
|
+
Document.prototype.createElement = function createElement(tagName, options) {
|
|
23
|
+
var element = rawDocumentCreateElement.call(this, tagName, options);
|
|
24
|
+
if (isHijackingTag(tagName)) {
|
|
25
|
+
var _ref = getCurrentRunningApp() || {},
|
|
26
|
+
currentRunningSandboxProxy = _ref.window;
|
|
27
|
+
if (currentRunningSandboxProxy) {
|
|
28
|
+
var proxyContainerConfig = proxyAttachContainerConfigMap.get(currentRunningSandboxProxy);
|
|
29
|
+
if (proxyContainerConfig) {
|
|
30
|
+
elementAttachContainerConfigMap.set(element, proxyContainerConfig);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return element;
|
|
35
|
+
};
|
|
36
|
+
// It means it have been overwritten while createElement is an own property of document
|
|
37
|
+
if (document.hasOwnProperty('createElement')) {
|
|
38
|
+
document.createElement = Document.prototype.createElement;
|
|
39
|
+
}
|
|
40
|
+
docCreatePatchedMap.set(Document.prototype.createElement, rawDocumentCreateElement);
|
|
41
|
+
}
|
|
42
|
+
return function unpatch() {
|
|
43
|
+
if (docCreateElementFnBeforeOverwrite) {
|
|
44
|
+
Document.prototype.createElement = docCreateElementFnBeforeOverwrite;
|
|
45
|
+
document.createElement = docCreateElementFnBeforeOverwrite;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
var bootstrappingPatchCount = 0;
|
|
50
|
+
var mountingPatchCount = 0;
|
|
51
|
+
export function patchStrictSandbox(appName, appWrapperGetter, proxy) {
|
|
52
|
+
var mounting = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
|
|
53
|
+
var scopedCSS = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
|
|
54
|
+
var excludeAssetFilter = arguments.length > 5 ? arguments[5] : undefined;
|
|
55
|
+
var containerConfig = proxyAttachContainerConfigMap.get(proxy);
|
|
56
|
+
if (!containerConfig) {
|
|
57
|
+
containerConfig = {
|
|
58
|
+
appName: appName,
|
|
59
|
+
proxy: proxy,
|
|
60
|
+
appWrapperGetter: appWrapperGetter,
|
|
61
|
+
dynamicStyleSheetElements: [],
|
|
62
|
+
strictGlobal: true,
|
|
63
|
+
excludeAssetFilter: excludeAssetFilter,
|
|
64
|
+
scopedCSS: scopedCSS
|
|
65
|
+
};
|
|
66
|
+
proxyAttachContainerConfigMap.set(proxy, containerConfig);
|
|
67
|
+
}
|
|
68
|
+
// all dynamic style sheets are stored in proxy container
|
|
69
|
+
var _containerConfig = containerConfig,
|
|
70
|
+
dynamicStyleSheetElements = _containerConfig.dynamicStyleSheetElements;
|
|
71
|
+
var unpatchDocumentCreate = patchDocumentCreateElement();
|
|
72
|
+
var unpatchDynamicAppendPrototypeFunctions = patchHTMLDynamicAppendPrototypeFunctions(function (element) {
|
|
73
|
+
return elementAttachContainerConfigMap.has(element);
|
|
74
|
+
}, function (element) {
|
|
75
|
+
return elementAttachContainerConfigMap.get(element);
|
|
76
|
+
});
|
|
77
|
+
if (!mounting) bootstrappingPatchCount++;
|
|
78
|
+
if (mounting) mountingPatchCount++;
|
|
79
|
+
return function free() {
|
|
80
|
+
// bootstrap patch just called once but its freer will be called multiple times
|
|
81
|
+
if (!mounting && bootstrappingPatchCount !== 0) bootstrappingPatchCount--;
|
|
82
|
+
if (mounting) mountingPatchCount--;
|
|
83
|
+
var allMicroAppUnmounted = mountingPatchCount === 0 && bootstrappingPatchCount === 0;
|
|
84
|
+
// release the overwrite prototype after all the micro apps unmounted
|
|
85
|
+
if (allMicroAppUnmounted) {
|
|
86
|
+
unpatchDynamicAppendPrototypeFunctions();
|
|
87
|
+
unpatchDocumentCreate();
|
|
88
|
+
}
|
|
89
|
+
recordStyledComponentsCSSRules(dynamicStyleSheetElements);
|
|
90
|
+
// As now the sub app content all wrapped with a special id container,
|
|
91
|
+
// the dynamic style sheet would be removed automatically while unmoutting
|
|
92
|
+
return function rebuild() {
|
|
93
|
+
rebuildCSSRules(dynamicStyleSheetElements, function (stylesheetElement) {
|
|
94
|
+
var appWrapper = appWrapperGetter();
|
|
95
|
+
if (!appWrapper.contains(stylesheetElement)) {
|
|
96
|
+
rawHeadAppendChild.call(appWrapper, stylesheetElement);
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
return false;
|
|
100
|
+
});
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import _isFunction from "lodash/isFunction";
|
|
2
|
+
import _noop from "lodash/noop";
|
|
3
|
+
/**
|
|
4
|
+
* @author Kuitos
|
|
5
|
+
* @since 2019-04-11
|
|
6
|
+
*/
|
|
7
|
+
export default function patch() {
|
|
8
|
+
// FIXME umi unmount feature request
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
10
|
+
var rawHistoryListen = function rawHistoryListen(_) {
|
|
11
|
+
return _noop;
|
|
12
|
+
};
|
|
13
|
+
var historyListeners = [];
|
|
14
|
+
var historyUnListens = [];
|
|
15
|
+
if (window.g_history && _isFunction(window.g_history.listen)) {
|
|
16
|
+
rawHistoryListen = window.g_history.listen.bind(window.g_history);
|
|
17
|
+
window.g_history.listen = function (listener) {
|
|
18
|
+
historyListeners.push(listener);
|
|
19
|
+
var unListen = rawHistoryListen(listener);
|
|
20
|
+
historyUnListens.push(unListen);
|
|
21
|
+
return function () {
|
|
22
|
+
unListen();
|
|
23
|
+
historyUnListens.splice(historyUnListens.indexOf(unListen), 1);
|
|
24
|
+
historyListeners.splice(historyListeners.indexOf(listener), 1);
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
return function free() {
|
|
29
|
+
var rebuild = _noop;
|
|
30
|
+
/*
|
|
31
|
+
还存在余量 listener 表明未被卸载,存在两种情况
|
|
32
|
+
1. 应用在 unmout 时未正确卸载 listener
|
|
33
|
+
2. listener 是应用 mount 之前绑定的,
|
|
34
|
+
第二种情况下应用在下次 mount 之前需重新绑定该 listener
|
|
35
|
+
*/
|
|
36
|
+
if (historyListeners.length) {
|
|
37
|
+
rebuild = function rebuild() {
|
|
38
|
+
// 必须使用 window.g_history.listen 的方式重新绑定 listener,从而能保证 rebuild 这部分也能被捕获到,否则在应用卸载后无法正确的移除这部分副作用
|
|
39
|
+
historyListeners.forEach(function (listener) {
|
|
40
|
+
return window.g_history.listen(listener);
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
// 卸载余下的 listener
|
|
45
|
+
historyUnListens.forEach(function (unListen) {
|
|
46
|
+
return unListen();
|
|
47
|
+
});
|
|
48
|
+
// restore
|
|
49
|
+
if (window.g_history && _isFunction(window.g_history.listen)) {
|
|
50
|
+
window.g_history.listen = rawHistoryListen;
|
|
51
|
+
}
|
|
52
|
+
return rebuild;
|
|
53
|
+
};
|
|
54
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author Kuitos
|
|
3
|
+
* @since 2019-04-11
|
|
4
|
+
*/
|
|
5
|
+
import type { Freer, SandBox } from '../../interfaces';
|
|
6
|
+
import * as css from './css';
|
|
7
|
+
export declare function patchAtMounting(appName: string, elementGetter: () => HTMLElement | ShadowRoot, sandbox: SandBox, scopedCSS: boolean, excludeAssetFilter?: CallableFunction): Freer[];
|
|
8
|
+
export declare function patchAtBootstrapping(appName: string, elementGetter: () => HTMLElement | ShadowRoot, sandbox: SandBox, scopedCSS: boolean, excludeAssetFilter?: CallableFunction): Freer[];
|
|
9
|
+
export { css };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
|
|
2
|
+
/**
|
|
3
|
+
* @author Kuitos
|
|
4
|
+
* @since 2019-04-11
|
|
5
|
+
*/
|
|
6
|
+
import { SandBoxType } from '../../interfaces';
|
|
7
|
+
import * as css from './css';
|
|
8
|
+
import { patchLooseSandbox, patchStrictSandbox } from './dynamicAppend';
|
|
9
|
+
import patchHistoryListener from './historyListener';
|
|
10
|
+
import patchInterval from './interval';
|
|
11
|
+
import patchWindowListener from './windowListener';
|
|
12
|
+
export function patchAtMounting(appName, elementGetter, sandbox, scopedCSS, excludeAssetFilter) {
|
|
13
|
+
var _a;
|
|
14
|
+
var basePatchers = [function () {
|
|
15
|
+
return patchInterval(sandbox.proxy);
|
|
16
|
+
}, function () {
|
|
17
|
+
return patchWindowListener(sandbox.proxy);
|
|
18
|
+
}, function () {
|
|
19
|
+
return patchHistoryListener();
|
|
20
|
+
}];
|
|
21
|
+
var patchersInSandbox = _defineProperty(_defineProperty(_defineProperty({}, SandBoxType.LegacyProxy, [].concat(basePatchers, [function () {
|
|
22
|
+
return patchLooseSandbox(appName, elementGetter, sandbox.proxy, true, scopedCSS, excludeAssetFilter);
|
|
23
|
+
}])), SandBoxType.Proxy, [].concat(basePatchers, [function () {
|
|
24
|
+
return patchStrictSandbox(appName, elementGetter, sandbox.proxy, true, scopedCSS, excludeAssetFilter);
|
|
25
|
+
}])), SandBoxType.Snapshot, [].concat(basePatchers, [function () {
|
|
26
|
+
return patchLooseSandbox(appName, elementGetter, sandbox.proxy, true, scopedCSS, excludeAssetFilter);
|
|
27
|
+
}]));
|
|
28
|
+
return (_a = patchersInSandbox[sandbox.type]) === null || _a === void 0 ? void 0 : _a.map(function (patch) {
|
|
29
|
+
return patch();
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
export function patchAtBootstrapping(appName, elementGetter, sandbox, scopedCSS, excludeAssetFilter) {
|
|
33
|
+
var _a;
|
|
34
|
+
var patchersInSandbox = _defineProperty(_defineProperty(_defineProperty({}, SandBoxType.LegacyProxy, [function () {
|
|
35
|
+
return patchLooseSandbox(appName, elementGetter, sandbox.proxy, false, scopedCSS, excludeAssetFilter);
|
|
36
|
+
}]), SandBoxType.Proxy, [function () {
|
|
37
|
+
return patchStrictSandbox(appName, elementGetter, sandbox.proxy, false, scopedCSS, excludeAssetFilter);
|
|
38
|
+
}]), SandBoxType.Snapshot, [function () {
|
|
39
|
+
return patchLooseSandbox(appName, elementGetter, sandbox.proxy, false, scopedCSS, excludeAssetFilter);
|
|
40
|
+
}]);
|
|
41
|
+
return (_a = patchersInSandbox[sandbox.type]) === null || _a === void 0 ? void 0 : _a.map(function (patch) {
|
|
42
|
+
return patch();
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
export { css };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import _noop from "lodash/noop";
|
|
2
|
+
import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
|
|
3
|
+
/* eslint-disable no-param-reassign */
|
|
4
|
+
/**
|
|
5
|
+
* @author Kuitos
|
|
6
|
+
* @since 2019-04-11
|
|
7
|
+
*/
|
|
8
|
+
var rawWindowInterval = window.setInterval;
|
|
9
|
+
var rawWindowClearInterval = window.clearInterval;
|
|
10
|
+
export default function patch(global) {
|
|
11
|
+
var intervals = [];
|
|
12
|
+
global.clearInterval = function (intervalId) {
|
|
13
|
+
intervals = intervals.filter(function (id) {
|
|
14
|
+
return id !== intervalId;
|
|
15
|
+
});
|
|
16
|
+
return rawWindowClearInterval.call(window, intervalId);
|
|
17
|
+
};
|
|
18
|
+
global.setInterval = function (handler, timeout) {
|
|
19
|
+
for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
|
|
20
|
+
args[_key - 2] = arguments[_key];
|
|
21
|
+
}
|
|
22
|
+
var intervalId = rawWindowInterval.apply(void 0, [handler, timeout].concat(args));
|
|
23
|
+
intervals = [].concat(_toConsumableArray(intervals), [intervalId]);
|
|
24
|
+
return intervalId;
|
|
25
|
+
};
|
|
26
|
+
return function free() {
|
|
27
|
+
intervals.forEach(function (id) {
|
|
28
|
+
return global.clearInterval(id);
|
|
29
|
+
});
|
|
30
|
+
global.setInterval = rawWindowInterval;
|
|
31
|
+
global.clearInterval = rawWindowClearInterval;
|
|
32
|
+
return _noop;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import _noop from "lodash/noop";
|
|
2
|
+
import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
|
|
3
|
+
/* eslint-disable no-param-reassign */
|
|
4
|
+
/**
|
|
5
|
+
* @author Kuitos
|
|
6
|
+
* @since 2019-04-11
|
|
7
|
+
*/
|
|
8
|
+
var rawAddEventListener = window.addEventListener;
|
|
9
|
+
var rawRemoveEventListener = window.removeEventListener;
|
|
10
|
+
export default function patch(global) {
|
|
11
|
+
var listenerMap = new Map();
|
|
12
|
+
global.addEventListener = function (type, listener, options) {
|
|
13
|
+
var listeners = listenerMap.get(type) || [];
|
|
14
|
+
listenerMap.set(type, [].concat(_toConsumableArray(listeners), [listener]));
|
|
15
|
+
return rawAddEventListener.call(window, type, listener, options);
|
|
16
|
+
};
|
|
17
|
+
global.removeEventListener = function (type, listener, options) {
|
|
18
|
+
var storedTypeListeners = listenerMap.get(type);
|
|
19
|
+
if (storedTypeListeners && storedTypeListeners.length && storedTypeListeners.indexOf(listener) !== -1) {
|
|
20
|
+
storedTypeListeners.splice(storedTypeListeners.indexOf(listener), 1);
|
|
21
|
+
}
|
|
22
|
+
return rawRemoveEventListener.call(window, type, listener, options);
|
|
23
|
+
};
|
|
24
|
+
return function free() {
|
|
25
|
+
listenerMap.forEach(function (listeners, type) {
|
|
26
|
+
return _toConsumableArray(listeners).forEach(function (listener) {
|
|
27
|
+
return global.removeEventListener(type, listener);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
global.addEventListener = rawAddEventListener;
|
|
31
|
+
global.removeEventListener = rawRemoveEventListener;
|
|
32
|
+
return _noop;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author Kuitos
|
|
3
|
+
* @since 2020-3-31
|
|
4
|
+
*/
|
|
5
|
+
import type { SandBox } from '../interfaces';
|
|
6
|
+
import { SandBoxType } from '../interfaces';
|
|
7
|
+
/**
|
|
8
|
+
* 基于 Proxy 实现的沙箱
|
|
9
|
+
*/
|
|
10
|
+
export default class ProxySandbox implements SandBox {
|
|
11
|
+
/** window 值变更记录 */
|
|
12
|
+
private updatedValueSet;
|
|
13
|
+
name: string;
|
|
14
|
+
type: SandBoxType;
|
|
15
|
+
proxy: WindowProxy;
|
|
16
|
+
globalContext: typeof window;
|
|
17
|
+
sandboxRunning: boolean;
|
|
18
|
+
latestSetProp: PropertyKey | null;
|
|
19
|
+
private registerRunningApp;
|
|
20
|
+
active(): void;
|
|
21
|
+
inactive(): void;
|
|
22
|
+
constructor(name: string, globalContext?: Window & typeof globalThis, transformStorage?: boolean);
|
|
23
|
+
}
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
|
|
2
|
+
import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
|
|
3
|
+
import _createClass from "@babel/runtime/helpers/esm/createClass";
|
|
4
|
+
import { SandBoxType } from '../interfaces';
|
|
5
|
+
import { nativeGlobal, nextTask } from '../utils';
|
|
6
|
+
import { getTargetValue, setCurrentRunningApp, getCurrentRunningApp, getZsLocalStorage, getZsSessionStorage } from './common';
|
|
7
|
+
/**
|
|
8
|
+
* fastest(at most time) unique array method
|
|
9
|
+
* @see https://jsperf.com/array-filter-unique/30
|
|
10
|
+
*/
|
|
11
|
+
function uniq(array) {
|
|
12
|
+
return array.filter(function filter(element) {
|
|
13
|
+
return element in this ? false : this[element] = true;
|
|
14
|
+
}, Object.create(null));
|
|
15
|
+
}
|
|
16
|
+
// zone.js will overwrite Object.defineProperty
|
|
17
|
+
var rawObjectDefineProperty = Object.defineProperty;
|
|
18
|
+
var variableWhiteListInDev = process.env.NODE_ENV === 'development' || window.__QIANKUN_DEVELOPMENT__ ? [
|
|
19
|
+
// for react hot reload
|
|
20
|
+
// see https://github.com/facebook/create-react-app/blob/66bf7dfc43350249e2f09d138a20840dae8a0a4a/packages/react-error-overlay/src/index.js#L180
|
|
21
|
+
'__REACT_ERROR_OVERLAY_GLOBAL_HOOK__'] : [];
|
|
22
|
+
// who could escape the sandbox
|
|
23
|
+
var variableWhiteList = [
|
|
24
|
+
// FIXME System.js used a indirect call with eval, which would make it scope escape to global
|
|
25
|
+
// To make System.js works well, we write it back to global window temporary
|
|
26
|
+
// see https://github.com/systemjs/systemjs/blob/457f5b7e8af6bd120a279540477552a07d5de086/src/evaluate.js#L106
|
|
27
|
+
'System',
|
|
28
|
+
// see https://github.com/systemjs/systemjs/blob/457f5b7e8af6bd120a279540477552a07d5de086/src/instantiate.js#L357
|
|
29
|
+
'__cjsWrapper'].concat(variableWhiteListInDev);
|
|
30
|
+
/*
|
|
31
|
+
variables who are impossible to be overwrite need to be escaped from proxy sandbox for performance reasons
|
|
32
|
+
*/
|
|
33
|
+
var unscopables = {
|
|
34
|
+
undefined: true,
|
|
35
|
+
Array: true,
|
|
36
|
+
Object: true,
|
|
37
|
+
String: true,
|
|
38
|
+
Boolean: true,
|
|
39
|
+
Math: true,
|
|
40
|
+
Number: true,
|
|
41
|
+
Symbol: true,
|
|
42
|
+
parseFloat: true,
|
|
43
|
+
Float32Array: true,
|
|
44
|
+
isNaN: true,
|
|
45
|
+
Infinity: true,
|
|
46
|
+
Reflect: true,
|
|
47
|
+
Float64Array: true,
|
|
48
|
+
Function: true,
|
|
49
|
+
Map: true,
|
|
50
|
+
NaN: true,
|
|
51
|
+
Promise: true,
|
|
52
|
+
Proxy: true,
|
|
53
|
+
Set: true,
|
|
54
|
+
parseInt: true,
|
|
55
|
+
requestAnimationFrame: true
|
|
56
|
+
};
|
|
57
|
+
var useNativeWindowForBindingsProps = new Map([['fetch', true], ['mockDomAPIInBlackList', process.env.NODE_ENV === 'test']]);
|
|
58
|
+
function createFakeWindow(globalContext) {
|
|
59
|
+
// map always has the fastest performance in has check scenario
|
|
60
|
+
// see https://jsperf.com/array-indexof-vs-set-has/23
|
|
61
|
+
var propertiesWithGetter = new Map();
|
|
62
|
+
var fakeWindow = {};
|
|
63
|
+
/*
|
|
64
|
+
copy the non-configurable property of global to fakeWindow
|
|
65
|
+
see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/getOwnPropertyDescriptor
|
|
66
|
+
> A property cannot be reported as non-configurable, if it does not exists as an own property of the target object or if it exists as a configurable own property of the target object.
|
|
67
|
+
*/
|
|
68
|
+
Object.getOwnPropertyNames(globalContext).filter(function (p) {
|
|
69
|
+
var descriptor = Object.getOwnPropertyDescriptor(globalContext, p);
|
|
70
|
+
return !(descriptor === null || descriptor === void 0 ? void 0 : descriptor.configurable);
|
|
71
|
+
}).forEach(function (p) {
|
|
72
|
+
var descriptor = Object.getOwnPropertyDescriptor(globalContext, p);
|
|
73
|
+
if (descriptor) {
|
|
74
|
+
var hasGetter = Object.prototype.hasOwnProperty.call(descriptor, 'get');
|
|
75
|
+
/*
|
|
76
|
+
make top/self/window property configurable and writable, otherwise it will cause TypeError while get trap return.
|
|
77
|
+
see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/get
|
|
78
|
+
> The value reported for a property must be the same as the value of the corresponding target object property if the target object property is a non-writable, non-configurable data property.
|
|
79
|
+
*/
|
|
80
|
+
if (p === 'top' || p === 'parent' || p === 'self' || p === 'window' || process.env.NODE_ENV === 'test' && (p === 'mockTop' || p === 'mockSafariTop')) {
|
|
81
|
+
descriptor.configurable = true;
|
|
82
|
+
/*
|
|
83
|
+
The descriptor of window.window/window.top/window.self in Safari/FF are accessor descriptors, we need to avoid adding a data descriptor while it was
|
|
84
|
+
Example:
|
|
85
|
+
Safari/FF: Object.getOwnPropertyDescriptor(window, 'top') -> {get: function, set: undefined, enumerable: true, configurable: false}
|
|
86
|
+
Chrome: Object.getOwnPropertyDescriptor(window, 'top') -> {value: Window, writable: false, enumerable: true, configurable: false}
|
|
87
|
+
*/
|
|
88
|
+
if (!hasGetter) {
|
|
89
|
+
descriptor.writable = true;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (hasGetter) propertiesWithGetter.set(p, true);
|
|
93
|
+
// freeze the descriptor to avoid being modified by zone.js
|
|
94
|
+
// see https://github.com/angular/zone.js/blob/a5fe09b0fac27ac5df1fa746042f96f05ccb6a00/lib/browser/define-property.ts#L71
|
|
95
|
+
rawObjectDefineProperty(fakeWindow, p, Object.freeze(descriptor));
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
return {
|
|
99
|
+
fakeWindow: fakeWindow,
|
|
100
|
+
propertiesWithGetter: propertiesWithGetter
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
var activeSandboxCount = 0;
|
|
104
|
+
/**
|
|
105
|
+
* 基于 Proxy 实现的沙箱
|
|
106
|
+
*/
|
|
107
|
+
var ProxySandbox = /*#__PURE__*/function () {
|
|
108
|
+
function ProxySandbox(name) {
|
|
109
|
+
var _this = this;
|
|
110
|
+
var globalContext = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : window;
|
|
111
|
+
var transformStorage = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
112
|
+
_classCallCheck(this, ProxySandbox);
|
|
113
|
+
/** window 值变更记录 */
|
|
114
|
+
this.updatedValueSet = new Set();
|
|
115
|
+
this.sandboxRunning = true;
|
|
116
|
+
this.latestSetProp = null;
|
|
117
|
+
this.name = name;
|
|
118
|
+
this.globalContext = globalContext;
|
|
119
|
+
this.type = SandBoxType.Proxy;
|
|
120
|
+
var updatedValueSet = this.updatedValueSet;
|
|
121
|
+
var _createFakeWindow = createFakeWindow(globalContext),
|
|
122
|
+
fakeWindow = _createFakeWindow.fakeWindow,
|
|
123
|
+
propertiesWithGetter = _createFakeWindow.propertiesWithGetter;
|
|
124
|
+
var descriptorTargetMap = new Map();
|
|
125
|
+
var hasOwnProperty = function hasOwnProperty(key) {
|
|
126
|
+
return fakeWindow.hasOwnProperty(key) || globalContext.hasOwnProperty(key);
|
|
127
|
+
};
|
|
128
|
+
var proxy = new Proxy(fakeWindow, {
|
|
129
|
+
set: function set(target, p, value) {
|
|
130
|
+
if (_this.sandboxRunning) {
|
|
131
|
+
_this.registerRunningApp(name, proxy);
|
|
132
|
+
// We must kept its description while the property existed in globalContext before
|
|
133
|
+
if (!target.hasOwnProperty(p) && globalContext.hasOwnProperty(p)) {
|
|
134
|
+
var descriptor = Object.getOwnPropertyDescriptor(globalContext, p);
|
|
135
|
+
var writable = descriptor.writable,
|
|
136
|
+
configurable = descriptor.configurable,
|
|
137
|
+
enumerable = descriptor.enumerable;
|
|
138
|
+
if (writable) {
|
|
139
|
+
Object.defineProperty(target, p, {
|
|
140
|
+
configurable: configurable,
|
|
141
|
+
enumerable: enumerable,
|
|
142
|
+
writable: writable,
|
|
143
|
+
value: value
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
} else {
|
|
147
|
+
// @ts-ignore
|
|
148
|
+
target[p] = value;
|
|
149
|
+
}
|
|
150
|
+
if (variableWhiteList.indexOf(p) !== -1) {
|
|
151
|
+
// @ts-ignore
|
|
152
|
+
globalContext[p] = value;
|
|
153
|
+
}
|
|
154
|
+
updatedValueSet.add(p);
|
|
155
|
+
_this.latestSetProp = p;
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
if (process.env.NODE_ENV === 'development') {
|
|
159
|
+
console.warn("[qiankun] Set window.".concat(p.toString(), " while sandbox destroyed or inactive in ").concat(name, "!"));
|
|
160
|
+
}
|
|
161
|
+
// 在 strict-mode 下,Proxy 的 handler.set 返回 false 会抛出 TypeError,在沙箱卸载的情况下应该忽略错误
|
|
162
|
+
return true;
|
|
163
|
+
},
|
|
164
|
+
get: function get(target, p) {
|
|
165
|
+
_this.registerRunningApp(name, proxy);
|
|
166
|
+
if (p === Symbol.unscopables) return unscopables;
|
|
167
|
+
// avoid who using window.window or window.self to escape the sandbox environment to touch the really window
|
|
168
|
+
// see https://github.com/eligrey/FileSaver.js/blob/master/src/FileSaver.js#L13
|
|
169
|
+
if (p === 'window' || p === 'self') {
|
|
170
|
+
return proxy;
|
|
171
|
+
}
|
|
172
|
+
// hijack globalWindow accessing with globalThis keyword
|
|
173
|
+
if (p === 'globalThis') {
|
|
174
|
+
return proxy;
|
|
175
|
+
}
|
|
176
|
+
if (p === 'top' || p === 'parent' || process.env.NODE_ENV === 'test' && (p === 'mockTop' || p === 'mockSafariTop')) {
|
|
177
|
+
// if your master app in an iframe context, allow these props escape the sandbox
|
|
178
|
+
if (globalContext === globalContext.parent) {
|
|
179
|
+
return proxy;
|
|
180
|
+
}
|
|
181
|
+
return globalContext[p];
|
|
182
|
+
}
|
|
183
|
+
// proxy.hasOwnProperty would invoke getter firstly, then its value represented as globalContext.hasOwnProperty
|
|
184
|
+
if (p === 'hasOwnProperty') {
|
|
185
|
+
return hasOwnProperty;
|
|
186
|
+
}
|
|
187
|
+
if (p === 'document') {
|
|
188
|
+
return document;
|
|
189
|
+
}
|
|
190
|
+
if (p === 'eval') {
|
|
191
|
+
return eval;
|
|
192
|
+
}
|
|
193
|
+
if (transformStorage && p === 'localStorage') {
|
|
194
|
+
return getZsLocalStorage(name);
|
|
195
|
+
}
|
|
196
|
+
if (transformStorage && p === 'sessionStorage') {
|
|
197
|
+
return getZsSessionStorage(name);
|
|
198
|
+
}
|
|
199
|
+
var value = propertiesWithGetter.has(p) ? globalContext[p] : p in target ? target[p] : globalContext[p];
|
|
200
|
+
/* Some dom api must be bound to native window, otherwise it would cause exception like 'TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation'
|
|
201
|
+
See this code:
|
|
202
|
+
const proxy = new Proxy(window, {});
|
|
203
|
+
const proxyFetch = fetch.bind(proxy);
|
|
204
|
+
proxyFetch('https://qiankun.com');
|
|
205
|
+
*/
|
|
206
|
+
var boundTarget = useNativeWindowForBindingsProps.get(p) ? nativeGlobal : globalContext;
|
|
207
|
+
return getTargetValue(boundTarget, value);
|
|
208
|
+
},
|
|
209
|
+
// trap in operator
|
|
210
|
+
// see https://github.com/styled-components/styled-components/blob/master/packages/styled-components/src/constants.js#L12
|
|
211
|
+
has: function has(target, p) {
|
|
212
|
+
return p in unscopables || p in target || p in globalContext;
|
|
213
|
+
},
|
|
214
|
+
getOwnPropertyDescriptor: function getOwnPropertyDescriptor(target, p) {
|
|
215
|
+
/*
|
|
216
|
+
as the descriptor of top/self/window/mockTop in raw window are configurable but not in proxy target, we need to get it from target to avoid TypeError
|
|
217
|
+
see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/getOwnPropertyDescriptor
|
|
218
|
+
> A property cannot be reported as non-configurable, if it does not exists as an own property of the target object or if it exists as a configurable own property of the target object.
|
|
219
|
+
*/
|
|
220
|
+
if (target.hasOwnProperty(p)) {
|
|
221
|
+
var descriptor = Object.getOwnPropertyDescriptor(target, p);
|
|
222
|
+
descriptorTargetMap.set(p, 'target');
|
|
223
|
+
return descriptor;
|
|
224
|
+
}
|
|
225
|
+
if (globalContext.hasOwnProperty(p)) {
|
|
226
|
+
var _descriptor = Object.getOwnPropertyDescriptor(globalContext, p);
|
|
227
|
+
descriptorTargetMap.set(p, 'globalContext');
|
|
228
|
+
// A property cannot be reported as non-configurable, if it does not exists as an own property of the target object
|
|
229
|
+
if (_descriptor && !_descriptor.configurable) {
|
|
230
|
+
_descriptor.configurable = true;
|
|
231
|
+
}
|
|
232
|
+
return _descriptor;
|
|
233
|
+
}
|
|
234
|
+
return undefined;
|
|
235
|
+
},
|
|
236
|
+
// trap to support iterator with sandbox
|
|
237
|
+
ownKeys: function ownKeys(target) {
|
|
238
|
+
return uniq(Reflect.ownKeys(globalContext).concat(Reflect.ownKeys(target)));
|
|
239
|
+
},
|
|
240
|
+
defineProperty: function defineProperty(target, p, attributes) {
|
|
241
|
+
var from = descriptorTargetMap.get(p);
|
|
242
|
+
/*
|
|
243
|
+
Descriptor must be defined to native window while it comes from native window via Object.getOwnPropertyDescriptor(window, p),
|
|
244
|
+
otherwise it would cause a TypeError with illegal invocation.
|
|
245
|
+
*/
|
|
246
|
+
switch (from) {
|
|
247
|
+
case 'globalContext':
|
|
248
|
+
return Reflect.defineProperty(globalContext, p, attributes);
|
|
249
|
+
default:
|
|
250
|
+
return Reflect.defineProperty(target, p, attributes);
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
|
+
deleteProperty: function deleteProperty(target, p) {
|
|
254
|
+
_this.registerRunningApp(name, proxy);
|
|
255
|
+
if (target.hasOwnProperty(p)) {
|
|
256
|
+
// @ts-ignore
|
|
257
|
+
delete target[p];
|
|
258
|
+
updatedValueSet.delete(p);
|
|
259
|
+
return true;
|
|
260
|
+
}
|
|
261
|
+
return true;
|
|
262
|
+
},
|
|
263
|
+
// makes sure `window instanceof Window` returns truthy in micro app
|
|
264
|
+
getPrototypeOf: function getPrototypeOf() {
|
|
265
|
+
return Reflect.getPrototypeOf(globalContext);
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
this.proxy = proxy;
|
|
269
|
+
activeSandboxCount++;
|
|
270
|
+
}
|
|
271
|
+
return _createClass(ProxySandbox, [{
|
|
272
|
+
key: "registerRunningApp",
|
|
273
|
+
value: function registerRunningApp(name, proxy) {
|
|
274
|
+
if (this.sandboxRunning) {
|
|
275
|
+
var currentRunningApp = getCurrentRunningApp();
|
|
276
|
+
if (!currentRunningApp || currentRunningApp.name !== name) {
|
|
277
|
+
setCurrentRunningApp({
|
|
278
|
+
name: name,
|
|
279
|
+
window: proxy
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
// FIXME if you have any other good ideas
|
|
283
|
+
// remove the mark in next tick, thus we can identify whether it in micro app or not
|
|
284
|
+
// this approach is just a workaround, it could not cover all complex cases, such as the micro app runs in the same task context with master in some case
|
|
285
|
+
nextTask(function () {
|
|
286
|
+
setCurrentRunningApp(null);
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}, {
|
|
291
|
+
key: "active",
|
|
292
|
+
value: function active() {
|
|
293
|
+
if (!this.sandboxRunning) activeSandboxCount++;
|
|
294
|
+
this.sandboxRunning = true;
|
|
295
|
+
}
|
|
296
|
+
}, {
|
|
297
|
+
key: "inactive",
|
|
298
|
+
value: function inactive() {
|
|
299
|
+
var _this2 = this;
|
|
300
|
+
if (process.env.NODE_ENV === 'development') {
|
|
301
|
+
console.info("[qiankun:sandbox] ".concat(this.name, " modified global properties restore..."), _toConsumableArray(this.updatedValueSet.keys()));
|
|
302
|
+
}
|
|
303
|
+
if (--activeSandboxCount === 0) {
|
|
304
|
+
variableWhiteList.forEach(function (p) {
|
|
305
|
+
if (_this2.proxy.hasOwnProperty(p)) {
|
|
306
|
+
// @ts-ignore
|
|
307
|
+
delete _this2.globalContext[p];
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
this.sandboxRunning = false;
|
|
312
|
+
}
|
|
313
|
+
}]);
|
|
314
|
+
}();
|
|
315
|
+
export { ProxySandbox as default };
|