@micro-zoe/micro-app 1.0.0-alpha.1 → 1.0.0-alpha.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 +13 -6
- package/lib/index.esm.js +784 -370
- 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 +3 -1
- package/typings/global.d.ts +78 -10
package/lib/index.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const version = '1.0.0-alpha.
|
|
1
|
+
const version = '1.0.0-alpha.4';
|
|
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
|
|
@@ -270,6 +290,7 @@ function pureCreateElement(tagName, options) {
|
|
|
270
290
|
const element = document.createElement(tagName, options);
|
|
271
291
|
if (element.__MICRO_APP_NAME__)
|
|
272
292
|
delete element.__MICRO_APP_NAME__;
|
|
293
|
+
element.__PURE_ELEMENT__ = true;
|
|
273
294
|
return element;
|
|
274
295
|
}
|
|
275
296
|
/**
|
|
@@ -465,14 +486,82 @@ const globalKeyToBeCached = 'window,self,globalThis,Array,Object,String,Boolean,
|
|
|
465
486
|
* @param config fetch options
|
|
466
487
|
*/
|
|
467
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();
|
|
468
496
|
if (isFunction(microApp.fetch)) {
|
|
469
497
|
return microApp.fetch(url, options, appName);
|
|
470
498
|
}
|
|
471
|
-
|
|
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) => {
|
|
472
501
|
return res.text();
|
|
473
502
|
});
|
|
474
503
|
}
|
|
475
504
|
|
|
505
|
+
class HTMLLoader {
|
|
506
|
+
static getInstance() {
|
|
507
|
+
if (!this.instance) {
|
|
508
|
+
this.instance = new HTMLLoader();
|
|
509
|
+
}
|
|
510
|
+
return this.instance;
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* run logic of load and format html
|
|
514
|
+
* @param successCb success callback
|
|
515
|
+
* @param errorCb error callback, type: (err: Error, meetFetchErr: boolean) => void
|
|
516
|
+
*/
|
|
517
|
+
run(app, successCb) {
|
|
518
|
+
const appName = app.name;
|
|
519
|
+
const htmlUrl = app.ssrUrl || app.url;
|
|
520
|
+
fetchSource(htmlUrl, appName, { cache: 'no-cache' }).then((htmlStr) => {
|
|
521
|
+
if (!htmlStr) {
|
|
522
|
+
const msg = 'html is empty, please check in detail';
|
|
523
|
+
app.onerror(new Error(msg));
|
|
524
|
+
return logError(msg, appName);
|
|
525
|
+
}
|
|
526
|
+
htmlStr = this.formatHTML(htmlUrl, htmlStr, appName);
|
|
527
|
+
successCb(htmlStr, app);
|
|
528
|
+
}).catch((e) => {
|
|
529
|
+
logError(`Failed to fetch data from ${app.url}, micro-app stop rendering`, appName, e);
|
|
530
|
+
app.onLoadError(e);
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
formatHTML(htmlUrl, htmlStr, appName) {
|
|
534
|
+
return this.processHtml(htmlUrl, htmlStr, appName, microApp.plugins)
|
|
535
|
+
.replace(/<head[^>]*>[\s\S]*?<\/head>/i, (match) => {
|
|
536
|
+
return match
|
|
537
|
+
.replace(/<head/i, '<micro-app-head')
|
|
538
|
+
.replace(/<\/head>/i, '</micro-app-head>');
|
|
539
|
+
})
|
|
540
|
+
.replace(/<body[^>]*>[\s\S]*?<\/body>/i, (match) => {
|
|
541
|
+
return match
|
|
542
|
+
.replace(/<body/i, '<micro-app-body')
|
|
543
|
+
.replace(/<\/body>/i, '</micro-app-body>');
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
processHtml(url, code, appName, plugins) {
|
|
547
|
+
var _a;
|
|
548
|
+
if (!plugins)
|
|
549
|
+
return code;
|
|
550
|
+
const mergedPlugins = [];
|
|
551
|
+
plugins.global && mergedPlugins.push(...plugins.global);
|
|
552
|
+
((_a = plugins.modules) === null || _a === void 0 ? void 0 : _a[appName]) && mergedPlugins.push(...plugins.modules[appName]);
|
|
553
|
+
if (mergedPlugins.length > 0) {
|
|
554
|
+
return mergedPlugins.reduce((preCode, plugin) => {
|
|
555
|
+
if (isPlainObject(plugin) && isFunction(plugin.processHtml)) {
|
|
556
|
+
return plugin.processHtml(preCode, url, plugin.options);
|
|
557
|
+
}
|
|
558
|
+
return preCode;
|
|
559
|
+
}, code);
|
|
560
|
+
}
|
|
561
|
+
return code;
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
476
565
|
// common reg
|
|
477
566
|
const rootSelectorREG = /(^|\s+)(html|:root)(?=[\s>~[.#:]+|$)/;
|
|
478
567
|
const bodySelectorREG = /(^|\s+)((html[\s>~]+body)|body)(?=[\s>~[.#:]+|$)/;
|
|
@@ -551,7 +640,7 @@ class CSSParser {
|
|
|
551
640
|
return true;
|
|
552
641
|
}
|
|
553
642
|
formatSelector(skip) {
|
|
554
|
-
const m = this.commonMatch(/^
|
|
643
|
+
const m = this.commonMatch(/^[^{]+/, skip);
|
|
555
644
|
if (!m)
|
|
556
645
|
return false;
|
|
557
646
|
return m[0].replace(/(^|,[\n\s]*)([^,]+)/g, (_, separator, selector) => {
|
|
@@ -631,7 +720,7 @@ class CSSParser {
|
|
|
631
720
|
keyframesRule() {
|
|
632
721
|
if (!this.commonMatch(/^@([-\w]+)?keyframes\s*/))
|
|
633
722
|
return false;
|
|
634
|
-
if (!this.commonMatch(/^
|
|
723
|
+
if (!this.commonMatch(/^[^{]+/))
|
|
635
724
|
return parseError('@keyframes missing name', this.linkPath);
|
|
636
725
|
this.matchComments();
|
|
637
726
|
if (!this.matchOpenBrace())
|
|
@@ -783,7 +872,7 @@ class CSSParser {
|
|
|
783
872
|
}
|
|
784
873
|
// splice string
|
|
785
874
|
recordResult(strFragment) {
|
|
786
|
-
// Firefox
|
|
875
|
+
// Firefox performance degradation when string contain special characters, see https://github.com/micro-zoe/micro-app/issues/256
|
|
787
876
|
if (isFireFox()) {
|
|
788
877
|
this.result += encodeURIComponent(strFragment);
|
|
789
878
|
}
|
|
@@ -1071,6 +1160,27 @@ function fixReactHMRConflict(app) {
|
|
|
1071
1160
|
}
|
|
1072
1161
|
}
|
|
1073
1162
|
}
|
|
1163
|
+
/**
|
|
1164
|
+
* reDefine parentNode of html
|
|
1165
|
+
* Scenes:
|
|
1166
|
+
* 1. element-ui popover.js
|
|
1167
|
+
* if (html.parentNode === document) ...
|
|
1168
|
+
*/
|
|
1169
|
+
function throttleDeferForParentNode(proxyDocument) {
|
|
1170
|
+
const html = globalEnv.rawDocument.firstElementChild;
|
|
1171
|
+
if (html && html.parentNode !== proxyDocument) {
|
|
1172
|
+
setRootParentNode(html, proxyDocument);
|
|
1173
|
+
defer(() => {
|
|
1174
|
+
setRootParentNode(html, globalEnv.rawDocument);
|
|
1175
|
+
});
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
function setRootParentNode(root, value) {
|
|
1179
|
+
Object.defineProperty(root, 'parentNode', {
|
|
1180
|
+
value,
|
|
1181
|
+
configurable: true,
|
|
1182
|
+
});
|
|
1183
|
+
}
|
|
1074
1184
|
|
|
1075
1185
|
// Record element and map element
|
|
1076
1186
|
const dynamicElementInMicroAppMap = new WeakMap();
|
|
@@ -1093,12 +1203,12 @@ function handleNewNode(parent, child, app) {
|
|
|
1093
1203
|
return child;
|
|
1094
1204
|
}
|
|
1095
1205
|
else if (child instanceof HTMLLinkElement) {
|
|
1096
|
-
if (child.hasAttribute('exclude')) {
|
|
1206
|
+
if (child.hasAttribute('exclude') || checkExcludeUrl(child.getAttribute('href'), app.name)) {
|
|
1097
1207
|
const linkReplaceComment = document.createComment('link element with exclude attribute ignored by micro-app');
|
|
1098
1208
|
dynamicElementInMicroAppMap.set(child, linkReplaceComment);
|
|
1099
1209
|
return linkReplaceComment;
|
|
1100
1210
|
}
|
|
1101
|
-
else if (child.hasAttribute('ignore')) {
|
|
1211
|
+
else if (child.hasAttribute('ignore') || checkIgnoreUrl(child.getAttribute('href'), app.name)) {
|
|
1102
1212
|
return child;
|
|
1103
1213
|
}
|
|
1104
1214
|
const { url, info, replaceComment } = extractLinkFromHtml(child, parent, app, true);
|
|
@@ -1208,20 +1318,35 @@ function getMappingNode(node) {
|
|
|
1208
1318
|
* @param rawMethod method
|
|
1209
1319
|
*/
|
|
1210
1320
|
function commonElementHandler(parent, newChild, passiveChild, rawMethod) {
|
|
1211
|
-
|
|
1321
|
+
const currentAppName = getCurrentAppName();
|
|
1322
|
+
if (newChild instanceof Node &&
|
|
1323
|
+
(newChild.__MICRO_APP_NAME__ ||
|
|
1324
|
+
(currentAppName && !newChild.__PURE_ELEMENT__))) {
|
|
1325
|
+
newChild.__MICRO_APP_NAME__ = newChild.__MICRO_APP_NAME__ || currentAppName;
|
|
1212
1326
|
const app = appInstanceMap.get(newChild.__MICRO_APP_NAME__);
|
|
1213
1327
|
if (app === null || app === void 0 ? void 0 : app.container) {
|
|
1328
|
+
if (newChild instanceof Element) {
|
|
1329
|
+
if (/^(img|script)$/i.test(newChild.tagName)) {
|
|
1330
|
+
if (newChild.hasAttribute('src')) {
|
|
1331
|
+
globalEnv.rawSetAttribute.call(newChild, 'src', CompletionPath(newChild.getAttribute('src'), app.url));
|
|
1332
|
+
}
|
|
1333
|
+
if (newChild.hasAttribute('srcset')) {
|
|
1334
|
+
globalEnv.rawSetAttribute.call(newChild, 'srcset', CompletionPath(newChild.getAttribute('srcset'), app.url));
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
else if (/^link$/i.test(newChild.tagName) && newChild.hasAttribute('href')) {
|
|
1338
|
+
globalEnv.rawSetAttribute.call(newChild, 'href', CompletionPath(newChild.getAttribute('href'), app.url));
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1214
1341
|
return invokePrototypeMethod(app, rawMethod, parent, handleNewNode(parent, newChild, app), passiveChild && getMappingNode(passiveChild));
|
|
1215
1342
|
}
|
|
1216
1343
|
else if (rawMethod === globalEnv.rawAppend || rawMethod === globalEnv.rawPrepend) {
|
|
1217
1344
|
return rawMethod.call(parent, newChild);
|
|
1218
1345
|
}
|
|
1219
|
-
return rawMethod.call(parent, newChild, passiveChild);
|
|
1220
1346
|
}
|
|
1221
1347
|
else if (rawMethod === globalEnv.rawAppend || rawMethod === globalEnv.rawPrepend) {
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
const app = appInstanceMap.get(appName);
|
|
1348
|
+
if (!(newChild instanceof Node) && currentAppName) {
|
|
1349
|
+
const app = appInstanceMap.get(currentAppName);
|
|
1225
1350
|
if (app === null || app === void 0 ? void 0 : app.container) {
|
|
1226
1351
|
if (parent === document.head) {
|
|
1227
1352
|
return rawMethod.call(app.container.querySelector('micro-app-head'), newChild);
|
|
@@ -1267,12 +1392,18 @@ function patchElementPrototypeMethods() {
|
|
|
1267
1392
|
};
|
|
1268
1393
|
// prototype methods of delete element👇
|
|
1269
1394
|
Element.prototype.removeChild = function removeChild(oldChild) {
|
|
1395
|
+
var _a;
|
|
1270
1396
|
if (oldChild === null || oldChild === void 0 ? void 0 : oldChild.__MICRO_APP_NAME__) {
|
|
1271
1397
|
const app = appInstanceMap.get(oldChild.__MICRO_APP_NAME__);
|
|
1272
1398
|
if (app === null || app === void 0 ? void 0 : app.container) {
|
|
1273
1399
|
return invokePrototypeMethod(app, globalEnv.rawRemoveChild, this, getMappingNode(oldChild));
|
|
1274
1400
|
}
|
|
1275
|
-
|
|
1401
|
+
try {
|
|
1402
|
+
return globalEnv.rawRemoveChild.call(this, oldChild);
|
|
1403
|
+
}
|
|
1404
|
+
catch (_b) {
|
|
1405
|
+
return (_a = oldChild === null || oldChild === void 0 ? void 0 : oldChild.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(oldChild);
|
|
1406
|
+
}
|
|
1276
1407
|
}
|
|
1277
1408
|
return globalEnv.rawRemoveChild.call(this, oldChild);
|
|
1278
1409
|
};
|
|
@@ -1288,109 +1419,120 @@ function patchElementPrototypeMethods() {
|
|
|
1288
1419
|
* @param element new element
|
|
1289
1420
|
*/
|
|
1290
1421
|
function markElement(element) {
|
|
1291
|
-
const
|
|
1292
|
-
if (
|
|
1293
|
-
element.__MICRO_APP_NAME__ =
|
|
1422
|
+
const currentAppName = getCurrentAppName();
|
|
1423
|
+
if (currentAppName)
|
|
1424
|
+
element.__MICRO_APP_NAME__ = currentAppName;
|
|
1294
1425
|
return element;
|
|
1295
1426
|
}
|
|
1296
1427
|
// methods of document
|
|
1297
1428
|
function patchDocument() {
|
|
1298
1429
|
const rawDocument = globalEnv.rawDocument;
|
|
1430
|
+
const rawRootDocument = globalEnv.rawRootDocument;
|
|
1431
|
+
function getBindTarget(target) {
|
|
1432
|
+
return isProxyDocument(target) ? rawDocument : target;
|
|
1433
|
+
}
|
|
1299
1434
|
// create element 👇
|
|
1300
|
-
|
|
1301
|
-
const element = globalEnv.rawCreateElement.call(this, tagName, options);
|
|
1435
|
+
rawRootDocument.prototype.createElement = function createElement(tagName, options) {
|
|
1436
|
+
const element = globalEnv.rawCreateElement.call(getBindTarget(this), tagName, options);
|
|
1302
1437
|
return markElement(element);
|
|
1303
1438
|
};
|
|
1304
|
-
|
|
1305
|
-
const element = globalEnv.rawCreateElementNS.call(this, namespaceURI, name, options);
|
|
1439
|
+
rawRootDocument.prototype.createElementNS = function createElementNS(namespaceURI, name, options) {
|
|
1440
|
+
const element = globalEnv.rawCreateElementNS.call(getBindTarget(this), namespaceURI, name, options);
|
|
1306
1441
|
return markElement(element);
|
|
1307
1442
|
};
|
|
1308
|
-
|
|
1309
|
-
const element = globalEnv.rawCreateDocumentFragment.call(this);
|
|
1443
|
+
rawRootDocument.prototype.createDocumentFragment = function createDocumentFragment() {
|
|
1444
|
+
const element = globalEnv.rawCreateDocumentFragment.call(getBindTarget(this));
|
|
1310
1445
|
return markElement(element);
|
|
1311
1446
|
};
|
|
1312
1447
|
// query element👇
|
|
1313
1448
|
function querySelector(selectors) {
|
|
1314
1449
|
var _a, _b, _c, _d;
|
|
1315
|
-
const
|
|
1316
|
-
|
|
1317
|
-
|
|
1450
|
+
const _this = getBindTarget(this);
|
|
1451
|
+
const currentAppName = getCurrentAppName();
|
|
1452
|
+
if (!currentAppName ||
|
|
1453
|
+
!((_a = appInstanceMap.get(currentAppName)) === null || _a === void 0 ? void 0 : _a.container) ||
|
|
1318
1454
|
!selectors ||
|
|
1319
1455
|
isUniqueElement(selectors) ||
|
|
1320
1456
|
// see https://github.com/micro-zoe/micro-app/issues/56
|
|
1321
|
-
rawDocument !==
|
|
1322
|
-
return globalEnv.rawQuerySelector.call(
|
|
1457
|
+
rawDocument !== _this) {
|
|
1458
|
+
return globalEnv.rawQuerySelector.call(_this, selectors);
|
|
1323
1459
|
}
|
|
1324
|
-
return (_d = (_c = (_b = appInstanceMap.get(
|
|
1460
|
+
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;
|
|
1325
1461
|
}
|
|
1326
1462
|
function querySelectorAll(selectors) {
|
|
1327
1463
|
var _a, _b, _c, _d;
|
|
1328
|
-
const
|
|
1329
|
-
|
|
1330
|
-
|
|
1464
|
+
const _this = getBindTarget(this);
|
|
1465
|
+
const currentAppName = getCurrentAppName();
|
|
1466
|
+
if (!currentAppName ||
|
|
1467
|
+
!((_a = appInstanceMap.get(currentAppName)) === null || _a === void 0 ? void 0 : _a.container) ||
|
|
1331
1468
|
!selectors ||
|
|
1332
1469
|
isUniqueElement(selectors) ||
|
|
1333
|
-
rawDocument !==
|
|
1334
|
-
return globalEnv.rawQuerySelectorAll.call(
|
|
1470
|
+
rawDocument !== _this) {
|
|
1471
|
+
return globalEnv.rawQuerySelectorAll.call(_this, selectors);
|
|
1335
1472
|
}
|
|
1336
|
-
return (_d = (_c = (_b = appInstanceMap.get(
|
|
1473
|
+
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 : [];
|
|
1337
1474
|
}
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1475
|
+
rawRootDocument.prototype.querySelector = querySelector;
|
|
1476
|
+
rawRootDocument.prototype.querySelectorAll = querySelectorAll;
|
|
1477
|
+
rawRootDocument.prototype.getElementById = function getElementById(key) {
|
|
1478
|
+
const _this = getBindTarget(this);
|
|
1341
1479
|
if (!getCurrentAppName() || isInvalidQuerySelectorKey(key)) {
|
|
1342
|
-
return globalEnv.rawGetElementById.call(
|
|
1480
|
+
return globalEnv.rawGetElementById.call(_this, key);
|
|
1343
1481
|
}
|
|
1344
1482
|
try {
|
|
1345
|
-
return querySelector.call(
|
|
1483
|
+
return querySelector.call(_this, `#${key}`);
|
|
1346
1484
|
}
|
|
1347
1485
|
catch (_a) {
|
|
1348
|
-
return globalEnv.rawGetElementById.call(
|
|
1486
|
+
return globalEnv.rawGetElementById.call(_this, key);
|
|
1349
1487
|
}
|
|
1350
1488
|
};
|
|
1351
|
-
|
|
1489
|
+
rawRootDocument.prototype.getElementsByClassName = function getElementsByClassName(key) {
|
|
1490
|
+
const _this = getBindTarget(this);
|
|
1352
1491
|
if (!getCurrentAppName() || isInvalidQuerySelectorKey(key)) {
|
|
1353
|
-
return globalEnv.rawGetElementsByClassName.call(
|
|
1492
|
+
return globalEnv.rawGetElementsByClassName.call(_this, key);
|
|
1354
1493
|
}
|
|
1355
1494
|
try {
|
|
1356
|
-
return querySelectorAll.call(
|
|
1495
|
+
return querySelectorAll.call(_this, `.${key}`);
|
|
1357
1496
|
}
|
|
1358
1497
|
catch (_a) {
|
|
1359
|
-
return globalEnv.rawGetElementsByClassName.call(
|
|
1498
|
+
return globalEnv.rawGetElementsByClassName.call(_this, key);
|
|
1360
1499
|
}
|
|
1361
1500
|
};
|
|
1362
|
-
|
|
1501
|
+
rawRootDocument.prototype.getElementsByTagName = function getElementsByTagName(key) {
|
|
1363
1502
|
var _a;
|
|
1364
|
-
const
|
|
1365
|
-
|
|
1503
|
+
const _this = getBindTarget(this);
|
|
1504
|
+
const currentAppName = getCurrentAppName();
|
|
1505
|
+
if (!currentAppName ||
|
|
1366
1506
|
isUniqueElement(key) ||
|
|
1367
1507
|
isInvalidQuerySelectorKey(key) ||
|
|
1368
|
-
(!((_a = appInstanceMap.get(
|
|
1369
|
-
return globalEnv.rawGetElementsByTagName.call(
|
|
1508
|
+
(!((_a = appInstanceMap.get(currentAppName)) === null || _a === void 0 ? void 0 : _a.inline) && /^script$/i.test(key))) {
|
|
1509
|
+
return globalEnv.rawGetElementsByTagName.call(_this, key);
|
|
1370
1510
|
}
|
|
1371
1511
|
try {
|
|
1372
|
-
return querySelectorAll.call(
|
|
1512
|
+
return querySelectorAll.call(_this, key);
|
|
1373
1513
|
}
|
|
1374
1514
|
catch (_b) {
|
|
1375
|
-
return globalEnv.rawGetElementsByTagName.call(
|
|
1515
|
+
return globalEnv.rawGetElementsByTagName.call(_this, key);
|
|
1376
1516
|
}
|
|
1377
1517
|
};
|
|
1378
|
-
|
|
1518
|
+
rawRootDocument.prototype.getElementsByName = function getElementsByName(key) {
|
|
1519
|
+
const _this = getBindTarget(this);
|
|
1379
1520
|
if (!getCurrentAppName() || isInvalidQuerySelectorKey(key)) {
|
|
1380
|
-
return globalEnv.rawGetElementsByName.call(
|
|
1521
|
+
return globalEnv.rawGetElementsByName.call(_this, key);
|
|
1381
1522
|
}
|
|
1382
1523
|
try {
|
|
1383
|
-
return querySelectorAll.call(
|
|
1524
|
+
return querySelectorAll.call(_this, `[name=${key}]`);
|
|
1384
1525
|
}
|
|
1385
1526
|
catch (_a) {
|
|
1386
|
-
return globalEnv.rawGetElementsByName.call(
|
|
1527
|
+
return globalEnv.rawGetElementsByName.call(_this, key);
|
|
1387
1528
|
}
|
|
1388
1529
|
};
|
|
1389
1530
|
}
|
|
1390
1531
|
/**
|
|
1391
1532
|
* patchSetAttribute is different from other patch
|
|
1392
|
-
*
|
|
1393
|
-
* it
|
|
1533
|
+
* NOTE:
|
|
1534
|
+
* 1. it not dependent on sandbox
|
|
1535
|
+
* 2. it should exec when first micro-app-element created & release when all app unmounted
|
|
1394
1536
|
*/
|
|
1395
1537
|
let hasRewriteSetAttribute = false;
|
|
1396
1538
|
function patchSetAttribute() {
|
|
@@ -1401,9 +1543,9 @@ function patchSetAttribute() {
|
|
|
1401
1543
|
if (/^micro-app(-\S+)?/i.test(this.tagName) && key === 'data') {
|
|
1402
1544
|
if (isPlainObject(value)) {
|
|
1403
1545
|
const cloneValue = {};
|
|
1404
|
-
Object.getOwnPropertyNames(value).forEach((
|
|
1405
|
-
if (!(isString(
|
|
1406
|
-
cloneValue[
|
|
1546
|
+
Object.getOwnPropertyNames(value).forEach((ownKey) => {
|
|
1547
|
+
if (!(isString(ownKey) && ownKey.indexOf('__') === 0)) {
|
|
1548
|
+
cloneValue[ownKey] = value[ownKey];
|
|
1407
1549
|
}
|
|
1408
1550
|
});
|
|
1409
1551
|
this.data = cloneValue;
|
|
@@ -1412,36 +1554,34 @@ function patchSetAttribute() {
|
|
|
1412
1554
|
logWarn('property data must be an object', this.getAttribute('name'));
|
|
1413
1555
|
}
|
|
1414
1556
|
}
|
|
1415
|
-
else if ((((key === 'src' || key === 'srcset') && /^(img|script)$/i.test(this.tagName)) ||
|
|
1416
|
-
(key === 'href' && /^link$/i.test(this.tagName))) &&
|
|
1417
|
-
this.__MICRO_APP_NAME__ &&
|
|
1418
|
-
appInstanceMap.has(this.__MICRO_APP_NAME__)) {
|
|
1419
|
-
const app = appInstanceMap.get(this.__MICRO_APP_NAME__);
|
|
1420
|
-
globalEnv.rawSetAttribute.call(this, key, CompletionPath(value, app.url));
|
|
1421
|
-
}
|
|
1422
1557
|
else {
|
|
1558
|
+
const appName = this.__MICRO_APP_NAME__ || getCurrentAppName();
|
|
1559
|
+
if (appName &&
|
|
1560
|
+
appInstanceMap.has(appName) &&
|
|
1561
|
+
(((key === 'src' || key === 'srcset') && /^(img|script)$/i.test(this.tagName)) ||
|
|
1562
|
+
(key === 'href' && /^link$/i.test(this.tagName)))) {
|
|
1563
|
+
const app = appInstanceMap.get(appName);
|
|
1564
|
+
value = CompletionPath(value, app.url);
|
|
1565
|
+
}
|
|
1423
1566
|
globalEnv.rawSetAttribute.call(this, key, value);
|
|
1424
1567
|
}
|
|
1425
1568
|
};
|
|
1426
1569
|
}
|
|
1427
|
-
function releasePatchSetAttribute() {
|
|
1428
|
-
hasRewriteSetAttribute = false;
|
|
1429
|
-
Element.prototype.setAttribute = globalEnv.rawSetAttribute;
|
|
1430
|
-
}
|
|
1431
1570
|
function releasePatchDocument() {
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1571
|
+
const rawRootDocument = globalEnv.rawRootDocument;
|
|
1572
|
+
rawRootDocument.prototype.createElement = globalEnv.rawCreateElement;
|
|
1573
|
+
rawRootDocument.prototype.createElementNS = globalEnv.rawCreateElementNS;
|
|
1574
|
+
rawRootDocument.prototype.createDocumentFragment = globalEnv.rawCreateDocumentFragment;
|
|
1575
|
+
rawRootDocument.prototype.querySelector = globalEnv.rawQuerySelector;
|
|
1576
|
+
rawRootDocument.prototype.querySelectorAll = globalEnv.rawQuerySelectorAll;
|
|
1577
|
+
rawRootDocument.prototype.getElementById = globalEnv.rawGetElementById;
|
|
1578
|
+
rawRootDocument.prototype.getElementsByClassName = globalEnv.rawGetElementsByClassName;
|
|
1579
|
+
rawRootDocument.prototype.getElementsByTagName = globalEnv.rawGetElementsByTagName;
|
|
1580
|
+
rawRootDocument.prototype.getElementsByName = globalEnv.rawGetElementsByName;
|
|
1441
1581
|
}
|
|
1442
1582
|
// release patch
|
|
1443
1583
|
function releasePatches() {
|
|
1444
|
-
|
|
1584
|
+
removeDomScope();
|
|
1445
1585
|
releasePatchDocument();
|
|
1446
1586
|
Element.prototype.appendChild = globalEnv.rawAppendChild;
|
|
1447
1587
|
Element.prototype.insertBefore = globalEnv.rawInsertBefore;
|
|
@@ -1451,6 +1591,11 @@ function releasePatches() {
|
|
|
1451
1591
|
Element.prototype.prepend = globalEnv.rawPrepend;
|
|
1452
1592
|
Element.prototype.cloneNode = globalEnv.rawCloneNode;
|
|
1453
1593
|
}
|
|
1594
|
+
// exec when last child unmount
|
|
1595
|
+
function releasePatchSetAttribute() {
|
|
1596
|
+
hasRewriteSetAttribute = false;
|
|
1597
|
+
Element.prototype.setAttribute = globalEnv.rawSetAttribute;
|
|
1598
|
+
}
|
|
1454
1599
|
// Set the style of micro-app-head and micro-app-body
|
|
1455
1600
|
let hasRejectMicroAppStyle = false;
|
|
1456
1601
|
function rejectMicroAppStyle() {
|
|
@@ -1470,6 +1615,10 @@ const globalEnv = {};
|
|
|
1470
1615
|
*/
|
|
1471
1616
|
function initGlobalEnv() {
|
|
1472
1617
|
if (isBrowser) {
|
|
1618
|
+
const rawWindow = Function('return window')();
|
|
1619
|
+
const rawDocument = Function('return document')();
|
|
1620
|
+
const rawRootDocument = Function('return Document')();
|
|
1621
|
+
const supportModuleScript = isSupportModuleScript();
|
|
1473
1622
|
/**
|
|
1474
1623
|
* save patch raw methods
|
|
1475
1624
|
* pay attention to this binding
|
|
@@ -1482,15 +1631,15 @@ function initGlobalEnv() {
|
|
|
1482
1631
|
const rawAppend = Element.prototype.append;
|
|
1483
1632
|
const rawPrepend = Element.prototype.prepend;
|
|
1484
1633
|
const rawCloneNode = Element.prototype.cloneNode;
|
|
1485
|
-
const rawCreateElement =
|
|
1486
|
-
const rawCreateElementNS =
|
|
1487
|
-
const rawCreateDocumentFragment =
|
|
1488
|
-
const rawQuerySelector =
|
|
1489
|
-
const rawQuerySelectorAll =
|
|
1490
|
-
const rawGetElementById =
|
|
1491
|
-
const rawGetElementsByClassName =
|
|
1492
|
-
const rawGetElementsByTagName =
|
|
1493
|
-
const rawGetElementsByName =
|
|
1634
|
+
const rawCreateElement = rawRootDocument.prototype.createElement;
|
|
1635
|
+
const rawCreateElementNS = rawRootDocument.prototype.createElementNS;
|
|
1636
|
+
const rawCreateDocumentFragment = rawRootDocument.prototype.createDocumentFragment;
|
|
1637
|
+
const rawQuerySelector = rawRootDocument.prototype.querySelector;
|
|
1638
|
+
const rawQuerySelectorAll = rawRootDocument.prototype.querySelectorAll;
|
|
1639
|
+
const rawGetElementById = rawRootDocument.prototype.getElementById;
|
|
1640
|
+
const rawGetElementsByClassName = rawRootDocument.prototype.getElementsByClassName;
|
|
1641
|
+
const rawGetElementsByTagName = rawRootDocument.prototype.getElementsByTagName;
|
|
1642
|
+
const rawGetElementsByName = rawRootDocument.prototype.getElementsByName;
|
|
1494
1643
|
const ImageProxy = new Proxy(Image, {
|
|
1495
1644
|
construct(Target, args) {
|
|
1496
1645
|
const elementImage = new Target(...args);
|
|
@@ -1498,9 +1647,6 @@ function initGlobalEnv() {
|
|
|
1498
1647
|
return elementImage;
|
|
1499
1648
|
},
|
|
1500
1649
|
});
|
|
1501
|
-
const rawWindow = Function('return window')();
|
|
1502
|
-
const rawDocument = Function('return document')();
|
|
1503
|
-
const supportModuleScript = isSupportModuleScript();
|
|
1504
1650
|
/**
|
|
1505
1651
|
* save effect raw methods
|
|
1506
1652
|
* pay attention to this binding, especially setInterval, setTimeout, clearInterval, clearTimeout
|
|
@@ -1511,11 +1657,18 @@ function initGlobalEnv() {
|
|
|
1511
1657
|
const rawSetTimeout = rawWindow.setTimeout;
|
|
1512
1658
|
const rawClearInterval = rawWindow.clearInterval;
|
|
1513
1659
|
const rawClearTimeout = rawWindow.clearTimeout;
|
|
1660
|
+
const rawPushState = rawWindow.history.pushState;
|
|
1661
|
+
const rawReplaceState = rawWindow.history.replaceState;
|
|
1514
1662
|
const rawDocumentAddEventListener = rawDocument.addEventListener;
|
|
1515
1663
|
const rawDocumentRemoveEventListener = rawDocument.removeEventListener;
|
|
1516
1664
|
// mark current application as base application
|
|
1517
1665
|
window.__MICRO_APP_BASE_APPLICATION__ = true;
|
|
1518
1666
|
assign(globalEnv, {
|
|
1667
|
+
// common global vars
|
|
1668
|
+
rawWindow,
|
|
1669
|
+
rawDocument,
|
|
1670
|
+
rawRootDocument,
|
|
1671
|
+
supportModuleScript,
|
|
1519
1672
|
// source/patch
|
|
1520
1673
|
rawSetAttribute,
|
|
1521
1674
|
rawAppendChild,
|
|
@@ -1535,10 +1688,6 @@ function initGlobalEnv() {
|
|
|
1535
1688
|
rawGetElementsByTagName,
|
|
1536
1689
|
rawGetElementsByName,
|
|
1537
1690
|
ImageProxy,
|
|
1538
|
-
// common global vars
|
|
1539
|
-
rawWindow,
|
|
1540
|
-
rawDocument,
|
|
1541
|
-
supportModuleScript,
|
|
1542
1691
|
// sandbox/effect
|
|
1543
1692
|
rawWindowAddEventListener,
|
|
1544
1693
|
rawWindowRemoveEventListener,
|
|
@@ -1548,6 +1697,8 @@ function initGlobalEnv() {
|
|
|
1548
1697
|
rawClearTimeout,
|
|
1549
1698
|
rawDocumentAddEventListener,
|
|
1550
1699
|
rawDocumentRemoveEventListener,
|
|
1700
|
+
rawPushState,
|
|
1701
|
+
rawReplaceState,
|
|
1551
1702
|
});
|
|
1552
1703
|
// global effect
|
|
1553
1704
|
rejectMicroAppStyle();
|
|
@@ -1566,11 +1717,14 @@ const globalScripts = new Map();
|
|
|
1566
1717
|
function extractScriptElement(script, parent, app, isDynamic = false) {
|
|
1567
1718
|
let replaceComment = null;
|
|
1568
1719
|
let src = script.getAttribute('src');
|
|
1569
|
-
if (
|
|
1720
|
+
if (src) {
|
|
1721
|
+
src = CompletionPath(src, app.url);
|
|
1722
|
+
}
|
|
1723
|
+
if (script.hasAttribute('exclude') || checkExcludeUrl(src, app.name)) {
|
|
1570
1724
|
replaceComment = document.createComment('script element with exclude attribute removed by micro-app');
|
|
1571
1725
|
}
|
|
1572
|
-
else if ((script.type && !['text/javascript', 'text/ecmascript', 'application/javascript', 'application/ecmascript', 'module'].includes(script.type)) ||
|
|
1573
|
-
script.hasAttribute('ignore')) {
|
|
1726
|
+
else if ((script.type && !['text/javascript', 'text/ecmascript', 'application/javascript', 'application/ecmascript', 'module', 'systemjs-module', 'systemjs-importmap'].includes(script.type)) ||
|
|
1727
|
+
script.hasAttribute('ignore') || checkIgnoreUrl(src, app.name)) {
|
|
1574
1728
|
return null;
|
|
1575
1729
|
}
|
|
1576
1730
|
else if ((globalEnv.supportModuleScript && script.noModule) ||
|
|
@@ -1578,7 +1732,6 @@ function extractScriptElement(script, parent, app, isDynamic = false) {
|
|
|
1578
1732
|
replaceComment = document.createComment(`${script.noModule ? 'noModule' : 'module'} script ignored by micro-app`);
|
|
1579
1733
|
}
|
|
1580
1734
|
else if (src) { // remote script
|
|
1581
|
-
src = CompletionPath(src, app.url);
|
|
1582
1735
|
const info = {
|
|
1583
1736
|
code: '',
|
|
1584
1737
|
isExternal: true,
|
|
@@ -1628,6 +1781,46 @@ function extractScriptElement(script, parent, app, isDynamic = false) {
|
|
|
1628
1781
|
return parent.replaceChild(replaceComment, script);
|
|
1629
1782
|
}
|
|
1630
1783
|
}
|
|
1784
|
+
/**
|
|
1785
|
+
* get assets plugins
|
|
1786
|
+
* @param appName app name
|
|
1787
|
+
*/
|
|
1788
|
+
function getAssetsPlugins(appName) {
|
|
1789
|
+
var _a, _b, _c;
|
|
1790
|
+
const globalPlugins = ((_a = microApp.plugins) === null || _a === void 0 ? void 0 : _a.global) || [];
|
|
1791
|
+
const modulePlugins = ((_c = (_b = microApp.plugins) === null || _b === void 0 ? void 0 : _b.modules) === null || _c === void 0 ? void 0 : _c[appName]) || [];
|
|
1792
|
+
return [...globalPlugins, ...modulePlugins];
|
|
1793
|
+
}
|
|
1794
|
+
/**
|
|
1795
|
+
* whether the url needs to be excluded
|
|
1796
|
+
* @param url css or js link
|
|
1797
|
+
* @param plugins microApp plugins
|
|
1798
|
+
*/
|
|
1799
|
+
function checkExcludeUrl(url, appName) {
|
|
1800
|
+
if (!url)
|
|
1801
|
+
return false;
|
|
1802
|
+
const plugins = getAssetsPlugins(appName) || [];
|
|
1803
|
+
return plugins.some(plugin => {
|
|
1804
|
+
if (!plugin.excludeChecker)
|
|
1805
|
+
return false;
|
|
1806
|
+
return plugin.excludeChecker(url);
|
|
1807
|
+
});
|
|
1808
|
+
}
|
|
1809
|
+
/**
|
|
1810
|
+
* whether the url needs to be ignore
|
|
1811
|
+
* @param url css or js link
|
|
1812
|
+
* @param plugins microApp plugins
|
|
1813
|
+
*/
|
|
1814
|
+
function checkIgnoreUrl(url, appName) {
|
|
1815
|
+
if (!url)
|
|
1816
|
+
return false;
|
|
1817
|
+
const plugins = getAssetsPlugins(appName) || [];
|
|
1818
|
+
return plugins.some(plugin => {
|
|
1819
|
+
if (!plugin.ignoreChecker)
|
|
1820
|
+
return false;
|
|
1821
|
+
return plugin.ignoreChecker(url);
|
|
1822
|
+
});
|
|
1823
|
+
}
|
|
1631
1824
|
/**
|
|
1632
1825
|
* Get remote resources of script
|
|
1633
1826
|
* @param wrapElement htmlDom
|
|
@@ -1768,6 +1961,13 @@ function runDynamicRemoteScript(url, info, app, originScript) {
|
|
|
1768
1961
|
if (app.source.scripts.has(url)) {
|
|
1769
1962
|
const existInfo = app.source.scripts.get(url);
|
|
1770
1963
|
!existInfo.module && defer(dispatchScriptOnLoadEvent);
|
|
1964
|
+
/**
|
|
1965
|
+
* TODO: 这里要改,当script初始化时动态创建远程script时,初次渲染和二次渲染的顺序不一致,会导致错误
|
|
1966
|
+
* 1、url不存在缓存,初始化的时候肯定是要异步请求,那么执行顺序就会靠后,至少落后于html自带的script
|
|
1967
|
+
* 2、url存在缓存,那么二次渲染的时候这里会同步执行,就会先于html自带的script执行
|
|
1968
|
+
* 3、测试一下,初次渲染和二次渲染时,onload的执行时机,是在js执行完成,还是执行之前
|
|
1969
|
+
* 4、将上述问题做成注释,方便后续阅读和理解
|
|
1970
|
+
*/
|
|
1771
1971
|
return runScript(url, app, existInfo, true, dispatchScriptOnLoadEvent);
|
|
1772
1972
|
}
|
|
1773
1973
|
if (globalScripts.has(url)) {
|
|
@@ -1800,7 +2000,7 @@ function runDynamicRemoteScript(url, info, app, originScript) {
|
|
|
1800
2000
|
catch (e) {
|
|
1801
2001
|
console.error(`[micro-app from runDynamicScript] app ${app.name}: `, e, url);
|
|
1802
2002
|
}
|
|
1803
|
-
!info.module &&
|
|
2003
|
+
!info.module && dispatchScriptOnLoadEvent();
|
|
1804
2004
|
}).catch((err) => {
|
|
1805
2005
|
logError(err, app.name);
|
|
1806
2006
|
dispatchOnErrorEvent(originScript);
|
|
@@ -1848,6 +2048,7 @@ function runCode2Function(code, info) {
|
|
|
1848
2048
|
* @param info source script info
|
|
1849
2049
|
*/
|
|
1850
2050
|
function bindScope(url, app, code, info) {
|
|
2051
|
+
// TODO: 增加缓存机制
|
|
1851
2052
|
if (isPlainObject(microApp.plugins)) {
|
|
1852
2053
|
code = usePlugins(url, code, app.name, microApp.plugins, info);
|
|
1853
2054
|
}
|
|
@@ -1904,10 +2105,10 @@ function flatChildren(parent, app, microAppHead) {
|
|
|
1904
2105
|
});
|
|
1905
2106
|
for (const dom of children) {
|
|
1906
2107
|
if (dom instanceof HTMLLinkElement) {
|
|
1907
|
-
if (dom.hasAttribute('exclude')) {
|
|
2108
|
+
if (dom.hasAttribute('exclude') || checkExcludeUrl(dom.getAttribute('href'), app.name)) {
|
|
1908
2109
|
parent.replaceChild(document.createComment('link element with exclude attribute ignored by micro-app'), dom);
|
|
1909
2110
|
}
|
|
1910
|
-
else if (!dom.hasAttribute('ignore')) {
|
|
2111
|
+
else if (!(dom.hasAttribute('ignore') || checkIgnoreUrl(dom.getAttribute('href'), app.name))) {
|
|
1911
2112
|
extractLinkFromHtml(dom, parent, app);
|
|
1912
2113
|
}
|
|
1913
2114
|
else if (dom.hasAttribute('href')) {
|
|
@@ -1961,34 +2162,6 @@ function extractSourceDom(htmlStr, app) {
|
|
|
1961
2162
|
app.onLoad(wrapElement);
|
|
1962
2163
|
}
|
|
1963
2164
|
}
|
|
1964
|
-
/**
|
|
1965
|
-
* Get and format html
|
|
1966
|
-
* @param app app
|
|
1967
|
-
*/
|
|
1968
|
-
function extractHtml(app) {
|
|
1969
|
-
fetchSource(app.ssrUrl || app.url, app.name, { cache: 'no-cache' }).then((htmlStr) => {
|
|
1970
|
-
if (!htmlStr) {
|
|
1971
|
-
const msg = 'html is empty, please check in detail';
|
|
1972
|
-
app.onerror(new Error(msg));
|
|
1973
|
-
return logError(msg, app.name);
|
|
1974
|
-
}
|
|
1975
|
-
htmlStr = htmlStr
|
|
1976
|
-
.replace(/<head[^>]*>[\s\S]*?<\/head>/i, (match) => {
|
|
1977
|
-
return match
|
|
1978
|
-
.replace(/<head/i, '<micro-app-head')
|
|
1979
|
-
.replace(/<\/head>/i, '</micro-app-head>');
|
|
1980
|
-
})
|
|
1981
|
-
.replace(/<body[^>]*>[\s\S]*?<\/body>/i, (match) => {
|
|
1982
|
-
return match
|
|
1983
|
-
.replace(/<body/i, '<micro-app-body')
|
|
1984
|
-
.replace(/<\/body>/i, '</micro-app-body>');
|
|
1985
|
-
});
|
|
1986
|
-
extractSourceDom(htmlStr, app);
|
|
1987
|
-
}).catch((e) => {
|
|
1988
|
-
logError(`Failed to fetch data from ${app.url}, micro-app stop rendering`, app.name, e);
|
|
1989
|
-
app.onLoadError(e);
|
|
1990
|
-
});
|
|
1991
|
-
}
|
|
1992
2165
|
|
|
1993
2166
|
class EventCenter {
|
|
1994
2167
|
constructor() {
|
|
@@ -2271,12 +2444,39 @@ function rebuildDataCenterSnapshot(microAppEventCenter) {
|
|
|
2271
2444
|
}
|
|
2272
2445
|
}
|
|
2273
2446
|
|
|
2447
|
+
// 管理 app 的单例
|
|
2448
|
+
class AppManager {
|
|
2449
|
+
constructor() {
|
|
2450
|
+
// Todo: appInstanceMap 由 AppManager 来创建,不再由 create_app 管理
|
|
2451
|
+
this.appInstanceMap = appInstanceMap;
|
|
2452
|
+
}
|
|
2453
|
+
static getInstance() {
|
|
2454
|
+
if (!this.instance) {
|
|
2455
|
+
this.instance = new AppManager();
|
|
2456
|
+
}
|
|
2457
|
+
return this.instance;
|
|
2458
|
+
}
|
|
2459
|
+
get(appName) {
|
|
2460
|
+
return this.appInstanceMap.get(appName);
|
|
2461
|
+
}
|
|
2462
|
+
set(appName, app) {
|
|
2463
|
+
this.appInstanceMap.set(appName, app);
|
|
2464
|
+
}
|
|
2465
|
+
getAll() {
|
|
2466
|
+
return Array.from(this.appInstanceMap.values());
|
|
2467
|
+
}
|
|
2468
|
+
clear() {
|
|
2469
|
+
this.appInstanceMap.clear();
|
|
2470
|
+
}
|
|
2471
|
+
}
|
|
2472
|
+
|
|
2274
2473
|
function unmountNestedApp() {
|
|
2275
|
-
|
|
2474
|
+
releaseUnmountOfNestedApp();
|
|
2475
|
+
AppManager.getInstance().getAll().forEach(app => {
|
|
2276
2476
|
// @ts-ignore
|
|
2277
2477
|
app.container && getRootContainer(app.container).disconnectedCallback();
|
|
2278
2478
|
});
|
|
2279
|
-
!window.__MICRO_APP_UMD_MODE__ &&
|
|
2479
|
+
!window.__MICRO_APP_UMD_MODE__ && AppManager.getInstance().clear();
|
|
2280
2480
|
}
|
|
2281
2481
|
// release listener
|
|
2282
2482
|
function releaseUnmountOfNestedApp() {
|
|
@@ -2286,7 +2486,7 @@ function releaseUnmountOfNestedApp() {
|
|
|
2286
2486
|
}
|
|
2287
2487
|
// if micro-app run in micro application, delete all next generation application when unmount event received
|
|
2288
2488
|
// unmount event will auto release by sandbox
|
|
2289
|
-
function
|
|
2489
|
+
function initEnvOfNestedApp() {
|
|
2290
2490
|
if (window.__MICRO_APP_ENVIRONMENT__) {
|
|
2291
2491
|
releaseUnmountOfNestedApp();
|
|
2292
2492
|
window.addEventListener('unmount', unmountNestedApp, false);
|
|
@@ -2299,35 +2499,30 @@ function isBoundedFunction(value) {
|
|
|
2299
2499
|
return value.__MICRO_APP_IS_BOUND_FUNCTION__;
|
|
2300
2500
|
return value.__MICRO_APP_IS_BOUND_FUNCTION__ = isBoundFunction(value);
|
|
2301
2501
|
}
|
|
2302
|
-
function
|
|
2303
|
-
var _a;
|
|
2502
|
+
function isConstructorFunction(value) {
|
|
2304
2503
|
if (isBoolean(value.__MICRO_APP_IS_CONSTRUCTOR__))
|
|
2305
2504
|
return value.__MICRO_APP_IS_CONSTRUCTOR__;
|
|
2306
|
-
|
|
2307
|
-
const result = (((_a = value.prototype) === null || _a === void 0 ? void 0 : _a.constructor) === value &&
|
|
2308
|
-
Object.getOwnPropertyNames(value.prototype).length > 1) ||
|
|
2309
|
-
/^function\s+[A-Z]/.test(valueStr) ||
|
|
2310
|
-
/^class\s+/.test(valueStr);
|
|
2311
|
-
return value.__MICRO_APP_IS_CONSTRUCTOR__ = result;
|
|
2505
|
+
return value.__MICRO_APP_IS_CONSTRUCTOR__ = isConstructor(value);
|
|
2312
2506
|
}
|
|
2313
2507
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
2314
|
-
function
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2508
|
+
function bindFunctionToRawObject(rawObject, value, key = 'WINDOW') {
|
|
2509
|
+
const cacheKey = `__MICRO_APP_BOUND_${key}_FUNCTION__`;
|
|
2510
|
+
if (value[cacheKey])
|
|
2511
|
+
return value[cacheKey];
|
|
2512
|
+
if (!isConstructorFunction(value) && !isBoundedFunction(value)) {
|
|
2513
|
+
const bindRawObjectValue = value.bind(rawObject);
|
|
2319
2514
|
for (const key in value) {
|
|
2320
|
-
|
|
2515
|
+
bindRawObjectValue[key] = value[key];
|
|
2321
2516
|
}
|
|
2322
2517
|
if (value.hasOwnProperty('prototype')) {
|
|
2323
|
-
rawDefineProperty(
|
|
2518
|
+
rawDefineProperty(bindRawObjectValue, 'prototype', {
|
|
2324
2519
|
value: value.prototype,
|
|
2325
2520
|
configurable: true,
|
|
2326
2521
|
enumerable: false,
|
|
2327
2522
|
writable: true,
|
|
2328
2523
|
});
|
|
2329
2524
|
}
|
|
2330
|
-
return value
|
|
2525
|
+
return value[cacheKey] = bindRawObjectValue;
|
|
2331
2526
|
}
|
|
2332
2527
|
return value;
|
|
2333
2528
|
}
|
|
@@ -2493,6 +2688,13 @@ function effect(appName, microAppWindow) {
|
|
|
2493
2688
|
let umdIntervalIdMap = new Map();
|
|
2494
2689
|
let umdTimeoutIdMap = new Map();
|
|
2495
2690
|
let umdOnClickHandler;
|
|
2691
|
+
const clearUmdSnapshotData = () => {
|
|
2692
|
+
umdWindowListenerMap.clear();
|
|
2693
|
+
umdIntervalIdMap.clear();
|
|
2694
|
+
umdTimeoutIdMap.clear();
|
|
2695
|
+
umdDocumentListenerMap.clear();
|
|
2696
|
+
umdOnClickHandler = null;
|
|
2697
|
+
};
|
|
2496
2698
|
// record event and timer before exec umdMountHook
|
|
2497
2699
|
const recordUmdEffect = () => {
|
|
2498
2700
|
// record window event
|
|
@@ -2538,13 +2740,12 @@ function effect(appName, microAppWindow) {
|
|
|
2538
2740
|
// rebuild onclick event
|
|
2539
2741
|
umdOnClickHandler && documentClickListMap.set(appName, umdOnClickHandler);
|
|
2540
2742
|
// rebuild document event
|
|
2541
|
-
setCurrentAppName(appName);
|
|
2542
2743
|
umdDocumentListenerMap.forEach((listenerList, type) => {
|
|
2543
2744
|
for (const listener of listenerList) {
|
|
2544
2745
|
document.addEventListener(type, listener, listener === null || listener === void 0 ? void 0 : listener.__MICRO_APP_MARK_OPTIONS__);
|
|
2545
2746
|
}
|
|
2546
2747
|
});
|
|
2547
|
-
|
|
2748
|
+
clearUmdSnapshotData();
|
|
2548
2749
|
};
|
|
2549
2750
|
// release all event listener & interval & timeout when unmount app
|
|
2550
2751
|
const releaseEffect = () => {
|
|
@@ -2591,7 +2792,8 @@ function effect(appName, microAppWindow) {
|
|
|
2591
2792
|
}
|
|
2592
2793
|
|
|
2593
2794
|
// set micro app state to origin state
|
|
2594
|
-
function setMicroState(appName,
|
|
2795
|
+
function setMicroState(appName, microState) {
|
|
2796
|
+
const rawState = globalEnv.rawWindow.history.state;
|
|
2595
2797
|
const additionalState = {
|
|
2596
2798
|
microAppState: assign({}, rawState === null || rawState === void 0 ? void 0 : rawState.microAppState, {
|
|
2597
2799
|
[appName]: microState
|
|
@@ -2614,9 +2816,9 @@ function removeMicroState(appName, rawState) {
|
|
|
2614
2816
|
return assign({}, rawState);
|
|
2615
2817
|
}
|
|
2616
2818
|
// get micro app state form origin state
|
|
2617
|
-
function getMicroState(appName
|
|
2618
|
-
var _a;
|
|
2619
|
-
return ((_a = state === null ||
|
|
2819
|
+
function getMicroState(appName) {
|
|
2820
|
+
var _a, _b;
|
|
2821
|
+
return ((_b = (_a = globalEnv.rawWindow.history.state) === null || _a === void 0 ? void 0 : _a.microAppState) === null || _b === void 0 ? void 0 : _b[appName]) || null;
|
|
2620
2822
|
}
|
|
2621
2823
|
const ENC_AD_RE = /&/g; // %M1
|
|
2622
2824
|
const ENC_EQ_RE = /=/g; // %M2
|
|
@@ -2641,7 +2843,8 @@ function commonDecode(path) {
|
|
|
2641
2843
|
}
|
|
2642
2844
|
// 格式化query参数key,防止与原有参数的冲突
|
|
2643
2845
|
function formatQueryAppName(appName) {
|
|
2644
|
-
return `app-${appName}
|
|
2846
|
+
// return `app-${appName}`
|
|
2847
|
+
return appName;
|
|
2645
2848
|
}
|
|
2646
2849
|
// 根据浏览器url参数,获取当前子应用的path
|
|
2647
2850
|
function getMicroPathFromURL(appName) {
|
|
@@ -2746,7 +2949,10 @@ function addHistoryListener(appName) {
|
|
|
2746
2949
|
const rawWindow = globalEnv.rawWindow;
|
|
2747
2950
|
// handle popstate event and distribute to child app
|
|
2748
2951
|
const popStateHandler = (e) => {
|
|
2749
|
-
|
|
2952
|
+
/**
|
|
2953
|
+
* 1. unmount app & hidden keep-alive app will not receive popstate event
|
|
2954
|
+
* 2. filter out onlyForBrowser
|
|
2955
|
+
*/
|
|
2750
2956
|
if (getActiveApps(true).includes(appName) && !e.onlyForBrowser) {
|
|
2751
2957
|
const microPath = getMicroPathFromURL(appName);
|
|
2752
2958
|
const app = appInstanceMap.get(appName);
|
|
@@ -2761,7 +2967,7 @@ function addHistoryListener(appName) {
|
|
|
2761
2967
|
isHashChange = proxyWindow.location.hash !== oldHash;
|
|
2762
2968
|
}
|
|
2763
2969
|
// dispatch formatted popStateEvent to child
|
|
2764
|
-
dispatchPopStateEventToMicroApp(appName, proxyWindow
|
|
2970
|
+
dispatchPopStateEventToMicroApp(appName, proxyWindow);
|
|
2765
2971
|
// dispatch formatted hashChangeEvent to child when hash change
|
|
2766
2972
|
if (isHashChange)
|
|
2767
2973
|
dispatchHashChangeEventToMicroApp(appName, proxyWindow, oldHref);
|
|
@@ -2780,9 +2986,9 @@ function addHistoryListener(appName) {
|
|
|
2780
2986
|
* @param proxyWindow sandbox window
|
|
2781
2987
|
* @param eventState history.state
|
|
2782
2988
|
*/
|
|
2783
|
-
function dispatchPopStateEventToMicroApp(appName, proxyWindow
|
|
2989
|
+
function dispatchPopStateEventToMicroApp(appName, proxyWindow) {
|
|
2784
2990
|
// create PopStateEvent named popstate-appName with sub app state
|
|
2785
|
-
const newPopStateEvent = new PopStateEvent(formatEventName$1('popstate', appName), { state: getMicroState(appName
|
|
2991
|
+
const newPopStateEvent = new PopStateEvent(formatEventName$1('popstate', appName), { state: getMicroState(appName) });
|
|
2786
2992
|
globalEnv.rawWindow.dispatchEvent(newPopStateEvent);
|
|
2787
2993
|
// call function window.onpopstate if it exists
|
|
2788
2994
|
typeof proxyWindow.onpopstate === 'function' && proxyWindow.onpopstate(newPopStateEvent);
|
|
@@ -2847,37 +3053,44 @@ function createMicroHistory(appName, microLocation) {
|
|
|
2847
3053
|
const rawHistory = globalEnv.rawWindow.history;
|
|
2848
3054
|
function getMicroHistoryMethod(methodName) {
|
|
2849
3055
|
return function (...rests) {
|
|
2850
|
-
if ((
|
|
2851
|
-
(isString(rests[2]) || isURL(rests[2]))) {
|
|
3056
|
+
if (isString(rests[2]) || isURL(rests[2])) {
|
|
2852
3057
|
const targetLocation = createURL(rests[2], microLocation.href);
|
|
2853
3058
|
if (targetLocation.origin === microLocation.origin) {
|
|
2854
|
-
navigateWithNativeEvent(methodName, setMicroPathToURL(appName, targetLocation), true, setMicroState(appName,
|
|
3059
|
+
navigateWithNativeEvent(methodName, setMicroPathToURL(appName, targetLocation), true, setMicroState(appName, rests[0]), rests[1]);
|
|
2855
3060
|
const targetFullPath = targetLocation.pathname + targetLocation.search + targetLocation.hash;
|
|
2856
3061
|
if (targetFullPath !== microLocation.fullPath) {
|
|
2857
3062
|
updateMicroLocation(appName, targetFullPath, microLocation);
|
|
2858
3063
|
}
|
|
3064
|
+
return void 0;
|
|
2859
3065
|
}
|
|
2860
|
-
else {
|
|
2861
|
-
rawHistory[methodName].apply(rawHistory, rests);
|
|
2862
|
-
}
|
|
2863
|
-
}
|
|
2864
|
-
else {
|
|
2865
|
-
rawHistory[methodName].apply(rawHistory, rests);
|
|
2866
3066
|
}
|
|
3067
|
+
nativeHistoryNavigate(methodName, rests[2], rests[0], rests[1]);
|
|
2867
3068
|
};
|
|
2868
3069
|
}
|
|
3070
|
+
const pushState = getMicroHistoryMethod('pushState');
|
|
3071
|
+
const replaceState = getMicroHistoryMethod('replaceState');
|
|
2869
3072
|
return new Proxy(rawHistory, {
|
|
2870
3073
|
get(target, key) {
|
|
2871
3074
|
if (key === 'state') {
|
|
2872
|
-
return getMicroState(appName
|
|
3075
|
+
return getMicroState(appName);
|
|
3076
|
+
}
|
|
3077
|
+
else if (key === 'pushState') {
|
|
3078
|
+
return pushState;
|
|
2873
3079
|
}
|
|
2874
|
-
else if (
|
|
2875
|
-
return
|
|
3080
|
+
else if (key === 'replaceState') {
|
|
3081
|
+
return replaceState;
|
|
2876
3082
|
}
|
|
2877
|
-
|
|
3083
|
+
const rawValue = Reflect.get(target, key);
|
|
3084
|
+
return isFunction(rawValue) ? bindFunctionToRawObject(target, rawValue, 'HISTORY') : rawValue;
|
|
2878
3085
|
},
|
|
2879
3086
|
set(target, key, value) {
|
|
2880
|
-
|
|
3087
|
+
Reflect.set(target, key, value);
|
|
3088
|
+
/**
|
|
3089
|
+
* If the set() method returns false, and the assignment happened in strict-mode code, a TypeError will be thrown.
|
|
3090
|
+
* e.g. history.state = {}
|
|
3091
|
+
* TypeError: 'set' on proxy: trap returned falsish for property 'state'
|
|
3092
|
+
*/
|
|
3093
|
+
return true;
|
|
2881
3094
|
}
|
|
2882
3095
|
});
|
|
2883
3096
|
}
|
|
@@ -2889,12 +3102,13 @@ function createMicroHistory(appName, microLocation) {
|
|
|
2889
3102
|
* @param title history.title, default is ''
|
|
2890
3103
|
*/
|
|
2891
3104
|
function nativeHistoryNavigate(methodName, fullPath, state = null, title = '') {
|
|
2892
|
-
globalEnv.
|
|
3105
|
+
const method = methodName === 'pushState' ? globalEnv.rawPushState : globalEnv.rawReplaceState;
|
|
3106
|
+
method.call(globalEnv.rawWindow.history, state, title, fullPath);
|
|
2893
3107
|
}
|
|
2894
3108
|
/**
|
|
2895
3109
|
* Navigate to new path, and dispatch native popStateEvent/hashChangeEvent to browser
|
|
2896
3110
|
* Use scenes:
|
|
2897
|
-
* 1. mount/unmount through
|
|
3111
|
+
* 1. mount/unmount through attachRouteToBrowserURL with limited popstateEvent
|
|
2898
3112
|
* 2. proxyHistory.pushState/replaceState with limited popstateEvent
|
|
2899
3113
|
* 3. api microApp.router.push/replace
|
|
2900
3114
|
* 4. proxyLocation.hash = xxx
|
|
@@ -2914,19 +3128,20 @@ function navigateWithNativeEvent(methodName, result, onlyForBrowser, state, titl
|
|
|
2914
3128
|
dispatchNativeEvent(onlyForBrowser, oldHref);
|
|
2915
3129
|
}
|
|
2916
3130
|
/**
|
|
2917
|
-
* update browser url when mount/unmount/hidden/show
|
|
3131
|
+
* update browser url when mount/unmount/hidden/show/attachToURL/attachAllToURL
|
|
3132
|
+
* just attach microRoute info to browser, dispatch event to base app(exclude child)
|
|
2918
3133
|
* @param result result of add/remove microApp path on browser url
|
|
2919
3134
|
* @param state history.state
|
|
2920
3135
|
*/
|
|
2921
|
-
function
|
|
3136
|
+
function attachRouteToBrowserURL(result, state) {
|
|
2922
3137
|
navigateWithNativeEvent('replaceState', result, true, state);
|
|
2923
3138
|
}
|
|
2924
3139
|
/**
|
|
2925
3140
|
* When path is same, keep the microAppState in history.state
|
|
2926
|
-
* Fix bug of missing microAppState
|
|
3141
|
+
* Fix bug of missing microAppState when base app is next.js or angular
|
|
2927
3142
|
* @param method history.pushState/replaceState
|
|
2928
3143
|
*/
|
|
2929
|
-
function
|
|
3144
|
+
function reWriteHistoryMethod(method) {
|
|
2930
3145
|
const rawWindow = globalEnv.rawWindow;
|
|
2931
3146
|
return function (...rests) {
|
|
2932
3147
|
var _a;
|
|
@@ -2942,22 +3157,38 @@ function patchHistoryState(method) {
|
|
|
2942
3157
|
}
|
|
2943
3158
|
}
|
|
2944
3159
|
method.apply(rawWindow.history, rests);
|
|
3160
|
+
/**
|
|
3161
|
+
* Attach child router info to browser url when base app navigate with pushState/replaceState
|
|
3162
|
+
* NOTE:
|
|
3163
|
+
* 1. Exec after apply pushState/replaceState
|
|
3164
|
+
* 2. Unable to catch when base app navigate with location
|
|
3165
|
+
* 3. When in nest app, rawPushState/rawReplaceState has been modified by parent
|
|
3166
|
+
* 4.
|
|
3167
|
+
*/
|
|
3168
|
+
getActiveApps(true).forEach(appName => {
|
|
3169
|
+
const app = appInstanceMap.get(appName);
|
|
3170
|
+
if (app.sandBox && app.useMemoryRouter && !getMicroPathFromURL(appName)) {
|
|
3171
|
+
attachRouteToBrowserURL(setMicroPathToURL(appName, app.sandBox.proxyWindow.location), setMicroState(appName, getMicroState(appName)));
|
|
3172
|
+
}
|
|
3173
|
+
});
|
|
3174
|
+
// fix bug for nest app
|
|
3175
|
+
removeDomScope();
|
|
2945
3176
|
};
|
|
2946
3177
|
}
|
|
2947
|
-
let isReWriteHistoryState = false;
|
|
2948
3178
|
/**
|
|
2949
3179
|
* rewrite history.pushState/replaceState
|
|
2950
3180
|
* used to fix the problem that the microAppState maybe missing when mainApp navigate to same path
|
|
2951
3181
|
* e.g: when nextjs, angular receive popstate event, they will use history.replaceState to update browser url with a new state object
|
|
2952
3182
|
*/
|
|
2953
|
-
function
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
3183
|
+
function patchHistory() {
|
|
3184
|
+
const rawWindow = globalEnv.rawWindow;
|
|
3185
|
+
rawWindow.history.pushState = reWriteHistoryMethod(globalEnv.rawPushState);
|
|
3186
|
+
rawWindow.history.replaceState = reWriteHistoryMethod(globalEnv.rawReplaceState);
|
|
3187
|
+
}
|
|
3188
|
+
function releasePatchHistory() {
|
|
3189
|
+
const rawWindow = globalEnv.rawWindow;
|
|
3190
|
+
rawWindow.history.pushState = globalEnv.rawPushState;
|
|
3191
|
+
rawWindow.history.replaceState = globalEnv.rawReplaceState;
|
|
2961
3192
|
}
|
|
2962
3193
|
|
|
2963
3194
|
function createRouterApi() {
|
|
@@ -2969,7 +3200,7 @@ function createRouterApi() {
|
|
|
2969
3200
|
* @param state to.state
|
|
2970
3201
|
*/
|
|
2971
3202
|
function navigateWithRawHistory(appName, methodName, targetLocation, state) {
|
|
2972
|
-
navigateWithNativeEvent(methodName, setMicroPathToURL(appName, targetLocation), false, setMicroState(appName,
|
|
3203
|
+
navigateWithNativeEvent(methodName, setMicroPathToURL(appName, targetLocation), false, setMicroState(appName, state !== null && state !== void 0 ? state : null));
|
|
2973
3204
|
// clear element scope after navigate
|
|
2974
3205
|
removeDomScope();
|
|
2975
3206
|
}
|
|
@@ -2984,11 +3215,11 @@ function createRouterApi() {
|
|
|
2984
3215
|
function createNavigationMethod(replace) {
|
|
2985
3216
|
return function (to) {
|
|
2986
3217
|
const appName = formatAppName(to.name);
|
|
2987
|
-
// console.log(3333333, appInstanceMap.get(appName))
|
|
2988
3218
|
if (appName && isString(to.path)) {
|
|
2989
3219
|
const app = appInstanceMap.get(appName);
|
|
2990
|
-
if (app && !app.sandBox)
|
|
2991
|
-
return logError(`navigation failed,
|
|
3220
|
+
if (app && (!app.sandBox || !app.useMemoryRouter)) {
|
|
3221
|
+
return logError(`navigation failed, memory router of app ${appName} is closed`);
|
|
3222
|
+
}
|
|
2992
3223
|
// active apps, include hidden keep-alive app
|
|
2993
3224
|
if (getActiveApps().includes(appName)) {
|
|
2994
3225
|
const microLocation = app.sandBox.proxyWindow.location;
|
|
@@ -3031,7 +3262,7 @@ function createRouterApi() {
|
|
|
3031
3262
|
* NOTE:
|
|
3032
3263
|
* 1. Modify browser url first, and then run guards,
|
|
3033
3264
|
* consistent with the browser forward & back button
|
|
3034
|
-
* 2.
|
|
3265
|
+
* 2. Prevent the element binding
|
|
3035
3266
|
* @param appName app name
|
|
3036
3267
|
* @param to target location
|
|
3037
3268
|
* @param from old location
|
|
@@ -3065,43 +3296,102 @@ function createRouterApi() {
|
|
|
3065
3296
|
function clearRouterWhenUnmount(appName) {
|
|
3066
3297
|
router.current.delete(appName);
|
|
3067
3298
|
}
|
|
3068
|
-
// defaultPage data
|
|
3069
|
-
const defaultPageRecord = useMapRecord();
|
|
3070
3299
|
/**
|
|
3071
|
-
*
|
|
3300
|
+
* NOTE:
|
|
3301
|
+
* 1. sandbox not open
|
|
3302
|
+
* 2. useMemoryRouter is false
|
|
3303
|
+
*/
|
|
3304
|
+
function commonHandlerForAttachToURL(appName) {
|
|
3305
|
+
const app = appInstanceMap.get(appName);
|
|
3306
|
+
if (app.sandBox && app.useMemoryRouter) {
|
|
3307
|
+
attachRouteToBrowserURL(setMicroPathToURL(appName, app.sandBox.proxyWindow.location), setMicroState(appName, getMicroState(appName)));
|
|
3308
|
+
}
|
|
3309
|
+
}
|
|
3310
|
+
/**
|
|
3311
|
+
* Attach specified active app router info to browser url
|
|
3072
3312
|
* @param appName app name
|
|
3073
|
-
* @param path page path
|
|
3074
3313
|
*/
|
|
3075
|
-
function
|
|
3314
|
+
function attachToURL(appName) {
|
|
3076
3315
|
appName = formatAppName(appName);
|
|
3077
|
-
if (
|
|
3078
|
-
|
|
3079
|
-
|
|
3316
|
+
if (appName && getActiveApps().includes(appName)) {
|
|
3317
|
+
commonHandlerForAttachToURL(appName);
|
|
3318
|
+
}
|
|
3080
3319
|
}
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3320
|
+
/**
|
|
3321
|
+
* Attach all active app router info to browser url
|
|
3322
|
+
* exclude hidden keep-alive app
|
|
3323
|
+
*/
|
|
3324
|
+
function attachAllToURL(includeHiddenApp = false) {
|
|
3325
|
+
getActiveApps(!includeHiddenApp).forEach(appName => commonHandlerForAttachToURL(appName));
|
|
3326
|
+
}
|
|
3327
|
+
function createDefaultPageApi() {
|
|
3328
|
+
// defaultPage data
|
|
3329
|
+
const defaultPageRecord = useMapRecord();
|
|
3330
|
+
/**
|
|
3331
|
+
* defaultPage only effect when mount, and has lower priority than query on browser url
|
|
3332
|
+
* SetDefaultPageOptions {
|
|
3333
|
+
* @param name app name
|
|
3334
|
+
* @param path page path
|
|
3335
|
+
* }
|
|
3336
|
+
*/
|
|
3337
|
+
function setDefaultPage(options) {
|
|
3338
|
+
const appName = formatAppName(options.name);
|
|
3339
|
+
if (!appName || !options.path) {
|
|
3340
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
3341
|
+
if (!appName) {
|
|
3342
|
+
logWarn(`setDefaultPage: invalid appName "${appName}"`);
|
|
3343
|
+
}
|
|
3344
|
+
else {
|
|
3345
|
+
logWarn('setDefaultPage: path is required');
|
|
3346
|
+
}
|
|
3347
|
+
}
|
|
3348
|
+
return noopFalse;
|
|
3349
|
+
}
|
|
3350
|
+
return defaultPageRecord.add(appName, options.path);
|
|
3351
|
+
}
|
|
3352
|
+
function removeDefaultPage(appName) {
|
|
3353
|
+
appName = formatAppName(appName);
|
|
3354
|
+
if (!appName)
|
|
3355
|
+
return false;
|
|
3356
|
+
return defaultPageRecord.delete(appName);
|
|
3357
|
+
}
|
|
3358
|
+
return {
|
|
3359
|
+
setDefaultPage,
|
|
3360
|
+
removeDefaultPage,
|
|
3361
|
+
getDefaultPage: defaultPageRecord.get,
|
|
3362
|
+
};
|
|
3363
|
+
}
|
|
3364
|
+
function createBaseRouterApi() {
|
|
3365
|
+
/**
|
|
3366
|
+
* Record base app router, let child app control base app navigation
|
|
3367
|
+
*/
|
|
3368
|
+
let baseRouterProxy = null;
|
|
3369
|
+
function setBaseAppRouter(baseRouter) {
|
|
3370
|
+
if (isObject(baseRouter)) {
|
|
3371
|
+
baseRouterProxy = new Proxy(baseRouter, {
|
|
3372
|
+
get(target, key) {
|
|
3373
|
+
removeDomScope();
|
|
3374
|
+
const rawValue = Reflect.get(target, key);
|
|
3375
|
+
return isFunction(rawValue) ? bindFunctionToRawObject(target, rawValue, 'BASEROUTER') : rawValue;
|
|
3376
|
+
},
|
|
3377
|
+
set(target, key, value) {
|
|
3378
|
+
Reflect.set(target, key, value);
|
|
3379
|
+
return true;
|
|
3380
|
+
}
|
|
3381
|
+
});
|
|
3382
|
+
}
|
|
3383
|
+
else if (process.env.NODE_ENV !== 'production') {
|
|
3384
|
+
logWarn('setBaseAppRouter: Invalid base router');
|
|
3385
|
+
}
|
|
3386
|
+
}
|
|
3387
|
+
return {
|
|
3388
|
+
setBaseAppRouter,
|
|
3389
|
+
getBaseAppRouter: () => baseRouterProxy,
|
|
3390
|
+
};
|
|
3086
3391
|
}
|
|
3087
3392
|
// Router API for developer
|
|
3088
|
-
const router = {
|
|
3089
|
-
|
|
3090
|
-
encode: encodeMicroPath,
|
|
3091
|
-
decode: decodeMicroPath,
|
|
3092
|
-
push: createNavigationMethod(false),
|
|
3093
|
-
replace: createNavigationMethod(true),
|
|
3094
|
-
go: createRawHistoryMethod('go'),
|
|
3095
|
-
back: createRawHistoryMethod('back'),
|
|
3096
|
-
forward: createRawHistoryMethod('forward'),
|
|
3097
|
-
beforeEach: beforeGuards.add,
|
|
3098
|
-
afterEach: afterGuards.add,
|
|
3099
|
-
// attachToURL: 将指定的子应用路由信息添加到浏览器地址上
|
|
3100
|
-
// attachAllToURL: 将所有正在运行的子应用路由信息添加到浏览器地址上
|
|
3101
|
-
setDefaultPage,
|
|
3102
|
-
removeDefaultPage,
|
|
3103
|
-
getDefaultPage: defaultPageRecord.get,
|
|
3104
|
-
};
|
|
3393
|
+
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,
|
|
3394
|
+
attachAllToURL }, createDefaultPageApi()), createBaseRouterApi());
|
|
3105
3395
|
return {
|
|
3106
3396
|
router,
|
|
3107
3397
|
executeNavigationGuard,
|
|
@@ -3115,56 +3405,6 @@ const shadowLocationKeys = ['href', 'pathname', 'search', 'hash'];
|
|
|
3115
3405
|
const locationKeys = [...shadowLocationKeys, 'host', 'hostname', 'port', 'protocol', 'search'];
|
|
3116
3406
|
// origin, fullPath is necessary for guardLocation
|
|
3117
3407
|
const guardLocationKeys = [...locationKeys, 'origin', 'fullPath'];
|
|
3118
|
-
/**
|
|
3119
|
-
* create guardLocation by microLocation, used for router guard
|
|
3120
|
-
*/
|
|
3121
|
-
function createGuardLocation(appName, microLocation) {
|
|
3122
|
-
const guardLocation = assign({ name: appName }, microLocation);
|
|
3123
|
-
// The prototype values on the URL needs to be manually transferred
|
|
3124
|
-
for (const key of guardLocationKeys)
|
|
3125
|
-
guardLocation[key] = microLocation[key];
|
|
3126
|
-
return guardLocation;
|
|
3127
|
-
}
|
|
3128
|
-
// for updateBrowserURLWithLocation when initial
|
|
3129
|
-
function autoTriggerNavigationGuard(appName, microLocation) {
|
|
3130
|
-
executeNavigationGuard(appName, createGuardLocation(appName, microLocation), createGuardLocation(appName, microLocation));
|
|
3131
|
-
}
|
|
3132
|
-
/**
|
|
3133
|
-
* The following scenes will trigger location update:
|
|
3134
|
-
* 1. pushState/replaceState
|
|
3135
|
-
* 2. popStateEvent
|
|
3136
|
-
* 3. query on browser url when init sub app
|
|
3137
|
-
* 4. set defaultPage when when init sub app
|
|
3138
|
-
* NOTE:
|
|
3139
|
-
* 1. update browser URL first, and then update microLocation
|
|
3140
|
-
* 2. the same fullPath will not trigger router guards
|
|
3141
|
-
* @param appName app name
|
|
3142
|
-
* @param path target path
|
|
3143
|
-
* @param base base url
|
|
3144
|
-
* @param microLocation micro app location
|
|
3145
|
-
* @param type auto prevent
|
|
3146
|
-
*/
|
|
3147
|
-
function updateMicroLocation(appName, path, microLocation, type) {
|
|
3148
|
-
const newLocation = createURL(path, microLocation.href);
|
|
3149
|
-
// record old values of microLocation to `from`
|
|
3150
|
-
const from = createGuardLocation(appName, microLocation);
|
|
3151
|
-
for (const key of locationKeys) {
|
|
3152
|
-
if (shadowLocationKeys.includes(key)) {
|
|
3153
|
-
// reference of shadowLocation
|
|
3154
|
-
microLocation.shadowLocation[key] = newLocation[key];
|
|
3155
|
-
}
|
|
3156
|
-
else {
|
|
3157
|
-
// @ts-ignore reference of microLocation
|
|
3158
|
-
microLocation[key] = newLocation[key];
|
|
3159
|
-
}
|
|
3160
|
-
}
|
|
3161
|
-
// update latest values of microLocation to `to`
|
|
3162
|
-
const to = createGuardLocation(appName, microLocation);
|
|
3163
|
-
// The hook called only when fullPath changed
|
|
3164
|
-
if (type === 'auto' || (from.fullPath !== to.fullPath && type !== 'prevent')) {
|
|
3165
|
-
executeNavigationGuard(appName, to, from);
|
|
3166
|
-
}
|
|
3167
|
-
}
|
|
3168
3408
|
/**
|
|
3169
3409
|
* Create location for microApp, each microApp has only one location object, it is a reference type
|
|
3170
3410
|
* MDN https://developer.mozilla.org/en-US/docs/Web/API/Location
|
|
@@ -3309,6 +3549,56 @@ function createMicroLocation(appName, url) {
|
|
|
3309
3549
|
shadowLocation,
|
|
3310
3550
|
});
|
|
3311
3551
|
}
|
|
3552
|
+
/**
|
|
3553
|
+
* create guardLocation by microLocation, used for router guard
|
|
3554
|
+
*/
|
|
3555
|
+
function createGuardLocation(appName, microLocation) {
|
|
3556
|
+
const guardLocation = assign({ name: appName }, microLocation);
|
|
3557
|
+
// The prototype values on the URL needs to be manually transferred
|
|
3558
|
+
for (const key of guardLocationKeys)
|
|
3559
|
+
guardLocation[key] = microLocation[key];
|
|
3560
|
+
return guardLocation;
|
|
3561
|
+
}
|
|
3562
|
+
// for updateBrowserURLWithLocation when initial
|
|
3563
|
+
function autoTriggerNavigationGuard(appName, microLocation) {
|
|
3564
|
+
executeNavigationGuard(appName, createGuardLocation(appName, microLocation), createGuardLocation(appName, microLocation));
|
|
3565
|
+
}
|
|
3566
|
+
/**
|
|
3567
|
+
* The following scenes will trigger location update:
|
|
3568
|
+
* 1. pushState/replaceState
|
|
3569
|
+
* 2. popStateEvent
|
|
3570
|
+
* 3. query on browser url when init sub app
|
|
3571
|
+
* 4. set defaultPage when when init sub app
|
|
3572
|
+
* NOTE:
|
|
3573
|
+
* 1. update browser URL first, and then update microLocation
|
|
3574
|
+
* 2. the same fullPath will not trigger router guards
|
|
3575
|
+
* @param appName app name
|
|
3576
|
+
* @param path target path
|
|
3577
|
+
* @param base base url
|
|
3578
|
+
* @param microLocation micro app location
|
|
3579
|
+
* @param type auto prevent
|
|
3580
|
+
*/
|
|
3581
|
+
function updateMicroLocation(appName, path, microLocation, type) {
|
|
3582
|
+
const newLocation = createURL(path, microLocation.href);
|
|
3583
|
+
// record old values of microLocation to `from`
|
|
3584
|
+
const from = createGuardLocation(appName, microLocation);
|
|
3585
|
+
for (const key of locationKeys) {
|
|
3586
|
+
if (shadowLocationKeys.includes(key)) {
|
|
3587
|
+
// reference of shadowLocation
|
|
3588
|
+
microLocation.shadowLocation[key] = newLocation[key];
|
|
3589
|
+
}
|
|
3590
|
+
else {
|
|
3591
|
+
// @ts-ignore reference of microLocation
|
|
3592
|
+
microLocation[key] = newLocation[key];
|
|
3593
|
+
}
|
|
3594
|
+
}
|
|
3595
|
+
// update latest values of microLocation to `to`
|
|
3596
|
+
const to = createGuardLocation(appName, microLocation);
|
|
3597
|
+
// The hook called only when fullPath changed
|
|
3598
|
+
if (type === 'auto' || (from.fullPath !== to.fullPath && type !== 'prevent')) {
|
|
3599
|
+
executeNavigationGuard(appName, to, from);
|
|
3600
|
+
}
|
|
3601
|
+
}
|
|
3312
3602
|
|
|
3313
3603
|
/**
|
|
3314
3604
|
* The router system has two operations: read and write
|
|
@@ -3318,7 +3608,6 @@ function createMicroLocation(appName, url) {
|
|
|
3318
3608
|
* @returns MicroRouter
|
|
3319
3609
|
*/
|
|
3320
3610
|
function createMicroRouter(appName, url) {
|
|
3321
|
-
rewriteHistoryState();
|
|
3322
3611
|
const microLocation = createMicroLocation(appName, url);
|
|
3323
3612
|
return {
|
|
3324
3613
|
microLocation,
|
|
@@ -3344,7 +3633,7 @@ function updateBrowserURLWithLocation(appName, microLocation, defaultPage) {
|
|
|
3344
3633
|
if (defaultPage)
|
|
3345
3634
|
updateMicroLocation(appName, defaultPage, microLocation, 'prevent');
|
|
3346
3635
|
// attach microApp route info to browser URL
|
|
3347
|
-
|
|
3636
|
+
attachRouteToBrowserURL(setMicroPathToURL(appName, microLocation), setMicroState(appName, null));
|
|
3348
3637
|
// trigger guards after change browser URL
|
|
3349
3638
|
autoTriggerNavigationGuard(appName, microLocation);
|
|
3350
3639
|
}
|
|
@@ -3368,7 +3657,7 @@ function clearRouteStateFromURL(appName, url, microLocation, keepRouteState) {
|
|
|
3368
3657
|
* called on sandbox.stop or hidden of keep-alive app
|
|
3369
3658
|
*/
|
|
3370
3659
|
function removeStateAndPathFromBrowser(appName) {
|
|
3371
|
-
|
|
3660
|
+
attachRouteToBrowserURL(removeMicroPathFromURL(appName), removeMicroState(appName, globalEnv.rawWindow.history.state));
|
|
3372
3661
|
}
|
|
3373
3662
|
|
|
3374
3663
|
/**
|
|
@@ -3380,13 +3669,21 @@ function removeStateAndPathFromBrowser(appName) {
|
|
|
3380
3669
|
* @param target proxy target
|
|
3381
3670
|
*/
|
|
3382
3671
|
function createMicroFetch(url, target) {
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3672
|
+
const rawFetch = !isUndefined(target) ? target : globalEnv.rawWindow.fetch;
|
|
3673
|
+
if (!isFunction(rawFetch))
|
|
3674
|
+
return rawFetch;
|
|
3386
3675
|
return function microFetch(input, init, ...rests) {
|
|
3387
3676
|
if (isString(input) || isURL(input)) {
|
|
3388
3677
|
input = createURL(input, url).toString();
|
|
3389
3678
|
}
|
|
3679
|
+
/**
|
|
3680
|
+
* When fetch rewrite by baseApp, domScope still active when exec rawWindow.fetch
|
|
3681
|
+
* If baseApp operate dom in fetch, it will cause error
|
|
3682
|
+
* The same for XMLHttpRequest, EventSource
|
|
3683
|
+
* e.g.
|
|
3684
|
+
* baseApp: <script crossorigin src="https://sgm-static.jd.com/sgm-2.8.0.js" name="SGMH5" sid="6f88a6e4ba4b4ae5acef2ec22c075085" appKey="jdb-adminb2b-pc"></script>
|
|
3685
|
+
*/
|
|
3686
|
+
removeDomScope();
|
|
3390
3687
|
return rawFetch.call(globalEnv.rawWindow, input, init, ...rests);
|
|
3391
3688
|
};
|
|
3392
3689
|
}
|
|
@@ -3397,14 +3694,15 @@ function createMicroFetch(url, target) {
|
|
|
3397
3694
|
* @param target proxy target
|
|
3398
3695
|
*/
|
|
3399
3696
|
function createMicroXMLHttpRequest(url, target) {
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3697
|
+
const rawXMLHttpRequest = !isUndefined(target) ? target : globalEnv.rawWindow.XMLHttpRequest;
|
|
3698
|
+
if (!isConstructor(rawXMLHttpRequest))
|
|
3699
|
+
return rawXMLHttpRequest;
|
|
3403
3700
|
return class MicroXMLHttpRequest extends rawXMLHttpRequest {
|
|
3404
3701
|
open(method, reqUrl, ...rests) {
|
|
3405
3702
|
if ((isString(reqUrl) && !/^f(ile|tp):\/\//.test(reqUrl)) || isURL(reqUrl)) {
|
|
3406
3703
|
reqUrl = createURL(reqUrl, url).toString();
|
|
3407
3704
|
}
|
|
3705
|
+
removeDomScope();
|
|
3408
3706
|
super.open(method, reqUrl, ...rests);
|
|
3409
3707
|
}
|
|
3410
3708
|
};
|
|
@@ -3420,14 +3718,15 @@ function useMicroEventSource() {
|
|
|
3420
3718
|
* @param target proxy target
|
|
3421
3719
|
*/
|
|
3422
3720
|
function createMicroEventSource(appName, url, target) {
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3721
|
+
const rawEventSource = !isUndefined(target) ? target : globalEnv.rawWindow.EventSource;
|
|
3722
|
+
if (!isConstructor(rawEventSource))
|
|
3723
|
+
return rawEventSource;
|
|
3426
3724
|
return class MicroEventSource extends rawEventSource {
|
|
3427
3725
|
constructor(eventSourceUrl, eventSourceInitDict, ...rests) {
|
|
3428
3726
|
if (isString(eventSourceUrl) || isURL(eventSourceUrl)) {
|
|
3429
3727
|
eventSourceUrl = createURL(eventSourceUrl, url).toString();
|
|
3430
3728
|
}
|
|
3729
|
+
removeDomScope();
|
|
3431
3730
|
super(eventSourceUrl, eventSourceInitDict, ...rests);
|
|
3432
3731
|
if (eventSourceMap) {
|
|
3433
3732
|
const eventSourceList = eventSourceMap.get(appName);
|
|
@@ -3479,6 +3778,8 @@ class SandBox {
|
|
|
3479
3778
|
this.injectedKeys = new Set();
|
|
3480
3779
|
// Properties escape to rawWindow, cleared when unmount
|
|
3481
3780
|
this.escapeKeys = new Set();
|
|
3781
|
+
// record injected values before the first execution of umdHookMount and rebuild before remount umd app
|
|
3782
|
+
// private recordUmdInjectedValues?: Map<PropertyKey, unknown>
|
|
3482
3783
|
// sandbox state
|
|
3483
3784
|
this.active = false;
|
|
3484
3785
|
this.microAppWindow = {}; // Proxy target
|
|
@@ -3492,7 +3793,8 @@ class SandBox {
|
|
|
3492
3793
|
// inject global properties
|
|
3493
3794
|
this.initStaticGlobalKeys(this.microAppWindow, appName, url, useMemoryRouter);
|
|
3494
3795
|
}
|
|
3495
|
-
|
|
3796
|
+
// TODO: 重构
|
|
3797
|
+
start(umdMode = false, baseRoute = '', useMemoryRouter = true, defaultPage = '', disablePatchRequest = false) {
|
|
3496
3798
|
if (!this.active) {
|
|
3497
3799
|
this.active = true;
|
|
3498
3800
|
if (useMemoryRouter) {
|
|
@@ -3503,17 +3805,23 @@ class SandBox {
|
|
|
3503
3805
|
else {
|
|
3504
3806
|
this.microAppWindow.__MICRO_APP_BASE_ROUTE__ = this.microAppWindow.__MICRO_APP_BASE_URL__ = baseRoute;
|
|
3505
3807
|
}
|
|
3506
|
-
|
|
3507
|
-
|
|
3808
|
+
/**
|
|
3809
|
+
* 1. prevent the key deleted during sandBox.stop after rewrite
|
|
3810
|
+
* 2. umd mode will not delete any keys during sandBox.stop
|
|
3811
|
+
*/
|
|
3812
|
+
if (!umdMode) {
|
|
3813
|
+
this.initGlobalKeysWhenStart(this.microAppWindow, this.proxyWindow.__MICRO_APP_NAME__, this.proxyWindow.__MICRO_APP_URL__, disablePatchRequest);
|
|
3814
|
+
}
|
|
3508
3815
|
if (++SandBox.activeCount === 1) {
|
|
3509
3816
|
effectDocumentEvent();
|
|
3510
3817
|
patchElementPrototypeMethods();
|
|
3511
|
-
|
|
3818
|
+
initEnvOfNestedApp();
|
|
3819
|
+
patchHistory();
|
|
3512
3820
|
}
|
|
3513
3821
|
fixBabelPolyfill6();
|
|
3514
3822
|
}
|
|
3515
3823
|
}
|
|
3516
|
-
stop(keepRouteState, clearEventSource) {
|
|
3824
|
+
stop(umdMode, keepRouteState, clearEventSource) {
|
|
3517
3825
|
if (this.active) {
|
|
3518
3826
|
this.releaseEffect();
|
|
3519
3827
|
this.microAppWindow.microApp.clearDataListener();
|
|
@@ -3530,37 +3838,41 @@ class SandBox {
|
|
|
3530
3838
|
* NOTE:
|
|
3531
3839
|
* 1. injectedKeys and escapeKeys must be placed at the back
|
|
3532
3840
|
* 2. if key in initial microAppWindow, and then rewrite, this key will be delete from microAppWindow when stop, and lost when restart
|
|
3841
|
+
* 3. umd mode will not delete global keys
|
|
3533
3842
|
*/
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3843
|
+
if (!umdMode) {
|
|
3844
|
+
this.injectedKeys.forEach((key) => {
|
|
3845
|
+
Reflect.deleteProperty(this.microAppWindow, key);
|
|
3846
|
+
});
|
|
3847
|
+
this.injectedKeys.clear();
|
|
3848
|
+
this.escapeKeys.forEach((key) => {
|
|
3849
|
+
Reflect.deleteProperty(globalEnv.rawWindow, key);
|
|
3850
|
+
});
|
|
3851
|
+
this.escapeKeys.clear();
|
|
3852
|
+
}
|
|
3542
3853
|
if (--SandBox.activeCount === 0) {
|
|
3543
3854
|
releaseEffectDocumentEvent();
|
|
3544
3855
|
releasePatches();
|
|
3856
|
+
releasePatchHistory();
|
|
3545
3857
|
}
|
|
3546
3858
|
this.active = false;
|
|
3547
3859
|
}
|
|
3548
3860
|
}
|
|
3549
3861
|
// record umd snapshot before the first execution of umdHookMount
|
|
3550
3862
|
recordUmdSnapshot() {
|
|
3551
|
-
this.microAppWindow.__MICRO_APP_UMD_MODE__ = true
|
|
3863
|
+
// this.microAppWindow.__MICRO_APP_UMD_MODE__ = true
|
|
3552
3864
|
this.recordUmdEffect();
|
|
3553
3865
|
recordDataCenterSnapshot(this.microAppWindow.microApp);
|
|
3554
|
-
this.recordUmdInjectedValues = new Map()
|
|
3555
|
-
this.injectedKeys.forEach((key) => {
|
|
3556
|
-
|
|
3557
|
-
})
|
|
3866
|
+
// this.recordUmdInjectedValues = new Map<PropertyKey, unknown>()
|
|
3867
|
+
// this.injectedKeys.forEach((key: PropertyKey) => {
|
|
3868
|
+
// this.recordUmdInjectedValues!.set(key, Reflect.get(this.microAppWindow, key))
|
|
3869
|
+
// })
|
|
3558
3870
|
}
|
|
3559
3871
|
// rebuild umd snapshot before remount umd app
|
|
3560
3872
|
rebuildUmdSnapshot() {
|
|
3561
|
-
this.recordUmdInjectedValues
|
|
3562
|
-
|
|
3563
|
-
})
|
|
3873
|
+
// this.recordUmdInjectedValues!.forEach((value: unknown, key: PropertyKey) => {
|
|
3874
|
+
// Reflect.set(this.proxyWindow, key, value)
|
|
3875
|
+
// })
|
|
3564
3876
|
this.rebuildUmdEffect();
|
|
3565
3877
|
rebuildDataCenterSnapshot(this.microAppWindow.microApp);
|
|
3566
3878
|
}
|
|
@@ -3604,7 +3916,7 @@ class SandBox {
|
|
|
3604
3916
|
this.scopeProperties.includes(key))
|
|
3605
3917
|
return Reflect.get(target, key);
|
|
3606
3918
|
const rawValue = Reflect.get(rawWindow, key);
|
|
3607
|
-
return isFunction(rawValue) ?
|
|
3919
|
+
return isFunction(rawValue) ? bindFunctionToRawObject(rawWindow, rawValue) : rawValue;
|
|
3608
3920
|
},
|
|
3609
3921
|
set: (target, key, value) => {
|
|
3610
3922
|
if (this.active) {
|
|
@@ -3704,20 +4016,33 @@ class SandBox {
|
|
|
3704
4016
|
pureCreateElement,
|
|
3705
4017
|
router,
|
|
3706
4018
|
});
|
|
4019
|
+
this.setProxyDocument(microAppWindow, appName);
|
|
3707
4020
|
this.setMappingPropertiesWithRawDescriptor(microAppWindow);
|
|
3708
4021
|
if (useMemoryRouter)
|
|
3709
4022
|
this.setMicroAppRouter(microAppWindow, appName, url);
|
|
3710
4023
|
}
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
4024
|
+
setProxyDocument(microAppWindow, appName) {
|
|
4025
|
+
const { proxyDocument, MicroDocument } = this.createProxyDocument(appName);
|
|
4026
|
+
rawDefineProperties(microAppWindow, {
|
|
4027
|
+
document: {
|
|
4028
|
+
configurable: false,
|
|
4029
|
+
enumerable: true,
|
|
4030
|
+
get() {
|
|
4031
|
+
throttleDeferForSetAppName(appName);
|
|
4032
|
+
// return globalEnv.rawDocument
|
|
4033
|
+
return proxyDocument;
|
|
4034
|
+
},
|
|
4035
|
+
},
|
|
4036
|
+
Document: {
|
|
4037
|
+
configurable: false,
|
|
4038
|
+
enumerable: false,
|
|
4039
|
+
get() {
|
|
4040
|
+
throttleDeferForSetAppName(appName);
|
|
4041
|
+
// return globalEnv.rawRootDocument
|
|
4042
|
+
return MicroDocument;
|
|
4043
|
+
},
|
|
4044
|
+
}
|
|
4045
|
+
});
|
|
3721
4046
|
}
|
|
3722
4047
|
// properties associated with the native window
|
|
3723
4048
|
setMappingPropertiesWithRawDescriptor(microAppWindow) {
|
|
@@ -3746,18 +4071,23 @@ class SandBox {
|
|
|
3746
4071
|
};
|
|
3747
4072
|
return descriptor;
|
|
3748
4073
|
}
|
|
4074
|
+
/**
|
|
4075
|
+
* init global properties of microAppWindow when exec sandBox.start
|
|
4076
|
+
* @param microAppWindow micro window
|
|
4077
|
+
* @param appName app name
|
|
4078
|
+
* @param url app url
|
|
4079
|
+
* @param disablePatchRequest prevent rewrite request method of child app
|
|
4080
|
+
*/
|
|
4081
|
+
initGlobalKeysWhenStart(microAppWindow, appName, url, disablePatchRequest) {
|
|
4082
|
+
microAppWindow.hasOwnProperty = (key) => rawHasOwnProperty.call(microAppWindow, key) || rawHasOwnProperty.call(globalEnv.rawWindow, key);
|
|
4083
|
+
this.setHijackProperty(microAppWindow, appName);
|
|
4084
|
+
if (!disablePatchRequest)
|
|
4085
|
+
this.patchRequestApi(microAppWindow, appName, url);
|
|
4086
|
+
}
|
|
3749
4087
|
// set hijack Properties to microAppWindow
|
|
3750
|
-
|
|
4088
|
+
setHijackProperty(microAppWindow, appName) {
|
|
3751
4089
|
let modifiedEval, modifiedImage;
|
|
3752
4090
|
rawDefineProperties(microAppWindow, {
|
|
3753
|
-
document: {
|
|
3754
|
-
configurable: true,
|
|
3755
|
-
enumerable: true,
|
|
3756
|
-
get() {
|
|
3757
|
-
throttleDeferForSetAppName(appName);
|
|
3758
|
-
return globalEnv.rawDocument;
|
|
3759
|
-
},
|
|
3760
|
-
},
|
|
3761
4091
|
eval: {
|
|
3762
4092
|
configurable: true,
|
|
3763
4093
|
enumerable: false,
|
|
@@ -3783,7 +4113,7 @@ class SandBox {
|
|
|
3783
4113
|
});
|
|
3784
4114
|
}
|
|
3785
4115
|
// rewrite fetch, XMLHttpRequest, EventSource
|
|
3786
|
-
|
|
4116
|
+
patchRequestApi(microAppWindow, appName, url) {
|
|
3787
4117
|
let microFetch = createMicroFetch(url);
|
|
3788
4118
|
let microXMLHttpRequest = createMicroXMLHttpRequest(url);
|
|
3789
4119
|
let microEventSource = createMicroEventSource(appName, url);
|
|
@@ -3855,6 +4185,76 @@ class SandBox {
|
|
|
3855
4185
|
removeRouteInfoForKeepAliveApp() {
|
|
3856
4186
|
removeStateAndPathFromBrowser(this.proxyWindow.__MICRO_APP_NAME__);
|
|
3857
4187
|
}
|
|
4188
|
+
/**
|
|
4189
|
+
* Create new document and Document
|
|
4190
|
+
*/
|
|
4191
|
+
createProxyDocument(appName) {
|
|
4192
|
+
const rawDocument = globalEnv.rawDocument;
|
|
4193
|
+
const rawRootDocument = globalEnv.rawRootDocument;
|
|
4194
|
+
const createElement = function (tagName, options) {
|
|
4195
|
+
const element = globalEnv.rawCreateElement.call(rawDocument, tagName, options);
|
|
4196
|
+
element.__MICRO_APP_NAME__ = appName;
|
|
4197
|
+
return element;
|
|
4198
|
+
};
|
|
4199
|
+
const proxyDocument = new Proxy(rawDocument, {
|
|
4200
|
+
get(target, key) {
|
|
4201
|
+
throttleDeferForSetAppName(appName);
|
|
4202
|
+
throttleDeferForParentNode(proxyDocument);
|
|
4203
|
+
if (key === 'createElement')
|
|
4204
|
+
return createElement;
|
|
4205
|
+
if (key === Symbol.toStringTag)
|
|
4206
|
+
return 'ProxyDocument';
|
|
4207
|
+
const rawValue = Reflect.get(target, key);
|
|
4208
|
+
return isFunction(rawValue) ? bindFunctionToRawObject(rawDocument, rawValue, 'DOCUMENT') : rawValue;
|
|
4209
|
+
},
|
|
4210
|
+
set(target, key, value) {
|
|
4211
|
+
// Fix TypeError: Illegal invocation when set document.title
|
|
4212
|
+
Reflect.set(target, key, value);
|
|
4213
|
+
/**
|
|
4214
|
+
* If the set method returns false, and the assignment happened in strict-mode code, a TypeError will be thrown.
|
|
4215
|
+
*/
|
|
4216
|
+
return true;
|
|
4217
|
+
}
|
|
4218
|
+
});
|
|
4219
|
+
class MicroDocument {
|
|
4220
|
+
static [Symbol.hasInstance](target) {
|
|
4221
|
+
let proto = target;
|
|
4222
|
+
while (proto = Object.getPrototypeOf(proto)) {
|
|
4223
|
+
if (proto === MicroDocument.prototype) {
|
|
4224
|
+
return true;
|
|
4225
|
+
}
|
|
4226
|
+
}
|
|
4227
|
+
return (target === proxyDocument ||
|
|
4228
|
+
target instanceof rawRootDocument);
|
|
4229
|
+
}
|
|
4230
|
+
}
|
|
4231
|
+
/**
|
|
4232
|
+
* TIP:
|
|
4233
|
+
* 1. child class __proto__, which represents the inherit of the constructor, always points to the parent class
|
|
4234
|
+
* 2. child class prototype.__proto__, which represents the inherit of methods, always points to parent class prototype
|
|
4235
|
+
* e.g.
|
|
4236
|
+
* class B extends A {}
|
|
4237
|
+
* B.__proto__ === A // true
|
|
4238
|
+
* B.prototype.__proto__ === A.prototype // true
|
|
4239
|
+
*/
|
|
4240
|
+
Object.setPrototypeOf(MicroDocument, rawRootDocument);
|
|
4241
|
+
// Object.create(rawRootDocument.prototype) will cause MicroDocument and proxyDocument methods not same when exec Document.prototype.xxx = xxx in child app
|
|
4242
|
+
Object.setPrototypeOf(MicroDocument.prototype, new Proxy(rawRootDocument.prototype, {
|
|
4243
|
+
get(target, key) {
|
|
4244
|
+
throttleDeferForSetAppName(appName);
|
|
4245
|
+
const rawValue = Reflect.get(target, key);
|
|
4246
|
+
return isFunction(rawValue) ? bindFunctionToRawObject(rawDocument, rawValue, 'DOCUMENT') : rawValue;
|
|
4247
|
+
},
|
|
4248
|
+
set(target, key, value) {
|
|
4249
|
+
Reflect.set(target, key, value);
|
|
4250
|
+
return true;
|
|
4251
|
+
}
|
|
4252
|
+
}));
|
|
4253
|
+
return {
|
|
4254
|
+
proxyDocument,
|
|
4255
|
+
MicroDocument,
|
|
4256
|
+
};
|
|
4257
|
+
}
|
|
3858
4258
|
}
|
|
3859
4259
|
SandBox.activeCount = 0; // number of active sandbox
|
|
3860
4260
|
|
|
@@ -3922,7 +4322,7 @@ function dispatchCustomEventToMicroApp(eventName, appName, detail = {}) {
|
|
|
3922
4322
|
// micro app instances
|
|
3923
4323
|
const appInstanceMap = new Map();
|
|
3924
4324
|
class CreateApp {
|
|
3925
|
-
constructor({ name, url, ssrUrl, container, inline, scopecss, useSandbox, useMemoryRouter, baseroute, keepRouteState, defaultPage, }) {
|
|
4325
|
+
constructor({ name, url, ssrUrl, container, inline, scopecss, useSandbox, useMemoryRouter, baseroute, keepRouteState, hiddenRouter, defaultPage, disablePatchRequest, }) {
|
|
3926
4326
|
this.state = appStates.CREATED;
|
|
3927
4327
|
this.keepAliveState = null;
|
|
3928
4328
|
this.keepAliveContainer = null;
|
|
@@ -3935,18 +4335,20 @@ class CreateApp {
|
|
|
3935
4335
|
this.prefetchResolve = null;
|
|
3936
4336
|
this.container = null;
|
|
3937
4337
|
this.sandBox = null;
|
|
3938
|
-
this.container = container !== null && container !== void 0 ? container : null;
|
|
3939
|
-
this.inline = inline !== null && inline !== void 0 ? inline : false;
|
|
3940
|
-
this.baseroute = baseroute !== null && baseroute !== void 0 ? baseroute : '';
|
|
3941
|
-
this.keepRouteState = keepRouteState !== null && keepRouteState !== void 0 ? keepRouteState : false;
|
|
3942
|
-
this.ssrUrl = ssrUrl !== null && ssrUrl !== void 0 ? ssrUrl : '';
|
|
3943
|
-
// optional during init👆
|
|
3944
4338
|
this.name = name;
|
|
3945
4339
|
this.url = url;
|
|
3946
4340
|
this.useSandbox = useSandbox;
|
|
3947
4341
|
this.scopecss = this.useSandbox && scopecss;
|
|
3948
4342
|
this.useMemoryRouter = this.useSandbox && useMemoryRouter;
|
|
4343
|
+
// optional during init base on prefetch 👇
|
|
4344
|
+
this.container = container !== null && container !== void 0 ? container : null;
|
|
4345
|
+
this.ssrUrl = ssrUrl !== null && ssrUrl !== void 0 ? ssrUrl : '';
|
|
4346
|
+
this.inline = inline !== null && inline !== void 0 ? inline : false;
|
|
4347
|
+
this.baseroute = baseroute !== null && baseroute !== void 0 ? baseroute : '';
|
|
4348
|
+
this.keepRouteState = keepRouteState !== null && keepRouteState !== void 0 ? keepRouteState : false;
|
|
4349
|
+
this.hiddenRouter = hiddenRouter !== null && hiddenRouter !== void 0 ? hiddenRouter : false;
|
|
3949
4350
|
this.defaultPage = defaultPage !== null && defaultPage !== void 0 ? defaultPage : '';
|
|
4351
|
+
this.disablePatchRequest = disablePatchRequest !== null && disablePatchRequest !== void 0 ? disablePatchRequest : false;
|
|
3950
4352
|
this.source = {
|
|
3951
4353
|
links: new Map(),
|
|
3952
4354
|
scripts: new Map(),
|
|
@@ -3957,7 +4359,7 @@ class CreateApp {
|
|
|
3957
4359
|
// Load resources
|
|
3958
4360
|
loadSourceCode() {
|
|
3959
4361
|
this.state = appStates.LOADING;
|
|
3960
|
-
|
|
4362
|
+
HTMLLoader.getInstance().run(this, extractSourceDom);
|
|
3961
4363
|
}
|
|
3962
4364
|
/**
|
|
3963
4365
|
* When resource is loaded, mount app if it is not prefetch or unmount
|
|
@@ -3997,17 +4399,17 @@ class CreateApp {
|
|
|
3997
4399
|
* @param inline js runs in inline mode
|
|
3998
4400
|
* @param baseroute route prefix, default is ''
|
|
3999
4401
|
* @param keepRouteState keep route state when unmount, default is false
|
|
4402
|
+
* @param disablePatchRequest prevent rewrite request method of child app
|
|
4000
4403
|
*/
|
|
4001
|
-
mount(container, inline, baseroute, keepRouteState, defaultPage) {
|
|
4404
|
+
mount(container, inline, baseroute, keepRouteState, defaultPage, hiddenRouter, disablePatchRequest) {
|
|
4002
4405
|
var _a, _b, _c;
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
// keepRouteState effective on unmount
|
|
4006
|
-
if (isBoolean(keepRouteState))
|
|
4007
|
-
this.keepRouteState = keepRouteState;
|
|
4406
|
+
this.inline = inline !== null && inline !== void 0 ? inline : this.inline;
|
|
4407
|
+
this.keepRouteState = keepRouteState !== null && keepRouteState !== void 0 ? keepRouteState : this.keepRouteState;
|
|
4008
4408
|
this.container = (_a = this.container) !== null && _a !== void 0 ? _a : container;
|
|
4009
4409
|
this.baseroute = baseroute !== null && baseroute !== void 0 ? baseroute : this.baseroute;
|
|
4010
4410
|
this.defaultPage = defaultPage !== null && defaultPage !== void 0 ? defaultPage : this.defaultPage;
|
|
4411
|
+
this.hiddenRouter = hiddenRouter !== null && hiddenRouter !== void 0 ? hiddenRouter : this.hiddenRouter;
|
|
4412
|
+
this.disablePatchRequest = disablePatchRequest !== null && disablePatchRequest !== void 0 ? disablePatchRequest : this.disablePatchRequest;
|
|
4011
4413
|
if (this.loadSourceLevel !== 2) {
|
|
4012
4414
|
this.state = appStates.LOADING;
|
|
4013
4415
|
return;
|
|
@@ -4015,13 +4417,12 @@ class CreateApp {
|
|
|
4015
4417
|
dispatchLifecyclesEvent(this.container, this.name, lifeCycles.BEFOREMOUNT);
|
|
4016
4418
|
this.state = appStates.MOUNTING;
|
|
4017
4419
|
cloneContainer(this.source.html, this.container, !this.umdMode);
|
|
4018
|
-
(_b = this.sandBox) === null || _b === void 0 ? void 0 : _b.start(this.baseroute, this.useMemoryRouter, this.defaultPage);
|
|
4420
|
+
(_b = this.sandBox) === null || _b === void 0 ? void 0 : _b.start(this.umdMode, this.baseroute, this.useMemoryRouter, this.defaultPage, this.disablePatchRequest);
|
|
4019
4421
|
let umdHookMountResult; // result of mount function
|
|
4020
4422
|
if (!this.umdMode) {
|
|
4021
4423
|
let hasDispatchMountedEvent = false;
|
|
4022
4424
|
// if all js are executed, param isFinished will be true
|
|
4023
4425
|
execScripts(this.source.scripts, this, (isFinished) => {
|
|
4024
|
-
var _a;
|
|
4025
4426
|
if (!this.umdMode) {
|
|
4026
4427
|
const { mount, unmount } = this.getUmdLibraryHooks();
|
|
4027
4428
|
// if mount & unmount is function, the sub app is umd mode
|
|
@@ -4029,7 +4430,9 @@ class CreateApp {
|
|
|
4029
4430
|
this.umdHookMount = mount;
|
|
4030
4431
|
this.umdHookUnmount = unmount;
|
|
4031
4432
|
this.umdMode = true;
|
|
4032
|
-
(
|
|
4433
|
+
if (this.sandBox)
|
|
4434
|
+
this.sandBox.proxyWindow.__MICRO_APP_UMD_MODE__ = true;
|
|
4435
|
+
// this.sandBox?.recordUmdSnapshot()
|
|
4033
4436
|
try {
|
|
4034
4437
|
umdHookMountResult = this.umdHookMount();
|
|
4035
4438
|
}
|
|
@@ -4131,20 +4534,23 @@ class CreateApp {
|
|
|
4131
4534
|
* @param unmountcb callback of unmount
|
|
4132
4535
|
*/
|
|
4133
4536
|
actionsForUnmount(destroy, unmountcb) {
|
|
4134
|
-
var _a;
|
|
4537
|
+
var _a, _b;
|
|
4135
4538
|
if (destroy) {
|
|
4136
4539
|
this.actionsForCompletelyDestroy();
|
|
4137
4540
|
}
|
|
4138
4541
|
else if (this.umdMode && this.container.childElementCount) {
|
|
4139
4542
|
cloneContainer(this.container, this.source.html, false);
|
|
4140
4543
|
}
|
|
4544
|
+
if (this.umdMode) {
|
|
4545
|
+
(_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.recordUmdSnapshot();
|
|
4546
|
+
}
|
|
4141
4547
|
/**
|
|
4142
4548
|
* this.container maybe contains micro-app element, stop sandbox should exec after cloneContainer
|
|
4143
4549
|
* NOTE:
|
|
4144
4550
|
* 1. if destroy is true, clear route state
|
|
4145
4551
|
* 2. umd mode and keep-alive will not clear EventSource
|
|
4146
4552
|
*/
|
|
4147
|
-
(
|
|
4553
|
+
(_b = this.sandBox) === null || _b === void 0 ? void 0 : _b.stop(this.umdMode, this.keepRouteState && !destroy, !this.umdMode || destroy);
|
|
4148
4554
|
if (!getActiveApps().length) {
|
|
4149
4555
|
releasePatchSetAttribute();
|
|
4150
4556
|
}
|
|
@@ -4282,6 +4688,7 @@ function defineElement(tagName) {
|
|
|
4282
4688
|
this.setAttribute('name', this.appName);
|
|
4283
4689
|
}
|
|
4284
4690
|
};
|
|
4691
|
+
// patchSetAttribute hijiack data attribute, it needs exec first
|
|
4285
4692
|
patchSetAttribute();
|
|
4286
4693
|
}
|
|
4287
4694
|
static get observedAttributes() {
|
|
@@ -4458,7 +4865,7 @@ function defineElement(tagName) {
|
|
|
4458
4865
|
app.isPrefetch = false;
|
|
4459
4866
|
defer(() => {
|
|
4460
4867
|
var _a;
|
|
4461
|
-
return app.mount((_a = this.shadowRoot) !== null && _a !== void 0 ? _a : this, this.getDisposeResult('inline'), this.getBaseRouteCompatible(), this.getDisposeResult('keep-router-state'), this.getDefaultPageValue());
|
|
4868
|
+
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'), this.getDisposeResult('disable-patch-request'));
|
|
4462
4869
|
});
|
|
4463
4870
|
}
|
|
4464
4871
|
// create app instance
|
|
@@ -4477,12 +4884,14 @@ function defineElement(tagName) {
|
|
|
4477
4884
|
ssrUrl: this.ssrUrl,
|
|
4478
4885
|
container: (_a = this.shadowRoot) !== null && _a !== void 0 ? _a : this,
|
|
4479
4886
|
inline: this.getDisposeResult('inline'),
|
|
4480
|
-
scopecss: !(this.getDisposeResult('
|
|
4481
|
-
useSandbox: !this.getDisposeResult('
|
|
4887
|
+
scopecss: !(this.getDisposeResult('disable-scopecss') || this.getDisposeResult('shadowDOM')),
|
|
4888
|
+
useSandbox: !this.getDisposeResult('disable-sandbox'),
|
|
4482
4889
|
useMemoryRouter: !this.getDisposeResult('disable-memory-router'),
|
|
4483
4890
|
baseroute: this.getBaseRouteCompatible(),
|
|
4484
4891
|
keepRouteState: this.getDisposeResult('keep-router-state'),
|
|
4485
4892
|
defaultPage: this.getDefaultPageValue(),
|
|
4893
|
+
hiddenRouter: this.getDisposeResult('hidden-router'),
|
|
4894
|
+
disablePatchRequest: this.getDisposeResult('disable-patch-request'),
|
|
4486
4895
|
});
|
|
4487
4896
|
appInstanceMap.set(this.appName, instance);
|
|
4488
4897
|
}
|
|
@@ -4517,25 +4926,25 @@ function defineElement(tagName) {
|
|
|
4517
4926
|
*/
|
|
4518
4927
|
getDisposeResult(name) {
|
|
4519
4928
|
// @ts-ignore
|
|
4520
|
-
return (this.compatibleSpecialProperties(name) || microApp[name]) && this.compatibleDisableSpecialProperties(name);
|
|
4929
|
+
return (this.compatibleSpecialProperties(name) || !!microApp[name]) && this.compatibleDisableSpecialProperties(name);
|
|
4521
4930
|
}
|
|
4522
4931
|
// compatible of disableScopecss & disableSandbox
|
|
4523
4932
|
compatibleSpecialProperties(name) {
|
|
4524
|
-
if (name === '
|
|
4525
|
-
return this.hasAttribute('
|
|
4933
|
+
if (name === 'disable-scopecss') {
|
|
4934
|
+
return this.hasAttribute('disable-scopecss') || this.hasAttribute('disableScopecss');
|
|
4526
4935
|
}
|
|
4527
|
-
else if (name === '
|
|
4528
|
-
return this.hasAttribute('
|
|
4936
|
+
else if (name === 'disable-sandbox') {
|
|
4937
|
+
return this.hasAttribute('disable-sandbox') || this.hasAttribute('disableSandbox');
|
|
4529
4938
|
}
|
|
4530
4939
|
return this.hasAttribute(name);
|
|
4531
4940
|
}
|
|
4532
4941
|
// compatible of disableScopecss & disableSandbox
|
|
4533
4942
|
compatibleDisableSpecialProperties(name) {
|
|
4534
|
-
if (name === '
|
|
4535
|
-
return this.getAttribute('
|
|
4943
|
+
if (name === 'disable-scopecss') {
|
|
4944
|
+
return this.getAttribute('disable-scopecss') !== 'false' && this.getAttribute('disableScopecss') !== 'false';
|
|
4536
4945
|
}
|
|
4537
|
-
else if (name === '
|
|
4538
|
-
return this.getAttribute('
|
|
4946
|
+
else if (name === 'disable-sandbox') {
|
|
4947
|
+
return this.getAttribute('disable-sandbox') !== 'false' && this.getAttribute('disableSandbox') !== 'false';
|
|
4539
4948
|
}
|
|
4540
4949
|
return this.getAttribute(name) !== 'false';
|
|
4541
4950
|
}
|
|
@@ -4563,7 +4972,7 @@ function defineElement(tagName) {
|
|
|
4563
4972
|
*/
|
|
4564
4973
|
updateSsrUrl(baseUrl) {
|
|
4565
4974
|
if (this.getDisposeResult('ssr')) {
|
|
4566
|
-
if (this.getDisposeResult('disable-memory-router')) {
|
|
4975
|
+
if (this.getDisposeResult('disable-memory-router') || this.getDisposeResult('disableSandbox')) {
|
|
4567
4976
|
const rawLocation = globalEnv.rawWindow.location;
|
|
4568
4977
|
this.ssrUrl = CompletionPath(rawLocation.pathname + rawLocation.search, baseUrl);
|
|
4569
4978
|
}
|
|
@@ -4647,7 +5056,7 @@ function preFetch(apps) {
|
|
|
4647
5056
|
function preFetchInSerial(prefetchApp) {
|
|
4648
5057
|
return new Promise((resolve) => {
|
|
4649
5058
|
requestIdleCallback(() => {
|
|
4650
|
-
var _a, _b, _c;
|
|
5059
|
+
var _a, _b, _c, _d, _e;
|
|
4651
5060
|
if (isPlainObject(prefetchApp) && navigator.onLine) {
|
|
4652
5061
|
prefetchApp.name = formatAppName(prefetchApp.name);
|
|
4653
5062
|
prefetchApp.url = formatAppURL(prefetchApp.url, prefetchApp.name);
|
|
@@ -4655,9 +5064,9 @@ function preFetchInSerial(prefetchApp) {
|
|
|
4655
5064
|
const app = new CreateApp({
|
|
4656
5065
|
name: prefetchApp.name,
|
|
4657
5066
|
url: prefetchApp.url,
|
|
4658
|
-
scopecss: !((_a = prefetchApp
|
|
4659
|
-
useSandbox: !((
|
|
4660
|
-
useMemoryRouter: !((
|
|
5067
|
+
scopecss: !((_b = (_a = prefetchApp['disable-scopecss']) !== null && _a !== void 0 ? _a : prefetchApp.disableScopecss) !== null && _b !== void 0 ? _b : microApp['disable-scopecss']),
|
|
5068
|
+
useSandbox: !((_d = (_c = prefetchApp['disable-sandbox']) !== null && _c !== void 0 ? _c : prefetchApp.disableSandbox) !== null && _d !== void 0 ? _d : microApp['disable-sandbox']),
|
|
5069
|
+
useMemoryRouter: !((_e = prefetchApp['disable-memory-router']) !== null && _e !== void 0 ? _e : microApp['disable-memory-router']),
|
|
4661
5070
|
});
|
|
4662
5071
|
app.isPrefetch = true;
|
|
4663
5072
|
app.prefetchResolve = resolve;
|
|
@@ -4707,7 +5116,7 @@ function fetchGlobalResources(resources, suffix, cache) {
|
|
|
4707
5116
|
* @param excludeHiddenApp exclude hidden keep-alive app, default is false
|
|
4708
5117
|
* @returns active apps
|
|
4709
5118
|
*/
|
|
4710
|
-
function getActiveApps(excludeHiddenApp) {
|
|
5119
|
+
function getActiveApps(excludeHiddenApp = false) {
|
|
4711
5120
|
const activeApps = [];
|
|
4712
5121
|
appInstanceMap.forEach((app, appName) => {
|
|
4713
5122
|
if (appStates.UNMOUNT !== app.getAppState() &&
|
|
@@ -4803,6 +5212,7 @@ class MicroApp extends EventCenterForBaseApp {
|
|
|
4803
5212
|
this.router = router;
|
|
4804
5213
|
}
|
|
4805
5214
|
start(options) {
|
|
5215
|
+
var _a, _b;
|
|
4806
5216
|
if (!isBrowser || !window.customElements) {
|
|
4807
5217
|
return logError('micro-app is not supported in this environment');
|
|
4808
5218
|
}
|
|
@@ -4828,9 +5238,13 @@ class MicroApp extends EventCenterForBaseApp {
|
|
|
4828
5238
|
// @ts-ignore
|
|
4829
5239
|
this.destory = options.destory;
|
|
4830
5240
|
this.inline = options.inline;
|
|
4831
|
-
this
|
|
4832
|
-
this
|
|
4833
|
-
this
|
|
5241
|
+
this['disable-scopecss'] = (_a = options['disable-scopecss']) !== null && _a !== void 0 ? _a : options.disableScopecss;
|
|
5242
|
+
this['disable-sandbox'] = (_b = options['disable-sandbox']) !== null && _b !== void 0 ? _b : options.disableSandbox;
|
|
5243
|
+
this['disable-memory-router'] = options['disable-memory-router'];
|
|
5244
|
+
this['disable-patch-request'] = options['disable-patch-request'];
|
|
5245
|
+
this['keep-router-state'] = options['keep-router-state'];
|
|
5246
|
+
this['hidden-router'] = options['hidden-router'];
|
|
5247
|
+
this.esmodule = options.esmodule;
|
|
4834
5248
|
this.ssr = options.ssr;
|
|
4835
5249
|
isFunction(options.fetch) && (this.fetch = options.fetch);
|
|
4836
5250
|
isPlainObject(options.lifeCycles) && (this.lifeCycles = options.lifeCycles);
|