@micro-zoe/micro-app 1.0.0-rc.2 → 1.0.0-rc.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.esm.js CHANGED
@@ -1,4 +1,4 @@
1
- const version = '1.0.0-rc.2';
1
+ const version = '1.0.0-rc.3';
2
2
  // do not use isUndefined
3
3
  const isBrowser = typeof window !== 'undefined';
4
4
  // do not use isUndefined
@@ -15,7 +15,9 @@ const assign = Object.assign;
15
15
  // Object prototype methods
16
16
  const rawDefineProperty = Object.defineProperty;
17
17
  const rawDefineProperties = Object.defineProperties;
18
+ const rawToString = Object.prototype.toString;
18
19
  const rawHasOwnProperty = Object.prototype.hasOwnProperty;
20
+ const toTypeString = (value) => rawToString.call(value);
19
21
  // is Undefined
20
22
  function isUndefined(target) {
21
23
  return target === undefined;
@@ -42,15 +44,15 @@ function isFunction(target) {
42
44
  }
43
45
  // is PlainObject
44
46
  function isPlainObject(target) {
45
- return toString.call(target) === '[object Object]';
47
+ return toTypeString(target) === '[object Object]';
46
48
  }
47
49
  // is Object
48
50
  function isObject(target) {
49
- return typeof target === 'object';
51
+ return !isNull(target) && typeof target === 'object';
50
52
  }
51
53
  // is Promise
52
54
  function isPromise(target) {
53
- return toString.call(target) === '[object Promise]';
55
+ return toTypeString(target) === '[object Promise]';
54
56
  }
55
57
  // is bind function
56
58
  function isBoundFunction(target) {
@@ -87,40 +89,32 @@ function isNode(target) {
87
89
  return target instanceof Node || isNumber((_a = target) === null || _a === void 0 ? void 0 : _a.nodeType);
88
90
  }
89
91
  function isLinkElement(target) {
90
- var _a, _b;
91
- return ((_b = (_a = target) === null || _a === void 0 ? void 0 : _a.tagName) === null || _b === void 0 ? void 0 : _b.toUpperCase()) === 'LINK';
92
+ return toTypeString(target) === '[object HTMLLinkElement]';
92
93
  }
93
94
  function isStyleElement(target) {
94
- var _a, _b;
95
- return ((_b = (_a = target) === null || _a === void 0 ? void 0 : _a.tagName) === null || _b === void 0 ? void 0 : _b.toUpperCase()) === 'STYLE';
95
+ return toTypeString(target) === '[object HTMLStyleElement]';
96
96
  }
97
97
  function isScriptElement(target) {
98
- var _a, _b;
99
- return ((_b = (_a = target) === null || _a === void 0 ? void 0 : _a.tagName) === null || _b === void 0 ? void 0 : _b.toUpperCase()) === 'SCRIPT';
98
+ return toTypeString(target) === '[object HTMLScriptElement]';
100
99
  }
101
100
  function isIFrameElement(target) {
102
- var _a, _b;
103
- return ((_b = (_a = target) === null || _a === void 0 ? void 0 : _a.tagName) === null || _b === void 0 ? void 0 : _b.toUpperCase()) === 'IFRAME';
101
+ return toTypeString(target) === '[object HTMLIFrameElement]';
104
102
  }
105
103
  function isDivElement(target) {
106
- var _a, _b;
107
- return ((_b = (_a = target) === null || _a === void 0 ? void 0 : _a.tagName) === null || _b === void 0 ? void 0 : _b.toUpperCase()) === 'DIV';
104
+ return toTypeString(target) === '[object HTMLDivElement]';
108
105
  }
109
106
  function isImageElement(target) {
110
- var _a, _b;
111
- return ((_b = (_a = target) === null || _a === void 0 ? void 0 : _a.tagName) === null || _b === void 0 ? void 0 : _b.toUpperCase()) === 'IMG';
107
+ return toTypeString(target) === '[object HTMLImageElement]';
112
108
  }
113
109
  function isBaseElement(target) {
114
- var _a, _b;
115
- return ((_b = (_a = target) === null || _a === void 0 ? void 0 : _a.tagName) === null || _b === void 0 ? void 0 : _b.toUpperCase()) === 'BASE';
110
+ return toTypeString(target) === '[object HTMLBaseElement]';
116
111
  }
117
112
  function isMicroAppBody(target) {
118
- var _a, _b;
119
- return ((_b = (_a = target) === null || _a === void 0 ? void 0 : _a.tagName) === null || _b === void 0 ? void 0 : _b.toUpperCase()) === 'MICRO-APP-BODY';
113
+ return isElement(target) && target.tagName.toUpperCase() === 'MICRO-APP-BODY';
120
114
  }
121
115
  // is ProxyDocument
122
116
  function isProxyDocument(target) {
123
- return toString.call(target) === '[object ProxyDocument]';
117
+ return toTypeString(target) === '[object ProxyDocument]';
124
118
  }
125
119
  /**
126
120
  * format error log
@@ -666,7 +660,10 @@ class HTMLLoader {
666
660
  run(app, successCb) {
667
661
  const appName = app.name;
668
662
  const htmlUrl = app.ssrUrl || app.url;
669
- fetchSource(htmlUrl, appName, { cache: 'no-cache' }).then((htmlStr) => {
663
+ const htmlPromise = htmlUrl.includes('.js')
664
+ ? Promise.resolve(`<micro-app-head><script src='${htmlUrl}'></script></micro-app-head><micro-app-body></micro-app-body>`)
665
+ : fetchSource(htmlUrl, appName, { cache: 'no-cache' });
666
+ htmlPromise.then((htmlStr) => {
670
667
  if (!htmlStr) {
671
668
  const msg = 'html is empty, please check in detail';
672
669
  app.onerror(new Error(msg));
@@ -821,8 +818,8 @@ class CSSParser {
821
818
  return parseError("Declaration missing '}'", this.linkPath);
822
819
  return true;
823
820
  }
824
- matchAllDeclarations() {
825
- let cssValue = this.commonMatch(/^(?:url\(["']?(?:[^)"'}]+)["']?\)|[^}/])*/, true)[0];
821
+ matchAllDeclarations(nesting = 1) {
822
+ let cssValue = this.commonMatch(/^(?:url\(["']?(?:[^)"'}]+)["']?\)|[^{}/])*/, true)[0];
826
823
  if (cssValue) {
827
824
  if (!this.scopecssDisableNextLine &&
828
825
  (!this.scopecssDisable || this.scopecssDisableSelectors.length)) {
@@ -841,16 +838,30 @@ class CSSParser {
841
838
  }
842
839
  // reset scopecssDisableNextLine
843
840
  this.scopecssDisableNextLine = false;
844
- if (!this.cssText || this.cssText.charAt(0) === '}')
841
+ if (!this.cssText)
845
842
  return;
843
+ if (this.cssText.charAt(0) === '}') {
844
+ if (!nesting)
845
+ return;
846
+ if (nesting > 1) {
847
+ this.commonMatch(/}+/);
848
+ }
849
+ return this.matchAllDeclarations(nesting - 1);
850
+ }
846
851
  // extract comments in declarations
847
- if (this.cssText.charAt(0) === '/' && this.cssText.charAt(1) === '*') {
848
- this.matchComments();
852
+ if (this.cssText.charAt(0) === '/') {
853
+ if (this.cssText.charAt(1) === '*') {
854
+ this.matchComments();
855
+ }
856
+ else {
857
+ this.commonMatch(/\/+/);
858
+ }
849
859
  }
850
- else {
851
- this.commonMatch(/\/+/);
860
+ if (this.cssText.charAt(0) === '{') {
861
+ this.commonMatch(/{+\s*/);
862
+ nesting++;
852
863
  }
853
- return this.matchAllDeclarations();
864
+ return this.matchAllDeclarations(nesting);
854
865
  }
855
866
  matchAtRule() {
856
867
  if (this.cssText[0] !== '@')
@@ -1479,6 +1490,8 @@ const SCOPE_WINDOW_EVENT = [
1479
1490
  'unload',
1480
1491
  'unmount',
1481
1492
  'appstate-change',
1493
+ 'statechange',
1494
+ 'mounted',
1482
1495
  ];
1483
1496
  // on event bound to child app window
1484
1497
  const SCOPE_WINDOW_ON_EVENT = [
@@ -1487,6 +1500,7 @@ const SCOPE_WINDOW_ON_EVENT = [
1487
1500
  'onload',
1488
1501
  'onbeforeunload',
1489
1502
  'onunload',
1503
+ 'onerror'
1490
1504
  ];
1491
1505
  // event bound to child app document
1492
1506
  const SCOPE_DOCUMENT_EVENT = [
@@ -1952,6 +1966,8 @@ function runScript(address, app, scriptInfo, callback, replaceElement) {
1952
1966
  }
1953
1967
  catch (e) {
1954
1968
  console.error(`[micro-app from ${replaceElement ? 'runDynamicScript' : 'runScript'}] app ${app.name}: `, e, address);
1969
+ // throw error in with sandbox to parent app
1970
+ throw e;
1955
1971
  }
1956
1972
  }
1957
1973
  /**
@@ -2908,7 +2924,8 @@ function createMicroDocument(appName, proxyDocument) {
2908
2924
  class MicroDocument {
2909
2925
  static [Symbol.hasInstance](target) {
2910
2926
  let proto = target;
2911
- while (proto = Object.getPrototypeOf(proto)) {
2927
+ while (proto) {
2928
+ proto = Object.getPrototypeOf(proto);
2912
2929
  if (proto === MicroDocument.prototype) {
2913
2930
  return true;
2914
2931
  }
@@ -3807,52 +3824,53 @@ function createRouterApi() {
3807
3824
  */
3808
3825
  function createNavigationMethod(replace) {
3809
3826
  return function (to) {
3810
- const appName = formatAppName(to.name);
3811
- if (appName && isString(to.path)) {
3812
- /**
3813
- * active apps, exclude prerender app or hidden keep-alive app
3814
- * NOTE:
3815
- * 1. prerender app or hidden keep-alive app clear and record popstate event, so we cannot control app jump through the API
3816
- * 2. disable memory-router
3817
- */
3818
- /**
3819
- * TODO: 子应用开始渲染但是还没渲染完成
3820
- * 1、调用跳转改如何处理
3821
- * 2、iframe的沙箱还没初始化时执行跳转报错,如何处理。。。
3822
- * 3hidden app 是否支持跳转
3823
- */
3824
- if (getActiveApps({ excludeHiddenApp: true, excludePreRender: true }).includes(appName)) {
3825
- const app = appInstanceMap.get(appName);
3826
- const navigateAction = () => handleNavigate(appName, app, to, replace);
3827
- app.iframe ? app.sandBox.sandboxReady.then(navigateAction) : navigateAction();
3827
+ return new Promise((resolve, reject) => {
3828
+ const appName = formatAppName(to.name);
3829
+ if (appName && isString(to.path)) {
3830
+ /**
3831
+ * active apps, exclude prerender app or hidden keep-alive app
3832
+ * NOTE:
3833
+ * 1. prerender app or hidden keep-alive app clear and record popstate event, so we cannot control app jump through the API
3834
+ * 2. disable memory-router
3835
+ */
3836
+ /**
3837
+ * TODO: 子应用开始渲染但是还没渲染完成
3838
+ * 1、调用跳转改如何处理
3839
+ * 2iframe的沙箱还没初始化时执行跳转报错,如何处理。。。
3840
+ * 3、hidden app 是否支持跳转
3841
+ */
3842
+ if (getActiveApps({ excludeHiddenApp: true, excludePreRender: true }).includes(appName)) {
3843
+ const app = appInstanceMap.get(appName);
3844
+ resolve(app.sandBox.sandboxReady.then(() => handleNavigate(appName, app, to, replace)));
3845
+ }
3846
+ else {
3847
+ reject(logError('navigation failed, app does not exist or is inactive'));
3848
+ }
3849
+ // /**
3850
+ // * app not exit or unmounted, update browser URL with replaceState
3851
+ // * use base app location.origin as baseURL
3852
+ // * 应用不存在或已卸载,依然使用replaceState来更新浏览器地址 -- 不合理
3853
+ // */
3854
+ // /**
3855
+ // * TODO: 应用还没渲染或已经卸载最好不要支持跳转了,我知道这是因为解决一些特殊场景,但这么做是非常反直觉的
3856
+ // * 并且在新版本中有多种路由模式,如果应用不存在,我们根本无法知道是哪种模式,那么这里的操作就无意义了。
3857
+ // */
3858
+ // const rawLocation = globalEnv.rawWindow.location
3859
+ // const targetLocation = createURL(to.path, rawLocation.origin)
3860
+ // const targetFullPath = targetLocation.pathname + targetLocation.search + targetLocation.hash
3861
+ // if (getMicroPathFromURL(appName) !== targetFullPath) {
3862
+ // navigateWithRawHistory(
3863
+ // appName,
3864
+ // to.replace === false ? 'pushState' : 'replaceState',
3865
+ // targetLocation,
3866
+ // to.state,
3867
+ // )
3868
+ // }
3828
3869
  }
3829
3870
  else {
3830
- logWarn('navigation failed, app does not exist or is inactive');
3871
+ reject(logError(`navigation failed, name & path are required when use router.${replace ? 'replace' : 'push'}`));
3831
3872
  }
3832
- // /**
3833
- // * app not exit or unmounted, update browser URL with replaceState
3834
- // * use base app location.origin as baseURL
3835
- // * 应用不存在或已卸载,依然使用replaceState来更新浏览器地址 -- 不合理
3836
- // */
3837
- // /**
3838
- // * TODO: 应用还没渲染或已经卸载最好不要支持跳转了,我知道这是因为解决一些特殊场景,但这么做是非常反直觉的
3839
- // * 并且在新版本中有多种路由模式,如果应用不存在,我们根本无法知道是哪种模式,那么这里的操作就无意义了。
3840
- // */
3841
- // const rawLocation = globalEnv.rawWindow.location
3842
- // const targetLocation = createURL(to.path, rawLocation.origin)
3843
- // const targetFullPath = targetLocation.pathname + targetLocation.search + targetLocation.hash
3844
- // if (getMicroPathFromURL(appName) !== targetFullPath) {
3845
- // navigateWithRawHistory(
3846
- // appName,
3847
- // to.replace === false ? 'pushState' : 'replaceState',
3848
- // targetLocation,
3849
- // to.state,
3850
- // )
3851
- // }
3852
- }
3853
- else {
3854
- logError(`navigation failed, name & path are required when use router.${replace ? 'replace' : 'push'}`);
3855
- }
3873
+ });
3856
3874
  };
3857
3875
  }
3858
3876
  // create method of router.go/back/forward
@@ -4522,7 +4540,6 @@ function updateElementInfo(node, appName) {
4522
4540
  * 1. 测试baseURI和ownerDocument在with沙箱中是否正确
4523
4541
  * 经过验证with沙箱不能重写ownerDocument,否则react点击事件会触发两次
4524
4542
  * 2. with沙箱所有node设置__MICRO_APP_NAME__都使用updateElementInfo
4525
- * 3. 性能: defineProperty的性能肯定不如直接设置
4526
4543
  */
4527
4544
  rawDefineProperties(node, {
4528
4545
  baseURI: {
@@ -4536,14 +4553,57 @@ function updateElementInfo(node, appName) {
4536
4553
  },
4537
4554
  });
4538
4555
  if (isIframeSandbox(appName)) {
4539
- rawDefineProperty(node, 'ownerDocument', {
4540
- configurable: true,
4541
- get: () => proxyWindow.document,
4542
- });
4556
+ /**
4557
+ * If HTML built-in node belongs to base app, it needs to be handled separately for parentNode
4558
+ * Fix error for nuxt@2.x + ElementUI@2.x
4559
+ */
4560
+ if (node instanceof globalEnv.rawRootNode) {
4561
+ rawDefineProperty(node, 'parentNode', {
4562
+ configurable: true,
4563
+ get: createGetterForIframeParentNode(appName, globalEnv.rawParentNodeDesc, true)
4564
+ });
4565
+ }
4543
4566
  }
4544
4567
  }
4545
4568
  return node;
4546
4569
  }
4570
+ /**
4571
+ * patch iframe node parentNode
4572
+ * Scenes:
4573
+ * 1. iframe common node: patch Node.prototype.parentNode to hijack parentNode
4574
+ * 2. iframe HTML built-in node: belongs to base app, we should rewrite parentNode for every built-in node
4575
+ * NOTE:
4576
+ * 1. HTML built-in node parentNode cannot point to raw body, otherwise Vue2 will render failed
4577
+ * @param appName app name
4578
+ * @param parentNode parentNode Descriptor of iframe or browser
4579
+ * @param HTMLBuildInNode is HTML built-in node
4580
+ */
4581
+ function createGetterForIframeParentNode(appName, parentNodeDesc, HTMLBuildInNode) {
4582
+ return function () {
4583
+ var _a, _b, _c;
4584
+ /**
4585
+ * set current appName for hijack parentNode of html
4586
+ * NOTE:
4587
+ * 1. Is there a problem with setting the current appName in iframe mode
4588
+ */
4589
+ throttleDeferForSetAppName(appName);
4590
+ const result = parentNodeDesc.get.call(this);
4591
+ /**
4592
+ * If parentNode is <micro-app-body>, return rawDocument.body
4593
+ * Scenes:
4594
+ * 1. element-ui@2/lib/utils/vue-popper.js
4595
+ * if (this.popperElm.parentNode === document.body) ...
4596
+ * WARNING:
4597
+ * Will it cause other problems ?
4598
+ * e.g. target.parentNode.remove(target)
4599
+ */
4600
+ if (!HTMLBuildInNode &&
4601
+ isMicroAppBody(result) && ((_a = appInstanceMap.get(appName)) === null || _a === void 0 ? void 0 : _a.container)) {
4602
+ return ((_c = (_b = microApp.options).getRootElementParentNode) === null || _c === void 0 ? void 0 : _c.call(_b, this, appName)) || globalEnv.rawDocument.body;
4603
+ }
4604
+ return result;
4605
+ };
4606
+ }
4547
4607
 
4548
4608
  /**
4549
4609
  * https://developer.mozilla.org/en-US/docs/Web/API/fetch
@@ -4662,17 +4722,20 @@ class WithSandBox {
4662
4722
  // Properties newly added to microAppWindow
4663
4723
  this.injectedKeys = new Set();
4664
4724
  this.microAppWindow = new EventTarget(); // Proxy target
4665
- this.adapter = new Adapter();
4666
- // get scopeProperties and escapeProperties from plugins
4667
- this.getSpecialProperties(appName);
4668
- // create location, history for child app
4669
- this.patchRouter(appName, url, this.microAppWindow);
4670
- // patch window of child app
4671
- this.windowEffect = patchWindow(appName, this.microAppWindow, this);
4672
- // patch document of child app
4673
- this.documentEffect = patchDocument(appName, this.microAppWindow, this);
4674
- // inject global properties
4675
- this.initStaticGlobalKeys(appName, url, this.microAppWindow);
4725
+ this.patchWith((resolve) => {
4726
+ this.adapter = new Adapter();
4727
+ // get scopeProperties and escapeProperties from plugins
4728
+ this.getSpecialProperties(appName);
4729
+ // create location, history for child app
4730
+ this.patchRouter(appName, url, this.microAppWindow);
4731
+ // patch window of child app
4732
+ this.windowEffect = patchWindow(appName, this.microAppWindow, this);
4733
+ // patch document of child app
4734
+ this.documentEffect = patchDocument(appName, this.microAppWindow, this);
4735
+ // inject global properties
4736
+ this.initStaticGlobalKeys(appName, url, this.microAppWindow);
4737
+ resolve();
4738
+ });
4676
4739
  }
4677
4740
  /**
4678
4741
  * open sandbox and perform some initial actions
@@ -4690,7 +4753,9 @@ class WithSandBox {
4690
4753
  this.initRouteState(defaultPage);
4691
4754
  // unique listener of popstate event for sub app
4692
4755
  this.removeHistoryListener = addHistoryListener(this.microAppWindow.__MICRO_APP_NAME__);
4693
- this.microAppWindow.__MICRO_APP_BASE_ROUTE__ = this.microAppWindow.__MICRO_APP_BASE_URL__ = baseroute;
4756
+ if (isRouterModeCustom(this.microAppWindow.__MICRO_APP_NAME__)) {
4757
+ this.microAppWindow.__MICRO_APP_BASE_ROUTE__ = this.microAppWindow.__MICRO_APP_BASE_URL__ = baseroute;
4758
+ }
4694
4759
  /* --- memory router part --- end */
4695
4760
  /**
4696
4761
  * Target: Ensure default mode action exactly same to first time when render again
@@ -4888,6 +4953,9 @@ class WithSandBox {
4888
4953
  markUmdMode(state) {
4889
4954
  this.microAppWindow.__MICRO_APP_UMD_MODE__ = state;
4890
4955
  }
4956
+ patchWith(cb) {
4957
+ this.sandboxReady = new Promise((resolve) => cb(resolve));
4958
+ }
4891
4959
  // properties associated with the native window
4892
4960
  setMappingPropertiesWithRawDescriptor(microAppWindow) {
4893
4961
  let topValue, parentValue;
@@ -5059,6 +5127,9 @@ class WithSandBox {
5059
5127
  actionBeforeExecScripts(container) {
5060
5128
  this.patchStaticElement(container);
5061
5129
  }
5130
+ setStaticAppState(state) {
5131
+ this.microAppWindow.__MICRO_APP_STATE__ = state;
5132
+ }
5062
5133
  }
5063
5134
  WithSandBox.activeCount = 0; // number of active sandbox
5064
5135
 
@@ -5454,7 +5525,10 @@ function patchDocumentProperty(appName, microAppWindow, sandbox) {
5454
5525
  rawDefineProperty(microDocument, tagName, {
5455
5526
  enumerable: true,
5456
5527
  configurable: true,
5457
- get: () => rawDocument[tagName],
5528
+ get: () => {
5529
+ throttleDeferForSetAppName(appName);
5530
+ return rawDocument[tagName];
5531
+ },
5458
5532
  set: (value) => { rawDocument[tagName] = value; },
5459
5533
  });
5460
5534
  });
@@ -5626,7 +5700,8 @@ function patchIframeNode(appName, microAppWindow, sandbox) {
5626
5700
  const rawMicroInsertAdjacentElement = microRootElement.prototype.insertAdjacentElement;
5627
5701
  const rawMicroCloneNode = microRootNode.prototype.cloneNode;
5628
5702
  const rawInnerHTMLDesc = Object.getOwnPropertyDescriptor(microRootElement.prototype, 'innerHTML');
5629
- const rawParentNodeLDesc = Object.getOwnPropertyDescriptor(microRootNode.prototype, 'parentNode');
5703
+ const rawParentNodeDesc = Object.getOwnPropertyDescriptor(microRootNode.prototype, 'parentNode');
5704
+ const rawOwnerDocumentDesc = Object.getOwnPropertyDescriptor(microRootNode.prototype, 'ownerDocument');
5630
5705
  const isPureNode = (target) => {
5631
5706
  return (isScriptElement(target) || isBaseElement(target)) && target.__PURE_ELEMENT__;
5632
5707
  };
@@ -5718,6 +5793,15 @@ function patchIframeNode(appName, microAppWindow, sandbox) {
5718
5793
  const clonedNode = rawMicroCloneNode.call(this, deep);
5719
5794
  return updateElementInfo(clonedNode, appName);
5720
5795
  };
5796
+ rawDefineProperty(microRootNode.prototype, 'ownerDocument', {
5797
+ configurable: true,
5798
+ enumerable: true,
5799
+ get() {
5800
+ return this.__PURE_ELEMENT__
5801
+ ? rawOwnerDocumentDesc.get.call(this)
5802
+ : microDocument;
5803
+ },
5804
+ });
5721
5805
  rawDefineProperty(microRootElement.prototype, 'innerHTML', {
5722
5806
  configurable: true,
5723
5807
  enumerable: true,
@@ -5737,29 +5821,7 @@ function patchIframeNode(appName, microAppWindow, sandbox) {
5737
5821
  rawDefineProperty(microRootNode.prototype, 'parentNode', {
5738
5822
  configurable: true,
5739
5823
  enumerable: true,
5740
- get() {
5741
- var _a, _b, _c;
5742
- /**
5743
- * set current appName for hijack parentNode of html
5744
- * NOTE:
5745
- * 1. Is there a problem with setting the current appName in iframe mode
5746
- */
5747
- throttleDeferForSetAppName(appName);
5748
- const result = rawParentNodeLDesc.get.call(this);
5749
- /**
5750
- * If parentNode is <micro-app-body>, return rawDocument.body
5751
- * Scenes:
5752
- * 1. element-ui@2/lib/utils/vue-popper.js
5753
- * if (this.popperElm.parentNode === document.body) ...
5754
- * WARNING:
5755
- * Will it cause other problems ?
5756
- * e.g. target.parentNode.remove(target)
5757
- */
5758
- if (isMicroAppBody(result) && ((_a = appInstanceMap.get(appName)) === null || _a === void 0 ? void 0 : _a.container)) {
5759
- return ((_c = (_b = microApp.options).getRootElementParentNode) === null || _c === void 0 ? void 0 : _c.call(_b, this, appName)) || rawDocument.body;
5760
- }
5761
- return result;
5762
- },
5824
+ get: createGetterForIframeParentNode(appName, rawParentNodeDesc),
5763
5825
  });
5764
5826
  // Adapt to new image(...) scene
5765
5827
  const ImageProxy = new Proxy(microAppWindow.Image, {
@@ -5910,7 +5972,9 @@ class IframeSandbox {
5910
5972
  this.initRouteState(defaultPage);
5911
5973
  // unique listener of popstate event for child app
5912
5974
  this.removeHistoryListener = addHistoryListener(this.microAppWindow.__MICRO_APP_NAME__);
5913
- this.microAppWindow.__MICRO_APP_BASE_ROUTE__ = this.microAppWindow.__MICRO_APP_BASE_URL__ = baseroute;
5975
+ if (isRouterModeCustom(this.microAppWindow.__MICRO_APP_NAME__)) {
5976
+ this.microAppWindow.__MICRO_APP_BASE_ROUTE__ = this.microAppWindow.__MICRO_APP_BASE_URL__ = baseroute;
5977
+ }
5914
5978
  /* --- memory router part --- end */
5915
5979
  /**
5916
5980
  * create base element to iframe
@@ -6163,6 +6227,9 @@ class IframeSandbox {
6163
6227
  actionBeforeExecScripts(container) {
6164
6228
  this.patchStaticElement(container);
6165
6229
  }
6230
+ setStaticAppState(state) {
6231
+ this.microAppWindow.__MICRO_APP_STATE__ = state;
6232
+ }
6166
6233
  }
6167
6234
  IframeSandbox.activeCount = 0; // number of active sandbox
6168
6235
 
@@ -6175,6 +6242,7 @@ class CreateApp {
6175
6242
  this.loadSourceLevel = 0;
6176
6243
  this.umdHookMount = null;
6177
6244
  this.umdHookUnmount = null;
6245
+ this.lifeCycleState = null;
6178
6246
  this.umdMode = false;
6179
6247
  // TODO: 类型优化,加上iframe沙箱
6180
6248
  this.sandBox = null;
@@ -6284,6 +6352,10 @@ class CreateApp {
6284
6352
  this.container = container;
6285
6353
  // mount before prerender exec mount (loading source), set isPrerender to false
6286
6354
  this.isPrerender = false;
6355
+ // dispatch state event to micro app
6356
+ dispatchCustomEventToMicroApp(this, 'statechange', {
6357
+ appState: appStates.LOADING
6358
+ });
6287
6359
  // reset app state to LOADING
6288
6360
  return this.setAppState(appStates.LOADING);
6289
6361
  }
@@ -6333,7 +6405,10 @@ class CreateApp {
6333
6405
  this.inline = this.getInlineModeState(inline);
6334
6406
  this.fiber = fiber;
6335
6407
  this.routerMode = routerMode;
6336
- const dispatchBeforeMount = () => dispatchLifecyclesEvent(this.container, this.name, lifeCycles.BEFOREMOUNT);
6408
+ const dispatchBeforeMount = () => {
6409
+ this.setLifeCycleState(lifeCycles.BEFOREMOUNT);
6410
+ dispatchLifecyclesEvent(this.container, this.name, lifeCycles.BEFOREMOUNT);
6411
+ };
6337
6412
  if (this.isPrerender) {
6338
6413
  ((_d = this.preRenderEvents) !== null && _d !== void 0 ? _d : (this.preRenderEvents = [])).push(dispatchBeforeMount);
6339
6414
  }
@@ -6341,6 +6416,10 @@ class CreateApp {
6341
6416
  dispatchBeforeMount();
6342
6417
  }
6343
6418
  this.setAppState(appStates.MOUNTING);
6419
+ // dispatch state event to micro app
6420
+ dispatchCustomEventToMicroApp(this, 'statechange', {
6421
+ appState: appStates.MOUNTING
6422
+ });
6344
6423
  // TODO: 将所有cloneContainer中的'as Element'去掉,兼容shadowRoot的场景
6345
6424
  cloneContainer(this.container, this.source.html, !this.umdMode);
6346
6425
  (_e = this.sandBox) === null || _e === void 0 ? void 0 : _e.start({
@@ -6395,8 +6474,8 @@ class CreateApp {
6395
6474
  }
6396
6475
  }
6397
6476
  };
6398
- // TODO: any替换为iframe沙箱类型
6399
- this.iframe ? this.sandBox.sandboxReady.then(nextAction) : nextAction();
6477
+ // TODO: 可优化?
6478
+ this.sandBox ? this.sandBox.sandboxReady.then(nextAction) : nextAction();
6400
6479
  }
6401
6480
  /**
6402
6481
  * handle for promise umdHookMount
@@ -6434,6 +6513,13 @@ class CreateApp {
6434
6513
  this.setAppState(appStates.MOUNTED);
6435
6514
  // call window.onmount of child app
6436
6515
  execMicroAppGlobalHook(this.getMicroAppGlobalHook(microGlobalEvent.ONMOUNT), this.name, microGlobalEvent.ONMOUNT, microApp.getData(this.name, true));
6516
+ // dispatch state event to micro app
6517
+ dispatchCustomEventToMicroApp(this, 'statechange', {
6518
+ appState: appStates.MOUNTED
6519
+ });
6520
+ // dispatch mounted event to micro app
6521
+ dispatchCustomEventToMicroApp(this, 'mounted');
6522
+ this.setLifeCycleState(lifeCycles.MOUNTED);
6437
6523
  // dispatch event mounted to parent
6438
6524
  dispatchLifecyclesEvent(this.container, this.name, lifeCycles.MOUNTED);
6439
6525
  /**
@@ -6473,6 +6559,10 @@ class CreateApp {
6473
6559
  catch (e) {
6474
6560
  logError('An error occurred in window.unmount \n', this.name, e);
6475
6561
  }
6562
+ // dispatch state event to micro app
6563
+ dispatchCustomEventToMicroApp(this, 'statechange', {
6564
+ appState: appStates.UNMOUNT
6565
+ });
6476
6566
  // dispatch unmount event to micro app
6477
6567
  dispatchCustomEventToMicroApp(this, 'unmount');
6478
6568
  // call window.onunmount of child app
@@ -6533,6 +6623,7 @@ class CreateApp {
6533
6623
  destroy,
6534
6624
  clearData: clearData || destroy,
6535
6625
  });
6626
+ this.setLifeCycleState(lifeCycles.UNMOUNT);
6536
6627
  // dispatch unmount event to base app
6537
6628
  dispatchLifecyclesEvent(this.container, this.name, lifeCycles.UNMOUNT);
6538
6629
  this.clearOptions(destroy);
@@ -6573,6 +6664,7 @@ class CreateApp {
6573
6664
  dispatchCustomEventToMicroApp(this, 'appstate-change', {
6574
6665
  appState: 'afterhidden',
6575
6666
  });
6667
+ this.setLifeCycleState(lifeCycles.AFTERHIDDEN);
6576
6668
  // dispatch afterHidden event to base app
6577
6669
  dispatchLifecyclesEvent(this.container, this.name, lifeCycles.AFTERHIDDEN);
6578
6670
  if (this.routerMode !== ROUTER_MODE_CUSTOM) {
@@ -6616,6 +6708,7 @@ class CreateApp {
6616
6708
  dispatchCustomEventToMicroApp(this, 'appstate-change', {
6617
6709
  appState: 'aftershow',
6618
6710
  });
6711
+ this.setLifeCycleState(lifeCycles.AFTERSHOW);
6619
6712
  // dispatch afterShow event to base app
6620
6713
  dispatchLifecyclesEvent(this.container, this.name, lifeCycles.AFTERSHOW);
6621
6714
  }
@@ -6624,6 +6717,11 @@ class CreateApp {
6624
6717
  * @param e Error
6625
6718
  */
6626
6719
  onerror(e) {
6720
+ this.setLifeCycleState(lifeCycles.ERROR);
6721
+ // dispatch state event to micro app
6722
+ dispatchCustomEventToMicroApp(this, 'statechange', {
6723
+ appState: appStates.LOAD_FAILED
6724
+ });
6627
6725
  dispatchLifecyclesEvent(this.container, this.name, lifeCycles.ERROR, e);
6628
6726
  }
6629
6727
  /**
@@ -6644,12 +6742,23 @@ class CreateApp {
6644
6742
  }
6645
6743
  // set app state
6646
6744
  setAppState(state) {
6745
+ var _a;
6647
6746
  this.state = state;
6747
+ // set window.__MICRO_APP_STATE__
6748
+ (_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.setStaticAppState(state);
6648
6749
  }
6649
6750
  // get app state
6650
6751
  getAppState() {
6651
6752
  return this.state;
6652
6753
  }
6754
+ // set app lifeCycleState
6755
+ setLifeCycleState(state) {
6756
+ this.lifeCycleState = state;
6757
+ }
6758
+ // get app lifeCycleState
6759
+ getLifeCycleState() {
6760
+ return this.lifeCycleState || '';
6761
+ }
6653
6762
  // set keep-alive state
6654
6763
  setKeepAliveState(state) {
6655
6764
  this.keepAliveState = state;
@@ -7090,6 +7199,7 @@ function patchElementAndDocument() {
7090
7199
  const currentAppName = getCurrentAppName();
7091
7200
  Array.from(this.children).forEach((child) => {
7092
7201
  if (isElement(child) && currentAppName) {
7202
+ // TODO: 使用updateElementInfo进行更新
7093
7203
  child.__MICRO_APP_NAME__ = currentAppName;
7094
7204
  }
7095
7205
  });
@@ -7106,7 +7216,7 @@ function patchElementAndDocument() {
7106
7216
  * 1. element-ui@2/lib/utils/popper.js
7107
7217
  * // root is child app window, so root.document is proxyDocument or microDocument
7108
7218
  * if (element.parentNode === root.document) ...
7109
- */
7219
+ */
7110
7220
  const currentAppName = getCurrentAppName();
7111
7221
  if (currentAppName && this === globalEnv.rawDocument.firstElementChild) {
7112
7222
  const microDocument = (_c = (_b = (_a = appInstanceMap.get(currentAppName)) === null || _a === void 0 ? void 0 : _a.sandBox) === null || _b === void 0 ? void 0 : _b.proxyWindow) === null || _c === void 0 ? void 0 : _c.document;
@@ -8278,6 +8388,20 @@ function renderApp(options) {
8278
8388
  container.appendChild(microAppElement);
8279
8389
  });
8280
8390
  }
8391
+ /**
8392
+ * get app state
8393
+ * @param appName app.name
8394
+ * @returns app.state
8395
+ */
8396
+ function getAppStatus(appName) {
8397
+ const app = appInstanceMap.get(formatAppName(appName));
8398
+ if (app) {
8399
+ return app.getLifeCycleState();
8400
+ }
8401
+ else {
8402
+ logWarn(`app ${appName} does not exist`);
8403
+ }
8404
+ }
8281
8405
  class MicroApp extends EventCenterForBaseApp {
8282
8406
  constructor() {
8283
8407
  super(...arguments);
@@ -8292,6 +8416,7 @@ class MicroApp extends EventCenterForBaseApp {
8292
8416
  this.getAllApps = getAllApps;
8293
8417
  this.reload = reload;
8294
8418
  this.renderApp = renderApp;
8419
+ this.getAppStatus = getAppStatus;
8295
8420
  }
8296
8421
  start(options) {
8297
8422
  var _a, _b;
@@ -8347,5 +8472,5 @@ class MicroApp extends EventCenterForBaseApp {
8347
8472
  const microApp = new MicroApp();
8348
8473
 
8349
8474
  export default microApp;
8350
- export { EventCenterForMicroApp, MicroApp, getActiveApps, getAllApps, preFetch, pureCreateElement, reload, removeDomScope, renderApp, unmountAllApps, unmountApp, version };
8475
+ export { EventCenterForMicroApp, MicroApp, getActiveApps, getAllApps, getAppStatus, preFetch, pureCreateElement, reload, removeDomScope, renderApp, unmountAllApps, unmountApp, version };
8351
8476
  //# sourceMappingURL=index.esm.js.map