@micro-zoe/micro-app 1.0.0-rc.3 → 1.0.0-rc.4
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/lib/index.d.ts +3 -9
- package/lib/index.esm.js +417 -267
- package/lib/index.esm.js.map +1 -1
- package/lib/index.min.js +1 -1
- package/lib/index.min.js.map +1 -1
- package/lib/index.umd.js +1 -1
- package/lib/index.umd.js.map +1 -1
- package/package.json +1 -1
- package/typings/global.d.ts +28 -26
package/lib/index.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const version = '1.0.0-rc.
|
|
1
|
+
const version = '1.0.0-rc.4';
|
|
2
2
|
// do not use isUndefined
|
|
3
3
|
const isBrowser = typeof window !== 'undefined';
|
|
4
4
|
// do not use isUndefined
|
|
@@ -116,6 +116,26 @@ function isMicroAppBody(target) {
|
|
|
116
116
|
function isProxyDocument(target) {
|
|
117
117
|
return toTypeString(target) === '[object ProxyDocument]';
|
|
118
118
|
}
|
|
119
|
+
function includes(target, searchElement, fromIndex) {
|
|
120
|
+
if (target == null) {
|
|
121
|
+
throw new TypeError('includes target is null or undefined');
|
|
122
|
+
}
|
|
123
|
+
const O = Object(target);
|
|
124
|
+
const len = parseInt(O.length, 10) || 0;
|
|
125
|
+
if (len === 0)
|
|
126
|
+
return false;
|
|
127
|
+
// @ts-ignore
|
|
128
|
+
fromIndex = parseInt(fromIndex, 10) || 0;
|
|
129
|
+
let i = Math.max(fromIndex >= 0 ? fromIndex : len + fromIndex, 0);
|
|
130
|
+
while (i < len) {
|
|
131
|
+
// NaN !== NaN
|
|
132
|
+
if (searchElement === O[i] || (searchElement !== searchElement && O[i] !== O[i])) {
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
i++;
|
|
136
|
+
}
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
119
139
|
/**
|
|
120
140
|
* format error log
|
|
121
141
|
* @param msg message
|
|
@@ -179,7 +199,7 @@ function formatAppURL(url, appName = null) {
|
|
|
179
199
|
if (!isString(url) || !url)
|
|
180
200
|
return '';
|
|
181
201
|
try {
|
|
182
|
-
const { origin, pathname, search } = createURL(addProtocol(url));
|
|
202
|
+
const { origin, pathname, search } = createURL(addProtocol(url), (window.rawWindow || window).location.href);
|
|
183
203
|
// If it ends with .html/.node/.php/.net/.etc, don’t need to add /
|
|
184
204
|
if (/\.(\w+)$/.test(pathname)) {
|
|
185
205
|
return `${origin}${pathname}${search}`;
|
|
@@ -318,21 +338,28 @@ let currentMicroAppName = null;
|
|
|
318
338
|
function setCurrentAppName(appName) {
|
|
319
339
|
currentMicroAppName = appName;
|
|
320
340
|
}
|
|
321
|
-
function throttleDeferForSetAppName(appName) {
|
|
322
|
-
if (currentMicroAppName !== appName) {
|
|
323
|
-
setCurrentAppName(appName);
|
|
324
|
-
defer(() => {
|
|
325
|
-
setCurrentAppName(null);
|
|
326
|
-
});
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
341
|
// get the currently running app.name
|
|
330
342
|
function getCurrentAppName() {
|
|
331
343
|
return currentMicroAppName;
|
|
332
344
|
}
|
|
333
345
|
// Clear appName
|
|
334
|
-
|
|
346
|
+
let preventSetAppName = false;
|
|
347
|
+
function removeDomScope(force) {
|
|
335
348
|
setCurrentAppName(null);
|
|
349
|
+
if (force && !preventSetAppName) {
|
|
350
|
+
preventSetAppName = true;
|
|
351
|
+
defer(() => {
|
|
352
|
+
preventSetAppName = false;
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
function throttleDeferForSetAppName(appName) {
|
|
357
|
+
if (currentMicroAppName !== appName && !preventSetAppName) {
|
|
358
|
+
setCurrentAppName(appName);
|
|
359
|
+
defer(() => {
|
|
360
|
+
setCurrentAppName(null);
|
|
361
|
+
});
|
|
362
|
+
}
|
|
336
363
|
}
|
|
337
364
|
/**
|
|
338
365
|
* Create pure elements
|
|
@@ -344,33 +371,6 @@ function pureCreateElement(tagName, options) {
|
|
|
344
371
|
element.__PURE_ELEMENT__ = true;
|
|
345
372
|
return element;
|
|
346
373
|
}
|
|
347
|
-
/**
|
|
348
|
-
* clone origin elements to target
|
|
349
|
-
* @param origin Cloned element
|
|
350
|
-
* @param target Accept cloned elements
|
|
351
|
-
* @param deep deep clone or transfer dom
|
|
352
|
-
*/
|
|
353
|
-
function cloneContainer(target, origin, deep) {
|
|
354
|
-
// 在基座接受到afterhidden方法后立即执行unmount,彻底destroy应用时,因为unmount时同步执行,所以this.container为null后才执行cloneContainer
|
|
355
|
-
if (origin) {
|
|
356
|
-
target.innerHTML = '';
|
|
357
|
-
if (deep) {
|
|
358
|
-
// TODO: ShadowRoot兼容,ShadowRoot不能直接使用cloneNode
|
|
359
|
-
const clonedNode = origin.cloneNode(true);
|
|
360
|
-
const fragment = document.createDocumentFragment();
|
|
361
|
-
Array.from(clonedNode.childNodes).forEach((node) => {
|
|
362
|
-
fragment.appendChild(node);
|
|
363
|
-
});
|
|
364
|
-
target.appendChild(fragment);
|
|
365
|
-
}
|
|
366
|
-
else {
|
|
367
|
-
Array.from(origin.childNodes).forEach((node) => {
|
|
368
|
-
target.appendChild(node);
|
|
369
|
-
});
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
return target;
|
|
373
|
-
}
|
|
374
374
|
// is invalid key of querySelector
|
|
375
375
|
function isInvalidQuerySelectorKey(key) {
|
|
376
376
|
return !key || /(^\d)|([^\w\d-_\u4e00-\u9fa5])/gi.test(key);
|
|
@@ -1295,12 +1295,12 @@ function fetchLinksFromHtml(wrapElement, app, microAppHead, fiberStyleResult) {
|
|
|
1295
1295
|
*/
|
|
1296
1296
|
if (fiberStyleResult) {
|
|
1297
1297
|
fiberStyleResult.then(() => {
|
|
1298
|
-
fiberLinkTasks.push(() => Promise.resolve(app.onLoad(wrapElement)));
|
|
1298
|
+
fiberLinkTasks.push(() => Promise.resolve(app.onLoad({ html: wrapElement })));
|
|
1299
1299
|
serialExecFiberTasks(fiberLinkTasks);
|
|
1300
1300
|
});
|
|
1301
1301
|
}
|
|
1302
1302
|
else {
|
|
1303
|
-
app.onLoad(wrapElement);
|
|
1303
|
+
app.onLoad({ html: wrapElement });
|
|
1304
1304
|
}
|
|
1305
1305
|
});
|
|
1306
1306
|
}
|
|
@@ -1473,13 +1473,24 @@ var MicroAppConfig;
|
|
|
1473
1473
|
// prefetch level
|
|
1474
1474
|
const PREFETCH_LEVEL = [1, 2, 3];
|
|
1475
1475
|
// memory router constants
|
|
1476
|
+
// default mode, child router info will sync to browser url
|
|
1476
1477
|
const DEFAULT_ROUTER_MODE = 'search';
|
|
1477
|
-
|
|
1478
|
-
|
|
1478
|
+
/**
|
|
1479
|
+
* render base on browser url, and location.origin location.href point to base app
|
|
1480
|
+
* equal to disable-memory-router
|
|
1481
|
+
* NOTE:
|
|
1482
|
+
* 1. The only difference between native and native-scope is location.origin, in native-scope mode location.origin point to child app
|
|
1483
|
+
*/
|
|
1484
|
+
const ROUTER_MODE_NATIVE = 'native';
|
|
1485
|
+
// render base on browser url, but location.origin location.href point to child app
|
|
1486
|
+
const ROUTER_MODE_NATIVE_SCOPE = 'native-scope';
|
|
1487
|
+
// search mode, but child router info will not sync to browser url
|
|
1488
|
+
const ROUTER_MODE_PURE = 'pure';
|
|
1479
1489
|
const ROUTER_MODE_LIST = [
|
|
1480
1490
|
DEFAULT_ROUTER_MODE,
|
|
1481
|
-
|
|
1482
|
-
|
|
1491
|
+
ROUTER_MODE_NATIVE,
|
|
1492
|
+
ROUTER_MODE_NATIVE_SCOPE,
|
|
1493
|
+
ROUTER_MODE_PURE,
|
|
1483
1494
|
];
|
|
1484
1495
|
// event bound to child app window
|
|
1485
1496
|
const SCOPE_WINDOW_EVENT = [
|
|
@@ -1494,6 +1505,7 @@ const SCOPE_WINDOW_EVENT = [
|
|
|
1494
1505
|
'mounted',
|
|
1495
1506
|
];
|
|
1496
1507
|
// on event bound to child app window
|
|
1508
|
+
// TODO: with和iframe处理方式不同,需修改
|
|
1497
1509
|
const SCOPE_WINDOW_ON_EVENT = [
|
|
1498
1510
|
'onpopstate',
|
|
1499
1511
|
'onhashchange',
|
|
@@ -1790,16 +1802,16 @@ function fetchScriptsFromHtml(wrapElement, app) {
|
|
|
1790
1802
|
logError(err, app.name);
|
|
1791
1803
|
}, () => {
|
|
1792
1804
|
if (fiberScriptTasks) {
|
|
1793
|
-
fiberScriptTasks.push(() => Promise.resolve(app.onLoad(wrapElement)));
|
|
1805
|
+
fiberScriptTasks.push(() => Promise.resolve(app.onLoad({ html: wrapElement })));
|
|
1794
1806
|
serialExecFiberTasks(fiberScriptTasks);
|
|
1795
1807
|
}
|
|
1796
1808
|
else {
|
|
1797
|
-
app.onLoad(wrapElement);
|
|
1809
|
+
app.onLoad({ html: wrapElement });
|
|
1798
1810
|
}
|
|
1799
1811
|
});
|
|
1800
1812
|
}
|
|
1801
1813
|
else {
|
|
1802
|
-
app.onLoad(wrapElement);
|
|
1814
|
+
app.onLoad({ html: wrapElement });
|
|
1803
1815
|
}
|
|
1804
1816
|
}
|
|
1805
1817
|
/**
|
|
@@ -2123,15 +2135,6 @@ function processCode(configs, code, address) {
|
|
|
2123
2135
|
}, code);
|
|
2124
2136
|
}
|
|
2125
2137
|
|
|
2126
|
-
/**
|
|
2127
|
-
* transform html string to dom
|
|
2128
|
-
* @param str string dom
|
|
2129
|
-
*/
|
|
2130
|
-
function getWrapElement(str) {
|
|
2131
|
-
const wrapDiv = pureCreateElement('div');
|
|
2132
|
-
wrapDiv.innerHTML = str;
|
|
2133
|
-
return wrapDiv;
|
|
2134
|
-
}
|
|
2135
2138
|
/**
|
|
2136
2139
|
* Recursively process each child element
|
|
2137
2140
|
* @param parent parent element
|
|
@@ -2188,7 +2191,7 @@ function flatChildren(parent, app, microAppHead, fiberStyleTasks) {
|
|
|
2188
2191
|
* @param app app
|
|
2189
2192
|
*/
|
|
2190
2193
|
function extractSourceDom(htmlStr, app) {
|
|
2191
|
-
const wrapElement =
|
|
2194
|
+
const wrapElement = app.parseHtmlString(htmlStr);
|
|
2192
2195
|
const microAppHead = globalEnv.rawElementQuerySelector.call(wrapElement, 'micro-app-head');
|
|
2193
2196
|
const microAppBody = globalEnv.rawElementQuerySelector.call(wrapElement, 'micro-app-body');
|
|
2194
2197
|
if (!microAppHead || !microAppBody) {
|
|
@@ -2206,16 +2209,16 @@ function extractSourceDom(htmlStr, app) {
|
|
|
2206
2209
|
fetchLinksFromHtml(wrapElement, app, microAppHead, fiberStyleResult);
|
|
2207
2210
|
}
|
|
2208
2211
|
else if (fiberStyleResult) {
|
|
2209
|
-
fiberStyleResult.then(() => app.onLoad(wrapElement));
|
|
2212
|
+
fiberStyleResult.then(() => app.onLoad({ html: wrapElement }));
|
|
2210
2213
|
}
|
|
2211
2214
|
else {
|
|
2212
|
-
app.onLoad(wrapElement);
|
|
2215
|
+
app.onLoad({ html: wrapElement });
|
|
2213
2216
|
}
|
|
2214
2217
|
if (app.source.scripts.size) {
|
|
2215
2218
|
fetchScriptsFromHtml(wrapElement, app);
|
|
2216
2219
|
}
|
|
2217
2220
|
else {
|
|
2218
|
-
app.onLoad(wrapElement);
|
|
2221
|
+
app.onLoad({ html: wrapElement });
|
|
2219
2222
|
}
|
|
2220
2223
|
}
|
|
2221
2224
|
|
|
@@ -2751,12 +2754,17 @@ function createProxyDocument(appName, sandbox) {
|
|
|
2751
2754
|
const sstEventListenerMap = new Map();
|
|
2752
2755
|
let onClickHandler = null;
|
|
2753
2756
|
let sstOnClickHandler = null;
|
|
2754
|
-
const { rawDocument, rawCreateElement, rawAddEventListener, rawRemoveEventListener, } = globalEnv;
|
|
2757
|
+
const { rawDocument, rawCreateElement, rawCreateElementNS, rawAddEventListener, rawRemoveEventListener, } = globalEnv;
|
|
2755
2758
|
function createElement(tagName, options) {
|
|
2756
2759
|
const element = rawCreateElement.call(rawDocument, tagName, options);
|
|
2757
2760
|
element.__MICRO_APP_NAME__ = appName;
|
|
2758
2761
|
return element;
|
|
2759
2762
|
}
|
|
2763
|
+
function createElementNS(namespaceURI, name, options) {
|
|
2764
|
+
const element = rawCreateElementNS.call(rawDocument, namespaceURI, name, options);
|
|
2765
|
+
element.__MICRO_APP_NAME__ = appName;
|
|
2766
|
+
return element;
|
|
2767
|
+
}
|
|
2760
2768
|
/**
|
|
2761
2769
|
* TODO:
|
|
2762
2770
|
* 1. listener 是否需要绑定proxyDocument,否则函数中的this指向原生window
|
|
@@ -2872,6 +2880,8 @@ function createProxyDocument(appName, sandbox) {
|
|
|
2872
2880
|
// TODO: 转换成数据形式,类似iframe的方式
|
|
2873
2881
|
if (key === 'createElement')
|
|
2874
2882
|
return createElement;
|
|
2883
|
+
if (key === 'createElementNS')
|
|
2884
|
+
return createElementNS;
|
|
2875
2885
|
if (key === Symbol.toStringTag)
|
|
2876
2886
|
return 'ProxyDocument';
|
|
2877
2887
|
if (key === 'defaultView')
|
|
@@ -2968,7 +2978,7 @@ function createMicroDocument(appName, proxyDocument) {
|
|
|
2968
2978
|
function patchWindow(appName, microAppWindow, sandbox) {
|
|
2969
2979
|
patchWindowProperty(microAppWindow);
|
|
2970
2980
|
createProxyWindow(appName, microAppWindow, sandbox);
|
|
2971
|
-
return patchWindowEffect(microAppWindow);
|
|
2981
|
+
return patchWindowEffect(microAppWindow, appName);
|
|
2972
2982
|
}
|
|
2973
2983
|
/**
|
|
2974
2984
|
* rewrite special properties of window
|
|
@@ -3009,22 +3019,22 @@ function createProxyWindow(appName, microAppWindow, sandbox) {
|
|
|
3009
3019
|
throttleDeferForSetAppName(appName);
|
|
3010
3020
|
if (Reflect.has(target, key) ||
|
|
3011
3021
|
(isString(key) && /^__MICRO_APP_/.test(key)) ||
|
|
3012
|
-
sandbox.scopeProperties
|
|
3013
|
-
if (
|
|
3022
|
+
includes(sandbox.scopeProperties, key)) {
|
|
3023
|
+
if (includes(RAW_GLOBAL_TARGET, key))
|
|
3014
3024
|
removeDomScope();
|
|
3015
3025
|
return Reflect.get(target, key);
|
|
3016
3026
|
}
|
|
3017
3027
|
return bindFunctionToRawTarget(Reflect.get(rawWindow, key), rawWindow);
|
|
3018
3028
|
},
|
|
3019
3029
|
set: (target, key, value) => {
|
|
3020
|
-
if (sandbox.
|
|
3030
|
+
if (includes(sandbox.rawWindowScopeKeyList, key)) {
|
|
3021
3031
|
Reflect.set(rawWindow, key, value);
|
|
3022
3032
|
}
|
|
3023
3033
|
else if (
|
|
3024
3034
|
// target.hasOwnProperty has been rewritten
|
|
3025
3035
|
!rawHasOwnProperty.call(target, key) &&
|
|
3026
3036
|
rawHasOwnProperty.call(rawWindow, key) &&
|
|
3027
|
-
!sandbox.scopeProperties
|
|
3037
|
+
!includes(sandbox.scopeProperties, key)) {
|
|
3028
3038
|
const descriptor = Object.getOwnPropertyDescriptor(rawWindow, key);
|
|
3029
3039
|
const { configurable, enumerable, writable, set } = descriptor;
|
|
3030
3040
|
// set value because it can be set
|
|
@@ -3037,32 +3047,37 @@ function createProxyWindow(appName, microAppWindow, sandbox) {
|
|
|
3037
3047
|
sandbox.injectedKeys.add(key);
|
|
3038
3048
|
}
|
|
3039
3049
|
else {
|
|
3040
|
-
|
|
3050
|
+
// all scopeProperties will add to injectedKeys, use for key in window (Proxy.has)
|
|
3051
|
+
if (!Reflect.has(target, key) || includes(sandbox.scopeProperties, key)) {
|
|
3052
|
+
sandbox.injectedKeys.add(key);
|
|
3053
|
+
}
|
|
3041
3054
|
Reflect.set(target, key, value);
|
|
3042
3055
|
}
|
|
3043
|
-
if ((sandbox.escapeProperties
|
|
3044
|
-
(
|
|
3056
|
+
if ((includes(sandbox.escapeProperties, key) ||
|
|
3057
|
+
(
|
|
3058
|
+
// TODO: staticEscapeProperties 合并到 escapeProperties
|
|
3059
|
+
includes(sandbox.staticEscapeProperties, key) &&
|
|
3045
3060
|
!Reflect.has(rawWindow, key))) &&
|
|
3046
|
-
!sandbox.scopeProperties
|
|
3061
|
+
!includes(sandbox.scopeProperties, key)) {
|
|
3047
3062
|
!Reflect.has(rawWindow, key) && sandbox.escapeKeys.add(key);
|
|
3048
3063
|
Reflect.set(rawWindow, key, value);
|
|
3049
3064
|
}
|
|
3050
3065
|
return true;
|
|
3051
3066
|
},
|
|
3052
3067
|
has: (target, key) => {
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
if (sandbox.
|
|
3061
|
-
return
|
|
3068
|
+
/**
|
|
3069
|
+
* Some keywords, such as Vue, need to meet two conditions at the same time:
|
|
3070
|
+
* 1. window.Vue --> undefined
|
|
3071
|
+
* 2. 'Vue' in window --> false
|
|
3072
|
+
* Issue https://github.com/micro-zoe/micro-app/issues/686
|
|
3073
|
+
*/
|
|
3074
|
+
if (includes(sandbox.scopeProperties, key)) {
|
|
3075
|
+
if (sandbox.injectedKeys.has(key)) {
|
|
3076
|
+
return Reflect.has(target, key); // true
|
|
3062
3077
|
}
|
|
3063
|
-
return key
|
|
3078
|
+
return !!target[key]; // false
|
|
3064
3079
|
}
|
|
3065
|
-
return
|
|
3080
|
+
return Reflect.has(target, key) || Reflect.has(rawWindow, key);
|
|
3066
3081
|
},
|
|
3067
3082
|
// Object.getOwnPropertyDescriptor(window, key)
|
|
3068
3083
|
getOwnPropertyDescriptor: (target, key) => {
|
|
@@ -3107,14 +3122,26 @@ function createProxyWindow(appName, microAppWindow, sandbox) {
|
|
|
3107
3122
|
* Rewrite side-effect events
|
|
3108
3123
|
* @param microAppWindow micro window
|
|
3109
3124
|
*/
|
|
3110
|
-
function patchWindowEffect(microAppWindow) {
|
|
3125
|
+
function patchWindowEffect(microAppWindow, appName) {
|
|
3111
3126
|
const eventListenerMap = new Map();
|
|
3112
3127
|
const sstEventListenerMap = new Map();
|
|
3113
3128
|
const intervalIdMap = new Map();
|
|
3114
3129
|
const timeoutIdMap = new Map();
|
|
3115
3130
|
const { rawWindow, rawAddEventListener, rawRemoveEventListener, rawDispatchEvent, rawSetInterval, rawSetTimeout, rawClearInterval, rawClearTimeout, } = globalEnv;
|
|
3131
|
+
/**
|
|
3132
|
+
* All events will bind to microAppElement or rawWindow
|
|
3133
|
+
* Some special events, such as popstate、load、unmount、appstate-change、statechange..., bind to microAppElement, others bind to rawWindow
|
|
3134
|
+
* NOTE:
|
|
3135
|
+
* 1、At first, microAppWindow = new EventTarget(), but it can not compatible with iOS 14 or below, so microAppElement was used instead. (2024.1.22)
|
|
3136
|
+
* @param type event name
|
|
3137
|
+
* @returns microAppElement/rawWindow
|
|
3138
|
+
*/
|
|
3116
3139
|
function getEventTarget(type) {
|
|
3117
|
-
|
|
3140
|
+
var _a;
|
|
3141
|
+
if (SCOPE_WINDOW_EVENT.includes(type) && ((_a = appInstanceMap.get(appName)) === null || _a === void 0 ? void 0 : _a.container)) {
|
|
3142
|
+
return getRootContainer(appInstanceMap.get(appName).container);
|
|
3143
|
+
}
|
|
3144
|
+
return rawWindow;
|
|
3118
3145
|
}
|
|
3119
3146
|
/**
|
|
3120
3147
|
* listener may be null, e.g test-passive
|
|
@@ -3228,7 +3255,7 @@ function patchWindowEffect(microAppWindow) {
|
|
|
3228
3255
|
|
|
3229
3256
|
// set micro app state to origin state
|
|
3230
3257
|
function setMicroState(appName, microState) {
|
|
3231
|
-
if (
|
|
3258
|
+
if (isRouterModeSearch(appName)) {
|
|
3232
3259
|
const rawState = globalEnv.rawWindow.history.state;
|
|
3233
3260
|
const additionalState = {
|
|
3234
3261
|
microAppState: assign({}, rawState === null || rawState === void 0 ? void 0 : rawState.microAppState, {
|
|
@@ -3242,7 +3269,7 @@ function setMicroState(appName, microState) {
|
|
|
3242
3269
|
}
|
|
3243
3270
|
// delete micro app state form origin state
|
|
3244
3271
|
function removeMicroState(appName, rawState) {
|
|
3245
|
-
if (
|
|
3272
|
+
if (isRouterModeSearch(appName)) {
|
|
3246
3273
|
if (isPlainObject(rawState === null || rawState === void 0 ? void 0 : rawState.microAppState)) {
|
|
3247
3274
|
if (!isUndefined(rawState.microAppState[appName])) {
|
|
3248
3275
|
delete rawState.microAppState[appName];
|
|
@@ -3259,7 +3286,7 @@ function removeMicroState(appName, rawState) {
|
|
|
3259
3286
|
function getMicroState(appName) {
|
|
3260
3287
|
var _a;
|
|
3261
3288
|
const rawState = globalEnv.rawWindow.history.state;
|
|
3262
|
-
if (
|
|
3289
|
+
if (isRouterModeSearch(appName)) {
|
|
3263
3290
|
return ((_a = rawState === null || rawState === void 0 ? void 0 : rawState.microAppState) === null || _a === void 0 ? void 0 : _a[appName]) || null;
|
|
3264
3291
|
}
|
|
3265
3292
|
return rawState;
|
|
@@ -3299,8 +3326,11 @@ function formatQueryAppName(appName) {
|
|
|
3299
3326
|
*/
|
|
3300
3327
|
function getMicroPathFromURL(appName) {
|
|
3301
3328
|
var _a, _b;
|
|
3329
|
+
// TODO: pure模式从state中获取地址
|
|
3330
|
+
if (isRouterModePure(appName))
|
|
3331
|
+
return null;
|
|
3302
3332
|
const rawLocation = globalEnv.rawWindow.location;
|
|
3303
|
-
if (
|
|
3333
|
+
if (isRouterModeSearch(appName)) {
|
|
3304
3334
|
const queryObject = getQueryObjectFromURL(rawLocation.search, rawLocation.hash);
|
|
3305
3335
|
const microPath = ((_a = queryObject.hashQuery) === null || _a === void 0 ? void 0 : _a[formatQueryAppName(appName)]) || ((_b = queryObject.searchQuery) === null || _b === void 0 ? void 0 : _b[formatQueryAppName(appName)]);
|
|
3306
3336
|
return isString(microPath) ? decodeMicroPath(microPath) : null;
|
|
@@ -3315,7 +3345,7 @@ function getMicroPathFromURL(appName) {
|
|
|
3315
3345
|
function setMicroPathToURL(appName, targetLocation) {
|
|
3316
3346
|
const targetFullPath = targetLocation.pathname + targetLocation.search + targetLocation.hash;
|
|
3317
3347
|
let isAttach2Hash = false;
|
|
3318
|
-
if (
|
|
3348
|
+
if (isRouterModeSearch(appName)) {
|
|
3319
3349
|
let { pathname, search, hash } = globalEnv.rawWindow.location;
|
|
3320
3350
|
const queryObject = getQueryObjectFromURL(search, hash);
|
|
3321
3351
|
const encodedMicroPath = encodeMicroPath(targetFullPath);
|
|
@@ -3367,7 +3397,7 @@ function removeMicroPathFromURL(appName, targetLocation) {
|
|
|
3367
3397
|
var _a, _b, _c, _d;
|
|
3368
3398
|
let { pathname, search, hash } = targetLocation || globalEnv.rawWindow.location;
|
|
3369
3399
|
let isAttach2Hash = false;
|
|
3370
|
-
if (
|
|
3400
|
+
if (isRouterModeSearch(appName)) {
|
|
3371
3401
|
const queryObject = getQueryObjectFromURL(search, hash);
|
|
3372
3402
|
if ((_a = queryObject.hashQuery) === null || _a === void 0 ? void 0 : _a[formatQueryAppName(appName)]) {
|
|
3373
3403
|
isAttach2Hash = true;
|
|
@@ -3427,15 +3457,31 @@ function isEffectiveApp(appName) {
|
|
|
3427
3457
|
*/
|
|
3428
3458
|
return !!(app && !app.isPrefetch);
|
|
3429
3459
|
}
|
|
3460
|
+
// router mode is search
|
|
3461
|
+
function isRouterModeSearch(appName) {
|
|
3462
|
+
const app = appInstanceMap.get(appName);
|
|
3463
|
+
return !!(app && app.sandBox && app.routerMode === DEFAULT_ROUTER_MODE);
|
|
3464
|
+
}
|
|
3465
|
+
// router mode is history
|
|
3466
|
+
function isRouterModeNative(appName) {
|
|
3467
|
+
const app = appInstanceMap.get(appName);
|
|
3468
|
+
return !!(app && app.sandBox && app.routerMode === ROUTER_MODE_NATIVE);
|
|
3469
|
+
}
|
|
3470
|
+
// router mode is disable
|
|
3471
|
+
function isRouterModeNativeScope(appName) {
|
|
3472
|
+
const app = appInstanceMap.get(appName);
|
|
3473
|
+
return !!(app && app.sandBox && app.routerMode === ROUTER_MODE_NATIVE_SCOPE);
|
|
3474
|
+
}
|
|
3475
|
+
// router mode is pure
|
|
3476
|
+
function isRouterModePure(appName) {
|
|
3477
|
+
const app = appInstanceMap.get(appName);
|
|
3478
|
+
return !!(app && app.sandBox && app.routerMode === ROUTER_MODE_PURE);
|
|
3479
|
+
}
|
|
3430
3480
|
/**
|
|
3431
|
-
* router mode is
|
|
3432
|
-
* NOTE:
|
|
3433
|
-
* 1. if sandbox disabled, router mode defaults to custom
|
|
3434
|
-
* 2. if app not exist, router mode defaults to custom
|
|
3481
|
+
* router mode is history or disable
|
|
3435
3482
|
*/
|
|
3436
3483
|
function isRouterModeCustom(appName) {
|
|
3437
|
-
|
|
3438
|
-
return !app || !app.sandBox || app.routerMode === ROUTER_MODE_CUSTOM;
|
|
3484
|
+
return isRouterModeNative(appName) || isRouterModeNativeScope(appName);
|
|
3439
3485
|
}
|
|
3440
3486
|
/**
|
|
3441
3487
|
* get memory router mode of child app
|
|
@@ -3443,21 +3489,21 @@ function isRouterModeCustom(appName) {
|
|
|
3443
3489
|
* 1. if microAppElement exists, it means the app render by the micro-app element
|
|
3444
3490
|
* 2. if microAppElement not exists, it means it is prerender app
|
|
3445
3491
|
* @param mode native config
|
|
3446
|
-
* @param
|
|
3447
|
-
* @returns mode
|
|
3492
|
+
* @param inlineDisableMemoryRouter disable-memory-router set by micro-app element or prerender
|
|
3493
|
+
* @returns router mode
|
|
3448
3494
|
*/
|
|
3449
|
-
function getRouterMode(mode,
|
|
3450
|
-
let routerMode;
|
|
3495
|
+
function getRouterMode(mode, inlineDisableMemoryRouter) {
|
|
3451
3496
|
/**
|
|
3452
3497
|
* compatible with disable-memory-router in older versions
|
|
3453
|
-
* if disable-memory-router is true, router-mode will be
|
|
3498
|
+
* if disable-memory-router is true, router-mode will be disable
|
|
3499
|
+
* Priority:
|
|
3500
|
+
* inline disable-memory-router > inline router-mode > global disable-memory-router > global router-mode
|
|
3454
3501
|
*/
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
}
|
|
3502
|
+
const routerMode = ((inlineDisableMemoryRouter && ROUTER_MODE_NATIVE) ||
|
|
3503
|
+
mode ||
|
|
3504
|
+
(microApp.options['disable-memory-router'] && ROUTER_MODE_NATIVE) ||
|
|
3505
|
+
microApp.options['router-mode'] ||
|
|
3506
|
+
DEFAULT_ROUTER_MODE);
|
|
3461
3507
|
return ROUTER_MODE_LIST.includes(routerMode) ? routerMode : DEFAULT_ROUTER_MODE;
|
|
3462
3508
|
}
|
|
3463
3509
|
|
|
@@ -3603,7 +3649,7 @@ function dispatchNativeEvent(appName, onlyForBrowser, oldHref) {
|
|
|
3603
3649
|
* create proxyHistory for microApp
|
|
3604
3650
|
* MDN https://developer.mozilla.org/en-US/docs/Web/API/History
|
|
3605
3651
|
* @param appName app name
|
|
3606
|
-
* @param microLocation microApp location
|
|
3652
|
+
* @param microLocation microApp location(with: proxyLocation iframe: iframeWindow.location)
|
|
3607
3653
|
*/
|
|
3608
3654
|
function createMicroHistory(appName, microLocation) {
|
|
3609
3655
|
const rawHistory = globalEnv.rawWindow.history;
|
|
@@ -3614,7 +3660,9 @@ function createMicroHistory(appName, microLocation) {
|
|
|
3614
3660
|
if (isString(rests[2]) || isURL(rests[2])) {
|
|
3615
3661
|
const targetLocation = createURL(rests[2], microLocation.href);
|
|
3616
3662
|
const targetFullPath = targetLocation.pathname + targetLocation.search + targetLocation.hash;
|
|
3617
|
-
|
|
3663
|
+
if (!isRouterModePure(appName)) {
|
|
3664
|
+
navigateWithNativeEvent(appName, methodName, setMicroPathToURL(appName, targetLocation), true, setMicroState(appName, rests[0]), rests[1]);
|
|
3665
|
+
}
|
|
3618
3666
|
if (targetFullPath !== microLocation.fullPath) {
|
|
3619
3667
|
updateMicroLocation(appName, targetFullPath, microLocation);
|
|
3620
3668
|
}
|
|
@@ -3693,10 +3741,10 @@ function navigateWithNativeEvent(appName, methodName, result, onlyForBrowser, st
|
|
|
3693
3741
|
nativeHistoryNavigate(appName, methodName, result.fullPath, state, title);
|
|
3694
3742
|
/**
|
|
3695
3743
|
* TODO:
|
|
3696
|
-
* 1. 如果所有模式统一发送popstate
|
|
3744
|
+
* 1. 如果所有模式统一发送popstate事件,则isRouterModeSearch(appName)要去掉
|
|
3697
3745
|
* 2. 如果发送事件,则会导致vue router-view :key='router.path'绑定,无限卸载应用,死循环
|
|
3698
3746
|
*/
|
|
3699
|
-
if (oldFullPath !== result.fullPath &&
|
|
3747
|
+
if (oldFullPath !== result.fullPath && isRouterModeSearch(appName)) {
|
|
3700
3748
|
dispatchNativeEvent(appName, onlyForBrowser, oldHref);
|
|
3701
3749
|
}
|
|
3702
3750
|
}
|
|
@@ -3743,7 +3791,7 @@ function reWriteHistoryMethod(method) {
|
|
|
3743
3791
|
excludeHiddenApp: true,
|
|
3744
3792
|
excludePreRender: true,
|
|
3745
3793
|
}).forEach(appName => {
|
|
3746
|
-
if (
|
|
3794
|
+
if (isRouterModeSearch(appName) && !getMicroPathFromURL(appName)) {
|
|
3747
3795
|
const app = appInstanceMap.get(appName);
|
|
3748
3796
|
attachRouteToBrowserURL(appName, setMicroPathToURL(appName, app.sandBox.proxyWindow.location), setMicroState(appName, getMicroState(appName)));
|
|
3749
3797
|
}
|
|
@@ -3795,8 +3843,10 @@ function createRouterApi() {
|
|
|
3795
3843
|
const currentFullPath = microLocation.pathname + microLocation.search + microLocation.hash;
|
|
3796
3844
|
const targetFullPath = targetLocation.pathname + targetLocation.search + targetLocation.hash;
|
|
3797
3845
|
if (currentFullPath !== targetFullPath || getMicroPathFromURL(appName) !== targetFullPath) {
|
|
3798
|
-
|
|
3799
|
-
|
|
3846
|
+
if (!isRouterModePure(appName)) {
|
|
3847
|
+
const methodName = (replace && to.replace !== false) || to.replace === true ? 'replaceState' : 'pushState';
|
|
3848
|
+
navigateWithRawHistory(appName, methodName, targetLocation, to.state);
|
|
3849
|
+
}
|
|
3800
3850
|
/**
|
|
3801
3851
|
* TODO:
|
|
3802
3852
|
* 1. 关闭虚拟路由的跳转地址不同:baseRoute + 子应用地址,文档中要说明
|
|
@@ -3809,7 +3859,7 @@ function createRouterApi() {
|
|
|
3809
3859
|
* NOTE1: history和search模式采用2,这样可以解决vue3的问题,custom采用1,避免vue循环刷新的问题,这样在用户出现问题时各有解决方案。但反过来说,每种方案又分别导致另外的问题,不统一,导致复杂度增高
|
|
3810
3860
|
* NOTE2: 关闭虚拟路由,同时发送popstate事件还是无法解决vue3的问题(毕竟history.state理论上还是会冲突),那么就没必要发送popstate事件了。
|
|
3811
3861
|
*/
|
|
3812
|
-
if (isRouterModeCustom(appName)) {
|
|
3862
|
+
if (isRouterModeCustom(appName) || isRouterModePure(appName)) {
|
|
3813
3863
|
updateMicroLocationWithEvent(appName, targetFullPath);
|
|
3814
3864
|
}
|
|
3815
3865
|
}
|
|
@@ -3927,7 +3977,7 @@ function createRouterApi() {
|
|
|
3927
3977
|
* 3. router mode is custom
|
|
3928
3978
|
*/
|
|
3929
3979
|
function commonHandlerForAttachToURL(appName) {
|
|
3930
|
-
if (
|
|
3980
|
+
if (isRouterModeSearch(appName)) {
|
|
3931
3981
|
const app = appInstanceMap.get(appName);
|
|
3932
3982
|
attachRouteToBrowserURL(appName, setMicroPathToURL(appName, app.sandBox.proxyWindow.location), setMicroState(appName, getMicroState(appName)));
|
|
3933
3983
|
}
|
|
@@ -4159,7 +4209,7 @@ function createMicroLocation(appName, url, microAppWindow, childStaticLocation,
|
|
|
4159
4209
|
if (targetLocation.origin === proxyLocation.origin) {
|
|
4160
4210
|
const setMicroPathResult = setMicroPathToURL(appName, targetLocation);
|
|
4161
4211
|
// if disable memory-router, navigate directly through rawLocation
|
|
4162
|
-
if (
|
|
4212
|
+
if (isRouterModeSearch(appName)) {
|
|
4163
4213
|
/**
|
|
4164
4214
|
* change hash with location.href will not trigger the browser reload
|
|
4165
4215
|
* so we use pushState & reload to imitate href behavior
|
|
@@ -4245,6 +4295,20 @@ function createMicroLocation(appName, url, microAppWindow, childStaticLocation,
|
|
|
4245
4295
|
const proxyLocation = new Proxy({}, {
|
|
4246
4296
|
get: (_, key) => {
|
|
4247
4297
|
const target = getTarget();
|
|
4298
|
+
if (key === 'assign')
|
|
4299
|
+
return assign;
|
|
4300
|
+
if (key === 'replace')
|
|
4301
|
+
return replace;
|
|
4302
|
+
if (key === 'reload')
|
|
4303
|
+
return reload;
|
|
4304
|
+
if (key === 'self')
|
|
4305
|
+
return target;
|
|
4306
|
+
if (key === 'fullPath')
|
|
4307
|
+
return target.fullPath;
|
|
4308
|
+
if (isRouterModeNative(appName)) {
|
|
4309
|
+
return bindFunctionToRawTarget(Reflect.get(rawLocation, key), rawLocation, 'LOCATION');
|
|
4310
|
+
}
|
|
4311
|
+
// src of iframe is base app address, it needs to be replaced separately
|
|
4248
4312
|
if (isIframe) {
|
|
4249
4313
|
// host hostname port protocol
|
|
4250
4314
|
if (hijackMicroLocationKeys.includes(key)) {
|
|
@@ -4255,29 +4319,21 @@ function createMicroLocation(appName, url, microAppWindow, childStaticLocation,
|
|
|
4255
4319
|
return target[key].replace(browserHost, childHost);
|
|
4256
4320
|
}
|
|
4257
4321
|
}
|
|
4258
|
-
if (key === 'assign')
|
|
4259
|
-
return assign;
|
|
4260
|
-
if (key === 'replace')
|
|
4261
|
-
return replace;
|
|
4262
|
-
if (key === 'reload')
|
|
4263
|
-
return reload;
|
|
4264
|
-
if (key === 'self')
|
|
4265
|
-
return target;
|
|
4266
4322
|
return bindFunctionToRawTarget(Reflect.get(target, key), target, 'LOCATION');
|
|
4267
4323
|
},
|
|
4268
4324
|
set: (_, key, value) => {
|
|
4269
4325
|
if (isEffectiveApp(appName)) {
|
|
4270
4326
|
const target = getTarget();
|
|
4271
4327
|
if (key === 'href') {
|
|
4272
|
-
const targetPath = commonHandler(value, 'pushState');
|
|
4273
4328
|
/**
|
|
4274
4329
|
* In vite, targetPath without origin will be completed with child origin
|
|
4275
4330
|
* So we use browser origin to complete targetPath to avoid this problem
|
|
4276
|
-
*
|
|
4277
|
-
*
|
|
4278
|
-
*
|
|
4279
|
-
*
|
|
4331
|
+
* NOTE:
|
|
4332
|
+
* 1. history mode & value is childOrigin + path ==> jump to browserOrigin + path
|
|
4333
|
+
* 2. disable mode & value is childOrigin + path ==> jump to childOrigin + path
|
|
4334
|
+
* 3. search mode & value is browserOrigin + path ==> jump to browserOrigin + path
|
|
4280
4335
|
*/
|
|
4336
|
+
const targetPath = commonHandler(value, 'pushState');
|
|
4281
4337
|
if (targetPath) {
|
|
4282
4338
|
rawLocation.href = createURL(targetPath, rawLocation.origin).href;
|
|
4283
4339
|
}
|
|
@@ -4362,9 +4418,11 @@ function updateMicroLocation(appName, path, microLocation, type) {
|
|
|
4362
4418
|
(_a = microAppWindow.rawReplaceState) === null || _a === void 0 ? void 0 : _a.call(microAppWindow.history, getMicroState(appName), '', newLocation.href);
|
|
4363
4419
|
}
|
|
4364
4420
|
else {
|
|
4365
|
-
|
|
4366
|
-
|
|
4421
|
+
let targetHref = newLocation.href;
|
|
4422
|
+
if (microLocation.self.origin !== newLocation.origin) {
|
|
4423
|
+
targetHref = targetHref.replace(newLocation.origin, microLocation.self.origin);
|
|
4367
4424
|
}
|
|
4425
|
+
microLocation.self.href = targetHref;
|
|
4368
4426
|
}
|
|
4369
4427
|
// update latest values of microLocation to `to`
|
|
4370
4428
|
const to = createGuardLocation(appName, microLocation);
|
|
@@ -4375,13 +4433,9 @@ function updateMicroLocation(appName, path, microLocation, type) {
|
|
|
4375
4433
|
}
|
|
4376
4434
|
|
|
4377
4435
|
/**
|
|
4378
|
-
* TODO:
|
|
4379
|
-
* 1.
|
|
4380
|
-
* 2.
|
|
4381
|
-
* 3. keep-router-state功能失效,因为始终为true
|
|
4382
|
-
* 4. 基座控制子应用跳转地址改变,正确的值为:baseRoute + 子应用地址,这要在文档中说明,否则很容易出错,确实也很难理解
|
|
4383
|
-
* 5. 是否需要发送popstate事件,为了减小对基座的影响,现在不发送
|
|
4384
|
-
* 6. 关闭后导致的vue3路由冲突问题需要在文档中明确指出(2处:在关闭虚拟路由系统的配置那里着重说明,在vue常见问题中说明)
|
|
4436
|
+
* TODO: 关于关闭虚拟路由系统的custom、history模式
|
|
4437
|
+
* 1. 是否需要发送popstate事件,为了减小对基座的影响,现在不发送
|
|
4438
|
+
* 2. 关闭后导致的vue3路由冲突问题需要在文档中明确指出(2处:在关闭虚拟路由系统的配置那里着重说明,在vue常见问题中说明)
|
|
4385
4439
|
*/
|
|
4386
4440
|
/**
|
|
4387
4441
|
* The router system has two operations: read and write
|
|
@@ -4422,8 +4476,10 @@ function updateBrowserURLWithLocation(appName, microLocation, defaultPage) {
|
|
|
4422
4476
|
// update microLocation with defaultPage
|
|
4423
4477
|
if (defaultPage)
|
|
4424
4478
|
updateMicroLocation(appName, defaultPage, microLocation, 'prevent');
|
|
4425
|
-
|
|
4426
|
-
|
|
4479
|
+
if (!isRouterModePure(appName)) {
|
|
4480
|
+
// attach microApp route info to browser URL
|
|
4481
|
+
attachRouteToBrowserURL(appName, setMicroPathToURL(appName, microLocation), setMicroState(appName, null));
|
|
4482
|
+
}
|
|
4427
4483
|
// trigger guards after change browser URL
|
|
4428
4484
|
autoTriggerNavigationGuard(appName, microLocation);
|
|
4429
4485
|
}
|
|
@@ -4440,7 +4496,9 @@ function clearRouteStateFromURL(appName, url, microLocation, keepRouteState) {
|
|
|
4440
4496
|
const { pathname, search, hash } = createURL(url);
|
|
4441
4497
|
updateMicroLocation(appName, pathname + search + hash, microLocation, 'prevent');
|
|
4442
4498
|
}
|
|
4443
|
-
|
|
4499
|
+
if (!isRouterModePure(appName)) {
|
|
4500
|
+
removePathFromBrowser(appName);
|
|
4501
|
+
}
|
|
4444
4502
|
}
|
|
4445
4503
|
clearRouterWhenUnmount(appName);
|
|
4446
4504
|
}
|
|
@@ -4452,10 +4510,10 @@ function removePathFromBrowser(appName) {
|
|
|
4452
4510
|
attachRouteToBrowserURL(appName, removeMicroPathFromURL(appName), removeMicroState(appName, globalEnv.rawWindow.history.state));
|
|
4453
4511
|
}
|
|
4454
4512
|
|
|
4455
|
-
class
|
|
4513
|
+
class BaseSandbox {
|
|
4456
4514
|
constructor() {
|
|
4457
4515
|
// keys that can only assigned to rawWindow
|
|
4458
|
-
this.
|
|
4516
|
+
this.rawWindowScopeKeyList = [
|
|
4459
4517
|
'location',
|
|
4460
4518
|
];
|
|
4461
4519
|
// keys that can escape to rawWindow
|
|
@@ -4468,7 +4526,18 @@ class Adapter {
|
|
|
4468
4526
|
'webpackJsonp',
|
|
4469
4527
|
'webpackHotUpdate',
|
|
4470
4528
|
'Vue',
|
|
4529
|
+
// TODO: 是否可以和constants/SCOPE_WINDOW_ON_EVENT合并
|
|
4530
|
+
'onpopstate',
|
|
4531
|
+
'onhashchange',
|
|
4471
4532
|
];
|
|
4533
|
+
// Properties that can only get and set in microAppWindow, will not escape to rawWindow
|
|
4534
|
+
this.scopeProperties = Array.from(this.staticScopeProperties);
|
|
4535
|
+
// Properties that can be escape to rawWindow
|
|
4536
|
+
this.escapeProperties = [];
|
|
4537
|
+
// Properties newly added to microAppWindow
|
|
4538
|
+
this.injectedKeys = new Set();
|
|
4539
|
+
// Properties escape to rawWindow, cleared when unmount
|
|
4540
|
+
this.escapeKeys = new Set();
|
|
4472
4541
|
this.injectReactHMRProperty();
|
|
4473
4542
|
}
|
|
4474
4543
|
// adapter for react
|
|
@@ -4486,6 +4555,14 @@ class Adapter {
|
|
|
4486
4555
|
}
|
|
4487
4556
|
}
|
|
4488
4557
|
}
|
|
4558
|
+
/**
|
|
4559
|
+
* TODO:
|
|
4560
|
+
* 1、将class Adapter去掉,改为CustomWindow,或者让CustomWindow继承Adapter
|
|
4561
|
+
* 2、with沙箱中的常量放入CustomWindow,虽然和iframe沙箱不一致,但更合理
|
|
4562
|
+
* 修改时机:在iframe沙箱支持插件后再修改
|
|
4563
|
+
*/
|
|
4564
|
+
class CustomWindow {
|
|
4565
|
+
}
|
|
4489
4566
|
// Fix conflict of babel-polyfill@6.x
|
|
4490
4567
|
function fixBabelPolyfill6() {
|
|
4491
4568
|
if (globalEnv.rawWindow._babelPolyfill)
|
|
@@ -4544,6 +4621,7 @@ function updateElementInfo(node, appName) {
|
|
|
4544
4621
|
rawDefineProperties(node, {
|
|
4545
4622
|
baseURI: {
|
|
4546
4623
|
configurable: true,
|
|
4624
|
+
// if disable-memory-router or router-mode='disable', href point to base app
|
|
4547
4625
|
get: () => proxyWindow.location.href,
|
|
4548
4626
|
},
|
|
4549
4627
|
__MICRO_APP_NAME__: {
|
|
@@ -4552,58 +4630,9 @@ function updateElementInfo(node, appName) {
|
|
|
4552
4630
|
value: appName,
|
|
4553
4631
|
},
|
|
4554
4632
|
});
|
|
4555
|
-
if (isIframeSandbox(appName)) {
|
|
4556
|
-
/**
|
|
4557
|
-
* If HTML built-in node belongs to base app, it needs to be handled separately for parentNode
|
|
4558
|
-
* Fix error for nuxt@2.x + ElementUI@2.x
|
|
4559
|
-
*/
|
|
4560
|
-
if (node instanceof globalEnv.rawRootNode) {
|
|
4561
|
-
rawDefineProperty(node, 'parentNode', {
|
|
4562
|
-
configurable: true,
|
|
4563
|
-
get: createGetterForIframeParentNode(appName, globalEnv.rawParentNodeDesc, true)
|
|
4564
|
-
});
|
|
4565
|
-
}
|
|
4566
|
-
}
|
|
4567
4633
|
}
|
|
4568
4634
|
return node;
|
|
4569
4635
|
}
|
|
4570
|
-
/**
|
|
4571
|
-
* patch iframe node parentNode
|
|
4572
|
-
* Scenes:
|
|
4573
|
-
* 1. iframe common node: patch Node.prototype.parentNode to hijack parentNode
|
|
4574
|
-
* 2. iframe HTML built-in node: belongs to base app, we should rewrite parentNode for every built-in node
|
|
4575
|
-
* NOTE:
|
|
4576
|
-
* 1. HTML built-in node parentNode cannot point to raw body, otherwise Vue2 will render failed
|
|
4577
|
-
* @param appName app name
|
|
4578
|
-
* @param parentNode parentNode Descriptor of iframe or browser
|
|
4579
|
-
* @param HTMLBuildInNode is HTML built-in node
|
|
4580
|
-
*/
|
|
4581
|
-
function createGetterForIframeParentNode(appName, parentNodeDesc, HTMLBuildInNode) {
|
|
4582
|
-
return function () {
|
|
4583
|
-
var _a, _b, _c;
|
|
4584
|
-
/**
|
|
4585
|
-
* set current appName for hijack parentNode of html
|
|
4586
|
-
* NOTE:
|
|
4587
|
-
* 1. Is there a problem with setting the current appName in iframe mode
|
|
4588
|
-
*/
|
|
4589
|
-
throttleDeferForSetAppName(appName);
|
|
4590
|
-
const result = parentNodeDesc.get.call(this);
|
|
4591
|
-
/**
|
|
4592
|
-
* If parentNode is <micro-app-body>, return rawDocument.body
|
|
4593
|
-
* Scenes:
|
|
4594
|
-
* 1. element-ui@2/lib/utils/vue-popper.js
|
|
4595
|
-
* if (this.popperElm.parentNode === document.body) ...
|
|
4596
|
-
* WARNING:
|
|
4597
|
-
* Will it cause other problems ?
|
|
4598
|
-
* e.g. target.parentNode.remove(target)
|
|
4599
|
-
*/
|
|
4600
|
-
if (!HTMLBuildInNode &&
|
|
4601
|
-
isMicroAppBody(result) && ((_a = appInstanceMap.get(appName)) === null || _a === void 0 ? void 0 : _a.container)) {
|
|
4602
|
-
return ((_c = (_b = microApp.options).getRootElementParentNode) === null || _c === void 0 ? void 0 : _c.call(_b, this, appName)) || globalEnv.rawDocument.body;
|
|
4603
|
-
}
|
|
4604
|
-
return result;
|
|
4605
|
-
};
|
|
4606
|
-
}
|
|
4607
4636
|
|
|
4608
4637
|
/**
|
|
4609
4638
|
* https://developer.mozilla.org/en-US/docs/Web/API/fetch
|
|
@@ -4707,23 +4736,12 @@ function useMicroEventSource() {
|
|
|
4707
4736
|
}
|
|
4708
4737
|
|
|
4709
4738
|
const { createMicroEventSource, clearMicroEventSource } = useMicroEventSource();
|
|
4710
|
-
class WithSandBox {
|
|
4739
|
+
class WithSandBox extends BaseSandbox {
|
|
4711
4740
|
constructor(appName, url) {
|
|
4741
|
+
super();
|
|
4712
4742
|
this.active = false;
|
|
4713
|
-
|
|
4714
|
-
* Scoped global Properties(Properties that can only get and set in microAppWindow, will not escape to rawWindow)
|
|
4715
|
-
* Fix https://github.com/micro-zoe/micro-app/issues/234
|
|
4716
|
-
*/
|
|
4717
|
-
this.scopeProperties = [];
|
|
4718
|
-
// Properties that can be escape to rawWindow
|
|
4719
|
-
this.escapeProperties = [];
|
|
4720
|
-
// Properties escape to rawWindow, cleared when unmount
|
|
4721
|
-
this.escapeKeys = new Set();
|
|
4722
|
-
// Properties newly added to microAppWindow
|
|
4723
|
-
this.injectedKeys = new Set();
|
|
4724
|
-
this.microAppWindow = new EventTarget(); // Proxy target
|
|
4743
|
+
this.microAppWindow = new CustomWindow(); // Proxy target
|
|
4725
4744
|
this.patchWith((resolve) => {
|
|
4726
|
-
this.adapter = new Adapter();
|
|
4727
4745
|
// get scopeProperties and escapeProperties from plugins
|
|
4728
4746
|
this.getSpecialProperties(appName);
|
|
4729
4747
|
// create location, history for child app
|
|
@@ -4732,6 +4750,8 @@ class WithSandBox {
|
|
|
4732
4750
|
this.windowEffect = patchWindow(appName, this.microAppWindow, this);
|
|
4733
4751
|
// patch document of child app
|
|
4734
4752
|
this.documentEffect = patchDocument(appName, this.microAppWindow, this);
|
|
4753
|
+
// properties associated with the native window
|
|
4754
|
+
this.setMappingPropertiesWithRawDescriptor(this.microAppWindow);
|
|
4735
4755
|
// inject global properties
|
|
4736
4756
|
this.initStaticGlobalKeys(appName, url, this.microAppWindow);
|
|
4737
4757
|
resolve();
|
|
@@ -4820,6 +4840,7 @@ class WithSandBox {
|
|
|
4820
4840
|
}
|
|
4821
4841
|
/**
|
|
4822
4842
|
* inject global properties to microAppWindow
|
|
4843
|
+
* TODO: 设置为只读变量
|
|
4823
4844
|
* @param appName app name
|
|
4824
4845
|
* @param url app url
|
|
4825
4846
|
* @param microAppWindow micro window
|
|
@@ -4833,6 +4854,7 @@ class WithSandBox {
|
|
|
4833
4854
|
microAppWindow.__MICRO_APP_WINDOW__ = microAppWindow;
|
|
4834
4855
|
microAppWindow.__MICRO_APP_PRE_RENDER__ = false;
|
|
4835
4856
|
microAppWindow.__MICRO_APP_UMD_MODE__ = false;
|
|
4857
|
+
microAppWindow.__MICRO_APP_PROXY_WINDOW__ = this.proxyWindow;
|
|
4836
4858
|
microAppWindow.__MICRO_APP_SANDBOX__ = this;
|
|
4837
4859
|
microAppWindow.__MICRO_APP_SANDBOX_TYPE__ = 'with';
|
|
4838
4860
|
microAppWindow.rawWindow = globalEnv.rawWindow;
|
|
@@ -4842,7 +4864,6 @@ class WithSandBox {
|
|
|
4842
4864
|
pureCreateElement,
|
|
4843
4865
|
router,
|
|
4844
4866
|
});
|
|
4845
|
-
this.setMappingPropertiesWithRawDescriptor(microAppWindow);
|
|
4846
4867
|
}
|
|
4847
4868
|
/**
|
|
4848
4869
|
* Record global effect and then release (effect: global event, timeout, data listener)
|
|
@@ -4925,7 +4946,6 @@ class WithSandBox {
|
|
|
4925
4946
|
*/
|
|
4926
4947
|
getSpecialProperties(appName) {
|
|
4927
4948
|
var _a;
|
|
4928
|
-
this.scopeProperties = this.scopeProperties.concat(this.adapter.staticScopeProperties);
|
|
4929
4949
|
if (isPlainObject(microApp.options.plugins)) {
|
|
4930
4950
|
this.commonActionForSpecialProperties(microApp.options.plugins.global);
|
|
4931
4951
|
this.commonActionForSpecialProperties((_a = microApp.options.plugins.modules) === null || _a === void 0 ? void 0 : _a[appName]);
|
|
@@ -4967,9 +4987,10 @@ class WithSandBox {
|
|
|
4967
4987
|
topValue = rawWindow.top;
|
|
4968
4988
|
parentValue = rawWindow.parent;
|
|
4969
4989
|
}
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
4990
|
+
rawDefineProperties(microAppWindow, {
|
|
4991
|
+
top: this.createDescriptorForMicroAppWindow('top', topValue),
|
|
4992
|
+
parent: this.createDescriptorForMicroAppWindow('parent', parentValue),
|
|
4993
|
+
});
|
|
4973
4994
|
GLOBAL_KEY_TO_WINDOW.forEach((key) => {
|
|
4974
4995
|
rawDefineProperty(microAppWindow, key, this.createDescriptorForMicroAppWindow(key, this.proxyWindow));
|
|
4975
4996
|
});
|
|
@@ -5134,7 +5155,7 @@ class WithSandBox {
|
|
|
5134
5155
|
WithSandBox.activeCount = 0; // number of active sandbox
|
|
5135
5156
|
|
|
5136
5157
|
function patchRouter(appName, url, microAppWindow, browserHost) {
|
|
5137
|
-
const childStaticLocation =
|
|
5158
|
+
const childStaticLocation = createURL(url);
|
|
5138
5159
|
const childHost = childStaticLocation.protocol + '//' + childStaticLocation.host;
|
|
5139
5160
|
const childFullPath = childStaticLocation.pathname + childStaticLocation.search + childStaticLocation.hash;
|
|
5140
5161
|
// rewrite microAppWindow.history
|
|
@@ -5227,18 +5248,35 @@ function patchWindowProperty$1(appName, microAppWindow) {
|
|
|
5227
5248
|
*/
|
|
5228
5249
|
function createProxyWindow$1(microAppWindow, sandbox) {
|
|
5229
5250
|
const rawWindow = globalEnv.rawWindow;
|
|
5230
|
-
const customProperties =
|
|
5251
|
+
const customProperties = new Set();
|
|
5252
|
+
/**
|
|
5253
|
+
* proxyWindow will only take effect in certain scenes, such as window.key
|
|
5254
|
+
* e.g:
|
|
5255
|
+
* 1. window.key in normal app --> fall into proxyWindow
|
|
5256
|
+
* 2. window.key in module app(vite), fall into microAppWindow(iframeWindow)
|
|
5257
|
+
* 3. if (key)... --> fall into microAppWindow(iframeWindow)
|
|
5258
|
+
*/
|
|
5231
5259
|
const proxyWindow = new Proxy(microAppWindow, {
|
|
5232
5260
|
get: (target, key) => {
|
|
5233
5261
|
if (key === 'location') {
|
|
5234
5262
|
return sandbox.proxyLocation;
|
|
5235
5263
|
}
|
|
5236
|
-
if (
|
|
5264
|
+
if (includes(GLOBAL_KEY_TO_WINDOW, key)) {
|
|
5237
5265
|
return proxyWindow;
|
|
5238
5266
|
}
|
|
5239
|
-
if (customProperties.
|
|
5267
|
+
if (customProperties.has(key)) {
|
|
5240
5268
|
return Reflect.get(target, key);
|
|
5241
5269
|
}
|
|
5270
|
+
/**
|
|
5271
|
+
* Same as proxyWindow, escapeProperties will only take effect in certain scenes
|
|
5272
|
+
* e.g:
|
|
5273
|
+
* 1. window.key in normal app --> fall into proxyWindow, escapeProperties will effect
|
|
5274
|
+
* 2. window.key in module app(vite), fall into microAppWindow(iframeWindow), escapeProperties will not take effect
|
|
5275
|
+
* 3. if (key)... --> fall into microAppWindow(iframeWindow), escapeProperties will not take effect
|
|
5276
|
+
*/
|
|
5277
|
+
if (includes(sandbox.escapeProperties, key) && !Reflect.has(target, key)) {
|
|
5278
|
+
return bindFunctionToRawTarget(Reflect.get(rawWindow, key), rawWindow);
|
|
5279
|
+
}
|
|
5242
5280
|
return bindFunctionToRawTarget(Reflect.get(target, key), target);
|
|
5243
5281
|
},
|
|
5244
5282
|
set: (target, key, value) => {
|
|
@@ -5246,10 +5284,10 @@ function createProxyWindow$1(microAppWindow, sandbox) {
|
|
|
5246
5284
|
return Reflect.set(rawWindow, key, value);
|
|
5247
5285
|
}
|
|
5248
5286
|
if (!Reflect.has(target, key)) {
|
|
5249
|
-
customProperties.
|
|
5287
|
+
customProperties.add(key);
|
|
5250
5288
|
}
|
|
5251
5289
|
Reflect.set(target, key, value);
|
|
5252
|
-
if (sandbox.escapeProperties
|
|
5290
|
+
if (includes(sandbox.escapeProperties, key)) {
|
|
5253
5291
|
!Reflect.has(rawWindow, key) && sandbox.escapeKeys.add(key);
|
|
5254
5292
|
Reflect.set(rawWindow, key, value);
|
|
5255
5293
|
}
|
|
@@ -5364,7 +5402,9 @@ function patchDocumentPrototype(appName, microAppWindow) {
|
|
|
5364
5402
|
const microRootDocument = microAppWindow.Document;
|
|
5365
5403
|
const microDocument = microAppWindow.document;
|
|
5366
5404
|
const rawMicroCreateElement = microRootDocument.prototype.createElement;
|
|
5405
|
+
const rawMicroCreateElementNS = microRootDocument.prototype.createElementNS;
|
|
5367
5406
|
const rawMicroCreateTextNode = microRootDocument.prototype.createTextNode;
|
|
5407
|
+
const rawMicroCreateDocumentFragment = microRootDocument.prototype.createDocumentFragment;
|
|
5368
5408
|
const rawMicroCreateComment = microRootDocument.prototype.createComment;
|
|
5369
5409
|
const rawMicroQuerySelector = microRootDocument.prototype.querySelector;
|
|
5370
5410
|
const rawMicroQuerySelectorAll = microRootDocument.prototype.querySelectorAll;
|
|
@@ -5385,10 +5425,18 @@ function patchDocumentPrototype(appName, microAppWindow) {
|
|
|
5385
5425
|
const element = rawMicroCreateElement.call(this, tagName, options);
|
|
5386
5426
|
return updateElementInfo(element, appName);
|
|
5387
5427
|
};
|
|
5428
|
+
microRootDocument.prototype.createElementNS = function createElementNS(namespaceURI, name, options) {
|
|
5429
|
+
const element = rawMicroCreateElementNS.call(this, namespaceURI, name, options);
|
|
5430
|
+
return updateElementInfo(element, appName);
|
|
5431
|
+
};
|
|
5388
5432
|
microRootDocument.prototype.createTextNode = function createTextNode(data) {
|
|
5389
5433
|
const element = rawMicroCreateTextNode.call(this, data);
|
|
5390
5434
|
return updateElementInfo(element, appName);
|
|
5391
5435
|
};
|
|
5436
|
+
microRootDocument.prototype.createDocumentFragment = function createDocumentFragment() {
|
|
5437
|
+
const element = rawMicroCreateDocumentFragment.call(this);
|
|
5438
|
+
return updateElementInfo(element, appName);
|
|
5439
|
+
};
|
|
5392
5440
|
microRootDocument.prototype.createComment = function createComment(data) {
|
|
5393
5441
|
const element = rawMicroCreateComment.call(this, data);
|
|
5394
5442
|
return updateElementInfo(element, appName);
|
|
@@ -5489,6 +5537,7 @@ function patchDocumentProperty(appName, microAppWindow, sandbox) {
|
|
|
5489
5537
|
const createDescriptors = () => {
|
|
5490
5538
|
const result = {};
|
|
5491
5539
|
const descList = [
|
|
5540
|
+
// if disable-memory-router or router-mode='disable', href point to base app
|
|
5492
5541
|
['documentURI', () => sandbox.proxyLocation.href],
|
|
5493
5542
|
['URL', () => sandbox.proxyLocation.href],
|
|
5494
5543
|
['documentElement', () => rawDocument.documentElement],
|
|
@@ -5722,6 +5771,7 @@ function patchIframeNode(appName, microAppWindow, sandbox) {
|
|
|
5722
5771
|
// return rootNode
|
|
5723
5772
|
};
|
|
5724
5773
|
microRootNode.prototype.appendChild = function appendChild(node) {
|
|
5774
|
+
// TODO: 有必要执行这么多次updateElementInfo?
|
|
5725
5775
|
updateElementInfo(node, appName);
|
|
5726
5776
|
if (isPureNode(node)) {
|
|
5727
5777
|
return rawMicroAppendChild.call(this, node);
|
|
@@ -5821,7 +5871,29 @@ function patchIframeNode(appName, microAppWindow, sandbox) {
|
|
|
5821
5871
|
rawDefineProperty(microRootNode.prototype, 'parentNode', {
|
|
5822
5872
|
configurable: true,
|
|
5823
5873
|
enumerable: true,
|
|
5824
|
-
get
|
|
5874
|
+
get() {
|
|
5875
|
+
var _a, _b, _c;
|
|
5876
|
+
/**
|
|
5877
|
+
* set current appName for hijack parentNode of html
|
|
5878
|
+
* NOTE:
|
|
5879
|
+
* 1. Is there a problem with setting the current appName in iframe mode
|
|
5880
|
+
*/
|
|
5881
|
+
throttleDeferForSetAppName(appName);
|
|
5882
|
+
const result = rawParentNodeDesc.get.call(this);
|
|
5883
|
+
/**
|
|
5884
|
+
* If parentNode is <micro-app-body>, return rawDocument.body
|
|
5885
|
+
* Scenes:
|
|
5886
|
+
* 1. element-ui@2/lib/utils/vue-popper.js
|
|
5887
|
+
* if (this.popperElm.parentNode === document.body) ...
|
|
5888
|
+
* WARNING:
|
|
5889
|
+
* Will it cause other problems ?
|
|
5890
|
+
* e.g. target.parentNode.remove(target)
|
|
5891
|
+
*/
|
|
5892
|
+
if (isMicroAppBody(result) && ((_a = appInstanceMap.get(appName)) === null || _a === void 0 ? void 0 : _a.container)) {
|
|
5893
|
+
return ((_c = (_b = microApp.options).getRootElementParentNode) === null || _c === void 0 ? void 0 : _c.call(_b, this, appName)) || globalEnv.rawDocument.body;
|
|
5894
|
+
}
|
|
5895
|
+
return result;
|
|
5896
|
+
}
|
|
5825
5897
|
});
|
|
5826
5898
|
// Adapt to new image(...) scene
|
|
5827
5899
|
const ImageProxy = new Proxy(microAppWindow.Image, {
|
|
@@ -5883,14 +5955,17 @@ class IframeSandbox {
|
|
|
5883
5955
|
this.escapeProperties = [];
|
|
5884
5956
|
// Properties escape to rawWindow, cleared when unmount
|
|
5885
5957
|
this.escapeKeys = new Set();
|
|
5886
|
-
//
|
|
5958
|
+
// 初始化和每次跳转时都要更新base的href
|
|
5887
5959
|
this.updateIframeBase = () => {
|
|
5888
5960
|
var _a;
|
|
5889
|
-
|
|
5961
|
+
// origin must be child app origin
|
|
5962
|
+
(_a = this.baseElement) === null || _a === void 0 ? void 0 : _a.setAttribute('href', createURL(this.url).origin + this.proxyLocation.pathname);
|
|
5890
5963
|
};
|
|
5964
|
+
this.appName = appName;
|
|
5965
|
+
this.url = url;
|
|
5891
5966
|
const rawLocation = globalEnv.rawWindow.location;
|
|
5892
5967
|
const browserHost = rawLocation.protocol + '//' + rawLocation.host;
|
|
5893
|
-
this.deleteIframeElement = this.createIframeElement(appName, browserHost);
|
|
5968
|
+
this.deleteIframeElement = this.createIframeElement(appName, browserHost + rawLocation.pathname);
|
|
5894
5969
|
this.microAppWindow = this.iframe.contentWindow;
|
|
5895
5970
|
this.patchIframe(this.microAppWindow, (resolve) => {
|
|
5896
5971
|
// create new html to iframe
|
|
@@ -5918,13 +5993,13 @@ class IframeSandbox {
|
|
|
5918
5993
|
/**
|
|
5919
5994
|
* create iframe for sandbox
|
|
5920
5995
|
* @param appName app name
|
|
5921
|
-
* @param
|
|
5996
|
+
* @param browserPath browser origin
|
|
5922
5997
|
* @returns release callback
|
|
5923
5998
|
*/
|
|
5924
|
-
createIframeElement(appName,
|
|
5999
|
+
createIframeElement(appName, browserPath) {
|
|
5925
6000
|
this.iframe = pureCreateElement('iframe');
|
|
5926
6001
|
const iframeAttrs = {
|
|
5927
|
-
src:
|
|
6002
|
+
src: microApp.options.iframeSrc || browserPath,
|
|
5928
6003
|
style: 'display: none',
|
|
5929
6004
|
id: appName,
|
|
5930
6005
|
};
|
|
@@ -6019,6 +6094,7 @@ class IframeSandbox {
|
|
|
6019
6094
|
* NOTE:
|
|
6020
6095
|
* 1. execute as early as possible
|
|
6021
6096
|
* 2. run after patchRouter & createProxyWindow
|
|
6097
|
+
* TODO: 设置为只读变量
|
|
6022
6098
|
*/
|
|
6023
6099
|
initStaticGlobalKeys(appName, url, microAppWindow) {
|
|
6024
6100
|
microAppWindow.__MICRO_APP_ENVIRONMENT__ = true;
|
|
@@ -6220,6 +6296,7 @@ class IframeSandbox {
|
|
|
6220
6296
|
patchElementTree(container, this.microAppWindow.__MICRO_APP_NAME__);
|
|
6221
6297
|
}
|
|
6222
6298
|
/**
|
|
6299
|
+
* action before exec scripts when mount
|
|
6223
6300
|
* Actions:
|
|
6224
6301
|
* 1. patch static elements from html
|
|
6225
6302
|
* @param container micro app container
|
|
@@ -6279,8 +6356,11 @@ class CreateApp {
|
|
|
6279
6356
|
}
|
|
6280
6357
|
/**
|
|
6281
6358
|
* When resource is loaded, mount app if it is not prefetch or unmount
|
|
6359
|
+
* defaultPage disablePatchRequest routerMode baseroute is only for prerender app
|
|
6282
6360
|
*/
|
|
6283
|
-
onLoad(html,
|
|
6361
|
+
onLoad({ html,
|
|
6362
|
+
// below params is only for prerender app
|
|
6363
|
+
defaultPage, routerMode, baseroute, disablePatchRequest, }) {
|
|
6284
6364
|
var _a;
|
|
6285
6365
|
if (++this.loadSourceLevel === 2) {
|
|
6286
6366
|
this.source.html = html;
|
|
@@ -6311,11 +6391,11 @@ class CreateApp {
|
|
|
6311
6391
|
this.mount({
|
|
6312
6392
|
container,
|
|
6313
6393
|
inline: this.inline,
|
|
6314
|
-
routerMode: routerMode,
|
|
6315
|
-
baseroute: baseroute || '',
|
|
6316
6394
|
fiber: true,
|
|
6317
6395
|
defaultPage: defaultPage || '',
|
|
6318
6396
|
disablePatchRequest: disablePatchRequest !== null && disablePatchRequest !== void 0 ? disablePatchRequest : false,
|
|
6397
|
+
routerMode: routerMode,
|
|
6398
|
+
baseroute: baseroute || '',
|
|
6319
6399
|
});
|
|
6320
6400
|
}
|
|
6321
6401
|
}
|
|
@@ -6385,7 +6465,7 @@ class CreateApp {
|
|
|
6385
6465
|
*/
|
|
6386
6466
|
(_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.rebuildEffectSnapshot();
|
|
6387
6467
|
// current this.container is <div prerender='true'></div>
|
|
6388
|
-
cloneContainer(container, this.container, false);
|
|
6468
|
+
this.cloneContainer(container, this.container, false);
|
|
6389
6469
|
/**
|
|
6390
6470
|
* set this.container to <micro-app></micro-app>
|
|
6391
6471
|
* NOTE:
|
|
@@ -6421,7 +6501,7 @@ class CreateApp {
|
|
|
6421
6501
|
appState: appStates.MOUNTING
|
|
6422
6502
|
});
|
|
6423
6503
|
// TODO: 将所有cloneContainer中的'as Element'去掉,兼容shadowRoot的场景
|
|
6424
|
-
cloneContainer(this.container, this.source.html, !this.umdMode);
|
|
6504
|
+
this.cloneContainer(this.container, this.source.html, !this.umdMode);
|
|
6425
6505
|
(_e = this.sandBox) === null || _e === void 0 ? void 0 : _e.start({
|
|
6426
6506
|
umdMode: this.umdMode,
|
|
6427
6507
|
baseroute,
|
|
@@ -6439,6 +6519,7 @@ class CreateApp {
|
|
|
6439
6519
|
* umdHookUnmount can works in default mode
|
|
6440
6520
|
* register through window.unmount
|
|
6441
6521
|
*/
|
|
6522
|
+
// TODO: 不对,这里要改,因为unmount不一定是函数
|
|
6442
6523
|
this.umdHookUnmount = unmount;
|
|
6443
6524
|
// if mount & unmount is function, the sub app is umd mode
|
|
6444
6525
|
if (isFunction(mount) && isFunction(unmount)) {
|
|
@@ -6609,7 +6690,7 @@ class CreateApp {
|
|
|
6609
6690
|
actionsForUnmount({ destroy, clearData, keepRouteState, unmountcb, }) {
|
|
6610
6691
|
var _a;
|
|
6611
6692
|
if (this.umdMode && this.container && !destroy) {
|
|
6612
|
-
cloneContainer(this.source.html, this.container, false);
|
|
6693
|
+
this.cloneContainer(this.source.html, this.container, false);
|
|
6613
6694
|
}
|
|
6614
6695
|
/**
|
|
6615
6696
|
* this.container maybe contains micro-app element, stop sandbox should exec after cloneContainer
|
|
@@ -6636,6 +6717,7 @@ class CreateApp {
|
|
|
6636
6717
|
this.preRenderEvents = null;
|
|
6637
6718
|
this.setKeepAliveState(null);
|
|
6638
6719
|
// in iframe sandbox & default mode, delete the sandbox & iframeElement
|
|
6720
|
+
// TODO: with沙箱与iframe沙箱保持一致:with沙箱默认模式下删除 或者 iframe沙箱umd模式下保留
|
|
6639
6721
|
if (this.iframe && !this.umdMode)
|
|
6640
6722
|
this.sandBox = null;
|
|
6641
6723
|
if (destroy)
|
|
@@ -6667,7 +6749,7 @@ class CreateApp {
|
|
|
6667
6749
|
this.setLifeCycleState(lifeCycles.AFTERHIDDEN);
|
|
6668
6750
|
// dispatch afterHidden event to base app
|
|
6669
6751
|
dispatchLifecyclesEvent(this.container, this.name, lifeCycles.AFTERHIDDEN);
|
|
6670
|
-
if (this.
|
|
6752
|
+
if (isRouterModeSearch(this.name)) {
|
|
6671
6753
|
// called after lifeCyclesEvent
|
|
6672
6754
|
(_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.removeRouteInfoForKeepAliveApp();
|
|
6673
6755
|
}
|
|
@@ -6678,7 +6760,7 @@ class CreateApp {
|
|
|
6678
6760
|
getRootContainer(this.container).unmount();
|
|
6679
6761
|
}
|
|
6680
6762
|
else {
|
|
6681
|
-
this.container = cloneContainer(pureCreateElement('div'), this.container, false);
|
|
6763
|
+
this.container = this.cloneContainer(pureCreateElement('div'), this.container, false);
|
|
6682
6764
|
(_b = this.sandBox) === null || _b === void 0 ? void 0 : _b.recordAndReleaseEffect({ keepAlive: true });
|
|
6683
6765
|
}
|
|
6684
6766
|
callback === null || callback === void 0 ? void 0 : callback();
|
|
@@ -6694,13 +6776,13 @@ class CreateApp {
|
|
|
6694
6776
|
// dispatch beforeShow event to base app
|
|
6695
6777
|
dispatchLifecyclesEvent(container, this.name, lifeCycles.BEFORESHOW);
|
|
6696
6778
|
this.setKeepAliveState(keepAliveStates.KEEP_ALIVE_SHOW);
|
|
6697
|
-
this.container = cloneContainer(container, this.container, false);
|
|
6779
|
+
this.container = this.cloneContainer(container, this.container, false);
|
|
6698
6780
|
/**
|
|
6699
6781
|
* TODO:
|
|
6700
6782
|
* 问题:当路由模式为custom时,keep-alive应用在重新展示,是否需要根据子应用location信息更新浏览器地址?
|
|
6701
6783
|
* 暂时不这么做吧,因为无法确定二次展示时新旧地址是否相同,是否带有特殊信息
|
|
6702
6784
|
*/
|
|
6703
|
-
if (this.
|
|
6785
|
+
if (isRouterModeSearch(this.name)) {
|
|
6704
6786
|
// called before lifeCyclesEvent
|
|
6705
6787
|
(_b = this.sandBox) === null || _b === void 0 ? void 0 : _b.setRouteInfoForKeepAliveApp();
|
|
6706
6788
|
}
|
|
@@ -6724,6 +6806,34 @@ class CreateApp {
|
|
|
6724
6806
|
});
|
|
6725
6807
|
dispatchLifecyclesEvent(this.container, this.name, lifeCycles.ERROR, e);
|
|
6726
6808
|
}
|
|
6809
|
+
/**
|
|
6810
|
+
* Parse htmlString to DOM
|
|
6811
|
+
* NOTE: iframe sandbox will use DOMParser of iframeWindow, with sandbox will use DOMParser of base app
|
|
6812
|
+
* @param htmlString DOMString
|
|
6813
|
+
* @returns parsed DOM
|
|
6814
|
+
*/
|
|
6815
|
+
parseHtmlString(htmlString) {
|
|
6816
|
+
var _a;
|
|
6817
|
+
const DOMParser = ((_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.proxyWindow) ? this.sandBox.proxyWindow.DOMParser
|
|
6818
|
+
: globalEnv.rawWindow.DOMParser;
|
|
6819
|
+
return (new DOMParser()).parseFromString(htmlString, 'text/html').body;
|
|
6820
|
+
}
|
|
6821
|
+
/**
|
|
6822
|
+
* clone origin elements to target
|
|
6823
|
+
* @param origin Cloned element
|
|
6824
|
+
* @param target Accept cloned elements
|
|
6825
|
+
* @param deep deep clone or transfer dom
|
|
6826
|
+
*/
|
|
6827
|
+
cloneContainer(target, origin, deep) {
|
|
6828
|
+
// 在基座接受到afterhidden方法后立即执行unmount,彻底destroy应用时,因为unmount时同步执行,所以this.container为null后才执行cloneContainer
|
|
6829
|
+
if (origin) {
|
|
6830
|
+
target.innerHTML = '';
|
|
6831
|
+
Array.from(deep ? this.parseHtmlString(origin.innerHTML).childNodes : origin.childNodes).forEach((node) => {
|
|
6832
|
+
target.appendChild(node);
|
|
6833
|
+
});
|
|
6834
|
+
}
|
|
6835
|
+
return target;
|
|
6836
|
+
}
|
|
6727
6837
|
/**
|
|
6728
6838
|
* Scene:
|
|
6729
6839
|
* 1. create app
|
|
@@ -6732,12 +6842,7 @@ class CreateApp {
|
|
|
6732
6842
|
*/
|
|
6733
6843
|
createSandbox() {
|
|
6734
6844
|
if (this.useSandbox && !this.sandBox) {
|
|
6735
|
-
|
|
6736
|
-
this.sandBox = new IframeSandbox(this.name, this.url);
|
|
6737
|
-
}
|
|
6738
|
-
else {
|
|
6739
|
-
this.sandBox = new WithSandBox(this.name, this.url);
|
|
6740
|
-
}
|
|
6845
|
+
this.sandBox = this.iframe ? new IframeSandbox(this.name, this.url) : new WithSandBox(this.name, this.url);
|
|
6741
6846
|
}
|
|
6742
6847
|
}
|
|
6743
6848
|
// set app state
|
|
@@ -6902,10 +7007,6 @@ function handleNewNode(child, app) {
|
|
|
6902
7007
|
*/
|
|
6903
7008
|
function invokePrototypeMethod(app, rawMethod, parent, targetChild, passiveChild) {
|
|
6904
7009
|
const hijackParent = getHijackParent(parent, targetChild, app);
|
|
6905
|
-
/**
|
|
6906
|
-
* If passiveChild is not the child node, insertBefore replaceChild will have a problem, at this time, it will be degraded to appendChild
|
|
6907
|
-
* E.g: document.head.insertBefore(targetChild, document.head.childNodes[0])
|
|
6908
|
-
*/
|
|
6909
7010
|
if (hijackParent) {
|
|
6910
7011
|
/**
|
|
6911
7012
|
* If parentNode is <micro-app-body>, return rawDocument.body
|
|
@@ -6944,11 +7045,28 @@ function invokePrototypeMethod(app, rawMethod, parent, targetChild, passiveChild
|
|
|
6944
7045
|
});
|
|
6945
7046
|
}
|
|
6946
7047
|
}
|
|
7048
|
+
if ((process.env.NODE_ENV !== 'production') &&
|
|
7049
|
+
isIFrameElement(targetChild) &&
|
|
7050
|
+
rawMethod === globalEnv.rawAppendChild) {
|
|
7051
|
+
fixReactHMRConflict(app);
|
|
7052
|
+
}
|
|
6947
7053
|
/**
|
|
6948
7054
|
* 1. If passiveChild exists, it must be insertBefore or replaceChild
|
|
6949
7055
|
* 2. When removeChild, targetChild may not be in microAppHead or head
|
|
7056
|
+
* NOTE:
|
|
7057
|
+
* 1. If passiveChild not in hijackParent, insertBefore replaceChild will be degraded to appendChild
|
|
7058
|
+
* E.g: document.head.replaceChild(targetChild, document.scripts[0])
|
|
7059
|
+
* 2. If passiveChild not in hijackParent but in parent and method is insertBefore, try insert it into the position corresponding to hijackParent
|
|
7060
|
+
* E.g: document.head.insertBefore(targetChild, document.head.childNodes[0])
|
|
7061
|
+
* ISSUE: https://github.com/micro-zoe/micro-app/issues/1071
|
|
6950
7062
|
*/
|
|
6951
7063
|
if (passiveChild && !hijackParent.contains(passiveChild)) {
|
|
7064
|
+
if (rawMethod === globalEnv.rawInsertBefore && parent.contains(passiveChild)) {
|
|
7065
|
+
const indexOfParent = Array.from(parent.childNodes).indexOf(passiveChild);
|
|
7066
|
+
if (hijackParent.childNodes[indexOfParent]) {
|
|
7067
|
+
return invokeRawMethod(rawMethod, hijackParent, targetChild, hijackParent.childNodes[indexOfParent]);
|
|
7068
|
+
}
|
|
7069
|
+
}
|
|
6952
7070
|
return globalEnv.rawAppendChild.call(hijackParent, targetChild);
|
|
6953
7071
|
}
|
|
6954
7072
|
else if (rawMethod === globalEnv.rawRemoveChild && !hijackParent.contains(targetChild)) {
|
|
@@ -6957,11 +7075,6 @@ function invokePrototypeMethod(app, rawMethod, parent, targetChild, passiveChild
|
|
|
6957
7075
|
}
|
|
6958
7076
|
return targetChild;
|
|
6959
7077
|
}
|
|
6960
|
-
if ((process.env.NODE_ENV !== 'production') &&
|
|
6961
|
-
isIFrameElement(targetChild) &&
|
|
6962
|
-
rawMethod === globalEnv.rawAppendChild) {
|
|
6963
|
-
fixReactHMRConflict(app);
|
|
6964
|
-
}
|
|
6965
7078
|
return invokeRawMethod(rawMethod, hijackParent, targetChild, passiveChild);
|
|
6966
7079
|
}
|
|
6967
7080
|
return invokeRawMethod(rawMethod, parent, targetChild, passiveChild);
|
|
@@ -7031,6 +7144,11 @@ function commonElementHandler(parent, newChild, passiveChild, rawMethod) {
|
|
|
7031
7144
|
currentAppName)) {
|
|
7032
7145
|
newChild.__MICRO_APP_NAME__ = newChild.__MICRO_APP_NAME__ || currentAppName;
|
|
7033
7146
|
const app = appInstanceMap.get(newChild.__MICRO_APP_NAME__);
|
|
7147
|
+
if (isStyleElement(newChild)) {
|
|
7148
|
+
const isShadowNode = parent.getRootNode();
|
|
7149
|
+
const isShadowEnvironment = isShadowNode instanceof ShadowRoot;
|
|
7150
|
+
isShadowEnvironment && newChild.setAttribute('ignore', 'true');
|
|
7151
|
+
}
|
|
7034
7152
|
if (app === null || app === void 0 ? void 0 : app.container) {
|
|
7035
7153
|
completePathDynamic(app, newChild);
|
|
7036
7154
|
return invokePrototypeMethod(app, rawMethod, parent, handleNewNode(newChild, app), passiveChild && getMappingNode(passiveChild));
|
|
@@ -7117,30 +7235,34 @@ function patchElementAndDocument() {
|
|
|
7117
7235
|
this.__MICRO_APP_NAME__ && (clonedNode.__MICRO_APP_NAME__ = this.__MICRO_APP_NAME__);
|
|
7118
7236
|
return clonedNode;
|
|
7119
7237
|
};
|
|
7120
|
-
|
|
7238
|
+
/**
|
|
7239
|
+
* document.body(head).querySelector(querySelectorAll) hijack to microAppBody(microAppHead).querySelector(querySelectorAll)
|
|
7240
|
+
* NOTE:
|
|
7241
|
+
* 1. May cause some problems!
|
|
7242
|
+
* 2. Add config options?
|
|
7243
|
+
*/
|
|
7244
|
+
function getQueryTarget(target) {
|
|
7121
7245
|
const currentAppName = getCurrentAppName();
|
|
7122
|
-
if ((
|
|
7246
|
+
if ((target === document.body || target === document.head) && currentAppName) {
|
|
7123
7247
|
const app = appInstanceMap.get(currentAppName);
|
|
7124
7248
|
if (app === null || app === void 0 ? void 0 : app.container) {
|
|
7125
|
-
if (
|
|
7249
|
+
if (target === document.body) {
|
|
7126
7250
|
return app.querySelector('micro-app-body');
|
|
7127
7251
|
}
|
|
7128
|
-
else if (
|
|
7252
|
+
else if (target === document.head) {
|
|
7129
7253
|
return app.querySelector('micro-app-head');
|
|
7130
7254
|
}
|
|
7131
7255
|
}
|
|
7132
7256
|
}
|
|
7133
|
-
return
|
|
7257
|
+
return target;
|
|
7134
7258
|
}
|
|
7135
7259
|
rawRootElement.prototype.querySelector = function querySelector(selectors) {
|
|
7136
7260
|
var _a;
|
|
7137
|
-
|
|
7138
|
-
return globalEnv.rawElementQuerySelector.call(target, selectors);
|
|
7261
|
+
return globalEnv.rawElementQuerySelector.call((_a = getQueryTarget(this)) !== null && _a !== void 0 ? _a : this, selectors);
|
|
7139
7262
|
};
|
|
7140
7263
|
rawRootElement.prototype.querySelectorAll = function querySelectorAll(selectors) {
|
|
7141
7264
|
var _a;
|
|
7142
|
-
|
|
7143
|
-
return globalEnv.rawElementQuerySelectorAll.call(target, selectors);
|
|
7265
|
+
return globalEnv.rawElementQuerySelectorAll.call((_a = getQueryTarget(this)) !== null && _a !== void 0 ? _a : this, selectors);
|
|
7144
7266
|
};
|
|
7145
7267
|
// rewrite setAttribute, complete resource address
|
|
7146
7268
|
rawRootElement.prototype.setAttribute = function setAttribute(key, value) {
|
|
@@ -7268,14 +7390,15 @@ function patchDocument$2() {
|
|
|
7268
7390
|
const element = globalEnv.rawCreateElementNS.call(getBindTarget(this), namespaceURI, name, options);
|
|
7269
7391
|
return markElement(element);
|
|
7270
7392
|
};
|
|
7271
|
-
|
|
7272
|
-
const element = globalEnv.rawCreateDocumentFragment.call(getBindTarget(this));
|
|
7273
|
-
return markElement(element);
|
|
7274
|
-
};
|
|
7393
|
+
// TODO: 放开
|
|
7275
7394
|
// rawRootDocument.prototype.createTextNode = function createTextNode (data: string): Text {
|
|
7276
7395
|
// const element = globalEnv.rawCreateTextNode.call(getBindTarget(this), data)
|
|
7277
7396
|
// return markElement(element)
|
|
7278
7397
|
// }
|
|
7398
|
+
rawRootDocument.prototype.createDocumentFragment = function createDocumentFragment() {
|
|
7399
|
+
const element = globalEnv.rawCreateDocumentFragment.call(getBindTarget(this));
|
|
7400
|
+
return markElement(element);
|
|
7401
|
+
};
|
|
7279
7402
|
rawRootDocument.prototype.createComment = function createComment(data) {
|
|
7280
7403
|
const element = globalEnv.rawCreateComment.call(getBindTarget(this), data);
|
|
7281
7404
|
return markElement(element);
|
|
@@ -7288,7 +7411,7 @@ function patchDocument$2() {
|
|
|
7288
7411
|
if (!currentAppName ||
|
|
7289
7412
|
!selectors ||
|
|
7290
7413
|
isUniqueElement(selectors) ||
|
|
7291
|
-
//
|
|
7414
|
+
// ISSUE: https://github.com/micro-zoe/micro-app/issues/56
|
|
7292
7415
|
rawDocument !== _this) {
|
|
7293
7416
|
return globalEnv.rawQuerySelector.call(_this, selectors);
|
|
7294
7417
|
}
|
|
@@ -7438,8 +7561,8 @@ function initGlobalEnv() {
|
|
|
7438
7561
|
// Document proto methods
|
|
7439
7562
|
const rawCreateElement = rawRootDocument.prototype.createElement;
|
|
7440
7563
|
const rawCreateElementNS = rawRootDocument.prototype.createElementNS;
|
|
7441
|
-
const rawCreateDocumentFragment = rawRootDocument.prototype.createDocumentFragment;
|
|
7442
7564
|
const rawCreateTextNode = rawRootDocument.prototype.createTextNode;
|
|
7565
|
+
const rawCreateDocumentFragment = rawRootDocument.prototype.createDocumentFragment;
|
|
7443
7566
|
const rawCreateComment = rawRootDocument.prototype.createComment;
|
|
7444
7567
|
const rawQuerySelector = rawRootDocument.prototype.querySelector;
|
|
7445
7568
|
const rawQuerySelectorAll = rawRootDocument.prototype.querySelectorAll;
|
|
@@ -7999,7 +8122,9 @@ function defineElement(tagName) {
|
|
|
7999
8122
|
* @returns router-mode
|
|
8000
8123
|
*/
|
|
8001
8124
|
getMemoryRouterMode() {
|
|
8002
|
-
return getRouterMode(this.getAttribute('router-mode'),
|
|
8125
|
+
return getRouterMode(this.getAttribute('router-mode'),
|
|
8126
|
+
// is micro-app element set disable-memory-router, like <micro-app disable-memory-router></micro-app>
|
|
8127
|
+
this.compatibleProperties('disable-memory-router') && this.compatibleDisableProperties('disable-memory-router'));
|
|
8003
8128
|
}
|
|
8004
8129
|
/**
|
|
8005
8130
|
* rewrite micro-app.setAttribute, process attr data
|
|
@@ -8048,6 +8173,18 @@ function defineElement(tagName) {
|
|
|
8048
8173
|
}
|
|
8049
8174
|
return null;
|
|
8050
8175
|
}
|
|
8176
|
+
/**
|
|
8177
|
+
* get publicPath from a valid address,it can used in micro-app-devtools
|
|
8178
|
+
*/
|
|
8179
|
+
get publicPath() {
|
|
8180
|
+
return getEffectivePath(this.appUrl);
|
|
8181
|
+
}
|
|
8182
|
+
/**
|
|
8183
|
+
* get baseRoute from attribute,it can used in micro-app-devtools
|
|
8184
|
+
*/
|
|
8185
|
+
get baseRoute() {
|
|
8186
|
+
return this.getBaseRouteCompatible();
|
|
8187
|
+
}
|
|
8051
8188
|
}
|
|
8052
8189
|
globalEnv.rawWindow.customElements.define(tagName, MicroAppElement);
|
|
8053
8190
|
}
|
|
@@ -8126,9 +8263,22 @@ function preFetchAction(options) {
|
|
|
8126
8263
|
});
|
|
8127
8264
|
const oldOnload = app.onLoad;
|
|
8128
8265
|
const oldOnLoadError = app.onLoadError;
|
|
8129
|
-
app.onLoad = (
|
|
8266
|
+
app.onLoad = (onLoadParam) => {
|
|
8267
|
+
if (app.isPrerender) {
|
|
8268
|
+
assign(onLoadParam, {
|
|
8269
|
+
defaultPage: options['default-page'],
|
|
8270
|
+
/**
|
|
8271
|
+
* TODO: 预渲染支持disable-memory-router,默认渲染首页即可,文档中也要保留
|
|
8272
|
+
* 问题:
|
|
8273
|
+
* 1、如何确保子应用进行跳转时不影响到浏览器地址??pure??
|
|
8274
|
+
*/
|
|
8275
|
+
routerMode: getRouterMode(options['router-mode']),
|
|
8276
|
+
baseroute: options.baseroute,
|
|
8277
|
+
disablePatchRequest: options['disable-patch-request'],
|
|
8278
|
+
});
|
|
8279
|
+
}
|
|
8130
8280
|
resolve();
|
|
8131
|
-
oldOnload.call(app,
|
|
8281
|
+
oldOnload.call(app, onLoadParam);
|
|
8132
8282
|
};
|
|
8133
8283
|
app.onLoadError = (...rests) => {
|
|
8134
8284
|
resolve();
|