@micro-zoe/micro-app 1.0.0-alpha.9 → 1.0.0-beta.0
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/README.md +3 -3
- package/README.zh-cn.md +4 -3
- package/lib/index.d.ts +18 -4
- package/lib/index.esm.js +2076 -617
- 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 -3
- package/typings/global.d.ts +53 -19
package/lib/index.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const version = '1.0.0-
|
|
1
|
+
const version = '1.0.0-beta.0';
|
|
2
2
|
// do not use isUndefined
|
|
3
3
|
const isBrowser = typeof window !== 'undefined';
|
|
4
4
|
// do not use isUndefined
|
|
@@ -7,7 +7,6 @@ const globalThis = (typeof global !== 'undefined')
|
|
|
7
7
|
: ((typeof window !== 'undefined')
|
|
8
8
|
? window
|
|
9
9
|
: ((typeof self !== 'undefined') ? self : Function('return this')()));
|
|
10
|
-
const noop = () => { };
|
|
11
10
|
const noopFalse = () => false;
|
|
12
11
|
// Array.isArray
|
|
13
12
|
const isArray = Array.isArray;
|
|
@@ -74,13 +73,46 @@ function isShadowRoot(target) {
|
|
|
74
73
|
return typeof ShadowRoot !== 'undefined' && target instanceof ShadowRoot;
|
|
75
74
|
}
|
|
76
75
|
function isURL(target) {
|
|
77
|
-
|
|
76
|
+
var _a;
|
|
77
|
+
return target instanceof URL || !!((_a = target) === null || _a === void 0 ? void 0 : _a.href);
|
|
78
78
|
}
|
|
79
|
+
// iframe element not instanceof base app Element, use tagName instead
|
|
79
80
|
function isElement(target) {
|
|
80
|
-
|
|
81
|
+
var _a;
|
|
82
|
+
return target instanceof Element || isString((_a = target) === null || _a === void 0 ? void 0 : _a.tagName);
|
|
81
83
|
}
|
|
84
|
+
// iframe node not instanceof base app Node, use nodeType instead
|
|
82
85
|
function isNode(target) {
|
|
83
|
-
|
|
86
|
+
var _a;
|
|
87
|
+
return target instanceof Node || isNumber((_a = target) === null || _a === void 0 ? void 0 : _a.nodeType);
|
|
88
|
+
}
|
|
89
|
+
function isLinkElement(target) {
|
|
90
|
+
var _a, _b;
|
|
91
|
+
return ((_b = (_a = target) === null || _a === void 0 ? void 0 : _a.tagName) === null || _b === void 0 ? void 0 : _b.toUpperCase()) === 'LINK';
|
|
92
|
+
}
|
|
93
|
+
function isStyleElement(target) {
|
|
94
|
+
var _a, _b;
|
|
95
|
+
return ((_b = (_a = target) === null || _a === void 0 ? void 0 : _a.tagName) === null || _b === void 0 ? void 0 : _b.toUpperCase()) === 'STYLE';
|
|
96
|
+
}
|
|
97
|
+
function isScriptElement(target) {
|
|
98
|
+
var _a, _b;
|
|
99
|
+
return ((_b = (_a = target) === null || _a === void 0 ? void 0 : _a.tagName) === null || _b === void 0 ? void 0 : _b.toUpperCase()) === 'SCRIPT';
|
|
100
|
+
}
|
|
101
|
+
function isIFrameElement(target) {
|
|
102
|
+
var _a, _b;
|
|
103
|
+
return ((_b = (_a = target) === null || _a === void 0 ? void 0 : _a.tagName) === null || _b === void 0 ? void 0 : _b.toUpperCase()) === 'IFRAME';
|
|
104
|
+
}
|
|
105
|
+
function isDivElement(target) {
|
|
106
|
+
var _a, _b;
|
|
107
|
+
return ((_b = (_a = target) === null || _a === void 0 ? void 0 : _a.tagName) === null || _b === void 0 ? void 0 : _b.toUpperCase()) === 'DIV';
|
|
108
|
+
}
|
|
109
|
+
function isImageElement(target) {
|
|
110
|
+
var _a, _b;
|
|
111
|
+
return ((_b = (_a = target) === null || _a === void 0 ? void 0 : _a.tagName) === null || _b === void 0 ? void 0 : _b.toUpperCase()) === 'IMG';
|
|
112
|
+
}
|
|
113
|
+
function isBaseElement(target) {
|
|
114
|
+
var _a, _b;
|
|
115
|
+
return ((_b = (_a = target) === null || _a === void 0 ? void 0 : _a.tagName) === null || _b === void 0 ? void 0 : _b.toUpperCase()) === 'BASE';
|
|
84
116
|
}
|
|
85
117
|
// is ProxyDocument
|
|
86
118
|
function isProxyDocument(target) {
|
|
@@ -323,6 +355,7 @@ function pureCreateElement(tagName, options) {
|
|
|
323
355
|
function cloneContainer(origin, target, deep) {
|
|
324
356
|
target.innerHTML = '';
|
|
325
357
|
if (deep) {
|
|
358
|
+
// TODO: ShadowRoot兼容,ShadowRoot不能直接使用cloneNode
|
|
326
359
|
const clonedNode = origin.cloneNode(true);
|
|
327
360
|
const fragment = document.createDocumentFragment();
|
|
328
361
|
Array.from(clonedNode.childNodes).forEach((node) => {
|
|
@@ -335,6 +368,7 @@ function cloneContainer(origin, target, deep) {
|
|
|
335
368
|
target.appendChild(node);
|
|
336
369
|
});
|
|
337
370
|
}
|
|
371
|
+
return target;
|
|
338
372
|
}
|
|
339
373
|
// is invalid key of querySelector
|
|
340
374
|
function isInvalidQuerySelectorKey(key) {
|
|
@@ -500,12 +534,17 @@ function isInlineScript(address) {
|
|
|
500
534
|
* @param appName app.name
|
|
501
535
|
* @param args arguments
|
|
502
536
|
*/
|
|
503
|
-
function
|
|
537
|
+
function execMicroAppGlobalHook(fn, appName, hookName, ...args) {
|
|
504
538
|
try {
|
|
505
539
|
isFunction(fn) && fn(...args);
|
|
506
540
|
}
|
|
507
541
|
catch (e) {
|
|
508
|
-
logError(`
|
|
542
|
+
logError(`An error occurred in app ${appName} window.${hookName} \n`, null, e);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
function clearDOM($dom) {
|
|
546
|
+
while ($dom === null || $dom === void 0 ? void 0 : $dom.firstChild) {
|
|
547
|
+
$dom.removeChild($dom.firstChild);
|
|
509
548
|
}
|
|
510
549
|
}
|
|
511
550
|
|
|
@@ -544,6 +583,11 @@ var microGlobalEvent;
|
|
|
544
583
|
microGlobalEvent["ONMOUNT"] = "onmount";
|
|
545
584
|
microGlobalEvent["ONUNMOUNT"] = "onunmount";
|
|
546
585
|
})(microGlobalEvent || (microGlobalEvent = {}));
|
|
586
|
+
// custom event of child app
|
|
587
|
+
const microAppCustomEvent = [
|
|
588
|
+
'unmount',
|
|
589
|
+
'appstate-change',
|
|
590
|
+
];
|
|
547
591
|
// keep-alive status
|
|
548
592
|
var keepAliveStates;
|
|
549
593
|
(function (keepAliveStates) {
|
|
@@ -566,7 +610,6 @@ var MicroAppConfig;
|
|
|
566
610
|
MicroAppConfig["HIDDEN_ROUTER"] = "hidden-router";
|
|
567
611
|
MicroAppConfig["KEEP_ALIVE"] = "keep-alive";
|
|
568
612
|
MicroAppConfig["CLEAR_DATA"] = "clear-data";
|
|
569
|
-
MicroAppConfig["ESMODULE"] = "esmodule";
|
|
570
613
|
MicroAppConfig["SSR"] = "ssr";
|
|
571
614
|
MicroAppConfig["FIBER"] = "fiber";
|
|
572
615
|
})(MicroAppConfig || (MicroAppConfig = {}));
|
|
@@ -1094,9 +1137,6 @@ function dispatchOnErrorEvent(element) {
|
|
|
1094
1137
|
function createSourceCenter() {
|
|
1095
1138
|
const linkList = new Map();
|
|
1096
1139
|
const scriptList = new Map();
|
|
1097
|
-
// setInterval(() => {
|
|
1098
|
-
// console.log(linkList, scriptList)
|
|
1099
|
-
// }, 10000);
|
|
1100
1140
|
function createSourceHandler(targetList) {
|
|
1101
1141
|
return {
|
|
1102
1142
|
setInfo(address, info) {
|
|
@@ -1138,7 +1178,7 @@ function getExistParseCode(appName, prefix, linkInfo) {
|
|
|
1138
1178
|
if (item !== appName) {
|
|
1139
1179
|
const appSpaceData = appSpace[item];
|
|
1140
1180
|
if (appSpaceData.parsedCode) {
|
|
1141
|
-
return appSpaceData.parsedCode.
|
|
1181
|
+
return appSpaceData.parsedCode.replace(new RegExp(createPrefix(item, true), 'g'), prefix);
|
|
1142
1182
|
}
|
|
1143
1183
|
}
|
|
1144
1184
|
}
|
|
@@ -1224,18 +1264,18 @@ function fetchLinksFromHtml(wrapElement, app, microAppHead, fiberStyleResult) {
|
|
|
1224
1264
|
const linkInfo = sourceCenter.link.getInfo(address);
|
|
1225
1265
|
return linkInfo.code ? linkInfo.code : fetchSource(address, app.name);
|
|
1226
1266
|
});
|
|
1227
|
-
const fiberLinkTasks =
|
|
1267
|
+
const fiberLinkTasks = fiberStyleResult ? [] : null;
|
|
1228
1268
|
promiseStream(fetchLinkPromise, (res) => {
|
|
1229
1269
|
injectFiberTask(fiberLinkTasks, () => fetchLinkSuccess(styleList[res.index], res.data, microAppHead, app));
|
|
1230
1270
|
}, (err) => {
|
|
1231
1271
|
logError(err, app.name);
|
|
1232
1272
|
}, () => {
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1273
|
+
/**
|
|
1274
|
+
* 1. If fiberStyleResult exist, fiberLinkTasks must exist
|
|
1275
|
+
* 2. Download link source while processing style
|
|
1276
|
+
* 3. Process style first, and then process link
|
|
1277
|
+
*/
|
|
1278
|
+
if (fiberStyleResult) {
|
|
1239
1279
|
fiberStyleResult.then(() => {
|
|
1240
1280
|
fiberLinkTasks.push(() => Promise.resolve(app.onLoad(wrapElement)));
|
|
1241
1281
|
serialExecFiberTasks(fiberLinkTasks);
|
|
@@ -1369,10 +1409,10 @@ class Adapter {
|
|
|
1369
1409
|
'webpackHotUpdate',
|
|
1370
1410
|
'Vue',
|
|
1371
1411
|
];
|
|
1372
|
-
this.
|
|
1412
|
+
this.injectReactHMRProperty();
|
|
1373
1413
|
}
|
|
1374
1414
|
// adapter for react
|
|
1375
|
-
|
|
1415
|
+
injectReactHMRProperty() {
|
|
1376
1416
|
if ((process.env.NODE_ENV !== 'production')) {
|
|
1377
1417
|
// react child in non-react env
|
|
1378
1418
|
this.staticEscapeProperties.push('__REACT_ERROR_OVERLAY_GLOBAL_HOOK__');
|
|
@@ -1411,13 +1451,15 @@ function fixReactHMRConflict(app) {
|
|
|
1411
1451
|
/**
|
|
1412
1452
|
* reDefine parentNode of html
|
|
1413
1453
|
* Scenes:
|
|
1414
|
-
* 1. element-ui
|
|
1415
|
-
*
|
|
1454
|
+
* 1. element-ui@2/lib/utils/popper.js
|
|
1455
|
+
* var parent = element.parentNode;
|
|
1456
|
+
* // root is child app window
|
|
1457
|
+
* if (parent === root.document) ...
|
|
1416
1458
|
*/
|
|
1417
|
-
function throttleDeferForParentNode(
|
|
1459
|
+
function throttleDeferForParentNode(microDocument) {
|
|
1418
1460
|
const html = globalEnv.rawDocument.firstElementChild;
|
|
1419
|
-
if (html
|
|
1420
|
-
setParentNode(html,
|
|
1461
|
+
if ((html === null || html === void 0 ? void 0 : html.parentNode) === globalEnv.rawDocument) {
|
|
1462
|
+
setParentNode(html, microDocument);
|
|
1421
1463
|
defer(() => {
|
|
1422
1464
|
setParentNode(html, globalEnv.rawDocument);
|
|
1423
1465
|
});
|
|
@@ -1437,6 +1479,64 @@ function setParentNode(target, value) {
|
|
|
1437
1479
|
});
|
|
1438
1480
|
}
|
|
1439
1481
|
}
|
|
1482
|
+
// this events should be sent to the specified app
|
|
1483
|
+
const formatEventList = ['unmount', 'appstate-change'];
|
|
1484
|
+
/**
|
|
1485
|
+
* Format event name
|
|
1486
|
+
* @param eventName event name
|
|
1487
|
+
* @param appName app name
|
|
1488
|
+
*/
|
|
1489
|
+
function formatEventName(eventName, appName) {
|
|
1490
|
+
var _a;
|
|
1491
|
+
if (!isIframeSandbox(appName) && (formatEventList.includes(eventName) ||
|
|
1492
|
+
((eventName === 'popstate' || eventName === 'hashchange') && ((_a = appInstanceMap.get(appName)) === null || _a === void 0 ? void 0 : _a.useMemoryRouter)))) {
|
|
1493
|
+
return `${eventName}-${appName}`;
|
|
1494
|
+
}
|
|
1495
|
+
return eventName;
|
|
1496
|
+
}
|
|
1497
|
+
/**
|
|
1498
|
+
* update dom tree of target dom
|
|
1499
|
+
* @param container target dom
|
|
1500
|
+
* @param appName app name
|
|
1501
|
+
*/
|
|
1502
|
+
function patchElementTree(container, appName) {
|
|
1503
|
+
const children = Array.from(container.children);
|
|
1504
|
+
children.length && children.forEach((child) => {
|
|
1505
|
+
patchElementTree(child, appName);
|
|
1506
|
+
});
|
|
1507
|
+
for (const child of children) {
|
|
1508
|
+
updateElementInfo(child, appName);
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
/**
|
|
1512
|
+
* rewrite baseURI, ownerDocument, __MICRO_APP_NAME__ of target node
|
|
1513
|
+
* @param node target node
|
|
1514
|
+
* @param appName app name
|
|
1515
|
+
* @returns target node
|
|
1516
|
+
*/
|
|
1517
|
+
function updateElementInfo(node, appName) {
|
|
1518
|
+
var _a, _b;
|
|
1519
|
+
const proxyWindow = (_b = (_a = appInstanceMap.get(appName)) === null || _a === void 0 ? void 0 : _a.sandBox) === null || _b === void 0 ? void 0 : _b.proxyWindow;
|
|
1520
|
+
if (proxyWindow && isNode(node) && !node.__MICRO_APP_NAME__) {
|
|
1521
|
+
// TODO: 测试baseURI和ownerDocument在with沙箱中是否正确
|
|
1522
|
+
rawDefineProperties(node, {
|
|
1523
|
+
baseURI: {
|
|
1524
|
+
configurable: true,
|
|
1525
|
+
get: () => proxyWindow.location.href,
|
|
1526
|
+
},
|
|
1527
|
+
ownerDocument: {
|
|
1528
|
+
configurable: true,
|
|
1529
|
+
get: () => proxyWindow.document,
|
|
1530
|
+
},
|
|
1531
|
+
__MICRO_APP_NAME__: {
|
|
1532
|
+
configurable: true,
|
|
1533
|
+
writable: true,
|
|
1534
|
+
value: appName,
|
|
1535
|
+
},
|
|
1536
|
+
});
|
|
1537
|
+
}
|
|
1538
|
+
return node;
|
|
1539
|
+
}
|
|
1440
1540
|
|
|
1441
1541
|
// Record element and map element
|
|
1442
1542
|
const dynamicElementInMicroAppMap = new WeakMap();
|
|
@@ -1447,7 +1547,7 @@ const dynamicElementInMicroAppMap = new WeakMap();
|
|
|
1447
1547
|
* @param app app
|
|
1448
1548
|
*/
|
|
1449
1549
|
function handleNewNode(parent, child, app) {
|
|
1450
|
-
if (child
|
|
1550
|
+
if (isStyleElement(child)) {
|
|
1451
1551
|
if (child.hasAttribute('exclude')) {
|
|
1452
1552
|
const replaceComment = document.createComment('style element with exclude attribute ignored by micro-app');
|
|
1453
1553
|
dynamicElementInMicroAppMap.set(child, replaceComment);
|
|
@@ -1458,7 +1558,7 @@ function handleNewNode(parent, child, app) {
|
|
|
1458
1558
|
}
|
|
1459
1559
|
return child;
|
|
1460
1560
|
}
|
|
1461
|
-
else if (child
|
|
1561
|
+
else if (isLinkElement(child)) {
|
|
1462
1562
|
if (child.hasAttribute('exclude') || checkExcludeUrl(child.getAttribute('href'), app.name)) {
|
|
1463
1563
|
const linkReplaceComment = document.createComment('link element with exclude attribute ignored by micro-app');
|
|
1464
1564
|
dynamicElementInMicroAppMap.set(child, linkReplaceComment);
|
|
@@ -1483,7 +1583,7 @@ function handleNewNode(parent, child, app) {
|
|
|
1483
1583
|
}
|
|
1484
1584
|
return child;
|
|
1485
1585
|
}
|
|
1486
|
-
else if (child
|
|
1586
|
+
else if (isScriptElement(child)) {
|
|
1487
1587
|
if (child.src &&
|
|
1488
1588
|
isFunction(microApp.options.excludeAssetFilter) &&
|
|
1489
1589
|
microApp.options.excludeAssetFilter(child.src)) {
|
|
@@ -1513,17 +1613,20 @@ function handleNewNode(parent, child, app) {
|
|
|
1513
1613
|
* @param passiveChild second param of insertBefore and replaceChild
|
|
1514
1614
|
*/
|
|
1515
1615
|
function invokePrototypeMethod(app, rawMethod, parent, targetChild, passiveChild) {
|
|
1516
|
-
const hijackParent = getHijackParent(parent, app);
|
|
1616
|
+
const hijackParent = getHijackParent(parent, targetChild, app);
|
|
1517
1617
|
/**
|
|
1518
1618
|
* If passiveChild is not the child node, insertBefore replaceChild will have a problem, at this time, it will be degraded to appendChild
|
|
1519
1619
|
* E.g: document.head.insertBefore(targetChild, document.head.childNodes[0])
|
|
1520
1620
|
*/
|
|
1521
1621
|
if (hijackParent) {
|
|
1522
1622
|
/**
|
|
1623
|
+
* Adapter for
|
|
1523
1624
|
* WARNING:
|
|
1524
1625
|
* Verifying that the parentNode of the targetChild points to document.body will cause other problems ?
|
|
1525
1626
|
*/
|
|
1526
|
-
if (
|
|
1627
|
+
if (!isIframeSandbox(app.name) &&
|
|
1628
|
+
hijackParent.tagName === 'MICRO-APP-BODY' &&
|
|
1629
|
+
rawMethod !== globalEnv.rawRemoveChild) {
|
|
1527
1630
|
const descriptor = Object.getOwnPropertyDescriptor(targetChild, 'parentNode');
|
|
1528
1631
|
if (!descriptor || descriptor.configurable) {
|
|
1529
1632
|
rawDefineProperty(targetChild, 'parentNode', {
|
|
@@ -1553,7 +1656,7 @@ function invokePrototypeMethod(app, rawMethod, parent, targetChild, passiveChild
|
|
|
1553
1656
|
return targetChild;
|
|
1554
1657
|
}
|
|
1555
1658
|
if ((process.env.NODE_ENV !== 'production') &&
|
|
1556
|
-
targetChild
|
|
1659
|
+
isIFrameElement(targetChild) &&
|
|
1557
1660
|
rawMethod === globalEnv.rawAppendChild) {
|
|
1558
1661
|
fixReactHMRConflict(app);
|
|
1559
1662
|
}
|
|
@@ -1562,13 +1665,20 @@ function invokePrototypeMethod(app, rawMethod, parent, targetChild, passiveChild
|
|
|
1562
1665
|
return invokeRawMethod(rawMethod, parent, targetChild, passiveChild);
|
|
1563
1666
|
}
|
|
1564
1667
|
// head/body map to micro-app-head/micro-app-body
|
|
1565
|
-
function getHijackParent(
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1668
|
+
function getHijackParent(parent, targetChild, app) {
|
|
1669
|
+
if (app) {
|
|
1670
|
+
if (parent === document.head) {
|
|
1671
|
+
if (app.iframe && isScriptElement(targetChild)) {
|
|
1672
|
+
return app.sandBox.microHead;
|
|
1673
|
+
}
|
|
1674
|
+
return app.querySelector('micro-app-head');
|
|
1675
|
+
}
|
|
1676
|
+
if (parent === document.body || parent === document.body.parentNode) {
|
|
1677
|
+
if (app.iframe && isScriptElement(targetChild)) {
|
|
1678
|
+
return app.sandBox.microBody;
|
|
1679
|
+
}
|
|
1680
|
+
return app.querySelector('micro-app-body');
|
|
1681
|
+
}
|
|
1572
1682
|
}
|
|
1573
1683
|
return null;
|
|
1574
1684
|
}
|
|
@@ -1596,8 +1706,9 @@ function getMappingNode(node) {
|
|
|
1596
1706
|
function commonElementHandler(parent, newChild, passiveChild, rawMethod) {
|
|
1597
1707
|
const currentAppName = getCurrentAppName();
|
|
1598
1708
|
if (isNode(newChild) &&
|
|
1709
|
+
!newChild.__PURE_ELEMENT__ &&
|
|
1599
1710
|
(newChild.__MICRO_APP_NAME__ ||
|
|
1600
|
-
|
|
1711
|
+
currentAppName)) {
|
|
1601
1712
|
newChild.__MICRO_APP_NAME__ = newChild.__MICRO_APP_NAME__ || currentAppName;
|
|
1602
1713
|
const app = appInstanceMap.get(newChild.__MICRO_APP_NAME__);
|
|
1603
1714
|
if (app === null || app === void 0 ? void 0 : app.container) {
|
|
@@ -1625,10 +1736,10 @@ function commonElementHandler(parent, newChild, passiveChild, rawMethod) {
|
|
|
1625
1736
|
const app = appInstanceMap.get(currentAppName);
|
|
1626
1737
|
if (app === null || app === void 0 ? void 0 : app.container) {
|
|
1627
1738
|
if (parent === document.head) {
|
|
1628
|
-
return rawMethod.call(app.
|
|
1739
|
+
return rawMethod.call(app.querySelector('micro-app-head'), newChild);
|
|
1629
1740
|
}
|
|
1630
1741
|
else if (parent === document.body) {
|
|
1631
|
-
return rawMethod.call(app.
|
|
1742
|
+
return rawMethod.call(app.querySelector('micro-app-body'), newChild);
|
|
1632
1743
|
}
|
|
1633
1744
|
}
|
|
1634
1745
|
}
|
|
@@ -1639,7 +1750,7 @@ function commonElementHandler(parent, newChild, passiveChild, rawMethod) {
|
|
|
1639
1750
|
/**
|
|
1640
1751
|
* Rewrite element prototype method
|
|
1641
1752
|
*/
|
|
1642
|
-
function
|
|
1753
|
+
function patchElementAndDocument() {
|
|
1643
1754
|
patchDocument();
|
|
1644
1755
|
// prototype methods of add element👇
|
|
1645
1756
|
Element.prototype.appendChild = function appendChild(newChild) {
|
|
@@ -1688,6 +1799,71 @@ function patchElementPrototypeMethods() {
|
|
|
1688
1799
|
this.__MICRO_APP_NAME__ && (clonedNode.__MICRO_APP_NAME__ = this.__MICRO_APP_NAME__);
|
|
1689
1800
|
return clonedNode;
|
|
1690
1801
|
};
|
|
1802
|
+
function getQueryTarget(node) {
|
|
1803
|
+
const currentAppName = getCurrentAppName();
|
|
1804
|
+
if ((node === document.body || node === document.head) && currentAppName) {
|
|
1805
|
+
const app = appInstanceMap.get(currentAppName);
|
|
1806
|
+
if (app === null || app === void 0 ? void 0 : app.container) {
|
|
1807
|
+
if (node === document.body) {
|
|
1808
|
+
return app.querySelector('micro-app-body');
|
|
1809
|
+
}
|
|
1810
|
+
else if (node === document.head) {
|
|
1811
|
+
return app.querySelector('micro-app-head');
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
}
|
|
1815
|
+
return null;
|
|
1816
|
+
}
|
|
1817
|
+
Element.prototype.querySelector = function querySelector(selectors) {
|
|
1818
|
+
var _a;
|
|
1819
|
+
const target = (_a = getQueryTarget(this)) !== null && _a !== void 0 ? _a : this;
|
|
1820
|
+
return globalEnv.rawElementQuerySelector.call(target, selectors);
|
|
1821
|
+
};
|
|
1822
|
+
Element.prototype.querySelectorAll = function querySelectorAll(selectors) {
|
|
1823
|
+
var _a;
|
|
1824
|
+
const target = (_a = getQueryTarget(this)) !== null && _a !== void 0 ? _a : this;
|
|
1825
|
+
return globalEnv.rawElementQuerySelectorAll.call(target, selectors);
|
|
1826
|
+
};
|
|
1827
|
+
rawDefineProperty(Element.prototype, 'innerHTML', {
|
|
1828
|
+
configurable: true,
|
|
1829
|
+
enumerable: true,
|
|
1830
|
+
get() {
|
|
1831
|
+
return globalEnv.rawInnerHTMLDesc.get.call(this);
|
|
1832
|
+
},
|
|
1833
|
+
set(code) {
|
|
1834
|
+
globalEnv.rawInnerHTMLDesc.set.call(this, code);
|
|
1835
|
+
const currentAppName = getCurrentAppName();
|
|
1836
|
+
Array.from(this.children).forEach((child) => {
|
|
1837
|
+
if (isElement(child) && currentAppName) {
|
|
1838
|
+
child.__MICRO_APP_NAME__ = currentAppName;
|
|
1839
|
+
}
|
|
1840
|
+
});
|
|
1841
|
+
}
|
|
1842
|
+
});
|
|
1843
|
+
// Abandon this way at 2023.2.28 before v1.0.0-beta.0, it will cause vue2 throw error when render again
|
|
1844
|
+
// rawDefineProperty(Node.prototype, 'parentNode', {
|
|
1845
|
+
// configurable: true,
|
|
1846
|
+
// enumerable: true,
|
|
1847
|
+
// get () {
|
|
1848
|
+
// const result = globalEnv.rawParentNodeDesc.get.call(this)
|
|
1849
|
+
// /**
|
|
1850
|
+
// * If parentNode is <micro-app-body>, return rawDocument.body
|
|
1851
|
+
// * Scenes:
|
|
1852
|
+
// * 1. element-ui@2/lib/utils/vue-popper.js
|
|
1853
|
+
// * if (this.popperElm.parentNode === document.body) ...
|
|
1854
|
+
// * WARNING:
|
|
1855
|
+
// * Will it cause other problems ?
|
|
1856
|
+
// * e.g. target.parentNode.remove(target)
|
|
1857
|
+
// * BUG:
|
|
1858
|
+
// * 1. vue2 umdMode, throw error when render again (<div id='app'></div> will be deleted when render again )
|
|
1859
|
+
// */
|
|
1860
|
+
// if (result?.tagName === 'MICRO-APP-BODY' && appInstanceMap.get(this.__MICRO_APP_NAME__)?.container) {
|
|
1861
|
+
// return globalEnv.rawDocument.body
|
|
1862
|
+
// }
|
|
1863
|
+
// return result
|
|
1864
|
+
// },
|
|
1865
|
+
// set: undefined,
|
|
1866
|
+
// })
|
|
1691
1867
|
}
|
|
1692
1868
|
/**
|
|
1693
1869
|
* Mark the newly created element in the micro application
|
|
@@ -1721,7 +1897,7 @@ function patchDocument() {
|
|
|
1721
1897
|
};
|
|
1722
1898
|
// query element👇
|
|
1723
1899
|
function querySelector(selectors) {
|
|
1724
|
-
var _a, _b, _c
|
|
1900
|
+
var _a, _b, _c;
|
|
1725
1901
|
const _this = getBindTarget(this);
|
|
1726
1902
|
const currentAppName = getCurrentAppName();
|
|
1727
1903
|
if (!currentAppName ||
|
|
@@ -1732,10 +1908,10 @@ function patchDocument() {
|
|
|
1732
1908
|
rawDocument !== _this) {
|
|
1733
1909
|
return globalEnv.rawQuerySelector.call(_this, selectors);
|
|
1734
1910
|
}
|
|
1735
|
-
return (
|
|
1911
|
+
return (_c = (_b = appInstanceMap.get(currentAppName)) === null || _b === void 0 ? void 0 : _b.querySelector(selectors)) !== null && _c !== void 0 ? _c : null;
|
|
1736
1912
|
}
|
|
1737
1913
|
function querySelectorAll(selectors) {
|
|
1738
|
-
var _a, _b, _c
|
|
1914
|
+
var _a, _b, _c;
|
|
1739
1915
|
const _this = getBindTarget(this);
|
|
1740
1916
|
const currentAppName = getCurrentAppName();
|
|
1741
1917
|
if (!currentAppName ||
|
|
@@ -1745,7 +1921,7 @@ function patchDocument() {
|
|
|
1745
1921
|
rawDocument !== _this) {
|
|
1746
1922
|
return globalEnv.rawQuerySelectorAll.call(_this, selectors);
|
|
1747
1923
|
}
|
|
1748
|
-
return (
|
|
1924
|
+
return (_c = (_b = appInstanceMap.get(currentAppName)) === null || _b === void 0 ? void 0 : _b.querySelectorAll(selectors)) !== null && _c !== void 0 ? _c : [];
|
|
1749
1925
|
}
|
|
1750
1926
|
rawRootDocument.prototype.querySelector = querySelector;
|
|
1751
1927
|
rawRootDocument.prototype.querySelectorAll = querySelectorAll;
|
|
@@ -1833,7 +2009,7 @@ function patchSetAttribute() {
|
|
|
1833
2009
|
const appName = this.__MICRO_APP_NAME__ || getCurrentAppName();
|
|
1834
2010
|
if (appName &&
|
|
1835
2011
|
appInstanceMap.has(appName) &&
|
|
1836
|
-
(((key === 'src' || key === 'srcset') && /^(img|script)$/i.test(this.tagName)) ||
|
|
2012
|
+
(((key === 'src' || key === 'srcset') && /^(img|script|video|audio|source|embed)$/i.test(this.tagName)) ||
|
|
1837
2013
|
(key === 'href' && /^link$/i.test(this.tagName)))) {
|
|
1838
2014
|
const app = appInstanceMap.get(appName);
|
|
1839
2015
|
value = CompletionPath(value, app.url);
|
|
@@ -1855,7 +2031,7 @@ function releasePatchDocument() {
|
|
|
1855
2031
|
rawRootDocument.prototype.getElementsByName = globalEnv.rawGetElementsByName;
|
|
1856
2032
|
}
|
|
1857
2033
|
// release patch
|
|
1858
|
-
function
|
|
2034
|
+
function releasePatchElementAndDocument() {
|
|
1859
2035
|
removeDomScope();
|
|
1860
2036
|
releasePatchDocument();
|
|
1861
2037
|
Element.prototype.appendChild = globalEnv.rawAppendChild;
|
|
@@ -1865,6 +2041,9 @@ function releasePatches() {
|
|
|
1865
2041
|
Element.prototype.append = globalEnv.rawAppend;
|
|
1866
2042
|
Element.prototype.prepend = globalEnv.rawPrepend;
|
|
1867
2043
|
Element.prototype.cloneNode = globalEnv.rawCloneNode;
|
|
2044
|
+
Element.prototype.querySelector = globalEnv.rawElementQuerySelector;
|
|
2045
|
+
Element.prototype.querySelectorAll = globalEnv.rawElementQuerySelectorAll;
|
|
2046
|
+
rawDefineProperty(Element.prototype, 'innerHTML', globalEnv.rawInnerHTMLDesc);
|
|
1868
2047
|
}
|
|
1869
2048
|
// exec when last child unmount
|
|
1870
2049
|
function releasePatchSetAttribute() {
|
|
@@ -1883,16 +2062,21 @@ function rejectMicroAppStyle() {
|
|
|
1883
2062
|
}
|
|
1884
2063
|
}
|
|
1885
2064
|
|
|
1886
|
-
const globalEnv = {
|
|
2065
|
+
const globalEnv = {
|
|
2066
|
+
// mark current application as base application
|
|
2067
|
+
__MICRO_APP_BASE_APPLICATION__: true,
|
|
2068
|
+
// active sandbox count
|
|
2069
|
+
activeSandbox: 0,
|
|
2070
|
+
};
|
|
1887
2071
|
/**
|
|
1888
2072
|
* Note loop nesting
|
|
1889
2073
|
* Only prototype or unique values can be put here
|
|
1890
2074
|
*/
|
|
1891
2075
|
function initGlobalEnv() {
|
|
1892
2076
|
if (isBrowser) {
|
|
1893
|
-
const rawWindow = Function('return window')();
|
|
1894
|
-
const rawDocument = Function('return document')();
|
|
1895
|
-
const rawRootDocument = Function('return Document')();
|
|
2077
|
+
const rawWindow = window.rawWindow || Function('return window')();
|
|
2078
|
+
const rawDocument = window.rawDocument || Function('return document')();
|
|
2079
|
+
const rawRootDocument = rawWindow.Document || Function('return Document')();
|
|
1896
2080
|
const supportModuleScript = isSupportModuleScript();
|
|
1897
2081
|
/**
|
|
1898
2082
|
* save patch raw methods
|
|
@@ -1906,9 +2090,14 @@ function initGlobalEnv() {
|
|
|
1906
2090
|
const rawAppend = Element.prototype.append;
|
|
1907
2091
|
const rawPrepend = Element.prototype.prepend;
|
|
1908
2092
|
const rawCloneNode = Element.prototype.cloneNode;
|
|
2093
|
+
const rawElementQuerySelector = Element.prototype.querySelector;
|
|
2094
|
+
const rawElementQuerySelectorAll = Element.prototype.querySelectorAll;
|
|
2095
|
+
const rawInnerHTMLDesc = Object.getOwnPropertyDescriptor(Element.prototype, 'innerHTML');
|
|
2096
|
+
const rawParentNodeDesc = Object.getOwnPropertyDescriptor(Node.prototype, 'parentNode');
|
|
1909
2097
|
const rawCreateElement = rawRootDocument.prototype.createElement;
|
|
1910
2098
|
const rawCreateElementNS = rawRootDocument.prototype.createElementNS;
|
|
1911
2099
|
const rawCreateDocumentFragment = rawRootDocument.prototype.createDocumentFragment;
|
|
2100
|
+
const rawCreateTextNode = rawRootDocument.prototype.createTextNode;
|
|
1912
2101
|
const rawQuerySelector = rawRootDocument.prototype.querySelector;
|
|
1913
2102
|
const rawQuerySelectorAll = rawRootDocument.prototype.querySelectorAll;
|
|
1914
2103
|
const rawGetElementById = rawRootDocument.prototype.getElementById;
|
|
@@ -1926,18 +2115,19 @@ function initGlobalEnv() {
|
|
|
1926
2115
|
* save effect raw methods
|
|
1927
2116
|
* pay attention to this binding, especially setInterval, setTimeout, clearInterval, clearTimeout
|
|
1928
2117
|
*/
|
|
1929
|
-
const rawWindowAddEventListener = rawWindow.addEventListener;
|
|
1930
|
-
const rawWindowRemoveEventListener = rawWindow.removeEventListener;
|
|
1931
2118
|
const rawSetInterval = rawWindow.setInterval;
|
|
1932
2119
|
const rawSetTimeout = rawWindow.setTimeout;
|
|
1933
2120
|
const rawClearInterval = rawWindow.clearInterval;
|
|
1934
2121
|
const rawClearTimeout = rawWindow.clearTimeout;
|
|
1935
2122
|
const rawPushState = rawWindow.history.pushState;
|
|
1936
2123
|
const rawReplaceState = rawWindow.history.replaceState;
|
|
2124
|
+
const rawWindowAddEventListener = rawWindow.addEventListener;
|
|
2125
|
+
const rawWindowRemoveEventListener = rawWindow.removeEventListener;
|
|
1937
2126
|
const rawDocumentAddEventListener = rawDocument.addEventListener;
|
|
1938
2127
|
const rawDocumentRemoveEventListener = rawDocument.removeEventListener;
|
|
1939
|
-
//
|
|
1940
|
-
|
|
2128
|
+
// TODO: 统一使用 EventTarget 去掉上面四个
|
|
2129
|
+
const rawAddEventListener = EventTarget.prototype.addEventListener;
|
|
2130
|
+
const rawRemoveEventListener = EventTarget.prototype.removeEventListener;
|
|
1941
2131
|
assign(globalEnv, {
|
|
1942
2132
|
// common global vars
|
|
1943
2133
|
rawWindow,
|
|
@@ -1953,9 +2143,14 @@ function initGlobalEnv() {
|
|
|
1953
2143
|
rawAppend,
|
|
1954
2144
|
rawPrepend,
|
|
1955
2145
|
rawCloneNode,
|
|
2146
|
+
rawElementQuerySelector,
|
|
2147
|
+
rawElementQuerySelectorAll,
|
|
2148
|
+
rawInnerHTMLDesc,
|
|
2149
|
+
rawParentNodeDesc,
|
|
1956
2150
|
rawCreateElement,
|
|
1957
2151
|
rawCreateElementNS,
|
|
1958
2152
|
rawCreateDocumentFragment,
|
|
2153
|
+
rawCreateTextNode,
|
|
1959
2154
|
rawQuerySelector,
|
|
1960
2155
|
rawQuerySelectorAll,
|
|
1961
2156
|
rawGetElementById,
|
|
@@ -1974,6 +2169,8 @@ function initGlobalEnv() {
|
|
|
1974
2169
|
rawDocumentRemoveEventListener,
|
|
1975
2170
|
rawPushState,
|
|
1976
2171
|
rawReplaceState,
|
|
2172
|
+
rawAddEventListener,
|
|
2173
|
+
rawRemoveEventListener,
|
|
1977
2174
|
});
|
|
1978
2175
|
// global effect
|
|
1979
2176
|
rejectMicroAppStyle();
|
|
@@ -1983,7 +2180,7 @@ function initGlobalEnv() {
|
|
|
1983
2180
|
const scriptTypes = ['text/javascript', 'text/ecmascript', 'application/javascript', 'application/ecmascript', 'module', 'systemjs-module', 'systemjs-importmap'];
|
|
1984
2181
|
// whether use type='module' script
|
|
1985
2182
|
function isTypeModule(app, scriptInfo) {
|
|
1986
|
-
return scriptInfo.appSpace[app.name].module && (!app.useSandbox || app.
|
|
2183
|
+
return scriptInfo.appSpace[app.name].module && (!app.useSandbox || app.iframe);
|
|
1987
2184
|
}
|
|
1988
2185
|
// special script element
|
|
1989
2186
|
function isSpecialScript(app, scriptInfo) {
|
|
@@ -2002,11 +2199,17 @@ function isInlineMode(app, scriptInfo) {
|
|
|
2002
2199
|
return (app.inline ||
|
|
2003
2200
|
scriptInfo.appSpace[app.name].inline ||
|
|
2004
2201
|
isTypeModule(app, scriptInfo) ||
|
|
2005
|
-
isSpecialScript(app, scriptInfo)
|
|
2202
|
+
isSpecialScript(app, scriptInfo) ||
|
|
2203
|
+
app.iframe);
|
|
2204
|
+
}
|
|
2205
|
+
// TODO: iframe重新插入window前后不一致,通过iframe Function创建的函数无法复用
|
|
2206
|
+
function getEffectWindow(app) {
|
|
2207
|
+
return app.iframe ? app.sandBox.microAppWindow : globalEnv.rawWindow;
|
|
2006
2208
|
}
|
|
2007
2209
|
// Convert string code to function
|
|
2008
|
-
function code2Function(code) {
|
|
2009
|
-
|
|
2210
|
+
function code2Function(app, code) {
|
|
2211
|
+
const targetWindow = getEffectWindow(app);
|
|
2212
|
+
return new targetWindow.Function(code);
|
|
2010
2213
|
}
|
|
2011
2214
|
/**
|
|
2012
2215
|
* If the appSpace of the current js address has other app, try to reuse parsedFunction of other app
|
|
@@ -2014,10 +2217,10 @@ function code2Function(code) {
|
|
|
2014
2217
|
* @param scriptInfo scriptInfo of current address
|
|
2015
2218
|
* @param currentCode pure code of current address
|
|
2016
2219
|
*/
|
|
2017
|
-
function getExistParseResult(
|
|
2220
|
+
function getExistParseResult(app, scriptInfo, currentCode) {
|
|
2018
2221
|
const appSpace = scriptInfo.appSpace;
|
|
2019
2222
|
for (const item in appSpace) {
|
|
2020
|
-
if (item !==
|
|
2223
|
+
if (item !== app.name) {
|
|
2021
2224
|
const appSpaceData = appSpace[item];
|
|
2022
2225
|
if (appSpaceData.parsedCode === currentCode && appSpaceData.parsedFunction) {
|
|
2023
2226
|
return appSpaceData.parsedFunction;
|
|
@@ -2030,7 +2233,7 @@ function getExistParseResult(appName, scriptInfo, currentCode) {
|
|
|
2030
2233
|
* @returns parsedFunction
|
|
2031
2234
|
*/
|
|
2032
2235
|
function getParsedFunction(app, scriptInfo, parsedCode) {
|
|
2033
|
-
return getExistParseResult(app
|
|
2236
|
+
return getExistParseResult(app, scriptInfo, parsedCode) || code2Function(app, parsedCode);
|
|
2034
2237
|
}
|
|
2035
2238
|
// Prevent randomly created strings from repeating
|
|
2036
2239
|
function getUniqueNonceSrc() {
|
|
@@ -2054,6 +2257,9 @@ function setConvertScriptAttr(convertScript, attrs) {
|
|
|
2054
2257
|
function isWrapInSandBox(app, scriptInfo) {
|
|
2055
2258
|
return app.useSandbox && !isTypeModule(app, scriptInfo);
|
|
2056
2259
|
}
|
|
2260
|
+
function getSandboxType(app, scriptInfo) {
|
|
2261
|
+
return isWrapInSandBox(app, scriptInfo) ? app.iframe ? 'iframe' : 'with' : 'disable';
|
|
2262
|
+
}
|
|
2057
2263
|
/**
|
|
2058
2264
|
* Extract script elements
|
|
2059
2265
|
* @param script script element
|
|
@@ -2062,6 +2268,7 @@ function isWrapInSandBox(app, scriptInfo) {
|
|
|
2062
2268
|
* @param isDynamic dynamic insert
|
|
2063
2269
|
*/
|
|
2064
2270
|
function extractScriptElement(script, parent, app, isDynamic = false) {
|
|
2271
|
+
var _a;
|
|
2065
2272
|
let replaceComment = null;
|
|
2066
2273
|
let src = script.getAttribute('src');
|
|
2067
2274
|
if (src)
|
|
@@ -2073,6 +2280,10 @@ function extractScriptElement(script, parent, app, isDynamic = false) {
|
|
|
2073
2280
|
!scriptTypes.includes(script.type)) ||
|
|
2074
2281
|
script.hasAttribute('ignore') ||
|
|
2075
2282
|
checkIgnoreUrl(src, app.name)) {
|
|
2283
|
+
// 配置为忽略的脚本,清空 rawDocument.currentScript,避免被忽略的脚本内获取 currentScript 出错
|
|
2284
|
+
if ((_a = globalEnv.rawDocument) === null || _a === void 0 ? void 0 : _a.currentScript) {
|
|
2285
|
+
delete globalEnv.rawDocument.currentScript;
|
|
2286
|
+
}
|
|
2076
2287
|
return null;
|
|
2077
2288
|
}
|
|
2078
2289
|
else if ((globalEnv.supportModuleScript && script.noModule) ||
|
|
@@ -2268,13 +2479,13 @@ function fetchScriptSuccess(address, scriptInfo, code, app) {
|
|
|
2268
2479
|
*/
|
|
2269
2480
|
if (!appSpaceData.parsedCode) {
|
|
2270
2481
|
appSpaceData.parsedCode = bindScope(address, app, code, scriptInfo);
|
|
2271
|
-
appSpaceData.
|
|
2482
|
+
appSpaceData.sandboxType = getSandboxType(app, scriptInfo);
|
|
2272
2483
|
if (!isInlineMode(app, scriptInfo)) {
|
|
2273
2484
|
try {
|
|
2274
2485
|
appSpaceData.parsedFunction = getParsedFunction(app, scriptInfo, appSpaceData.parsedCode);
|
|
2275
2486
|
}
|
|
2276
2487
|
catch (err) {
|
|
2277
|
-
|
|
2488
|
+
logError('Something went wrong while handling preloaded resources', app.name, '\n', err);
|
|
2278
2489
|
}
|
|
2279
2490
|
}
|
|
2280
2491
|
}
|
|
@@ -2295,7 +2506,8 @@ function execScripts(app, initHook) {
|
|
|
2295
2506
|
const appSpaceData = scriptInfo.appSpace[app.name];
|
|
2296
2507
|
// Notice the second render
|
|
2297
2508
|
if (appSpaceData.defer || appSpaceData.async) {
|
|
2298
|
-
|
|
2509
|
+
// TODO: defer和module彻底分开,不要混在一起
|
|
2510
|
+
if (scriptInfo.isExternal && !scriptInfo.code && !(app.iframe && appSpaceData.module)) {
|
|
2299
2511
|
deferScriptPromise.push(fetchSource(address, app.name));
|
|
2300
2512
|
}
|
|
2301
2513
|
else {
|
|
@@ -2320,7 +2532,7 @@ function execScripts(app, initHook) {
|
|
|
2320
2532
|
logError(err, app.name);
|
|
2321
2533
|
}, () => {
|
|
2322
2534
|
deferScriptInfo.forEach(([address, scriptInfo]) => {
|
|
2323
|
-
if (scriptInfo.code) {
|
|
2535
|
+
if (isString(scriptInfo.code)) {
|
|
2324
2536
|
injectFiberTask(fiberScriptTasks, () => {
|
|
2325
2537
|
runScript(address, app, scriptInfo, initHook);
|
|
2326
2538
|
!isTypeModule(app, scriptInfo) && initHook(false);
|
|
@@ -2364,20 +2576,19 @@ function execScripts(app, initHook) {
|
|
|
2364
2576
|
* @param callback callback of module script
|
|
2365
2577
|
*/
|
|
2366
2578
|
function runScript(address, app, scriptInfo, callback, replaceElement) {
|
|
2367
|
-
var _a;
|
|
2368
2579
|
try {
|
|
2369
2580
|
actionsBeforeRunScript(app);
|
|
2370
2581
|
const appSpaceData = scriptInfo.appSpace[app.name];
|
|
2371
|
-
const
|
|
2582
|
+
const sandboxType = getSandboxType(app, scriptInfo);
|
|
2372
2583
|
/**
|
|
2373
2584
|
* NOTE:
|
|
2374
2585
|
* 1. plugins and wrapCode will only be executed once
|
|
2375
2586
|
* 2. if parsedCode not exist, parsedFunction is not exist
|
|
2376
2587
|
* 3. if parsedCode exist, parsedFunction does not necessarily exist
|
|
2377
2588
|
*/
|
|
2378
|
-
if (!appSpaceData.parsedCode || appSpaceData.
|
|
2589
|
+
if (!appSpaceData.parsedCode || appSpaceData.sandboxType !== sandboxType) {
|
|
2379
2590
|
appSpaceData.parsedCode = bindScope(address, app, scriptInfo.code, scriptInfo);
|
|
2380
|
-
appSpaceData.
|
|
2591
|
+
appSpaceData.sandboxType = sandboxType;
|
|
2381
2592
|
appSpaceData.parsedFunction = null;
|
|
2382
2593
|
}
|
|
2383
2594
|
if (isInlineMode(app, scriptInfo)) {
|
|
@@ -2385,7 +2596,8 @@ function runScript(address, app, scriptInfo, callback, replaceElement) {
|
|
|
2385
2596
|
runCode2InlineScript(address, appSpaceData.parsedCode, isTypeModule(app, scriptInfo), scriptElement, appSpaceData.attrs, callback);
|
|
2386
2597
|
if (!replaceElement) {
|
|
2387
2598
|
// TEST IGNORE
|
|
2388
|
-
|
|
2599
|
+
const parent = app.iframe ? app.sandBox.microBody : app.querySelector('micro-app-body');
|
|
2600
|
+
parent === null || parent === void 0 ? void 0 : parent.appendChild(scriptElement);
|
|
2389
2601
|
}
|
|
2390
2602
|
}
|
|
2391
2603
|
else {
|
|
@@ -2417,7 +2629,7 @@ function runDynamicRemoteScript(address, app, scriptInfo, originScript) {
|
|
|
2417
2629
|
runScript(address, app, scriptInfo, dispatchScriptOnLoadEvent, replaceElement);
|
|
2418
2630
|
!isTypeModule(app, scriptInfo) && dispatchScriptOnLoadEvent();
|
|
2419
2631
|
};
|
|
2420
|
-
if (scriptInfo.code) {
|
|
2632
|
+
if (scriptInfo.code || (app.iframe && scriptInfo.appSpace[app.name].module)) {
|
|
2421
2633
|
defer(runDynamicScript);
|
|
2422
2634
|
}
|
|
2423
2635
|
else {
|
|
@@ -2464,6 +2676,9 @@ function runCode2InlineScript(address, code, module, scriptElement, attrs, callb
|
|
|
2464
2676
|
scriptElement.setAttribute('type', 'module');
|
|
2465
2677
|
if (callback) {
|
|
2466
2678
|
callback.moduleCount && callback.moduleCount--;
|
|
2679
|
+
/**
|
|
2680
|
+
* module script will execute onload method only after it insert to document/iframe
|
|
2681
|
+
*/
|
|
2467
2682
|
scriptElement.onload = callback.bind(scriptElement, callback.moduleCount === 0);
|
|
2468
2683
|
}
|
|
2469
2684
|
}
|
|
@@ -2478,7 +2693,7 @@ function runParsedFunction(app, scriptInfo) {
|
|
|
2478
2693
|
if (!appSpaceData.parsedFunction) {
|
|
2479
2694
|
appSpaceData.parsedFunction = getParsedFunction(app, scriptInfo, appSpaceData.parsedCode);
|
|
2480
2695
|
}
|
|
2481
|
-
appSpaceData.parsedFunction.call(
|
|
2696
|
+
appSpaceData.parsedFunction.call(getEffectWindow(app));
|
|
2482
2697
|
}
|
|
2483
2698
|
/**
|
|
2484
2699
|
* bind js scope
|
|
@@ -2487,12 +2702,12 @@ function runParsedFunction(app, scriptInfo) {
|
|
|
2487
2702
|
* @param scriptInfo source script info
|
|
2488
2703
|
*/
|
|
2489
2704
|
function bindScope(address, app, code, scriptInfo) {
|
|
2490
|
-
// TODO: cache
|
|
2705
|
+
// TODO: 1、cache 2、esm code is null
|
|
2491
2706
|
if (isPlainObject(microApp.options.plugins)) {
|
|
2492
2707
|
code = usePlugins(address, code, app.name, microApp.options.plugins);
|
|
2493
2708
|
}
|
|
2494
2709
|
if (isWrapInSandBox(app, scriptInfo)) {
|
|
2495
|
-
return `;(function(proxyWindow){with(proxyWindow.__MICRO_APP_WINDOW__){(function(${globalKeyToBeCached}){;${code}\n${isInlineScript(address) ? '' : `//# sourceURL=${address}\n`}}).call(proxyWindow,${globalKeyToBeCached})}})(window.__MICRO_APP_PROXY_WINDOW__);`;
|
|
2710
|
+
return app.iframe ? `(function(window,self,global,location){;${code}\n${isInlineScript(address) ? '' : `//# sourceURL=${address}\n`}}).call(window.__MICRO_APP_SANDBOX__.proxyWindow,window.__MICRO_APP_SANDBOX__.proxyWindow,window.__MICRO_APP_SANDBOX__.proxyWindow,window.__MICRO_APP_SANDBOX__.proxyWindow,window.__MICRO_APP_SANDBOX__.proxyLocation);` : `;(function(proxyWindow){with(proxyWindow.__MICRO_APP_WINDOW__){(function(${globalKeyToBeCached}){;${code}\n${isInlineScript(address) ? '' : `//# sourceURL=${address}\n`}}).call(proxyWindow,${globalKeyToBeCached})}})(window.__MICRO_APP_PROXY_WINDOW__);`;
|
|
2496
2711
|
}
|
|
2497
2712
|
return code;
|
|
2498
2713
|
}
|
|
@@ -2555,7 +2770,7 @@ function flatChildren(parent, app, microAppHead, fiberStyleTasks) {
|
|
|
2555
2770
|
flatChildren(child, app, microAppHead, fiberStyleTasks);
|
|
2556
2771
|
});
|
|
2557
2772
|
for (const dom of children) {
|
|
2558
|
-
if (dom
|
|
2773
|
+
if (isLinkElement(dom)) {
|
|
2559
2774
|
if (dom.hasAttribute('exclude') || checkExcludeUrl(dom.getAttribute('href'), app.name)) {
|
|
2560
2775
|
parent.replaceChild(document.createComment('link element with exclude attribute ignored by micro-app'), dom);
|
|
2561
2776
|
}
|
|
@@ -2566,7 +2781,7 @@ function flatChildren(parent, app, microAppHead, fiberStyleTasks) {
|
|
|
2566
2781
|
dom.setAttribute('href', CompletionPath(dom.getAttribute('href'), app.url));
|
|
2567
2782
|
}
|
|
2568
2783
|
}
|
|
2569
|
-
else if (dom
|
|
2784
|
+
else if (isStyleElement(dom)) {
|
|
2570
2785
|
if (dom.hasAttribute('exclude')) {
|
|
2571
2786
|
parent.replaceChild(document.createComment('style element with exclude attribute ignored by micro-app'), dom);
|
|
2572
2787
|
}
|
|
@@ -2574,10 +2789,10 @@ function flatChildren(parent, app, microAppHead, fiberStyleTasks) {
|
|
|
2574
2789
|
injectFiberTask(fiberStyleTasks, () => scopedCSS(dom, app));
|
|
2575
2790
|
}
|
|
2576
2791
|
}
|
|
2577
|
-
else if (dom
|
|
2792
|
+
else if (isScriptElement(dom)) {
|
|
2578
2793
|
extractScriptElement(dom, parent, app);
|
|
2579
2794
|
}
|
|
2580
|
-
else if (dom
|
|
2795
|
+
else if (isImageElement(dom) && dom.hasAttribute('src')) {
|
|
2581
2796
|
dom.setAttribute('src', CompletionPath(dom.getAttribute('src'), app.url));
|
|
2582
2797
|
}
|
|
2583
2798
|
/**
|
|
@@ -2600,8 +2815,8 @@ function flatChildren(parent, app, microAppHead, fiberStyleTasks) {
|
|
|
2600
2815
|
*/
|
|
2601
2816
|
function extractSourceDom(htmlStr, app) {
|
|
2602
2817
|
const wrapElement = getWrapElement(htmlStr);
|
|
2603
|
-
const microAppHead =
|
|
2604
|
-
const microAppBody =
|
|
2818
|
+
const microAppHead = globalEnv.rawElementQuerySelector.call(wrapElement, 'micro-app-head');
|
|
2819
|
+
const microAppBody = globalEnv.rawElementQuerySelector.call(wrapElement, 'micro-app-body');
|
|
2605
2820
|
if (!microAppHead || !microAppBody) {
|
|
2606
2821
|
const msg = `element ${microAppHead ? 'body' : 'head'} is missing`;
|
|
2607
2822
|
app.onerror(new Error(msg));
|
|
@@ -2802,7 +3017,7 @@ const eventCenter = new EventCenter();
|
|
|
2802
3017
|
* @param appName app.name
|
|
2803
3018
|
* @param fromBaseApp is from base app
|
|
2804
3019
|
*/
|
|
2805
|
-
function
|
|
3020
|
+
function createEventName(appName, fromBaseApp) {
|
|
2806
3021
|
if (!isString(appName) || !appName)
|
|
2807
3022
|
return '';
|
|
2808
3023
|
return fromBaseApp ? `__from_base_app_${appName}__` : `__from_micro_app_${appName}__`;
|
|
@@ -2881,7 +3096,7 @@ class EventCenterForBaseApp extends EventCenterForGlobal {
|
|
|
2881
3096
|
* @param autoTrigger If there is cached data when first bind listener, whether it needs to trigger, default is false
|
|
2882
3097
|
*/
|
|
2883
3098
|
addDataListener(appName, cb, autoTrigger) {
|
|
2884
|
-
eventCenter.on(
|
|
3099
|
+
eventCenter.on(createEventName(formatAppName(appName), false), cb, autoTrigger);
|
|
2885
3100
|
}
|
|
2886
3101
|
/**
|
|
2887
3102
|
* remove listener
|
|
@@ -2889,7 +3104,7 @@ class EventCenterForBaseApp extends EventCenterForGlobal {
|
|
|
2889
3104
|
* @param cb listener
|
|
2890
3105
|
*/
|
|
2891
3106
|
removeDataListener(appName, cb) {
|
|
2892
|
-
isFunction(cb) && eventCenter.off(
|
|
3107
|
+
isFunction(cb) && eventCenter.off(createEventName(formatAppName(appName), false), cb);
|
|
2893
3108
|
}
|
|
2894
3109
|
/**
|
|
2895
3110
|
* get data from micro app or base app
|
|
@@ -2897,7 +3112,7 @@ class EventCenterForBaseApp extends EventCenterForGlobal {
|
|
|
2897
3112
|
* @param fromBaseApp whether get data from base app, default is false
|
|
2898
3113
|
*/
|
|
2899
3114
|
getData(appName, fromBaseApp = false) {
|
|
2900
|
-
return eventCenter.getData(
|
|
3115
|
+
return eventCenter.getData(createEventName(formatAppName(appName), fromBaseApp));
|
|
2901
3116
|
}
|
|
2902
3117
|
/**
|
|
2903
3118
|
* Dispatch data to the specified micro app
|
|
@@ -2905,7 +3120,7 @@ class EventCenterForBaseApp extends EventCenterForGlobal {
|
|
|
2905
3120
|
* @param data data
|
|
2906
3121
|
*/
|
|
2907
3122
|
setData(appName, data, nextStep, force) {
|
|
2908
|
-
eventCenter.dispatch(
|
|
3123
|
+
eventCenter.dispatch(createEventName(formatAppName(appName), true), data, (resArr) => isFunction(nextStep) && nextStep(resArr), force);
|
|
2909
3124
|
}
|
|
2910
3125
|
forceSetData(appName, data, nextStep) {
|
|
2911
3126
|
this.setData(appName, data, nextStep, true);
|
|
@@ -2916,14 +3131,14 @@ class EventCenterForBaseApp extends EventCenterForGlobal {
|
|
|
2916
3131
|
* @param fromBaseApp whether clear data from child app, default is true
|
|
2917
3132
|
*/
|
|
2918
3133
|
clearData(appName, fromBaseApp = true) {
|
|
2919
|
-
eventCenter.clearData(
|
|
3134
|
+
eventCenter.clearData(createEventName(formatAppName(appName), fromBaseApp));
|
|
2920
3135
|
}
|
|
2921
3136
|
/**
|
|
2922
3137
|
* clear all listener for specified micro app
|
|
2923
3138
|
* @param appName app.name
|
|
2924
3139
|
*/
|
|
2925
3140
|
clearDataListener(appName) {
|
|
2926
|
-
eventCenter.off(
|
|
3141
|
+
eventCenter.off(createEventName(formatAppName(appName), false));
|
|
2927
3142
|
}
|
|
2928
3143
|
}
|
|
2929
3144
|
// Event center for sub app
|
|
@@ -2940,20 +3155,20 @@ class EventCenterForMicroApp extends EventCenterForGlobal {
|
|
|
2940
3155
|
*/
|
|
2941
3156
|
addDataListener(cb, autoTrigger) {
|
|
2942
3157
|
cb.__AUTO_TRIGGER__ = autoTrigger;
|
|
2943
|
-
eventCenter.on(
|
|
3158
|
+
eventCenter.on(createEventName(this.appName, true), cb, autoTrigger);
|
|
2944
3159
|
}
|
|
2945
3160
|
/**
|
|
2946
3161
|
* remove listener
|
|
2947
3162
|
* @param cb listener
|
|
2948
3163
|
*/
|
|
2949
3164
|
removeDataListener(cb) {
|
|
2950
|
-
isFunction(cb) && eventCenter.off(
|
|
3165
|
+
isFunction(cb) && eventCenter.off(createEventName(this.appName, true), cb);
|
|
2951
3166
|
}
|
|
2952
3167
|
/**
|
|
2953
3168
|
* get data from base app
|
|
2954
3169
|
*/
|
|
2955
3170
|
getData(fromBaseApp = true) {
|
|
2956
|
-
return eventCenter.getData(
|
|
3171
|
+
return eventCenter.getData(createEventName(this.appName, fromBaseApp));
|
|
2957
3172
|
}
|
|
2958
3173
|
/**
|
|
2959
3174
|
* dispatch data to base app
|
|
@@ -2961,12 +3176,12 @@ class EventCenterForMicroApp extends EventCenterForGlobal {
|
|
|
2961
3176
|
*/
|
|
2962
3177
|
dispatch(data, nextStep, force) {
|
|
2963
3178
|
removeDomScope();
|
|
2964
|
-
eventCenter.dispatch(
|
|
3179
|
+
eventCenter.dispatch(createEventName(this.appName, false), data, (resArr) => isFunction(nextStep) && nextStep(resArr), force, () => {
|
|
2965
3180
|
const app = appInstanceMap.get(this.appName);
|
|
2966
3181
|
if ((app === null || app === void 0 ? void 0 : app.container) && isPlainObject(data)) {
|
|
2967
3182
|
const event = new CustomEvent('datachange', {
|
|
2968
3183
|
detail: {
|
|
2969
|
-
data: eventCenter.getData(
|
|
3184
|
+
data: eventCenter.getData(createEventName(this.appName, false))
|
|
2970
3185
|
}
|
|
2971
3186
|
});
|
|
2972
3187
|
getRootContainer(app.container).dispatchEvent(event);
|
|
@@ -2981,33 +3196,35 @@ class EventCenterForMicroApp extends EventCenterForGlobal {
|
|
|
2981
3196
|
* @param fromBaseApp whether clear data from base app, default is false
|
|
2982
3197
|
*/
|
|
2983
3198
|
clearData(fromBaseApp = false) {
|
|
2984
|
-
eventCenter.clearData(
|
|
3199
|
+
eventCenter.clearData(createEventName(this.appName, fromBaseApp));
|
|
2985
3200
|
}
|
|
2986
3201
|
/**
|
|
2987
3202
|
* clear all listeners
|
|
2988
3203
|
*/
|
|
2989
3204
|
clearDataListener() {
|
|
2990
|
-
eventCenter.off(
|
|
3205
|
+
eventCenter.off(createEventName(this.appName, true));
|
|
2991
3206
|
}
|
|
2992
3207
|
}
|
|
2993
3208
|
/**
|
|
2994
3209
|
* Record UMD function before exec umdHookMount
|
|
2995
|
-
*
|
|
3210
|
+
* NOTE: record maybe call twice when unmount prerender, keep-alive app manually with umd mode
|
|
3211
|
+
* @param microAppEventCenter instance of EventCenterForMicroApp
|
|
2996
3212
|
*/
|
|
2997
3213
|
function recordDataCenterSnapshot(microAppEventCenter) {
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3214
|
+
if (microAppEventCenter && !microAppEventCenter.umdDataListeners) {
|
|
3215
|
+
microAppEventCenter.umdDataListeners = { global: new Set(), normal: new Set() };
|
|
3216
|
+
const globalEventInfo = eventCenter.eventList.get('global');
|
|
3217
|
+
if (globalEventInfo) {
|
|
3218
|
+
for (const cb of globalEventInfo.callbacks) {
|
|
3219
|
+
if (microAppEventCenter.appName === cb.__APP_NAME__) {
|
|
3220
|
+
microAppEventCenter.umdDataListeners.global.add(cb);
|
|
3221
|
+
}
|
|
3005
3222
|
}
|
|
3006
3223
|
}
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3224
|
+
const subAppEventInfo = eventCenter.eventList.get(createEventName(microAppEventCenter.appName, true));
|
|
3225
|
+
if (subAppEventInfo) {
|
|
3226
|
+
microAppEventCenter.umdDataListeners.normal = new Set(subAppEventInfo.callbacks);
|
|
3227
|
+
}
|
|
3011
3228
|
}
|
|
3012
3229
|
}
|
|
3013
3230
|
/**
|
|
@@ -3015,13 +3232,24 @@ function recordDataCenterSnapshot(microAppEventCenter) {
|
|
|
3015
3232
|
* @param microAppEventCenter instance of EventCenterForMicroApp
|
|
3016
3233
|
*/
|
|
3017
3234
|
function rebuildDataCenterSnapshot(microAppEventCenter) {
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3235
|
+
// in withSandbox preRender mode with module script, umdDataListeners maybe undefined
|
|
3236
|
+
if (microAppEventCenter === null || microAppEventCenter === void 0 ? void 0 : microAppEventCenter.umdDataListeners) {
|
|
3237
|
+
for (const cb of microAppEventCenter.umdDataListeners.global) {
|
|
3238
|
+
microAppEventCenter.addGlobalDataListener(cb, cb.__AUTO_TRIGGER__);
|
|
3239
|
+
}
|
|
3240
|
+
for (const cb of microAppEventCenter.umdDataListeners.normal) {
|
|
3241
|
+
microAppEventCenter.addDataListener(cb, cb.__AUTO_TRIGGER__);
|
|
3242
|
+
}
|
|
3243
|
+
resetDataCenterSnapshot(microAppEventCenter);
|
|
3023
3244
|
}
|
|
3024
3245
|
}
|
|
3246
|
+
/**
|
|
3247
|
+
* delete umdDataListeners from microAppEventCenter
|
|
3248
|
+
* @param microAppEventCenter instance of EventCenterForMicroApp
|
|
3249
|
+
*/
|
|
3250
|
+
function resetDataCenterSnapshot(microAppEventCenter) {
|
|
3251
|
+
delete microAppEventCenter.umdDataListeners;
|
|
3252
|
+
}
|
|
3025
3253
|
|
|
3026
3254
|
// 管理 app 的单例
|
|
3027
3255
|
class AppManager {
|
|
@@ -3084,12 +3312,12 @@ function isConstructorFunction(value) {
|
|
|
3084
3312
|
return value.__MICRO_APP_IS_CONSTRUCTOR__ = isConstructor(value);
|
|
3085
3313
|
}
|
|
3086
3314
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
3087
|
-
function
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
const bindRawObjectValue = value.bind(
|
|
3315
|
+
function bindFunctionToRawTarget(value, rawTarget, key = 'WINDOW') {
|
|
3316
|
+
if (isFunction(value) && !isConstructorFunction(value) && !isBoundedFunction(value)) {
|
|
3317
|
+
const cacheKey = `__MICRO_APP_BOUND_${key}_FUNCTION__`;
|
|
3318
|
+
if (value[cacheKey])
|
|
3319
|
+
return value[cacheKey];
|
|
3320
|
+
const bindRawObjectValue = value.bind(rawTarget);
|
|
3093
3321
|
for (const key in value) {
|
|
3094
3322
|
bindRawObjectValue[key] = value[key];
|
|
3095
3323
|
}
|
|
@@ -3106,21 +3334,6 @@ function bindFunctionToRawObject(rawObject, value, key = 'WINDOW') {
|
|
|
3106
3334
|
return value;
|
|
3107
3335
|
}
|
|
3108
3336
|
|
|
3109
|
-
// this events should be sent to the specified app
|
|
3110
|
-
const formatEventList = ['unmount', 'appstate-change'];
|
|
3111
|
-
/**
|
|
3112
|
-
* Format event name
|
|
3113
|
-
* @param eventName event name
|
|
3114
|
-
* @param appName app name
|
|
3115
|
-
*/
|
|
3116
|
-
function formatEventName$1(eventName, appName) {
|
|
3117
|
-
var _a;
|
|
3118
|
-
if (formatEventList.includes(eventName) ||
|
|
3119
|
-
((eventName === 'popstate' || eventName === 'hashchange') && ((_a = appInstanceMap.get(appName)) === null || _a === void 0 ? void 0 : _a.useMemoryRouter))) {
|
|
3120
|
-
return `${eventName}-${appName}`;
|
|
3121
|
-
}
|
|
3122
|
-
return eventName;
|
|
3123
|
-
}
|
|
3124
3337
|
// document.onclick binding list, the binding function of each application is unique
|
|
3125
3338
|
const documentClickListMap = new Map();
|
|
3126
3339
|
let hasRewriteDocumentOnClick = false;
|
|
@@ -3231,7 +3444,7 @@ function effect(appName, microAppWindow) {
|
|
|
3231
3444
|
const { rawWindow, rawDocument, rawWindowAddEventListener, rawWindowRemoveEventListener, rawSetInterval, rawSetTimeout, rawClearInterval, rawClearTimeout, rawDocumentRemoveEventListener, } = globalEnv;
|
|
3232
3445
|
// listener may be null, e.g test-passive
|
|
3233
3446
|
microAppWindow.addEventListener = function (type, listener, options) {
|
|
3234
|
-
type = formatEventName
|
|
3447
|
+
type = formatEventName(type, appName);
|
|
3235
3448
|
const listenerList = eventListenerMap.get(type);
|
|
3236
3449
|
if (listenerList) {
|
|
3237
3450
|
listenerList.add(listener);
|
|
@@ -3243,7 +3456,7 @@ function effect(appName, microAppWindow) {
|
|
|
3243
3456
|
rawWindowAddEventListener.call(rawWindow, type, listener, options);
|
|
3244
3457
|
};
|
|
3245
3458
|
microAppWindow.removeEventListener = function (type, listener, options) {
|
|
3246
|
-
type = formatEventName
|
|
3459
|
+
type = formatEventName(type, appName);
|
|
3247
3460
|
const listenerList = eventListenerMap.get(type);
|
|
3248
3461
|
if ((listenerList === null || listenerList === void 0 ? void 0 : listenerList.size) && listenerList.has(listener)) {
|
|
3249
3462
|
listenerList.delete(listener);
|
|
@@ -3270,39 +3483,32 @@ function effect(appName, microAppWindow) {
|
|
|
3270
3483
|
};
|
|
3271
3484
|
const sstWindowListenerMap = new Map();
|
|
3272
3485
|
const sstDocumentListenerMap = new Map();
|
|
3273
|
-
let sstIntervalIdMap = new Map();
|
|
3274
|
-
let sstTimeoutIdMap = new Map();
|
|
3275
3486
|
let sstOnClickHandler;
|
|
3276
|
-
|
|
3487
|
+
// reset snapshot data
|
|
3488
|
+
const reset = () => {
|
|
3277
3489
|
sstWindowListenerMap.clear();
|
|
3278
|
-
sstIntervalIdMap.clear();
|
|
3279
|
-
sstTimeoutIdMap.clear();
|
|
3280
3490
|
sstDocumentListenerMap.clear();
|
|
3281
3491
|
sstOnClickHandler = null;
|
|
3282
3492
|
};
|
|
3283
3493
|
/**
|
|
3284
|
-
*
|
|
3285
|
-
*
|
|
3286
|
-
*
|
|
3287
|
-
*
|
|
3288
|
-
*
|
|
3494
|
+
* NOTE:
|
|
3495
|
+
* 1. about timer(events & properties should record & rebuild at all modes, exclude default mode)
|
|
3496
|
+
* 2. record maybe call twice when unmount prerender, keep-alive app manually with umd mode
|
|
3497
|
+
* 4 modes: default-mode、umd-mode、prerender、keep-alive
|
|
3498
|
+
* Solution:
|
|
3499
|
+
* 1. default-mode(normal): clear events & timers, not record & rebuild anything
|
|
3500
|
+
* 2. umd-mode(normal): not clear timers, record & rebuild events
|
|
3501
|
+
* 3. prerender/keep-alive(default, umd): not clear timers, record & rebuild events
|
|
3289
3502
|
*/
|
|
3290
|
-
const
|
|
3503
|
+
const record = () => {
|
|
3291
3504
|
// record window event
|
|
3292
3505
|
eventListenerMap.forEach((listenerList, type) => {
|
|
3293
3506
|
if (listenerList.size) {
|
|
3294
3507
|
sstWindowListenerMap.set(type, new Set(listenerList));
|
|
3295
3508
|
}
|
|
3296
3509
|
});
|
|
3297
|
-
// record timers
|
|
3298
|
-
if (intervalIdMap.size) {
|
|
3299
|
-
sstIntervalIdMap = new Map(intervalIdMap);
|
|
3300
|
-
}
|
|
3301
|
-
if (timeoutIdMap.size) {
|
|
3302
|
-
sstTimeoutIdMap = new Map(timeoutIdMap);
|
|
3303
|
-
}
|
|
3304
3510
|
// record onclick handler
|
|
3305
|
-
sstOnClickHandler = documentClickListMap.get(appName);
|
|
3511
|
+
sstOnClickHandler = sstOnClickHandler || documentClickListMap.get(appName);
|
|
3306
3512
|
// record document event
|
|
3307
3513
|
const documentAppListenersMap = documentEventListenerMap.get(appName);
|
|
3308
3514
|
if (documentAppListenersMap) {
|
|
@@ -3314,20 +3520,13 @@ function effect(appName, microAppWindow) {
|
|
|
3314
3520
|
}
|
|
3315
3521
|
};
|
|
3316
3522
|
// rebuild event and timer before remount app
|
|
3317
|
-
const
|
|
3523
|
+
const rebuild = () => {
|
|
3318
3524
|
// rebuild window event
|
|
3319
3525
|
sstWindowListenerMap.forEach((listenerList, type) => {
|
|
3320
3526
|
for (const listener of listenerList) {
|
|
3321
3527
|
microAppWindow.addEventListener(type, listener, listener === null || listener === void 0 ? void 0 : listener.__MICRO_APP_MARK_OPTIONS__);
|
|
3322
3528
|
}
|
|
3323
3529
|
});
|
|
3324
|
-
// rebuild timer
|
|
3325
|
-
sstIntervalIdMap.forEach((info) => {
|
|
3326
|
-
microAppWindow.setInterval(info.handler, info.timeout, ...info.args);
|
|
3327
|
-
});
|
|
3328
|
-
sstTimeoutIdMap.forEach((info) => {
|
|
3329
|
-
microAppWindow.setTimeout(info.handler, info.timeout, ...info.args);
|
|
3330
|
-
});
|
|
3331
3530
|
// rebuild onclick event
|
|
3332
3531
|
sstOnClickHandler && documentClickListMap.set(appName, sstOnClickHandler);
|
|
3333
3532
|
/**
|
|
@@ -3341,10 +3540,10 @@ function effect(appName, microAppWindow) {
|
|
|
3341
3540
|
}
|
|
3342
3541
|
});
|
|
3343
3542
|
removeDomScope();
|
|
3344
|
-
|
|
3543
|
+
reset();
|
|
3345
3544
|
};
|
|
3346
3545
|
// release all event listener & interval & timeout when unmount app
|
|
3347
|
-
const
|
|
3546
|
+
const release = ({ umdMode, isPrerender, keepAlive, destroy }) => {
|
|
3348
3547
|
// Clear window binding events
|
|
3349
3548
|
if (eventListenerMap.size) {
|
|
3350
3549
|
eventListenerMap.forEach((listenerList, type) => {
|
|
@@ -3354,17 +3553,15 @@ function effect(appName, microAppWindow) {
|
|
|
3354
3553
|
});
|
|
3355
3554
|
eventListenerMap.clear();
|
|
3356
3555
|
}
|
|
3357
|
-
//
|
|
3358
|
-
if (
|
|
3556
|
+
// default mode(not keep-alive or isPrerender)
|
|
3557
|
+
if ((!umdMode && !keepAlive && !isPrerender) || destroy) {
|
|
3359
3558
|
intervalIdMap.forEach((_, intervalId) => {
|
|
3360
3559
|
rawClearInterval.call(rawWindow, intervalId);
|
|
3361
3560
|
});
|
|
3362
|
-
intervalIdMap.clear();
|
|
3363
|
-
}
|
|
3364
|
-
if (timeoutIdMap.size) {
|
|
3365
3561
|
timeoutIdMap.forEach((_, timeoutId) => {
|
|
3366
3562
|
rawClearTimeout.call(rawWindow, timeoutId);
|
|
3367
3563
|
});
|
|
3564
|
+
intervalIdMap.clear();
|
|
3368
3565
|
timeoutIdMap.clear();
|
|
3369
3566
|
}
|
|
3370
3567
|
// Clear the function bound by micro application through document.onclick
|
|
@@ -3381,9 +3578,10 @@ function effect(appName, microAppWindow) {
|
|
|
3381
3578
|
}
|
|
3382
3579
|
};
|
|
3383
3580
|
return {
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3581
|
+
reset,
|
|
3582
|
+
record,
|
|
3583
|
+
rebuild,
|
|
3584
|
+
release,
|
|
3387
3585
|
};
|
|
3388
3586
|
}
|
|
3389
3587
|
|
|
@@ -3578,25 +3776,29 @@ function addHistoryListener(appName) {
|
|
|
3578
3776
|
* 1. unmount app & hidden keep-alive app will not receive popstate event
|
|
3579
3777
|
* 2. filter out onlyForBrowser
|
|
3580
3778
|
*/
|
|
3581
|
-
if (getActiveApps({
|
|
3779
|
+
if (getActiveApps({
|
|
3780
|
+
excludeHiddenApp: true,
|
|
3781
|
+
excludePreRender: true,
|
|
3782
|
+
}).includes(appName) &&
|
|
3582
3783
|
!e.onlyForBrowser) {
|
|
3583
3784
|
const microPath = getMicroPathFromURL(appName);
|
|
3584
3785
|
const app = appInstanceMap.get(appName);
|
|
3585
3786
|
const proxyWindow = app.sandBox.proxyWindow;
|
|
3787
|
+
const microAppWindow = app.sandBox.microAppWindow;
|
|
3586
3788
|
let isHashChange = false;
|
|
3587
3789
|
// for hashChangeEvent
|
|
3588
3790
|
const oldHref = proxyWindow.location.href;
|
|
3589
3791
|
// Do not attach micro state to url when microPath is empty
|
|
3590
3792
|
if (microPath) {
|
|
3591
3793
|
const oldHash = proxyWindow.location.hash;
|
|
3592
|
-
updateMicroLocation(appName, microPath,
|
|
3794
|
+
updateMicroLocation(appName, microPath, microAppWindow.location);
|
|
3593
3795
|
isHashChange = proxyWindow.location.hash !== oldHash;
|
|
3594
3796
|
}
|
|
3595
3797
|
// dispatch formatted popStateEvent to child
|
|
3596
|
-
dispatchPopStateEventToMicroApp(appName, proxyWindow);
|
|
3798
|
+
dispatchPopStateEventToMicroApp(appName, proxyWindow, microAppWindow);
|
|
3597
3799
|
// dispatch formatted hashChangeEvent to child when hash change
|
|
3598
3800
|
if (isHashChange)
|
|
3599
|
-
dispatchHashChangeEventToMicroApp(appName, proxyWindow, oldHref);
|
|
3801
|
+
dispatchHashChangeEventToMicroApp(appName, proxyWindow, microAppWindow, oldHref);
|
|
3600
3802
|
// clear element scope before trigger event of next app
|
|
3601
3803
|
removeDomScope();
|
|
3602
3804
|
}
|
|
@@ -3612,10 +3814,9 @@ function addHistoryListener(appName) {
|
|
|
3612
3814
|
* @param proxyWindow sandbox window
|
|
3613
3815
|
* @param eventState history.state
|
|
3614
3816
|
*/
|
|
3615
|
-
function dispatchPopStateEventToMicroApp(appName, proxyWindow) {
|
|
3616
|
-
// create PopStateEvent named popstate-appName with sub app state
|
|
3617
|
-
const newPopStateEvent = new PopStateEvent(formatEventName$1('popstate', appName), { state: getMicroState(appName) });
|
|
3817
|
+
function dispatchPopStateEventToMicroApp(appName, proxyWindow, microAppWindow) {
|
|
3618
3818
|
/**
|
|
3819
|
+
* TODO: test
|
|
3619
3820
|
* angular14 takes e.type as type judgment
|
|
3620
3821
|
* when e.type is popstate-appName popstate event will be invalid
|
|
3621
3822
|
*/
|
|
@@ -3625,7 +3826,14 @@ function dispatchPopStateEventToMicroApp(appName, proxyWindow) {
|
|
|
3625
3826
|
// configurable: true,
|
|
3626
3827
|
// enumerable: true,
|
|
3627
3828
|
// })
|
|
3628
|
-
|
|
3829
|
+
// create PopStateEvent named popstate-appName with sub app state
|
|
3830
|
+
const newPopStateEvent = new PopStateEvent(formatEventName('popstate', appName), { state: getMicroState(appName) });
|
|
3831
|
+
if (isIframeSandbox(appName)) {
|
|
3832
|
+
microAppWindow.dispatchEvent(newPopStateEvent);
|
|
3833
|
+
}
|
|
3834
|
+
else {
|
|
3835
|
+
globalEnv.rawWindow.dispatchEvent(newPopStateEvent);
|
|
3836
|
+
}
|
|
3629
3837
|
// call function window.onpopstate if it exists
|
|
3630
3838
|
isFunction(proxyWindow.onpopstate) && proxyWindow.onpopstate(newPopStateEvent);
|
|
3631
3839
|
}
|
|
@@ -3635,12 +3843,17 @@ function dispatchPopStateEventToMicroApp(appName, proxyWindow) {
|
|
|
3635
3843
|
* @param proxyWindow sandbox window
|
|
3636
3844
|
* @param oldHref old href
|
|
3637
3845
|
*/
|
|
3638
|
-
function dispatchHashChangeEventToMicroApp(appName, proxyWindow, oldHref) {
|
|
3639
|
-
const newHashChangeEvent = new HashChangeEvent(formatEventName
|
|
3846
|
+
function dispatchHashChangeEventToMicroApp(appName, proxyWindow, microAppWindow, oldHref) {
|
|
3847
|
+
const newHashChangeEvent = new HashChangeEvent(formatEventName('hashchange', appName), {
|
|
3640
3848
|
newURL: proxyWindow.location.href,
|
|
3641
3849
|
oldURL: oldHref,
|
|
3642
3850
|
});
|
|
3643
|
-
|
|
3851
|
+
if (isIframeSandbox(appName)) {
|
|
3852
|
+
microAppWindow.dispatchEvent(newHashChangeEvent);
|
|
3853
|
+
}
|
|
3854
|
+
else {
|
|
3855
|
+
globalEnv.rawWindow.dispatchEvent(newHashChangeEvent);
|
|
3856
|
+
}
|
|
3644
3857
|
// call function window.onhashchange if it exists
|
|
3645
3858
|
isFunction(proxyWindow.onhashchange) && proxyWindow.onhashchange(newHashChangeEvent);
|
|
3646
3859
|
}
|
|
@@ -3692,22 +3905,26 @@ function createMicroHistory(appName, microLocation) {
|
|
|
3692
3905
|
const rawHistory = globalEnv.rawWindow.history;
|
|
3693
3906
|
function getMicroHistoryMethod(methodName) {
|
|
3694
3907
|
return function (...rests) {
|
|
3908
|
+
var _a, _b, _c;
|
|
3909
|
+
// TODO: 测试iframe的URL兼容isURL的情况
|
|
3695
3910
|
if (isString(rests[2]) || isURL(rests[2])) {
|
|
3696
3911
|
const targetLocation = createURL(rests[2], microLocation.href);
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
updateMicroLocation(appName, targetFullPath, microLocation);
|
|
3702
|
-
}
|
|
3703
|
-
return void 0;
|
|
3912
|
+
const targetFullPath = targetLocation.pathname + targetLocation.search + targetLocation.hash;
|
|
3913
|
+
navigateWithNativeEvent(appName, methodName, setMicroPathToURL(appName, targetLocation), true, setMicroState(appName, rests[0]), rests[1]);
|
|
3914
|
+
if (targetFullPath !== microLocation.fullPath) {
|
|
3915
|
+
updateMicroLocation(appName, targetFullPath, microLocation);
|
|
3704
3916
|
}
|
|
3917
|
+
(_c = (_a = appInstanceMap.get(appName)) === null || _a === void 0 ? void 0 : (_b = _a.sandBox).updateIframeBase) === null || _c === void 0 ? void 0 : _c.call(_b);
|
|
3918
|
+
}
|
|
3919
|
+
else {
|
|
3920
|
+
nativeHistoryNavigate(appName, methodName, rests[2], rests[0], rests[1]);
|
|
3705
3921
|
}
|
|
3706
|
-
nativeHistoryNavigate(appName, methodName, rests[2], rests[0], rests[1]);
|
|
3707
3922
|
};
|
|
3708
3923
|
}
|
|
3709
3924
|
const pushState = getMicroHistoryMethod('pushState');
|
|
3710
3925
|
const replaceState = getMicroHistoryMethod('replaceState');
|
|
3926
|
+
if (isIframeSandbox(appName))
|
|
3927
|
+
return { pushState, replaceState };
|
|
3711
3928
|
return new Proxy(rawHistory, {
|
|
3712
3929
|
get(target, key) {
|
|
3713
3930
|
if (key === 'state') {
|
|
@@ -3719,8 +3936,7 @@ function createMicroHistory(appName, microLocation) {
|
|
|
3719
3936
|
else if (key === 'replaceState') {
|
|
3720
3937
|
return replaceState;
|
|
3721
3938
|
}
|
|
3722
|
-
|
|
3723
|
-
return isFunction(rawValue) ? bindFunctionToRawObject(target, rawValue, 'HISTORY') : rawValue;
|
|
3939
|
+
return bindFunctionToRawTarget(Reflect.get(target, key), target, 'HISTORY');
|
|
3724
3940
|
},
|
|
3725
3941
|
set(target, key, value) {
|
|
3726
3942
|
Reflect.set(target, key, value);
|
|
@@ -3765,6 +3981,7 @@ function navigateWithNativeEvent(appName, methodName, result, onlyForBrowser, st
|
|
|
3765
3981
|
if (isEffectiveApp(appName)) {
|
|
3766
3982
|
const rawLocation = globalEnv.rawWindow.location;
|
|
3767
3983
|
const oldFullPath = rawLocation.pathname + rawLocation.search + rawLocation.hash;
|
|
3984
|
+
// oldHref use for hashChangeEvent of base app
|
|
3768
3985
|
const oldHref = result.isAttach2Hash && oldFullPath !== result.fullPath ? rawLocation.href : null;
|
|
3769
3986
|
// navigate with native history method
|
|
3770
3987
|
nativeHistoryNavigate(appName, methodName, result.fullPath, state, title);
|
|
@@ -3873,8 +4090,9 @@ function createRouterApi() {
|
|
|
3873
4090
|
const microLocation = app.sandBox.proxyWindow.location;
|
|
3874
4091
|
const targetLocation = createURL(to.path, microLocation.href);
|
|
3875
4092
|
// Only get path data, even if the origin is different from microApp
|
|
4093
|
+
const currentFullPath = microLocation.pathname + microLocation.search + microLocation.hash;
|
|
3876
4094
|
const targetFullPath = targetLocation.pathname + targetLocation.search + targetLocation.hash;
|
|
3877
|
-
if (
|
|
4095
|
+
if (currentFullPath !== targetFullPath || getMicroPathFromURL(appName) !== targetFullPath) {
|
|
3878
4096
|
const methodName = (replace && to.replace !== false) || to.replace === true ? 'replaceState' : 'pushState';
|
|
3879
4097
|
navigateWithRawHistory(appName, methodName, targetLocation, to.state);
|
|
3880
4098
|
}
|
|
@@ -4023,8 +4241,7 @@ function createRouterApi() {
|
|
|
4023
4241
|
baseRouterProxy = new Proxy(baseRouter, {
|
|
4024
4242
|
get(target, key) {
|
|
4025
4243
|
removeDomScope();
|
|
4026
|
-
|
|
4027
|
-
return isFunction(rawValue) ? bindFunctionToRawObject(target, rawValue, 'BASEROUTER') : rawValue;
|
|
4244
|
+
return bindFunctionToRawTarget(Reflect.get(target, key), target, 'BASEROUTER');
|
|
4028
4245
|
},
|
|
4029
4246
|
set(target, key, value) {
|
|
4030
4247
|
Reflect.set(target, key, value);
|
|
@@ -4052,9 +4269,118 @@ function createRouterApi() {
|
|
|
4052
4269
|
}
|
|
4053
4270
|
const { router, executeNavigationGuard, clearRouterWhenUnmount, } = createRouterApi();
|
|
4054
4271
|
|
|
4055
|
-
const
|
|
4272
|
+
const escape2RawWindowKeys = [
|
|
4273
|
+
'getComputedStyle',
|
|
4274
|
+
'visualViewport',
|
|
4275
|
+
'matchMedia',
|
|
4276
|
+
// 'DOMParser',
|
|
4277
|
+
'ResizeObserver',
|
|
4278
|
+
'IntersectionObserver',
|
|
4279
|
+
];
|
|
4280
|
+
const escape2RawWindowRegExpKeys = [
|
|
4281
|
+
/animationFrame$/i,
|
|
4282
|
+
/mutationObserver$/i,
|
|
4283
|
+
/height$|width$/i,
|
|
4284
|
+
/offset$/i,
|
|
4285
|
+
// /event$/i,
|
|
4286
|
+
/^screen/i,
|
|
4287
|
+
/^scroll/i,
|
|
4288
|
+
/X$|Y$/,
|
|
4289
|
+
];
|
|
4290
|
+
const scopeIframeWindowOnEvent = [
|
|
4291
|
+
'onload',
|
|
4292
|
+
'onbeforeunload',
|
|
4293
|
+
'onunload',
|
|
4294
|
+
];
|
|
4295
|
+
const scopeIframeWindowEvent = [
|
|
4296
|
+
'hashchange',
|
|
4297
|
+
'popstate',
|
|
4298
|
+
'DOMContentLoaded',
|
|
4299
|
+
'load',
|
|
4300
|
+
'beforeunload',
|
|
4301
|
+
'unload',
|
|
4302
|
+
].concat(microAppCustomEvent);
|
|
4303
|
+
const scopeIframeDocumentEvent = [
|
|
4304
|
+
'DOMContentLoaded',
|
|
4305
|
+
'readystatechange',
|
|
4306
|
+
];
|
|
4307
|
+
const scopeIframeDocumentOnEvent = [
|
|
4308
|
+
'onreadystatechange',
|
|
4309
|
+
];
|
|
4310
|
+
const uniqueDocumentElement = [
|
|
4311
|
+
'body',
|
|
4312
|
+
'head',
|
|
4313
|
+
'html',
|
|
4314
|
+
'title',
|
|
4315
|
+
];
|
|
4316
|
+
const hijackMicroLocationKeys = [
|
|
4317
|
+
'host',
|
|
4318
|
+
'hostname',
|
|
4319
|
+
'port',
|
|
4320
|
+
'protocol',
|
|
4321
|
+
'origin',
|
|
4322
|
+
];
|
|
4323
|
+
// 有shadowRoot则代理到shadowRoot否则代理到原生document上 (属性)
|
|
4324
|
+
const proxy2RawDocOrShadowKeys = [
|
|
4325
|
+
'childElementCount',
|
|
4326
|
+
'children',
|
|
4327
|
+
'firstElementChild',
|
|
4328
|
+
'firstChild',
|
|
4329
|
+
'lastElementChild',
|
|
4330
|
+
'activeElement',
|
|
4331
|
+
'fullscreenElement',
|
|
4332
|
+
'pictureInPictureElement',
|
|
4333
|
+
'pointerLockElement',
|
|
4334
|
+
'styleSheets',
|
|
4335
|
+
];
|
|
4336
|
+
// 有shadowRoot则代理到shadowRoot否则代理到原生document上 (方法)
|
|
4337
|
+
const proxy2RawDocOrShadowMethods = [
|
|
4338
|
+
'append',
|
|
4339
|
+
'contains',
|
|
4340
|
+
'replaceChildren',
|
|
4341
|
+
'getSelection',
|
|
4342
|
+
'elementFromPoint',
|
|
4343
|
+
'elementsFromPoint',
|
|
4344
|
+
'getAnimations',
|
|
4345
|
+
];
|
|
4346
|
+
// 直接代理到原生document上 (属性)
|
|
4347
|
+
const proxy2RawDocumentKeys = [
|
|
4348
|
+
'characterSet',
|
|
4349
|
+
'compatMode',
|
|
4350
|
+
'contentType',
|
|
4351
|
+
'designMode',
|
|
4352
|
+
'dir',
|
|
4353
|
+
'doctype',
|
|
4354
|
+
'embeds',
|
|
4355
|
+
'fullscreenEnabled',
|
|
4356
|
+
'hidden',
|
|
4357
|
+
'implementation',
|
|
4358
|
+
'lastModified',
|
|
4359
|
+
'pictureInPictureEnabled',
|
|
4360
|
+
'plugins',
|
|
4361
|
+
'readyState',
|
|
4362
|
+
'referrer',
|
|
4363
|
+
'visibilityState',
|
|
4364
|
+
'fonts',
|
|
4365
|
+
];
|
|
4366
|
+
// 直接代理到原生document上 (方法)
|
|
4367
|
+
const proxy2RawDocumentMethods = [
|
|
4368
|
+
'execCommand',
|
|
4369
|
+
'createRange',
|
|
4370
|
+
'exitFullscreen',
|
|
4371
|
+
'exitPictureInPicture',
|
|
4372
|
+
'getElementsByTagNameNS',
|
|
4373
|
+
'hasFocus',
|
|
4374
|
+
'prepend',
|
|
4375
|
+
];
|
|
4376
|
+
const globalPropertyList = [
|
|
4377
|
+
'window',
|
|
4378
|
+
'self',
|
|
4379
|
+
'globalThis'
|
|
4380
|
+
];
|
|
4381
|
+
|
|
4056
4382
|
// origin is readonly, so we ignore when updateMicroLocation
|
|
4057
|
-
const locationKeys = [
|
|
4383
|
+
const locationKeys = ['href', 'pathname', 'search', 'hash', 'host', 'hostname', 'port', 'protocol', 'search'];
|
|
4058
4384
|
// origin, fullPath is necessary for guardLocation
|
|
4059
4385
|
const guardLocationKeys = [...locationKeys, 'origin', 'fullPath'];
|
|
4060
4386
|
/**
|
|
@@ -4062,19 +4388,27 @@ const guardLocationKeys = [...locationKeys, 'origin', 'fullPath'];
|
|
|
4062
4388
|
* MDN https://developer.mozilla.org/en-US/docs/Web/API/Location
|
|
4063
4389
|
* @param appName app name
|
|
4064
4390
|
* @param url app url
|
|
4391
|
+
* @param microAppWindow iframeWindow, iframe only
|
|
4392
|
+
* @param childStaticLocation real child location info, iframe only
|
|
4393
|
+
* @param browserHost host of browser, iframe only
|
|
4394
|
+
* @param childHost host of child app, iframe only
|
|
4065
4395
|
*/
|
|
4066
|
-
function createMicroLocation(appName, url) {
|
|
4396
|
+
function createMicroLocation(appName, url, microAppWindow, childStaticLocation, browserHost, childHost) {
|
|
4067
4397
|
const rawWindow = globalEnv.rawWindow;
|
|
4068
4398
|
const rawLocation = rawWindow.location;
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4399
|
+
const isIframe = !!microAppWindow;
|
|
4400
|
+
/**
|
|
4401
|
+
* withLocation is microLocation for with sandbox
|
|
4402
|
+
* it is globally unique for child app
|
|
4403
|
+
*/
|
|
4404
|
+
const withLocation = createURL(url);
|
|
4405
|
+
/**
|
|
4406
|
+
* In iframe, jump through raw iframeLocation will cause microAppWindow.location reset
|
|
4407
|
+
* So we get location dynamically
|
|
4408
|
+
*/
|
|
4409
|
+
function getTarget() {
|
|
4410
|
+
return isIframe ? microAppWindow.location : withLocation;
|
|
4411
|
+
}
|
|
4078
4412
|
/**
|
|
4079
4413
|
* Common handler for href, assign, replace
|
|
4080
4414
|
* It is mainly used to deal with special scenes about hash
|
|
@@ -4082,10 +4416,10 @@ function createMicroLocation(appName, url) {
|
|
|
4082
4416
|
* @param methodName pushState/replaceState
|
|
4083
4417
|
* @returns origin value or formatted value
|
|
4084
4418
|
*/
|
|
4085
|
-
|
|
4086
|
-
const targetLocation = createURL(value,
|
|
4419
|
+
function commonHandler(value, methodName) {
|
|
4420
|
+
const targetLocation = createURL(value, proxyLocation.href);
|
|
4087
4421
|
// Even if the origin is the same, developers still have the possibility of want to jump to a new page
|
|
4088
|
-
if (targetLocation.origin ===
|
|
4422
|
+
if (targetLocation.origin === proxyLocation.origin) {
|
|
4089
4423
|
const setMicroPathResult = setMicroPathToURL(appName, targetLocation);
|
|
4090
4424
|
/**
|
|
4091
4425
|
* change hash with location.href will not trigger the browser reload
|
|
@@ -4094,10 +4428,10 @@ function createMicroLocation(appName, url) {
|
|
|
4094
4428
|
* 1. if child app only change hash, it should not trigger browser reload
|
|
4095
4429
|
* 2. if address is same and has hash, it should not add route stack
|
|
4096
4430
|
*/
|
|
4097
|
-
if (targetLocation.pathname ===
|
|
4098
|
-
targetLocation.search ===
|
|
4431
|
+
if (targetLocation.pathname === proxyLocation.pathname &&
|
|
4432
|
+
targetLocation.search === proxyLocation.search) {
|
|
4099
4433
|
let oldHref = null;
|
|
4100
|
-
if (targetLocation.hash !==
|
|
4434
|
+
if (targetLocation.hash !== proxyLocation.hash) {
|
|
4101
4435
|
if (setMicroPathResult.isAttach2Hash)
|
|
4102
4436
|
oldHref = rawLocation.href;
|
|
4103
4437
|
nativeHistoryNavigate(appName, methodName, setMicroPathResult.fullPath);
|
|
@@ -4106,35 +4440,22 @@ function createMicroLocation(appName, url) {
|
|
|
4106
4440
|
dispatchNativeEvent(appName, false, oldHref);
|
|
4107
4441
|
}
|
|
4108
4442
|
else {
|
|
4109
|
-
|
|
4443
|
+
reload();
|
|
4110
4444
|
}
|
|
4111
4445
|
return void 0;
|
|
4112
4446
|
/**
|
|
4113
4447
|
* when baseApp is hash router, address change of child can not reload browser
|
|
4114
|
-
* so we imitate behavior of browser (reload)
|
|
4448
|
+
* so we imitate behavior of browser (reload) manually
|
|
4115
4449
|
*/
|
|
4116
4450
|
}
|
|
4117
4451
|
else if (setMicroPathResult.isAttach2Hash) {
|
|
4118
4452
|
nativeHistoryNavigate(appName, methodName, setMicroPathResult.fullPath);
|
|
4119
|
-
|
|
4453
|
+
reload();
|
|
4120
4454
|
return void 0;
|
|
4121
4455
|
}
|
|
4122
|
-
|
|
4456
|
+
return setMicroPathResult.fullPath;
|
|
4123
4457
|
}
|
|
4124
4458
|
return value;
|
|
4125
|
-
};
|
|
4126
|
-
/**
|
|
4127
|
-
* create location PropertyDescriptor (href, pathname, search, hash)
|
|
4128
|
-
* @param key property name
|
|
4129
|
-
* @param setter setter of location property
|
|
4130
|
-
*/
|
|
4131
|
-
function createPropertyDescriptor(getter, setter) {
|
|
4132
|
-
return {
|
|
4133
|
-
enumerable: true,
|
|
4134
|
-
configurable: true,
|
|
4135
|
-
get: getter,
|
|
4136
|
-
set: setter,
|
|
4137
|
-
};
|
|
4138
4459
|
}
|
|
4139
4460
|
/**
|
|
4140
4461
|
* common handler for location.pathname & location.search
|
|
@@ -4144,7 +4465,7 @@ function createMicroLocation(appName, url) {
|
|
|
4144
4465
|
function handleForPathNameAndSearch(targetPath, key) {
|
|
4145
4466
|
const targetLocation = createURL(targetPath, url);
|
|
4146
4467
|
// When the browser url has a hash value, the same pathname/search will not refresh browser
|
|
4147
|
-
if (targetLocation[key] ===
|
|
4468
|
+
if (targetLocation[key] === proxyLocation[key] && proxyLocation.hash) {
|
|
4148
4469
|
// The href has not changed, not need to dispatch hashchange event
|
|
4149
4470
|
dispatchNativeEvent(appName, false);
|
|
4150
4471
|
}
|
|
@@ -4155,58 +4476,96 @@ function createMicroLocation(appName, url) {
|
|
|
4155
4476
|
* pathname: /path ==> /path#hash, /path ==> /path?query
|
|
4156
4477
|
* search: ?query ==> ?query#hash
|
|
4157
4478
|
*/
|
|
4158
|
-
nativeHistoryNavigate(appName, targetLocation[key] ===
|
|
4159
|
-
|
|
4479
|
+
nativeHistoryNavigate(appName, targetLocation[key] === proxyLocation[key] ? 'replaceState' : 'pushState', setMicroPathToURL(appName, targetLocation).fullPath);
|
|
4480
|
+
reload();
|
|
4160
4481
|
}
|
|
4161
4482
|
}
|
|
4162
|
-
function rawReload() {
|
|
4163
|
-
isEffectiveApp(appName) && rawLocation.reload();
|
|
4164
|
-
}
|
|
4165
|
-
/**
|
|
4166
|
-
* Special processing for four keys: href, pathname, search and hash
|
|
4167
|
-
* They take values from shadowLocation, and require special operations when assigning values
|
|
4168
|
-
*/
|
|
4169
|
-
rawDefineProperties(microLocation, {
|
|
4170
|
-
href: createPropertyDescriptor(() => shadowLocation.href, (value) => {
|
|
4171
|
-
if (isEffectiveApp(appName)) {
|
|
4172
|
-
const targetPath = commonHandler(value, 'pushState');
|
|
4173
|
-
if (targetPath)
|
|
4174
|
-
rawLocation.href = targetPath;
|
|
4175
|
-
}
|
|
4176
|
-
}),
|
|
4177
|
-
pathname: createPropertyDescriptor(() => shadowLocation.pathname, (value) => {
|
|
4178
|
-
const targetPath = ('/' + value).replace(/^\/+/, '/') + shadowLocation.search + shadowLocation.hash;
|
|
4179
|
-
handleForPathNameAndSearch(targetPath, 'pathname');
|
|
4180
|
-
}),
|
|
4181
|
-
search: createPropertyDescriptor(() => shadowLocation.search, (value) => {
|
|
4182
|
-
const targetPath = shadowLocation.pathname + ('?' + value).replace(/^\?+/, '?') + shadowLocation.hash;
|
|
4183
|
-
handleForPathNameAndSearch(targetPath, 'search');
|
|
4184
|
-
}),
|
|
4185
|
-
hash: createPropertyDescriptor(() => shadowLocation.hash, (value) => {
|
|
4186
|
-
const targetPath = shadowLocation.pathname + shadowLocation.search + ('#' + value).replace(/^#+/, '#');
|
|
4187
|
-
const targetLocation = createURL(targetPath, url);
|
|
4188
|
-
// The same hash will not trigger popStateEvent
|
|
4189
|
-
if (targetLocation.hash !== shadowLocation.hash) {
|
|
4190
|
-
navigateWithNativeEvent(appName, 'pushState', setMicroPathToURL(appName, targetLocation), false);
|
|
4191
|
-
}
|
|
4192
|
-
}),
|
|
4193
|
-
fullPath: createPropertyDescriptor(() => shadowLocation.pathname + shadowLocation.search + shadowLocation.hash, noop),
|
|
4194
|
-
});
|
|
4195
4483
|
const createLocationMethod = (locationMethodName) => {
|
|
4196
4484
|
return function (value) {
|
|
4197
4485
|
if (isEffectiveApp(appName)) {
|
|
4198
4486
|
const targetPath = commonHandler(value, locationMethodName === 'assign' ? 'pushState' : 'replaceState');
|
|
4199
|
-
if (targetPath)
|
|
4200
|
-
|
|
4487
|
+
if (targetPath) {
|
|
4488
|
+
// Same as href, complete targetPath with browser origin in vite env
|
|
4489
|
+
rawLocation[locationMethodName](createURL(targetPath, rawLocation.origin).href);
|
|
4490
|
+
}
|
|
4201
4491
|
}
|
|
4202
4492
|
};
|
|
4203
4493
|
};
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4494
|
+
const assign = createLocationMethod('assign');
|
|
4495
|
+
const replace = createLocationMethod('replace');
|
|
4496
|
+
const reload = (forcedReload) => rawLocation.reload(forcedReload);
|
|
4497
|
+
rawDefineProperty(getTarget(), 'fullPath', {
|
|
4498
|
+
enumerable: true,
|
|
4499
|
+
configurable: true,
|
|
4500
|
+
get: () => proxyLocation.pathname + proxyLocation.search + proxyLocation.hash,
|
|
4501
|
+
});
|
|
4502
|
+
/**
|
|
4503
|
+
* location.assign/replace is readonly, cannot be proxy, so we use empty object as proxy target
|
|
4504
|
+
*/
|
|
4505
|
+
const proxyLocation = new Proxy({}, {
|
|
4506
|
+
get: (_, key) => {
|
|
4507
|
+
const target = getTarget();
|
|
4508
|
+
if (isIframe) {
|
|
4509
|
+
// host hostname port protocol
|
|
4510
|
+
if (hijackMicroLocationKeys.includes(key)) {
|
|
4511
|
+
return childStaticLocation[key];
|
|
4512
|
+
}
|
|
4513
|
+
if (key === 'href') {
|
|
4514
|
+
// do not use target, because target may be deleted
|
|
4515
|
+
return target[key].replace(browserHost, childHost);
|
|
4516
|
+
}
|
|
4517
|
+
}
|
|
4518
|
+
if (key === 'assign')
|
|
4519
|
+
return assign;
|
|
4520
|
+
if (key === 'replace')
|
|
4521
|
+
return replace;
|
|
4522
|
+
if (key === 'reload')
|
|
4523
|
+
return reload;
|
|
4524
|
+
if (key === 'self')
|
|
4525
|
+
return target;
|
|
4526
|
+
return bindFunctionToRawTarget(Reflect.get(target, key), target, 'LOCATION');
|
|
4527
|
+
},
|
|
4528
|
+
set: (_, key, value) => {
|
|
4529
|
+
if (isEffectiveApp(appName)) {
|
|
4530
|
+
const target = getTarget();
|
|
4531
|
+
if (key === 'href') {
|
|
4532
|
+
const targetPath = commonHandler(value, 'pushState');
|
|
4533
|
+
/**
|
|
4534
|
+
* In vite, targetPath without origin will be completed with child origin
|
|
4535
|
+
* So we use browser origin to complete targetPath to avoid this problem
|
|
4536
|
+
* But, why child app can affect browser jump?
|
|
4537
|
+
* Guess(need check):
|
|
4538
|
+
* 1. vite records the origin when init
|
|
4539
|
+
* 2. listen for browser jump and automatically complete the address
|
|
4540
|
+
*/
|
|
4541
|
+
if (targetPath) {
|
|
4542
|
+
rawLocation.href = createURL(targetPath, rawLocation.origin).href;
|
|
4543
|
+
}
|
|
4544
|
+
}
|
|
4545
|
+
else if (key === 'pathname') {
|
|
4546
|
+
const targetPath = ('/' + value).replace(/^\/+/, '/') + proxyLocation.search + proxyLocation.hash;
|
|
4547
|
+
handleForPathNameAndSearch(targetPath, 'pathname');
|
|
4548
|
+
}
|
|
4549
|
+
else if (key === 'search') {
|
|
4550
|
+
const targetPath = proxyLocation.pathname + ('?' + value).replace(/^\?+/, '?') + proxyLocation.hash;
|
|
4551
|
+
handleForPathNameAndSearch(targetPath, 'search');
|
|
4552
|
+
}
|
|
4553
|
+
else if (key === 'hash') {
|
|
4554
|
+
const targetPath = proxyLocation.pathname + proxyLocation.search + ('#' + value).replace(/^#+/, '#');
|
|
4555
|
+
const targetLocation = createURL(targetPath, url);
|
|
4556
|
+
// The same hash will not trigger popStateEvent
|
|
4557
|
+
if (targetLocation.hash !== proxyLocation.hash) {
|
|
4558
|
+
navigateWithNativeEvent(appName, 'pushState', setMicroPathToURL(appName, targetLocation), false);
|
|
4559
|
+
}
|
|
4560
|
+
}
|
|
4561
|
+
else {
|
|
4562
|
+
Reflect.set(target, key, value);
|
|
4563
|
+
}
|
|
4564
|
+
}
|
|
4565
|
+
return true;
|
|
4566
|
+
},
|
|
4209
4567
|
});
|
|
4568
|
+
return proxyLocation;
|
|
4210
4569
|
}
|
|
4211
4570
|
/**
|
|
4212
4571
|
* create guardLocation by microLocation, used for router guard
|
|
@@ -4238,17 +4597,17 @@ function autoTriggerNavigationGuard(appName, microLocation) {
|
|
|
4238
4597
|
* @param type auto prevent
|
|
4239
4598
|
*/
|
|
4240
4599
|
function updateMicroLocation(appName, path, microLocation, type) {
|
|
4241
|
-
|
|
4600
|
+
var _a;
|
|
4242
4601
|
// record old values of microLocation to `from`
|
|
4243
4602
|
const from = createGuardLocation(appName, microLocation);
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
|
|
4249
|
-
|
|
4250
|
-
|
|
4251
|
-
microLocation[key] = newLocation[key];
|
|
4603
|
+
const newLocation = createURL(path, microLocation.href);
|
|
4604
|
+
if (isIframeSandbox(appName)) {
|
|
4605
|
+
const microAppWindow = appInstanceMap.get(appName).sandBox.microAppWindow;
|
|
4606
|
+
(_a = microAppWindow.rawReplaceState) === null || _a === void 0 ? void 0 : _a.call(microAppWindow.history, getMicroState(appName), '', newLocation.href);
|
|
4607
|
+
}
|
|
4608
|
+
else {
|
|
4609
|
+
for (const key of locationKeys) {
|
|
4610
|
+
microLocation.self[key] = newLocation[key];
|
|
4252
4611
|
}
|
|
4253
4612
|
}
|
|
4254
4613
|
// update latest values of microLocation to `to`
|
|
@@ -4426,8 +4785,8 @@ function useMicroEventSource() {
|
|
|
4426
4785
|
}
|
|
4427
4786
|
|
|
4428
4787
|
const { createMicroEventSource, clearMicroEventSource } = useMicroEventSource();
|
|
4429
|
-
const globalPropertyList = ['window', 'self', 'globalThis'];
|
|
4430
|
-
class
|
|
4788
|
+
const globalPropertyList$1 = ['window', 'self', 'globalThis'];
|
|
4789
|
+
class WithSandBox {
|
|
4431
4790
|
constructor(appName, url) {
|
|
4432
4791
|
/**
|
|
4433
4792
|
* Scoped global Properties(Properties that can only get and set in microAppWindow, will not escape to rawWindow)
|
|
@@ -4478,18 +4837,21 @@ class SandBox {
|
|
|
4478
4837
|
this.microAppWindow.__MICRO_APP_BASE_ROUTE__ = this.microAppWindow.__MICRO_APP_BASE_URL__ = baseroute;
|
|
4479
4838
|
}
|
|
4480
4839
|
/**
|
|
4481
|
-
*
|
|
4482
|
-
*
|
|
4483
|
-
*
|
|
4840
|
+
* Target: Ensure default mode action exactly same to first time when render again
|
|
4841
|
+
* 1. The following globalKey maybe modified when render, reset them when render again in default mode
|
|
4842
|
+
* 2. Umd mode will not delete any keys during sandBox.stop, ignore umd mode
|
|
4843
|
+
* 3. When sandbox.start called for the first time, it must be the default mode
|
|
4484
4844
|
*/
|
|
4485
4845
|
if (!umdMode) {
|
|
4486
4846
|
this.initGlobalKeysWhenStart(this.microAppWindow, this.microAppWindow.__MICRO_APP_NAME__, this.microAppWindow.__MICRO_APP_URL__, disablePatchRequest);
|
|
4487
4847
|
}
|
|
4488
|
-
if (++
|
|
4848
|
+
if (++globalEnv.activeSandbox === 1) {
|
|
4849
|
+
patchElementAndDocument();
|
|
4850
|
+
patchHistory();
|
|
4851
|
+
}
|
|
4852
|
+
if (++WithSandBox.activeCount === 1) {
|
|
4489
4853
|
effectDocumentEvent();
|
|
4490
|
-
patchElementPrototypeMethods();
|
|
4491
4854
|
initEnvOfNestedApp();
|
|
4492
|
-
patchHistory();
|
|
4493
4855
|
}
|
|
4494
4856
|
fixBabelPolyfill6();
|
|
4495
4857
|
}
|
|
@@ -4498,28 +4860,25 @@ class SandBox {
|
|
|
4498
4860
|
* close sandbox and perform some clean up actions
|
|
4499
4861
|
* @param umdMode is umd mode
|
|
4500
4862
|
* @param keepRouteState prevent reset route
|
|
4501
|
-
* @param
|
|
4863
|
+
* @param destroy completely destroy, delete cache resources
|
|
4502
4864
|
* @param clearData clear data from base app
|
|
4503
4865
|
*/
|
|
4504
|
-
stop({ umdMode, keepRouteState,
|
|
4866
|
+
stop({ umdMode, keepRouteState, destroy, clearData, }) {
|
|
4505
4867
|
if (this.active) {
|
|
4506
|
-
|
|
4507
|
-
this.releaseGlobalEffect(clearData);
|
|
4868
|
+
this.recordAndReleaseEffect({ clearData, destroy }, !umdMode || destroy);
|
|
4508
4869
|
if (this.removeHistoryListener) {
|
|
4509
4870
|
this.clearRouteState(keepRouteState);
|
|
4510
4871
|
// release listener of popstate
|
|
4511
4872
|
this.removeHistoryListener();
|
|
4512
4873
|
}
|
|
4513
|
-
if (clearEventSource) {
|
|
4514
|
-
clearMicroEventSource(this.microAppWindow.__MICRO_APP_NAME__);
|
|
4515
|
-
}
|
|
4516
4874
|
/**
|
|
4517
4875
|
* NOTE:
|
|
4518
4876
|
* 1. injectedKeys and escapeKeys must be placed at the back
|
|
4519
4877
|
* 2. if key in initial microAppWindow, and then rewrite, this key will be delete from microAppWindow when stop, and lost when restart
|
|
4520
4878
|
* 3. umd mode will not delete global keys
|
|
4521
4879
|
*/
|
|
4522
|
-
if (!umdMode) {
|
|
4880
|
+
if (!umdMode || destroy) {
|
|
4881
|
+
clearMicroEventSource(this.microAppWindow.__MICRO_APP_NAME__);
|
|
4523
4882
|
this.injectedKeys.forEach((key) => {
|
|
4524
4883
|
Reflect.deleteProperty(this.microAppWindow, key);
|
|
4525
4884
|
});
|
|
@@ -4529,30 +4888,47 @@ class SandBox {
|
|
|
4529
4888
|
});
|
|
4530
4889
|
this.escapeKeys.clear();
|
|
4531
4890
|
}
|
|
4532
|
-
if (--
|
|
4533
|
-
|
|
4534
|
-
releasePatches();
|
|
4891
|
+
if (--globalEnv.activeSandbox === 0) {
|
|
4892
|
+
releasePatchElementAndDocument();
|
|
4535
4893
|
releasePatchHistory();
|
|
4536
4894
|
}
|
|
4895
|
+
if (--WithSandBox.activeCount === 0) {
|
|
4896
|
+
releaseEffectDocumentEvent();
|
|
4897
|
+
}
|
|
4537
4898
|
this.active = false;
|
|
4538
4899
|
}
|
|
4539
4900
|
}
|
|
4540
4901
|
/**
|
|
4541
|
-
*
|
|
4902
|
+
* Record global effect and then release (effect: global event, timeout, data listener)
|
|
4542
4903
|
* Scenes:
|
|
4543
|
-
* 1. unmount of
|
|
4904
|
+
* 1. unmount of default/umd app
|
|
4544
4905
|
* 2. hidden keep-alive app
|
|
4545
4906
|
* 3. after init prerender app
|
|
4546
|
-
* @param
|
|
4907
|
+
* @param options {
|
|
4908
|
+
* @param clearData clear data from base app
|
|
4909
|
+
* @param isPrerender is prerender app
|
|
4910
|
+
* @param keepAlive is keep-alive app
|
|
4911
|
+
* }
|
|
4912
|
+
* @param preventRecord prevent record effect events
|
|
4547
4913
|
*/
|
|
4548
|
-
|
|
4549
|
-
|
|
4550
|
-
|
|
4551
|
-
this.microAppWindow.microApp.clearGlobalDataListener();
|
|
4552
|
-
if (clearData) {
|
|
4553
|
-
microApp.clearData(this.microAppWindow.__MICRO_APP_NAME__);
|
|
4554
|
-
this.microAppWindow.microApp.clearData();
|
|
4914
|
+
recordAndReleaseEffect(options, preventRecord = false) {
|
|
4915
|
+
if (preventRecord) {
|
|
4916
|
+
this.resetEffectSnapshot();
|
|
4555
4917
|
}
|
|
4918
|
+
else {
|
|
4919
|
+
this.recordEffectSnapshot();
|
|
4920
|
+
}
|
|
4921
|
+
this.releaseGlobalEffect(options);
|
|
4922
|
+
}
|
|
4923
|
+
/**
|
|
4924
|
+
* reset effect snapshot data in default mode or destroy
|
|
4925
|
+
* Scenes:
|
|
4926
|
+
* 1. unmount hidden keep-alive app manually
|
|
4927
|
+
* 2. unmount prerender app manually
|
|
4928
|
+
*/
|
|
4929
|
+
resetEffectSnapshot() {
|
|
4930
|
+
this.effectController.reset();
|
|
4931
|
+
resetDataCenterSnapshot(this.microAppWindow.microApp);
|
|
4556
4932
|
}
|
|
4557
4933
|
/**
|
|
4558
4934
|
* record umd snapshot before the first execution of umdHookMount
|
|
@@ -4563,7 +4939,7 @@ class SandBox {
|
|
|
4563
4939
|
*/
|
|
4564
4940
|
recordEffectSnapshot() {
|
|
4565
4941
|
// this.microAppWindow.__MICRO_APP_UMD_MODE__ = true
|
|
4566
|
-
this.effectController.
|
|
4942
|
+
this.effectController.record();
|
|
4567
4943
|
recordDataCenterSnapshot(this.microAppWindow.microApp);
|
|
4568
4944
|
// this.recordUmdInjectedValues = new Map<PropertyKey, unknown>()
|
|
4569
4945
|
// this.injectedKeys.forEach((key: PropertyKey) => {
|
|
@@ -4575,12 +4951,34 @@ class SandBox {
|
|
|
4575
4951
|
// this.recordUmdInjectedValues!.forEach((value: unknown, key: PropertyKey) => {
|
|
4576
4952
|
// Reflect.set(this.proxyWindow, key, value)
|
|
4577
4953
|
// })
|
|
4578
|
-
this.effectController.
|
|
4954
|
+
this.effectController.rebuild();
|
|
4579
4955
|
rebuildDataCenterSnapshot(this.microAppWindow.microApp);
|
|
4580
4956
|
}
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4957
|
+
/**
|
|
4958
|
+
* clear global event, timeout, data listener
|
|
4959
|
+
* Scenes:
|
|
4960
|
+
* 1. unmount of default/umd app
|
|
4961
|
+
* 2. hidden keep-alive app
|
|
4962
|
+
* 3. after init prerender app
|
|
4963
|
+
* @param clearData clear data from base app
|
|
4964
|
+
* @param isPrerender is prerender app
|
|
4965
|
+
* @param keepAlive is keep-alive app
|
|
4966
|
+
* @param destroy completely destroy
|
|
4967
|
+
*/
|
|
4968
|
+
releaseGlobalEffect({ clearData = false, isPrerender = false, keepAlive = false, destroy = false, }) {
|
|
4969
|
+
var _a, _b, _c;
|
|
4970
|
+
this.effectController.release({
|
|
4971
|
+
umdMode: this.proxyWindow.__MICRO_APP_UMD_MODE__,
|
|
4972
|
+
isPrerender,
|
|
4973
|
+
keepAlive,
|
|
4974
|
+
destroy,
|
|
4975
|
+
});
|
|
4976
|
+
(_a = this.microAppWindow.microApp) === null || _a === void 0 ? void 0 : _a.clearDataListener();
|
|
4977
|
+
(_b = this.microAppWindow.microApp) === null || _b === void 0 ? void 0 : _b.clearGlobalDataListener();
|
|
4978
|
+
if (clearData) {
|
|
4979
|
+
microApp.clearData(this.microAppWindow.__MICRO_APP_NAME__);
|
|
4980
|
+
(_c = this.microAppWindow.microApp) === null || _c === void 0 ? void 0 : _c.clearData();
|
|
4981
|
+
}
|
|
4584
4982
|
}
|
|
4585
4983
|
/**
|
|
4586
4984
|
* get scopeProperties and escapeProperties from plugins & adapter
|
|
@@ -4613,7 +5011,6 @@ class SandBox {
|
|
|
4613
5011
|
createProxyWindow(appName) {
|
|
4614
5012
|
const rawWindow = globalEnv.rawWindow;
|
|
4615
5013
|
const descriptorTargetMap = new Map();
|
|
4616
|
-
// window.xxx will trigger proxy
|
|
4617
5014
|
return new Proxy(this.microAppWindow, {
|
|
4618
5015
|
get: (target, key) => {
|
|
4619
5016
|
throttleDeferForSetAppName(appName);
|
|
@@ -4621,11 +5018,14 @@ class SandBox {
|
|
|
4621
5018
|
(isString(key) && /^__MICRO_APP_/.test(key)) ||
|
|
4622
5019
|
this.scopeProperties.includes(key))
|
|
4623
5020
|
return Reflect.get(target, key);
|
|
4624
|
-
|
|
4625
|
-
return isFunction(rawValue) ? bindFunctionToRawObject(rawWindow, rawValue) : rawValue;
|
|
5021
|
+
return bindFunctionToRawTarget(Reflect.get(rawWindow, key), rawWindow);
|
|
4626
5022
|
},
|
|
4627
5023
|
set: (target, key, value) => {
|
|
4628
5024
|
if (this.active) {
|
|
5025
|
+
/**
|
|
5026
|
+
* TODO:
|
|
5027
|
+
* 1、location域名相同,子应用内部跳转时的处理
|
|
5028
|
+
*/
|
|
4629
5029
|
if (this.adapter.escapeSetterKeyList.includes(key)) {
|
|
4630
5030
|
Reflect.set(rawWindow, key, value);
|
|
4631
5031
|
}
|
|
@@ -4646,15 +5046,15 @@ class SandBox {
|
|
|
4646
5046
|
this.injectedKeys.add(key);
|
|
4647
5047
|
}
|
|
4648
5048
|
else {
|
|
5049
|
+
!Reflect.has(target, key) && this.injectedKeys.add(key);
|
|
4649
5050
|
Reflect.set(target, key, value);
|
|
4650
|
-
this.injectedKeys.add(key);
|
|
4651
5051
|
}
|
|
4652
5052
|
if ((this.escapeProperties.includes(key) ||
|
|
4653
5053
|
(this.adapter.staticEscapeProperties.includes(key) &&
|
|
4654
5054
|
!Reflect.has(rawWindow, key))) &&
|
|
4655
5055
|
!this.scopeProperties.includes(key)) {
|
|
5056
|
+
!Reflect.has(rawWindow, key) && this.escapeKeys.add(key);
|
|
4656
5057
|
Reflect.set(rawWindow, key, value);
|
|
4657
|
-
this.escapeKeys.add(key);
|
|
4658
5058
|
}
|
|
4659
5059
|
}
|
|
4660
5060
|
return true;
|
|
@@ -4702,6 +5102,13 @@ class SandBox {
|
|
|
4702
5102
|
},
|
|
4703
5103
|
});
|
|
4704
5104
|
}
|
|
5105
|
+
// set __MICRO_APP_PRE_RENDER__ state
|
|
5106
|
+
setPreRenderState(state) {
|
|
5107
|
+
this.microAppWindow.__MICRO_APP_PRE_RENDER__ = state;
|
|
5108
|
+
}
|
|
5109
|
+
markUmdMode(state) {
|
|
5110
|
+
this.microAppWindow.__MICRO_APP_UMD_MODE__ = state;
|
|
5111
|
+
}
|
|
4705
5112
|
/**
|
|
4706
5113
|
* inject global properties to microAppWindow
|
|
4707
5114
|
* @param microAppWindow micro window
|
|
@@ -4716,6 +5123,7 @@ class SandBox {
|
|
|
4716
5123
|
microAppWindow.__MICRO_APP_PUBLIC_PATH__ = getEffectivePath(url);
|
|
4717
5124
|
microAppWindow.__MICRO_APP_WINDOW__ = microAppWindow;
|
|
4718
5125
|
microAppWindow.__MICRO_APP_PRE_RENDER__ = false;
|
|
5126
|
+
microAppWindow.__MICRO_APP_UMD_MODE__ = false;
|
|
4719
5127
|
microAppWindow.rawWindow = globalEnv.rawWindow;
|
|
4720
5128
|
microAppWindow.rawDocument = globalEnv.rawDocument;
|
|
4721
5129
|
microAppWindow.microApp = assign(new EventCenterForMicroApp(appName), {
|
|
@@ -4760,7 +5168,7 @@ class SandBox {
|
|
|
4760
5168
|
}
|
|
4761
5169
|
rawDefineProperty(microAppWindow, 'top', this.createDescriptorForMicroAppWindow('top', topValue));
|
|
4762
5170
|
rawDefineProperty(microAppWindow, 'parent', this.createDescriptorForMicroAppWindow('parent', parentValue));
|
|
4763
|
-
globalPropertyList.forEach((key) => {
|
|
5171
|
+
globalPropertyList$1.forEach((key) => {
|
|
4764
5172
|
rawDefineProperty(microAppWindow, key, this.createDescriptorForMicroAppWindow(key, this.proxyWindow));
|
|
4765
5173
|
});
|
|
4766
5174
|
}
|
|
@@ -4890,16 +5298,32 @@ class SandBox {
|
|
|
4890
5298
|
});
|
|
4891
5299
|
}
|
|
4892
5300
|
initRouteState(defaultPage) {
|
|
4893
|
-
initRouteStateWithURL(this.
|
|
5301
|
+
initRouteStateWithURL(this.microAppWindow.__MICRO_APP_NAME__, this.microAppWindow.location, defaultPage);
|
|
4894
5302
|
}
|
|
4895
5303
|
clearRouteState(keepRouteState) {
|
|
4896
|
-
clearRouteStateFromURL(this.
|
|
5304
|
+
clearRouteStateFromURL(this.microAppWindow.__MICRO_APP_NAME__, this.microAppWindow.__MICRO_APP_URL__, this.microAppWindow.location, keepRouteState);
|
|
4897
5305
|
}
|
|
4898
5306
|
setRouteInfoForKeepAliveApp() {
|
|
4899
|
-
updateBrowserURLWithLocation(this.
|
|
5307
|
+
updateBrowserURLWithLocation(this.microAppWindow.__MICRO_APP_NAME__, this.microAppWindow.location);
|
|
4900
5308
|
}
|
|
4901
5309
|
removeRouteInfoForKeepAliveApp() {
|
|
4902
|
-
removeStateAndPathFromBrowser(this.
|
|
5310
|
+
removeStateAndPathFromBrowser(this.microAppWindow.__MICRO_APP_NAME__);
|
|
5311
|
+
}
|
|
5312
|
+
/**
|
|
5313
|
+
* Format all html elements when init
|
|
5314
|
+
* @param container micro app container
|
|
5315
|
+
*/
|
|
5316
|
+
patchStaticElement(container) {
|
|
5317
|
+
patchElementTree(container, this.microAppWindow.__MICRO_APP_NAME__);
|
|
5318
|
+
}
|
|
5319
|
+
/**
|
|
5320
|
+
* action before exec scripts when mount
|
|
5321
|
+
* Actions:
|
|
5322
|
+
* 1. patch static elements from html
|
|
5323
|
+
* @param container micro app container
|
|
5324
|
+
*/
|
|
5325
|
+
actionBeforeExecScripts(container) {
|
|
5326
|
+
this.patchStaticElement(container);
|
|
4903
5327
|
}
|
|
4904
5328
|
/**
|
|
4905
5329
|
* Create new document and Document
|
|
@@ -4922,8 +5346,7 @@ class SandBox {
|
|
|
4922
5346
|
return 'ProxyDocument';
|
|
4923
5347
|
if (key === 'defaultView')
|
|
4924
5348
|
return this.proxyWindow;
|
|
4925
|
-
|
|
4926
|
-
return isFunction(rawValue) ? bindFunctionToRawObject(rawDocument, rawValue, 'DOCUMENT') : rawValue;
|
|
5349
|
+
return bindFunctionToRawTarget(Reflect.get(target, key), rawDocument, 'DOCUMENT');
|
|
4927
5350
|
},
|
|
4928
5351
|
set: (target, key, value) => {
|
|
4929
5352
|
/**
|
|
@@ -4960,8 +5383,7 @@ class SandBox {
|
|
|
4960
5383
|
Object.setPrototypeOf(MicroDocument.prototype, new Proxy(rawRootDocument.prototype, {
|
|
4961
5384
|
get(target, key) {
|
|
4962
5385
|
throttleDeferForSetAppName(appName);
|
|
4963
|
-
|
|
4964
|
-
return isFunction(rawValue) ? bindFunctionToRawObject(rawDocument, rawValue, 'DOCUMENT') : rawValue;
|
|
5386
|
+
return bindFunctionToRawTarget(Reflect.get(target, key), rawDocument, 'DOCUMENT');
|
|
4965
5387
|
},
|
|
4966
5388
|
set(target, key, value) {
|
|
4967
5389
|
Reflect.set(target, key, value);
|
|
@@ -4974,13 +5396,993 @@ class SandBox {
|
|
|
4974
5396
|
};
|
|
4975
5397
|
}
|
|
4976
5398
|
}
|
|
4977
|
-
|
|
5399
|
+
WithSandBox.activeCount = 0; // number of active sandbox
|
|
4978
5400
|
|
|
4979
|
-
function
|
|
4980
|
-
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
|
|
5401
|
+
function patchIframeRoute(appName, microAppWindow, childFullPath) {
|
|
5402
|
+
const microHistory = microAppWindow.history;
|
|
5403
|
+
microAppWindow.rawReplaceState = microHistory.replaceState;
|
|
5404
|
+
assign(microHistory, createMicroHistory(appName, microAppWindow.location));
|
|
5405
|
+
// exec updateMicroLocation after patch microHistory
|
|
5406
|
+
updateMicroLocation(appName, childFullPath, microAppWindow.location, 'prevent');
|
|
5407
|
+
}
|
|
5408
|
+
|
|
5409
|
+
function patchIframeWindow(appName, microAppWindow) {
|
|
5410
|
+
const rawWindow = globalEnv.rawWindow;
|
|
5411
|
+
escape2RawWindowKeys.forEach((key) => {
|
|
5412
|
+
microAppWindow[key] = bindFunctionToRawTarget(rawWindow[key], rawWindow);
|
|
5413
|
+
});
|
|
5414
|
+
Object.getOwnPropertyNames(microAppWindow)
|
|
5415
|
+
.filter((key) => {
|
|
5416
|
+
escape2RawWindowRegExpKeys.some((reg) => {
|
|
5417
|
+
if (reg.test(key) && key in microAppWindow.parent) {
|
|
5418
|
+
if (isFunction(rawWindow[key])) {
|
|
5419
|
+
microAppWindow[key] = bindFunctionToRawTarget(rawWindow[key], rawWindow);
|
|
5420
|
+
}
|
|
5421
|
+
else {
|
|
5422
|
+
const { configurable, enumerable } = Object.getOwnPropertyDescriptor(microAppWindow, key) || {
|
|
5423
|
+
configurable: true,
|
|
5424
|
+
enumerable: true,
|
|
5425
|
+
};
|
|
5426
|
+
if (configurable) {
|
|
5427
|
+
rawDefineProperty(microAppWindow, key, {
|
|
5428
|
+
configurable,
|
|
5429
|
+
enumerable,
|
|
5430
|
+
get: () => rawWindow[key],
|
|
5431
|
+
set: (value) => { rawWindow[key] = value; },
|
|
5432
|
+
});
|
|
5433
|
+
}
|
|
5434
|
+
}
|
|
5435
|
+
return true;
|
|
5436
|
+
}
|
|
5437
|
+
return false;
|
|
5438
|
+
});
|
|
5439
|
+
return /^on/.test(key) && !scopeIframeWindowOnEvent.includes(key);
|
|
5440
|
+
})
|
|
5441
|
+
.forEach((eventName) => {
|
|
5442
|
+
const { enumerable, writable, set } = Object.getOwnPropertyDescriptor(microAppWindow, eventName) || {
|
|
5443
|
+
enumerable: true,
|
|
5444
|
+
writable: true,
|
|
5445
|
+
};
|
|
5446
|
+
try {
|
|
5447
|
+
/**
|
|
5448
|
+
* 如果设置了iframeWindow上的这些on事件,处理函数会设置到原生window上,但this会绑定到iframeWindow
|
|
5449
|
+
* 获取这些值,则直接从原生window上取
|
|
5450
|
+
* 总结:这些on事件全部都代理到原生window上
|
|
5451
|
+
*
|
|
5452
|
+
* 问题:
|
|
5453
|
+
* 1、如果子应用没有设置,基座设置了on事件,子应用触发事件是会不会执行基座的函数?
|
|
5454
|
+
* 比如 基座定义了 window.onpopstate,子应用执行跳转会不会触发基座的onpopstate函数?
|
|
5455
|
+
*
|
|
5456
|
+
* 2、如果基座已经定义了 window.onpopstate,子应用定义会不会覆盖基座的?
|
|
5457
|
+
* 现在的逻辑看来,是会覆盖的,那么问题1就是 肯定的
|
|
5458
|
+
* TODO: 一些特殊事件onpopstate、onhashchange不代理,放在scopeIframeWindowOnEvent中
|
|
5459
|
+
*/
|
|
5460
|
+
rawDefineProperty(microAppWindow, eventName, {
|
|
5461
|
+
enumerable,
|
|
5462
|
+
configurable: true,
|
|
5463
|
+
get: () => rawWindow[eventName],
|
|
5464
|
+
set: (writable !== null && writable !== void 0 ? writable : !!set) ? (value) => { rawWindow[eventName] = isFunction(value) ? value.bind(microAppWindow) : value; }
|
|
5465
|
+
: undefined,
|
|
5466
|
+
});
|
|
5467
|
+
}
|
|
5468
|
+
catch (e) {
|
|
5469
|
+
logWarn(e, appName);
|
|
5470
|
+
}
|
|
5471
|
+
});
|
|
5472
|
+
return windowEffect(microAppWindow);
|
|
5473
|
+
}
|
|
5474
|
+
function windowEffect(microAppWindow) {
|
|
5475
|
+
const { rawWindow, rawAddEventListener, rawRemoveEventListener, } = globalEnv;
|
|
5476
|
+
const eventListenerMap = new Map();
|
|
5477
|
+
const sstWindowListenerMap = new Map();
|
|
5478
|
+
function getEventTarget(type) {
|
|
5479
|
+
return scopeIframeWindowEvent.includes(type) ? microAppWindow : rawWindow;
|
|
5480
|
+
}
|
|
5481
|
+
microAppWindow.addEventListener = function (type, listener, options) {
|
|
5482
|
+
const listenerList = eventListenerMap.get(type);
|
|
5483
|
+
if (listenerList) {
|
|
5484
|
+
listenerList.add(listener);
|
|
5485
|
+
}
|
|
5486
|
+
else {
|
|
5487
|
+
eventListenerMap.set(type, new Set([listener]));
|
|
5488
|
+
}
|
|
5489
|
+
listener && (listener.__MICRO_APP_MARK_OPTIONS__ = options);
|
|
5490
|
+
rawAddEventListener.call(getEventTarget(type), type, listener, options);
|
|
5491
|
+
};
|
|
5492
|
+
microAppWindow.removeEventListener = function (type, listener, options) {
|
|
5493
|
+
const listenerList = eventListenerMap.get(type);
|
|
5494
|
+
if ((listenerList === null || listenerList === void 0 ? void 0 : listenerList.size) && listenerList.has(listener)) {
|
|
5495
|
+
listenerList.delete(listener);
|
|
5496
|
+
}
|
|
5497
|
+
rawRemoveEventListener.call(getEventTarget(type), type, listener, options);
|
|
5498
|
+
};
|
|
5499
|
+
const reset = () => {
|
|
5500
|
+
sstWindowListenerMap.clear();
|
|
5501
|
+
};
|
|
5502
|
+
/**
|
|
5503
|
+
* NOTE:
|
|
5504
|
+
* 1. about timer(events & properties should record & rebuild at all modes, exclude default mode)
|
|
5505
|
+
* 2. record maybe call twice when unmount prerender, keep-alive app manually with umd mode
|
|
5506
|
+
* 4 modes: default-mode、umd-mode、prerender、keep-alive
|
|
5507
|
+
* Solution:
|
|
5508
|
+
* 1. default-mode(normal): clear events & timers, not record & rebuild anything
|
|
5509
|
+
* 2. umd-mode(normal): not clear timers, record & rebuild events
|
|
5510
|
+
* 3. prerender/keep-alive(default, umd): not clear timers, record & rebuild events
|
|
5511
|
+
*
|
|
5512
|
+
* TODO: 现在的 清除、记录和恢复操作分散的太零散,sandbox、create_app中都有分散,将代码再优化一下,集中处理
|
|
5513
|
+
*/
|
|
5514
|
+
const record = () => {
|
|
5515
|
+
// record window event
|
|
5516
|
+
eventListenerMap.forEach((listenerList, type) => {
|
|
5517
|
+
if (listenerList.size) {
|
|
5518
|
+
sstWindowListenerMap.set(type, new Set(listenerList));
|
|
5519
|
+
}
|
|
5520
|
+
});
|
|
5521
|
+
};
|
|
5522
|
+
// rebuild event and timer before remount app
|
|
5523
|
+
const rebuild = () => {
|
|
5524
|
+
// rebuild window event
|
|
5525
|
+
sstWindowListenerMap.forEach((listenerList, type) => {
|
|
5526
|
+
for (const listener of listenerList) {
|
|
5527
|
+
microAppWindow.addEventListener(type, listener, listener === null || listener === void 0 ? void 0 : listener.__MICRO_APP_MARK_OPTIONS__);
|
|
5528
|
+
}
|
|
5529
|
+
});
|
|
5530
|
+
reset();
|
|
5531
|
+
};
|
|
5532
|
+
const release = () => {
|
|
5533
|
+
// Clear window binding events
|
|
5534
|
+
if (eventListenerMap.size) {
|
|
5535
|
+
eventListenerMap.forEach((listenerList, type) => {
|
|
5536
|
+
for (const listener of listenerList) {
|
|
5537
|
+
rawRemoveEventListener.call(getEventTarget(type), type, listener);
|
|
5538
|
+
}
|
|
5539
|
+
});
|
|
5540
|
+
eventListenerMap.clear();
|
|
5541
|
+
}
|
|
5542
|
+
};
|
|
5543
|
+
return {
|
|
5544
|
+
reset,
|
|
5545
|
+
record,
|
|
5546
|
+
rebuild,
|
|
5547
|
+
release,
|
|
5548
|
+
};
|
|
5549
|
+
}
|
|
5550
|
+
|
|
5551
|
+
/**
|
|
5552
|
+
* TODO:
|
|
5553
|
+
* 1、shadowDOM
|
|
5554
|
+
* 2、重构
|
|
5555
|
+
*/
|
|
5556
|
+
function patchIframeDocument(appName, microAppWindow, proxyLocation) {
|
|
5557
|
+
patchDocumentPrototype(appName, microAppWindow);
|
|
5558
|
+
patchDocumentProperties(appName, microAppWindow, proxyLocation);
|
|
5559
|
+
return documentEffect(appName, microAppWindow);
|
|
5560
|
+
}
|
|
5561
|
+
function patchDocumentPrototype(appName, microAppWindow) {
|
|
5562
|
+
const rawDocument = globalEnv.rawDocument;
|
|
5563
|
+
const microRootDocument = microAppWindow.Document;
|
|
5564
|
+
const microDocument = microAppWindow.document;
|
|
5565
|
+
microRootDocument.prototype.createElement = function createElement(tagName, options) {
|
|
5566
|
+
const element = globalEnv.rawCreateElement.call(this, tagName, options);
|
|
5567
|
+
return updateElementInfo(element, appName);
|
|
5568
|
+
};
|
|
5569
|
+
microRootDocument.prototype.createTextNode = function createTextNode(data) {
|
|
5570
|
+
const element = globalEnv.rawCreateTextNode.call(this, data);
|
|
5571
|
+
return updateElementInfo(element, appName);
|
|
5572
|
+
};
|
|
5573
|
+
function getDefaultRawTarget(target) {
|
|
5574
|
+
return microDocument !== target ? target : rawDocument;
|
|
5575
|
+
}
|
|
5576
|
+
// query element👇
|
|
5577
|
+
function querySelector(selectors) {
|
|
5578
|
+
var _a, _b;
|
|
5579
|
+
if (isUniqueElement(selectors) ||
|
|
5580
|
+
microDocument !== this) {
|
|
5581
|
+
const _this = getDefaultRawTarget(this);
|
|
5582
|
+
return globalEnv.rawQuerySelector.call(_this, selectors);
|
|
5583
|
+
}
|
|
5584
|
+
return (_b = (_a = appInstanceMap.get(appName)) === null || _a === void 0 ? void 0 : _a.querySelector(selectors)) !== null && _b !== void 0 ? _b : null;
|
|
5585
|
+
}
|
|
5586
|
+
function querySelectorAll(selectors) {
|
|
5587
|
+
var _a, _b;
|
|
5588
|
+
if (isUniqueElement(selectors) ||
|
|
5589
|
+
microDocument !== this) {
|
|
5590
|
+
const _this = getDefaultRawTarget(this);
|
|
5591
|
+
return globalEnv.rawQuerySelectorAll.call(_this, selectors);
|
|
5592
|
+
}
|
|
5593
|
+
return (_b = (_a = appInstanceMap.get(appName)) === null || _a === void 0 ? void 0 : _a.querySelectorAll(selectors)) !== null && _b !== void 0 ? _b : [];
|
|
5594
|
+
}
|
|
5595
|
+
microRootDocument.prototype.querySelector = querySelector;
|
|
5596
|
+
microRootDocument.prototype.querySelectorAll = querySelectorAll;
|
|
5597
|
+
microRootDocument.prototype.getElementById = function getElementById(key) {
|
|
5598
|
+
const _this = getDefaultRawTarget(this);
|
|
5599
|
+
if (isInvalidQuerySelectorKey(key)) {
|
|
5600
|
+
return globalEnv.rawGetElementById.call(_this, key);
|
|
5601
|
+
}
|
|
5602
|
+
try {
|
|
5603
|
+
return querySelector.call(this, `#${key}`);
|
|
5604
|
+
}
|
|
5605
|
+
catch (_a) {
|
|
5606
|
+
return globalEnv.rawGetElementById.call(_this, key);
|
|
5607
|
+
}
|
|
5608
|
+
};
|
|
5609
|
+
microRootDocument.prototype.getElementsByClassName = function getElementsByClassName(key) {
|
|
5610
|
+
const _this = getDefaultRawTarget(this);
|
|
5611
|
+
if (isInvalidQuerySelectorKey(key)) {
|
|
5612
|
+
return globalEnv.rawGetElementsByClassName.call(_this, key);
|
|
5613
|
+
}
|
|
5614
|
+
try {
|
|
5615
|
+
return querySelectorAll.call(this, `.${key}`);
|
|
5616
|
+
}
|
|
5617
|
+
catch (_a) {
|
|
5618
|
+
return globalEnv.rawGetElementsByClassName.call(_this, key);
|
|
5619
|
+
}
|
|
5620
|
+
};
|
|
5621
|
+
microRootDocument.prototype.getElementsByTagName = function getElementsByTagName(key) {
|
|
5622
|
+
var _a;
|
|
5623
|
+
const _this = getDefaultRawTarget(this);
|
|
5624
|
+
if (isUniqueElement(key) ||
|
|
5625
|
+
isInvalidQuerySelectorKey(key) ||
|
|
5626
|
+
(!((_a = appInstanceMap.get(appName)) === null || _a === void 0 ? void 0 : _a.inline) && /^script$/i.test(key))) {
|
|
5627
|
+
return globalEnv.rawGetElementsByTagName.call(_this, key);
|
|
5628
|
+
}
|
|
5629
|
+
try {
|
|
5630
|
+
return querySelectorAll.call(this, key);
|
|
5631
|
+
}
|
|
5632
|
+
catch (_b) {
|
|
5633
|
+
return globalEnv.rawGetElementsByTagName.call(_this, key);
|
|
5634
|
+
}
|
|
5635
|
+
};
|
|
5636
|
+
microRootDocument.prototype.getElementsByName = function getElementsByName(key) {
|
|
5637
|
+
const _this = getDefaultRawTarget(this);
|
|
5638
|
+
if (isInvalidQuerySelectorKey(key)) {
|
|
5639
|
+
return globalEnv.rawGetElementsByName.call(_this, key);
|
|
5640
|
+
}
|
|
5641
|
+
try {
|
|
5642
|
+
return querySelectorAll.call(this, `[name=${key}]`);
|
|
5643
|
+
}
|
|
5644
|
+
catch (_a) {
|
|
5645
|
+
return globalEnv.rawGetElementsByName.call(_this, key);
|
|
5646
|
+
}
|
|
5647
|
+
};
|
|
5648
|
+
}
|
|
5649
|
+
function patchDocumentProperties(appName, microAppWindow, proxyLocation) {
|
|
5650
|
+
const rawDocument = globalEnv.rawDocument;
|
|
5651
|
+
const microRootDocument = microAppWindow.Document;
|
|
5652
|
+
const microDocument = microAppWindow.document;
|
|
5653
|
+
const getCommonDescriptor = (key, getter) => {
|
|
5654
|
+
const { enumerable } = Object.getOwnPropertyDescriptor(microRootDocument.prototype, key) || {
|
|
5655
|
+
enumerable: true,
|
|
5656
|
+
writable: true,
|
|
5657
|
+
};
|
|
5658
|
+
return {
|
|
5659
|
+
configurable: true,
|
|
5660
|
+
enumerable,
|
|
5661
|
+
get: getter,
|
|
5662
|
+
};
|
|
5663
|
+
};
|
|
5664
|
+
const createDescriptors = () => {
|
|
5665
|
+
const result = {};
|
|
5666
|
+
const descList = [
|
|
5667
|
+
['documentURI', () => proxyLocation.href],
|
|
5668
|
+
['URL', () => proxyLocation.href],
|
|
5669
|
+
['documentElement', () => rawDocument.documentElement],
|
|
5670
|
+
['scrollingElement', () => rawDocument.scrollingElement],
|
|
5671
|
+
['forms', () => microRootDocument.prototype.querySelectorAll.call(microDocument, 'form')],
|
|
5672
|
+
['images', () => microRootDocument.prototype.querySelectorAll.call(microDocument, 'img')],
|
|
5673
|
+
['links', () => microRootDocument.prototype.querySelectorAll.call(microDocument, 'a')],
|
|
5674
|
+
];
|
|
5675
|
+
descList.forEach((desc) => {
|
|
5676
|
+
result[desc[0]] = getCommonDescriptor(desc[0], desc[1]);
|
|
5677
|
+
});
|
|
5678
|
+
// TODO: shadowDOM
|
|
5679
|
+
proxy2RawDocOrShadowKeys.forEach((key) => {
|
|
5680
|
+
result[key] = getCommonDescriptor(key, () => rawDocument[key]);
|
|
5681
|
+
});
|
|
5682
|
+
// TODO: shadowDOM
|
|
5683
|
+
proxy2RawDocOrShadowMethods.forEach((key) => {
|
|
5684
|
+
result[key] = getCommonDescriptor(key, () => bindFunctionToRawTarget(rawDocument[key], rawDocument, 'DOCUMENT'));
|
|
5685
|
+
});
|
|
5686
|
+
proxy2RawDocumentKeys.forEach((key) => {
|
|
5687
|
+
result[key] = getCommonDescriptor(key, () => rawDocument[key]);
|
|
5688
|
+
});
|
|
5689
|
+
proxy2RawDocumentMethods.forEach((key) => {
|
|
5690
|
+
result[key] = getCommonDescriptor(key, () => bindFunctionToRawTarget(rawDocument[key], rawDocument, 'DOCUMENT'));
|
|
5691
|
+
});
|
|
5692
|
+
return result;
|
|
5693
|
+
};
|
|
5694
|
+
rawDefineProperties(microRootDocument.prototype, createDescriptors());
|
|
5695
|
+
// head, body, html, title
|
|
5696
|
+
uniqueDocumentElement.forEach((tagName) => {
|
|
5697
|
+
rawDefineProperty(microDocument, tagName, {
|
|
5698
|
+
enumerable: true,
|
|
5699
|
+
configurable: true,
|
|
5700
|
+
get: () => rawDocument[tagName],
|
|
5701
|
+
set: undefined,
|
|
5702
|
+
});
|
|
5703
|
+
});
|
|
5704
|
+
}
|
|
5705
|
+
function documentEffect(appName, microAppWindow) {
|
|
5706
|
+
const documentEventListenerMap = new Map();
|
|
5707
|
+
const sstDocumentListenerMap = new Map();
|
|
5708
|
+
let onClickHandler = null;
|
|
5709
|
+
let sstOnClickHandler = null;
|
|
5710
|
+
const microRootDocument = microAppWindow.Document;
|
|
5711
|
+
const microDocument = microAppWindow.document;
|
|
5712
|
+
const { rawDocument, rawAddEventListener, rawRemoveEventListener, } = globalEnv;
|
|
5713
|
+
function getEventTarget(type, bindTarget) {
|
|
5714
|
+
return scopeIframeDocumentEvent.includes(type) ? bindTarget : rawDocument;
|
|
5715
|
+
}
|
|
5716
|
+
microRootDocument.prototype.addEventListener = function (type, listener, options) {
|
|
5717
|
+
const handler = isFunction(listener) ? (listener.__MICRO_APP_BOUND_FUNCTION__ = listener.__MICRO_APP_BOUND_FUNCTION__ || listener.bind(this)) : listener;
|
|
5718
|
+
const appListenersMap = documentEventListenerMap.get(appName);
|
|
5719
|
+
if (appListenersMap) {
|
|
5720
|
+
const appListenerList = appListenersMap.get(type);
|
|
5721
|
+
if (appListenerList) {
|
|
5722
|
+
appListenerList.add(listener);
|
|
5723
|
+
}
|
|
5724
|
+
else {
|
|
5725
|
+
appListenersMap.set(type, new Set([listener]));
|
|
5726
|
+
}
|
|
5727
|
+
}
|
|
5728
|
+
else {
|
|
5729
|
+
documentEventListenerMap.set(appName, new Map([[type, new Set([listener])]]));
|
|
5730
|
+
}
|
|
5731
|
+
listener && (listener.__MICRO_APP_MARK_OPTIONS__ = options);
|
|
5732
|
+
rawAddEventListener.call(getEventTarget(type, this), type, handler, options);
|
|
5733
|
+
};
|
|
5734
|
+
microRootDocument.prototype.removeEventListener = function (type, listener, options) {
|
|
5735
|
+
const appListenersMap = documentEventListenerMap.get(appName);
|
|
5736
|
+
if (appListenersMap) {
|
|
5737
|
+
const appListenerList = appListenersMap.get(type);
|
|
5738
|
+
if ((appListenerList === null || appListenerList === void 0 ? void 0 : appListenerList.size) && appListenerList.has(listener)) {
|
|
5739
|
+
appListenerList.delete(listener);
|
|
5740
|
+
}
|
|
5741
|
+
}
|
|
5742
|
+
const handler = (listener === null || listener === void 0 ? void 0 : listener.__MICRO_APP_BOUND_FUNCTION__) || listener;
|
|
5743
|
+
rawRemoveEventListener.call(getEventTarget(type, this), type, handler, options);
|
|
5744
|
+
};
|
|
5745
|
+
// 重新定义microRootDocument.prototype 上的on开头方法
|
|
5746
|
+
function createSetterHandler(eventName) {
|
|
5747
|
+
if (eventName === 'onclick') {
|
|
5748
|
+
return (value) => {
|
|
5749
|
+
if (isFunction(onClickHandler)) {
|
|
5750
|
+
rawRemoveEventListener.call(rawDocument, 'click', onClickHandler, false);
|
|
5751
|
+
}
|
|
5752
|
+
if (isFunction(value)) {
|
|
5753
|
+
onClickHandler = value.bind(microDocument);
|
|
5754
|
+
rawAddEventListener.call(rawDocument, 'click', onClickHandler, false);
|
|
5755
|
+
}
|
|
5756
|
+
else {
|
|
5757
|
+
onClickHandler = value;
|
|
5758
|
+
}
|
|
5759
|
+
};
|
|
5760
|
+
}
|
|
5761
|
+
return (value) => { rawDocument[eventName] = isFunction(value) ? value.bind(microDocument) : value; };
|
|
5762
|
+
}
|
|
5763
|
+
/**
|
|
5764
|
+
* TODO:
|
|
5765
|
+
* 1、直接代理到原生document是否正确
|
|
5766
|
+
* 2、shadowDOM
|
|
5767
|
+
*/
|
|
5768
|
+
Object.getOwnPropertyNames(microRootDocument.prototype)
|
|
5769
|
+
.filter((key) => /^on/.test(key) && !scopeIframeDocumentOnEvent.includes(key))
|
|
5770
|
+
.forEach((eventName) => {
|
|
5771
|
+
const { enumerable, writable, set } = Object.getOwnPropertyDescriptor(microRootDocument.prototype, eventName) || {
|
|
5772
|
+
enumerable: true,
|
|
5773
|
+
writable: true,
|
|
5774
|
+
};
|
|
5775
|
+
try {
|
|
5776
|
+
rawDefineProperty(microRootDocument.prototype, eventName, {
|
|
5777
|
+
enumerable,
|
|
5778
|
+
configurable: true,
|
|
5779
|
+
get: () => {
|
|
5780
|
+
if (eventName === 'onclick')
|
|
5781
|
+
return onClickHandler;
|
|
5782
|
+
return rawDocument[eventName];
|
|
5783
|
+
},
|
|
5784
|
+
set: (writable !== null && writable !== void 0 ? writable : !!set) ? createSetterHandler(eventName) : undefined,
|
|
5785
|
+
});
|
|
5786
|
+
}
|
|
5787
|
+
catch (e) {
|
|
5788
|
+
logWarn(e, appName);
|
|
5789
|
+
}
|
|
5790
|
+
});
|
|
5791
|
+
const reset = () => {
|
|
5792
|
+
sstDocumentListenerMap.clear();
|
|
5793
|
+
sstOnClickHandler = null;
|
|
5794
|
+
};
|
|
5795
|
+
/**
|
|
5796
|
+
* record event
|
|
5797
|
+
* NOTE:
|
|
5798
|
+
* 1.record maybe call twice when unmount prerender, keep-alive app manually with umd mode
|
|
5799
|
+
* Scenes:
|
|
5800
|
+
* 1. exec umdMountHook in umd mode
|
|
5801
|
+
* 2. hidden keep-alive app
|
|
5802
|
+
* 3. after init prerender app
|
|
5803
|
+
*/
|
|
5804
|
+
const record = () => {
|
|
5805
|
+
// record onclick handler
|
|
5806
|
+
sstOnClickHandler = sstOnClickHandler || onClickHandler;
|
|
5807
|
+
// record document event
|
|
5808
|
+
const documentAppListenersMap = documentEventListenerMap.get(appName);
|
|
5809
|
+
if (documentAppListenersMap) {
|
|
5810
|
+
documentAppListenersMap.forEach((listenerList, type) => {
|
|
5811
|
+
if (listenerList.size) {
|
|
5812
|
+
sstDocumentListenerMap.set(type, new Set(listenerList));
|
|
5813
|
+
}
|
|
5814
|
+
});
|
|
5815
|
+
}
|
|
5816
|
+
};
|
|
5817
|
+
// rebuild event and timer before remount app
|
|
5818
|
+
const rebuild = () => {
|
|
5819
|
+
// rebuild onclick event
|
|
5820
|
+
if (sstOnClickHandler)
|
|
5821
|
+
microDocument.onclick = sstOnClickHandler;
|
|
5822
|
+
sstDocumentListenerMap.forEach((listenerList, type) => {
|
|
5823
|
+
for (const listener of listenerList) {
|
|
5824
|
+
microDocument.addEventListener(type, listener, listener === null || listener === void 0 ? void 0 : listener.__MICRO_APP_MARK_OPTIONS__);
|
|
5825
|
+
}
|
|
5826
|
+
});
|
|
5827
|
+
reset();
|
|
5828
|
+
};
|
|
5829
|
+
const release = () => {
|
|
5830
|
+
// Clear the function bound by micro application through document.onclick
|
|
5831
|
+
if (isFunction(onClickHandler)) {
|
|
5832
|
+
rawRemoveEventListener.call(rawDocument, 'click', onClickHandler);
|
|
5833
|
+
onClickHandler = null;
|
|
5834
|
+
}
|
|
5835
|
+
// Clear document binding event
|
|
5836
|
+
const documentAppListenersMap = documentEventListenerMap.get(appName);
|
|
5837
|
+
if (documentAppListenersMap) {
|
|
5838
|
+
documentAppListenersMap.forEach((listenerList, type) => {
|
|
5839
|
+
for (const listener of listenerList) {
|
|
5840
|
+
rawRemoveEventListener.call(getEventTarget(type, microDocument), type, (listener === null || listener === void 0 ? void 0 : listener.__MICRO_APP_BOUND_FUNCTION__) || listener);
|
|
5841
|
+
}
|
|
5842
|
+
});
|
|
5843
|
+
documentAppListenersMap.clear();
|
|
5844
|
+
}
|
|
5845
|
+
};
|
|
5846
|
+
return {
|
|
5847
|
+
reset,
|
|
5848
|
+
record,
|
|
5849
|
+
rebuild,
|
|
5850
|
+
release,
|
|
5851
|
+
};
|
|
5852
|
+
}
|
|
5853
|
+
|
|
5854
|
+
function patchIframeElement(appName, url, microAppWindow, iframeSandbox) {
|
|
5855
|
+
patchIframeNode(appName, microAppWindow, iframeSandbox);
|
|
5856
|
+
patchIframeAttribute(appName, url, microAppWindow);
|
|
5857
|
+
}
|
|
5858
|
+
function patchIframeNode(appName, microAppWindow, iframeSandbox) {
|
|
5859
|
+
const microDocument = microAppWindow.document;
|
|
5860
|
+
const rawDocument = globalEnv.rawDocument;
|
|
5861
|
+
const microRootNode = microAppWindow.Node;
|
|
5862
|
+
const microRootElement = microAppWindow.Element;
|
|
5863
|
+
// const rawMicroGetRootNode = microRootNode.prototype.getRootNode
|
|
5864
|
+
const rawMicroAppendChild = microRootNode.prototype.appendChild;
|
|
5865
|
+
const rawMicroInsertBefore = microRootNode.prototype.insertBefore;
|
|
5866
|
+
const rawMicroReplaceChild = microRootNode.prototype.replaceChild;
|
|
5867
|
+
const rawMicroCloneNode = microRootNode.prototype.cloneNode;
|
|
5868
|
+
const rawInnerHTMLDesc = Object.getOwnPropertyDescriptor(microRootElement.prototype, 'innerHTML');
|
|
5869
|
+
const rawParentNodeLDesc = Object.getOwnPropertyDescriptor(microRootNode.prototype, 'parentNode');
|
|
5870
|
+
const isPureNode = (target) => {
|
|
5871
|
+
return (isScriptElement(target) || isBaseElement(target)) && target.__PURE_ELEMENT__;
|
|
5872
|
+
};
|
|
5873
|
+
const getRawTarget = (target) => {
|
|
5874
|
+
if (target === iframeSandbox.microHead) {
|
|
5875
|
+
return rawDocument.head;
|
|
5876
|
+
}
|
|
5877
|
+
else if (target === iframeSandbox.microBody) {
|
|
5878
|
+
return rawDocument.body;
|
|
5879
|
+
}
|
|
5880
|
+
return target;
|
|
5881
|
+
};
|
|
5882
|
+
microRootNode.prototype.getRootNode = function getRootNode() {
|
|
5883
|
+
return microDocument;
|
|
5884
|
+
// TODO: 什么情况下返回原生document?
|
|
5885
|
+
// const rootNode = rawMicroGetRootNode.call(this, options)
|
|
5886
|
+
// if (rootNode === appInstanceMap.get(appName)?.container) return microDocument
|
|
5887
|
+
// return rootNode
|
|
5888
|
+
};
|
|
5889
|
+
microRootNode.prototype.appendChild = function appendChild(node) {
|
|
5890
|
+
updateElementInfo(node, appName);
|
|
5891
|
+
// TODO:只有script才可以这样拦截,link、style不应该拦截
|
|
5892
|
+
if (isPureNode(node)) {
|
|
5893
|
+
return rawMicroAppendChild.call(this, node);
|
|
5894
|
+
}
|
|
5895
|
+
const _this = getRawTarget(this);
|
|
5896
|
+
if (_this !== this) {
|
|
5897
|
+
return _this.appendChild(node);
|
|
5898
|
+
}
|
|
5899
|
+
return rawMicroAppendChild.call(_this, node);
|
|
5900
|
+
};
|
|
5901
|
+
// TODO: 更多场景适配
|
|
5902
|
+
microRootNode.prototype.insertBefore = function insertBefore(node, child) {
|
|
5903
|
+
updateElementInfo(node, appName);
|
|
5904
|
+
if (isPureNode(node)) {
|
|
5905
|
+
return rawMicroInsertBefore.call(this, node, child);
|
|
5906
|
+
}
|
|
5907
|
+
const _this = getRawTarget(this);
|
|
5908
|
+
if (_this !== this) {
|
|
5909
|
+
if (child && !_this.contains(child)) {
|
|
5910
|
+
return _this.appendChild(node);
|
|
5911
|
+
}
|
|
5912
|
+
return _this.insertBefore(node, child);
|
|
5913
|
+
}
|
|
5914
|
+
return rawMicroInsertBefore.call(_this, node, child);
|
|
5915
|
+
};
|
|
5916
|
+
// TODO: 更多场景适配
|
|
5917
|
+
microRootNode.prototype.replaceChild = function replaceChild(node, child) {
|
|
5918
|
+
updateElementInfo(node, appName);
|
|
5919
|
+
if (isPureNode(node)) {
|
|
5920
|
+
return rawMicroReplaceChild.call(this, node, child);
|
|
5921
|
+
}
|
|
5922
|
+
const _this = getRawTarget(this);
|
|
5923
|
+
if (_this !== this) {
|
|
5924
|
+
if (child && !_this.contains(child)) {
|
|
5925
|
+
_this.appendChild(node);
|
|
5926
|
+
return child;
|
|
5927
|
+
}
|
|
5928
|
+
return _this.replaceChild(node, child);
|
|
5929
|
+
}
|
|
5930
|
+
return rawMicroReplaceChild.call(_this, node, child);
|
|
5931
|
+
};
|
|
5932
|
+
// patch cloneNode
|
|
5933
|
+
microRootNode.prototype.cloneNode = function cloneNode(deep) {
|
|
5934
|
+
const clonedNode = rawMicroCloneNode.call(this, deep);
|
|
5935
|
+
return updateElementInfo(clonedNode, appName);
|
|
5936
|
+
};
|
|
5937
|
+
rawDefineProperty(microRootElement.prototype, 'innerHTML', {
|
|
5938
|
+
configurable: true,
|
|
5939
|
+
enumerable: true,
|
|
5940
|
+
get() {
|
|
5941
|
+
return rawInnerHTMLDesc.get.call(this);
|
|
5942
|
+
},
|
|
5943
|
+
set(code) {
|
|
5944
|
+
rawInnerHTMLDesc.set.call(this, code);
|
|
5945
|
+
Array.from(this.children).forEach((child) => {
|
|
5946
|
+
if (isElement(child)) {
|
|
5947
|
+
updateElementInfo(child, appName);
|
|
5948
|
+
}
|
|
5949
|
+
});
|
|
5950
|
+
}
|
|
5951
|
+
});
|
|
5952
|
+
// patch parentNode
|
|
5953
|
+
rawDefineProperty(microRootNode.prototype, 'parentNode', {
|
|
5954
|
+
configurable: true,
|
|
5955
|
+
enumerable: true,
|
|
5956
|
+
get() {
|
|
5957
|
+
var _a;
|
|
5958
|
+
// set html.parentNode to microDocument
|
|
5959
|
+
throttleDeferForParentNode(microDocument);
|
|
5960
|
+
const result = rawParentNodeLDesc.get.call(this);
|
|
5961
|
+
/**
|
|
5962
|
+
* If parentNode is <micro-app-body>, return rawDocument.body
|
|
5963
|
+
* Scenes:
|
|
5964
|
+
* 1. element-ui@2/lib/utils/vue-popper.js
|
|
5965
|
+
* if (this.popperElm.parentNode === document.body) ...
|
|
5966
|
+
* WARNING:
|
|
5967
|
+
* Will it cause other problems ?
|
|
5968
|
+
* e.g. target.parentNode.remove(target)
|
|
5969
|
+
*/
|
|
5970
|
+
if ((result === null || result === void 0 ? void 0 : result.tagName) === 'MICRO-APP-BODY' && ((_a = appInstanceMap.get(appName)) === null || _a === void 0 ? void 0 : _a.container)) {
|
|
5971
|
+
return rawDocument.body;
|
|
5972
|
+
}
|
|
5973
|
+
return result;
|
|
5974
|
+
},
|
|
5975
|
+
set: undefined,
|
|
5976
|
+
});
|
|
5977
|
+
// Adapt to new image(...) scene
|
|
5978
|
+
const ImageProxy = new Proxy(microAppWindow.Image, {
|
|
5979
|
+
construct(Target, args) {
|
|
5980
|
+
const elementImage = new Target(...args);
|
|
5981
|
+
updateElementInfo(elementImage, appName);
|
|
5982
|
+
return elementImage;
|
|
5983
|
+
},
|
|
5984
|
+
});
|
|
5985
|
+
rawDefineProperty(microAppWindow, 'Image', {
|
|
5986
|
+
configurable: true,
|
|
5987
|
+
writable: true,
|
|
5988
|
+
value: ImageProxy,
|
|
5989
|
+
});
|
|
5990
|
+
/**
|
|
5991
|
+
* TODO:
|
|
5992
|
+
* 1、append prepend
|
|
5993
|
+
* 2、cloneNode -- 完成
|
|
5994
|
+
* 3、innerHTML
|
|
5995
|
+
* 4、querySelector、querySelectorAll (head, body)
|
|
5996
|
+
* 5、Image -- 完成
|
|
5997
|
+
* 都是Element原型链上的方法
|
|
5998
|
+
*/
|
|
5999
|
+
}
|
|
6000
|
+
function patchIframeAttribute(appName, url, microAppWindow) {
|
|
6001
|
+
const microRootElement = microAppWindow.Element;
|
|
6002
|
+
const rawMicroSetAttribute = microRootElement.prototype.setAttribute;
|
|
6003
|
+
microRootElement.prototype.setAttribute = function setAttribute(key, value) {
|
|
6004
|
+
if (((key === 'src' || key === 'srcset') && /^(img|script)$/i.test(this.tagName)) ||
|
|
6005
|
+
(key === 'href' && /^link$/i.test(this.tagName))) {
|
|
6006
|
+
value = CompletionPath(value, url);
|
|
6007
|
+
}
|
|
6008
|
+
rawMicroSetAttribute.call(this, key, value);
|
|
6009
|
+
};
|
|
6010
|
+
const protoAttrList = [
|
|
6011
|
+
[microAppWindow.HTMLImageElement.prototype, 'src'],
|
|
6012
|
+
[microAppWindow.HTMLScriptElement.prototype, 'src'],
|
|
6013
|
+
[microAppWindow.HTMLLinkElement.prototype, 'href'],
|
|
6014
|
+
];
|
|
6015
|
+
protoAttrList.forEach(([target, attr]) => {
|
|
6016
|
+
const { enumerable, configurable, get, set } = Object.getOwnPropertyDescriptor(target, attr) || {
|
|
6017
|
+
enumerable: true,
|
|
6018
|
+
configurable: true,
|
|
6019
|
+
};
|
|
6020
|
+
rawDefineProperty(target, attr, {
|
|
6021
|
+
enumerable,
|
|
6022
|
+
configurable,
|
|
6023
|
+
get: function () {
|
|
6024
|
+
return get === null || get === void 0 ? void 0 : get.call(this);
|
|
6025
|
+
},
|
|
6026
|
+
set: function (value) {
|
|
6027
|
+
set === null || set === void 0 ? void 0 : set.call(this, CompletionPath(value, url));
|
|
6028
|
+
},
|
|
6029
|
+
});
|
|
6030
|
+
});
|
|
6031
|
+
}
|
|
6032
|
+
|
|
6033
|
+
class IframeSandbox {
|
|
6034
|
+
constructor(appName, url) {
|
|
6035
|
+
this.active = false;
|
|
6036
|
+
// Properties that can be escape to rawWindow
|
|
6037
|
+
this.escapeProperties = [];
|
|
6038
|
+
// Properties escape to rawWindow, cleared when unmount
|
|
6039
|
+
this.escapeKeys = new Set();
|
|
6040
|
+
// TODO: 初始化和每次跳转时都要更新base的href
|
|
6041
|
+
this.updateIframeBase = () => {
|
|
6042
|
+
var _a;
|
|
6043
|
+
(_a = this.baseElement) === null || _a === void 0 ? void 0 : _a.setAttribute('href', this.proxyLocation.protocol + '//' + this.proxyLocation.host + this.proxyLocation.pathname);
|
|
6044
|
+
};
|
|
6045
|
+
const rawLocation = globalEnv.rawWindow.location;
|
|
6046
|
+
const browserHost = rawLocation.protocol + '//' + rawLocation.host;
|
|
6047
|
+
const childStaticLocation = new URL(url);
|
|
6048
|
+
const childHost = childStaticLocation.protocol + '//' + childStaticLocation.host;
|
|
6049
|
+
const childFullPath = childStaticLocation.pathname + childStaticLocation.search + childStaticLocation.hash;
|
|
6050
|
+
this.deleteIframeElement = this.createIframeElement(appName, browserHost);
|
|
6051
|
+
this.microAppWindow = this.iframe.contentWindow;
|
|
6052
|
+
// TODO: 优化代码
|
|
6053
|
+
// exec before initStaticGlobalKeys
|
|
6054
|
+
this.createProxyLocation(appName, url, this.microAppWindow, childStaticLocation, browserHost, childHost);
|
|
6055
|
+
this.createProxyWindow(appName, this.microAppWindow);
|
|
6056
|
+
this.initStaticGlobalKeys(appName, url);
|
|
6057
|
+
// get escapeProperties from plugins
|
|
6058
|
+
this.getSpecialProperties(appName);
|
|
6059
|
+
this.patchIframe(this.microAppWindow, (resolve) => {
|
|
6060
|
+
this.createIframeTemplate(this.microAppWindow);
|
|
6061
|
+
patchIframeRoute(appName, this.microAppWindow, childFullPath);
|
|
6062
|
+
this.windowEffect = patchIframeWindow(appName, this.microAppWindow);
|
|
6063
|
+
this.documentEffect = patchIframeDocument(appName, this.microAppWindow, this.proxyLocation);
|
|
6064
|
+
patchIframeElement(appName, url, this.microAppWindow, this);
|
|
6065
|
+
resolve();
|
|
6066
|
+
});
|
|
6067
|
+
}
|
|
6068
|
+
/**
|
|
6069
|
+
* create iframe for sandbox
|
|
6070
|
+
* @param appName app name
|
|
6071
|
+
* @param browserHost browser origin
|
|
6072
|
+
* @returns release callback
|
|
6073
|
+
*/
|
|
6074
|
+
createIframeElement(appName, browserHost) {
|
|
6075
|
+
this.iframe = pureCreateElement('iframe');
|
|
6076
|
+
const iframeAttrs = {
|
|
6077
|
+
src: browserHost,
|
|
6078
|
+
style: 'display: none',
|
|
6079
|
+
id: appName,
|
|
6080
|
+
};
|
|
6081
|
+
Object.keys(iframeAttrs).forEach((key) => this.iframe.setAttribute(key, iframeAttrs[key]));
|
|
6082
|
+
// effect action during construct
|
|
6083
|
+
globalEnv.rawDocument.body.appendChild(this.iframe);
|
|
6084
|
+
/**
|
|
6085
|
+
* If dom operated async when unmount, premature deletion of iframe will cause unexpected problems
|
|
6086
|
+
* e.g.
|
|
6087
|
+
* 1. antd: notification.destroy()
|
|
6088
|
+
* WARNING:
|
|
6089
|
+
* If async operation time is too long, defer cannot avoid the problem
|
|
6090
|
+
* TODO: more test
|
|
6091
|
+
*/
|
|
6092
|
+
return () => defer(() => {
|
|
6093
|
+
var _a, _b;
|
|
6094
|
+
// default mode or destroy, iframe will be deleted when unmount
|
|
6095
|
+
(_b = (_a = this.iframe) === null || _a === void 0 ? void 0 : _a.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(this.iframe);
|
|
6096
|
+
this.iframe = null;
|
|
6097
|
+
});
|
|
6098
|
+
}
|
|
6099
|
+
start({ baseroute, useMemoryRouter, defaultPage, disablePatchRequest, }) {
|
|
6100
|
+
if (!this.active) {
|
|
6101
|
+
this.active = true;
|
|
6102
|
+
// TODO: 虚拟路由升级
|
|
6103
|
+
if (useMemoryRouter) {
|
|
6104
|
+
this.initRouteState(defaultPage);
|
|
6105
|
+
// unique listener of popstate event for sub app
|
|
6106
|
+
this.removeHistoryListener = addHistoryListener(this.microAppWindow.__MICRO_APP_NAME__);
|
|
6107
|
+
}
|
|
6108
|
+
else {
|
|
6109
|
+
this.microAppWindow.__MICRO_APP_BASE_ROUTE__ = this.microAppWindow.__MICRO_APP_BASE_URL__ = baseroute;
|
|
6110
|
+
}
|
|
6111
|
+
/**
|
|
6112
|
+
* create base element to iframe
|
|
6113
|
+
* WARNING: This will also affect a, image, link and script
|
|
6114
|
+
*/
|
|
6115
|
+
if (!disablePatchRequest) {
|
|
6116
|
+
this.createIframeBase();
|
|
6117
|
+
}
|
|
6118
|
+
if (++globalEnv.activeSandbox === 1) {
|
|
6119
|
+
patchElementAndDocument();
|
|
6120
|
+
patchHistory();
|
|
6121
|
+
}
|
|
6122
|
+
if (++IframeSandbox.activeCount === 1) ;
|
|
6123
|
+
}
|
|
6124
|
+
}
|
|
6125
|
+
stop({ umdMode, keepRouteState, destroy, clearData, }) {
|
|
6126
|
+
if (this.active) {
|
|
6127
|
+
this.recordAndReleaseEffect({ clearData }, !umdMode || destroy);
|
|
6128
|
+
if (this.removeHistoryListener) {
|
|
6129
|
+
this.clearRouteState(keepRouteState);
|
|
6130
|
+
// release listener of popstate
|
|
6131
|
+
this.removeHistoryListener();
|
|
6132
|
+
}
|
|
6133
|
+
if (!umdMode || destroy) {
|
|
6134
|
+
this.deleteIframeElement();
|
|
6135
|
+
this.escapeKeys.forEach((key) => {
|
|
6136
|
+
Reflect.deleteProperty(globalEnv.rawWindow, key);
|
|
6137
|
+
});
|
|
6138
|
+
this.escapeKeys.clear();
|
|
6139
|
+
}
|
|
6140
|
+
if (--globalEnv.activeSandbox === 0) {
|
|
6141
|
+
releasePatchElementAndDocument();
|
|
6142
|
+
releasePatchHistory();
|
|
6143
|
+
}
|
|
6144
|
+
if (--IframeSandbox.activeCount === 0) ;
|
|
6145
|
+
this.active = false;
|
|
6146
|
+
}
|
|
6147
|
+
}
|
|
6148
|
+
/**
|
|
6149
|
+
* Record global effect and then release (effect: global event, timeout, data listener)
|
|
6150
|
+
* Scenes:
|
|
6151
|
+
* 1. unmount of default/umd app
|
|
6152
|
+
* 2. hidden keep-alive app
|
|
6153
|
+
* 3. after init prerender app
|
|
6154
|
+
* @param options {
|
|
6155
|
+
* @param clearData clear data from base app
|
|
6156
|
+
* @param isPrerender is prerender app
|
|
6157
|
+
* @param keepAlive is keep-alive app
|
|
6158
|
+
* }
|
|
6159
|
+
* @param preventRecord prevent record effect events (default or destroy)
|
|
6160
|
+
*/
|
|
6161
|
+
recordAndReleaseEffect(options, preventRecord = false) {
|
|
6162
|
+
if (preventRecord) {
|
|
6163
|
+
this.resetEffectSnapshot();
|
|
6164
|
+
}
|
|
6165
|
+
else {
|
|
6166
|
+
this.recordEffectSnapshot();
|
|
6167
|
+
}
|
|
6168
|
+
this.releaseGlobalEffect(options);
|
|
6169
|
+
}
|
|
6170
|
+
/**
|
|
6171
|
+
* reset effect snapshot data in default mode or destroy
|
|
6172
|
+
* Scenes:
|
|
6173
|
+
* 1. unmount hidden keep-alive app manually
|
|
6174
|
+
* 2. unmount prerender app manually
|
|
6175
|
+
*/
|
|
6176
|
+
resetEffectSnapshot() {
|
|
6177
|
+
this.windowEffect.reset();
|
|
6178
|
+
this.documentEffect.reset();
|
|
6179
|
+
resetDataCenterSnapshot(this.microAppWindow.microApp);
|
|
6180
|
+
}
|
|
6181
|
+
/**
|
|
6182
|
+
* record umd snapshot before the first execution of umdHookMount
|
|
6183
|
+
* Scenes:
|
|
6184
|
+
* 1. exec umdMountHook in umd mode
|
|
6185
|
+
* 2. hidden keep-alive app
|
|
6186
|
+
* 3. after init prerender app
|
|
6187
|
+
*/
|
|
6188
|
+
recordEffectSnapshot() {
|
|
6189
|
+
this.windowEffect.record();
|
|
6190
|
+
this.documentEffect.record();
|
|
6191
|
+
recordDataCenterSnapshot(this.microAppWindow.microApp);
|
|
6192
|
+
}
|
|
6193
|
+
// rebuild umd snapshot before remount umd app
|
|
6194
|
+
rebuildEffectSnapshot() {
|
|
6195
|
+
this.windowEffect.rebuild();
|
|
6196
|
+
this.documentEffect.rebuild();
|
|
6197
|
+
rebuildDataCenterSnapshot(this.microAppWindow.microApp);
|
|
6198
|
+
}
|
|
6199
|
+
/**
|
|
6200
|
+
* clear global event, timeout, data listener
|
|
6201
|
+
* Scenes:
|
|
6202
|
+
* 1. unmount of normal/umd app
|
|
6203
|
+
* 2. hidden keep-alive app
|
|
6204
|
+
* 3. after init prerender app
|
|
6205
|
+
* @param clearData clear data from base app
|
|
6206
|
+
* @param isPrerender is prerender app
|
|
6207
|
+
* @param keepAlive is keep-alive app
|
|
6208
|
+
*/
|
|
6209
|
+
releaseGlobalEffect({ clearData = false }) {
|
|
6210
|
+
var _a, _b, _c;
|
|
6211
|
+
this.windowEffect.release();
|
|
6212
|
+
this.documentEffect.release();
|
|
6213
|
+
(_a = this.microAppWindow.microApp) === null || _a === void 0 ? void 0 : _a.clearDataListener();
|
|
6214
|
+
(_b = this.microAppWindow.microApp) === null || _b === void 0 ? void 0 : _b.clearGlobalDataListener();
|
|
6215
|
+
if (clearData) {
|
|
6216
|
+
microApp.clearData(this.microAppWindow.__MICRO_APP_NAME__);
|
|
6217
|
+
(_c = this.microAppWindow.microApp) === null || _c === void 0 ? void 0 : _c.clearData();
|
|
6218
|
+
}
|
|
6219
|
+
}
|
|
6220
|
+
// set __MICRO_APP_PRE_RENDER__ state
|
|
6221
|
+
setPreRenderState(state) {
|
|
6222
|
+
this.microAppWindow.__MICRO_APP_PRE_RENDER__ = state;
|
|
6223
|
+
}
|
|
6224
|
+
markUmdMode(state) {
|
|
6225
|
+
this.microAppWindow.__MICRO_APP_UMD_MODE__ = state;
|
|
6226
|
+
}
|
|
6227
|
+
initStaticGlobalKeys(appName, url) {
|
|
6228
|
+
this.microAppWindow.__MICRO_APP_ENVIRONMENT__ = true;
|
|
6229
|
+
this.microAppWindow.__MICRO_APP_NAME__ = appName;
|
|
6230
|
+
this.microAppWindow.__MICRO_APP_URL__ = url;
|
|
6231
|
+
this.microAppWindow.__MICRO_APP_PUBLIC_PATH__ = getEffectivePath(url);
|
|
6232
|
+
this.microAppWindow.__MICRO_APP_WINDOW__ = this.microAppWindow;
|
|
6233
|
+
this.microAppWindow.__MICRO_APP_PRE_RENDER__ = false;
|
|
6234
|
+
this.microAppWindow.__MICRO_APP_UMD_MODE__ = false;
|
|
6235
|
+
this.microAppWindow.__MICRO_APP_SANDBOX__ = this;
|
|
6236
|
+
this.microAppWindow.__MICRO_APP_PROXY_WINDOW__ = this.proxyWindow;
|
|
6237
|
+
this.microAppWindow.rawWindow = globalEnv.rawWindow;
|
|
6238
|
+
this.microAppWindow.rawDocument = globalEnv.rawDocument;
|
|
6239
|
+
this.microAppWindow.microApp = assign(new EventCenterForMicroApp(appName), {
|
|
6240
|
+
removeDomScope,
|
|
6241
|
+
pureCreateElement,
|
|
6242
|
+
location: this.proxyLocation,
|
|
6243
|
+
router,
|
|
6244
|
+
});
|
|
6245
|
+
}
|
|
6246
|
+
// TODO: RESTRUCTURE
|
|
6247
|
+
patchIframe(microAppWindow, cb) {
|
|
6248
|
+
this.sandboxReady = new Promise((resolve) => {
|
|
6249
|
+
(function iframeLocationReady() {
|
|
6250
|
+
setTimeout(() => {
|
|
6251
|
+
if (microAppWindow.location.href === 'about:blank') {
|
|
6252
|
+
iframeLocationReady();
|
|
6253
|
+
}
|
|
6254
|
+
else {
|
|
6255
|
+
/**
|
|
6256
|
+
* microAppWindow.document rebuild
|
|
6257
|
+
*/
|
|
6258
|
+
microAppWindow.stop();
|
|
6259
|
+
cb(resolve);
|
|
6260
|
+
}
|
|
6261
|
+
}, 0);
|
|
6262
|
+
})();
|
|
6263
|
+
});
|
|
6264
|
+
}
|
|
6265
|
+
// TODO: RESTRUCTURE
|
|
6266
|
+
createIframeTemplate(microAppWindow) {
|
|
6267
|
+
const microDocument = microAppWindow.document;
|
|
6268
|
+
clearDOM(microDocument);
|
|
6269
|
+
const html = microDocument.createElement('html');
|
|
6270
|
+
html.innerHTML = '<head></head><body></body>';
|
|
6271
|
+
microDocument.appendChild(html);
|
|
6272
|
+
// 记录iframe原生body
|
|
6273
|
+
this.microBody = microDocument.body;
|
|
6274
|
+
this.microHead = microDocument.head;
|
|
6275
|
+
}
|
|
6276
|
+
/**
|
|
6277
|
+
* baseElement will complete the relative address of element according to the URL
|
|
6278
|
+
* e.g: a image link script fetch ajax EventSource
|
|
6279
|
+
*/
|
|
6280
|
+
createIframeBase() {
|
|
6281
|
+
this.baseElement = pureCreateElement('base');
|
|
6282
|
+
this.updateIframeBase();
|
|
6283
|
+
this.microHead.appendChild(this.baseElement);
|
|
6284
|
+
}
|
|
6285
|
+
createProxyLocation(appName, url, microAppWindow, childStaticLocation, browserHost, childHost) {
|
|
6286
|
+
this.proxyLocation = createMicroLocation(appName, url, microAppWindow, childStaticLocation, browserHost, childHost);
|
|
6287
|
+
}
|
|
6288
|
+
createProxyWindow(appName, microAppWindow) {
|
|
6289
|
+
const rawWindow = globalEnv.rawWindow;
|
|
6290
|
+
this.proxyWindow = new Proxy(microAppWindow, {
|
|
6291
|
+
get: (target, key) => {
|
|
6292
|
+
if (key === 'location') {
|
|
6293
|
+
return this.proxyLocation;
|
|
6294
|
+
}
|
|
6295
|
+
if (globalPropertyList.includes(key.toString())) {
|
|
6296
|
+
return this.proxyWindow;
|
|
6297
|
+
}
|
|
6298
|
+
return bindFunctionToRawTarget(Reflect.get(target, key), target);
|
|
6299
|
+
},
|
|
6300
|
+
set: (target, key, value) => {
|
|
6301
|
+
if (this.active) {
|
|
6302
|
+
/**
|
|
6303
|
+
* TODO:
|
|
6304
|
+
* 1、location域名相同,子应用内部跳转时的处理
|
|
6305
|
+
* 2、和with沙箱的变量相同,提取成公共数组
|
|
6306
|
+
*/
|
|
6307
|
+
if (key === 'location') {
|
|
6308
|
+
return Reflect.set(rawWindow, key, value);
|
|
6309
|
+
}
|
|
6310
|
+
Reflect.set(target, key, value);
|
|
6311
|
+
if (this.escapeProperties.includes(key)) {
|
|
6312
|
+
!Reflect.has(rawWindow, key) && this.escapeKeys.add(key);
|
|
6313
|
+
Reflect.set(rawWindow, key, value);
|
|
6314
|
+
}
|
|
6315
|
+
}
|
|
6316
|
+
return true;
|
|
6317
|
+
},
|
|
6318
|
+
has: (target, key) => key in target,
|
|
6319
|
+
deleteProperty: (target, key) => {
|
|
6320
|
+
if (Reflect.has(target, key)) {
|
|
6321
|
+
this.escapeKeys.has(key) && Reflect.deleteProperty(rawWindow, key);
|
|
6322
|
+
return Reflect.deleteProperty(target, key);
|
|
6323
|
+
}
|
|
6324
|
+
return true;
|
|
6325
|
+
},
|
|
6326
|
+
});
|
|
6327
|
+
}
|
|
6328
|
+
/**
|
|
6329
|
+
* get escapeProperties from plugins & adapter
|
|
6330
|
+
* @param appName app name
|
|
6331
|
+
*/
|
|
6332
|
+
getSpecialProperties(appName) {
|
|
6333
|
+
var _a;
|
|
6334
|
+
if (isPlainObject(microApp.options.plugins)) {
|
|
6335
|
+
this.commonActionForSpecialProperties(microApp.options.plugins.global);
|
|
6336
|
+
this.commonActionForSpecialProperties((_a = microApp.options.plugins.modules) === null || _a === void 0 ? void 0 : _a[appName]);
|
|
6337
|
+
}
|
|
6338
|
+
}
|
|
6339
|
+
// common action for global plugins and module plugins
|
|
6340
|
+
commonActionForSpecialProperties(plugins) {
|
|
6341
|
+
if (isArray(plugins)) {
|
|
6342
|
+
for (const plugin of plugins) {
|
|
6343
|
+
if (isPlainObject(plugin)) {
|
|
6344
|
+
if (isArray(plugin.escapeProperties)) {
|
|
6345
|
+
this.escapeProperties = this.escapeProperties.concat(plugin.escapeProperties);
|
|
6346
|
+
}
|
|
6347
|
+
}
|
|
6348
|
+
}
|
|
6349
|
+
}
|
|
6350
|
+
}
|
|
6351
|
+
initRouteState(defaultPage) {
|
|
6352
|
+
initRouteStateWithURL(this.microAppWindow.__MICRO_APP_NAME__, this.microAppWindow.location, defaultPage);
|
|
6353
|
+
}
|
|
6354
|
+
clearRouteState(keepRouteState) {
|
|
6355
|
+
clearRouteStateFromURL(this.microAppWindow.__MICRO_APP_NAME__, this.microAppWindow.__MICRO_APP_URL__, this.microAppWindow.location, keepRouteState);
|
|
6356
|
+
}
|
|
6357
|
+
setRouteInfoForKeepAliveApp() {
|
|
6358
|
+
updateBrowserURLWithLocation(this.microAppWindow.__MICRO_APP_NAME__, this.microAppWindow.location);
|
|
6359
|
+
}
|
|
6360
|
+
removeRouteInfoForKeepAliveApp() {
|
|
6361
|
+
removeStateAndPathFromBrowser(this.microAppWindow.__MICRO_APP_NAME__);
|
|
6362
|
+
}
|
|
6363
|
+
/**
|
|
6364
|
+
* Format all html elements when init
|
|
6365
|
+
* @param container micro app container
|
|
6366
|
+
*/
|
|
6367
|
+
patchStaticElement(container) {
|
|
6368
|
+
patchElementTree(container, this.microAppWindow.__MICRO_APP_NAME__);
|
|
6369
|
+
}
|
|
6370
|
+
/**
|
|
6371
|
+
* Actions:
|
|
6372
|
+
* 1. patch static elements from html
|
|
6373
|
+
* @param container micro app container
|
|
6374
|
+
*/
|
|
6375
|
+
actionBeforeExecScripts(container) {
|
|
6376
|
+
this.patchStaticElement(container);
|
|
6377
|
+
}
|
|
6378
|
+
}
|
|
6379
|
+
IframeSandbox.activeCount = 0; // number of active sandbox
|
|
6380
|
+
|
|
6381
|
+
function formatEventInfo(event, element) {
|
|
6382
|
+
Object.defineProperties(event, {
|
|
6383
|
+
currentTarget: {
|
|
6384
|
+
get() {
|
|
6385
|
+
return element;
|
|
4984
6386
|
}
|
|
4985
6387
|
},
|
|
4986
6388
|
target: {
|
|
@@ -5024,38 +6426,40 @@ function dispatchLifecyclesEvent(element, appName, lifecycleName, error) {
|
|
|
5024
6426
|
}
|
|
5025
6427
|
/**
|
|
5026
6428
|
* Dispatch custom event to micro app
|
|
6429
|
+
* @param app app
|
|
5027
6430
|
* @param eventName event name
|
|
5028
|
-
* @param appName app name
|
|
5029
6431
|
* @param detail event detail
|
|
5030
6432
|
*/
|
|
5031
|
-
function dispatchCustomEventToMicroApp(
|
|
5032
|
-
const event = new CustomEvent(formatEventName
|
|
6433
|
+
function dispatchCustomEventToMicroApp(app, eventName, detail = {}) {
|
|
6434
|
+
const event = new CustomEvent(formatEventName(eventName, app.name), {
|
|
5033
6435
|
detail,
|
|
5034
6436
|
});
|
|
5035
|
-
window
|
|
6437
|
+
const target = app.iframe ? app.sandBox.microAppWindow : window;
|
|
6438
|
+
target.dispatchEvent(event);
|
|
5036
6439
|
}
|
|
5037
6440
|
|
|
5038
6441
|
// micro app instances
|
|
5039
6442
|
const appInstanceMap = new Map();
|
|
5040
6443
|
class CreateApp {
|
|
5041
|
-
constructor({ name, url, container, scopecss, useSandbox, inline,
|
|
6444
|
+
constructor({ name, url, container, scopecss, useSandbox, inline, iframe, ssrUrl, isPrefetch, prefetchLevel, }) {
|
|
5042
6445
|
this.state = appStates.CREATED;
|
|
5043
6446
|
this.keepAliveState = null;
|
|
5044
|
-
this.keepAliveContainer = null;
|
|
5045
6447
|
this.loadSourceLevel = 0;
|
|
5046
6448
|
this.umdHookMount = null;
|
|
5047
6449
|
this.umdHookUnmount = null;
|
|
5048
|
-
this.libraryName = null;
|
|
5049
6450
|
this.umdMode = false;
|
|
6451
|
+
// TODO: 类型优化,加上iframe沙箱
|
|
5050
6452
|
this.sandBox = null;
|
|
5051
6453
|
this.fiber = false;
|
|
5052
6454
|
this.useMemoryRouter = true;
|
|
6455
|
+
appInstanceMap.set(name, this);
|
|
6456
|
+
// init actions
|
|
5053
6457
|
this.name = name;
|
|
5054
6458
|
this.url = url;
|
|
5055
6459
|
this.useSandbox = useSandbox;
|
|
5056
6460
|
this.scopecss = this.useSandbox && scopecss;
|
|
5057
6461
|
this.inline = inline !== null && inline !== void 0 ? inline : false;
|
|
5058
|
-
this.
|
|
6462
|
+
this.iframe = iframe !== null && iframe !== void 0 ? iframe : false;
|
|
5059
6463
|
// not exist when prefetch 👇
|
|
5060
6464
|
this.container = container !== null && container !== void 0 ? container : null;
|
|
5061
6465
|
this.ssrUrl = ssrUrl !== null && ssrUrl !== void 0 ? ssrUrl : '';
|
|
@@ -5063,15 +6467,13 @@ class CreateApp {
|
|
|
5063
6467
|
this.isPrefetch = isPrefetch !== null && isPrefetch !== void 0 ? isPrefetch : false;
|
|
5064
6468
|
this.isPrerender = prefetchLevel === 3;
|
|
5065
6469
|
this.prefetchLevel = prefetchLevel;
|
|
5066
|
-
// init actions
|
|
5067
|
-
appInstanceMap.set(this.name, this);
|
|
5068
6470
|
this.source = { html: null, links: new Set(), scripts: new Set() };
|
|
5069
6471
|
this.loadSourceCode();
|
|
5070
|
-
this.
|
|
6472
|
+
this.createSandbox();
|
|
5071
6473
|
}
|
|
5072
6474
|
// Load resources
|
|
5073
6475
|
loadSourceCode() {
|
|
5074
|
-
this.
|
|
6476
|
+
this.setAppState(appStates.LOADING);
|
|
5075
6477
|
HTMLLoader.getInstance().run(this, extractSourceDom);
|
|
5076
6478
|
}
|
|
5077
6479
|
/**
|
|
@@ -5081,7 +6483,7 @@ class CreateApp {
|
|
|
5081
6483
|
var _a;
|
|
5082
6484
|
if (++this.loadSourceLevel === 2) {
|
|
5083
6485
|
this.source.html = html;
|
|
5084
|
-
this.
|
|
6486
|
+
this.setAppState(appStates.LOADED);
|
|
5085
6487
|
if (!this.isPrefetch && appStates.UNMOUNT !== this.state) {
|
|
5086
6488
|
getRootContainer(this.container).mount(this);
|
|
5087
6489
|
}
|
|
@@ -5092,7 +6494,7 @@ class CreateApp {
|
|
|
5092
6494
|
* 1. fiber forced on
|
|
5093
6495
|
* 2. only virtual router support
|
|
5094
6496
|
*
|
|
5095
|
-
* NOTE: (
|
|
6497
|
+
* NOTE: (Don't update browser url, dispatch popstateEvent, reload window, dispatch lifecycle event)
|
|
5096
6498
|
* 1. pushState/replaceState in child can update microLocation, but will not attach router info to browser url
|
|
5097
6499
|
* 2. prevent dispatch popstate/hashchange event to browser
|
|
5098
6500
|
* 3. all navigation actions of location are invalid (In the future, we can consider update microLocation without trigger browser reload)
|
|
@@ -5112,7 +6514,6 @@ class CreateApp {
|
|
|
5112
6514
|
useMemoryRouter: true,
|
|
5113
6515
|
baseroute: '',
|
|
5114
6516
|
fiber: true,
|
|
5115
|
-
esmodule: this.esmodule,
|
|
5116
6517
|
defaultPage: defaultPage !== null && defaultPage !== void 0 ? defaultPage : '',
|
|
5117
6518
|
disablePatchRequest: disablePatchRequest !== null && disablePatchRequest !== void 0 ? disablePatchRequest : false,
|
|
5118
6519
|
});
|
|
@@ -5127,7 +6528,7 @@ class CreateApp {
|
|
|
5127
6528
|
this.loadSourceLevel = -1;
|
|
5128
6529
|
if (appStates.UNMOUNT !== this.state) {
|
|
5129
6530
|
this.onerror(e);
|
|
5130
|
-
this.
|
|
6531
|
+
this.setAppState(appStates.LOAD_FAILED);
|
|
5131
6532
|
}
|
|
5132
6533
|
}
|
|
5133
6534
|
/**
|
|
@@ -5139,150 +6540,151 @@ class CreateApp {
|
|
|
5139
6540
|
* @param baseroute route prefix, default is ''
|
|
5140
6541
|
* @param disablePatchRequest prevent rewrite request method of child app
|
|
5141
6542
|
* @param fiber run js in fiber mode
|
|
5142
|
-
* @param esmodule support type='module' script
|
|
5143
6543
|
*/
|
|
5144
|
-
mount({ container, inline, useMemoryRouter, defaultPage, baseroute, disablePatchRequest, fiber,
|
|
5145
|
-
var _a, _b, _c, _d, _e, _f;
|
|
6544
|
+
mount({ container, inline, useMemoryRouter, defaultPage, baseroute, disablePatchRequest, fiber, }) {
|
|
5146
6545
|
if (this.loadSourceLevel !== 2) {
|
|
5147
6546
|
/**
|
|
5148
|
-
*
|
|
5149
|
-
*
|
|
5150
|
-
*
|
|
6547
|
+
* container cannot be null when load end
|
|
6548
|
+
* NOTE:
|
|
6549
|
+
* 1. render prefetch app before load end
|
|
6550
|
+
* 2. unmount prefetch app and mount again before load end
|
|
5151
6551
|
*/
|
|
5152
6552
|
this.container = container;
|
|
5153
6553
|
// mount before prerender exec mount (loading source), set isPrerender to false
|
|
5154
6554
|
this.isPrerender = false;
|
|
5155
6555
|
// reset app state to LOADING
|
|
5156
|
-
this.
|
|
6556
|
+
this.setAppState(appStates.LOADING);
|
|
5157
6557
|
return;
|
|
5158
6558
|
}
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
* Transfer the contents of div to the <micro-app> tag
|
|
5163
|
-
*
|
|
5164
|
-
* Special scenes:
|
|
5165
|
-
* 1. mount before prerender exec mount (loading source)
|
|
5166
|
-
* 2. mount when prerender js executing
|
|
5167
|
-
* 3. mount after prerender js exec end
|
|
5168
|
-
*
|
|
5169
|
-
* TODO: test shadowDOM
|
|
5170
|
-
*/
|
|
5171
|
-
if (this.container instanceof HTMLDivElement &&
|
|
5172
|
-
this.container.hasAttribute('prerender')) {
|
|
5173
|
-
/**
|
|
5174
|
-
* rebuild effect event of window, document, data center
|
|
5175
|
-
* explain:
|
|
5176
|
-
* 1. rebuild before exec mount, do nothing
|
|
5177
|
-
* 2. rebuild when js executing, recovery recorded effect event, because prerender fiber mode
|
|
5178
|
-
* 3. rebuild after js exec end, normal recovery effect event
|
|
5179
|
-
*/
|
|
5180
|
-
(_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.rebuildEffectSnapshot();
|
|
5181
|
-
// current this.container is <div prerender='true'></div>
|
|
5182
|
-
cloneContainer(this.container, container, false);
|
|
6559
|
+
this.createSandbox();
|
|
6560
|
+
const nextAction = () => {
|
|
6561
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
5183
6562
|
/**
|
|
5184
|
-
*
|
|
5185
|
-
*
|
|
5186
|
-
*
|
|
6563
|
+
* Special scenes:
|
|
6564
|
+
* 1. mount before prerender exec mount (loading source)
|
|
6565
|
+
* 2. mount when prerender js executing
|
|
6566
|
+
* 3. mount after prerender js exec end
|
|
6567
|
+
* 4. mount after prerender unmounted
|
|
6568
|
+
*
|
|
6569
|
+
* TODO: test shadowDOM
|
|
5187
6570
|
*/
|
|
5188
|
-
this.
|
|
5189
|
-
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
|
|
5193
|
-
|
|
5194
|
-
|
|
5195
|
-
|
|
5196
|
-
|
|
5197
|
-
|
|
5198
|
-
|
|
5199
|
-
|
|
5200
|
-
|
|
5201
|
-
|
|
5202
|
-
|
|
5203
|
-
|
|
5204
|
-
|
|
5205
|
-
|
|
5206
|
-
|
|
5207
|
-
|
|
5208
|
-
|
|
5209
|
-
|
|
5210
|
-
|
|
5211
|
-
|
|
5212
|
-
|
|
5213
|
-
|
|
5214
|
-
|
|
5215
|
-
|
|
5216
|
-
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
|
-
|
|
5221
|
-
|
|
5222
|
-
|
|
5223
|
-
|
|
5224
|
-
|
|
5225
|
-
|
|
5226
|
-
|
|
5227
|
-
|
|
6571
|
+
if (this.isPrerender &&
|
|
6572
|
+
isDivElement(this.container) &&
|
|
6573
|
+
this.container.hasAttribute('prerender')) {
|
|
6574
|
+
/**
|
|
6575
|
+
* rebuild effect event of window, document, data center
|
|
6576
|
+
* explain:
|
|
6577
|
+
* 1. rebuild before exec mount, do nothing
|
|
6578
|
+
* 2. rebuild when js executing, recovery recorded effect event, because prerender fiber mode
|
|
6579
|
+
* 3. rebuild after js exec end, normal recovery effect event
|
|
6580
|
+
*/
|
|
6581
|
+
(_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.rebuildEffectSnapshot();
|
|
6582
|
+
// current this.container is <div prerender='true'></div>
|
|
6583
|
+
cloneContainer(this.container, container, false);
|
|
6584
|
+
/**
|
|
6585
|
+
* set this.container to <micro-app></micro-app>
|
|
6586
|
+
* NOTE:
|
|
6587
|
+
* must exec before this.preRenderEvents?.forEach((cb) => cb())
|
|
6588
|
+
*/
|
|
6589
|
+
this.container = container;
|
|
6590
|
+
(_b = this.preRenderEvents) === null || _b === void 0 ? void 0 : _b.forEach((cb) => cb());
|
|
6591
|
+
// reset isPrerender config
|
|
6592
|
+
this.isPrerender = false;
|
|
6593
|
+
this.preRenderEvents = null;
|
|
6594
|
+
// attach router info to browser url
|
|
6595
|
+
router.attachToURL(this.name);
|
|
6596
|
+
(_c = this.sandBox) === null || _c === void 0 ? void 0 : _c.setPreRenderState(false);
|
|
6597
|
+
}
|
|
6598
|
+
else {
|
|
6599
|
+
this.container = container;
|
|
6600
|
+
this.inline = inline;
|
|
6601
|
+
this.fiber = fiber;
|
|
6602
|
+
// use in sandbox/effect
|
|
6603
|
+
this.useMemoryRouter = useMemoryRouter;
|
|
6604
|
+
// this.hiddenRouter = hiddenRouter ?? this.hiddenRouter
|
|
6605
|
+
const dispatchBeforeMount = () => dispatchLifecyclesEvent(this.container, this.name, lifeCycles.BEFOREMOUNT);
|
|
6606
|
+
if (this.isPrerender) {
|
|
6607
|
+
((_d = this.preRenderEvents) !== null && _d !== void 0 ? _d : (this.preRenderEvents = [])).push(dispatchBeforeMount);
|
|
6608
|
+
}
|
|
6609
|
+
else {
|
|
6610
|
+
dispatchBeforeMount();
|
|
6611
|
+
}
|
|
6612
|
+
this.setAppState(appStates.MOUNTING);
|
|
6613
|
+
// TODO: 将所有cloneContainer中的'as Element'去掉,兼容shadowRoot的场景
|
|
6614
|
+
cloneContainer(this.source.html, this.container, !this.umdMode);
|
|
6615
|
+
(_e = this.sandBox) === null || _e === void 0 ? void 0 : _e.start({
|
|
6616
|
+
umdMode: this.umdMode,
|
|
6617
|
+
baseroute,
|
|
6618
|
+
useMemoryRouter,
|
|
6619
|
+
defaultPage,
|
|
6620
|
+
disablePatchRequest,
|
|
6621
|
+
});
|
|
5228
6622
|
if (!this.umdMode) {
|
|
5229
|
-
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
|
|
5242
|
-
|
|
5243
|
-
|
|
6623
|
+
// update element info of html
|
|
6624
|
+
(_f = this.sandBox) === null || _f === void 0 ? void 0 : _f.actionBeforeExecScripts(this.container);
|
|
6625
|
+
// if all js are executed, param isFinished will be true
|
|
6626
|
+
execScripts(this, (isFinished) => {
|
|
6627
|
+
if (!this.umdMode) {
|
|
6628
|
+
const { mount, unmount } = this.getUmdLibraryHooks();
|
|
6629
|
+
/**
|
|
6630
|
+
* umdHookUnmount can works in default mode
|
|
6631
|
+
* register through window.unmount
|
|
6632
|
+
*/
|
|
6633
|
+
this.umdHookUnmount = unmount;
|
|
6634
|
+
// if mount & unmount is function, the sub app is umd mode
|
|
6635
|
+
if (isFunction(mount) && isFunction(unmount)) {
|
|
6636
|
+
this.umdHookMount = mount;
|
|
6637
|
+
// sandbox must exist
|
|
6638
|
+
this.sandBox.markUmdMode(this.umdMode = true);
|
|
6639
|
+
try {
|
|
6640
|
+
this.handleMounted(this.umdHookMount(microApp.getData(this.name, true)));
|
|
6641
|
+
}
|
|
6642
|
+
catch (e) {
|
|
6643
|
+
logError('An error occurred in function mount \n', this.name, e);
|
|
6644
|
+
}
|
|
6645
|
+
}
|
|
6646
|
+
else if (isFinished === true) {
|
|
6647
|
+
this.handleMounted();
|
|
6648
|
+
}
|
|
5244
6649
|
}
|
|
5245
|
-
|
|
5246
|
-
logError('an error occurred in the mount function \n', this.name, e);
|
|
5247
|
-
}
|
|
5248
|
-
}
|
|
6650
|
+
});
|
|
5249
6651
|
}
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
((_a = this.preRenderEvent) !== null && _a !== void 0 ? _a : (this.preRenderEvent = [])).push(dispatchMounted);
|
|
5255
|
-
this.recordAndReleaseEffect();
|
|
6652
|
+
else {
|
|
6653
|
+
(_g = this.sandBox) === null || _g === void 0 ? void 0 : _g.rebuildEffectSnapshot();
|
|
6654
|
+
try {
|
|
6655
|
+
this.handleMounted(this.umdHookMount(microApp.getData(this.name, true)));
|
|
5256
6656
|
}
|
|
5257
|
-
|
|
5258
|
-
|
|
6657
|
+
catch (e) {
|
|
6658
|
+
logError('An error occurred in function mount \n', this.name, e);
|
|
5259
6659
|
}
|
|
5260
6660
|
}
|
|
5261
|
-
});
|
|
5262
|
-
}
|
|
5263
|
-
else {
|
|
5264
|
-
(_f = this.sandBox) === null || _f === void 0 ? void 0 : _f.rebuildEffectSnapshot();
|
|
5265
|
-
try {
|
|
5266
|
-
umdHookMountResult = this.umdHookMount();
|
|
5267
|
-
}
|
|
5268
|
-
catch (e) {
|
|
5269
|
-
logError('an error occurred in the mount function \n', this.name, e);
|
|
5270
6661
|
}
|
|
5271
|
-
|
|
5272
|
-
|
|
6662
|
+
};
|
|
6663
|
+
// TODO: any替换为iframe沙箱类型
|
|
6664
|
+
this.iframe ? this.sandBox.sandboxReady.then(nextAction) : nextAction();
|
|
5273
6665
|
}
|
|
5274
6666
|
/**
|
|
5275
6667
|
* handle for promise umdHookMount
|
|
5276
6668
|
* @param umdHookMountResult result of umdHookMount
|
|
5277
6669
|
*/
|
|
5278
6670
|
handleMounted(umdHookMountResult) {
|
|
5279
|
-
|
|
5280
|
-
|
|
5281
|
-
|
|
5282
|
-
|
|
6671
|
+
var _a, _b;
|
|
6672
|
+
const dispatchAction = () => {
|
|
6673
|
+
if (isPromise(umdHookMountResult)) {
|
|
6674
|
+
umdHookMountResult
|
|
6675
|
+
.then(() => this.dispatchMountedEvent())
|
|
6676
|
+
.catch((e) => this.onerror(e));
|
|
6677
|
+
}
|
|
6678
|
+
else {
|
|
6679
|
+
this.dispatchMountedEvent();
|
|
6680
|
+
}
|
|
6681
|
+
};
|
|
6682
|
+
if (this.isPrerender) {
|
|
6683
|
+
(_a = this.preRenderEvents) === null || _a === void 0 ? void 0 : _a.push(dispatchAction);
|
|
6684
|
+
(_b = this.sandBox) === null || _b === void 0 ? void 0 : _b.recordAndReleaseEffect({ isPrerender: true });
|
|
5283
6685
|
}
|
|
5284
6686
|
else {
|
|
5285
|
-
|
|
6687
|
+
dispatchAction();
|
|
5286
6688
|
}
|
|
5287
6689
|
}
|
|
5288
6690
|
/**
|
|
@@ -5290,9 +6692,9 @@ class CreateApp {
|
|
|
5290
6692
|
*/
|
|
5291
6693
|
dispatchMountedEvent() {
|
|
5292
6694
|
if (appStates.UNMOUNT !== this.state) {
|
|
5293
|
-
this.
|
|
6695
|
+
this.setAppState(appStates.MOUNTED);
|
|
5294
6696
|
// call window.onmount of child app
|
|
5295
|
-
|
|
6697
|
+
execMicroAppGlobalHook(this.getMicroAppGlobalHook(microGlobalEvent.ONMOUNT), this.name, microGlobalEvent.ONMOUNT, microApp.getData(this.name, true));
|
|
5296
6698
|
// dispatch event mounted to parent
|
|
5297
6699
|
dispatchLifecyclesEvent(this.container, this.name, lifeCycles.MOUNTED);
|
|
5298
6700
|
}
|
|
@@ -5306,30 +6708,25 @@ class CreateApp {
|
|
|
5306
6708
|
* @param unmountcb callback of unmount
|
|
5307
6709
|
*/
|
|
5308
6710
|
unmount({ destroy, clearData, keepRouteState, unmountcb, }) {
|
|
5309
|
-
|
|
5310
|
-
|
|
5311
|
-
|
|
5312
|
-
this.state = appStates.UNMOUNT;
|
|
5313
|
-
this.keepAliveState = null;
|
|
5314
|
-
this.keepAliveContainer = null;
|
|
6711
|
+
var _a;
|
|
6712
|
+
destroy = destroy || this.state === appStates.LOAD_FAILED;
|
|
6713
|
+
this.setAppState(appStates.UNMOUNT);
|
|
5315
6714
|
// result of unmount function
|
|
5316
|
-
let umdHookUnmountResult;
|
|
6715
|
+
let umdHookUnmountResult = null;
|
|
5317
6716
|
/**
|
|
5318
6717
|
* send an unmount event to the micro app or call umd unmount hook
|
|
5319
6718
|
* before the sandbox is cleared
|
|
5320
6719
|
*/
|
|
5321
|
-
|
|
5322
|
-
|
|
5323
|
-
|
|
5324
|
-
|
|
5325
|
-
|
|
5326
|
-
logError('an error occurred in the unmount function \n', this.name, e);
|
|
5327
|
-
}
|
|
6720
|
+
try {
|
|
6721
|
+
umdHookUnmountResult = (_a = this.umdHookUnmount) === null || _a === void 0 ? void 0 : _a.call(this, microApp.getData(this.name, true));
|
|
6722
|
+
}
|
|
6723
|
+
catch (e) {
|
|
6724
|
+
logError('An error occurred in function unmount \n', this.name, e);
|
|
5328
6725
|
}
|
|
5329
|
-
// call window.onunmount of child app
|
|
5330
|
-
callFnWithTryCatch(this.getGlobalEventListener(microGlobalEvent.ONUNMOUNT), this.name, `window.${microGlobalEvent.ONUNMOUNT}`);
|
|
5331
6726
|
// dispatch unmount event to micro app
|
|
5332
|
-
dispatchCustomEventToMicroApp('unmount'
|
|
6727
|
+
dispatchCustomEventToMicroApp(this, 'unmount');
|
|
6728
|
+
// call window.onunmount of child app
|
|
6729
|
+
execMicroAppGlobalHook(this.getMicroAppGlobalHook(microGlobalEvent.ONUNMOUNT), this.name, microGlobalEvent.ONUNMOUNT);
|
|
5333
6730
|
this.handleUnmounted(destroy, clearData, keepRouteState, umdHookUnmountResult, unmountcb);
|
|
5334
6731
|
}
|
|
5335
6732
|
/**
|
|
@@ -5341,19 +6738,17 @@ class CreateApp {
|
|
|
5341
6738
|
* @param unmountcb callback of unmount
|
|
5342
6739
|
*/
|
|
5343
6740
|
handleUnmounted(destroy, clearData, keepRouteState, umdHookUnmountResult, unmountcb) {
|
|
5344
|
-
const
|
|
6741
|
+
const nextAction = () => this.actionsForUnmount({
|
|
5345
6742
|
destroy,
|
|
5346
6743
|
clearData,
|
|
5347
6744
|
keepRouteState,
|
|
5348
6745
|
unmountcb,
|
|
5349
|
-
};
|
|
6746
|
+
});
|
|
5350
6747
|
if (isPromise(umdHookUnmountResult)) {
|
|
5351
|
-
umdHookUnmountResult
|
|
5352
|
-
.then(() => this.actionsForUnmount(unmountParam))
|
|
5353
|
-
.catch(() => this.actionsForUnmount(unmountParam));
|
|
6748
|
+
umdHookUnmountResult.then(nextAction).catch(nextAction);
|
|
5354
6749
|
}
|
|
5355
6750
|
else {
|
|
5356
|
-
|
|
6751
|
+
nextAction();
|
|
5357
6752
|
}
|
|
5358
6753
|
}
|
|
5359
6754
|
/**
|
|
@@ -5364,26 +6759,20 @@ class CreateApp {
|
|
|
5364
6759
|
* @param unmountcb callback of unmount
|
|
5365
6760
|
*/
|
|
5366
6761
|
actionsForUnmount({ destroy, clearData, keepRouteState, unmountcb }) {
|
|
5367
|
-
var _a
|
|
5368
|
-
if (destroy) {
|
|
5369
|
-
this.actionsForCompletelyDestroy();
|
|
5370
|
-
}
|
|
5371
|
-
else if (this.umdMode && this.container.childElementCount) {
|
|
6762
|
+
var _a;
|
|
6763
|
+
if (this.umdMode && this.container && !destroy) {
|
|
5372
6764
|
cloneContainer(this.container, this.source.html, false);
|
|
5373
6765
|
}
|
|
5374
|
-
if (this.umdMode) {
|
|
5375
|
-
(_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.recordEffectSnapshot();
|
|
5376
|
-
}
|
|
5377
6766
|
/**
|
|
5378
6767
|
* this.container maybe contains micro-app element, stop sandbox should exec after cloneContainer
|
|
5379
6768
|
* NOTE:
|
|
5380
6769
|
* 1. if destroy is true, clear route state
|
|
5381
6770
|
* 2. umd mode and keep-alive will not clear EventSource
|
|
5382
6771
|
*/
|
|
5383
|
-
(
|
|
6772
|
+
(_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.stop({
|
|
5384
6773
|
umdMode: this.umdMode,
|
|
5385
6774
|
keepRouteState: keepRouteState && !destroy,
|
|
5386
|
-
|
|
6775
|
+
destroy,
|
|
5387
6776
|
clearData: clearData || destroy,
|
|
5388
6777
|
});
|
|
5389
6778
|
if (!getActiveApps().length) {
|
|
@@ -5391,63 +6780,67 @@ class CreateApp {
|
|
|
5391
6780
|
}
|
|
5392
6781
|
// dispatch unmount event to base app
|
|
5393
6782
|
dispatchLifecyclesEvent(this.container, this.name, lifeCycles.UNMOUNT);
|
|
5394
|
-
this.
|
|
5395
|
-
unmountcb
|
|
6783
|
+
this.clearOptions(destroy);
|
|
6784
|
+
unmountcb === null || unmountcb === void 0 ? void 0 : unmountcb();
|
|
5396
6785
|
}
|
|
5397
|
-
|
|
6786
|
+
clearOptions(destroy) {
|
|
5398
6787
|
this.container.innerHTML = '';
|
|
5399
6788
|
this.container = null;
|
|
5400
6789
|
this.isPrerender = false;
|
|
5401
|
-
this.
|
|
6790
|
+
this.preRenderEvents = null;
|
|
6791
|
+
this.setKeepAliveState(null);
|
|
6792
|
+
// in iframe sandbox & default mode, delete the sandbox & iframeElement
|
|
6793
|
+
if (this.iframe && !this.umdMode)
|
|
6794
|
+
this.sandBox = null;
|
|
6795
|
+
if (destroy)
|
|
6796
|
+
this.actionsForCompletelyDestroy();
|
|
5402
6797
|
}
|
|
5403
6798
|
// actions for completely destroy
|
|
5404
6799
|
actionsForCompletelyDestroy() {
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
}
|
|
6800
|
+
var _a, _b;
|
|
6801
|
+
(_b = (_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.deleteIframeElement) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
5408
6802
|
sourceCenter.script.deleteInlineInfo(this.source.scripts);
|
|
5409
6803
|
appInstanceMap.delete(this.name);
|
|
5410
6804
|
}
|
|
5411
6805
|
// hidden app when disconnectedCallback called with keep-alive
|
|
5412
6806
|
hiddenKeepAliveApp(callback) {
|
|
5413
|
-
var _a;
|
|
5414
|
-
|
|
5415
|
-
|
|
5416
|
-
|
|
5417
|
-
|
|
5418
|
-
|
|
5419
|
-
|
|
5420
|
-
dispatchCustomEventToMicroApp('appstate-change', this.name, {
|
|
6807
|
+
var _a, _b;
|
|
6808
|
+
this.setKeepAliveState(keepAliveStates.KEEP_ALIVE_HIDDEN);
|
|
6809
|
+
/**
|
|
6810
|
+
* event should dispatch before clone node
|
|
6811
|
+
* dispatch afterHidden event to micro-app
|
|
6812
|
+
*/
|
|
6813
|
+
dispatchCustomEventToMicroApp(this, 'appstate-change', {
|
|
5421
6814
|
appState: 'afterhidden',
|
|
5422
6815
|
});
|
|
5423
6816
|
// dispatch afterHidden event to base app
|
|
5424
|
-
dispatchLifecyclesEvent(
|
|
6817
|
+
dispatchLifecyclesEvent(this.container, this.name, lifeCycles.AFTERHIDDEN);
|
|
5425
6818
|
if (this.useMemoryRouter) {
|
|
5426
6819
|
// called after lifeCyclesEvent
|
|
5427
6820
|
(_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.removeRouteInfoForKeepAliveApp();
|
|
5428
6821
|
}
|
|
5429
|
-
this.
|
|
5430
|
-
|
|
6822
|
+
this.container = cloneContainer(this.container, pureCreateElement('div'), false);
|
|
6823
|
+
(_b = this.sandBox) === null || _b === void 0 ? void 0 : _b.recordAndReleaseEffect({ keepAlive: true });
|
|
6824
|
+
callback === null || callback === void 0 ? void 0 : callback();
|
|
5431
6825
|
}
|
|
5432
6826
|
// show app when connectedCallback called with keep-alive
|
|
5433
6827
|
showKeepAliveApp(container) {
|
|
5434
6828
|
var _a, _b;
|
|
5435
6829
|
(_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.rebuildEffectSnapshot();
|
|
5436
6830
|
// dispatch beforeShow event to micro-app
|
|
5437
|
-
dispatchCustomEventToMicroApp('appstate-change',
|
|
6831
|
+
dispatchCustomEventToMicroApp(this, 'appstate-change', {
|
|
5438
6832
|
appState: 'beforeshow',
|
|
5439
6833
|
});
|
|
5440
6834
|
// dispatch beforeShow event to base app
|
|
5441
6835
|
dispatchLifecyclesEvent(container, this.name, lifeCycles.BEFORESHOW);
|
|
5442
|
-
|
|
5443
|
-
this.container = container;
|
|
5444
|
-
this.keepAliveState = keepAliveStates.KEEP_ALIVE_SHOW;
|
|
6836
|
+
this.setKeepAliveState(keepAliveStates.KEEP_ALIVE_SHOW);
|
|
6837
|
+
this.container = cloneContainer(this.container, container, false);
|
|
5445
6838
|
if (this.useMemoryRouter) {
|
|
5446
6839
|
// called before lifeCyclesEvent
|
|
5447
6840
|
(_b = this.sandBox) === null || _b === void 0 ? void 0 : _b.setRouteInfoForKeepAliveApp();
|
|
5448
6841
|
}
|
|
5449
6842
|
// dispatch afterShow event to micro-app
|
|
5450
|
-
dispatchCustomEventToMicroApp('appstate-change',
|
|
6843
|
+
dispatchCustomEventToMicroApp(this, 'appstate-change', {
|
|
5451
6844
|
appState: 'aftershow',
|
|
5452
6845
|
});
|
|
5453
6846
|
// dispatch afterShow event to base app
|
|
@@ -5460,48 +6853,71 @@ class CreateApp {
|
|
|
5460
6853
|
onerror(e) {
|
|
5461
6854
|
dispatchLifecyclesEvent(this.container, this.name, lifeCycles.ERROR, e);
|
|
5462
6855
|
}
|
|
6856
|
+
/**
|
|
6857
|
+
* Scene:
|
|
6858
|
+
* 1. create app
|
|
6859
|
+
* 2. remount of default mode with iframe sandbox
|
|
6860
|
+
* In default mode with iframe sandbox, unmount app will delete iframeElement & sandBox, and create sandBox when mount again, used to solve the problem that module script cannot be execute when append it again
|
|
6861
|
+
*/
|
|
6862
|
+
createSandbox() {
|
|
6863
|
+
if (this.useSandbox && !this.sandBox) {
|
|
6864
|
+
if (this.iframe) {
|
|
6865
|
+
this.sandBox = new IframeSandbox(this.name, this.url);
|
|
6866
|
+
}
|
|
6867
|
+
else {
|
|
6868
|
+
this.sandBox = new WithSandBox(this.name, this.url);
|
|
6869
|
+
}
|
|
6870
|
+
}
|
|
6871
|
+
}
|
|
6872
|
+
// set app state
|
|
6873
|
+
setAppState(state) {
|
|
6874
|
+
this.state = state;
|
|
6875
|
+
}
|
|
5463
6876
|
// get app state
|
|
5464
6877
|
getAppState() {
|
|
5465
6878
|
return this.state;
|
|
5466
6879
|
}
|
|
6880
|
+
// set keep-alive state
|
|
6881
|
+
setKeepAliveState(state) {
|
|
6882
|
+
this.keepAliveState = state;
|
|
6883
|
+
}
|
|
5467
6884
|
// get keep-alive state
|
|
5468
6885
|
getKeepAliveState() {
|
|
5469
6886
|
return this.keepAliveState;
|
|
5470
6887
|
}
|
|
5471
6888
|
// get umd library, if it not exist, return empty object
|
|
5472
6889
|
getUmdLibraryHooks() {
|
|
5473
|
-
var _a, _b, _c, _d;
|
|
5474
6890
|
// after execScripts, the app maybe unmounted
|
|
5475
|
-
if (appStates.UNMOUNT !== this.state) {
|
|
5476
|
-
const
|
|
5477
|
-
|
|
5478
|
-
|
|
5479
|
-
|
|
6891
|
+
if (appStates.UNMOUNT !== this.state && this.sandBox) {
|
|
6892
|
+
const libraryName = getRootContainer(this.container).getAttribute('library') || `micro-app-${this.name}`;
|
|
6893
|
+
const proxyWindow = this.sandBox.proxyWindow;
|
|
6894
|
+
// compatible with pre versions
|
|
6895
|
+
if (isObject(proxyWindow[libraryName])) {
|
|
6896
|
+
return proxyWindow[libraryName];
|
|
5480
6897
|
}
|
|
5481
6898
|
return {
|
|
5482
|
-
mount:
|
|
5483
|
-
unmount:
|
|
6899
|
+
mount: proxyWindow.mount,
|
|
6900
|
+
unmount: proxyWindow.unmount,
|
|
5484
6901
|
};
|
|
5485
6902
|
}
|
|
5486
6903
|
return {};
|
|
5487
6904
|
}
|
|
5488
|
-
|
|
6905
|
+
getMicroAppGlobalHook(eventName) {
|
|
5489
6906
|
var _a;
|
|
5490
|
-
|
|
5491
|
-
const listener = (_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.proxyWindow[eventName];
|
|
6907
|
+
const listener = ((_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.proxyWindow)[eventName];
|
|
5492
6908
|
return isFunction(listener) ? listener : null;
|
|
5493
6909
|
}
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
* Scenes:
|
|
5497
|
-
* 1. hidden keep-alive app
|
|
5498
|
-
* 2. after init prerender app
|
|
5499
|
-
*/
|
|
5500
|
-
recordAndReleaseEffect() {
|
|
5501
|
-
var _a, _b;
|
|
5502
|
-
(_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.recordEffectSnapshot();
|
|
5503
|
-
(_b = this.sandBox) === null || _b === void 0 ? void 0 : _b.releaseGlobalEffect();
|
|
6910
|
+
querySelector(selectors) {
|
|
6911
|
+
return this.container ? globalEnv.rawElementQuerySelector.call(this.container, selectors) : null;
|
|
5504
6912
|
}
|
|
6913
|
+
querySelectorAll(selectors) {
|
|
6914
|
+
return this.container ? globalEnv.rawElementQuerySelectorAll.call(this.container, selectors) : [];
|
|
6915
|
+
}
|
|
6916
|
+
}
|
|
6917
|
+
// iframe route mode
|
|
6918
|
+
function isIframeSandbox(appName) {
|
|
6919
|
+
var _a, _b;
|
|
6920
|
+
return (_b = (_a = appInstanceMap.get(appName)) === null || _a === void 0 ? void 0 : _a.iframe) !== null && _b !== void 0 ? _b : false;
|
|
5505
6921
|
}
|
|
5506
6922
|
|
|
5507
6923
|
/**
|
|
@@ -5530,12 +6946,14 @@ function defineElement(tagName) {
|
|
|
5530
6946
|
const formatAttrName = formatAppName(this.getAttribute('name'));
|
|
5531
6947
|
const formatAttrUrl = formatAppURL(this.getAttribute('url'), this.appName);
|
|
5532
6948
|
if (this.legalAttribute('name', formatAttrName) && this.legalAttribute('url', formatAttrUrl)) {
|
|
5533
|
-
const
|
|
5534
|
-
|
|
5535
|
-
|
|
5536
|
-
|
|
5537
|
-
|
|
5538
|
-
|
|
6949
|
+
const oldApp = appInstanceMap.get(formatAttrName);
|
|
6950
|
+
/**
|
|
6951
|
+
* If oldApp exist & appName is different, determine whether oldApp is running
|
|
6952
|
+
*/
|
|
6953
|
+
if (formatAttrName !== this.appName && oldApp) {
|
|
6954
|
+
if (oldApp.getAppState() !== appStates.UNMOUNT &&
|
|
6955
|
+
oldApp.getKeepAliveState() !== keepAliveStates.KEEP_ALIVE_HIDDEN &&
|
|
6956
|
+
!oldApp.isPrefetch) {
|
|
5539
6957
|
this.setAttribute('name', this.appName);
|
|
5540
6958
|
return logError(`app name conflict, an app named ${formatAttrName} is running`);
|
|
5541
6959
|
}
|
|
@@ -5543,16 +6961,16 @@ function defineElement(tagName) {
|
|
|
5543
6961
|
if (formatAttrName !== this.appName || formatAttrUrl !== this.appUrl) {
|
|
5544
6962
|
if (formatAttrName === this.appName) {
|
|
5545
6963
|
this.handleUnmount(true, () => {
|
|
5546
|
-
this.actionsForAttributeChange(formatAttrName, formatAttrUrl,
|
|
6964
|
+
this.actionsForAttributeChange(formatAttrName, formatAttrUrl, oldApp);
|
|
5547
6965
|
});
|
|
5548
6966
|
}
|
|
5549
6967
|
else if (this.getKeepAliveModeResult()) {
|
|
5550
6968
|
this.handleHiddenKeepAliveApp();
|
|
5551
|
-
this.actionsForAttributeChange(formatAttrName, formatAttrUrl,
|
|
6969
|
+
this.actionsForAttributeChange(formatAttrName, formatAttrUrl, oldApp);
|
|
5552
6970
|
}
|
|
5553
6971
|
else {
|
|
5554
6972
|
this.handleUnmount(this.getDestroyCompatibleResult(), () => {
|
|
5555
|
-
this.actionsForAttributeChange(formatAttrName, formatAttrUrl,
|
|
6973
|
+
this.actionsForAttributeChange(formatAttrName, formatAttrUrl, oldApp);
|
|
5556
6974
|
});
|
|
5557
6975
|
}
|
|
5558
6976
|
}
|
|
@@ -5684,37 +7102,35 @@ function defineElement(tagName) {
|
|
|
5684
7102
|
}
|
|
5685
7103
|
this.updateSsrUrl(this.appUrl);
|
|
5686
7104
|
if (appInstanceMap.has(this.appName)) {
|
|
5687
|
-
const
|
|
5688
|
-
const
|
|
5689
|
-
const
|
|
7105
|
+
const oldApp = appInstanceMap.get(this.appName);
|
|
7106
|
+
const oldAppUrl = oldApp.ssrUrl || oldApp.url;
|
|
7107
|
+
const targetUrl = this.ssrUrl || this.appUrl;
|
|
5690
7108
|
/**
|
|
5691
7109
|
* NOTE:
|
|
5692
7110
|
* 1. keep-alive don't care about ssrUrl
|
|
5693
7111
|
* 2. Even if the keep-alive app is pushed into the background, it is still active and cannot be replaced. Otherwise, it is difficult for developers to troubleshoot in case of conflict and will leave developers at a loss
|
|
5694
7112
|
* 3. When scopecss, useSandbox of prefetch app different from target app, delete prefetch app and create new one
|
|
5695
7113
|
*/
|
|
5696
|
-
if (
|
|
5697
|
-
|
|
5698
|
-
this.handleShowKeepAliveApp(
|
|
7114
|
+
if (oldApp.getKeepAliveState() === keepAliveStates.KEEP_ALIVE_HIDDEN &&
|
|
7115
|
+
oldApp.url === this.appUrl) {
|
|
7116
|
+
this.handleShowKeepAliveApp(oldApp);
|
|
5699
7117
|
}
|
|
5700
|
-
else if (
|
|
5701
|
-
(
|
|
5702
|
-
|
|
5703
|
-
this.handleAppMount(
|
|
7118
|
+
else if (oldAppUrl === targetUrl && (oldApp.getAppState() === appStates.UNMOUNT ||
|
|
7119
|
+
(oldApp.isPrefetch &&
|
|
7120
|
+
this.sameCoreOptions(oldApp)))) {
|
|
7121
|
+
this.handleAppMount(oldApp);
|
|
5704
7122
|
}
|
|
5705
|
-
else if (
|
|
5706
|
-
if ((process.env.NODE_ENV !== 'production') &&
|
|
5707
|
-
app.scopecss === this.isScopecss() &&
|
|
5708
|
-
app.useSandbox === this.isSandbox()) {
|
|
7123
|
+
else if (oldApp.isPrefetch || oldApp.getAppState() === appStates.UNMOUNT) {
|
|
7124
|
+
if ((process.env.NODE_ENV !== 'production') && this.sameCoreOptions(oldApp)) {
|
|
5709
7125
|
/**
|
|
5710
7126
|
* url is different & old app is unmounted or prefetch, create new app to replace old one
|
|
5711
7127
|
*/
|
|
5712
|
-
logWarn(`the ${
|
|
7128
|
+
logWarn(`the ${oldApp.isPrefetch ? 'prefetch' : 'unmounted'} app with url: ${oldAppUrl} replaced by a new app with url: ${targetUrl}`, this.appName);
|
|
5713
7129
|
}
|
|
5714
7130
|
this.handleCreateApp();
|
|
5715
7131
|
}
|
|
5716
7132
|
else {
|
|
5717
|
-
logError(`app name conflict, an app named: ${this.appName} with url: ${
|
|
7133
|
+
logError(`app name conflict, an app named: ${this.appName} with url: ${oldAppUrl} is running`);
|
|
5718
7134
|
}
|
|
5719
7135
|
}
|
|
5720
7136
|
else {
|
|
@@ -5722,7 +7138,7 @@ function defineElement(tagName) {
|
|
|
5722
7138
|
}
|
|
5723
7139
|
}
|
|
5724
7140
|
// remount app or create app if attribute url or name change
|
|
5725
|
-
actionsForAttributeChange(formatAttrName, formatAttrUrl,
|
|
7141
|
+
actionsForAttributeChange(formatAttrName, formatAttrUrl, oldApp) {
|
|
5726
7142
|
var _a;
|
|
5727
7143
|
/**
|
|
5728
7144
|
* do not add judgment of formatAttrUrl === this.appUrl
|
|
@@ -5735,26 +7151,38 @@ function defineElement(tagName) {
|
|
|
5735
7151
|
this.setAttribute('name', this.appName);
|
|
5736
7152
|
}
|
|
5737
7153
|
/**
|
|
5738
|
-
* when
|
|
5739
|
-
* scene1: if formatAttrName and this.appName are equal: exitApp is the current app, the url must be different,
|
|
5740
|
-
* scene2: if formatAttrName and this.appName are different:
|
|
7154
|
+
* when oldApp not null: this.appName === oldApp.name
|
|
7155
|
+
* scene1: if formatAttrName and this.appName are equal: exitApp is the current app, the url must be different, oldApp has been unmounted
|
|
7156
|
+
* scene2: if formatAttrName and this.appName are different: oldApp must be prefetch or unmounted, if url is equal, then just mount, if url is different, then create new app to replace oldApp
|
|
5741
7157
|
* scene3: url is different but ssrUrl is equal
|
|
5742
7158
|
* scene4: url is equal but ssrUrl is different, if url is equal, name must different
|
|
5743
|
-
* scene5: if
|
|
7159
|
+
* scene5: if oldApp is KEEP_ALIVE_HIDDEN, name must different
|
|
5744
7160
|
*/
|
|
5745
|
-
if (
|
|
5746
|
-
if (
|
|
5747
|
-
if (
|
|
5748
|
-
this.handleShowKeepAliveApp(
|
|
7161
|
+
if (oldApp) {
|
|
7162
|
+
if (oldApp.getKeepAliveState() === keepAliveStates.KEEP_ALIVE_HIDDEN) {
|
|
7163
|
+
if (oldApp.url === this.appUrl) {
|
|
7164
|
+
this.handleShowKeepAliveApp(oldApp);
|
|
5749
7165
|
}
|
|
5750
7166
|
else {
|
|
5751
7167
|
// the hidden keep-alive app is still active
|
|
5752
7168
|
logError(`app name conflict, an app named ${this.appName} is running`);
|
|
5753
7169
|
}
|
|
7170
|
+
/**
|
|
7171
|
+
* TODO:
|
|
7172
|
+
* 1. oldApp必是unmountApp或preFetchApp,这里还应该考虑沙箱、iframe、样式隔离不一致的情况
|
|
7173
|
+
* 2. unmountApp要不要判断样式隔离、沙箱、iframe,然后彻底删除并再次渲染?(包括handleConnected里的处理,先不改?)
|
|
7174
|
+
* 推荐:if (
|
|
7175
|
+
* oldApp.url === this.appUrl &&
|
|
7176
|
+
* oldApp.ssrUrl === this.ssrUrl && (
|
|
7177
|
+
* oldApp.getAppState() === appStates.UNMOUNT ||
|
|
7178
|
+
* (oldApp.isPrefetch && this.sameCoreOptions(oldApp))
|
|
7179
|
+
* )
|
|
7180
|
+
* )
|
|
7181
|
+
*/
|
|
5754
7182
|
}
|
|
5755
|
-
else if (
|
|
7183
|
+
else if (oldApp.url === this.appUrl && oldApp.ssrUrl === this.ssrUrl) {
|
|
5756
7184
|
// mount app
|
|
5757
|
-
this.handleAppMount(
|
|
7185
|
+
this.handleAppMount(oldApp);
|
|
5758
7186
|
}
|
|
5759
7187
|
else {
|
|
5760
7188
|
this.handleCreateApp();
|
|
@@ -5778,24 +7206,39 @@ function defineElement(tagName) {
|
|
|
5778
7206
|
}
|
|
5779
7207
|
// create app instance
|
|
5780
7208
|
handleCreateApp() {
|
|
5781
|
-
|
|
7209
|
+
const createAppInstance = () => {
|
|
7210
|
+
var _a;
|
|
7211
|
+
return new CreateApp({
|
|
7212
|
+
name: this.appName,
|
|
7213
|
+
url: this.appUrl,
|
|
7214
|
+
scopecss: this.useScopecss(),
|
|
7215
|
+
useSandbox: this.useSandbox(),
|
|
7216
|
+
inline: this.getDisposeResult('inline'),
|
|
7217
|
+
iframe: this.getDisposeResult('iframe'),
|
|
7218
|
+
container: (_a = this.shadowRoot) !== null && _a !== void 0 ? _a : this,
|
|
7219
|
+
ssrUrl: this.ssrUrl,
|
|
7220
|
+
});
|
|
7221
|
+
};
|
|
5782
7222
|
/**
|
|
5783
|
-
*
|
|
5784
|
-
*
|
|
7223
|
+
* Actions for destroy old app
|
|
7224
|
+
* If oldApp exist, it must be 3 scenes:
|
|
7225
|
+
* 1. oldApp is unmounted app (url is is different)
|
|
7226
|
+
* 2. oldApp is prefetch, not prerender (url, scopecss, useSandbox, iframe is different)
|
|
7227
|
+
* 3. oldApp is prerender (url, scopecss, useSandbox, iframe is different)
|
|
5785
7228
|
*/
|
|
5786
|
-
|
|
5787
|
-
|
|
7229
|
+
const oldApp = appInstanceMap.get(this.appName);
|
|
7230
|
+
if (oldApp) {
|
|
7231
|
+
if (oldApp.isPrerender) {
|
|
7232
|
+
this.handleUnmount(true, createAppInstance);
|
|
7233
|
+
}
|
|
7234
|
+
else {
|
|
7235
|
+
oldApp.actionsForCompletelyDestroy();
|
|
7236
|
+
createAppInstance();
|
|
7237
|
+
}
|
|
7238
|
+
}
|
|
7239
|
+
else {
|
|
7240
|
+
createAppInstance();
|
|
5788
7241
|
}
|
|
5789
|
-
new CreateApp({
|
|
5790
|
-
name: this.appName,
|
|
5791
|
-
url: this.appUrl,
|
|
5792
|
-
scopecss: this.isScopecss(),
|
|
5793
|
-
useSandbox: this.isSandbox(),
|
|
5794
|
-
inline: this.getDisposeResult('inline'),
|
|
5795
|
-
esmodule: this.getDisposeResult('esmodule'),
|
|
5796
|
-
container: (_a = this.shadowRoot) !== null && _a !== void 0 ? _a : this,
|
|
5797
|
-
ssrUrl: this.ssrUrl,
|
|
5798
|
-
});
|
|
5799
7242
|
}
|
|
5800
7243
|
/**
|
|
5801
7244
|
* mount app
|
|
@@ -5821,7 +7264,6 @@ function defineElement(tagName) {
|
|
|
5821
7264
|
baseroute: this.getBaseRouteCompatible(),
|
|
5822
7265
|
disablePatchRequest: this.getDisposeResult('disable-patch-request'),
|
|
5823
7266
|
fiber: this.getDisposeResult('fiber'),
|
|
5824
|
-
esmodule: this.getDisposeResult('esmodule'),
|
|
5825
7267
|
});
|
|
5826
7268
|
}
|
|
5827
7269
|
/**
|
|
@@ -5860,10 +7302,10 @@ function defineElement(tagName) {
|
|
|
5860
7302
|
* @param name Configuration item name
|
|
5861
7303
|
*/
|
|
5862
7304
|
getDisposeResult(name) {
|
|
5863
|
-
return (this.
|
|
7305
|
+
return (this.compatibleProperties(name) || !!microApp.options[name]) && this.compatibleDisableProperties(name);
|
|
5864
7306
|
}
|
|
5865
7307
|
// compatible of disableScopecss & disableSandbox
|
|
5866
|
-
|
|
7308
|
+
compatibleProperties(name) {
|
|
5867
7309
|
if (name === 'disable-scopecss') {
|
|
5868
7310
|
return this.hasAttribute('disable-scopecss') || this.hasAttribute('disableScopecss');
|
|
5869
7311
|
}
|
|
@@ -5873,7 +7315,7 @@ function defineElement(tagName) {
|
|
|
5873
7315
|
return this.hasAttribute(name);
|
|
5874
7316
|
}
|
|
5875
7317
|
// compatible of disableScopecss & disableSandbox
|
|
5876
|
-
|
|
7318
|
+
compatibleDisableProperties(name) {
|
|
5877
7319
|
if (name === 'disable-scopecss') {
|
|
5878
7320
|
return this.getAttribute('disable-scopecss') !== 'false' && this.getAttribute('disableScopecss') !== 'false';
|
|
5879
7321
|
}
|
|
@@ -5882,12 +7324,20 @@ function defineElement(tagName) {
|
|
|
5882
7324
|
}
|
|
5883
7325
|
return this.getAttribute(name) !== 'false';
|
|
5884
7326
|
}
|
|
5885
|
-
|
|
7327
|
+
useScopecss() {
|
|
5886
7328
|
return !(this.getDisposeResult('disable-scopecss') || this.getDisposeResult('shadowDOM'));
|
|
5887
7329
|
}
|
|
5888
|
-
|
|
7330
|
+
useSandbox() {
|
|
5889
7331
|
return !this.getDisposeResult('disable-sandbox');
|
|
5890
7332
|
}
|
|
7333
|
+
/**
|
|
7334
|
+
* Determine whether the core options of the existApp is consistent with the new one
|
|
7335
|
+
*/
|
|
7336
|
+
sameCoreOptions(app) {
|
|
7337
|
+
return (app.scopecss === this.useScopecss() &&
|
|
7338
|
+
app.useSandbox === this.useSandbox() &&
|
|
7339
|
+
app.iframe === this.getDisposeResult('iframe'));
|
|
7340
|
+
}
|
|
5891
7341
|
/**
|
|
5892
7342
|
* 2021-09-08
|
|
5893
7343
|
* get baseRoute
|
|
@@ -5972,7 +7422,7 @@ function defineElement(tagName) {
|
|
|
5972
7422
|
* {
|
|
5973
7423
|
* name: string,
|
|
5974
7424
|
* url: string,
|
|
5975
|
-
*
|
|
7425
|
+
* iframe: boolean,
|
|
5976
7426
|
* inline: boolean,
|
|
5977
7427
|
* 'disable-scopecss': boolean,
|
|
5978
7428
|
* 'disable-sandbox': boolean,
|
|
@@ -6036,7 +7486,7 @@ function preFetchAction(options) {
|
|
|
6036
7486
|
scopecss: !((_b = (_a = options['disable-scopecss']) !== null && _a !== void 0 ? _a : options.disableScopecss) !== null && _b !== void 0 ? _b : microApp.options['disable-scopecss']),
|
|
6037
7487
|
useSandbox: !((_d = (_c = options['disable-sandbox']) !== null && _c !== void 0 ? _c : options.disableSandbox) !== null && _d !== void 0 ? _d : microApp.options['disable-sandbox']),
|
|
6038
7488
|
inline: (_e = options.inline) !== null && _e !== void 0 ? _e : microApp.options.inline,
|
|
6039
|
-
|
|
7489
|
+
iframe: (_f = options.iframe) !== null && _f !== void 0 ? _f : microApp.options.iframe,
|
|
6040
7490
|
prefetchLevel: options.level && PREFETCH_LEVEL.includes(options.level) ? options.level : microApp.options.prefetchLevel && PREFETCH_LEVEL.includes(microApp.options.prefetchLevel) ? microApp.options.prefetchLevel : 2,
|
|
6041
7491
|
});
|
|
6042
7492
|
const oldOnload = app.onLoad;
|
|
@@ -6135,10 +7585,19 @@ function unmountApp(appName, options) {
|
|
|
6135
7585
|
return new Promise((resolve) => {
|
|
6136
7586
|
if (app) {
|
|
6137
7587
|
if (app.getAppState() === appStates.UNMOUNT || app.isPrefetch) {
|
|
6138
|
-
if (
|
|
6139
|
-
app.
|
|
7588
|
+
if (app.isPrerender) {
|
|
7589
|
+
app.unmount({
|
|
7590
|
+
destroy: !!(options === null || options === void 0 ? void 0 : options.destroy),
|
|
7591
|
+
clearData: !!(options === null || options === void 0 ? void 0 : options.clearData),
|
|
7592
|
+
keepRouteState: false,
|
|
7593
|
+
unmountcb: resolve.bind(null, true)
|
|
7594
|
+
});
|
|
7595
|
+
}
|
|
7596
|
+
else {
|
|
7597
|
+
if (options === null || options === void 0 ? void 0 : options.destroy)
|
|
7598
|
+
app.actionsForCompletelyDestroy();
|
|
7599
|
+
resolve(true);
|
|
6140
7600
|
}
|
|
6141
|
-
resolve(true);
|
|
6142
7601
|
}
|
|
6143
7602
|
else if (app.getKeepAliveState() === keepAliveStates.KEEP_ALIVE_HIDDEN) {
|
|
6144
7603
|
if (options === null || options === void 0 ? void 0 : options.destroy) {
|
|
@@ -6188,7 +7647,7 @@ function unmountApp(appName, options) {
|
|
|
6188
7647
|
else if ((options === null || options === void 0 ? void 0 : options.clearAliveState) && container.hasAttribute('keep-alive')) {
|
|
6189
7648
|
const keepAliveAttrValue = container.getAttribute('keep-alive');
|
|
6190
7649
|
container.removeAttribute('keep-alive');
|
|
6191
|
-
let clearDataAttrValue;
|
|
7650
|
+
let clearDataAttrValue = null;
|
|
6192
7651
|
if (options.clearData) {
|
|
6193
7652
|
clearDataAttrValue = container.getAttribute('clear-data');
|
|
6194
7653
|
container.setAttribute('clear-data', 'true');
|
|
@@ -6198,7 +7657,7 @@ function unmountApp(appName, options) {
|
|
|
6198
7657
|
isString(clearDataAttrValue) && container.setAttribute('clear-data', clearDataAttrValue);
|
|
6199
7658
|
}
|
|
6200
7659
|
else {
|
|
6201
|
-
let clearDataAttrValue;
|
|
7660
|
+
let clearDataAttrValue = null;
|
|
6202
7661
|
if (options === null || options === void 0 ? void 0 : options.clearData) {
|
|
6203
7662
|
clearDataAttrValue = container.getAttribute('clear-data');
|
|
6204
7663
|
container.setAttribute('clear-data', 'true');
|
|
@@ -6321,10 +7780,10 @@ class MicroApp extends EventCenterForBaseApp {
|
|
|
6321
7780
|
return logError(`${options.tagName} is invalid tagName`);
|
|
6322
7781
|
}
|
|
6323
7782
|
}
|
|
6324
|
-
|
|
7783
|
+
initGlobalEnv();
|
|
7784
|
+
if (globalEnv.rawWindow.customElements.get(this.tagName)) {
|
|
6325
7785
|
return logWarn(`element ${this.tagName} is already defined`);
|
|
6326
7786
|
}
|
|
6327
|
-
initGlobalEnv();
|
|
6328
7787
|
if (isPlainObject(options)) {
|
|
6329
7788
|
this.options = options;
|
|
6330
7789
|
options['disable-scopecss'] = (_a = options['disable-scopecss']) !== null && _a !== void 0 ? _a : options.disableScopecss;
|