@micro-zoe/micro-app 0.6.0 → 0.7.1
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.zh-cn.md +2 -2
- package/lib/index.d.ts +39 -86
- package/lib/index.esm.js +836 -650
- package/lib/index.esm.js.map +1 -1
- package/lib/index.min.js +1 -1
- package/lib/index.min.js.map +1 -1
- package/lib/index.umd.js +1 -1
- package/lib/index.umd.js.map +1 -1
- package/package.json +1 -1
- package/polyfill/jsx-custom-event.js.map +1 -1
- package/typings/global.d.ts +3 -7
package/lib/index.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const version = '0.
|
|
1
|
+
const version = '0.7.1';
|
|
2
2
|
// do not use isUndefined
|
|
3
3
|
const isBrowser = typeof window !== 'undefined';
|
|
4
4
|
// do not use isUndefined
|
|
@@ -41,6 +41,9 @@ function isBoundFunction(target) {
|
|
|
41
41
|
function isShadowRoot(target) {
|
|
42
42
|
return typeof ShadowRoot !== 'undefined' && target instanceof ShadowRoot;
|
|
43
43
|
}
|
|
44
|
+
const rawDefineProperty = Object.defineProperty;
|
|
45
|
+
const rawDefineProperties = Object.defineProperties;
|
|
46
|
+
const rawHasOwnProperty = Object.prototype.hasOwnProperty;
|
|
44
47
|
/**
|
|
45
48
|
* format error log
|
|
46
49
|
* @param msg message
|
|
@@ -230,6 +233,17 @@ let currentMicroAppName = null;
|
|
|
230
233
|
function setCurrentAppName(appName) {
|
|
231
234
|
currentMicroAppName = appName;
|
|
232
235
|
}
|
|
236
|
+
let isWaitingForReset = false;
|
|
237
|
+
function throttleDeferForSetAppName(appName) {
|
|
238
|
+
if (!isWaitingForReset || currentMicroAppName !== appName) {
|
|
239
|
+
isWaitingForReset = true;
|
|
240
|
+
setCurrentAppName(appName);
|
|
241
|
+
defer(() => {
|
|
242
|
+
isWaitingForReset = false;
|
|
243
|
+
setCurrentAppName(null);
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
}
|
|
233
247
|
// get the currently running app.name
|
|
234
248
|
function getCurrentAppName() {
|
|
235
249
|
return currentMicroAppName;
|
|
@@ -326,6 +340,7 @@ var keepAliveStates;
|
|
|
326
340
|
keepAliveStates["KEEP_ALIVE_SHOW"] = "KEEP_ALIVE_SHOW";
|
|
327
341
|
keepAliveStates["KEEP_ALIVE_HIDDEN"] = "KEEP_ALIVE_HIDDEN";
|
|
328
342
|
})(keepAliveStates || (keepAliveStates = {}));
|
|
343
|
+
const globalKeyToBeCached = 'window,self,globalThis,Array,Object,String,Boolean,Math,Number,Symbol,Date,Promise,Function,Proxy,WeakMap,WeakSet,Set,Map,Reflect,Element,Node,Document,RegExp,Error,TypeError,JSON,isNaN,parseFloat,parseInt,performance,console,decodeURI,encodeURI,decodeURIComponent,encodeURIComponent,location,navigator,undefined';
|
|
329
344
|
|
|
330
345
|
/**
|
|
331
346
|
* fetch source of html, js, css
|
|
@@ -343,6 +358,10 @@ function fetchSource(url, appName = null, options = {}) {
|
|
|
343
358
|
}
|
|
344
359
|
|
|
345
360
|
const globalEnv = {};
|
|
361
|
+
/**
|
|
362
|
+
* Note loop nesting
|
|
363
|
+
* Only prototype or unique values can be put here
|
|
364
|
+
*/
|
|
346
365
|
function initGlobalEnv() {
|
|
347
366
|
if (isBrowser) {
|
|
348
367
|
/**
|
|
@@ -350,12 +369,13 @@ function initGlobalEnv() {
|
|
|
350
369
|
* pay attention to this binding
|
|
351
370
|
*/
|
|
352
371
|
const rawSetAttribute = Element.prototype.setAttribute;
|
|
353
|
-
const rawAppendChild =
|
|
354
|
-
const rawInsertBefore =
|
|
355
|
-
const rawReplaceChild =
|
|
356
|
-
const rawRemoveChild =
|
|
372
|
+
const rawAppendChild = Element.prototype.appendChild;
|
|
373
|
+
const rawInsertBefore = Element.prototype.insertBefore;
|
|
374
|
+
const rawReplaceChild = Element.prototype.replaceChild;
|
|
375
|
+
const rawRemoveChild = Element.prototype.removeChild;
|
|
357
376
|
const rawAppend = Element.prototype.append;
|
|
358
377
|
const rawPrepend = Element.prototype.prepend;
|
|
378
|
+
const rawCloneNode = Element.prototype.cloneNode;
|
|
359
379
|
const rawCreateElement = Document.prototype.createElement;
|
|
360
380
|
const rawCreateElementNS = Document.prototype.createElementNS;
|
|
361
381
|
const rawCreateDocumentFragment = Document.prototype.createDocumentFragment;
|
|
@@ -365,6 +385,13 @@ function initGlobalEnv() {
|
|
|
365
385
|
const rawGetElementsByClassName = Document.prototype.getElementsByClassName;
|
|
366
386
|
const rawGetElementsByTagName = Document.prototype.getElementsByTagName;
|
|
367
387
|
const rawGetElementsByName = Document.prototype.getElementsByName;
|
|
388
|
+
const ImageProxy = new Proxy(Image, {
|
|
389
|
+
construct(Target, args) {
|
|
390
|
+
const elementImage = new Target(...args);
|
|
391
|
+
elementImage.__MICRO_APP_NAME__ = getCurrentAppName();
|
|
392
|
+
return elementImage;
|
|
393
|
+
},
|
|
394
|
+
});
|
|
368
395
|
const rawWindow = Function('return window')();
|
|
369
396
|
const rawDocument = Function('return document')();
|
|
370
397
|
const supportModuleScript = isSupportModuleScript();
|
|
@@ -392,6 +419,7 @@ function initGlobalEnv() {
|
|
|
392
419
|
rawRemoveChild,
|
|
393
420
|
rawAppend,
|
|
394
421
|
rawPrepend,
|
|
422
|
+
rawCloneNode,
|
|
395
423
|
rawCreateElement,
|
|
396
424
|
rawCreateElementNS,
|
|
397
425
|
rawCreateDocumentFragment,
|
|
@@ -401,6 +429,7 @@ function initGlobalEnv() {
|
|
|
401
429
|
rawGetElementsByClassName,
|
|
402
430
|
rawGetElementsByTagName,
|
|
403
431
|
rawGetElementsByName,
|
|
432
|
+
ImageProxy,
|
|
404
433
|
// common global vars
|
|
405
434
|
rawWindow,
|
|
406
435
|
rawDocument,
|
|
@@ -419,13 +448,6 @@ function initGlobalEnv() {
|
|
|
419
448
|
}
|
|
420
449
|
}
|
|
421
450
|
|
|
422
|
-
// https://developer.mozilla.org/zh-CN/docs/Web/API/CSSRule
|
|
423
|
-
var CSSRuleType;
|
|
424
|
-
(function (CSSRuleType) {
|
|
425
|
-
CSSRuleType[CSSRuleType["STYLE_RULE"] = 1] = "STYLE_RULE";
|
|
426
|
-
CSSRuleType[CSSRuleType["MEDIA_RULE"] = 4] = "MEDIA_RULE";
|
|
427
|
-
CSSRuleType[CSSRuleType["SUPPORTS_RULE"] = 12] = "SUPPORTS_RULE";
|
|
428
|
-
})(CSSRuleType || (CSSRuleType = {}));
|
|
429
451
|
/**
|
|
430
452
|
* Bind css scope
|
|
431
453
|
* Special case:
|
|
@@ -469,7 +491,7 @@ function scopedStyleRule(rule, prefix) {
|
|
|
469
491
|
*/
|
|
470
492
|
function scopedHost(cssText, baseURI, textContent, linkpath) {
|
|
471
493
|
return cssText.replace(/url\(["']?([^)"']+)["']?\)/gm, (all, $1) => {
|
|
472
|
-
if (/^(data|blob)
|
|
494
|
+
if (/^((data|blob):|#)/.test($1)) {
|
|
473
495
|
return all;
|
|
474
496
|
}
|
|
475
497
|
else if (/^(https?:)?\/\//.test($1)) {
|
|
@@ -506,14 +528,15 @@ function scopedPackRule(rule, prefix, packName) {
|
|
|
506
528
|
function scopedRule(rules, prefix) {
|
|
507
529
|
let result = '';
|
|
508
530
|
for (const rule of rules) {
|
|
509
|
-
|
|
510
|
-
|
|
531
|
+
// https://developer.mozilla.org/zh-CN/docs/Web/API/CSSRule
|
|
532
|
+
switch (rule.constructor.name) {
|
|
533
|
+
case 'CSSStyleRule':
|
|
511
534
|
result += scopedStyleRule(rule, prefix);
|
|
512
535
|
break;
|
|
513
|
-
case
|
|
536
|
+
case 'CSSMediaRule':
|
|
514
537
|
result += scopedPackRule(rule, prefix, 'media');
|
|
515
538
|
break;
|
|
516
|
-
case
|
|
539
|
+
case 'CSSSupportsRule':
|
|
517
540
|
result += scopedPackRule(rule, prefix, 'supports');
|
|
518
541
|
break;
|
|
519
542
|
default:
|
|
@@ -716,7 +739,12 @@ function fetchLinkSuccess(url, info, data, microAppHead, app) {
|
|
|
716
739
|
styleLink.textContent = data;
|
|
717
740
|
styleLink.__MICRO_APP_LINK_PATH__ = url;
|
|
718
741
|
styleLink.setAttribute('data-origin-href', url);
|
|
719
|
-
|
|
742
|
+
if (info.placeholder.parentNode) {
|
|
743
|
+
info.placeholder.parentNode.replaceChild(scopedCSS(styleLink, app), info.placeholder);
|
|
744
|
+
}
|
|
745
|
+
else {
|
|
746
|
+
microAppHead.appendChild(scopedCSS(styleLink, app));
|
|
747
|
+
}
|
|
720
748
|
info.placeholder = null;
|
|
721
749
|
info.code = data;
|
|
722
750
|
}
|
|
@@ -907,17 +935,21 @@ function execScripts(scriptList, app, initedHook) {
|
|
|
907
935
|
}
|
|
908
936
|
}
|
|
909
937
|
if (deferScriptPromise.length) {
|
|
910
|
-
|
|
911
|
-
res.
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
!info.module && initedHook(false);
|
|
916
|
-
});
|
|
917
|
-
initedHook(isUndefined(initedHook.moduleCount));
|
|
918
|
-
}).catch((err) => {
|
|
938
|
+
promiseStream(deferScriptPromise, (res) => {
|
|
939
|
+
const info = deferScriptInfo[res.index][1];
|
|
940
|
+
info.code = info.code || res.data;
|
|
941
|
+
}, (err) => {
|
|
942
|
+
initedHook.errorCount = initedHook.errorCount ? ++initedHook.errorCount : 1;
|
|
919
943
|
logError(err, app.name);
|
|
920
|
-
|
|
944
|
+
}, () => {
|
|
945
|
+
deferScriptInfo.forEach(([url, info]) => {
|
|
946
|
+
if (info.code) {
|
|
947
|
+
runScript(url, app, info, false, initedHook);
|
|
948
|
+
!info.module && initedHook(false);
|
|
949
|
+
}
|
|
950
|
+
});
|
|
951
|
+
initedHook(isUndefined(initedHook.moduleCount) ||
|
|
952
|
+
initedHook.errorCount === deferScriptPromise.length);
|
|
921
953
|
});
|
|
922
954
|
}
|
|
923
955
|
else {
|
|
@@ -1052,7 +1084,7 @@ function bindScope(url, app, code, module) {
|
|
|
1052
1084
|
}
|
|
1053
1085
|
if (app.sandBox && !module) {
|
|
1054
1086
|
globalEnv.rawWindow.__MICRO_APP_PROXY_WINDOW__ = app.sandBox.proxyWindow;
|
|
1055
|
-
return `;(function(
|
|
1087
|
+
return `;(function(proxyWindow){with(proxyWindow.__MICRO_APP_WINDOW__){(function(${globalKeyToBeCached}){;${code}\n}).call(proxyWindow,${globalKeyToBeCached})}})(window.__MICRO_APP_PROXY_WINDOW__);`;
|
|
1056
1088
|
}
|
|
1057
1089
|
return code;
|
|
1058
1090
|
}
|
|
@@ -1190,416 +1222,115 @@ function extractHtml(app) {
|
|
|
1190
1222
|
});
|
|
1191
1223
|
}
|
|
1192
1224
|
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
return boundedMap.get(value);
|
|
1197
|
-
}
|
|
1198
|
-
// bind function
|
|
1199
|
-
const boundFunction = isBoundFunction(value);
|
|
1200
|
-
boundedMap.set(value, boundFunction);
|
|
1201
|
-
return boundFunction;
|
|
1202
|
-
}
|
|
1203
|
-
const constructorMap = new WeakMap();
|
|
1204
|
-
function isConstructor(value) {
|
|
1205
|
-
if (constructorMap.has(value)) {
|
|
1206
|
-
return constructorMap.get(value);
|
|
1207
|
-
}
|
|
1208
|
-
const valueStr = value.toString();
|
|
1209
|
-
const result = (value.prototype &&
|
|
1210
|
-
value.prototype.constructor === value &&
|
|
1211
|
-
Object.getOwnPropertyNames(value.prototype).length > 1) ||
|
|
1212
|
-
/^function\s+[A-Z]/.test(valueStr) ||
|
|
1213
|
-
/^class\s+/.test(valueStr);
|
|
1214
|
-
constructorMap.set(value, result);
|
|
1215
|
-
return result;
|
|
1216
|
-
}
|
|
1217
|
-
const rawWindowMethodMap = new WeakMap();
|
|
1218
|
-
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
1219
|
-
function bindFunctionToRawWidow(rawWindow, value) {
|
|
1220
|
-
if (rawWindowMethodMap.has(value)) {
|
|
1221
|
-
return rawWindowMethodMap.get(value);
|
|
1225
|
+
class EventCenter {
|
|
1226
|
+
constructor() {
|
|
1227
|
+
this.eventList = new Map();
|
|
1222
1228
|
}
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
if (value.hasOwnProperty('prototype') && !bindRawWindowValue.hasOwnProperty('prototype')) {
|
|
1229
|
-
bindRawWindowValue.prototype = value.prototype;
|
|
1229
|
+
// whether the name is legal
|
|
1230
|
+
isLegalName(name) {
|
|
1231
|
+
if (!name) {
|
|
1232
|
+
logError('event-center: Invalid name');
|
|
1233
|
+
return false;
|
|
1230
1234
|
}
|
|
1231
|
-
|
|
1232
|
-
return bindRawWindowValue;
|
|
1233
|
-
}
|
|
1234
|
-
return value;
|
|
1235
|
-
}
|
|
1236
|
-
|
|
1237
|
-
// document.onclick binding list, the binding function of each application is unique
|
|
1238
|
-
const documentClickListMap = new Map();
|
|
1239
|
-
let hasRewriteDocumentOnClick = false;
|
|
1240
|
-
/**
|
|
1241
|
-
* Rewrite document.onclick and execute it only once
|
|
1242
|
-
*/
|
|
1243
|
-
function overwriteDocumentOnClick() {
|
|
1244
|
-
hasRewriteDocumentOnClick = true;
|
|
1245
|
-
if (Object.getOwnPropertyDescriptor(document, 'onclick')) {
|
|
1246
|
-
return logWarn('Cannot redefine document property onclick');
|
|
1247
|
-
}
|
|
1248
|
-
const rawOnClick = document.onclick;
|
|
1249
|
-
document.onclick = null;
|
|
1250
|
-
let hasDocumentClickInited = false;
|
|
1251
|
-
function onClickHandler(e) {
|
|
1252
|
-
documentClickListMap.forEach((f) => {
|
|
1253
|
-
isFunction(f) && f.call(document, e);
|
|
1254
|
-
});
|
|
1235
|
+
return true;
|
|
1255
1236
|
}
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
documentClickListMap.set(appName, f);
|
|
1237
|
+
/**
|
|
1238
|
+
* add listener
|
|
1239
|
+
* @param name event name
|
|
1240
|
+
* @param f listener
|
|
1241
|
+
* @param autoTrigger If there is cached data when first bind listener, whether it needs to trigger, default is false
|
|
1242
|
+
*/
|
|
1243
|
+
on(name, f, autoTrigger = false) {
|
|
1244
|
+
if (this.isLegalName(name)) {
|
|
1245
|
+
if (!isFunction(f)) {
|
|
1246
|
+
return logError('event-center: Invalid callback function');
|
|
1267
1247
|
}
|
|
1268
|
-
|
|
1269
|
-
|
|
1248
|
+
let eventInfo = this.eventList.get(name);
|
|
1249
|
+
if (!eventInfo) {
|
|
1250
|
+
eventInfo = {
|
|
1251
|
+
data: {},
|
|
1252
|
+
callbacks: new Set(),
|
|
1253
|
+
};
|
|
1254
|
+
this.eventList.set(name, eventInfo);
|
|
1270
1255
|
}
|
|
1271
|
-
if (
|
|
1272
|
-
|
|
1273
|
-
|
|
1256
|
+
else if (autoTrigger && Object.getOwnPropertyNames(eventInfo.data).length) {
|
|
1257
|
+
// auto trigger when data not null
|
|
1258
|
+
f(eventInfo.data);
|
|
1274
1259
|
}
|
|
1260
|
+
eventInfo.callbacks.add(f);
|
|
1275
1261
|
}
|
|
1276
|
-
}
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
const { rawDocument, rawDocumentAddEventListener, rawDocumentRemoveEventListener, } = globalEnv;
|
|
1285
|
-
!hasRewriteDocumentOnClick && overwriteDocumentOnClick();
|
|
1286
|
-
document.addEventListener = function (type, listener, options) {
|
|
1287
|
-
var _a;
|
|
1288
|
-
const appName = getCurrentAppName();
|
|
1289
|
-
/**
|
|
1290
|
-
* ignore bound function of document event in umd mode, used to solve problem of react global events
|
|
1291
|
-
*/
|
|
1292
|
-
if (appName && !(((_a = appInstanceMap.get(appName)) === null || _a === void 0 ? void 0 : _a.umdMode) && isBoundFunction(listener))) {
|
|
1293
|
-
const appListenersMap = documentEventListenerMap.get(appName);
|
|
1294
|
-
if (appListenersMap) {
|
|
1295
|
-
const appListenerList = appListenersMap.get(type);
|
|
1296
|
-
if (appListenerList) {
|
|
1297
|
-
appListenerList.add(listener);
|
|
1262
|
+
}
|
|
1263
|
+
// remove listener, but the data is not cleared
|
|
1264
|
+
off(name, f) {
|
|
1265
|
+
if (this.isLegalName(name)) {
|
|
1266
|
+
const eventInfo = this.eventList.get(name);
|
|
1267
|
+
if (eventInfo) {
|
|
1268
|
+
if (isFunction(f)) {
|
|
1269
|
+
eventInfo.callbacks.delete(f);
|
|
1298
1270
|
}
|
|
1299
1271
|
else {
|
|
1300
|
-
|
|
1272
|
+
eventInfo.callbacks.clear();
|
|
1301
1273
|
}
|
|
1302
1274
|
}
|
|
1303
|
-
else {
|
|
1304
|
-
documentEventListenerMap.set(appName, new Map([[type, new Set([listener])]]));
|
|
1305
|
-
}
|
|
1306
|
-
listener && (listener.__MICRO_MARK_OPTIONS__ = options);
|
|
1307
1275
|
}
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1276
|
+
}
|
|
1277
|
+
// dispatch data
|
|
1278
|
+
dispatch(name, data) {
|
|
1279
|
+
if (this.isLegalName(name)) {
|
|
1280
|
+
if (!isPlainObject(data)) {
|
|
1281
|
+
return logError('event-center: data must be object');
|
|
1282
|
+
}
|
|
1283
|
+
let eventInfo = this.eventList.get(name);
|
|
1284
|
+
if (eventInfo) {
|
|
1285
|
+
// Update when the data is not equal
|
|
1286
|
+
if (eventInfo.data !== data) {
|
|
1287
|
+
eventInfo.data = data;
|
|
1288
|
+
for (const f of eventInfo.callbacks) {
|
|
1289
|
+
f(data);
|
|
1290
|
+
}
|
|
1319
1291
|
}
|
|
1320
1292
|
}
|
|
1293
|
+
else {
|
|
1294
|
+
eventInfo = {
|
|
1295
|
+
data: data,
|
|
1296
|
+
callbacks: new Set(),
|
|
1297
|
+
};
|
|
1298
|
+
this.eventList.set(name, eventInfo);
|
|
1299
|
+
}
|
|
1321
1300
|
}
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1301
|
+
}
|
|
1302
|
+
// get data
|
|
1303
|
+
getData(name) {
|
|
1304
|
+
var _a;
|
|
1305
|
+
const eventInfo = this.eventList.get(name);
|
|
1306
|
+
return (_a = eventInfo === null || eventInfo === void 0 ? void 0 : eventInfo.data) !== null && _a !== void 0 ? _a : null;
|
|
1307
|
+
}
|
|
1329
1308
|
}
|
|
1330
|
-
|
|
1331
|
-
const
|
|
1309
|
+
|
|
1310
|
+
const eventCenter = new EventCenter();
|
|
1332
1311
|
/**
|
|
1333
1312
|
* Format event name
|
|
1334
|
-
* @param
|
|
1335
|
-
* @param
|
|
1313
|
+
* @param appName app.name
|
|
1314
|
+
* @param fromBaseApp is from base app
|
|
1336
1315
|
*/
|
|
1337
|
-
function
|
|
1338
|
-
if (
|
|
1339
|
-
return
|
|
1340
|
-
}
|
|
1341
|
-
return type;
|
|
1316
|
+
function formatEventName(appName, fromBaseApp) {
|
|
1317
|
+
if (!isString(appName) || !appName)
|
|
1318
|
+
return '';
|
|
1319
|
+
return fromBaseApp ? `__from_base_app_${appName}__` : `__from_micro_app_${appName}__`;
|
|
1342
1320
|
}
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
const listenerList = eventListenerMap.get(type);
|
|
1357
|
-
if (listenerList) {
|
|
1358
|
-
listenerList.add(listener);
|
|
1359
|
-
}
|
|
1360
|
-
else {
|
|
1361
|
-
eventListenerMap.set(type, new Set([listener]));
|
|
1362
|
-
}
|
|
1363
|
-
listener && (listener.__MICRO_MARK_OPTIONS__ = options);
|
|
1364
|
-
rawWindowAddEventListener.call(rawWindow, type, listener, options);
|
|
1365
|
-
};
|
|
1366
|
-
microWindow.removeEventListener = function (type, listener, options) {
|
|
1367
|
-
type = formatEventType(type, microWindow);
|
|
1368
|
-
const listenerList = eventListenerMap.get(type);
|
|
1369
|
-
if ((listenerList === null || listenerList === void 0 ? void 0 : listenerList.size) && listenerList.has(listener)) {
|
|
1370
|
-
listenerList.delete(listener);
|
|
1371
|
-
}
|
|
1372
|
-
rawWindowRemoveEventListener.call(rawWindow, type, listener, options);
|
|
1373
|
-
};
|
|
1374
|
-
microWindow.setInterval = function (handler, timeout, ...args) {
|
|
1375
|
-
const intervalId = rawSetInterval.call(rawWindow, handler, timeout, ...args);
|
|
1376
|
-
intervalIdMap.set(intervalId, { handler, timeout, args });
|
|
1377
|
-
return intervalId;
|
|
1378
|
-
};
|
|
1379
|
-
microWindow.setTimeout = function (handler, timeout, ...args) {
|
|
1380
|
-
const timeoutId = rawSetTimeout.call(rawWindow, handler, timeout, ...args);
|
|
1381
|
-
timeoutIdMap.set(timeoutId, { handler, timeout, args });
|
|
1382
|
-
return timeoutId;
|
|
1383
|
-
};
|
|
1384
|
-
microWindow.clearInterval = function (intervalId) {
|
|
1385
|
-
intervalIdMap.delete(intervalId);
|
|
1386
|
-
rawClearInterval.call(rawWindow, intervalId);
|
|
1387
|
-
};
|
|
1388
|
-
microWindow.clearTimeout = function (timeoutId) {
|
|
1389
|
-
timeoutIdMap.delete(timeoutId);
|
|
1390
|
-
rawClearTimeout.call(rawWindow, timeoutId);
|
|
1391
|
-
};
|
|
1392
|
-
const umdWindowListenerMap = new Map();
|
|
1393
|
-
const umdDocumentListenerMap = new Map();
|
|
1394
|
-
let umdIntervalIdMap = new Map();
|
|
1395
|
-
let umdTimeoutIdMap = new Map();
|
|
1396
|
-
let umdOnClickHandler;
|
|
1397
|
-
// record event and timer before exec umdMountHook
|
|
1398
|
-
const recordUmdEffect = () => {
|
|
1399
|
-
// record window event
|
|
1400
|
-
eventListenerMap.forEach((listenerList, type) => {
|
|
1401
|
-
if (listenerList.size) {
|
|
1402
|
-
umdWindowListenerMap.set(type, new Set(listenerList));
|
|
1403
|
-
}
|
|
1404
|
-
});
|
|
1405
|
-
// record timers
|
|
1406
|
-
if (intervalIdMap.size) {
|
|
1407
|
-
umdIntervalIdMap = new Map(intervalIdMap);
|
|
1408
|
-
}
|
|
1409
|
-
if (timeoutIdMap.size) {
|
|
1410
|
-
umdTimeoutIdMap = new Map(timeoutIdMap);
|
|
1411
|
-
}
|
|
1412
|
-
// record onclick handler
|
|
1413
|
-
umdOnClickHandler = documentClickListMap.get(appName);
|
|
1414
|
-
// record document event
|
|
1415
|
-
const documentAppListenersMap = documentEventListenerMap.get(appName);
|
|
1416
|
-
if (documentAppListenersMap) {
|
|
1417
|
-
documentAppListenersMap.forEach((listenerList, type) => {
|
|
1418
|
-
if (listenerList.size) {
|
|
1419
|
-
umdDocumentListenerMap.set(type, new Set(listenerList));
|
|
1420
|
-
}
|
|
1421
|
-
});
|
|
1422
|
-
}
|
|
1423
|
-
};
|
|
1424
|
-
// rebuild event and timer before remount umd app
|
|
1425
|
-
const rebuildUmdEffect = () => {
|
|
1426
|
-
// rebuild window event
|
|
1427
|
-
umdWindowListenerMap.forEach((listenerList, type) => {
|
|
1428
|
-
for (const listener of listenerList) {
|
|
1429
|
-
microWindow.addEventListener(type, listener, listener === null || listener === void 0 ? void 0 : listener.__MICRO_MARK_OPTIONS__);
|
|
1430
|
-
}
|
|
1431
|
-
});
|
|
1432
|
-
// rebuild timer
|
|
1433
|
-
umdIntervalIdMap.forEach((info) => {
|
|
1434
|
-
microWindow.setInterval(info.handler, info.timeout, ...info.args);
|
|
1435
|
-
});
|
|
1436
|
-
umdTimeoutIdMap.forEach((info) => {
|
|
1437
|
-
microWindow.setTimeout(info.handler, info.timeout, ...info.args);
|
|
1438
|
-
});
|
|
1439
|
-
// rebuild onclick event
|
|
1440
|
-
umdOnClickHandler && documentClickListMap.set(appName, umdOnClickHandler);
|
|
1441
|
-
// rebuild document event
|
|
1442
|
-
setCurrentAppName(appName);
|
|
1443
|
-
umdDocumentListenerMap.forEach((listenerList, type) => {
|
|
1444
|
-
for (const listener of listenerList) {
|
|
1445
|
-
document.addEventListener(type, listener, listener === null || listener === void 0 ? void 0 : listener.__MICRO_MARK_OPTIONS__);
|
|
1446
|
-
}
|
|
1447
|
-
});
|
|
1448
|
-
setCurrentAppName(null);
|
|
1449
|
-
};
|
|
1450
|
-
// release all event listener & interval & timeout when unmount app
|
|
1451
|
-
const releaseEffect = () => {
|
|
1452
|
-
// Clear window binding events
|
|
1453
|
-
if (eventListenerMap.size) {
|
|
1454
|
-
eventListenerMap.forEach((listenerList, type) => {
|
|
1455
|
-
for (const listener of listenerList) {
|
|
1456
|
-
rawWindowRemoveEventListener.call(rawWindow, type, listener);
|
|
1457
|
-
}
|
|
1458
|
-
});
|
|
1459
|
-
eventListenerMap.clear();
|
|
1460
|
-
}
|
|
1461
|
-
// Clear timers
|
|
1462
|
-
if (intervalIdMap.size) {
|
|
1463
|
-
intervalIdMap.forEach((_, intervalId) => {
|
|
1464
|
-
rawClearInterval.call(rawWindow, intervalId);
|
|
1465
|
-
});
|
|
1466
|
-
intervalIdMap.clear();
|
|
1467
|
-
}
|
|
1468
|
-
if (timeoutIdMap.size) {
|
|
1469
|
-
timeoutIdMap.forEach((_, timeoutId) => {
|
|
1470
|
-
rawClearTimeout.call(rawWindow, timeoutId);
|
|
1471
|
-
});
|
|
1472
|
-
timeoutIdMap.clear();
|
|
1473
|
-
}
|
|
1474
|
-
// Clear the function bound by micro application through document.onclick
|
|
1475
|
-
documentClickListMap.delete(appName);
|
|
1476
|
-
// Clear document binding event
|
|
1477
|
-
const documentAppListenersMap = documentEventListenerMap.get(appName);
|
|
1478
|
-
if (documentAppListenersMap) {
|
|
1479
|
-
documentAppListenersMap.forEach((listenerList, type) => {
|
|
1480
|
-
for (const listener of listenerList) {
|
|
1481
|
-
rawDocumentRemoveEventListener.call(rawDocument, type, listener);
|
|
1482
|
-
}
|
|
1483
|
-
});
|
|
1484
|
-
documentAppListenersMap.clear();
|
|
1485
|
-
}
|
|
1486
|
-
};
|
|
1487
|
-
return {
|
|
1488
|
-
recordUmdEffect,
|
|
1489
|
-
rebuildUmdEffect,
|
|
1490
|
-
releaseEffect,
|
|
1491
|
-
};
|
|
1492
|
-
}
|
|
1493
|
-
|
|
1494
|
-
class EventCenter {
|
|
1495
|
-
constructor() {
|
|
1496
|
-
this.eventList = new Map();
|
|
1497
|
-
}
|
|
1498
|
-
// whether the name is legal
|
|
1499
|
-
isLegalName(name) {
|
|
1500
|
-
if (!name) {
|
|
1501
|
-
logError('event-center: Invalid name');
|
|
1502
|
-
return false;
|
|
1503
|
-
}
|
|
1504
|
-
return true;
|
|
1505
|
-
}
|
|
1506
|
-
/**
|
|
1507
|
-
* add listener
|
|
1508
|
-
* @param name event name
|
|
1509
|
-
* @param f listener
|
|
1510
|
-
* @param autoTrigger If there is cached data when first bind listener, whether it needs to trigger, default is false
|
|
1511
|
-
*/
|
|
1512
|
-
on(name, f, autoTrigger = false) {
|
|
1513
|
-
if (this.isLegalName(name)) {
|
|
1514
|
-
if (!isFunction(f)) {
|
|
1515
|
-
return logError('event-center: Invalid callback function');
|
|
1516
|
-
}
|
|
1517
|
-
let eventInfo = this.eventList.get(name);
|
|
1518
|
-
if (!eventInfo) {
|
|
1519
|
-
eventInfo = {
|
|
1520
|
-
data: {},
|
|
1521
|
-
callbacks: new Set(),
|
|
1522
|
-
};
|
|
1523
|
-
this.eventList.set(name, eventInfo);
|
|
1524
|
-
}
|
|
1525
|
-
else if (autoTrigger && Object.getOwnPropertyNames(eventInfo.data).length) {
|
|
1526
|
-
// auto trigger when data not null
|
|
1527
|
-
f(eventInfo.data);
|
|
1528
|
-
}
|
|
1529
|
-
eventInfo.callbacks.add(f);
|
|
1530
|
-
}
|
|
1531
|
-
}
|
|
1532
|
-
// remove listener, but the data is not cleared
|
|
1533
|
-
off(name, f) {
|
|
1534
|
-
if (this.isLegalName(name)) {
|
|
1535
|
-
const eventInfo = this.eventList.get(name);
|
|
1536
|
-
if (eventInfo) {
|
|
1537
|
-
if (isFunction(f)) {
|
|
1538
|
-
eventInfo.callbacks.delete(f);
|
|
1539
|
-
}
|
|
1540
|
-
else {
|
|
1541
|
-
eventInfo.callbacks.clear();
|
|
1542
|
-
}
|
|
1543
|
-
}
|
|
1544
|
-
}
|
|
1545
|
-
}
|
|
1546
|
-
// dispatch data
|
|
1547
|
-
dispatch(name, data) {
|
|
1548
|
-
if (this.isLegalName(name)) {
|
|
1549
|
-
if (!isPlainObject(data)) {
|
|
1550
|
-
return logError('event-center: data must be object');
|
|
1551
|
-
}
|
|
1552
|
-
let eventInfo = this.eventList.get(name);
|
|
1553
|
-
if (eventInfo) {
|
|
1554
|
-
// Update when the data is not equal
|
|
1555
|
-
if (eventInfo.data !== data) {
|
|
1556
|
-
eventInfo.data = data;
|
|
1557
|
-
for (const f of eventInfo.callbacks) {
|
|
1558
|
-
f(data);
|
|
1559
|
-
}
|
|
1560
|
-
}
|
|
1561
|
-
}
|
|
1562
|
-
else {
|
|
1563
|
-
eventInfo = {
|
|
1564
|
-
data: data,
|
|
1565
|
-
callbacks: new Set(),
|
|
1566
|
-
};
|
|
1567
|
-
this.eventList.set(name, eventInfo);
|
|
1568
|
-
}
|
|
1569
|
-
}
|
|
1570
|
-
}
|
|
1571
|
-
// get data
|
|
1572
|
-
getData(name) {
|
|
1573
|
-
var _a;
|
|
1574
|
-
const eventInfo = this.eventList.get(name);
|
|
1575
|
-
return (_a = eventInfo === null || eventInfo === void 0 ? void 0 : eventInfo.data) !== null && _a !== void 0 ? _a : null;
|
|
1576
|
-
}
|
|
1577
|
-
}
|
|
1578
|
-
|
|
1579
|
-
const eventCenter = new EventCenter();
|
|
1580
|
-
/**
|
|
1581
|
-
* Format event name
|
|
1582
|
-
* @param appName app.name
|
|
1583
|
-
* @param fromBaseApp is from base app
|
|
1584
|
-
*/
|
|
1585
|
-
function formatEventName(appName, fromBaseApp) {
|
|
1586
|
-
if (!isString(appName) || !appName)
|
|
1587
|
-
return '';
|
|
1588
|
-
return fromBaseApp ? `__from_base_app_${appName}__` : `__from_micro_app_${appName}__`;
|
|
1589
|
-
}
|
|
1590
|
-
// Global data
|
|
1591
|
-
class EventCenterForGlobal {
|
|
1592
|
-
/**
|
|
1593
|
-
* add listener of global data
|
|
1594
|
-
* @param cb listener
|
|
1595
|
-
* @param autoTrigger If there is cached data when first bind listener, whether it needs to trigger, default is false
|
|
1596
|
-
*/
|
|
1597
|
-
addGlobalDataListener(cb, autoTrigger) {
|
|
1598
|
-
const appName = this.appName;
|
|
1599
|
-
// if appName exists, this is in sub app
|
|
1600
|
-
if (appName) {
|
|
1601
|
-
cb.__APP_NAME__ = appName;
|
|
1602
|
-
cb.__AUTO_TRIGGER__ = autoTrigger;
|
|
1321
|
+
// Global data
|
|
1322
|
+
class EventCenterForGlobal {
|
|
1323
|
+
/**
|
|
1324
|
+
* add listener of global data
|
|
1325
|
+
* @param cb listener
|
|
1326
|
+
* @param autoTrigger If there is cached data when first bind listener, whether it needs to trigger, default is false
|
|
1327
|
+
*/
|
|
1328
|
+
addGlobalDataListener(cb, autoTrigger) {
|
|
1329
|
+
const appName = this.appName;
|
|
1330
|
+
// if appName exists, this is in sub app
|
|
1331
|
+
if (appName) {
|
|
1332
|
+
cb.__APP_NAME__ = appName;
|
|
1333
|
+
cb.__AUTO_TRIGGER__ = autoTrigger;
|
|
1603
1334
|
}
|
|
1604
1335
|
eventCenter.on('global', cb, autoTrigger);
|
|
1605
1336
|
}
|
|
@@ -1753,197 +1484,384 @@ function recordDataCenterSnapshot(microAppEventCneter) {
|
|
|
1753
1484
|
microAppEventCneter.umdDataListeners.global.add(cb);
|
|
1754
1485
|
}
|
|
1755
1486
|
}
|
|
1756
|
-
}
|
|
1757
|
-
const subAppEventInfo = eventCenter.eventList.get(formatEventName(appName, true));
|
|
1758
|
-
if (subAppEventInfo) {
|
|
1759
|
-
microAppEventCneter.umdDataListeners.normal = new Set(subAppEventInfo.callbacks);
|
|
1760
|
-
}
|
|
1761
|
-
}
|
|
1762
|
-
/**
|
|
1763
|
-
* Rebind the UMD function of the record before remount
|
|
1764
|
-
* @param microAppEventCneter instance of EventCenterForMicroApp
|
|
1765
|
-
*/
|
|
1766
|
-
function rebuildDataCenterSnapshot(microAppEventCneter) {
|
|
1767
|
-
for (const cb of microAppEventCneter.umdDataListeners.global) {
|
|
1768
|
-
microAppEventCneter.addGlobalDataListener(cb, cb.__AUTO_TRIGGER__);
|
|
1769
|
-
}
|
|
1770
|
-
for (const cb of microAppEventCneter.umdDataListeners.normal) {
|
|
1771
|
-
microAppEventCneter.addDataListener(cb, cb.__AUTO_TRIGGER__);
|
|
1772
|
-
}
|
|
1487
|
+
}
|
|
1488
|
+
const subAppEventInfo = eventCenter.eventList.get(formatEventName(appName, true));
|
|
1489
|
+
if (subAppEventInfo) {
|
|
1490
|
+
microAppEventCneter.umdDataListeners.normal = new Set(subAppEventInfo.callbacks);
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
/**
|
|
1494
|
+
* Rebind the UMD function of the record before remount
|
|
1495
|
+
* @param microAppEventCneter instance of EventCenterForMicroApp
|
|
1496
|
+
*/
|
|
1497
|
+
function rebuildDataCenterSnapshot(microAppEventCneter) {
|
|
1498
|
+
for (const cb of microAppEventCneter.umdDataListeners.global) {
|
|
1499
|
+
microAppEventCneter.addGlobalDataListener(cb, cb.__AUTO_TRIGGER__);
|
|
1500
|
+
}
|
|
1501
|
+
for (const cb of microAppEventCneter.umdDataListeners.normal) {
|
|
1502
|
+
microAppEventCneter.addDataListener(cb, cb.__AUTO_TRIGGER__);
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1506
|
+
/* eslint-disable no-return-assign */
|
|
1507
|
+
function isBoundedFunction(value) {
|
|
1508
|
+
if (isBoolean(value.__MICRO_APP_ISBOUND_FUNCTION))
|
|
1509
|
+
return value.__MICRO_APP_ISBOUND_FUNCTION;
|
|
1510
|
+
return value.__MICRO_APP_ISBOUND_FUNCTION = isBoundFunction(value);
|
|
1511
|
+
}
|
|
1512
|
+
function isConstructor(value) {
|
|
1513
|
+
var _a;
|
|
1514
|
+
if (isBoolean(value.__MICRO_APP_ISCONSTRUCTOR))
|
|
1515
|
+
return value.__MICRO_APP_ISCONSTRUCTOR;
|
|
1516
|
+
const valueStr = value.toString();
|
|
1517
|
+
const result = (((_a = value.prototype) === null || _a === void 0 ? void 0 : _a.constructor) === value &&
|
|
1518
|
+
Object.getOwnPropertyNames(value.prototype).length > 1) ||
|
|
1519
|
+
/^function\s+[A-Z]/.test(valueStr) ||
|
|
1520
|
+
/^class\s+/.test(valueStr);
|
|
1521
|
+
return value.__MICRO_APP_ISCONSTRUCTOR = result;
|
|
1522
|
+
}
|
|
1523
|
+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
1524
|
+
function bindFunctionToRawWindow(rawWindow, value) {
|
|
1525
|
+
if (value.__MICRO_APP_BOUND_WINDOW_FUNCTION)
|
|
1526
|
+
return value.__MICRO_APP_BOUND_WINDOW_FUNCTION;
|
|
1527
|
+
if (!isConstructor(value) && !isBoundedFunction(value)) {
|
|
1528
|
+
const bindRawWindowValue = value.bind(rawWindow);
|
|
1529
|
+
for (const key in value) {
|
|
1530
|
+
bindRawWindowValue[key] = value[key];
|
|
1531
|
+
}
|
|
1532
|
+
if (value.hasOwnProperty('prototype')) {
|
|
1533
|
+
rawDefineProperty(bindRawWindowValue, 'prototype', {
|
|
1534
|
+
value: value.prototype,
|
|
1535
|
+
configurable: true,
|
|
1536
|
+
enumerable: false,
|
|
1537
|
+
writable: true,
|
|
1538
|
+
});
|
|
1539
|
+
}
|
|
1540
|
+
return value.__MICRO_APP_BOUND_WINDOW_FUNCTION = bindRawWindowValue;
|
|
1541
|
+
}
|
|
1542
|
+
return value;
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
// document.onclick binding list, the binding function of each application is unique
|
|
1546
|
+
const documentClickListMap = new Map();
|
|
1547
|
+
let hasRewriteDocumentOnClick = false;
|
|
1548
|
+
/**
|
|
1549
|
+
* Rewrite document.onclick and execute it only once
|
|
1550
|
+
*/
|
|
1551
|
+
function overwriteDocumentOnClick() {
|
|
1552
|
+
hasRewriteDocumentOnClick = true;
|
|
1553
|
+
if (Object.getOwnPropertyDescriptor(document, 'onclick')) {
|
|
1554
|
+
return logWarn('Cannot redefine document property onclick');
|
|
1555
|
+
}
|
|
1556
|
+
const rawOnClick = document.onclick;
|
|
1557
|
+
document.onclick = null;
|
|
1558
|
+
let hasDocumentClickInited = false;
|
|
1559
|
+
function onClickHandler(e) {
|
|
1560
|
+
documentClickListMap.forEach((f) => {
|
|
1561
|
+
isFunction(f) && f.call(document, e);
|
|
1562
|
+
});
|
|
1563
|
+
}
|
|
1564
|
+
rawDefineProperty(document, 'onclick', {
|
|
1565
|
+
configurable: true,
|
|
1566
|
+
enumerable: true,
|
|
1567
|
+
get() {
|
|
1568
|
+
const appName = getCurrentAppName();
|
|
1569
|
+
return appName ? documentClickListMap.get(appName) : documentClickListMap.get('base');
|
|
1570
|
+
},
|
|
1571
|
+
set(f) {
|
|
1572
|
+
const appName = getCurrentAppName();
|
|
1573
|
+
if (appName) {
|
|
1574
|
+
documentClickListMap.set(appName, f);
|
|
1575
|
+
}
|
|
1576
|
+
else {
|
|
1577
|
+
documentClickListMap.set('base', f);
|
|
1578
|
+
}
|
|
1579
|
+
if (!hasDocumentClickInited && isFunction(f)) {
|
|
1580
|
+
hasDocumentClickInited = true;
|
|
1581
|
+
globalEnv.rawDocumentAddEventListener.call(globalEnv.rawDocument, 'click', onClickHandler, false);
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
});
|
|
1585
|
+
rawOnClick && (document.onclick = rawOnClick);
|
|
1586
|
+
}
|
|
1587
|
+
/**
|
|
1588
|
+
* The document event is globally, we need to clear these event bindings when micro application unmounted
|
|
1589
|
+
*/
|
|
1590
|
+
const documentEventListenerMap = new Map();
|
|
1591
|
+
function effectDocumentEvent() {
|
|
1592
|
+
const { rawDocument, rawDocumentAddEventListener, rawDocumentRemoveEventListener, } = globalEnv;
|
|
1593
|
+
!hasRewriteDocumentOnClick && overwriteDocumentOnClick();
|
|
1594
|
+
document.addEventListener = function (type, listener, options) {
|
|
1595
|
+
var _a;
|
|
1596
|
+
const appName = getCurrentAppName();
|
|
1597
|
+
/**
|
|
1598
|
+
* ignore bound function of document event in umd mode, used to solve problem of react global events
|
|
1599
|
+
*/
|
|
1600
|
+
if (appName && !(((_a = appInstanceMap.get(appName)) === null || _a === void 0 ? void 0 : _a.umdMode) && isBoundFunction(listener))) {
|
|
1601
|
+
const appListenersMap = documentEventListenerMap.get(appName);
|
|
1602
|
+
if (appListenersMap) {
|
|
1603
|
+
const appListenerList = appListenersMap.get(type);
|
|
1604
|
+
if (appListenerList) {
|
|
1605
|
+
appListenerList.add(listener);
|
|
1606
|
+
}
|
|
1607
|
+
else {
|
|
1608
|
+
appListenersMap.set(type, new Set([listener]));
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
else {
|
|
1612
|
+
documentEventListenerMap.set(appName, new Map([[type, new Set([listener])]]));
|
|
1613
|
+
}
|
|
1614
|
+
listener && (listener.__MICRO_APP_MARK_OPTIONS__ = options);
|
|
1615
|
+
}
|
|
1616
|
+
rawDocumentAddEventListener.call(rawDocument, type, listener, options);
|
|
1617
|
+
};
|
|
1618
|
+
document.removeEventListener = function (type, listener, options) {
|
|
1619
|
+
var _a;
|
|
1620
|
+
const appName = getCurrentAppName();
|
|
1621
|
+
if (appName && !(((_a = appInstanceMap.get(appName)) === null || _a === void 0 ? void 0 : _a.umdMode) && isBoundFunction(listener))) {
|
|
1622
|
+
const appListenersMap = documentEventListenerMap.get(appName);
|
|
1623
|
+
if (appListenersMap) {
|
|
1624
|
+
const appListenerList = appListenersMap.get(type);
|
|
1625
|
+
if ((appListenerList === null || appListenerList === void 0 ? void 0 : appListenerList.size) && appListenerList.has(listener)) {
|
|
1626
|
+
appListenerList.delete(listener);
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
}
|
|
1630
|
+
rawDocumentRemoveEventListener.call(rawDocument, type, listener, options);
|
|
1631
|
+
};
|
|
1632
|
+
}
|
|
1633
|
+
// Clear the document event agent
|
|
1634
|
+
function releaseEffectDocumentEvent() {
|
|
1635
|
+
document.addEventListener = globalEnv.rawDocumentAddEventListener;
|
|
1636
|
+
document.removeEventListener = globalEnv.rawDocumentRemoveEventListener;
|
|
1637
|
+
}
|
|
1638
|
+
// this events should be sent to the specified app
|
|
1639
|
+
const formatEventList = ['unmount', 'appstate-change'];
|
|
1640
|
+
/**
|
|
1641
|
+
* Format event name
|
|
1642
|
+
* @param type event name
|
|
1643
|
+
* @param microAppWindow micro window
|
|
1644
|
+
*/
|
|
1645
|
+
function formatEventType(type, microAppWindow) {
|
|
1646
|
+
if (formatEventList.includes(type)) {
|
|
1647
|
+
return `${type}-${microAppWindow.__MICRO_APP_NAME__}`;
|
|
1648
|
+
}
|
|
1649
|
+
return type;
|
|
1650
|
+
}
|
|
1651
|
+
/**
|
|
1652
|
+
* Rewrite side-effect events
|
|
1653
|
+
* @param microAppWindow micro window
|
|
1654
|
+
*/
|
|
1655
|
+
function effect(microAppWindow) {
|
|
1656
|
+
const appName = microAppWindow.__MICRO_APP_NAME__;
|
|
1657
|
+
const eventListenerMap = new Map();
|
|
1658
|
+
const intervalIdMap = new Map();
|
|
1659
|
+
const timeoutIdMap = new Map();
|
|
1660
|
+
const { rawWindow, rawDocument, rawWindowAddEventListener, rawWindowRemoveEventListener, rawSetInterval, rawSetTimeout, rawClearInterval, rawClearTimeout, rawDocumentRemoveEventListener, } = globalEnv;
|
|
1661
|
+
// listener may be null, e.g test-passive
|
|
1662
|
+
microAppWindow.addEventListener = function (type, listener, options) {
|
|
1663
|
+
type = formatEventType(type, microAppWindow);
|
|
1664
|
+
const listenerList = eventListenerMap.get(type);
|
|
1665
|
+
if (listenerList) {
|
|
1666
|
+
listenerList.add(listener);
|
|
1667
|
+
}
|
|
1668
|
+
else {
|
|
1669
|
+
eventListenerMap.set(type, new Set([listener]));
|
|
1670
|
+
}
|
|
1671
|
+
listener && (listener.__MICRO_APP_MARK_OPTIONS__ = options);
|
|
1672
|
+
rawWindowAddEventListener.call(rawWindow, type, listener, options);
|
|
1673
|
+
};
|
|
1674
|
+
microAppWindow.removeEventListener = function (type, listener, options) {
|
|
1675
|
+
type = formatEventType(type, microAppWindow);
|
|
1676
|
+
const listenerList = eventListenerMap.get(type);
|
|
1677
|
+
if ((listenerList === null || listenerList === void 0 ? void 0 : listenerList.size) && listenerList.has(listener)) {
|
|
1678
|
+
listenerList.delete(listener);
|
|
1679
|
+
}
|
|
1680
|
+
rawWindowRemoveEventListener.call(rawWindow, type, listener, options);
|
|
1681
|
+
};
|
|
1682
|
+
microAppWindow.setInterval = function (handler, timeout, ...args) {
|
|
1683
|
+
const intervalId = rawSetInterval.call(rawWindow, handler, timeout, ...args);
|
|
1684
|
+
intervalIdMap.set(intervalId, { handler, timeout, args });
|
|
1685
|
+
return intervalId;
|
|
1686
|
+
};
|
|
1687
|
+
microAppWindow.setTimeout = function (handler, timeout, ...args) {
|
|
1688
|
+
const timeoutId = rawSetTimeout.call(rawWindow, handler, timeout, ...args);
|
|
1689
|
+
timeoutIdMap.set(timeoutId, { handler, timeout, args });
|
|
1690
|
+
return timeoutId;
|
|
1691
|
+
};
|
|
1692
|
+
microAppWindow.clearInterval = function (intervalId) {
|
|
1693
|
+
intervalIdMap.delete(intervalId);
|
|
1694
|
+
rawClearInterval.call(rawWindow, intervalId);
|
|
1695
|
+
};
|
|
1696
|
+
microAppWindow.clearTimeout = function (timeoutId) {
|
|
1697
|
+
timeoutIdMap.delete(timeoutId);
|
|
1698
|
+
rawClearTimeout.call(rawWindow, timeoutId);
|
|
1699
|
+
};
|
|
1700
|
+
const umdWindowListenerMap = new Map();
|
|
1701
|
+
const umdDocumentListenerMap = new Map();
|
|
1702
|
+
let umdIntervalIdMap = new Map();
|
|
1703
|
+
let umdTimeoutIdMap = new Map();
|
|
1704
|
+
let umdOnClickHandler;
|
|
1705
|
+
// record event and timer before exec umdMountHook
|
|
1706
|
+
const recordUmdEffect = () => {
|
|
1707
|
+
// record window event
|
|
1708
|
+
eventListenerMap.forEach((listenerList, type) => {
|
|
1709
|
+
if (listenerList.size) {
|
|
1710
|
+
umdWindowListenerMap.set(type, new Set(listenerList));
|
|
1711
|
+
}
|
|
1712
|
+
});
|
|
1713
|
+
// record timers
|
|
1714
|
+
if (intervalIdMap.size) {
|
|
1715
|
+
umdIntervalIdMap = new Map(intervalIdMap);
|
|
1716
|
+
}
|
|
1717
|
+
if (timeoutIdMap.size) {
|
|
1718
|
+
umdTimeoutIdMap = new Map(timeoutIdMap);
|
|
1719
|
+
}
|
|
1720
|
+
// record onclick handler
|
|
1721
|
+
umdOnClickHandler = documentClickListMap.get(appName);
|
|
1722
|
+
// record document event
|
|
1723
|
+
const documentAppListenersMap = documentEventListenerMap.get(appName);
|
|
1724
|
+
if (documentAppListenersMap) {
|
|
1725
|
+
documentAppListenersMap.forEach((listenerList, type) => {
|
|
1726
|
+
if (listenerList.size) {
|
|
1727
|
+
umdDocumentListenerMap.set(type, new Set(listenerList));
|
|
1728
|
+
}
|
|
1729
|
+
});
|
|
1730
|
+
}
|
|
1731
|
+
};
|
|
1732
|
+
// rebuild event and timer before remount umd app
|
|
1733
|
+
const rebuildUmdEffect = () => {
|
|
1734
|
+
// rebuild window event
|
|
1735
|
+
umdWindowListenerMap.forEach((listenerList, type) => {
|
|
1736
|
+
for (const listener of listenerList) {
|
|
1737
|
+
microAppWindow.addEventListener(type, listener, listener === null || listener === void 0 ? void 0 : listener.__MICRO_APP_MARK_OPTIONS__);
|
|
1738
|
+
}
|
|
1739
|
+
});
|
|
1740
|
+
// rebuild timer
|
|
1741
|
+
umdIntervalIdMap.forEach((info) => {
|
|
1742
|
+
microAppWindow.setInterval(info.handler, info.timeout, ...info.args);
|
|
1743
|
+
});
|
|
1744
|
+
umdTimeoutIdMap.forEach((info) => {
|
|
1745
|
+
microAppWindow.setTimeout(info.handler, info.timeout, ...info.args);
|
|
1746
|
+
});
|
|
1747
|
+
// rebuild onclick event
|
|
1748
|
+
umdOnClickHandler && documentClickListMap.set(appName, umdOnClickHandler);
|
|
1749
|
+
// rebuild document event
|
|
1750
|
+
setCurrentAppName(appName);
|
|
1751
|
+
umdDocumentListenerMap.forEach((listenerList, type) => {
|
|
1752
|
+
for (const listener of listenerList) {
|
|
1753
|
+
document.addEventListener(type, listener, listener === null || listener === void 0 ? void 0 : listener.__MICRO_APP_MARK_OPTIONS__);
|
|
1754
|
+
}
|
|
1755
|
+
});
|
|
1756
|
+
setCurrentAppName(null);
|
|
1757
|
+
};
|
|
1758
|
+
// release all event listener & interval & timeout when unmount app
|
|
1759
|
+
const releaseEffect = () => {
|
|
1760
|
+
// Clear window binding events
|
|
1761
|
+
if (eventListenerMap.size) {
|
|
1762
|
+
eventListenerMap.forEach((listenerList, type) => {
|
|
1763
|
+
for (const listener of listenerList) {
|
|
1764
|
+
rawWindowRemoveEventListener.call(rawWindow, type, listener);
|
|
1765
|
+
}
|
|
1766
|
+
});
|
|
1767
|
+
eventListenerMap.clear();
|
|
1768
|
+
}
|
|
1769
|
+
// Clear timers
|
|
1770
|
+
if (intervalIdMap.size) {
|
|
1771
|
+
intervalIdMap.forEach((_, intervalId) => {
|
|
1772
|
+
rawClearInterval.call(rawWindow, intervalId);
|
|
1773
|
+
});
|
|
1774
|
+
intervalIdMap.clear();
|
|
1775
|
+
}
|
|
1776
|
+
if (timeoutIdMap.size) {
|
|
1777
|
+
timeoutIdMap.forEach((_, timeoutId) => {
|
|
1778
|
+
rawClearTimeout.call(rawWindow, timeoutId);
|
|
1779
|
+
});
|
|
1780
|
+
timeoutIdMap.clear();
|
|
1781
|
+
}
|
|
1782
|
+
// Clear the function bound by micro application through document.onclick
|
|
1783
|
+
documentClickListMap.delete(appName);
|
|
1784
|
+
// Clear document binding event
|
|
1785
|
+
const documentAppListenersMap = documentEventListenerMap.get(appName);
|
|
1786
|
+
if (documentAppListenersMap) {
|
|
1787
|
+
documentAppListenersMap.forEach((listenerList, type) => {
|
|
1788
|
+
for (const listener of listenerList) {
|
|
1789
|
+
rawDocumentRemoveEventListener.call(rawDocument, type, listener);
|
|
1790
|
+
}
|
|
1791
|
+
});
|
|
1792
|
+
documentAppListenersMap.clear();
|
|
1793
|
+
}
|
|
1794
|
+
};
|
|
1795
|
+
return {
|
|
1796
|
+
recordUmdEffect,
|
|
1797
|
+
rebuildUmdEffect,
|
|
1798
|
+
releaseEffect,
|
|
1799
|
+
};
|
|
1773
1800
|
}
|
|
1801
|
+
// window.addEventListener('mousedown', (e: Event) => {
|
|
1802
|
+
// const targetNode = e.target
|
|
1803
|
+
// const activeApps = getActiveApps(true)
|
|
1804
|
+
// let isScopeOfMicroApp = false
|
|
1805
|
+
// for (const appName of activeApps) {
|
|
1806
|
+
// const app = appInstanceMap.get(appName)!
|
|
1807
|
+
// if (targetNode instanceof Node && app.container!.contains(targetNode)) {
|
|
1808
|
+
// isScopeOfMicroApp = true
|
|
1809
|
+
// // console.log(111111, appName)
|
|
1810
|
+
// setCurrentAppName(appName)
|
|
1811
|
+
// break
|
|
1812
|
+
// }
|
|
1813
|
+
// }
|
|
1814
|
+
// if (!isScopeOfMicroApp) {
|
|
1815
|
+
// setCurrentAppName(null)
|
|
1816
|
+
// }
|
|
1817
|
+
// }, false)
|
|
1818
|
+
// let isWaitingForMacroReset = false
|
|
1819
|
+
// window.addEventListener('mouseup', () => {
|
|
1820
|
+
// if (!isWaitingForMacroReset && getCurrentAppName()) {
|
|
1821
|
+
// isWaitingForMacroReset = true
|
|
1822
|
+
// setTimeout(() => {
|
|
1823
|
+
// setCurrentAppName(null)
|
|
1824
|
+
// isWaitingForMacroReset = false
|
|
1825
|
+
// })
|
|
1826
|
+
// }
|
|
1827
|
+
// }, false)
|
|
1774
1828
|
|
|
1775
1829
|
// Variables that can escape to rawWindow
|
|
1776
1830
|
const staticEscapeProperties = [
|
|
1777
1831
|
'System',
|
|
1778
1832
|
'__cjsWrapper',
|
|
1779
|
-
'__REACT_ERROR_OVERLAY_GLOBAL_HOOK__',
|
|
1780
1833
|
];
|
|
1781
1834
|
// Variables that can only assigned to rawWindow
|
|
1782
1835
|
const escapeSetterKeyList = [
|
|
1783
1836
|
'location',
|
|
1784
1837
|
];
|
|
1785
|
-
const
|
|
1786
|
-
undefined: true,
|
|
1787
|
-
Array: true,
|
|
1788
|
-
Object: true,
|
|
1789
|
-
String: true,
|
|
1790
|
-
Boolean: true,
|
|
1791
|
-
Math: true,
|
|
1792
|
-
Number: true,
|
|
1793
|
-
Symbol: true,
|
|
1794
|
-
parseFloat: true,
|
|
1795
|
-
Float32Array: true,
|
|
1796
|
-
};
|
|
1797
|
-
/**
|
|
1798
|
-
* macro task to solve the rendering problem of vue3
|
|
1799
|
-
*/
|
|
1800
|
-
let macroTimer;
|
|
1801
|
-
function macroTask(fn) {
|
|
1802
|
-
macroTimer && clearTimeout(macroTimer);
|
|
1803
|
-
macroTimer = setTimeout(fn, 0);
|
|
1804
|
-
}
|
|
1838
|
+
const globalPropertyList = ['window', 'self', 'globalThis'];
|
|
1805
1839
|
class SandBox {
|
|
1806
|
-
constructor(appName, url
|
|
1807
|
-
// Scoped global Properties(Properties that can only get and set in
|
|
1840
|
+
constructor(appName, url) {
|
|
1841
|
+
// Scoped global Properties(Properties that can only get and set in microAppWindow, will not escape to rawWindow)
|
|
1808
1842
|
this.scopeProperties = ['webpackJsonp'];
|
|
1809
1843
|
// Properties that can be escape to rawWindow
|
|
1810
1844
|
this.escapeProperties = [];
|
|
1811
|
-
// Properties newly added to
|
|
1845
|
+
// Properties newly added to microAppWindow
|
|
1812
1846
|
this.injectedKeys = new Set();
|
|
1813
1847
|
// Properties escape to rawWindow, cleared when unmount
|
|
1814
1848
|
this.escapeKeys = new Set();
|
|
1815
1849
|
// sandbox state
|
|
1816
1850
|
this.active = false;
|
|
1817
|
-
this.
|
|
1818
|
-
const rawWindow = globalEnv.rawWindow;
|
|
1819
|
-
const rawDocument = globalEnv.rawDocument;
|
|
1820
|
-
const descriptorTargetMap = new Map();
|
|
1821
|
-
const hasOwnProperty = (key) => this.microWindow.hasOwnProperty(key) || rawWindow.hasOwnProperty(key);
|
|
1851
|
+
this.microAppWindow = {}; // Proxy target
|
|
1822
1852
|
// get scopeProperties and escapeProperties from plugins
|
|
1823
1853
|
this.getScopeProperties(appName);
|
|
1854
|
+
// create proxyWindow with Proxy(microAppWindow)
|
|
1855
|
+
this.proxyWindow = this.createProxyWindow();
|
|
1824
1856
|
// inject global properties
|
|
1825
|
-
this.
|
|
1857
|
+
this.initMicroAppWindow(this.microAppWindow, appName, url);
|
|
1826
1858
|
// Rewrite global event listener & timeout
|
|
1827
|
-
Object.assign(this, effect(this.
|
|
1828
|
-
this.proxyWindow = new Proxy(this.microWindow, {
|
|
1829
|
-
get: (target, key) => {
|
|
1830
|
-
if (key === Symbol.unscopables)
|
|
1831
|
-
return unscopables;
|
|
1832
|
-
if (['window', 'self', 'globalThis'].includes(key)) {
|
|
1833
|
-
return this.proxyWindow;
|
|
1834
|
-
}
|
|
1835
|
-
if (key === 'top' || key === 'parent') {
|
|
1836
|
-
if (rawWindow === rawWindow.parent) { // not in iframe
|
|
1837
|
-
return this.proxyWindow;
|
|
1838
|
-
}
|
|
1839
|
-
return Reflect.get(rawWindow, key); // iframe
|
|
1840
|
-
}
|
|
1841
|
-
if (key === 'hasOwnProperty')
|
|
1842
|
-
return hasOwnProperty;
|
|
1843
|
-
if (key === 'document' || key === 'eval') {
|
|
1844
|
-
if (this.active) {
|
|
1845
|
-
setCurrentAppName(appName);
|
|
1846
|
-
(macro ? macroTask : defer)(() => setCurrentAppName(null));
|
|
1847
|
-
}
|
|
1848
|
-
switch (key) {
|
|
1849
|
-
case 'document':
|
|
1850
|
-
return rawDocument;
|
|
1851
|
-
case 'eval':
|
|
1852
|
-
return eval;
|
|
1853
|
-
}
|
|
1854
|
-
}
|
|
1855
|
-
if (Reflect.has(target, key)) {
|
|
1856
|
-
return Reflect.get(target, key);
|
|
1857
|
-
}
|
|
1858
|
-
if (this.scopeProperties.includes(key) ||
|
|
1859
|
-
(isString(key) && /^__MICRO_APP_/.test(key))) {
|
|
1860
|
-
return Reflect.get(target, key);
|
|
1861
|
-
}
|
|
1862
|
-
const rawValue = Reflect.get(rawWindow, key);
|
|
1863
|
-
return bindFunctionToRawWidow(rawWindow, rawValue);
|
|
1864
|
-
},
|
|
1865
|
-
set: (target, key, value) => {
|
|
1866
|
-
if (this.active) {
|
|
1867
|
-
if (escapeSetterKeyList.includes(key)) {
|
|
1868
|
-
Reflect.set(rawWindow, key, value);
|
|
1869
|
-
}
|
|
1870
|
-
else if (!target.hasOwnProperty(key) &&
|
|
1871
|
-
rawWindow.hasOwnProperty(key) &&
|
|
1872
|
-
!this.scopeProperties.includes(key)) {
|
|
1873
|
-
const descriptor = Object.getOwnPropertyDescriptor(rawWindow, key);
|
|
1874
|
-
const { writable, configurable, enumerable } = descriptor;
|
|
1875
|
-
if (writable) {
|
|
1876
|
-
Object.defineProperty(target, key, {
|
|
1877
|
-
configurable,
|
|
1878
|
-
enumerable,
|
|
1879
|
-
writable,
|
|
1880
|
-
value,
|
|
1881
|
-
});
|
|
1882
|
-
this.injectedKeys.add(key);
|
|
1883
|
-
}
|
|
1884
|
-
}
|
|
1885
|
-
else {
|
|
1886
|
-
Reflect.set(target, key, value);
|
|
1887
|
-
this.injectedKeys.add(key);
|
|
1888
|
-
}
|
|
1889
|
-
if ((this.escapeProperties.includes(key) ||
|
|
1890
|
-
(staticEscapeProperties.includes(key) && !Reflect.has(rawWindow, key))) &&
|
|
1891
|
-
!this.scopeProperties.includes(key)) {
|
|
1892
|
-
Reflect.set(rawWindow, key, value);
|
|
1893
|
-
this.escapeKeys.add(key);
|
|
1894
|
-
}
|
|
1895
|
-
}
|
|
1896
|
-
return true;
|
|
1897
|
-
},
|
|
1898
|
-
has: (target, key) => {
|
|
1899
|
-
if (this.scopeProperties.includes(key))
|
|
1900
|
-
return key in target;
|
|
1901
|
-
return key in unscopables || key in target || key in rawWindow;
|
|
1902
|
-
},
|
|
1903
|
-
// Object.getOwnPropertyDescriptor(window, key)
|
|
1904
|
-
// TODO: use set
|
|
1905
|
-
getOwnPropertyDescriptor: (target, key) => {
|
|
1906
|
-
if (target.hasOwnProperty(key)) {
|
|
1907
|
-
descriptorTargetMap.set(key, 'target');
|
|
1908
|
-
return Object.getOwnPropertyDescriptor(target, key);
|
|
1909
|
-
}
|
|
1910
|
-
if (rawWindow.hasOwnProperty(key)) {
|
|
1911
|
-
// like console, alert ...
|
|
1912
|
-
descriptorTargetMap.set(key, 'rawWindow');
|
|
1913
|
-
const descriptor = Object.getOwnPropertyDescriptor(rawWindow, key);
|
|
1914
|
-
if (descriptor && !descriptor.configurable) {
|
|
1915
|
-
descriptor.configurable = true;
|
|
1916
|
-
}
|
|
1917
|
-
return descriptor;
|
|
1918
|
-
}
|
|
1919
|
-
return undefined;
|
|
1920
|
-
},
|
|
1921
|
-
// Object.defineProperty(window, key, Descriptor)
|
|
1922
|
-
defineProperty: (target, key, value) => {
|
|
1923
|
-
const from = descriptorTargetMap.get(key);
|
|
1924
|
-
if (from === 'rawWindow') {
|
|
1925
|
-
return Reflect.defineProperty(rawWindow, key, value);
|
|
1926
|
-
}
|
|
1927
|
-
return Reflect.defineProperty(target, key, value);
|
|
1928
|
-
},
|
|
1929
|
-
// Object.getOwnPropertyNames(window)
|
|
1930
|
-
ownKeys: (target) => {
|
|
1931
|
-
return unique(Reflect.ownKeys(rawWindow).concat(Reflect.ownKeys(target)));
|
|
1932
|
-
},
|
|
1933
|
-
deleteProperty: (target, key) => {
|
|
1934
|
-
if (target.hasOwnProperty(key)) {
|
|
1935
|
-
this.injectedKeys.has(key) && this.injectedKeys.delete(key);
|
|
1936
|
-
this.escapeKeys.has(key) && Reflect.deleteProperty(rawWindow, key);
|
|
1937
|
-
return Reflect.deleteProperty(target, key);
|
|
1938
|
-
}
|
|
1939
|
-
return true;
|
|
1940
|
-
},
|
|
1941
|
-
});
|
|
1859
|
+
Object.assign(this, effect(this.microAppWindow));
|
|
1942
1860
|
}
|
|
1943
1861
|
start(baseroute) {
|
|
1944
1862
|
if (!this.active) {
|
|
1945
1863
|
this.active = true;
|
|
1946
|
-
this.
|
|
1864
|
+
this.microAppWindow.__MICRO_APP_BASE_ROUTE__ = this.microAppWindow.__MICRO_APP_BASE_URL__ = baseroute;
|
|
1947
1865
|
// BUG FIX: bable-polyfill@6.x
|
|
1948
1866
|
globalEnv.rawWindow._babelPolyfill && (globalEnv.rawWindow._babelPolyfill = false);
|
|
1949
1867
|
if (++SandBox.activeCount === 1) {
|
|
@@ -1955,10 +1873,10 @@ class SandBox {
|
|
|
1955
1873
|
if (this.active) {
|
|
1956
1874
|
this.active = false;
|
|
1957
1875
|
this.releaseEffect();
|
|
1958
|
-
this.
|
|
1959
|
-
this.
|
|
1876
|
+
this.microAppWindow.microApp.clearDataListener();
|
|
1877
|
+
this.microAppWindow.microApp.clearGlobalDataListener();
|
|
1960
1878
|
this.injectedKeys.forEach((key) => {
|
|
1961
|
-
Reflect.deleteProperty(this.
|
|
1879
|
+
Reflect.deleteProperty(this.microAppWindow, key);
|
|
1962
1880
|
});
|
|
1963
1881
|
this.injectedKeys.clear();
|
|
1964
1882
|
this.escapeKeys.forEach((key) => {
|
|
@@ -1972,12 +1890,12 @@ class SandBox {
|
|
|
1972
1890
|
}
|
|
1973
1891
|
// record umd snapshot before the first execution of umdHookMount
|
|
1974
1892
|
recordUmdSnapshot() {
|
|
1975
|
-
this.
|
|
1893
|
+
this.microAppWindow.__MICRO_APP_UMD_MODE__ = true;
|
|
1976
1894
|
this.recordUmdEffect();
|
|
1977
|
-
recordDataCenterSnapshot(this.
|
|
1895
|
+
recordDataCenterSnapshot(this.microAppWindow.microApp);
|
|
1978
1896
|
this.recordUmdinjectedValues = new Map();
|
|
1979
1897
|
this.injectedKeys.forEach((key) => {
|
|
1980
|
-
this.recordUmdinjectedValues.set(key, Reflect.get(this.
|
|
1898
|
+
this.recordUmdinjectedValues.set(key, Reflect.get(this.microAppWindow, key));
|
|
1981
1899
|
});
|
|
1982
1900
|
}
|
|
1983
1901
|
// rebuild umd snapshot before remount umd app
|
|
@@ -1986,7 +1904,7 @@ class SandBox {
|
|
|
1986
1904
|
Reflect.set(this.proxyWindow, key, value);
|
|
1987
1905
|
});
|
|
1988
1906
|
this.rebuildUmdEffect();
|
|
1989
|
-
rebuildDataCenterSnapshot(this.
|
|
1907
|
+
rebuildDataCenterSnapshot(this.microAppWindow.microApp);
|
|
1990
1908
|
}
|
|
1991
1909
|
/**
|
|
1992
1910
|
* get scopeProperties and escapeProperties from plugins
|
|
@@ -2021,25 +1939,183 @@ class SandBox {
|
|
|
2021
1939
|
}
|
|
2022
1940
|
}
|
|
2023
1941
|
}
|
|
1942
|
+
// create proxyWindow with Proxy(microAppWindow)
|
|
1943
|
+
createProxyWindow() {
|
|
1944
|
+
const rawWindow = globalEnv.rawWindow;
|
|
1945
|
+
const descriptorTargetMap = new Map();
|
|
1946
|
+
// window.xxx will trigger proxy
|
|
1947
|
+
return new Proxy(this.microAppWindow, {
|
|
1948
|
+
get: (target, key) => {
|
|
1949
|
+
if (Reflect.has(target, key) ||
|
|
1950
|
+
(isString(key) && /^__MICRO_APP_/.test(key)) ||
|
|
1951
|
+
this.scopeProperties.includes(key))
|
|
1952
|
+
return Reflect.get(target, key);
|
|
1953
|
+
const rawValue = Reflect.get(rawWindow, key);
|
|
1954
|
+
return isFunction(rawValue) ? bindFunctionToRawWindow(rawWindow, rawValue) : rawValue;
|
|
1955
|
+
},
|
|
1956
|
+
set: (target, key, value) => {
|
|
1957
|
+
if (this.active) {
|
|
1958
|
+
if (escapeSetterKeyList.includes(key)) {
|
|
1959
|
+
Reflect.set(rawWindow, key, value);
|
|
1960
|
+
}
|
|
1961
|
+
else if (
|
|
1962
|
+
// target.hasOwnProperty has been rewritten
|
|
1963
|
+
!rawHasOwnProperty.call(target, key) &&
|
|
1964
|
+
rawHasOwnProperty.call(rawWindow, key) &&
|
|
1965
|
+
!this.scopeProperties.includes(key)) {
|
|
1966
|
+
const descriptor = Object.getOwnPropertyDescriptor(rawWindow, key);
|
|
1967
|
+
const { configurable, enumerable, writable, set } = descriptor;
|
|
1968
|
+
// set value because it can be set
|
|
1969
|
+
rawDefineProperty(target, key, {
|
|
1970
|
+
value,
|
|
1971
|
+
configurable,
|
|
1972
|
+
enumerable,
|
|
1973
|
+
writable: writable !== null && writable !== void 0 ? writable : !!set,
|
|
1974
|
+
});
|
|
1975
|
+
this.injectedKeys.add(key);
|
|
1976
|
+
}
|
|
1977
|
+
else {
|
|
1978
|
+
Reflect.set(target, key, value);
|
|
1979
|
+
this.injectedKeys.add(key);
|
|
1980
|
+
}
|
|
1981
|
+
if ((this.escapeProperties.includes(key) ||
|
|
1982
|
+
(staticEscapeProperties.includes(key) && !Reflect.has(rawWindow, key))) &&
|
|
1983
|
+
!this.scopeProperties.includes(key)) {
|
|
1984
|
+
Reflect.set(rawWindow, key, value);
|
|
1985
|
+
this.escapeKeys.add(key);
|
|
1986
|
+
}
|
|
1987
|
+
}
|
|
1988
|
+
return true;
|
|
1989
|
+
},
|
|
1990
|
+
has: (target, key) => {
|
|
1991
|
+
if (this.scopeProperties.includes(key))
|
|
1992
|
+
return key in target;
|
|
1993
|
+
return key in target || key in rawWindow;
|
|
1994
|
+
},
|
|
1995
|
+
// Object.getOwnPropertyDescriptor(window, key)
|
|
1996
|
+
getOwnPropertyDescriptor: (target, key) => {
|
|
1997
|
+
if (rawHasOwnProperty.call(target, key)) {
|
|
1998
|
+
descriptorTargetMap.set(key, 'target');
|
|
1999
|
+
return Object.getOwnPropertyDescriptor(target, key);
|
|
2000
|
+
}
|
|
2001
|
+
if (rawHasOwnProperty.call(rawWindow, key)) {
|
|
2002
|
+
descriptorTargetMap.set(key, 'rawWindow');
|
|
2003
|
+
const descriptor = Object.getOwnPropertyDescriptor(rawWindow, key);
|
|
2004
|
+
if (descriptor && !descriptor.configurable) {
|
|
2005
|
+
descriptor.configurable = true;
|
|
2006
|
+
}
|
|
2007
|
+
return descriptor;
|
|
2008
|
+
}
|
|
2009
|
+
return undefined;
|
|
2010
|
+
},
|
|
2011
|
+
// Object.defineProperty(window, key, Descriptor)
|
|
2012
|
+
defineProperty: (target, key, value) => {
|
|
2013
|
+
const from = descriptorTargetMap.get(key);
|
|
2014
|
+
if (from === 'rawWindow') {
|
|
2015
|
+
return Reflect.defineProperty(rawWindow, key, value);
|
|
2016
|
+
}
|
|
2017
|
+
return Reflect.defineProperty(target, key, value);
|
|
2018
|
+
},
|
|
2019
|
+
// Object.getOwnPropertyNames(window)
|
|
2020
|
+
ownKeys: (target) => {
|
|
2021
|
+
return unique(Reflect.ownKeys(rawWindow).concat(Reflect.ownKeys(target)));
|
|
2022
|
+
},
|
|
2023
|
+
deleteProperty: (target, key) => {
|
|
2024
|
+
if (rawHasOwnProperty.call(target, key)) {
|
|
2025
|
+
this.injectedKeys.has(key) && this.injectedKeys.delete(key);
|
|
2026
|
+
this.escapeKeys.has(key) && Reflect.deleteProperty(rawWindow, key);
|
|
2027
|
+
return Reflect.deleteProperty(target, key);
|
|
2028
|
+
}
|
|
2029
|
+
return true;
|
|
2030
|
+
},
|
|
2031
|
+
});
|
|
2032
|
+
}
|
|
2024
2033
|
/**
|
|
2025
|
-
* inject global properties to
|
|
2026
|
-
* @param
|
|
2034
|
+
* inject global properties to microAppWindow
|
|
2035
|
+
* @param microAppWindow micro window
|
|
2027
2036
|
* @param appName app name
|
|
2028
2037
|
* @param url app url
|
|
2029
2038
|
*/
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2039
|
+
initMicroAppWindow(microAppWindow, appName, url) {
|
|
2040
|
+
microAppWindow.__MICRO_APP_ENVIRONMENT__ = true;
|
|
2041
|
+
microAppWindow.__MICRO_APP_NAME__ = appName;
|
|
2042
|
+
microAppWindow.__MICRO_APP_PUBLIC_PATH__ = getEffectivePath(url);
|
|
2043
|
+
microAppWindow.__MICRO_APP_WINDOW__ = microAppWindow;
|
|
2044
|
+
microAppWindow.microApp = new EventCenterForMicroApp(appName);
|
|
2045
|
+
microAppWindow.rawWindow = globalEnv.rawWindow;
|
|
2046
|
+
microAppWindow.rawDocument = globalEnv.rawDocument;
|
|
2047
|
+
microAppWindow.removeDomScope = removeDomScope;
|
|
2048
|
+
microAppWindow.hasOwnProperty = (key) => rawHasOwnProperty.call(microAppWindow, key) || rawHasOwnProperty.call(globalEnv.rawWindow, key);
|
|
2049
|
+
this.setMappingPropertiesWithRawDescriptor(microAppWindow);
|
|
2050
|
+
this.setHijackProperties(microAppWindow, appName);
|
|
2051
|
+
}
|
|
2052
|
+
// properties associated with the native window
|
|
2053
|
+
setMappingPropertiesWithRawDescriptor(microAppWindow) {
|
|
2054
|
+
let topValue, parentValue;
|
|
2055
|
+
const rawWindow = globalEnv.rawWindow;
|
|
2056
|
+
if (rawWindow === rawWindow.parent) { // not in iframe
|
|
2057
|
+
topValue = parentValue = this.proxyWindow;
|
|
2058
|
+
}
|
|
2059
|
+
else { // in iframe
|
|
2060
|
+
topValue = rawWindow.top;
|
|
2061
|
+
parentValue = rawWindow.parent;
|
|
2062
|
+
}
|
|
2063
|
+
rawDefineProperty(microAppWindow, 'top', this.createDescriptorFormicroAppWindow('top', topValue));
|
|
2064
|
+
rawDefineProperty(microAppWindow, 'parent', this.createDescriptorFormicroAppWindow('parent', parentValue));
|
|
2065
|
+
globalPropertyList.forEach((key) => {
|
|
2066
|
+
rawDefineProperty(microAppWindow, key, this.createDescriptorFormicroAppWindow(key, this.proxyWindow));
|
|
2067
|
+
});
|
|
2068
|
+
}
|
|
2069
|
+
createDescriptorFormicroAppWindow(key, value) {
|
|
2070
|
+
const { configurable = true, enumerable = true, writable, set } = Object.getOwnPropertyDescriptor(globalEnv.rawWindow, key) || { writable: true };
|
|
2071
|
+
const descriptor = {
|
|
2072
|
+
value,
|
|
2073
|
+
configurable,
|
|
2074
|
+
enumerable,
|
|
2075
|
+
writable: writable !== null && writable !== void 0 ? writable : !!set
|
|
2076
|
+
};
|
|
2077
|
+
return descriptor;
|
|
2078
|
+
}
|
|
2079
|
+
// set hijack Properties to microAppWindow
|
|
2080
|
+
setHijackProperties(microAppWindow, appName) {
|
|
2081
|
+
let modifiedEval, modifiedImage;
|
|
2082
|
+
rawDefineProperties(microAppWindow, {
|
|
2083
|
+
document: {
|
|
2084
|
+
get() {
|
|
2085
|
+
throttleDeferForSetAppName(appName);
|
|
2086
|
+
return globalEnv.rawDocument;
|
|
2087
|
+
},
|
|
2088
|
+
configurable: false,
|
|
2089
|
+
enumerable: true,
|
|
2090
|
+
},
|
|
2091
|
+
eval: {
|
|
2092
|
+
get() {
|
|
2093
|
+
throttleDeferForSetAppName(appName);
|
|
2094
|
+
return modifiedEval || eval;
|
|
2095
|
+
},
|
|
2096
|
+
set: (value) => {
|
|
2097
|
+
modifiedEval = value;
|
|
2098
|
+
},
|
|
2099
|
+
configurable: true,
|
|
2100
|
+
enumerable: false,
|
|
2101
|
+
},
|
|
2102
|
+
Image: {
|
|
2103
|
+
get() {
|
|
2104
|
+
throttleDeferForSetAppName(appName);
|
|
2105
|
+
return modifiedImage || globalEnv.ImageProxy;
|
|
2106
|
+
},
|
|
2107
|
+
set: (value) => {
|
|
2108
|
+
modifiedImage = value;
|
|
2109
|
+
},
|
|
2110
|
+
configurable: true,
|
|
2111
|
+
enumerable: false,
|
|
2112
|
+
},
|
|
2113
|
+
});
|
|
2038
2114
|
}
|
|
2039
2115
|
}
|
|
2040
2116
|
SandBox.activeCount = 0; // number of active sandbox
|
|
2041
2117
|
|
|
2042
|
-
function
|
|
2118
|
+
function formatEventInfo(event, element) {
|
|
2043
2119
|
Object.defineProperties(event, {
|
|
2044
2120
|
currentTarget: {
|
|
2045
2121
|
get() {
|
|
@@ -2078,7 +2154,7 @@ function dispatchLifecyclesEvent(element, appName, lifecycleName, error) {
|
|
|
2078
2154
|
const event = new CustomEvent(lifecycleName, {
|
|
2079
2155
|
detail,
|
|
2080
2156
|
});
|
|
2081
|
-
|
|
2157
|
+
formatEventInfo(event, element);
|
|
2082
2158
|
// global hooks
|
|
2083
2159
|
// @ts-ignore
|
|
2084
2160
|
if (isFunction((_a = microApp.lifeCycles) === null || _a === void 0 ? void 0 : _a[lifecycleName])) {
|
|
@@ -2103,7 +2179,7 @@ function dispatchCustomEventToMicroApp(eventName, appName, detail = {}) {
|
|
|
2103
2179
|
// micro app instances
|
|
2104
2180
|
const appInstanceMap = new Map();
|
|
2105
2181
|
class CreateApp {
|
|
2106
|
-
constructor({ name, url, ssrUrl, container, inline, scopecss, useSandbox,
|
|
2182
|
+
constructor({ name, url, ssrUrl, container, inline, scopecss, useSandbox, baseroute, }) {
|
|
2107
2183
|
this.state = appStates.NOT_LOADED;
|
|
2108
2184
|
this.keepAliveState = null;
|
|
2109
2185
|
this.keepAliveContainer = null;
|
|
@@ -2114,7 +2190,6 @@ class CreateApp {
|
|
|
2114
2190
|
this.umdMode = false;
|
|
2115
2191
|
this.isPrefetch = false;
|
|
2116
2192
|
this.container = null;
|
|
2117
|
-
this.macro = false;
|
|
2118
2193
|
this.baseroute = '';
|
|
2119
2194
|
this.sandBox = null;
|
|
2120
2195
|
this.container = container !== null && container !== void 0 ? container : null;
|
|
@@ -2126,13 +2201,12 @@ class CreateApp {
|
|
|
2126
2201
|
this.url = url;
|
|
2127
2202
|
this.useSandbox = useSandbox;
|
|
2128
2203
|
this.scopecss = this.useSandbox && scopecss;
|
|
2129
|
-
this.macro = macro !== null && macro !== void 0 ? macro : false;
|
|
2130
2204
|
this.source = {
|
|
2131
2205
|
links: new Map(),
|
|
2132
2206
|
scripts: new Map(),
|
|
2133
2207
|
};
|
|
2134
2208
|
this.loadSourceCode();
|
|
2135
|
-
this.useSandbox && (this.sandBox = new SandBox(name, url
|
|
2209
|
+
this.useSandbox && (this.sandBox = new SandBox(name, url));
|
|
2136
2210
|
}
|
|
2137
2211
|
// Load resources
|
|
2138
2212
|
loadSourceCode() {
|
|
@@ -2298,21 +2372,21 @@ class CreateApp {
|
|
|
2298
2372
|
*/
|
|
2299
2373
|
actionsForUnmount(destroy, unmountcb) {
|
|
2300
2374
|
var _a;
|
|
2301
|
-
// dispatch unmount event to base app
|
|
2302
|
-
dispatchLifecyclesEvent(this.container, this.name, lifeCycles.UNMOUNT);
|
|
2303
2375
|
(_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.stop();
|
|
2304
2376
|
if (destroy) {
|
|
2305
|
-
this.
|
|
2377
|
+
this.actionsForCompletelyDestroy();
|
|
2306
2378
|
}
|
|
2307
2379
|
else if (this.umdMode && this.container.childElementCount) {
|
|
2308
2380
|
cloneContainer(this.container, this.source.html, false);
|
|
2309
2381
|
}
|
|
2382
|
+
// dispatch unmount event to base app
|
|
2383
|
+
dispatchLifecyclesEvent(this.container, this.name, lifeCycles.UNMOUNT);
|
|
2310
2384
|
this.container.innerHTML = '';
|
|
2311
2385
|
this.container = null;
|
|
2312
2386
|
unmountcb && unmountcb();
|
|
2313
2387
|
}
|
|
2314
2388
|
// actions for completely destroy
|
|
2315
|
-
|
|
2389
|
+
actionsForCompletelyDestroy() {
|
|
2316
2390
|
if (!this.useSandbox && this.umdMode) {
|
|
2317
2391
|
delete window[this.libraryName];
|
|
2318
2392
|
}
|
|
@@ -2320,6 +2394,9 @@ class CreateApp {
|
|
|
2320
2394
|
}
|
|
2321
2395
|
// hidden app when disconnectedCallback called with keep-alive
|
|
2322
2396
|
hiddenKeepAliveApp() {
|
|
2397
|
+
const oldContainer = this.container;
|
|
2398
|
+
cloneContainer(this.container, this.keepAliveContainer ? this.keepAliveContainer : (this.keepAliveContainer = document.createElement('div')), false);
|
|
2399
|
+
this.container = this.keepAliveContainer;
|
|
2323
2400
|
this.keepAliveState = keepAliveStates.KEEP_ALIVE_HIDDEN;
|
|
2324
2401
|
// event should dispatch before clone node
|
|
2325
2402
|
// dispatch afterhidden event to micro-app
|
|
@@ -2327,9 +2404,7 @@ class CreateApp {
|
|
|
2327
2404
|
appState: 'afterhidden',
|
|
2328
2405
|
});
|
|
2329
2406
|
// dispatch afterhidden event to base app
|
|
2330
|
-
dispatchLifecyclesEvent(
|
|
2331
|
-
cloneContainer(this.container, this.keepAliveContainer ? this.keepAliveContainer : (this.keepAliveContainer = document.createElement('div')), false);
|
|
2332
|
-
this.container = this.keepAliveContainer;
|
|
2407
|
+
dispatchLifecyclesEvent(oldContainer, this.name, lifeCycles.AFTERHIDDEN);
|
|
2333
2408
|
}
|
|
2334
2409
|
// show app when connectedCallback called with keep-alive
|
|
2335
2410
|
showKeepAliveApp(container) {
|
|
@@ -2377,20 +2452,6 @@ class CreateApp {
|
|
|
2377
2452
|
return {};
|
|
2378
2453
|
}
|
|
2379
2454
|
}
|
|
2380
|
-
// if app not prefetch & not unmount, then app is active
|
|
2381
|
-
function getActiveApps() {
|
|
2382
|
-
const activeApps = [];
|
|
2383
|
-
appInstanceMap.forEach((app, appName) => {
|
|
2384
|
-
if (appStates.UNMOUNT !== app.getAppState() && !app.isPrefetch) {
|
|
2385
|
-
activeApps.push(appName);
|
|
2386
|
-
}
|
|
2387
|
-
});
|
|
2388
|
-
return activeApps;
|
|
2389
|
-
}
|
|
2390
|
-
// get all registered apps
|
|
2391
|
-
function getAllApps() {
|
|
2392
|
-
return Array.from(appInstanceMap.keys());
|
|
2393
|
-
}
|
|
2394
2455
|
|
|
2395
2456
|
// Record element and map element
|
|
2396
2457
|
const dynamicElementInMicroAppMap = new WeakMap();
|
|
@@ -2585,13 +2646,13 @@ function patchElementPrototypeMethods() {
|
|
|
2585
2646
|
}
|
|
2586
2647
|
};
|
|
2587
2648
|
// prototype methods of add element👇
|
|
2588
|
-
|
|
2649
|
+
Element.prototype.appendChild = function appendChild(newChild) {
|
|
2589
2650
|
return commonElementHander(this, newChild, null, globalEnv.rawAppendChild);
|
|
2590
2651
|
};
|
|
2591
|
-
|
|
2652
|
+
Element.prototype.insertBefore = function insertBefore(newChild, refChild) {
|
|
2592
2653
|
return commonElementHander(this, newChild, refChild, globalEnv.rawInsertBefore);
|
|
2593
2654
|
};
|
|
2594
|
-
|
|
2655
|
+
Element.prototype.replaceChild = function replaceChild(newChild, oldChild) {
|
|
2595
2656
|
return commonElementHander(this, newChild, oldChild, globalEnv.rawReplaceChild);
|
|
2596
2657
|
};
|
|
2597
2658
|
Element.prototype.append = function append(...nodes) {
|
|
@@ -2610,7 +2671,7 @@ function patchElementPrototypeMethods() {
|
|
|
2610
2671
|
}
|
|
2611
2672
|
};
|
|
2612
2673
|
// prototype methods of delete element👇
|
|
2613
|
-
|
|
2674
|
+
Element.prototype.removeChild = function removeChild(oldChild) {
|
|
2614
2675
|
if (oldChild === null || oldChild === void 0 ? void 0 : oldChild.__MICRO_APP_NAME__) {
|
|
2615
2676
|
const app = appInstanceMap.get(oldChild.__MICRO_APP_NAME__);
|
|
2616
2677
|
if (app === null || app === void 0 ? void 0 : app.container) {
|
|
@@ -2620,6 +2681,12 @@ function patchElementPrototypeMethods() {
|
|
|
2620
2681
|
}
|
|
2621
2682
|
return globalEnv.rawRemoveChild.call(this, oldChild);
|
|
2622
2683
|
};
|
|
2684
|
+
// patch cloneNode
|
|
2685
|
+
Element.prototype.cloneNode = function cloneNode(deep) {
|
|
2686
|
+
const clonedNode = globalEnv.rawCloneNode.call(this, deep);
|
|
2687
|
+
this.__MICRO_APP_NAME__ && (clonedNode.__MICRO_APP_NAME__ = this.__MICRO_APP_NAME__);
|
|
2688
|
+
return clonedNode;
|
|
2689
|
+
};
|
|
2623
2690
|
}
|
|
2624
2691
|
/**
|
|
2625
2692
|
* Mark the newly created element in the micro application
|
|
@@ -2738,12 +2805,13 @@ function releasePatches() {
|
|
|
2738
2805
|
setCurrentAppName(null);
|
|
2739
2806
|
releasePatchDocument();
|
|
2740
2807
|
Element.prototype.setAttribute = globalEnv.rawSetAttribute;
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2808
|
+
Element.prototype.appendChild = globalEnv.rawAppendChild;
|
|
2809
|
+
Element.prototype.insertBefore = globalEnv.rawInsertBefore;
|
|
2810
|
+
Element.prototype.replaceChild = globalEnv.rawReplaceChild;
|
|
2811
|
+
Element.prototype.removeChild = globalEnv.rawRemoveChild;
|
|
2745
2812
|
Element.prototype.append = globalEnv.rawAppend;
|
|
2746
2813
|
Element.prototype.prepend = globalEnv.rawPrepend;
|
|
2814
|
+
Element.prototype.cloneNode = globalEnv.rawCloneNode;
|
|
2747
2815
|
}
|
|
2748
2816
|
// Set the style of micro-app-head and micro-app-body
|
|
2749
2817
|
let hasRejectMicroAppStyle = false;
|
|
@@ -2823,12 +2891,12 @@ function defineElement(tagName) {
|
|
|
2823
2891
|
this.actionsForAttributeChange(formatAttrName, formatAttrUrl, existApp);
|
|
2824
2892
|
});
|
|
2825
2893
|
}
|
|
2826
|
-
else if (this.
|
|
2894
|
+
else if (this.getKeepAliveModeResult()) {
|
|
2827
2895
|
this.handleHiddenKeepAliveApp();
|
|
2828
2896
|
this.actionsForAttributeChange(formatAttrName, formatAttrUrl, existApp);
|
|
2829
2897
|
}
|
|
2830
2898
|
else {
|
|
2831
|
-
this.handleUnmount(this.
|
|
2899
|
+
this.handleUnmount(this.getDestroyCompatibleResult(), () => {
|
|
2832
2900
|
this.actionsForAttributeChange(formatAttrName, formatAttrUrl, existApp);
|
|
2833
2901
|
});
|
|
2834
2902
|
}
|
|
@@ -2854,9 +2922,8 @@ function defineElement(tagName) {
|
|
|
2854
2922
|
// inline: whether js runs in inline script mode, default is false
|
|
2855
2923
|
// disableScopecss: whether disable css scoped, default is false
|
|
2856
2924
|
// disableSandbox: whether disable sandbox, default is false
|
|
2857
|
-
// macro: used to solve the async render problem of vue3, default is false
|
|
2858
2925
|
// baseRoute: route prefix, default is ''
|
|
2859
|
-
// keep-alive: open keep-alive mode
|
|
2926
|
+
// keep-alive: open keep-alive mode
|
|
2860
2927
|
connectedCallback() {
|
|
2861
2928
|
this.hasConnected = true;
|
|
2862
2929
|
if (!elementInstanceMap.has(this)) {
|
|
@@ -2867,13 +2934,13 @@ function defineElement(tagName) {
|
|
|
2867
2934
|
}
|
|
2868
2935
|
disconnectedCallback() {
|
|
2869
2936
|
this.hasConnected = false;
|
|
2870
|
-
// keep-alive
|
|
2871
|
-
if (this.
|
|
2937
|
+
// keep-alive
|
|
2938
|
+
if (this.getKeepAliveModeResult()) {
|
|
2872
2939
|
this.handleHiddenKeepAliveApp();
|
|
2873
2940
|
}
|
|
2874
2941
|
else {
|
|
2875
2942
|
elementInstanceMap.delete(this);
|
|
2876
|
-
this.handleUnmount(this.
|
|
2943
|
+
this.handleUnmount(this.getDestroyCompatibleResult(), () => {
|
|
2877
2944
|
if (elementInstanceMap.size === 0) {
|
|
2878
2945
|
releasePatches();
|
|
2879
2946
|
}
|
|
@@ -3052,7 +3119,7 @@ function defineElement(tagName) {
|
|
|
3052
3119
|
* fix of unmounted umd app with disableSandbox
|
|
3053
3120
|
*/
|
|
3054
3121
|
if (appInstanceMap.has(this.appName)) {
|
|
3055
|
-
appInstanceMap.get(this.appName).
|
|
3122
|
+
appInstanceMap.get(this.appName).actionsForCompletelyDestroy();
|
|
3056
3123
|
}
|
|
3057
3124
|
const instance = new CreateApp({
|
|
3058
3125
|
name: this.appName,
|
|
@@ -3062,7 +3129,6 @@ function defineElement(tagName) {
|
|
|
3062
3129
|
inline: this.getDisposeResult('inline'),
|
|
3063
3130
|
scopecss: !(this.getDisposeResult('disableScopecss') || this.getDisposeResult('shadowDOM')),
|
|
3064
3131
|
useSandbox: !this.getDisposeResult('disableSandbox'),
|
|
3065
|
-
macro: this.getDisposeResult('macro'),
|
|
3066
3132
|
baseroute: this.getBaseRouteCompatible(),
|
|
3067
3133
|
});
|
|
3068
3134
|
appInstanceMap.set(this.appName, instance);
|
|
@@ -3097,7 +3163,27 @@ function defineElement(tagName) {
|
|
|
3097
3163
|
*/
|
|
3098
3164
|
getDisposeResult(name) {
|
|
3099
3165
|
// @ts-ignore
|
|
3100
|
-
return (this.
|
|
3166
|
+
return (this.compatibleSpecialProperties(name) || microApp[name]) && this.compatibleDisablSpecialProperties(name);
|
|
3167
|
+
}
|
|
3168
|
+
// compatible of disableScopecss & disableSandbox
|
|
3169
|
+
compatibleSpecialProperties(name) {
|
|
3170
|
+
if (name === 'disableScopecss') {
|
|
3171
|
+
return this.hasAttribute('disableScopecss') || this.hasAttribute('disable-scopecss');
|
|
3172
|
+
}
|
|
3173
|
+
else if (name === 'disableSandbox') {
|
|
3174
|
+
return this.hasAttribute('disableSandbox') || this.hasAttribute('disable-sandbox');
|
|
3175
|
+
}
|
|
3176
|
+
return this.hasAttribute(name);
|
|
3177
|
+
}
|
|
3178
|
+
// compatible of disableScopecss & disableSandbox
|
|
3179
|
+
compatibleDisablSpecialProperties(name) {
|
|
3180
|
+
if (name === 'disableScopecss') {
|
|
3181
|
+
return this.getAttribute('disableScopecss') !== 'false' && this.getAttribute('disable-scopecss') !== 'false';
|
|
3182
|
+
}
|
|
3183
|
+
else if (name === 'disableSandbox') {
|
|
3184
|
+
return this.getAttribute('disableSandbox') !== 'false' && this.getAttribute('disable-sandbox') !== 'false';
|
|
3185
|
+
}
|
|
3186
|
+
return this.getAttribute(name) !== 'false';
|
|
3101
3187
|
}
|
|
3102
3188
|
/**
|
|
3103
3189
|
* 2021-09-08
|
|
@@ -3108,6 +3194,16 @@ function defineElement(tagName) {
|
|
|
3108
3194
|
var _a, _b;
|
|
3109
3195
|
return (_b = (_a = this.getAttribute('baseroute')) !== null && _a !== void 0 ? _a : this.getAttribute('baseurl')) !== null && _b !== void 0 ? _b : '';
|
|
3110
3196
|
}
|
|
3197
|
+
// compatible of destroy
|
|
3198
|
+
getDestroyCompatibleResult() {
|
|
3199
|
+
return this.getDisposeResult('destroy') || this.getDisposeResult('destory');
|
|
3200
|
+
}
|
|
3201
|
+
/**
|
|
3202
|
+
* destroy has priority over destroy keep-alive
|
|
3203
|
+
*/
|
|
3204
|
+
getKeepAliveModeResult() {
|
|
3205
|
+
return this.getDisposeResult('keep-alive') && !this.getDestroyCompatibleResult();
|
|
3206
|
+
}
|
|
3111
3207
|
/**
|
|
3112
3208
|
* Data from the base application
|
|
3113
3209
|
*/
|
|
@@ -3157,13 +3253,12 @@ function filterPreFetchTarget(apps) {
|
|
|
3157
3253
|
* url: string,
|
|
3158
3254
|
* disableScopecss?: boolean,
|
|
3159
3255
|
* disableSandbox?: boolean,
|
|
3160
|
-
* macro?: boolean,
|
|
3161
3256
|
* },
|
|
3162
3257
|
* ...
|
|
3163
3258
|
* ])
|
|
3164
3259
|
* Note:
|
|
3165
3260
|
* 1: preFetch is asynchronous and is performed only when the browser is idle
|
|
3166
|
-
* 2: disableScopecss, disableSandbox
|
|
3261
|
+
* 2: disableScopecss, disableSandbox must be same with micro-app element, if conflict, the one who executes first shall prevail
|
|
3167
3262
|
* @param apps micro apps
|
|
3168
3263
|
*/
|
|
3169
3264
|
function preFetch(apps) {
|
|
@@ -3173,13 +3268,12 @@ function preFetch(apps) {
|
|
|
3173
3268
|
requestIdleCallback(() => {
|
|
3174
3269
|
isFunction(apps) && (apps = apps());
|
|
3175
3270
|
filterPreFetchTarget(apps).forEach((item) => {
|
|
3176
|
-
var _a, _b
|
|
3271
|
+
var _a, _b;
|
|
3177
3272
|
const app = new CreateApp({
|
|
3178
3273
|
name: item.name,
|
|
3179
3274
|
url: item.url,
|
|
3180
3275
|
scopecss: !((_a = item.disableScopecss) !== null && _a !== void 0 ? _a : microApp.disableScopecss),
|
|
3181
3276
|
useSandbox: !((_b = item.disableSandbox) !== null && _b !== void 0 ? _b : microApp.disableSandbox),
|
|
3182
|
-
macro: (_c = item.macro) !== null && _c !== void 0 ? _c : microApp.macro,
|
|
3183
3277
|
});
|
|
3184
3278
|
app.isPrefetch = true;
|
|
3185
3279
|
appInstanceMap.set(item.name, app);
|
|
@@ -3229,6 +3323,99 @@ function getGlobalAssets(assets) {
|
|
|
3229
3323
|
}
|
|
3230
3324
|
}
|
|
3231
3325
|
|
|
3326
|
+
/**
|
|
3327
|
+
* if app not prefetch & not unmount, then app is active
|
|
3328
|
+
* @param excludeHiddenApp exclude hidden keep-alive app
|
|
3329
|
+
* @returns active apps
|
|
3330
|
+
*/
|
|
3331
|
+
function getActiveApps(excludeHiddenApp) {
|
|
3332
|
+
const activeApps = [];
|
|
3333
|
+
appInstanceMap.forEach((app, appName) => {
|
|
3334
|
+
if (appStates.UNMOUNT !== app.getAppState() &&
|
|
3335
|
+
!app.isPrefetch &&
|
|
3336
|
+
(!excludeHiddenApp ||
|
|
3337
|
+
keepAliveStates.KEEP_ALIVE_HIDDEN !== app.getKeepAliveState())) {
|
|
3338
|
+
activeApps.push(appName);
|
|
3339
|
+
}
|
|
3340
|
+
});
|
|
3341
|
+
return activeApps;
|
|
3342
|
+
}
|
|
3343
|
+
// get all registered apps
|
|
3344
|
+
function getAllApps() {
|
|
3345
|
+
return Array.from(appInstanceMap.keys());
|
|
3346
|
+
}
|
|
3347
|
+
/**
|
|
3348
|
+
* unmount app by appname
|
|
3349
|
+
* @param appName
|
|
3350
|
+
* @param options unmountAppParams
|
|
3351
|
+
* @returns Promise<void>
|
|
3352
|
+
*/
|
|
3353
|
+
function unmountApp(appName, options) {
|
|
3354
|
+
const app = appInstanceMap.get(formatAppName(appName));
|
|
3355
|
+
return new Promise((reslove) => {
|
|
3356
|
+
if (app) {
|
|
3357
|
+
if (app.getAppState() === appStates.UNMOUNT || app.isPrefetch) {
|
|
3358
|
+
if (options === null || options === void 0 ? void 0 : options.destroy) {
|
|
3359
|
+
app.actionsForCompletelyDestroy();
|
|
3360
|
+
}
|
|
3361
|
+
reslove();
|
|
3362
|
+
}
|
|
3363
|
+
else if (app.getKeepAliveState() === keepAliveStates.KEEP_ALIVE_HIDDEN) {
|
|
3364
|
+
if (options === null || options === void 0 ? void 0 : options.destroy) {
|
|
3365
|
+
app.unmount(true, reslove);
|
|
3366
|
+
}
|
|
3367
|
+
else if (options === null || options === void 0 ? void 0 : options.clearAliveState) {
|
|
3368
|
+
app.unmount(false, reslove);
|
|
3369
|
+
}
|
|
3370
|
+
else {
|
|
3371
|
+
reslove();
|
|
3372
|
+
}
|
|
3373
|
+
}
|
|
3374
|
+
else {
|
|
3375
|
+
const container = getRootContainer(app.container);
|
|
3376
|
+
const unmountHandler = () => {
|
|
3377
|
+
container.removeEventListener('unmount', unmountHandler);
|
|
3378
|
+
container.removeEventListener('afterhidden', afterhiddenHandler);
|
|
3379
|
+
reslove();
|
|
3380
|
+
};
|
|
3381
|
+
const afterhiddenHandler = () => {
|
|
3382
|
+
container.removeEventListener('unmount', unmountHandler);
|
|
3383
|
+
container.removeEventListener('afterhidden', afterhiddenHandler);
|
|
3384
|
+
reslove();
|
|
3385
|
+
};
|
|
3386
|
+
container.addEventListener('unmount', unmountHandler);
|
|
3387
|
+
container.addEventListener('afterhidden', afterhiddenHandler);
|
|
3388
|
+
if (options === null || options === void 0 ? void 0 : options.destroy) {
|
|
3389
|
+
let destroyAttrValue, destoryAttrValue;
|
|
3390
|
+
container.hasAttribute('destroy') && (destroyAttrValue = container.getAttribute('destroy'));
|
|
3391
|
+
container.hasAttribute('destory') && (destoryAttrValue = container.getAttribute('destory'));
|
|
3392
|
+
container.setAttribute('destroy', 'true');
|
|
3393
|
+
container.parentNode.removeChild(container);
|
|
3394
|
+
container.removeAttribute('destroy');
|
|
3395
|
+
typeof destroyAttrValue === 'string' && container.setAttribute('destroy', destroyAttrValue);
|
|
3396
|
+
typeof destoryAttrValue === 'string' && container.setAttribute('destory', destoryAttrValue);
|
|
3397
|
+
}
|
|
3398
|
+
else if ((options === null || options === void 0 ? void 0 : options.clearAliveState) && container.hasAttribute('keep-alive')) {
|
|
3399
|
+
const keepAliveAttrValue = container.getAttribute('keep-alive');
|
|
3400
|
+
container.removeAttribute('keep-alive');
|
|
3401
|
+
container.parentNode.removeChild(container);
|
|
3402
|
+
container.setAttribute('keep-alive', keepAliveAttrValue);
|
|
3403
|
+
}
|
|
3404
|
+
else {
|
|
3405
|
+
container.parentNode.removeChild(container);
|
|
3406
|
+
}
|
|
3407
|
+
}
|
|
3408
|
+
}
|
|
3409
|
+
else {
|
|
3410
|
+
logWarn(`app ${appName} does not exist`);
|
|
3411
|
+
reslove();
|
|
3412
|
+
}
|
|
3413
|
+
});
|
|
3414
|
+
}
|
|
3415
|
+
// unmount all apps in turn
|
|
3416
|
+
function unmountAllApps(options) {
|
|
3417
|
+
return Array.from(appInstanceMap.keys()).reduce((pre, next) => pre.then(() => unmountApp(next, options)), Promise.resolve());
|
|
3418
|
+
}
|
|
3232
3419
|
class MicroApp extends EventCenterForBaseApp {
|
|
3233
3420
|
constructor() {
|
|
3234
3421
|
super(...arguments);
|
|
@@ -3263,7 +3450,6 @@ class MicroApp extends EventCenterForBaseApp {
|
|
|
3263
3450
|
this.inline = options.inline;
|
|
3264
3451
|
this.disableScopecss = options.disableScopecss;
|
|
3265
3452
|
this.disableSandbox = options.disableSandbox;
|
|
3266
|
-
this.macro = options.macro;
|
|
3267
3453
|
this.ssr = options.ssr;
|
|
3268
3454
|
isFunction(options.fetch) && (this.fetch = options.fetch);
|
|
3269
3455
|
isPlainObject(options.lifeCycles) && (this.lifeCycles = options.lifeCycles);
|
|
@@ -3292,5 +3478,5 @@ class MicroApp extends EventCenterForBaseApp {
|
|
|
3292
3478
|
var microApp = new MicroApp();
|
|
3293
3479
|
|
|
3294
3480
|
export default microApp;
|
|
3295
|
-
export { EventCenterForMicroApp, getActiveApps, getAllApps, preFetch, pureCreateElement, removeDomScope, version };
|
|
3481
|
+
export { EventCenterForMicroApp, MicroApp, getActiveApps, getAllApps, preFetch, pureCreateElement, removeDomScope, unmountAllApps, unmountApp, version };
|
|
3296
3482
|
//# sourceMappingURL=index.esm.js.map
|