@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/lib/index.esm.js CHANGED
@@ -1,4 +1,4 @@
1
- const version = '0.6.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 = Node.prototype.appendChild;
354
- const rawInsertBefore = Node.prototype.insertBefore;
355
- const rawReplaceChild = Node.prototype.replaceChild;
356
- const rawRemoveChild = Node.prototype.removeChild;
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):/.test($1)) {
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
- switch (rule.type) {
510
- case CSSRuleType.STYLE_RULE:
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 CSSRuleType.MEDIA_RULE:
536
+ case 'CSSMediaRule':
514
537
  result += scopedPackRule(rule, prefix, 'media');
515
538
  break;
516
- case CSSRuleType.SUPPORTS_RULE:
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
- microAppHead.replaceChild(scopedCSS(styleLink, app), info.placeholder);
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
- Promise.all(deferScriptPromise).then((res) => {
911
- res.forEach((code, index) => {
912
- const [url, info] = deferScriptInfo[index];
913
- info.code = info.code || code;
914
- runScript(url, app, info, false, initedHook);
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
- initedHook(true);
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(window, self){with(window){;${code}\n}}).call(window.__MICRO_APP_PROXY_WINDOW__, window.__MICRO_APP_PROXY_WINDOW__, window.__MICRO_APP_PROXY_WINDOW__);`;
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
- const boundedMap = new WeakMap();
1194
- function isBoundedFunction(value) {
1195
- if (boundedMap.has(value)) {
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
- if (isFunction(value) && !isConstructor(value) && !isBoundedFunction(value)) {
1224
- const bindRawWindowValue = value.bind(rawWindow);
1225
- for (const key in value) {
1226
- bindRawWindowValue[key] = value[key];
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
- rawWindowMethodMap.set(value, bindRawWindowValue);
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
- Object.defineProperty(document, 'onclick', {
1257
- configurable: true,
1258
- enumerable: true,
1259
- get() {
1260
- const appName = getCurrentAppName();
1261
- return appName ? documentClickListMap.get(appName) : documentClickListMap.get('base');
1262
- },
1263
- set(f) {
1264
- const appName = getCurrentAppName();
1265
- if (appName) {
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
- else {
1269
- documentClickListMap.set('base', f);
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 (!hasDocumentClickInited && isFunction(f)) {
1272
- hasDocumentClickInited = true;
1273
- globalEnv.rawDocumentAddEventListener.call(globalEnv.rawDocument, 'click', onClickHandler, false);
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
- rawOnClick && (document.onclick = rawOnClick);
1278
- }
1279
- /**
1280
- * The document event is globally, we need to clear these event bindings when micro application unmounted
1281
- */
1282
- const documentEventListenerMap = new Map();
1283
- function effectDocumentEvent() {
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
- appListenersMap.set(type, new Set([listener]));
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
- rawDocumentAddEventListener.call(rawDocument, type, listener, options);
1309
- };
1310
- document.removeEventListener = function (type, listener, options) {
1311
- var _a;
1312
- const appName = getCurrentAppName();
1313
- if (appName && !(((_a = appInstanceMap.get(appName)) === null || _a === void 0 ? void 0 : _a.umdMode) && isBoundFunction(listener))) {
1314
- const appListenersMap = documentEventListenerMap.get(appName);
1315
- if (appListenersMap) {
1316
- const appListenerList = appListenersMap.get(type);
1317
- if ((appListenerList === null || appListenerList === void 0 ? void 0 : appListenerList.size) && appListenerList.has(listener)) {
1318
- appListenerList.delete(listener);
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
- rawDocumentRemoveEventListener.call(rawDocument, type, listener, options);
1323
- };
1324
- }
1325
- // Clear the document event agent
1326
- function releaseEffectDocumentEvent() {
1327
- document.addEventListener = globalEnv.rawDocumentAddEventListener;
1328
- document.removeEventListener = globalEnv.rawDocumentRemoveEventListener;
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
- // this events should be sent to the specified app
1331
- const formatEventList = ['unmount', 'appstate-change'];
1309
+
1310
+ const eventCenter = new EventCenter();
1332
1311
  /**
1333
1312
  * Format event name
1334
- * @param type event name
1335
- * @param microWindow micro window
1313
+ * @param appName app.name
1314
+ * @param fromBaseApp is from base app
1336
1315
  */
1337
- function formatEventType(type, microWindow) {
1338
- if (formatEventList.includes(type)) {
1339
- return `${type}-${microWindow.__MICRO_APP_NAME__}`;
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
- * Rewrite side-effect events
1345
- * @param microWindow micro window
1346
- */
1347
- function effect(microWindow) {
1348
- const appName = microWindow.__MICRO_APP_NAME__;
1349
- const eventListenerMap = new Map();
1350
- const intervalIdMap = new Map();
1351
- const timeoutIdMap = new Map();
1352
- const { rawWindow, rawDocument, rawWindowAddEventListener, rawWindowRemoveEventListener, rawSetInterval, rawSetTimeout, rawClearInterval, rawClearTimeout, rawDocumentRemoveEventListener, } = globalEnv;
1353
- // listener may be null, e.g test-passive
1354
- microWindow.addEventListener = function (type, listener, options) {
1355
- type = formatEventType(type, microWindow);
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 unscopables = {
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, macro) {
1807
- // Scoped global Properties(Properties that can only get and set in microWindow, will not escape to rawWindow)
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 microWindow
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.microWindow = {}; // Proxy target
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.inject(this.microWindow, appName, url);
1857
+ this.initMicroAppWindow(this.microAppWindow, appName, url);
1826
1858
  // Rewrite global event listener & timeout
1827
- Object.assign(this, effect(this.microWindow));
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.microWindow.__MICRO_APP_BASE_ROUTE__ = this.microWindow.__MICRO_APP_BASE_URL__ = baseroute;
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.microWindow.microApp.clearDataListener();
1959
- this.microWindow.microApp.clearGlobalDataListener();
1876
+ this.microAppWindow.microApp.clearDataListener();
1877
+ this.microAppWindow.microApp.clearGlobalDataListener();
1960
1878
  this.injectedKeys.forEach((key) => {
1961
- Reflect.deleteProperty(this.microWindow, key);
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.microWindow.__MICRO_APP_UMD_MODE__ = true;
1893
+ this.microAppWindow.__MICRO_APP_UMD_MODE__ = true;
1976
1894
  this.recordUmdEffect();
1977
- recordDataCenterSnapshot(this.microWindow.microApp);
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.microWindow, key));
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.microWindow.microApp);
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 microWindow
2026
- * @param microWindow micro window
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
- inject(microWindow, appName, url) {
2031
- microWindow.__MICRO_APP_ENVIRONMENT__ = true;
2032
- microWindow.__MICRO_APP_NAME__ = appName;
2033
- microWindow.__MICRO_APP_PUBLIC_PATH__ = getEffectivePath(url);
2034
- microWindow.microApp = new EventCenterForMicroApp(appName);
2035
- microWindow.rawWindow = globalEnv.rawWindow;
2036
- microWindow.rawDocument = globalEnv.rawDocument;
2037
- microWindow.removeDomScope = removeDomScope;
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 eventHandler$1(event, element) {
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
- eventHandler$1(event, element);
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, macro, baseroute, }) {
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, this.macro));
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.actionsForCompletelyDestory();
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
- actionsForCompletelyDestory() {
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(this.container, this.name, lifeCycles.AFTERHIDDEN);
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
- Node.prototype.appendChild = function appendChild(newChild) {
2649
+ Element.prototype.appendChild = function appendChild(newChild) {
2589
2650
  return commonElementHander(this, newChild, null, globalEnv.rawAppendChild);
2590
2651
  };
2591
- Node.prototype.insertBefore = function insertBefore(newChild, refChild) {
2652
+ Element.prototype.insertBefore = function insertBefore(newChild, refChild) {
2592
2653
  return commonElementHander(this, newChild, refChild, globalEnv.rawInsertBefore);
2593
2654
  };
2594
- Node.prototype.replaceChild = function replaceChild(newChild, oldChild) {
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
- Node.prototype.removeChild = function removeChild(oldChild) {
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
- Node.prototype.appendChild = globalEnv.rawAppendChild;
2742
- Node.prototype.insertBefore = globalEnv.rawInsertBefore;
2743
- Node.prototype.replaceChild = globalEnv.rawReplaceChild;
2744
- Node.prototype.removeChild = globalEnv.rawRemoveChild;
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.getDisposeResult('keep-alive')) {
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.getDisposeResult('destroy') || this.getDisposeResult('destory'), () => {
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, keep-alive has priority over destroy
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 has priority over destroy
2871
- if (this.getDisposeResult('keep-alive')) {
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.getDisposeResult('destroy') || this.getDisposeResult('destory'), () => {
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).actionsForCompletelyDestory();
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.hasAttribute(name) || microApp[name]) && this.getAttribute(name) !== 'false';
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, macro must be same with micro-app element, if conflict, the one who executes first shall prevail
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, _c;
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