@micro-zoe/micro-app 1.0.0-alpha.0 → 1.0.0-alpha.3
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 +13 -7
- package/lib/index.esm.js +806 -397
- 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 +65 -9
package/lib/index.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const version = '1.0.0-alpha.
|
|
1
|
+
const version = '1.0.0-alpha.3';
|
|
2
2
|
// do not use isUndefined
|
|
3
3
|
const isBrowser = typeof window !== 'undefined';
|
|
4
4
|
// do not use isUndefined
|
|
@@ -41,6 +41,10 @@ function isFunction(target) {
|
|
|
41
41
|
function isPlainObject(target) {
|
|
42
42
|
return toString.call(target) === '[object Object]';
|
|
43
43
|
}
|
|
44
|
+
// is Object
|
|
45
|
+
function isObject(target) {
|
|
46
|
+
return typeof target === 'object';
|
|
47
|
+
}
|
|
44
48
|
// is Promise
|
|
45
49
|
function isPromise(target) {
|
|
46
50
|
return toString.call(target) === '[object Promise]';
|
|
@@ -49,6 +53,18 @@ function isPromise(target) {
|
|
|
49
53
|
function isBoundFunction(target) {
|
|
50
54
|
return isFunction(target) && target.name.indexOf('bound ') === 0 && !target.hasOwnProperty('prototype');
|
|
51
55
|
}
|
|
56
|
+
// is constructor function
|
|
57
|
+
function isConstructor(target) {
|
|
58
|
+
var _a;
|
|
59
|
+
if (isFunction(target)) {
|
|
60
|
+
const targetStr = target.toString();
|
|
61
|
+
return (((_a = target.prototype) === null || _a === void 0 ? void 0 : _a.constructor) === target &&
|
|
62
|
+
Object.getOwnPropertyNames(target.prototype).length > 1) ||
|
|
63
|
+
/^function\s+[A-Z]/.test(targetStr) ||
|
|
64
|
+
/^class\s+/.test(targetStr);
|
|
65
|
+
}
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
52
68
|
// is ShadowRoot
|
|
53
69
|
function isShadowRoot(target) {
|
|
54
70
|
return typeof ShadowRoot !== 'undefined' && target instanceof ShadowRoot;
|
|
@@ -56,6 +72,10 @@ function isShadowRoot(target) {
|
|
|
56
72
|
function isURL(target) {
|
|
57
73
|
return target instanceof URL;
|
|
58
74
|
}
|
|
75
|
+
// is ProxyDocument
|
|
76
|
+
function isProxyDocument(target) {
|
|
77
|
+
return toString.call(target) === '[object ProxyDocument]';
|
|
78
|
+
}
|
|
59
79
|
/**
|
|
60
80
|
* format error log
|
|
61
81
|
* @param msg message
|
|
@@ -107,7 +127,7 @@ const createURL = (function () {
|
|
|
107
127
|
* @param url address
|
|
108
128
|
*/
|
|
109
129
|
function addProtocol(url) {
|
|
110
|
-
return url.startsWith('//') ? `${location.protocol}${url}` : url;
|
|
130
|
+
return url.startsWith('//') ? `${globalThis.location.protocol}${url}` : url;
|
|
111
131
|
}
|
|
112
132
|
/**
|
|
113
133
|
* format URL address
|
|
@@ -199,24 +219,15 @@ function promiseStream(promiseList, successCb, errorCb, finallyCb) {
|
|
|
199
219
|
promiseList.forEach((p, i) => {
|
|
200
220
|
if (isPromise(p)) {
|
|
201
221
|
p.then((res) => {
|
|
202
|
-
successCb({
|
|
203
|
-
data: res,
|
|
204
|
-
index: i,
|
|
205
|
-
});
|
|
222
|
+
successCb({ data: res, index: i });
|
|
206
223
|
isFinished();
|
|
207
224
|
}).catch((err) => {
|
|
208
|
-
errorCb({
|
|
209
|
-
error: err,
|
|
210
|
-
index: i,
|
|
211
|
-
});
|
|
225
|
+
errorCb({ error: err, index: i });
|
|
212
226
|
isFinished();
|
|
213
227
|
});
|
|
214
228
|
}
|
|
215
229
|
else {
|
|
216
|
-
successCb({
|
|
217
|
-
data: p,
|
|
218
|
-
index: i,
|
|
219
|
-
});
|
|
230
|
+
successCb({ data: p, index: i });
|
|
220
231
|
isFinished();
|
|
221
232
|
}
|
|
222
233
|
});
|
|
@@ -279,6 +290,7 @@ function pureCreateElement(tagName, options) {
|
|
|
279
290
|
const element = document.createElement(tagName, options);
|
|
280
291
|
if (element.__MICRO_APP_NAME__)
|
|
281
292
|
delete element.__MICRO_APP_NAME__;
|
|
293
|
+
element.__PURE_ELEMENT__ = true;
|
|
282
294
|
return element;
|
|
283
295
|
}
|
|
284
296
|
/**
|
|
@@ -457,7 +469,15 @@ var keepAliveStates;
|
|
|
457
469
|
keepAliveStates["KEEP_ALIVE_SHOW"] = "keep_alive_show";
|
|
458
470
|
keepAliveStates["KEEP_ALIVE_HIDDEN"] = "keep_alive_hidden";
|
|
459
471
|
})(keepAliveStates || (keepAliveStates = {}));
|
|
460
|
-
|
|
472
|
+
/**
|
|
473
|
+
* global key must be static key, they can not rewrite
|
|
474
|
+
* e.g.
|
|
475
|
+
* window.Promise = newValue
|
|
476
|
+
* new Promise ==> still get old value, not newValue, because they are cached by top function
|
|
477
|
+
* NOTE:
|
|
478
|
+
* 1. Do not add fetch, XMLHttpRequest, EventSource
|
|
479
|
+
*/
|
|
480
|
+
const globalKeyToBeCached = 'window,self,globalThis,Array,Object,String,Boolean,Math,Number,Symbol,Date,Function,Proxy,WeakMap,WeakSet,Set,Map,Reflect,Element,Node,Document,RegExp,Error,TypeError,JSON,isNaN,parseFloat,parseInt,performance,console,decodeURI,encodeURI,decodeURIComponent,encodeURIComponent,navigator,undefined,location,history';
|
|
461
481
|
|
|
462
482
|
/**
|
|
463
483
|
* fetch source of html, js, css
|
|
@@ -466,10 +486,18 @@ const globalKeyToBeCached = 'window,self,globalThis,Array,Object,String,Boolean,
|
|
|
466
486
|
* @param config fetch options
|
|
467
487
|
*/
|
|
468
488
|
function fetchSource(url, appName = null, options = {}) {
|
|
489
|
+
/**
|
|
490
|
+
* When child navigate to new async page, click event will scope dom to child and then fetch new source
|
|
491
|
+
* this may cause error when fetch rewrite by baseApp
|
|
492
|
+
* e.g.
|
|
493
|
+
* baseApp: <script crossorigin src="https://sgm-static.jd.com/sgm-2.8.0.js" name="SGMH5" sid="6f88a6e4ba4b4ae5acef2ec22c075085" appKey="jdb-adminb2b-pc"></script>
|
|
494
|
+
*/
|
|
495
|
+
removeDomScope();
|
|
469
496
|
if (isFunction(microApp.fetch)) {
|
|
470
497
|
return microApp.fetch(url, options, appName);
|
|
471
498
|
}
|
|
472
|
-
|
|
499
|
+
// Don’t use globalEnv.rawWindow.fetch, will cause sgm-2.8.0.js throw error in nest app
|
|
500
|
+
return window.fetch(url, options).then((res) => {
|
|
473
501
|
return res.text();
|
|
474
502
|
});
|
|
475
503
|
}
|
|
@@ -552,7 +580,7 @@ class CSSParser {
|
|
|
552
580
|
return true;
|
|
553
581
|
}
|
|
554
582
|
formatSelector(skip) {
|
|
555
|
-
const m = this.commonMatch(/^
|
|
583
|
+
const m = this.commonMatch(/^[^{]+/, skip);
|
|
556
584
|
if (!m)
|
|
557
585
|
return false;
|
|
558
586
|
return m[0].replace(/(^|,[\n\s]*)([^,]+)/g, (_, separator, selector) => {
|
|
@@ -632,7 +660,7 @@ class CSSParser {
|
|
|
632
660
|
keyframesRule() {
|
|
633
661
|
if (!this.commonMatch(/^@([-\w]+)?keyframes\s*/))
|
|
634
662
|
return false;
|
|
635
|
-
if (!this.commonMatch(/^
|
|
663
|
+
if (!this.commonMatch(/^[^{]+/))
|
|
636
664
|
return parseError('@keyframes missing name', this.linkPath);
|
|
637
665
|
this.matchComments();
|
|
638
666
|
if (!this.matchOpenBrace())
|
|
@@ -784,7 +812,7 @@ class CSSParser {
|
|
|
784
812
|
}
|
|
785
813
|
// splice string
|
|
786
814
|
recordResult(strFragment) {
|
|
787
|
-
// Firefox
|
|
815
|
+
// Firefox performance degradation when string contain special characters, see https://github.com/micro-zoe/micro-app/issues/256
|
|
788
816
|
if (isFireFox()) {
|
|
789
817
|
this.result += encodeURIComponent(strFragment);
|
|
790
818
|
}
|
|
@@ -1015,6 +1043,85 @@ function formatDynamicLink(url, info, app, originLink, replaceStyle) {
|
|
|
1015
1043
|
});
|
|
1016
1044
|
}
|
|
1017
1045
|
|
|
1046
|
+
class Adapter {
|
|
1047
|
+
constructor() {
|
|
1048
|
+
// keys that can only assigned to rawWindow
|
|
1049
|
+
this.escapeSetterKeyList = [
|
|
1050
|
+
'location',
|
|
1051
|
+
];
|
|
1052
|
+
// keys that can escape to rawWindow
|
|
1053
|
+
this.staticEscapeProperties = [
|
|
1054
|
+
'System',
|
|
1055
|
+
'__cjsWrapper',
|
|
1056
|
+
];
|
|
1057
|
+
// keys that scoped in child app
|
|
1058
|
+
this.staticScopeProperties = [
|
|
1059
|
+
'webpackJsonp',
|
|
1060
|
+
'webpackHotUpdate',
|
|
1061
|
+
'Vue',
|
|
1062
|
+
];
|
|
1063
|
+
this.injectReactHRMProperty();
|
|
1064
|
+
}
|
|
1065
|
+
// TODO: __DEV__ process.env.NODE_ENV !== 'production'
|
|
1066
|
+
// adapter for react
|
|
1067
|
+
injectReactHRMProperty() {
|
|
1068
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
1069
|
+
// react child in non-react env
|
|
1070
|
+
this.staticEscapeProperties.push('__REACT_ERROR_OVERLAY_GLOBAL_HOOK__');
|
|
1071
|
+
// in react parent
|
|
1072
|
+
if (globalEnv.rawWindow.__REACT_ERROR_OVERLAY_GLOBAL_HOOK__) {
|
|
1073
|
+
this.staticScopeProperties = this.staticScopeProperties.concat([
|
|
1074
|
+
'__REACT_ERROR_OVERLAY_GLOBAL_HOOK__',
|
|
1075
|
+
'__reactRefreshInjected',
|
|
1076
|
+
]);
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
// Fix conflict of babel-polyfill@6.x
|
|
1082
|
+
function fixBabelPolyfill6() {
|
|
1083
|
+
if (globalEnv.rawWindow._babelPolyfill)
|
|
1084
|
+
globalEnv.rawWindow._babelPolyfill = false;
|
|
1085
|
+
}
|
|
1086
|
+
/**
|
|
1087
|
+
* Fix error of hot reload when parent&child created by create-react-app in development environment
|
|
1088
|
+
* Issue: https://github.com/micro-zoe/micro-app/issues/382
|
|
1089
|
+
*/
|
|
1090
|
+
function fixReactHMRConflict(app) {
|
|
1091
|
+
var _a;
|
|
1092
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
1093
|
+
const rawReactErrorHook = globalEnv.rawWindow.__REACT_ERROR_OVERLAY_GLOBAL_HOOK__;
|
|
1094
|
+
const childReactErrorHook = (_a = app.sandBox) === null || _a === void 0 ? void 0 : _a.proxyWindow.__REACT_ERROR_OVERLAY_GLOBAL_HOOK__;
|
|
1095
|
+
if (rawReactErrorHook && childReactErrorHook) {
|
|
1096
|
+
globalEnv.rawWindow.__REACT_ERROR_OVERLAY_GLOBAL_HOOK__ = childReactErrorHook;
|
|
1097
|
+
defer(() => {
|
|
1098
|
+
globalEnv.rawWindow.__REACT_ERROR_OVERLAY_GLOBAL_HOOK__ = rawReactErrorHook;
|
|
1099
|
+
});
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
/**
|
|
1104
|
+
* reDefine parentNode of html
|
|
1105
|
+
* Scenes:
|
|
1106
|
+
* 1. element-ui popover.js
|
|
1107
|
+
* if (html.parentNode === document) ...
|
|
1108
|
+
*/
|
|
1109
|
+
function throttleDeferForParentNode(proxyDocument) {
|
|
1110
|
+
const html = globalEnv.rawDocument.firstElementChild;
|
|
1111
|
+
if (html && html.parentNode !== proxyDocument) {
|
|
1112
|
+
setRootParentNode(html, proxyDocument);
|
|
1113
|
+
defer(() => {
|
|
1114
|
+
setRootParentNode(html, globalEnv.rawDocument);
|
|
1115
|
+
});
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
function setRootParentNode(root, value) {
|
|
1119
|
+
Object.defineProperty(root, 'parentNode', {
|
|
1120
|
+
value,
|
|
1121
|
+
configurable: true,
|
|
1122
|
+
});
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1018
1125
|
// Record element and map element
|
|
1019
1126
|
const dynamicElementInMicroAppMap = new WeakMap();
|
|
1020
1127
|
/**
|
|
@@ -1108,6 +1215,12 @@ function invokePrototypeMethod(app, rawMethod, parent, targetChild, passiveChild
|
|
|
1108
1215
|
}
|
|
1109
1216
|
return targetChild;
|
|
1110
1217
|
}
|
|
1218
|
+
// TODO: __DEV__
|
|
1219
|
+
if (process.env.NODE_ENV !== 'production' &&
|
|
1220
|
+
targetChild instanceof HTMLIFrameElement &&
|
|
1221
|
+
rawMethod === globalEnv.rawAppendChild) {
|
|
1222
|
+
fixReactHMRConflict(app);
|
|
1223
|
+
}
|
|
1111
1224
|
return invokeRawMethod(rawMethod, hijackElement, targetChild, passiveChild);
|
|
1112
1225
|
}
|
|
1113
1226
|
return invokeRawMethod(rawMethod, parent, targetChild, passiveChild);
|
|
@@ -1145,20 +1258,35 @@ function getMappingNode(node) {
|
|
|
1145
1258
|
* @param rawMethod method
|
|
1146
1259
|
*/
|
|
1147
1260
|
function commonElementHandler(parent, newChild, passiveChild, rawMethod) {
|
|
1148
|
-
|
|
1261
|
+
const currentAppName = getCurrentAppName();
|
|
1262
|
+
if (newChild instanceof Node &&
|
|
1263
|
+
(newChild.__MICRO_APP_NAME__ ||
|
|
1264
|
+
(currentAppName && !newChild.__PURE_ELEMENT__))) {
|
|
1265
|
+
newChild.__MICRO_APP_NAME__ = newChild.__MICRO_APP_NAME__ || currentAppName;
|
|
1149
1266
|
const app = appInstanceMap.get(newChild.__MICRO_APP_NAME__);
|
|
1150
1267
|
if (app === null || app === void 0 ? void 0 : app.container) {
|
|
1268
|
+
if (newChild instanceof Element) {
|
|
1269
|
+
if (/^(img|script)$/i.test(newChild.tagName)) {
|
|
1270
|
+
if (newChild.hasAttribute('src')) {
|
|
1271
|
+
globalEnv.rawSetAttribute.call(newChild, 'src', CompletionPath(newChild.getAttribute('src'), app.url));
|
|
1272
|
+
}
|
|
1273
|
+
if (newChild.hasAttribute('srcset')) {
|
|
1274
|
+
globalEnv.rawSetAttribute.call(newChild, 'srcset', CompletionPath(newChild.getAttribute('srcset'), app.url));
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
else if (/^link$/i.test(newChild.tagName) && newChild.hasAttribute('href')) {
|
|
1278
|
+
globalEnv.rawSetAttribute.call(newChild, 'href', CompletionPath(newChild.getAttribute('href'), app.url));
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1151
1281
|
return invokePrototypeMethod(app, rawMethod, parent, handleNewNode(parent, newChild, app), passiveChild && getMappingNode(passiveChild));
|
|
1152
1282
|
}
|
|
1153
1283
|
else if (rawMethod === globalEnv.rawAppend || rawMethod === globalEnv.rawPrepend) {
|
|
1154
1284
|
return rawMethod.call(parent, newChild);
|
|
1155
1285
|
}
|
|
1156
|
-
return rawMethod.call(parent, newChild, passiveChild);
|
|
1157
1286
|
}
|
|
1158
1287
|
else if (rawMethod === globalEnv.rawAppend || rawMethod === globalEnv.rawPrepend) {
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
const app = appInstanceMap.get(appName);
|
|
1288
|
+
if (!(newChild instanceof Node) && currentAppName) {
|
|
1289
|
+
const app = appInstanceMap.get(currentAppName);
|
|
1162
1290
|
if (app === null || app === void 0 ? void 0 : app.container) {
|
|
1163
1291
|
if (parent === document.head) {
|
|
1164
1292
|
return rawMethod.call(app.container.querySelector('micro-app-head'), newChild);
|
|
@@ -1204,12 +1332,18 @@ function patchElementPrototypeMethods() {
|
|
|
1204
1332
|
};
|
|
1205
1333
|
// prototype methods of delete element👇
|
|
1206
1334
|
Element.prototype.removeChild = function removeChild(oldChild) {
|
|
1335
|
+
var _a;
|
|
1207
1336
|
if (oldChild === null || oldChild === void 0 ? void 0 : oldChild.__MICRO_APP_NAME__) {
|
|
1208
1337
|
const app = appInstanceMap.get(oldChild.__MICRO_APP_NAME__);
|
|
1209
1338
|
if (app === null || app === void 0 ? void 0 : app.container) {
|
|
1210
1339
|
return invokePrototypeMethod(app, globalEnv.rawRemoveChild, this, getMappingNode(oldChild));
|
|
1211
1340
|
}
|
|
1212
|
-
|
|
1341
|
+
try {
|
|
1342
|
+
return globalEnv.rawRemoveChild.call(this, oldChild);
|
|
1343
|
+
}
|
|
1344
|
+
catch (_b) {
|
|
1345
|
+
return (_a = oldChild === null || oldChild === void 0 ? void 0 : oldChild.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(oldChild);
|
|
1346
|
+
}
|
|
1213
1347
|
}
|
|
1214
1348
|
return globalEnv.rawRemoveChild.call(this, oldChild);
|
|
1215
1349
|
};
|
|
@@ -1225,109 +1359,120 @@ function patchElementPrototypeMethods() {
|
|
|
1225
1359
|
* @param element new element
|
|
1226
1360
|
*/
|
|
1227
1361
|
function markElement(element) {
|
|
1228
|
-
const
|
|
1229
|
-
if (
|
|
1230
|
-
element.__MICRO_APP_NAME__ =
|
|
1362
|
+
const currentAppName = getCurrentAppName();
|
|
1363
|
+
if (currentAppName)
|
|
1364
|
+
element.__MICRO_APP_NAME__ = currentAppName;
|
|
1231
1365
|
return element;
|
|
1232
1366
|
}
|
|
1233
1367
|
// methods of document
|
|
1234
1368
|
function patchDocument() {
|
|
1235
1369
|
const rawDocument = globalEnv.rawDocument;
|
|
1370
|
+
const rawRootDocument = globalEnv.rawRootDocument;
|
|
1371
|
+
function getBindTarget(target) {
|
|
1372
|
+
return isProxyDocument(target) ? rawDocument : target;
|
|
1373
|
+
}
|
|
1236
1374
|
// create element 👇
|
|
1237
|
-
|
|
1238
|
-
const element = globalEnv.rawCreateElement.call(this, tagName, options);
|
|
1375
|
+
rawRootDocument.prototype.createElement = function createElement(tagName, options) {
|
|
1376
|
+
const element = globalEnv.rawCreateElement.call(getBindTarget(this), tagName, options);
|
|
1239
1377
|
return markElement(element);
|
|
1240
1378
|
};
|
|
1241
|
-
|
|
1242
|
-
const element = globalEnv.rawCreateElementNS.call(this, namespaceURI, name, options);
|
|
1379
|
+
rawRootDocument.prototype.createElementNS = function createElementNS(namespaceURI, name, options) {
|
|
1380
|
+
const element = globalEnv.rawCreateElementNS.call(getBindTarget(this), namespaceURI, name, options);
|
|
1243
1381
|
return markElement(element);
|
|
1244
1382
|
};
|
|
1245
|
-
|
|
1246
|
-
const element = globalEnv.rawCreateDocumentFragment.call(this);
|
|
1383
|
+
rawRootDocument.prototype.createDocumentFragment = function createDocumentFragment() {
|
|
1384
|
+
const element = globalEnv.rawCreateDocumentFragment.call(getBindTarget(this));
|
|
1247
1385
|
return markElement(element);
|
|
1248
1386
|
};
|
|
1249
1387
|
// query element👇
|
|
1250
1388
|
function querySelector(selectors) {
|
|
1251
1389
|
var _a, _b, _c, _d;
|
|
1252
|
-
const
|
|
1253
|
-
|
|
1254
|
-
|
|
1390
|
+
const _this = getBindTarget(this);
|
|
1391
|
+
const currentAppName = getCurrentAppName();
|
|
1392
|
+
if (!currentAppName ||
|
|
1393
|
+
!((_a = appInstanceMap.get(currentAppName)) === null || _a === void 0 ? void 0 : _a.container) ||
|
|
1255
1394
|
!selectors ||
|
|
1256
1395
|
isUniqueElement(selectors) ||
|
|
1257
1396
|
// see https://github.com/micro-zoe/micro-app/issues/56
|
|
1258
|
-
rawDocument !==
|
|
1259
|
-
return globalEnv.rawQuerySelector.call(
|
|
1397
|
+
rawDocument !== _this) {
|
|
1398
|
+
return globalEnv.rawQuerySelector.call(_this, selectors);
|
|
1260
1399
|
}
|
|
1261
|
-
return (_d = (_c = (_b = appInstanceMap.get(
|
|
1400
|
+
return (_d = (_c = (_b = appInstanceMap.get(currentAppName)) === null || _b === void 0 ? void 0 : _b.container) === null || _c === void 0 ? void 0 : _c.querySelector(selectors)) !== null && _d !== void 0 ? _d : null;
|
|
1262
1401
|
}
|
|
1263
1402
|
function querySelectorAll(selectors) {
|
|
1264
1403
|
var _a, _b, _c, _d;
|
|
1265
|
-
const
|
|
1266
|
-
|
|
1267
|
-
|
|
1404
|
+
const _this = getBindTarget(this);
|
|
1405
|
+
const currentAppName = getCurrentAppName();
|
|
1406
|
+
if (!currentAppName ||
|
|
1407
|
+
!((_a = appInstanceMap.get(currentAppName)) === null || _a === void 0 ? void 0 : _a.container) ||
|
|
1268
1408
|
!selectors ||
|
|
1269
1409
|
isUniqueElement(selectors) ||
|
|
1270
|
-
rawDocument !==
|
|
1271
|
-
return globalEnv.rawQuerySelectorAll.call(
|
|
1410
|
+
rawDocument !== _this) {
|
|
1411
|
+
return globalEnv.rawQuerySelectorAll.call(_this, selectors);
|
|
1272
1412
|
}
|
|
1273
|
-
return (_d = (_c = (_b = appInstanceMap.get(
|
|
1413
|
+
return (_d = (_c = (_b = appInstanceMap.get(currentAppName)) === null || _b === void 0 ? void 0 : _b.container) === null || _c === void 0 ? void 0 : _c.querySelectorAll(selectors)) !== null && _d !== void 0 ? _d : [];
|
|
1274
1414
|
}
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1415
|
+
rawRootDocument.prototype.querySelector = querySelector;
|
|
1416
|
+
rawRootDocument.prototype.querySelectorAll = querySelectorAll;
|
|
1417
|
+
rawRootDocument.prototype.getElementById = function getElementById(key) {
|
|
1418
|
+
const _this = getBindTarget(this);
|
|
1278
1419
|
if (!getCurrentAppName() || isInvalidQuerySelectorKey(key)) {
|
|
1279
|
-
return globalEnv.rawGetElementById.call(
|
|
1420
|
+
return globalEnv.rawGetElementById.call(_this, key);
|
|
1280
1421
|
}
|
|
1281
1422
|
try {
|
|
1282
|
-
return querySelector.call(
|
|
1423
|
+
return querySelector.call(_this, `#${key}`);
|
|
1283
1424
|
}
|
|
1284
1425
|
catch (_a) {
|
|
1285
|
-
return globalEnv.rawGetElementById.call(
|
|
1426
|
+
return globalEnv.rawGetElementById.call(_this, key);
|
|
1286
1427
|
}
|
|
1287
1428
|
};
|
|
1288
|
-
|
|
1429
|
+
rawRootDocument.prototype.getElementsByClassName = function getElementsByClassName(key) {
|
|
1430
|
+
const _this = getBindTarget(this);
|
|
1289
1431
|
if (!getCurrentAppName() || isInvalidQuerySelectorKey(key)) {
|
|
1290
|
-
return globalEnv.rawGetElementsByClassName.call(
|
|
1432
|
+
return globalEnv.rawGetElementsByClassName.call(_this, key);
|
|
1291
1433
|
}
|
|
1292
1434
|
try {
|
|
1293
|
-
return querySelectorAll.call(
|
|
1435
|
+
return querySelectorAll.call(_this, `.${key}`);
|
|
1294
1436
|
}
|
|
1295
1437
|
catch (_a) {
|
|
1296
|
-
return globalEnv.rawGetElementsByClassName.call(
|
|
1438
|
+
return globalEnv.rawGetElementsByClassName.call(_this, key);
|
|
1297
1439
|
}
|
|
1298
1440
|
};
|
|
1299
|
-
|
|
1441
|
+
rawRootDocument.prototype.getElementsByTagName = function getElementsByTagName(key) {
|
|
1300
1442
|
var _a;
|
|
1301
|
-
const
|
|
1302
|
-
|
|
1443
|
+
const _this = getBindTarget(this);
|
|
1444
|
+
const currentAppName = getCurrentAppName();
|
|
1445
|
+
if (!currentAppName ||
|
|
1303
1446
|
isUniqueElement(key) ||
|
|
1304
1447
|
isInvalidQuerySelectorKey(key) ||
|
|
1305
|
-
(!((_a = appInstanceMap.get(
|
|
1306
|
-
return globalEnv.rawGetElementsByTagName.call(
|
|
1448
|
+
(!((_a = appInstanceMap.get(currentAppName)) === null || _a === void 0 ? void 0 : _a.inline) && /^script$/i.test(key))) {
|
|
1449
|
+
return globalEnv.rawGetElementsByTagName.call(_this, key);
|
|
1307
1450
|
}
|
|
1308
1451
|
try {
|
|
1309
|
-
return querySelectorAll.call(
|
|
1452
|
+
return querySelectorAll.call(_this, key);
|
|
1310
1453
|
}
|
|
1311
1454
|
catch (_b) {
|
|
1312
|
-
return globalEnv.rawGetElementsByTagName.call(
|
|
1455
|
+
return globalEnv.rawGetElementsByTagName.call(_this, key);
|
|
1313
1456
|
}
|
|
1314
1457
|
};
|
|
1315
|
-
|
|
1458
|
+
rawRootDocument.prototype.getElementsByName = function getElementsByName(key) {
|
|
1459
|
+
const _this = getBindTarget(this);
|
|
1316
1460
|
if (!getCurrentAppName() || isInvalidQuerySelectorKey(key)) {
|
|
1317
|
-
return globalEnv.rawGetElementsByName.call(
|
|
1461
|
+
return globalEnv.rawGetElementsByName.call(_this, key);
|
|
1318
1462
|
}
|
|
1319
1463
|
try {
|
|
1320
|
-
return querySelectorAll.call(
|
|
1464
|
+
return querySelectorAll.call(_this, `[name=${key}]`);
|
|
1321
1465
|
}
|
|
1322
1466
|
catch (_a) {
|
|
1323
|
-
return globalEnv.rawGetElementsByName.call(
|
|
1467
|
+
return globalEnv.rawGetElementsByName.call(_this, key);
|
|
1324
1468
|
}
|
|
1325
1469
|
};
|
|
1326
1470
|
}
|
|
1327
1471
|
/**
|
|
1328
1472
|
* patchSetAttribute is different from other patch
|
|
1329
|
-
*
|
|
1330
|
-
* it
|
|
1473
|
+
* NOTE:
|
|
1474
|
+
* 1. it not dependent on sandbox
|
|
1475
|
+
* 2. it should exec when first micro-app-element created & release when all app unmounted
|
|
1331
1476
|
*/
|
|
1332
1477
|
let hasRewriteSetAttribute = false;
|
|
1333
1478
|
function patchSetAttribute() {
|
|
@@ -1338,9 +1483,9 @@ function patchSetAttribute() {
|
|
|
1338
1483
|
if (/^micro-app(-\S+)?/i.test(this.tagName) && key === 'data') {
|
|
1339
1484
|
if (isPlainObject(value)) {
|
|
1340
1485
|
const cloneValue = {};
|
|
1341
|
-
Object.getOwnPropertyNames(value).forEach((
|
|
1342
|
-
if (!(isString(
|
|
1343
|
-
cloneValue[
|
|
1486
|
+
Object.getOwnPropertyNames(value).forEach((ownKey) => {
|
|
1487
|
+
if (!(isString(ownKey) && ownKey.indexOf('__') === 0)) {
|
|
1488
|
+
cloneValue[ownKey] = value[ownKey];
|
|
1344
1489
|
}
|
|
1345
1490
|
});
|
|
1346
1491
|
this.data = cloneValue;
|
|
@@ -1349,36 +1494,34 @@ function patchSetAttribute() {
|
|
|
1349
1494
|
logWarn('property data must be an object', this.getAttribute('name'));
|
|
1350
1495
|
}
|
|
1351
1496
|
}
|
|
1352
|
-
else if ((((key === 'src' || key === 'srcset') && /^(img|script)$/i.test(this.tagName)) ||
|
|
1353
|
-
(key === 'href' && /^link$/i.test(this.tagName))) &&
|
|
1354
|
-
this.__MICRO_APP_NAME__ &&
|
|
1355
|
-
appInstanceMap.has(this.__MICRO_APP_NAME__)) {
|
|
1356
|
-
const app = appInstanceMap.get(this.__MICRO_APP_NAME__);
|
|
1357
|
-
globalEnv.rawSetAttribute.call(this, key, CompletionPath(value, app.url));
|
|
1358
|
-
}
|
|
1359
1497
|
else {
|
|
1498
|
+
const appName = this.__MICRO_APP_NAME__ || getCurrentAppName();
|
|
1499
|
+
if (appName &&
|
|
1500
|
+
appInstanceMap.has(appName) &&
|
|
1501
|
+
(((key === 'src' || key === 'srcset') && /^(img|script)$/i.test(this.tagName)) ||
|
|
1502
|
+
(key === 'href' && /^link$/i.test(this.tagName)))) {
|
|
1503
|
+
const app = appInstanceMap.get(appName);
|
|
1504
|
+
value = CompletionPath(value, app.url);
|
|
1505
|
+
}
|
|
1360
1506
|
globalEnv.rawSetAttribute.call(this, key, value);
|
|
1361
1507
|
}
|
|
1362
1508
|
};
|
|
1363
1509
|
}
|
|
1364
|
-
function releasePatchSetAttribute() {
|
|
1365
|
-
hasRewriteSetAttribute = false;
|
|
1366
|
-
Element.prototype.setAttribute = globalEnv.rawSetAttribute;
|
|
1367
|
-
}
|
|
1368
1510
|
function releasePatchDocument() {
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1511
|
+
const rawRootDocument = globalEnv.rawRootDocument;
|
|
1512
|
+
rawRootDocument.prototype.createElement = globalEnv.rawCreateElement;
|
|
1513
|
+
rawRootDocument.prototype.createElementNS = globalEnv.rawCreateElementNS;
|
|
1514
|
+
rawRootDocument.prototype.createDocumentFragment = globalEnv.rawCreateDocumentFragment;
|
|
1515
|
+
rawRootDocument.prototype.querySelector = globalEnv.rawQuerySelector;
|
|
1516
|
+
rawRootDocument.prototype.querySelectorAll = globalEnv.rawQuerySelectorAll;
|
|
1517
|
+
rawRootDocument.prototype.getElementById = globalEnv.rawGetElementById;
|
|
1518
|
+
rawRootDocument.prototype.getElementsByClassName = globalEnv.rawGetElementsByClassName;
|
|
1519
|
+
rawRootDocument.prototype.getElementsByTagName = globalEnv.rawGetElementsByTagName;
|
|
1520
|
+
rawRootDocument.prototype.getElementsByName = globalEnv.rawGetElementsByName;
|
|
1378
1521
|
}
|
|
1379
1522
|
// release patch
|
|
1380
1523
|
function releasePatches() {
|
|
1381
|
-
|
|
1524
|
+
removeDomScope();
|
|
1382
1525
|
releasePatchDocument();
|
|
1383
1526
|
Element.prototype.appendChild = globalEnv.rawAppendChild;
|
|
1384
1527
|
Element.prototype.insertBefore = globalEnv.rawInsertBefore;
|
|
@@ -1388,6 +1531,11 @@ function releasePatches() {
|
|
|
1388
1531
|
Element.prototype.prepend = globalEnv.rawPrepend;
|
|
1389
1532
|
Element.prototype.cloneNode = globalEnv.rawCloneNode;
|
|
1390
1533
|
}
|
|
1534
|
+
// exec when last child unmount
|
|
1535
|
+
function releasePatchSetAttribute() {
|
|
1536
|
+
hasRewriteSetAttribute = false;
|
|
1537
|
+
Element.prototype.setAttribute = globalEnv.rawSetAttribute;
|
|
1538
|
+
}
|
|
1391
1539
|
// Set the style of micro-app-head and micro-app-body
|
|
1392
1540
|
let hasRejectMicroAppStyle = false;
|
|
1393
1541
|
function rejectMicroAppStyle() {
|
|
@@ -1407,6 +1555,10 @@ const globalEnv = {};
|
|
|
1407
1555
|
*/
|
|
1408
1556
|
function initGlobalEnv() {
|
|
1409
1557
|
if (isBrowser) {
|
|
1558
|
+
const rawWindow = Function('return window')();
|
|
1559
|
+
const rawDocument = Function('return document')();
|
|
1560
|
+
const rawRootDocument = Function('return Document')();
|
|
1561
|
+
const supportModuleScript = isSupportModuleScript();
|
|
1410
1562
|
/**
|
|
1411
1563
|
* save patch raw methods
|
|
1412
1564
|
* pay attention to this binding
|
|
@@ -1419,15 +1571,15 @@ function initGlobalEnv() {
|
|
|
1419
1571
|
const rawAppend = Element.prototype.append;
|
|
1420
1572
|
const rawPrepend = Element.prototype.prepend;
|
|
1421
1573
|
const rawCloneNode = Element.prototype.cloneNode;
|
|
1422
|
-
const rawCreateElement =
|
|
1423
|
-
const rawCreateElementNS =
|
|
1424
|
-
const rawCreateDocumentFragment =
|
|
1425
|
-
const rawQuerySelector =
|
|
1426
|
-
const rawQuerySelectorAll =
|
|
1427
|
-
const rawGetElementById =
|
|
1428
|
-
const rawGetElementsByClassName =
|
|
1429
|
-
const rawGetElementsByTagName =
|
|
1430
|
-
const rawGetElementsByName =
|
|
1574
|
+
const rawCreateElement = rawRootDocument.prototype.createElement;
|
|
1575
|
+
const rawCreateElementNS = rawRootDocument.prototype.createElementNS;
|
|
1576
|
+
const rawCreateDocumentFragment = rawRootDocument.prototype.createDocumentFragment;
|
|
1577
|
+
const rawQuerySelector = rawRootDocument.prototype.querySelector;
|
|
1578
|
+
const rawQuerySelectorAll = rawRootDocument.prototype.querySelectorAll;
|
|
1579
|
+
const rawGetElementById = rawRootDocument.prototype.getElementById;
|
|
1580
|
+
const rawGetElementsByClassName = rawRootDocument.prototype.getElementsByClassName;
|
|
1581
|
+
const rawGetElementsByTagName = rawRootDocument.prototype.getElementsByTagName;
|
|
1582
|
+
const rawGetElementsByName = rawRootDocument.prototype.getElementsByName;
|
|
1431
1583
|
const ImageProxy = new Proxy(Image, {
|
|
1432
1584
|
construct(Target, args) {
|
|
1433
1585
|
const elementImage = new Target(...args);
|
|
@@ -1435,9 +1587,6 @@ function initGlobalEnv() {
|
|
|
1435
1587
|
return elementImage;
|
|
1436
1588
|
},
|
|
1437
1589
|
});
|
|
1438
|
-
const rawWindow = Function('return window')();
|
|
1439
|
-
const rawDocument = Function('return document')();
|
|
1440
|
-
const supportModuleScript = isSupportModuleScript();
|
|
1441
1590
|
/**
|
|
1442
1591
|
* save effect raw methods
|
|
1443
1592
|
* pay attention to this binding, especially setInterval, setTimeout, clearInterval, clearTimeout
|
|
@@ -1448,11 +1597,18 @@ function initGlobalEnv() {
|
|
|
1448
1597
|
const rawSetTimeout = rawWindow.setTimeout;
|
|
1449
1598
|
const rawClearInterval = rawWindow.clearInterval;
|
|
1450
1599
|
const rawClearTimeout = rawWindow.clearTimeout;
|
|
1600
|
+
const rawPushState = rawWindow.history.pushState;
|
|
1601
|
+
const rawReplaceState = rawWindow.history.replaceState;
|
|
1451
1602
|
const rawDocumentAddEventListener = rawDocument.addEventListener;
|
|
1452
1603
|
const rawDocumentRemoveEventListener = rawDocument.removeEventListener;
|
|
1453
1604
|
// mark current application as base application
|
|
1454
1605
|
window.__MICRO_APP_BASE_APPLICATION__ = true;
|
|
1455
1606
|
assign(globalEnv, {
|
|
1607
|
+
// common global vars
|
|
1608
|
+
rawWindow,
|
|
1609
|
+
rawDocument,
|
|
1610
|
+
rawRootDocument,
|
|
1611
|
+
supportModuleScript,
|
|
1456
1612
|
// source/patch
|
|
1457
1613
|
rawSetAttribute,
|
|
1458
1614
|
rawAppendChild,
|
|
@@ -1472,10 +1628,6 @@ function initGlobalEnv() {
|
|
|
1472
1628
|
rawGetElementsByTagName,
|
|
1473
1629
|
rawGetElementsByName,
|
|
1474
1630
|
ImageProxy,
|
|
1475
|
-
// common global vars
|
|
1476
|
-
rawWindow,
|
|
1477
|
-
rawDocument,
|
|
1478
|
-
supportModuleScript,
|
|
1479
1631
|
// sandbox/effect
|
|
1480
1632
|
rawWindowAddEventListener,
|
|
1481
1633
|
rawWindowRemoveEventListener,
|
|
@@ -1485,6 +1637,8 @@ function initGlobalEnv() {
|
|
|
1485
1637
|
rawClearTimeout,
|
|
1486
1638
|
rawDocumentAddEventListener,
|
|
1487
1639
|
rawDocumentRemoveEventListener,
|
|
1640
|
+
rawPushState,
|
|
1641
|
+
rawReplaceState,
|
|
1488
1642
|
});
|
|
1489
1643
|
// global effect
|
|
1490
1644
|
rejectMicroAppStyle();
|
|
@@ -1705,6 +1859,13 @@ function runDynamicRemoteScript(url, info, app, originScript) {
|
|
|
1705
1859
|
if (app.source.scripts.has(url)) {
|
|
1706
1860
|
const existInfo = app.source.scripts.get(url);
|
|
1707
1861
|
!existInfo.module && defer(dispatchScriptOnLoadEvent);
|
|
1862
|
+
/**
|
|
1863
|
+
* TODO: 这里要改,当script初始化时动态创建远程script时,初次渲染和二次渲染的顺序不一致,会导致错误
|
|
1864
|
+
* 1、url不存在缓存,初始化的时候肯定是要异步请求,那么执行顺序就会靠后,至少落后于html自带的script
|
|
1865
|
+
* 2、url存在缓存,那么二次渲染的时候这里会同步执行,就会先于html自带的script执行
|
|
1866
|
+
* 3、测试一下,初次渲染和二次渲染时,onload的执行时机,是在js执行完成,还是执行之前
|
|
1867
|
+
* 4、将上述问题做成注释,方便后续阅读和理解
|
|
1868
|
+
*/
|
|
1708
1869
|
return runScript(url, app, existInfo, true, dispatchScriptOnLoadEvent);
|
|
1709
1870
|
}
|
|
1710
1871
|
if (globalScripts.has(url)) {
|
|
@@ -2223,7 +2384,7 @@ function releaseUnmountOfNestedApp() {
|
|
|
2223
2384
|
}
|
|
2224
2385
|
// if micro-app run in micro application, delete all next generation application when unmount event received
|
|
2225
2386
|
// unmount event will auto release by sandbox
|
|
2226
|
-
function
|
|
2387
|
+
function initEnvOfNestedApp() {
|
|
2227
2388
|
if (window.__MICRO_APP_ENVIRONMENT__) {
|
|
2228
2389
|
releaseUnmountOfNestedApp();
|
|
2229
2390
|
window.addEventListener('unmount', unmountNestedApp, false);
|
|
@@ -2236,35 +2397,30 @@ function isBoundedFunction(value) {
|
|
|
2236
2397
|
return value.__MICRO_APP_IS_BOUND_FUNCTION__;
|
|
2237
2398
|
return value.__MICRO_APP_IS_BOUND_FUNCTION__ = isBoundFunction(value);
|
|
2238
2399
|
}
|
|
2239
|
-
function
|
|
2240
|
-
var _a;
|
|
2400
|
+
function isConstructorFunction(value) {
|
|
2241
2401
|
if (isBoolean(value.__MICRO_APP_IS_CONSTRUCTOR__))
|
|
2242
2402
|
return value.__MICRO_APP_IS_CONSTRUCTOR__;
|
|
2243
|
-
|
|
2244
|
-
const result = (((_a = value.prototype) === null || _a === void 0 ? void 0 : _a.constructor) === value &&
|
|
2245
|
-
Object.getOwnPropertyNames(value.prototype).length > 1) ||
|
|
2246
|
-
/^function\s+[A-Z]/.test(valueStr) ||
|
|
2247
|
-
/^class\s+/.test(valueStr);
|
|
2248
|
-
return value.__MICRO_APP_IS_CONSTRUCTOR__ = result;
|
|
2403
|
+
return value.__MICRO_APP_IS_CONSTRUCTOR__ = isConstructor(value);
|
|
2249
2404
|
}
|
|
2250
2405
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
2251
|
-
function
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2406
|
+
function bindFunctionToRawObject(rawObject, value, key = 'WINDOW') {
|
|
2407
|
+
const cacheKey = `__MICRO_APP_BOUND_${key}_FUNCTION__`;
|
|
2408
|
+
if (value[cacheKey])
|
|
2409
|
+
return value[cacheKey];
|
|
2410
|
+
if (!isConstructorFunction(value) && !isBoundedFunction(value)) {
|
|
2411
|
+
const bindRawObjectValue = value.bind(rawObject);
|
|
2256
2412
|
for (const key in value) {
|
|
2257
|
-
|
|
2413
|
+
bindRawObjectValue[key] = value[key];
|
|
2258
2414
|
}
|
|
2259
2415
|
if (value.hasOwnProperty('prototype')) {
|
|
2260
|
-
rawDefineProperty(
|
|
2416
|
+
rawDefineProperty(bindRawObjectValue, 'prototype', {
|
|
2261
2417
|
value: value.prototype,
|
|
2262
2418
|
configurable: true,
|
|
2263
2419
|
enumerable: false,
|
|
2264
2420
|
writable: true,
|
|
2265
2421
|
});
|
|
2266
2422
|
}
|
|
2267
|
-
return value
|
|
2423
|
+
return value[cacheKey] = bindRawObjectValue;
|
|
2268
2424
|
}
|
|
2269
2425
|
return value;
|
|
2270
2426
|
}
|
|
@@ -2381,8 +2537,7 @@ function releaseEffectDocumentEvent() {
|
|
|
2381
2537
|
* Rewrite side-effect events
|
|
2382
2538
|
* @param microAppWindow micro window
|
|
2383
2539
|
*/
|
|
2384
|
-
function effect(microAppWindow) {
|
|
2385
|
-
const appName = microAppWindow.__MICRO_APP_NAME__;
|
|
2540
|
+
function effect(appName, microAppWindow) {
|
|
2386
2541
|
const eventListenerMap = new Map();
|
|
2387
2542
|
const intervalIdMap = new Map();
|
|
2388
2543
|
const timeoutIdMap = new Map();
|
|
@@ -2529,7 +2684,8 @@ function effect(microAppWindow) {
|
|
|
2529
2684
|
}
|
|
2530
2685
|
|
|
2531
2686
|
// set micro app state to origin state
|
|
2532
|
-
function setMicroState(appName,
|
|
2687
|
+
function setMicroState(appName, microState) {
|
|
2688
|
+
const rawState = globalEnv.rawWindow.history.state;
|
|
2533
2689
|
const additionalState = {
|
|
2534
2690
|
microAppState: assign({}, rawState === null || rawState === void 0 ? void 0 : rawState.microAppState, {
|
|
2535
2691
|
[appName]: microState
|
|
@@ -2552,9 +2708,9 @@ function removeMicroState(appName, rawState) {
|
|
|
2552
2708
|
return assign({}, rawState);
|
|
2553
2709
|
}
|
|
2554
2710
|
// get micro app state form origin state
|
|
2555
|
-
function getMicroState(appName
|
|
2556
|
-
var _a;
|
|
2557
|
-
return ((_a = state === null ||
|
|
2711
|
+
function getMicroState(appName) {
|
|
2712
|
+
var _a, _b;
|
|
2713
|
+
return ((_b = (_a = globalEnv.rawWindow.history.state) === null || _a === void 0 ? void 0 : _a.microAppState) === null || _b === void 0 ? void 0 : _b[appName]) || null;
|
|
2558
2714
|
}
|
|
2559
2715
|
const ENC_AD_RE = /&/g; // %M1
|
|
2560
2716
|
const ENC_EQ_RE = /=/g; // %M2
|
|
@@ -2579,7 +2735,8 @@ function commonDecode(path) {
|
|
|
2579
2735
|
}
|
|
2580
2736
|
// 格式化query参数key,防止与原有参数的冲突
|
|
2581
2737
|
function formatQueryAppName(appName) {
|
|
2582
|
-
return `app-${appName}
|
|
2738
|
+
// return `app-${appName}`
|
|
2739
|
+
return appName;
|
|
2583
2740
|
}
|
|
2584
2741
|
// 根据浏览器url参数,获取当前子应用的path
|
|
2585
2742
|
function getMicroPathFromURL(appName) {
|
|
@@ -2684,7 +2841,10 @@ function addHistoryListener(appName) {
|
|
|
2684
2841
|
const rawWindow = globalEnv.rawWindow;
|
|
2685
2842
|
// handle popstate event and distribute to child app
|
|
2686
2843
|
const popStateHandler = (e) => {
|
|
2687
|
-
|
|
2844
|
+
/**
|
|
2845
|
+
* 1. unmount app & hidden keep-alive app will not receive popstate event
|
|
2846
|
+
* 2. filter out onlyForBrowser
|
|
2847
|
+
*/
|
|
2688
2848
|
if (getActiveApps(true).includes(appName) && !e.onlyForBrowser) {
|
|
2689
2849
|
const microPath = getMicroPathFromURL(appName);
|
|
2690
2850
|
const app = appInstanceMap.get(appName);
|
|
@@ -2699,7 +2859,7 @@ function addHistoryListener(appName) {
|
|
|
2699
2859
|
isHashChange = proxyWindow.location.hash !== oldHash;
|
|
2700
2860
|
}
|
|
2701
2861
|
// dispatch formatted popStateEvent to child
|
|
2702
|
-
dispatchPopStateEventToMicroApp(appName, proxyWindow
|
|
2862
|
+
dispatchPopStateEventToMicroApp(appName, proxyWindow);
|
|
2703
2863
|
// dispatch formatted hashChangeEvent to child when hash change
|
|
2704
2864
|
if (isHashChange)
|
|
2705
2865
|
dispatchHashChangeEventToMicroApp(appName, proxyWindow, oldHref);
|
|
@@ -2718,9 +2878,9 @@ function addHistoryListener(appName) {
|
|
|
2718
2878
|
* @param proxyWindow sandbox window
|
|
2719
2879
|
* @param eventState history.state
|
|
2720
2880
|
*/
|
|
2721
|
-
function dispatchPopStateEventToMicroApp(appName, proxyWindow
|
|
2881
|
+
function dispatchPopStateEventToMicroApp(appName, proxyWindow) {
|
|
2722
2882
|
// create PopStateEvent named popstate-appName with sub app state
|
|
2723
|
-
const newPopStateEvent = new PopStateEvent(formatEventName$1('popstate', appName), { state: getMicroState(appName
|
|
2883
|
+
const newPopStateEvent = new PopStateEvent(formatEventName$1('popstate', appName), { state: getMicroState(appName) });
|
|
2724
2884
|
globalEnv.rawWindow.dispatchEvent(newPopStateEvent);
|
|
2725
2885
|
// call function window.onpopstate if it exists
|
|
2726
2886
|
typeof proxyWindow.onpopstate === 'function' && proxyWindow.onpopstate(newPopStateEvent);
|
|
@@ -2785,37 +2945,35 @@ function createMicroHistory(appName, microLocation) {
|
|
|
2785
2945
|
const rawHistory = globalEnv.rawWindow.history;
|
|
2786
2946
|
function getMicroHistoryMethod(methodName) {
|
|
2787
2947
|
return function (...rests) {
|
|
2788
|
-
if ((
|
|
2789
|
-
(isString(rests[2]) || isURL(rests[2]))) {
|
|
2948
|
+
if (isString(rests[2]) || isURL(rests[2])) {
|
|
2790
2949
|
const targetLocation = createURL(rests[2], microLocation.href);
|
|
2791
2950
|
if (targetLocation.origin === microLocation.origin) {
|
|
2792
|
-
navigateWithNativeEvent(methodName, setMicroPathToURL(appName, targetLocation), true, setMicroState(appName,
|
|
2951
|
+
navigateWithNativeEvent(methodName, setMicroPathToURL(appName, targetLocation), true, setMicroState(appName, rests[0]), rests[1]);
|
|
2793
2952
|
const targetFullPath = targetLocation.pathname + targetLocation.search + targetLocation.hash;
|
|
2794
2953
|
if (targetFullPath !== microLocation.fullPath) {
|
|
2795
2954
|
updateMicroLocation(appName, targetFullPath, microLocation);
|
|
2796
2955
|
}
|
|
2797
|
-
|
|
2798
|
-
else {
|
|
2799
|
-
rawHistory[methodName].apply(rawHistory, rests);
|
|
2956
|
+
return void 0;
|
|
2800
2957
|
}
|
|
2801
2958
|
}
|
|
2802
|
-
|
|
2803
|
-
rawHistory[methodName].apply(rawHistory, rests);
|
|
2804
|
-
}
|
|
2959
|
+
nativeHistoryNavigate(methodName, rests[2], rests[0], rests[1]);
|
|
2805
2960
|
};
|
|
2806
2961
|
}
|
|
2962
|
+
const pushState = getMicroHistoryMethod('pushState');
|
|
2963
|
+
const replaceState = getMicroHistoryMethod('replaceState');
|
|
2807
2964
|
return new Proxy(rawHistory, {
|
|
2808
2965
|
get(target, key) {
|
|
2809
2966
|
if (key === 'state') {
|
|
2810
|
-
return getMicroState(appName
|
|
2967
|
+
return getMicroState(appName);
|
|
2811
2968
|
}
|
|
2812
|
-
else if (
|
|
2813
|
-
return
|
|
2969
|
+
else if (key === 'pushState') {
|
|
2970
|
+
return pushState;
|
|
2814
2971
|
}
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2972
|
+
else if (key === 'replaceState') {
|
|
2973
|
+
return replaceState;
|
|
2974
|
+
}
|
|
2975
|
+
const rawValue = Reflect.get(target, key);
|
|
2976
|
+
return isFunction(rawValue) ? bindFunctionToRawObject(target, rawValue, 'HISTORY') : rawValue;
|
|
2819
2977
|
}
|
|
2820
2978
|
});
|
|
2821
2979
|
}
|
|
@@ -2827,12 +2985,13 @@ function createMicroHistory(appName, microLocation) {
|
|
|
2827
2985
|
* @param title history.title, default is ''
|
|
2828
2986
|
*/
|
|
2829
2987
|
function nativeHistoryNavigate(methodName, fullPath, state = null, title = '') {
|
|
2830
|
-
globalEnv.
|
|
2988
|
+
const method = methodName === 'pushState' ? globalEnv.rawPushState : globalEnv.rawReplaceState;
|
|
2989
|
+
method.call(globalEnv.rawWindow.history, state, title, fullPath);
|
|
2831
2990
|
}
|
|
2832
2991
|
/**
|
|
2833
2992
|
* Navigate to new path, and dispatch native popStateEvent/hashChangeEvent to browser
|
|
2834
2993
|
* Use scenes:
|
|
2835
|
-
* 1. mount/unmount through
|
|
2994
|
+
* 1. mount/unmount through attachRouteToBrowserURL with limited popstateEvent
|
|
2836
2995
|
* 2. proxyHistory.pushState/replaceState with limited popstateEvent
|
|
2837
2996
|
* 3. api microApp.router.push/replace
|
|
2838
2997
|
* 4. proxyLocation.hash = xxx
|
|
@@ -2852,19 +3011,20 @@ function navigateWithNativeEvent(methodName, result, onlyForBrowser, state, titl
|
|
|
2852
3011
|
dispatchNativeEvent(onlyForBrowser, oldHref);
|
|
2853
3012
|
}
|
|
2854
3013
|
/**
|
|
2855
|
-
* update browser url when mount/unmount/hidden/show
|
|
3014
|
+
* update browser url when mount/unmount/hidden/show/attachToURL/attachAllToURL
|
|
3015
|
+
* just attach microRoute info to browser, dispatch event to base app(exclude child)
|
|
2856
3016
|
* @param result result of add/remove microApp path on browser url
|
|
2857
3017
|
* @param state history.state
|
|
2858
3018
|
*/
|
|
2859
|
-
function
|
|
3019
|
+
function attachRouteToBrowserURL(result, state) {
|
|
2860
3020
|
navigateWithNativeEvent('replaceState', result, true, state);
|
|
2861
3021
|
}
|
|
2862
3022
|
/**
|
|
2863
3023
|
* When path is same, keep the microAppState in history.state
|
|
2864
|
-
* Fix bug of missing microAppState
|
|
3024
|
+
* Fix bug of missing microAppState when base app is next.js or angular
|
|
2865
3025
|
* @param method history.pushState/replaceState
|
|
2866
3026
|
*/
|
|
2867
|
-
function
|
|
3027
|
+
function reWriteHistoryMethod(method) {
|
|
2868
3028
|
const rawWindow = globalEnv.rawWindow;
|
|
2869
3029
|
return function (...rests) {
|
|
2870
3030
|
var _a;
|
|
@@ -2880,22 +3040,38 @@ function patchHistoryState(method) {
|
|
|
2880
3040
|
}
|
|
2881
3041
|
}
|
|
2882
3042
|
method.apply(rawWindow.history, rests);
|
|
3043
|
+
/**
|
|
3044
|
+
* Attach child router info to browser url when base app navigate with pushState/replaceState
|
|
3045
|
+
* NOTE:
|
|
3046
|
+
* 1. Exec after apply pushState/replaceState
|
|
3047
|
+
* 2. Unable to catch when base app navigate with location
|
|
3048
|
+
* 3. When in nest app, rawPushState/rawReplaceState has been modified by parent
|
|
3049
|
+
* 4.
|
|
3050
|
+
*/
|
|
3051
|
+
getActiveApps(true).forEach(appName => {
|
|
3052
|
+
const app = appInstanceMap.get(appName);
|
|
3053
|
+
if (app.sandBox && app.useMemoryRouter && !getMicroPathFromURL(appName)) {
|
|
3054
|
+
attachRouteToBrowserURL(setMicroPathToURL(appName, app.sandBox.proxyWindow.location), setMicroState(appName, getMicroState(appName)));
|
|
3055
|
+
}
|
|
3056
|
+
});
|
|
3057
|
+
// fix bug for nest app
|
|
3058
|
+
removeDomScope();
|
|
2883
3059
|
};
|
|
2884
3060
|
}
|
|
2885
|
-
let isReWriteHistoryState = false;
|
|
2886
3061
|
/**
|
|
2887
3062
|
* rewrite history.pushState/replaceState
|
|
2888
3063
|
* used to fix the problem that the microAppState maybe missing when mainApp navigate to same path
|
|
2889
3064
|
* e.g: when nextjs, angular receive popstate event, they will use history.replaceState to update browser url with a new state object
|
|
2890
3065
|
*/
|
|
2891
|
-
function
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
3066
|
+
function patchHistory() {
|
|
3067
|
+
const rawWindow = globalEnv.rawWindow;
|
|
3068
|
+
rawWindow.history.pushState = reWriteHistoryMethod(globalEnv.rawPushState);
|
|
3069
|
+
rawWindow.history.replaceState = reWriteHistoryMethod(globalEnv.rawReplaceState);
|
|
3070
|
+
}
|
|
3071
|
+
function releasePatchHistory() {
|
|
3072
|
+
const rawWindow = globalEnv.rawWindow;
|
|
3073
|
+
rawWindow.history.pushState = globalEnv.rawPushState;
|
|
3074
|
+
rawWindow.history.replaceState = globalEnv.rawReplaceState;
|
|
2899
3075
|
}
|
|
2900
3076
|
|
|
2901
3077
|
function createRouterApi() {
|
|
@@ -2907,7 +3083,7 @@ function createRouterApi() {
|
|
|
2907
3083
|
* @param state to.state
|
|
2908
3084
|
*/
|
|
2909
3085
|
function navigateWithRawHistory(appName, methodName, targetLocation, state) {
|
|
2910
|
-
navigateWithNativeEvent(methodName, setMicroPathToURL(appName, targetLocation), false, setMicroState(appName,
|
|
3086
|
+
navigateWithNativeEvent(methodName, setMicroPathToURL(appName, targetLocation), false, setMicroState(appName, state !== null && state !== void 0 ? state : null));
|
|
2911
3087
|
// clear element scope after navigate
|
|
2912
3088
|
removeDomScope();
|
|
2913
3089
|
}
|
|
@@ -2922,11 +3098,11 @@ function createRouterApi() {
|
|
|
2922
3098
|
function createNavigationMethod(replace) {
|
|
2923
3099
|
return function (to) {
|
|
2924
3100
|
const appName = formatAppName(to.name);
|
|
2925
|
-
// console.log(3333333, appInstanceMap.get(appName))
|
|
2926
3101
|
if (appName && isString(to.path)) {
|
|
2927
3102
|
const app = appInstanceMap.get(appName);
|
|
2928
|
-
if (app && !app.sandBox)
|
|
2929
|
-
return logError(`navigation failed,
|
|
3103
|
+
if (app && (!app.sandBox || !app.useMemoryRouter)) {
|
|
3104
|
+
return logError(`navigation failed, memory router of app ${appName} is closed`);
|
|
3105
|
+
}
|
|
2930
3106
|
// active apps, include hidden keep-alive app
|
|
2931
3107
|
if (getActiveApps().includes(appName)) {
|
|
2932
3108
|
const microLocation = app.sandBox.proxyWindow.location;
|
|
@@ -3003,43 +3179,96 @@ function createRouterApi() {
|
|
|
3003
3179
|
function clearRouterWhenUnmount(appName) {
|
|
3004
3180
|
router.current.delete(appName);
|
|
3005
3181
|
}
|
|
3006
|
-
// defaultPage data
|
|
3007
|
-
const defaultPageRecord = useMapRecord();
|
|
3008
3182
|
/**
|
|
3009
|
-
*
|
|
3183
|
+
* NOTE:
|
|
3184
|
+
* 1. sandbox not open
|
|
3185
|
+
* 2. useMemoryRouter is false
|
|
3186
|
+
*/
|
|
3187
|
+
function commonHandlerForAttachToURL(appName) {
|
|
3188
|
+
const app = appInstanceMap.get(appName);
|
|
3189
|
+
if (app.sandBox && app.useMemoryRouter) {
|
|
3190
|
+
attachRouteToBrowserURL(setMicroPathToURL(appName, app.sandBox.proxyWindow.location), setMicroState(appName, getMicroState(appName)));
|
|
3191
|
+
}
|
|
3192
|
+
}
|
|
3193
|
+
/**
|
|
3194
|
+
* Attach specified active app router info to browser url
|
|
3010
3195
|
* @param appName app name
|
|
3011
|
-
* @param path page path
|
|
3012
3196
|
*/
|
|
3013
|
-
function
|
|
3197
|
+
function attachToURL(appName) {
|
|
3014
3198
|
appName = formatAppName(appName);
|
|
3015
|
-
if (
|
|
3016
|
-
|
|
3017
|
-
|
|
3199
|
+
if (appName && getActiveApps().includes(appName)) {
|
|
3200
|
+
commonHandlerForAttachToURL(appName);
|
|
3201
|
+
}
|
|
3018
3202
|
}
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3203
|
+
/**
|
|
3204
|
+
* Attach all active app router info to browser url
|
|
3205
|
+
* exclude hidden keep-alive app
|
|
3206
|
+
*/
|
|
3207
|
+
function attachAllToURL(includeHiddenApp = false) {
|
|
3208
|
+
getActiveApps(!includeHiddenApp).forEach(appName => commonHandlerForAttachToURL(appName));
|
|
3209
|
+
}
|
|
3210
|
+
function createDefaultPageApi() {
|
|
3211
|
+
// defaultPage data
|
|
3212
|
+
const defaultPageRecord = useMapRecord();
|
|
3213
|
+
/**
|
|
3214
|
+
* defaultPage only effect when mount, and has lower priority than query on browser url
|
|
3215
|
+
* @param appName app name
|
|
3216
|
+
* @param path page path
|
|
3217
|
+
*/
|
|
3218
|
+
function setDefaultPage(appName, path) {
|
|
3219
|
+
appName = formatAppName(appName);
|
|
3220
|
+
if (!appName || !path) {
|
|
3221
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
3222
|
+
if (!appName) {
|
|
3223
|
+
logWarn(`setDefaultPage: invalid appName "${appName}"`);
|
|
3224
|
+
}
|
|
3225
|
+
else {
|
|
3226
|
+
logWarn('setDefaultPage: path is required');
|
|
3227
|
+
}
|
|
3228
|
+
}
|
|
3229
|
+
return noopFalse;
|
|
3230
|
+
}
|
|
3231
|
+
return defaultPageRecord.add(appName, path);
|
|
3232
|
+
}
|
|
3233
|
+
function removeDefaultPage(appName) {
|
|
3234
|
+
appName = formatAppName(appName);
|
|
3235
|
+
if (!appName)
|
|
3236
|
+
return false;
|
|
3237
|
+
return defaultPageRecord.delete(appName);
|
|
3238
|
+
}
|
|
3239
|
+
return {
|
|
3240
|
+
setDefaultPage,
|
|
3241
|
+
removeDefaultPage,
|
|
3242
|
+
getDefaultPage: defaultPageRecord.get,
|
|
3243
|
+
};
|
|
3244
|
+
}
|
|
3245
|
+
function createBaseRouterApi() {
|
|
3246
|
+
/**
|
|
3247
|
+
* Record base app router, let child app control base app navigation
|
|
3248
|
+
*/
|
|
3249
|
+
let baseRouterProxy = null;
|
|
3250
|
+
function setBaseAppRouter(baseRouter) {
|
|
3251
|
+
if (isObject(baseRouter)) {
|
|
3252
|
+
baseRouterProxy = new Proxy(baseRouter, {
|
|
3253
|
+
get(target, key) {
|
|
3254
|
+
removeDomScope();
|
|
3255
|
+
const rawValue = Reflect.get(target, key);
|
|
3256
|
+
return isFunction(rawValue) ? bindFunctionToRawObject(target, rawValue, 'BASEROUTER') : rawValue;
|
|
3257
|
+
}
|
|
3258
|
+
});
|
|
3259
|
+
}
|
|
3260
|
+
else if (process.env.NODE_ENV !== 'production') {
|
|
3261
|
+
logWarn('setBaseAppRouter: Invalid base router');
|
|
3262
|
+
}
|
|
3263
|
+
}
|
|
3264
|
+
return {
|
|
3265
|
+
setBaseAppRouter,
|
|
3266
|
+
getBaseAppRouter: () => baseRouterProxy,
|
|
3267
|
+
};
|
|
3024
3268
|
}
|
|
3025
3269
|
// Router API for developer
|
|
3026
|
-
const router = {
|
|
3027
|
-
|
|
3028
|
-
encode: encodeMicroPath,
|
|
3029
|
-
decode: decodeMicroPath,
|
|
3030
|
-
push: createNavigationMethod(false),
|
|
3031
|
-
replace: createNavigationMethod(true),
|
|
3032
|
-
go: createRawHistoryMethod('go'),
|
|
3033
|
-
back: createRawHistoryMethod('back'),
|
|
3034
|
-
forward: createRawHistoryMethod('forward'),
|
|
3035
|
-
beforeEach: beforeGuards.add,
|
|
3036
|
-
afterEach: afterGuards.add,
|
|
3037
|
-
// attachToURL: 将指定的子应用路由信息添加到浏览器地址上
|
|
3038
|
-
// attachAllToURL: 将所有正在运行的子应用路由信息添加到浏览器地址上
|
|
3039
|
-
setDefaultPage,
|
|
3040
|
-
removeDefaultPage,
|
|
3041
|
-
getDefaultPage: defaultPageRecord.get,
|
|
3042
|
-
};
|
|
3270
|
+
const router = Object.assign(Object.assign({ current: new Map(), encode: encodeMicroPath, decode: decodeMicroPath, push: createNavigationMethod(false), replace: createNavigationMethod(true), go: createRawHistoryMethod('go'), back: createRawHistoryMethod('back'), forward: createRawHistoryMethod('forward'), beforeEach: beforeGuards.add, afterEach: afterGuards.add, attachToURL,
|
|
3271
|
+
attachAllToURL }, createDefaultPageApi()), createBaseRouterApi());
|
|
3043
3272
|
return {
|
|
3044
3273
|
router,
|
|
3045
3274
|
executeNavigationGuard,
|
|
@@ -3053,56 +3282,6 @@ const shadowLocationKeys = ['href', 'pathname', 'search', 'hash'];
|
|
|
3053
3282
|
const locationKeys = [...shadowLocationKeys, 'host', 'hostname', 'port', 'protocol', 'search'];
|
|
3054
3283
|
// origin, fullPath is necessary for guardLocation
|
|
3055
3284
|
const guardLocationKeys = [...locationKeys, 'origin', 'fullPath'];
|
|
3056
|
-
/**
|
|
3057
|
-
* create guardLocation by microLocation, used for router guard
|
|
3058
|
-
*/
|
|
3059
|
-
function createGuardLocation(appName, microLocation) {
|
|
3060
|
-
const guardLocation = assign({ name: appName }, microLocation);
|
|
3061
|
-
// The prototype values on the URL needs to be manually transferred
|
|
3062
|
-
for (const key of guardLocationKeys)
|
|
3063
|
-
guardLocation[key] = microLocation[key];
|
|
3064
|
-
return guardLocation;
|
|
3065
|
-
}
|
|
3066
|
-
// for updateBrowserURLWithLocation when initial
|
|
3067
|
-
function autoTriggerNavigationGuard(appName, microLocation) {
|
|
3068
|
-
executeNavigationGuard(appName, createGuardLocation(appName, microLocation), createGuardLocation(appName, microLocation));
|
|
3069
|
-
}
|
|
3070
|
-
/**
|
|
3071
|
-
* The following scenes will trigger location update:
|
|
3072
|
-
* 1. pushState/replaceState
|
|
3073
|
-
* 2. popStateEvent
|
|
3074
|
-
* 3. query on browser url when init sub app
|
|
3075
|
-
* 4. set defaultPage when when init sub app
|
|
3076
|
-
* NOTE:
|
|
3077
|
-
* 1. update browser URL first, and then update microLocation
|
|
3078
|
-
* 2. the same fullPath will not trigger router guards
|
|
3079
|
-
* @param appName app name
|
|
3080
|
-
* @param path target path
|
|
3081
|
-
* @param base base url
|
|
3082
|
-
* @param microLocation micro app location
|
|
3083
|
-
* @param type auto prevent
|
|
3084
|
-
*/
|
|
3085
|
-
function updateMicroLocation(appName, path, microLocation, type) {
|
|
3086
|
-
const newLocation = createURL(path, microLocation.href);
|
|
3087
|
-
// record old values of microLocation to `from`
|
|
3088
|
-
const from = createGuardLocation(appName, microLocation);
|
|
3089
|
-
for (const key of locationKeys) {
|
|
3090
|
-
if (shadowLocationKeys.includes(key)) {
|
|
3091
|
-
// reference of shadowLocation
|
|
3092
|
-
microLocation.shadowLocation[key] = newLocation[key];
|
|
3093
|
-
}
|
|
3094
|
-
else {
|
|
3095
|
-
// @ts-ignore reference of microLocation
|
|
3096
|
-
microLocation[key] = newLocation[key];
|
|
3097
|
-
}
|
|
3098
|
-
}
|
|
3099
|
-
// update latest values of microLocation to `to`
|
|
3100
|
-
const to = createGuardLocation(appName, microLocation);
|
|
3101
|
-
// The hook called only when fullPath changed
|
|
3102
|
-
if (type === 'auto' || (from.fullPath !== to.fullPath && type !== 'prevent')) {
|
|
3103
|
-
executeNavigationGuard(appName, to, from);
|
|
3104
|
-
}
|
|
3105
|
-
}
|
|
3106
3285
|
/**
|
|
3107
3286
|
* Create location for microApp, each microApp has only one location object, it is a reference type
|
|
3108
3287
|
* MDN https://developer.mozilla.org/en-US/docs/Web/API/Location
|
|
@@ -3247,6 +3426,56 @@ function createMicroLocation(appName, url) {
|
|
|
3247
3426
|
shadowLocation,
|
|
3248
3427
|
});
|
|
3249
3428
|
}
|
|
3429
|
+
/**
|
|
3430
|
+
* create guardLocation by microLocation, used for router guard
|
|
3431
|
+
*/
|
|
3432
|
+
function createGuardLocation(appName, microLocation) {
|
|
3433
|
+
const guardLocation = assign({ name: appName }, microLocation);
|
|
3434
|
+
// The prototype values on the URL needs to be manually transferred
|
|
3435
|
+
for (const key of guardLocationKeys)
|
|
3436
|
+
guardLocation[key] = microLocation[key];
|
|
3437
|
+
return guardLocation;
|
|
3438
|
+
}
|
|
3439
|
+
// for updateBrowserURLWithLocation when initial
|
|
3440
|
+
function autoTriggerNavigationGuard(appName, microLocation) {
|
|
3441
|
+
executeNavigationGuard(appName, createGuardLocation(appName, microLocation), createGuardLocation(appName, microLocation));
|
|
3442
|
+
}
|
|
3443
|
+
/**
|
|
3444
|
+
* The following scenes will trigger location update:
|
|
3445
|
+
* 1. pushState/replaceState
|
|
3446
|
+
* 2. popStateEvent
|
|
3447
|
+
* 3. query on browser url when init sub app
|
|
3448
|
+
* 4. set defaultPage when when init sub app
|
|
3449
|
+
* NOTE:
|
|
3450
|
+
* 1. update browser URL first, and then update microLocation
|
|
3451
|
+
* 2. the same fullPath will not trigger router guards
|
|
3452
|
+
* @param appName app name
|
|
3453
|
+
* @param path target path
|
|
3454
|
+
* @param base base url
|
|
3455
|
+
* @param microLocation micro app location
|
|
3456
|
+
* @param type auto prevent
|
|
3457
|
+
*/
|
|
3458
|
+
function updateMicroLocation(appName, path, microLocation, type) {
|
|
3459
|
+
const newLocation = createURL(path, microLocation.href);
|
|
3460
|
+
// record old values of microLocation to `from`
|
|
3461
|
+
const from = createGuardLocation(appName, microLocation);
|
|
3462
|
+
for (const key of locationKeys) {
|
|
3463
|
+
if (shadowLocationKeys.includes(key)) {
|
|
3464
|
+
// reference of shadowLocation
|
|
3465
|
+
microLocation.shadowLocation[key] = newLocation[key];
|
|
3466
|
+
}
|
|
3467
|
+
else {
|
|
3468
|
+
// @ts-ignore reference of microLocation
|
|
3469
|
+
microLocation[key] = newLocation[key];
|
|
3470
|
+
}
|
|
3471
|
+
}
|
|
3472
|
+
// update latest values of microLocation to `to`
|
|
3473
|
+
const to = createGuardLocation(appName, microLocation);
|
|
3474
|
+
// The hook called only when fullPath changed
|
|
3475
|
+
if (type === 'auto' || (from.fullPath !== to.fullPath && type !== 'prevent')) {
|
|
3476
|
+
executeNavigationGuard(appName, to, from);
|
|
3477
|
+
}
|
|
3478
|
+
}
|
|
3250
3479
|
|
|
3251
3480
|
/**
|
|
3252
3481
|
* The router system has two operations: read and write
|
|
@@ -3256,7 +3485,6 @@ function createMicroLocation(appName, url) {
|
|
|
3256
3485
|
* @returns MicroRouter
|
|
3257
3486
|
*/
|
|
3258
3487
|
function createMicroRouter(appName, url) {
|
|
3259
|
-
rewriteHistoryState();
|
|
3260
3488
|
const microLocation = createMicroLocation(appName, url);
|
|
3261
3489
|
return {
|
|
3262
3490
|
microLocation,
|
|
@@ -3282,7 +3510,7 @@ function updateBrowserURLWithLocation(appName, microLocation, defaultPage) {
|
|
|
3282
3510
|
if (defaultPage)
|
|
3283
3511
|
updateMicroLocation(appName, defaultPage, microLocation, 'prevent');
|
|
3284
3512
|
// attach microApp route info to browser URL
|
|
3285
|
-
|
|
3513
|
+
attachRouteToBrowserURL(setMicroPathToURL(appName, microLocation), setMicroState(appName, null));
|
|
3286
3514
|
// trigger guards after change browser URL
|
|
3287
3515
|
autoTriggerNavigationGuard(appName, microLocation);
|
|
3288
3516
|
}
|
|
@@ -3306,27 +3534,121 @@ function clearRouteStateFromURL(appName, url, microLocation, keepRouteState) {
|
|
|
3306
3534
|
* called on sandbox.stop or hidden of keep-alive app
|
|
3307
3535
|
*/
|
|
3308
3536
|
function removeStateAndPathFromBrowser(appName) {
|
|
3309
|
-
|
|
3537
|
+
attachRouteToBrowserURL(removeMicroPathFromURL(appName), removeMicroState(appName, globalEnv.rawWindow.history.state));
|
|
3310
3538
|
}
|
|
3311
3539
|
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3540
|
+
/**
|
|
3541
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/fetch
|
|
3542
|
+
* Promise<Response> fetch(input[, init])
|
|
3543
|
+
* input: string/Request
|
|
3544
|
+
* init?: object
|
|
3545
|
+
* @param url app url
|
|
3546
|
+
* @param target proxy target
|
|
3547
|
+
*/
|
|
3548
|
+
function createMicroFetch(url, target) {
|
|
3549
|
+
const rawFetch = !isUndefined(target) ? target : globalEnv.rawWindow.fetch;
|
|
3550
|
+
if (!isFunction(rawFetch))
|
|
3551
|
+
return rawFetch;
|
|
3552
|
+
return function microFetch(input, init, ...rests) {
|
|
3553
|
+
if (isString(input) || isURL(input)) {
|
|
3554
|
+
input = createURL(input, url).toString();
|
|
3555
|
+
}
|
|
3556
|
+
/**
|
|
3557
|
+
* When fetch rewrite by baseApp, domScope still active when exec rawWindow.fetch
|
|
3558
|
+
* If baseApp operate dom in fetch, it will cause error
|
|
3559
|
+
* The same for XMLHttpRequest, EventSource
|
|
3560
|
+
* e.g.
|
|
3561
|
+
* baseApp: <script crossorigin src="https://sgm-static.jd.com/sgm-2.8.0.js" name="SGMH5" sid="6f88a6e4ba4b4ae5acef2ec22c075085" appKey="jdb-adminb2b-pc"></script>
|
|
3562
|
+
*/
|
|
3563
|
+
removeDomScope();
|
|
3564
|
+
return rawFetch.call(globalEnv.rawWindow, input, init, ...rests);
|
|
3565
|
+
};
|
|
3566
|
+
}
|
|
3567
|
+
/**
|
|
3568
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
|
|
3569
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest
|
|
3570
|
+
* @param url app url
|
|
3571
|
+
* @param target proxy target
|
|
3572
|
+
*/
|
|
3573
|
+
function createMicroXMLHttpRequest(url, target) {
|
|
3574
|
+
const rawXMLHttpRequest = !isUndefined(target) ? target : globalEnv.rawWindow.XMLHttpRequest;
|
|
3575
|
+
if (!isConstructor(rawXMLHttpRequest))
|
|
3576
|
+
return rawXMLHttpRequest;
|
|
3577
|
+
return class MicroXMLHttpRequest extends rawXMLHttpRequest {
|
|
3578
|
+
open(method, reqUrl, ...rests) {
|
|
3579
|
+
if ((isString(reqUrl) && !/^f(ile|tp):\/\//.test(reqUrl)) || isURL(reqUrl)) {
|
|
3580
|
+
reqUrl = createURL(reqUrl, url).toString();
|
|
3581
|
+
}
|
|
3582
|
+
removeDomScope();
|
|
3583
|
+
super.open(method, reqUrl, ...rests);
|
|
3584
|
+
}
|
|
3585
|
+
};
|
|
3586
|
+
}
|
|
3587
|
+
function useMicroEventSource() {
|
|
3588
|
+
let eventSourceMap;
|
|
3589
|
+
/**
|
|
3590
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/EventSource
|
|
3591
|
+
* pc = new EventSource(url[, configuration])
|
|
3592
|
+
* url: string/Request
|
|
3593
|
+
* configuration?: object
|
|
3594
|
+
* @param url app url
|
|
3595
|
+
* @param target proxy target
|
|
3596
|
+
*/
|
|
3597
|
+
function createMicroEventSource(appName, url, target) {
|
|
3598
|
+
const rawEventSource = !isUndefined(target) ? target : globalEnv.rawWindow.EventSource;
|
|
3599
|
+
if (!isConstructor(rawEventSource))
|
|
3600
|
+
return rawEventSource;
|
|
3601
|
+
return class MicroEventSource extends rawEventSource {
|
|
3602
|
+
constructor(eventSourceUrl, eventSourceInitDict, ...rests) {
|
|
3603
|
+
if (isString(eventSourceUrl) || isURL(eventSourceUrl)) {
|
|
3604
|
+
eventSourceUrl = createURL(eventSourceUrl, url).toString();
|
|
3605
|
+
}
|
|
3606
|
+
removeDomScope();
|
|
3607
|
+
super(eventSourceUrl, eventSourceInitDict, ...rests);
|
|
3608
|
+
if (eventSourceMap) {
|
|
3609
|
+
const eventSourceList = eventSourceMap.get(appName);
|
|
3610
|
+
if (eventSourceList) {
|
|
3611
|
+
eventSourceList.add(this);
|
|
3612
|
+
}
|
|
3613
|
+
else {
|
|
3614
|
+
eventSourceMap.set(appName, new Set([this]));
|
|
3615
|
+
}
|
|
3616
|
+
}
|
|
3617
|
+
else {
|
|
3618
|
+
eventSourceMap = new Map([[appName, new Set([this])]]);
|
|
3619
|
+
}
|
|
3620
|
+
}
|
|
3621
|
+
close() {
|
|
3622
|
+
var _a;
|
|
3623
|
+
super.close();
|
|
3624
|
+
(_a = eventSourceMap.get(appName)) === null || _a === void 0 ? void 0 : _a.delete(this);
|
|
3625
|
+
}
|
|
3626
|
+
};
|
|
3627
|
+
}
|
|
3628
|
+
function clearMicroEventSource(appName) {
|
|
3629
|
+
const eventSourceList = eventSourceMap === null || eventSourceMap === void 0 ? void 0 : eventSourceMap.get(appName);
|
|
3630
|
+
if (eventSourceList === null || eventSourceList === void 0 ? void 0 : eventSourceList.size) {
|
|
3631
|
+
eventSourceList.forEach(item => {
|
|
3632
|
+
item.close();
|
|
3633
|
+
});
|
|
3634
|
+
eventSourceList.clear();
|
|
3635
|
+
}
|
|
3636
|
+
}
|
|
3637
|
+
return {
|
|
3638
|
+
createMicroEventSource,
|
|
3639
|
+
clearMicroEventSource,
|
|
3640
|
+
};
|
|
3641
|
+
}
|
|
3642
|
+
|
|
3643
|
+
const { createMicroEventSource, clearMicroEventSource } = useMicroEventSource();
|
|
3322
3644
|
const globalPropertyList = ['window', 'self', 'globalThis'];
|
|
3323
3645
|
class SandBox {
|
|
3324
3646
|
constructor(appName, url, useMemoryRouter = true) {
|
|
3325
3647
|
/**
|
|
3326
3648
|
* Scoped global Properties(Properties that can only get and set in microAppWindow, will not escape to rawWindow)
|
|
3327
|
-
* https://github.com/micro-zoe/micro-app/issues/234
|
|
3649
|
+
* Fix https://github.com/micro-zoe/micro-app/issues/234
|
|
3328
3650
|
*/
|
|
3329
|
-
this.scopeProperties = [
|
|
3651
|
+
this.scopeProperties = [];
|
|
3330
3652
|
// Properties that can be escape to rawWindow
|
|
3331
3653
|
this.escapeProperties = [];
|
|
3332
3654
|
// Properties newly added to microAppWindow
|
|
@@ -3336,14 +3658,15 @@ class SandBox {
|
|
|
3336
3658
|
// sandbox state
|
|
3337
3659
|
this.active = false;
|
|
3338
3660
|
this.microAppWindow = {}; // Proxy target
|
|
3661
|
+
this.adapter = new Adapter();
|
|
3339
3662
|
// get scopeProperties and escapeProperties from plugins
|
|
3340
3663
|
this.getSpecialProperties(appName);
|
|
3341
3664
|
// create proxyWindow with Proxy(microAppWindow)
|
|
3342
3665
|
this.proxyWindow = this.createProxyWindow(appName);
|
|
3343
|
-
// inject global properties
|
|
3344
|
-
this.initMicroAppWindow(this.microAppWindow, appName, url, useMemoryRouter);
|
|
3345
3666
|
// Rewrite global event listener & timeout
|
|
3346
|
-
assign(this, effect(this.microAppWindow));
|
|
3667
|
+
assign(this, effect(appName, this.microAppWindow));
|
|
3668
|
+
// inject global properties
|
|
3669
|
+
this.initStaticGlobalKeys(this.microAppWindow, appName, url, useMemoryRouter);
|
|
3347
3670
|
}
|
|
3348
3671
|
start(baseRoute, useMemoryRouter = true, defaultPage = '') {
|
|
3349
3672
|
if (!this.active) {
|
|
@@ -3356,20 +3679,35 @@ class SandBox {
|
|
|
3356
3679
|
else {
|
|
3357
3680
|
this.microAppWindow.__MICRO_APP_BASE_ROUTE__ = this.microAppWindow.__MICRO_APP_BASE_URL__ = baseRoute;
|
|
3358
3681
|
}
|
|
3682
|
+
// prevent the key deleted during sandBox.stop after rewrite
|
|
3683
|
+
this.initGlobalKeysWhenStart(this.microAppWindow, this.proxyWindow.__MICRO_APP_NAME__, this.proxyWindow.__MICRO_APP_URL__);
|
|
3359
3684
|
if (++SandBox.activeCount === 1) {
|
|
3360
3685
|
effectDocumentEvent();
|
|
3361
3686
|
patchElementPrototypeMethods();
|
|
3362
|
-
|
|
3687
|
+
initEnvOfNestedApp();
|
|
3688
|
+
patchHistory();
|
|
3363
3689
|
}
|
|
3364
|
-
|
|
3365
|
-
globalEnv.rawWindow._babelPolyfill && (globalEnv.rawWindow._babelPolyfill = false);
|
|
3690
|
+
fixBabelPolyfill6();
|
|
3366
3691
|
}
|
|
3367
3692
|
}
|
|
3368
|
-
stop(keepRouteState
|
|
3693
|
+
stop(keepRouteState, clearEventSource) {
|
|
3369
3694
|
if (this.active) {
|
|
3370
3695
|
this.releaseEffect();
|
|
3371
3696
|
this.microAppWindow.microApp.clearDataListener();
|
|
3372
3697
|
this.microAppWindow.microApp.clearGlobalDataListener();
|
|
3698
|
+
if (this.removeHistoryListener) {
|
|
3699
|
+
this.clearRouteState(keepRouteState);
|
|
3700
|
+
// release listener of popstate
|
|
3701
|
+
this.removeHistoryListener();
|
|
3702
|
+
}
|
|
3703
|
+
if (clearEventSource) {
|
|
3704
|
+
clearMicroEventSource(this.proxyWindow.__MICRO_APP_NAME__);
|
|
3705
|
+
}
|
|
3706
|
+
/**
|
|
3707
|
+
* NOTE:
|
|
3708
|
+
* 1. injectedKeys and escapeKeys must be placed at the back
|
|
3709
|
+
* 2. if key in initial microAppWindow, and then rewrite, this key will be delete from microAppWindow when stop, and lost when restart
|
|
3710
|
+
*/
|
|
3373
3711
|
this.injectedKeys.forEach((key) => {
|
|
3374
3712
|
Reflect.deleteProperty(this.microAppWindow, key);
|
|
3375
3713
|
});
|
|
@@ -3378,14 +3716,10 @@ class SandBox {
|
|
|
3378
3716
|
Reflect.deleteProperty(globalEnv.rawWindow, key);
|
|
3379
3717
|
});
|
|
3380
3718
|
this.escapeKeys.clear();
|
|
3381
|
-
if (this.removeHistoryListener) {
|
|
3382
|
-
this.clearRouteState(keepRouteState);
|
|
3383
|
-
// release listener of popstate
|
|
3384
|
-
this.removeHistoryListener();
|
|
3385
|
-
}
|
|
3386
3719
|
if (--SandBox.activeCount === 0) {
|
|
3387
3720
|
releaseEffectDocumentEvent();
|
|
3388
3721
|
releasePatches();
|
|
3722
|
+
releasePatchHistory();
|
|
3389
3723
|
}
|
|
3390
3724
|
this.active = false;
|
|
3391
3725
|
}
|
|
@@ -3409,15 +3743,16 @@ class SandBox {
|
|
|
3409
3743
|
rebuildDataCenterSnapshot(this.microAppWindow.microApp);
|
|
3410
3744
|
}
|
|
3411
3745
|
/**
|
|
3412
|
-
* get scopeProperties and escapeProperties from plugins
|
|
3746
|
+
* get scopeProperties and escapeProperties from plugins & adapter
|
|
3413
3747
|
* @param appName app name
|
|
3414
3748
|
*/
|
|
3415
3749
|
getSpecialProperties(appName) {
|
|
3416
3750
|
var _a;
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3751
|
+
this.scopeProperties = this.scopeProperties.concat(this.adapter.staticScopeProperties);
|
|
3752
|
+
if (isPlainObject(microApp.plugins)) {
|
|
3753
|
+
this.commonActionForSpecialProperties(microApp.plugins.global);
|
|
3754
|
+
this.commonActionForSpecialProperties((_a = microApp.plugins.modules) === null || _a === void 0 ? void 0 : _a[appName]);
|
|
3755
|
+
}
|
|
3421
3756
|
}
|
|
3422
3757
|
// common action for global plugins and module plugins
|
|
3423
3758
|
commonActionForSpecialProperties(plugins) {
|
|
@@ -3447,11 +3782,11 @@ class SandBox {
|
|
|
3447
3782
|
this.scopeProperties.includes(key))
|
|
3448
3783
|
return Reflect.get(target, key);
|
|
3449
3784
|
const rawValue = Reflect.get(rawWindow, key);
|
|
3450
|
-
return isFunction(rawValue) ?
|
|
3785
|
+
return isFunction(rawValue) ? bindFunctionToRawObject(rawWindow, rawValue) : rawValue;
|
|
3451
3786
|
},
|
|
3452
3787
|
set: (target, key, value) => {
|
|
3453
3788
|
if (this.active) {
|
|
3454
|
-
if (escapeSetterKeyList.includes(key)) {
|
|
3789
|
+
if (this.adapter.escapeSetterKeyList.includes(key)) {
|
|
3455
3790
|
Reflect.set(rawWindow, key, value);
|
|
3456
3791
|
}
|
|
3457
3792
|
else if (
|
|
@@ -3475,7 +3810,8 @@ class SandBox {
|
|
|
3475
3810
|
this.injectedKeys.add(key);
|
|
3476
3811
|
}
|
|
3477
3812
|
if ((this.escapeProperties.includes(key) ||
|
|
3478
|
-
(staticEscapeProperties.includes(key) &&
|
|
3813
|
+
(this.adapter.staticEscapeProperties.includes(key) &&
|
|
3814
|
+
!Reflect.has(rawWindow, key))) &&
|
|
3479
3815
|
!this.scopeProperties.includes(key)) {
|
|
3480
3816
|
Reflect.set(rawWindow, key, value);
|
|
3481
3817
|
this.escapeKeys.add(key);
|
|
@@ -3531,26 +3867,48 @@ class SandBox {
|
|
|
3531
3867
|
* @param microAppWindow micro window
|
|
3532
3868
|
* @param appName app name
|
|
3533
3869
|
* @param url app url
|
|
3870
|
+
* @param useMemoryRouter whether use memory router
|
|
3534
3871
|
*/
|
|
3535
|
-
|
|
3872
|
+
initStaticGlobalKeys(microAppWindow, appName, url, useMemoryRouter) {
|
|
3536
3873
|
microAppWindow.__MICRO_APP_ENVIRONMENT__ = true;
|
|
3537
3874
|
microAppWindow.__MICRO_APP_NAME__ = appName;
|
|
3538
3875
|
microAppWindow.__MICRO_APP_URL__ = url;
|
|
3539
3876
|
microAppWindow.__MICRO_APP_PUBLIC_PATH__ = getEffectivePath(url);
|
|
3540
3877
|
microAppWindow.__MICRO_APP_WINDOW__ = microAppWindow;
|
|
3878
|
+
microAppWindow.rawWindow = globalEnv.rawWindow;
|
|
3879
|
+
microAppWindow.rawDocument = globalEnv.rawDocument;
|
|
3541
3880
|
microAppWindow.microApp = assign(new EventCenterForMicroApp(appName), {
|
|
3542
3881
|
removeDomScope,
|
|
3543
3882
|
pureCreateElement,
|
|
3544
3883
|
router,
|
|
3545
3884
|
});
|
|
3546
|
-
microAppWindow
|
|
3547
|
-
microAppWindow.rawDocument = globalEnv.rawDocument;
|
|
3548
|
-
microAppWindow.hasOwnProperty = (key) => rawHasOwnProperty.call(microAppWindow, key) || rawHasOwnProperty.call(globalEnv.rawWindow, key);
|
|
3885
|
+
this.setProxyDocument(microAppWindow, appName);
|
|
3549
3886
|
this.setMappingPropertiesWithRawDescriptor(microAppWindow);
|
|
3550
|
-
this.setHijackProperties(microAppWindow, appName);
|
|
3551
|
-
// this.patchHijackRequest(microAppWindow, appName, url)
|
|
3552
3887
|
if (useMemoryRouter)
|
|
3553
|
-
this.
|
|
3888
|
+
this.setMicroAppRouter(microAppWindow, appName, url);
|
|
3889
|
+
}
|
|
3890
|
+
setProxyDocument(microAppWindow, appName) {
|
|
3891
|
+
const { proxyDocument, MicroDocument } = this.createProxyDocument(appName);
|
|
3892
|
+
rawDefineProperties(microAppWindow, {
|
|
3893
|
+
document: {
|
|
3894
|
+
configurable: false,
|
|
3895
|
+
enumerable: true,
|
|
3896
|
+
get() {
|
|
3897
|
+
throttleDeferForSetAppName(appName);
|
|
3898
|
+
// return globalEnv.rawDocument
|
|
3899
|
+
return proxyDocument;
|
|
3900
|
+
},
|
|
3901
|
+
},
|
|
3902
|
+
Document: {
|
|
3903
|
+
configurable: false,
|
|
3904
|
+
enumerable: false,
|
|
3905
|
+
get() {
|
|
3906
|
+
throttleDeferForSetAppName(appName);
|
|
3907
|
+
// return globalEnv.rawRootDocument
|
|
3908
|
+
return MicroDocument;
|
|
3909
|
+
},
|
|
3910
|
+
}
|
|
3911
|
+
});
|
|
3554
3912
|
}
|
|
3555
3913
|
// properties associated with the native window
|
|
3556
3914
|
setMappingPropertiesWithRawDescriptor(microAppWindow) {
|
|
@@ -3579,18 +3937,21 @@ class SandBox {
|
|
|
3579
3937
|
};
|
|
3580
3938
|
return descriptor;
|
|
3581
3939
|
}
|
|
3940
|
+
/**
|
|
3941
|
+
* init global properties of microAppWindow when exec sandBox.start
|
|
3942
|
+
* @param microAppWindow micro window
|
|
3943
|
+
* @param appName app name
|
|
3944
|
+
* @param url app url
|
|
3945
|
+
*/
|
|
3946
|
+
initGlobalKeysWhenStart(microAppWindow, appName, url) {
|
|
3947
|
+
microAppWindow.hasOwnProperty = (key) => rawHasOwnProperty.call(microAppWindow, key) || rawHasOwnProperty.call(globalEnv.rawWindow, key);
|
|
3948
|
+
this.setHijackProperty(microAppWindow, appName);
|
|
3949
|
+
this.patchRequestApi(microAppWindow, appName, url);
|
|
3950
|
+
}
|
|
3582
3951
|
// set hijack Properties to microAppWindow
|
|
3583
|
-
|
|
3952
|
+
setHijackProperty(microAppWindow, appName) {
|
|
3584
3953
|
let modifiedEval, modifiedImage;
|
|
3585
3954
|
rawDefineProperties(microAppWindow, {
|
|
3586
|
-
document: {
|
|
3587
|
-
configurable: false,
|
|
3588
|
-
enumerable: true,
|
|
3589
|
-
get() {
|
|
3590
|
-
throttleDeferForSetAppName(appName);
|
|
3591
|
-
return globalEnv.rawDocument;
|
|
3592
|
-
},
|
|
3593
|
-
},
|
|
3594
3955
|
eval: {
|
|
3595
3956
|
configurable: true,
|
|
3596
3957
|
enumerable: false,
|
|
@@ -3615,65 +3976,46 @@ class SandBox {
|
|
|
3615
3976
|
},
|
|
3616
3977
|
});
|
|
3617
3978
|
}
|
|
3618
|
-
//
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
// get () {
|
|
3657
|
-
// return patchFetch
|
|
3658
|
-
// },
|
|
3659
|
-
// set: (value) => {
|
|
3660
|
-
// modifiedImage = value
|
|
3661
|
-
// },
|
|
3662
|
-
// },
|
|
3663
|
-
// XMLHttpRequest: {
|
|
3664
|
-
// configurable: true,
|
|
3665
|
-
// enumerable: true,
|
|
3666
|
-
// get () {
|
|
3667
|
-
// return XMLHttpRequest
|
|
3668
|
-
// },
|
|
3669
|
-
// set: (value) => {
|
|
3670
|
-
// modifiedImage = value
|
|
3671
|
-
// },
|
|
3672
|
-
// },
|
|
3673
|
-
// })
|
|
3674
|
-
// }
|
|
3979
|
+
// rewrite fetch, XMLHttpRequest, EventSource
|
|
3980
|
+
patchRequestApi(microAppWindow, appName, url) {
|
|
3981
|
+
let microFetch = createMicroFetch(url);
|
|
3982
|
+
let microXMLHttpRequest = createMicroXMLHttpRequest(url);
|
|
3983
|
+
let microEventSource = createMicroEventSource(appName, url);
|
|
3984
|
+
rawDefineProperties(microAppWindow, {
|
|
3985
|
+
fetch: {
|
|
3986
|
+
configurable: true,
|
|
3987
|
+
enumerable: true,
|
|
3988
|
+
get() {
|
|
3989
|
+
return microFetch;
|
|
3990
|
+
},
|
|
3991
|
+
set(value) {
|
|
3992
|
+
microFetch = createMicroFetch(url, value);
|
|
3993
|
+
},
|
|
3994
|
+
},
|
|
3995
|
+
XMLHttpRequest: {
|
|
3996
|
+
configurable: true,
|
|
3997
|
+
enumerable: true,
|
|
3998
|
+
get() {
|
|
3999
|
+
return microXMLHttpRequest;
|
|
4000
|
+
},
|
|
4001
|
+
set(value) {
|
|
4002
|
+
microXMLHttpRequest = createMicroXMLHttpRequest(url, value);
|
|
4003
|
+
},
|
|
4004
|
+
},
|
|
4005
|
+
EventSource: {
|
|
4006
|
+
configurable: true,
|
|
4007
|
+
enumerable: true,
|
|
4008
|
+
get() {
|
|
4009
|
+
return microEventSource;
|
|
4010
|
+
},
|
|
4011
|
+
set(value) {
|
|
4012
|
+
microEventSource = createMicroEventSource(appName, url, value);
|
|
4013
|
+
},
|
|
4014
|
+
},
|
|
4015
|
+
});
|
|
4016
|
+
}
|
|
3675
4017
|
// set location & history for memory router
|
|
3676
|
-
|
|
4018
|
+
setMicroAppRouter(microAppWindow, appName, url) {
|
|
3677
4019
|
const { microLocation, microHistory } = createMicroRouter(appName, url);
|
|
3678
4020
|
rawDefineProperties(microAppWindow, {
|
|
3679
4021
|
location: {
|
|
@@ -3707,6 +4049,63 @@ class SandBox {
|
|
|
3707
4049
|
removeRouteInfoForKeepAliveApp() {
|
|
3708
4050
|
removeStateAndPathFromBrowser(this.proxyWindow.__MICRO_APP_NAME__);
|
|
3709
4051
|
}
|
|
4052
|
+
/**
|
|
4053
|
+
* Create new document and Document
|
|
4054
|
+
*/
|
|
4055
|
+
createProxyDocument(appName) {
|
|
4056
|
+
const rawDocument = globalEnv.rawDocument;
|
|
4057
|
+
const rawRootDocument = globalEnv.rawRootDocument;
|
|
4058
|
+
const createElement = function (tagName, options) {
|
|
4059
|
+
const element = globalEnv.rawCreateElement.call(rawDocument, tagName, options);
|
|
4060
|
+
element.__MICRO_APP_NAME__ = appName;
|
|
4061
|
+
return element;
|
|
4062
|
+
};
|
|
4063
|
+
const proxyDocument = new Proxy(rawDocument, {
|
|
4064
|
+
get(target, key) {
|
|
4065
|
+
throttleDeferForSetAppName(appName);
|
|
4066
|
+
throttleDeferForParentNode(proxyDocument);
|
|
4067
|
+
if (key === 'createElement')
|
|
4068
|
+
return createElement;
|
|
4069
|
+
if (key === Symbol.toStringTag)
|
|
4070
|
+
return 'ProxyDocument';
|
|
4071
|
+
const rawValue = Reflect.get(target, key);
|
|
4072
|
+
return isFunction(rawValue) ? bindFunctionToRawObject(rawDocument, rawValue, 'DOCUMENT') : rawValue;
|
|
4073
|
+
},
|
|
4074
|
+
});
|
|
4075
|
+
class MicroDocument {
|
|
4076
|
+
static [Symbol.hasInstance](target) {
|
|
4077
|
+
let proto = target;
|
|
4078
|
+
while (proto = Object.getPrototypeOf(proto)) {
|
|
4079
|
+
if (proto === MicroDocument.prototype) {
|
|
4080
|
+
return true;
|
|
4081
|
+
}
|
|
4082
|
+
}
|
|
4083
|
+
return (target === proxyDocument ||
|
|
4084
|
+
target instanceof rawRootDocument);
|
|
4085
|
+
}
|
|
4086
|
+
}
|
|
4087
|
+
/**
|
|
4088
|
+
* TIP:
|
|
4089
|
+
* 1. child class __proto__, which represents the inherit of the constructor, always points to the parent class
|
|
4090
|
+
* 2. child class prototype.__proto__, which represents the inherit of methods, always points to parent class prototype
|
|
4091
|
+
* e.g.
|
|
4092
|
+
* class B extends A {}
|
|
4093
|
+
* B.__proto__ === A // true
|
|
4094
|
+
* B.prototype.__proto__ === A.prototype // true
|
|
4095
|
+
*/
|
|
4096
|
+
Object.setPrototypeOf(MicroDocument, rawRootDocument);
|
|
4097
|
+
Object.setPrototypeOf(MicroDocument.prototype, new Proxy(rawRootDocument.prototype, {
|
|
4098
|
+
get(target, key) {
|
|
4099
|
+
throttleDeferForSetAppName(appName);
|
|
4100
|
+
const rawValue = Reflect.get(target, key);
|
|
4101
|
+
return isFunction(rawValue) ? bindFunctionToRawObject(rawDocument, rawValue, 'DOCUMENT') : rawValue;
|
|
4102
|
+
}
|
|
4103
|
+
}));
|
|
4104
|
+
return {
|
|
4105
|
+
proxyDocument,
|
|
4106
|
+
MicroDocument,
|
|
4107
|
+
};
|
|
4108
|
+
}
|
|
3710
4109
|
}
|
|
3711
4110
|
SandBox.activeCount = 0; // number of active sandbox
|
|
3712
4111
|
|
|
@@ -3774,7 +4173,7 @@ function dispatchCustomEventToMicroApp(eventName, appName, detail = {}) {
|
|
|
3774
4173
|
// micro app instances
|
|
3775
4174
|
const appInstanceMap = new Map();
|
|
3776
4175
|
class CreateApp {
|
|
3777
|
-
constructor({ name, url, ssrUrl, container, inline, scopecss, useSandbox, useMemoryRouter, baseroute, keepRouteState, defaultPage, }) {
|
|
4176
|
+
constructor({ name, url, ssrUrl, container, inline, scopecss, useSandbox, useMemoryRouter, baseroute, keepRouteState, hiddenRouter, defaultPage, }) {
|
|
3778
4177
|
this.state = appStates.CREATED;
|
|
3779
4178
|
this.keepAliveState = null;
|
|
3780
4179
|
this.keepAliveContainer = null;
|
|
@@ -3787,17 +4186,18 @@ class CreateApp {
|
|
|
3787
4186
|
this.prefetchResolve = null;
|
|
3788
4187
|
this.container = null;
|
|
3789
4188
|
this.sandBox = null;
|
|
3790
|
-
this.container = container !== null && container !== void 0 ? container : null;
|
|
3791
|
-
this.inline = inline !== null && inline !== void 0 ? inline : false;
|
|
3792
|
-
this.baseroute = baseroute !== null && baseroute !== void 0 ? baseroute : '';
|
|
3793
|
-
this.keepRouteState = keepRouteState !== null && keepRouteState !== void 0 ? keepRouteState : false;
|
|
3794
|
-
this.ssrUrl = ssrUrl !== null && ssrUrl !== void 0 ? ssrUrl : '';
|
|
3795
|
-
// optional during init👆
|
|
3796
4189
|
this.name = name;
|
|
3797
4190
|
this.url = url;
|
|
3798
4191
|
this.useSandbox = useSandbox;
|
|
3799
4192
|
this.scopecss = this.useSandbox && scopecss;
|
|
3800
4193
|
this.useMemoryRouter = this.useSandbox && useMemoryRouter;
|
|
4194
|
+
// optional during init base on prefetch 👇
|
|
4195
|
+
this.container = container !== null && container !== void 0 ? container : null;
|
|
4196
|
+
this.ssrUrl = ssrUrl !== null && ssrUrl !== void 0 ? ssrUrl : '';
|
|
4197
|
+
this.inline = inline !== null && inline !== void 0 ? inline : false;
|
|
4198
|
+
this.baseroute = baseroute !== null && baseroute !== void 0 ? baseroute : '';
|
|
4199
|
+
this.keepRouteState = keepRouteState !== null && keepRouteState !== void 0 ? keepRouteState : false;
|
|
4200
|
+
this.hiddenRouter = hiddenRouter !== null && hiddenRouter !== void 0 ? hiddenRouter : false;
|
|
3801
4201
|
this.defaultPage = defaultPage !== null && defaultPage !== void 0 ? defaultPage : '';
|
|
3802
4202
|
this.source = {
|
|
3803
4203
|
links: new Map(),
|
|
@@ -3850,16 +4250,14 @@ class CreateApp {
|
|
|
3850
4250
|
* @param baseroute route prefix, default is ''
|
|
3851
4251
|
* @param keepRouteState keep route state when unmount, default is false
|
|
3852
4252
|
*/
|
|
3853
|
-
mount(container, inline, baseroute, keepRouteState, defaultPage) {
|
|
4253
|
+
mount(container, inline, baseroute, keepRouteState, defaultPage, hiddenRouter) {
|
|
3854
4254
|
var _a, _b, _c;
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
// keepRouteState effective on unmount
|
|
3858
|
-
if (isBoolean(keepRouteState))
|
|
3859
|
-
this.keepRouteState = keepRouteState;
|
|
4255
|
+
this.inline = inline !== null && inline !== void 0 ? inline : this.inline;
|
|
4256
|
+
this.keepRouteState = keepRouteState !== null && keepRouteState !== void 0 ? keepRouteState : this.keepRouteState;
|
|
3860
4257
|
this.container = (_a = this.container) !== null && _a !== void 0 ? _a : container;
|
|
3861
4258
|
this.baseroute = baseroute !== null && baseroute !== void 0 ? baseroute : this.baseroute;
|
|
3862
4259
|
this.defaultPage = defaultPage !== null && defaultPage !== void 0 ? defaultPage : this.defaultPage;
|
|
4260
|
+
this.hiddenRouter = hiddenRouter !== null && hiddenRouter !== void 0 ? hiddenRouter : this.hiddenRouter;
|
|
3863
4261
|
if (this.loadSourceLevel !== 2) {
|
|
3864
4262
|
this.state = appStates.LOADING;
|
|
3865
4263
|
return;
|
|
@@ -3990,8 +4388,13 @@ class CreateApp {
|
|
|
3990
4388
|
else if (this.umdMode && this.container.childElementCount) {
|
|
3991
4389
|
cloneContainer(this.container, this.source.html, false);
|
|
3992
4390
|
}
|
|
3993
|
-
|
|
3994
|
-
|
|
4391
|
+
/**
|
|
4392
|
+
* this.container maybe contains micro-app element, stop sandbox should exec after cloneContainer
|
|
4393
|
+
* NOTE:
|
|
4394
|
+
* 1. if destroy is true, clear route state
|
|
4395
|
+
* 2. umd mode and keep-alive will not clear EventSource
|
|
4396
|
+
*/
|
|
4397
|
+
(_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.stop(this.keepRouteState && !destroy, !this.umdMode || destroy);
|
|
3995
4398
|
if (!getActiveApps().length) {
|
|
3996
4399
|
releasePatchSetAttribute();
|
|
3997
4400
|
}
|
|
@@ -4129,6 +4532,7 @@ function defineElement(tagName) {
|
|
|
4129
4532
|
this.setAttribute('name', this.appName);
|
|
4130
4533
|
}
|
|
4131
4534
|
};
|
|
4535
|
+
// patchSetAttribute hijiack data attribute, it needs exec first
|
|
4132
4536
|
patchSetAttribute();
|
|
4133
4537
|
}
|
|
4134
4538
|
static get observedAttributes() {
|
|
@@ -4305,7 +4709,7 @@ function defineElement(tagName) {
|
|
|
4305
4709
|
app.isPrefetch = false;
|
|
4306
4710
|
defer(() => {
|
|
4307
4711
|
var _a;
|
|
4308
|
-
return app.mount((_a = this.shadowRoot) !== null && _a !== void 0 ? _a : this, this.getDisposeResult('inline'), this.getBaseRouteCompatible(), this.getDisposeResult('keep-router-state'), this.getDefaultPageValue());
|
|
4712
|
+
return app.mount((_a = this.shadowRoot) !== null && _a !== void 0 ? _a : this, this.getDisposeResult('inline'), this.getBaseRouteCompatible(), this.getDisposeResult('keep-router-state'), this.getDefaultPageValue(), this.getDisposeResult('hidden-router'));
|
|
4309
4713
|
});
|
|
4310
4714
|
}
|
|
4311
4715
|
// create app instance
|
|
@@ -4324,12 +4728,13 @@ function defineElement(tagName) {
|
|
|
4324
4728
|
ssrUrl: this.ssrUrl,
|
|
4325
4729
|
container: (_a = this.shadowRoot) !== null && _a !== void 0 ? _a : this,
|
|
4326
4730
|
inline: this.getDisposeResult('inline'),
|
|
4327
|
-
scopecss: !(this.getDisposeResult('
|
|
4328
|
-
useSandbox: !this.getDisposeResult('
|
|
4731
|
+
scopecss: !(this.getDisposeResult('disable-scopecss') || this.getDisposeResult('shadowDOM')),
|
|
4732
|
+
useSandbox: !this.getDisposeResult('disable-sandbox'),
|
|
4329
4733
|
useMemoryRouter: !this.getDisposeResult('disable-memory-router'),
|
|
4330
4734
|
baseroute: this.getBaseRouteCompatible(),
|
|
4331
4735
|
keepRouteState: this.getDisposeResult('keep-router-state'),
|
|
4332
4736
|
defaultPage: this.getDefaultPageValue(),
|
|
4737
|
+
hiddenRouter: this.getDisposeResult('hidden-router'),
|
|
4333
4738
|
});
|
|
4334
4739
|
appInstanceMap.set(this.appName, instance);
|
|
4335
4740
|
}
|
|
@@ -4364,25 +4769,25 @@ function defineElement(tagName) {
|
|
|
4364
4769
|
*/
|
|
4365
4770
|
getDisposeResult(name) {
|
|
4366
4771
|
// @ts-ignore
|
|
4367
|
-
return (this.compatibleSpecialProperties(name) || microApp[name]) && this.compatibleDisableSpecialProperties(name);
|
|
4772
|
+
return (this.compatibleSpecialProperties(name) || !!microApp[name]) && this.compatibleDisableSpecialProperties(name);
|
|
4368
4773
|
}
|
|
4369
4774
|
// compatible of disableScopecss & disableSandbox
|
|
4370
4775
|
compatibleSpecialProperties(name) {
|
|
4371
|
-
if (name === '
|
|
4372
|
-
return this.hasAttribute('
|
|
4776
|
+
if (name === 'disable-scopecss') {
|
|
4777
|
+
return this.hasAttribute('disable-scopecss') || this.hasAttribute('disableScopecss');
|
|
4373
4778
|
}
|
|
4374
|
-
else if (name === '
|
|
4375
|
-
return this.hasAttribute('
|
|
4779
|
+
else if (name === 'disable-sandbox') {
|
|
4780
|
+
return this.hasAttribute('disable-sandbox') || this.hasAttribute('disableSandbox');
|
|
4376
4781
|
}
|
|
4377
4782
|
return this.hasAttribute(name);
|
|
4378
4783
|
}
|
|
4379
4784
|
// compatible of disableScopecss & disableSandbox
|
|
4380
4785
|
compatibleDisableSpecialProperties(name) {
|
|
4381
|
-
if (name === '
|
|
4382
|
-
return this.getAttribute('
|
|
4786
|
+
if (name === 'disable-scopecss') {
|
|
4787
|
+
return this.getAttribute('disable-scopecss') !== 'false' && this.getAttribute('disableScopecss') !== 'false';
|
|
4383
4788
|
}
|
|
4384
|
-
else if (name === '
|
|
4385
|
-
return this.getAttribute('
|
|
4789
|
+
else if (name === 'disable-sandbox') {
|
|
4790
|
+
return this.getAttribute('disable-sandbox') !== 'false' && this.getAttribute('disableSandbox') !== 'false';
|
|
4386
4791
|
}
|
|
4387
4792
|
return this.getAttribute(name) !== 'false';
|
|
4388
4793
|
}
|
|
@@ -4410,7 +4815,7 @@ function defineElement(tagName) {
|
|
|
4410
4815
|
*/
|
|
4411
4816
|
updateSsrUrl(baseUrl) {
|
|
4412
4817
|
if (this.getDisposeResult('ssr')) {
|
|
4413
|
-
if (this.getDisposeResult('disable-memory-router')) {
|
|
4818
|
+
if (this.getDisposeResult('disable-memory-router') || this.getDisposeResult('disableSandbox')) {
|
|
4414
4819
|
const rawLocation = globalEnv.rawWindow.location;
|
|
4415
4820
|
this.ssrUrl = CompletionPath(rawLocation.pathname + rawLocation.search, baseUrl);
|
|
4416
4821
|
}
|
|
@@ -4494,7 +4899,7 @@ function preFetch(apps) {
|
|
|
4494
4899
|
function preFetchInSerial(prefetchApp) {
|
|
4495
4900
|
return new Promise((resolve) => {
|
|
4496
4901
|
requestIdleCallback(() => {
|
|
4497
|
-
var _a, _b, _c;
|
|
4902
|
+
var _a, _b, _c, _d, _e;
|
|
4498
4903
|
if (isPlainObject(prefetchApp) && navigator.onLine) {
|
|
4499
4904
|
prefetchApp.name = formatAppName(prefetchApp.name);
|
|
4500
4905
|
prefetchApp.url = formatAppURL(prefetchApp.url, prefetchApp.name);
|
|
@@ -4502,9 +4907,9 @@ function preFetchInSerial(prefetchApp) {
|
|
|
4502
4907
|
const app = new CreateApp({
|
|
4503
4908
|
name: prefetchApp.name,
|
|
4504
4909
|
url: prefetchApp.url,
|
|
4505
|
-
scopecss: !((_a = prefetchApp
|
|
4506
|
-
useSandbox: !((
|
|
4507
|
-
useMemoryRouter: !((
|
|
4910
|
+
scopecss: !((_b = (_a = prefetchApp['disable-scopecss']) !== null && _a !== void 0 ? _a : prefetchApp.disableScopecss) !== null && _b !== void 0 ? _b : microApp['disable-scopecss']),
|
|
4911
|
+
useSandbox: !((_d = (_c = prefetchApp['disable-sandbox']) !== null && _c !== void 0 ? _c : prefetchApp.disableSandbox) !== null && _d !== void 0 ? _d : microApp['disable-sandbox']),
|
|
4912
|
+
useMemoryRouter: !((_e = prefetchApp['disable-memory-router']) !== null && _e !== void 0 ? _e : microApp['disable-memory-router']),
|
|
4508
4913
|
});
|
|
4509
4914
|
app.isPrefetch = true;
|
|
4510
4915
|
app.prefetchResolve = resolve;
|
|
@@ -4554,7 +4959,7 @@ function fetchGlobalResources(resources, suffix, cache) {
|
|
|
4554
4959
|
* @param excludeHiddenApp exclude hidden keep-alive app, default is false
|
|
4555
4960
|
* @returns active apps
|
|
4556
4961
|
*/
|
|
4557
|
-
function getActiveApps(excludeHiddenApp) {
|
|
4962
|
+
function getActiveApps(excludeHiddenApp = false) {
|
|
4558
4963
|
const activeApps = [];
|
|
4559
4964
|
appInstanceMap.forEach((app, appName) => {
|
|
4560
4965
|
if (appStates.UNMOUNT !== app.getAppState() &&
|
|
@@ -4650,6 +5055,7 @@ class MicroApp extends EventCenterForBaseApp {
|
|
|
4650
5055
|
this.router = router;
|
|
4651
5056
|
}
|
|
4652
5057
|
start(options) {
|
|
5058
|
+
var _a, _b;
|
|
4653
5059
|
if (!isBrowser || !window.customElements) {
|
|
4654
5060
|
return logError('micro-app is not supported in this environment');
|
|
4655
5061
|
}
|
|
@@ -4675,9 +5081,12 @@ class MicroApp extends EventCenterForBaseApp {
|
|
|
4675
5081
|
// @ts-ignore
|
|
4676
5082
|
this.destory = options.destory;
|
|
4677
5083
|
this.inline = options.inline;
|
|
4678
|
-
this
|
|
4679
|
-
this
|
|
4680
|
-
this
|
|
5084
|
+
this['disable-scopecss'] = (_a = options['disable-scopecss']) !== null && _a !== void 0 ? _a : options.disableScopecss;
|
|
5085
|
+
this['disable-sandbox'] = (_b = options['disable-sandbox']) !== null && _b !== void 0 ? _b : options.disableSandbox;
|
|
5086
|
+
this['disable-memory-router'] = options['disable-memory-router'];
|
|
5087
|
+
this['keep-router-state'] = options['keep-router-state'];
|
|
5088
|
+
this['hidden-router'] = options['hidden-router'];
|
|
5089
|
+
this.esmodule = options.esmodule;
|
|
4681
5090
|
this.ssr = options.ssr;
|
|
4682
5091
|
isFunction(options.fetch) && (this.fetch = options.fetch);
|
|
4683
5092
|
isPlainObject(options.lifeCycles) && (this.lifeCycles = options.lifeCycles);
|