@micro-zoe/micro-app 0.6.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.esm.js CHANGED
@@ -1,4 +1,4 @@
1
- const version = '0.6.1';
1
+ const version = '0.8.0';
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;
@@ -238,10 +252,6 @@ function getCurrentAppName() {
238
252
  function removeDomScope() {
239
253
  setCurrentAppName(null);
240
254
  }
241
- // is safari browser
242
- function isSafari() {
243
- return /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent);
244
- }
245
255
  /**
246
256
  * Create pure elements
247
257
  */
@@ -290,6 +300,12 @@ function isUniqueElement(key) {
290
300
  function getRootContainer(target) {
291
301
  return (isShadowRoot(target) ? target.host : target);
292
302
  }
303
+ /**
304
+ * trim start & end
305
+ */
306
+ function trim(str) {
307
+ return str ? str.replace(/^\s+|\s+$/g, '') : '';
308
+ }
293
309
 
294
310
  var ObservedAttrName;
295
311
  (function (ObservedAttrName) {
@@ -326,6 +342,7 @@ var keepAliveStates;
326
342
  keepAliveStates["KEEP_ALIVE_SHOW"] = "KEEP_ALIVE_SHOW";
327
343
  keepAliveStates["KEEP_ALIVE_HIDDEN"] = "KEEP_ALIVE_HIDDEN";
328
344
  })(keepAliveStates || (keepAliveStates = {}));
345
+ 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
346
 
330
347
  /**
331
348
  * fetch source of html, js, css
@@ -342,215 +359,355 @@ function fetchSource(url, appName = null, options = {}) {
342
359
  });
343
360
  }
344
361
 
345
- const globalEnv = {};
346
- function initGlobalEnv() {
347
- if (isBrowser) {
348
- /**
349
- * save patch raw methods
350
- * pay attention to this binding
351
- */
352
- const rawSetAttribute = Element.prototype.setAttribute;
353
- const rawAppendChild = Element.prototype.appendChild;
354
- const rawInsertBefore = Element.prototype.insertBefore;
355
- const rawReplaceChild = Element.prototype.replaceChild;
356
- const rawRemoveChild = Element.prototype.removeChild;
357
- const rawAppend = Element.prototype.append;
358
- const rawPrepend = Element.prototype.prepend;
359
- const rawCloneNode = Element.prototype.cloneNode;
360
- const rawCreateElement = Document.prototype.createElement;
361
- const rawCreateElementNS = Document.prototype.createElementNS;
362
- const rawCreateDocumentFragment = Document.prototype.createDocumentFragment;
363
- const rawQuerySelector = Document.prototype.querySelector;
364
- const rawQuerySelectorAll = Document.prototype.querySelectorAll;
365
- const rawGetElementById = Document.prototype.getElementById;
366
- const rawGetElementsByClassName = Document.prototype.getElementsByClassName;
367
- const rawGetElementsByTagName = Document.prototype.getElementsByTagName;
368
- const rawGetElementsByName = Document.prototype.getElementsByName;
369
- const rawWindow = Function('return window')();
370
- const rawDocument = Function('return document')();
371
- const supportModuleScript = isSupportModuleScript();
372
- const templateStyle = rawDocument.body.querySelector('#micro-app-template-style');
373
- /**
374
- * save effect raw methods
375
- * pay attention to this binding, especially setInterval, setTimeout, clearInterval, clearTimeout
376
- */
377
- const rawWindowAddEventListener = rawWindow.addEventListener;
378
- const rawWindowRemoveEventListener = rawWindow.removeEventListener;
379
- const rawSetInterval = rawWindow.setInterval;
380
- const rawSetTimeout = rawWindow.setTimeout;
381
- const rawClearInterval = rawWindow.clearInterval;
382
- const rawClearTimeout = rawWindow.clearTimeout;
383
- const rawDocumentAddEventListener = rawDocument.addEventListener;
384
- const rawDocumentRemoveEventListener = rawDocument.removeEventListener;
385
- // mark current application as base application
386
- window.__MICRO_APP_BASE_APPLICATION__ = true;
387
- Object.assign(globalEnv, {
388
- // source/patch
389
- rawSetAttribute,
390
- rawAppendChild,
391
- rawInsertBefore,
392
- rawReplaceChild,
393
- rawRemoveChild,
394
- rawAppend,
395
- rawPrepend,
396
- rawCloneNode,
397
- rawCreateElement,
398
- rawCreateElementNS,
399
- rawCreateDocumentFragment,
400
- rawQuerySelector,
401
- rawQuerySelectorAll,
402
- rawGetElementById,
403
- rawGetElementsByClassName,
404
- rawGetElementsByTagName,
405
- rawGetElementsByName,
406
- // common global vars
407
- rawWindow,
408
- rawDocument,
409
- supportModuleScript,
410
- templateStyle,
411
- // sandbox/effect
412
- rawWindowAddEventListener,
413
- rawWindowRemoveEventListener,
414
- rawSetInterval,
415
- rawSetTimeout,
416
- rawClearInterval,
417
- rawClearTimeout,
418
- rawDocumentAddEventListener,
419
- rawDocumentRemoveEventListener,
420
- });
421
- }
422
- }
423
-
424
- // https://developer.mozilla.org/zh-CN/docs/Web/API/CSSRule
425
- var CSSRuleType;
426
- (function (CSSRuleType) {
427
- CSSRuleType[CSSRuleType["STYLE_RULE"] = 1] = "STYLE_RULE";
428
- CSSRuleType[CSSRuleType["MEDIA_RULE"] = 4] = "MEDIA_RULE";
429
- CSSRuleType[CSSRuleType["SUPPORTS_RULE"] = 12] = "SUPPORTS_RULE";
430
- })(CSSRuleType || (CSSRuleType = {}));
431
- /**
432
- * Bind css scope
433
- * Special case:
434
- * 1. html-abc | abc-html
435
- * 2. html body.abc
436
- * 3. abchtml | htmlabc | abcbody | bodyabc
437
- * 4. html + body | html > body | html.body | html[name=xx] | body[name=xx]
438
- * 5. xxx, html xxx, body xxx
439
- *
440
- * TODO: BUG
441
- .test-b {
442
- border: 1px solid var(--color-a);
443
- border-bottom-color: var(--color-b);
444
- }
445
- */
446
- function scopedStyleRule(rule, prefix) {
447
- const { selectorText, cssText } = rule;
448
- if (/^((html[\s>~,]+body)|(html|body|:root))$/.test(selectorText)) {
449
- return cssText.replace(/^((html[\s>~,]+body)|(html|body|:root))/, prefix);
450
- }
451
- else if (selectorText === '*') {
452
- return cssText.replace('*', `${prefix} *`);
453
- }
454
- const builtInRootSelectorRE = /(^|\s+)((html[\s>~]+body)|(html|body|:root))(?=[\s>~]+|$)/;
455
- return cssText.replace(/^[\s\S]+{/, (selectors) => {
456
- return selectors.replace(/(^|,)([^,]+)/g, (all, $1, $2) => {
457
- if (builtInRootSelectorRE.test($2)) {
458
- // body[name=xx]|body.xx|body#xx etc. do not need to handle
459
- return all.replace(builtInRootSelectorRE, prefix);
460
- }
461
- return `${$1} ${prefix} ${$2.replace(/^\s*/, '')}`;
462
- });
463
- });
362
+ // common reg
363
+ const rootSelectorREG = /(^|\s+)(html|:root)(?=[\s>~[.#:]+|$)/;
364
+ const bodySelectorREG = /(^|\s+)((html[\s>~]+body)|body)(?=[\s>~[.#:]+|$)/;
365
+ const cssUrlREG = /url\(["']?([^)"']+)["']?\)/gm;
366
+ function parseError(msg, linkpath) {
367
+ msg = linkpath ? `${linkpath}:${msg}` : msg;
368
+ const err = new Error(msg);
369
+ err.reason = msg;
370
+ if (linkpath) {
371
+ err.filename = linkpath;
372
+ }
373
+ throw err;
464
374
  }
465
375
  /**
466
- * Complete static resource address
467
- * @param cssText css content
468
- * @param baseURI domain name
469
- * @param textContent origin content
470
- * @param linkpath link resource address, if it is the style converted from link, it will have linkpath
376
+ * Reference resources https://github.com/reworkcss/css
377
+ * CSSParser mainly deals with 3 scenes: styleRule, @, and comment
378
+ * And scopecss deals with 2 scenes: selector & url
379
+ * It can also disable scopecss with inline comments
471
380
  */
472
- function scopedHost(cssText, baseURI, textContent, linkpath) {
473
- return cssText.replace(/url\(["']?([^)"']+)["']?\)/gm, (all, $1) => {
474
- if (/^(data|blob):/.test($1)) {
475
- return all;
476
- }
477
- else if (/^(https?:)?\/\//.test($1)) {
478
- if (isSafari()) {
479
- const purePath = $1.replace(/^https?:/, '');
480
- if (textContent.indexOf(purePath) === -1) {
481
- $1 = $1.replace(window.location.origin, '');
482
- }
483
- else {
381
+ class CSSParser {
382
+ constructor() {
383
+ this.cssText = ''; // css content
384
+ this.prefix = ''; // prefix as micro-app[name=xxx]
385
+ this.baseURI = ''; // domain name
386
+ this.linkpath = ''; // link resource address, if it is the style converted from link, it will have linkpath
387
+ this.result = ''; // parsed cssText
388
+ this.scopecssDisable = false; // use block comments /* scopecss-disable */ to disable scopecss in your file, and use /* scopecss-enable */ to enable scopecss
389
+ this.scopecssDisableSelectors = []; // disable or enable scopecss for specific selectors
390
+ this.scopecssDisableNextLine = false; // use block comments /* scopecss-disable-next-line */ to disable scopecss on a specific line
391
+ // https://developer.mozilla.org/en-US/docs/Web/API/CSSMediaRule
392
+ this.mediaRule = this.createMatcherForAtRuleWithChildRule(/^@media *([^{]+)/, 'media');
393
+ // https://developer.mozilla.org/en-US/docs/Web/API/CSSSupportsRule
394
+ this.supportsRule = this.createMatcherForAtRuleWithChildRule(/^@supports *([^{]+)/, 'supports');
395
+ this.documentRule = this.createMatcherForAtRuleWithChildRule(/^@([-\w]+)?document *([^{]+)/, 'document');
396
+ this.hostRule = this.createMatcherForAtRuleWithChildRule(/^@host\s*/, 'host');
397
+ // https://developer.mozilla.org/en-US/docs/Web/API/CSSImportRule
398
+ this.importRule = this.createMatcherForNoneBraceAtRule('import');
399
+ // Removed in most browsers
400
+ this.charsetRule = this.createMatcherForNoneBraceAtRule('charset');
401
+ // https://developer.mozilla.org/en-US/docs/Web/API/CSSNamespaceRule
402
+ this.namespaceRule = this.createMatcherForNoneBraceAtRule('namespace');
403
+ }
404
+ exec(cssText, prefix, baseURI, linkpath) {
405
+ this.cssText = cssText;
406
+ this.prefix = prefix;
407
+ this.baseURI = baseURI;
408
+ this.linkpath = linkpath || '';
409
+ this.matchRules();
410
+ return this.result;
411
+ }
412
+ reset() {
413
+ this.cssText = this.prefix = this.baseURI = this.linkpath = this.result = '';
414
+ this.scopecssDisable = this.scopecssDisableNextLine = false;
415
+ this.scopecssDisableSelectors = [];
416
+ }
417
+ // core action for match rules
418
+ matchRules() {
419
+ this.matchLeadingSpaces();
420
+ this.matchComments();
421
+ while (this.cssText.length &&
422
+ this.cssText.charAt(0) !== '}' &&
423
+ (this.matchAtRule() || this.matchStyleRule())) {
424
+ this.matchComments();
425
+ }
426
+ }
427
+ // https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleRule
428
+ matchStyleRule() {
429
+ const selectorList = this.formatSelector();
430
+ // reset scopecssDisableNextLine
431
+ this.scopecssDisableNextLine = false;
432
+ if (!selectorList)
433
+ return parseError('selector missing', this.linkpath);
434
+ this.result += selectorList.join(', ');
435
+ this.matchComments();
436
+ this.styleDeclarations();
437
+ this.matchLeadingSpaces();
438
+ return true;
439
+ }
440
+ // https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration
441
+ styleDeclarations() {
442
+ if (!this.matchOpenBrace())
443
+ return parseError("Declaration missing '{'", this.linkpath);
444
+ this.matchComments();
445
+ while (this.styleDeclaration()) {
446
+ this.matchComments();
447
+ }
448
+ if (!this.matchCloseBrace())
449
+ return parseError("Declaration missing '}'", this.linkpath);
450
+ return true;
451
+ }
452
+ // match one styleDeclaration at a time
453
+ styleDeclaration() {
454
+ // css property
455
+ if (!this.commonMatch(/^(\*?[-#\/\*\\\w]+(\[[0-9a-z_-]+\])?)\s*/))
456
+ return false;
457
+ // match :
458
+ if (!this.commonMatch(/^:\s*/))
459
+ return parseError("property missing ':'", this.linkpath);
460
+ // match css value
461
+ const r = this.commonMatch(/^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^\)]*?\)|[^};])+)/, true);
462
+ let cssValue = r ? r[0] : '';
463
+ if (!this.scopecssDisableNextLine &&
464
+ (!this.scopecssDisable || this.scopecssDisableSelectors.length)) {
465
+ cssValue = cssValue.replace(cssUrlREG, (all, $1) => {
466
+ if (/^((data|blob):|#)/.test($1) || /^(https?:)?\/\//.test($1)) {
484
467
  return all;
485
468
  }
469
+ // ./a/b.png ../a/b.png a/b.png
470
+ if (/^((\.\.?\/)|[^/])/.test($1) && this.linkpath) {
471
+ this.baseURI = getLinkFileDir(this.linkpath);
472
+ }
473
+ return `url("${CompletionPath($1, this.baseURI)}")`;
474
+ });
475
+ }
476
+ // reset scopecssDisableNextLine
477
+ this.scopecssDisableNextLine = false;
478
+ this.result += cssValue;
479
+ this.matchLeadingSpaces();
480
+ this.commonMatch(/^[;\s]*/);
481
+ return true;
482
+ }
483
+ formatSelector() {
484
+ const m = this.commonMatch(/^([^{]+)/, true);
485
+ if (!m)
486
+ return false;
487
+ return trim(m[0])
488
+ .replace(/\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*\/+/g, '')
489
+ .replace(/"(?:\\"|[^"])*"|'(?:\\'|[^'])*'/g, (r) => {
490
+ return r.replace(/,/g, '\u200C');
491
+ })
492
+ .split(/\s*(?![^(]*\)),\s*/)
493
+ .map((s) => {
494
+ const selectorText = s.replace(/\u200C/g, ',');
495
+ if (this.scopecssDisableNextLine) {
496
+ return selectorText;
497
+ }
498
+ else if (this.scopecssDisable) {
499
+ if (!this.scopecssDisableSelectors.length ||
500
+ this.scopecssDisableSelectors.includes(selectorText)) {
501
+ return selectorText;
502
+ }
503
+ }
504
+ if (selectorText === '*') {
505
+ return this.prefix + ' *';
506
+ }
507
+ else if (bodySelectorREG.test(selectorText)) {
508
+ return selectorText.replace(bodySelectorREG, this.prefix + ' micro-app-body');
509
+ }
510
+ else if (rootSelectorREG.test(selectorText)) { // ignore root selector
511
+ return selectorText;
512
+ }
513
+ return this.prefix + ' ' + selectorText;
514
+ });
515
+ }
516
+ matchAtRule() {
517
+ if (this.cssText[0] !== '@')
518
+ return false;
519
+ // reset scopecssDisableNextLine
520
+ this.scopecssDisableNextLine = false;
521
+ return this.keyframesRule() ||
522
+ this.mediaRule() ||
523
+ this.custommediaRule() ||
524
+ this.supportsRule() ||
525
+ this.importRule() ||
526
+ this.charsetRule() ||
527
+ this.namespaceRule() ||
528
+ this.documentRule() ||
529
+ this.pageRule() ||
530
+ this.hostRule() ||
531
+ this.fontfaceRule();
532
+ }
533
+ // https://developer.mozilla.org/en-US/docs/Web/API/CSSKeyframesRule
534
+ keyframesRule() {
535
+ if (!this.commonMatch(/^@([-\w]+)?keyframes\s*/))
536
+ return false;
537
+ if (!this.commonMatch(/^([-\w]+)\s*/))
538
+ return parseError('@keyframes missing name', this.linkpath);
539
+ this.matchComments();
540
+ if (!this.matchOpenBrace())
541
+ return parseError("@keyframes missing '{'", this.linkpath);
542
+ this.matchComments();
543
+ while (this.keyframeRule()) {
544
+ this.matchComments();
545
+ }
546
+ if (!this.matchCloseBrace())
547
+ return parseError("@keyframes missing '}'", this.linkpath);
548
+ this.matchLeadingSpaces();
549
+ return true;
550
+ }
551
+ keyframeRule() {
552
+ let r;
553
+ const valList = [];
554
+ while (r = this.commonMatch(/^((\d+\.\d+|\.\d+|\d+)%?|[a-z]+)\s*/)) {
555
+ valList.push(r[1]);
556
+ this.commonMatch(/^,\s*/);
557
+ }
558
+ if (!valList.length)
559
+ return false;
560
+ this.styleDeclarations();
561
+ this.matchLeadingSpaces();
562
+ return true;
563
+ }
564
+ // https://github.com/postcss/postcss-custom-media
565
+ custommediaRule() {
566
+ if (!this.commonMatch(/^@custom-media\s+(--[^\s]+)\s*([^{;]+);/))
567
+ return false;
568
+ this.matchLeadingSpaces();
569
+ return true;
570
+ }
571
+ // https://developer.mozilla.org/en-US/docs/Web/API/CSSPageRule
572
+ pageRule() {
573
+ if (!this.commonMatch(/^@page */))
574
+ return false;
575
+ this.formatSelector();
576
+ // reset scopecssDisableNextLine
577
+ this.scopecssDisableNextLine = false;
578
+ return this.commonHandlerForAtRuleWithSelfRule('page');
579
+ }
580
+ // https://developer.mozilla.org/en-US/docs/Web/API/CSSFontFaceRule
581
+ fontfaceRule() {
582
+ if (!this.commonMatch(/^@font-face\s*/))
583
+ return false;
584
+ return this.commonHandlerForAtRuleWithSelfRule('font-face');
585
+ }
586
+ // common matcher for @media, @supports, @document, @host
587
+ createMatcherForAtRuleWithChildRule(reg, name) {
588
+ return () => {
589
+ if (!this.commonMatch(reg))
590
+ return false;
591
+ if (!this.matchOpenBrace())
592
+ return parseError(`@${name} missing '{'`, this.linkpath);
593
+ this.matchComments();
594
+ this.matchRules();
595
+ if (!this.matchCloseBrace())
596
+ return parseError(`@${name} missing '}'`, this.linkpath);
597
+ this.matchLeadingSpaces();
598
+ return true;
599
+ };
600
+ }
601
+ // common matcher for @import, @charset, @namespace
602
+ createMatcherForNoneBraceAtRule(name) {
603
+ const reg = new RegExp('^@' + name + '\\s*([^;]+);');
604
+ return () => {
605
+ if (!this.commonMatch(reg))
606
+ return false;
607
+ this.matchLeadingSpaces();
608
+ return false;
609
+ };
610
+ }
611
+ // common handler for @font-face, @page
612
+ commonHandlerForAtRuleWithSelfRule(name) {
613
+ if (!this.matchOpenBrace())
614
+ return parseError(`@${name} missing '{'`, this.linkpath);
615
+ this.matchComments();
616
+ while (this.styleDeclaration()) {
617
+ this.matchComments();
618
+ }
619
+ if (!this.matchCloseBrace())
620
+ return parseError(`@${name} missing '}'`, this.linkpath);
621
+ this.matchLeadingSpaces();
622
+ return true;
623
+ }
624
+ // match and slice comments
625
+ matchComments() {
626
+ while (this.matchComment())
627
+ ;
628
+ }
629
+ // css comment
630
+ matchComment() {
631
+ if (this.cssText.charAt(0) !== '/' || this.cssText.charAt(1) !== '*')
632
+ return false;
633
+ // reset scopecssDisableNextLine
634
+ this.scopecssDisableNextLine = false;
635
+ let i = 2;
636
+ while (this.cssText.charAt(i) !== '' && (this.cssText.charAt(i) !== '*' || this.cssText.charAt(i + 1) !== '/'))
637
+ ++i;
638
+ i += 2;
639
+ if (this.cssText.charAt(i - 1) === '') {
640
+ return parseError('End of comment missing', this.linkpath);
641
+ }
642
+ // get comment content
643
+ let commentText = this.cssText.slice(2, i - 2);
644
+ this.result += `/*${commentText}*/`;
645
+ commentText = trim(commentText.replace(/^\s*!/, ''));
646
+ // set ignore config
647
+ if (commentText === 'scopecss-disable-next-line') {
648
+ this.scopecssDisableNextLine = true;
649
+ }
650
+ else if (/^scopecss-disable/.test(commentText)) {
651
+ if (commentText === 'scopecss-disable') {
652
+ this.scopecssDisable = true;
486
653
  }
487
654
  else {
488
- return all;
655
+ this.scopecssDisable = true;
656
+ const ignoreRules = commentText.replace('scopecss-disable', '').split(',');
657
+ ignoreRules.forEach((rule) => {
658
+ this.scopecssDisableSelectors.push(trim(rule));
659
+ });
489
660
  }
490
661
  }
491
- // ./a/b.png ../a/b.png a/b.png
492
- if (/^((\.\.?\/)|[^/])/.test($1) && linkpath) {
493
- baseURI = getLinkFileDir(linkpath);
662
+ else if (commentText === 'scopecss-enable') {
663
+ this.scopecssDisable = false;
664
+ this.scopecssDisableSelectors = [];
494
665
  }
495
- return `url("${CompletionPath($1, baseURI)}")`;
496
- });
497
- }
498
- // handle media and supports
499
- function scopedPackRule(rule, prefix, packName) {
500
- const result = scopedRule(Array.from(rule.cssRules), prefix);
501
- return `@${packName} ${rule.conditionText} {${result}}`;
502
- }
503
- /**
504
- * Process each cssrule
505
- * @param rules cssRule
506
- * @param prefix prefix as micro-app[name=xxx]
507
- */
508
- function scopedRule(rules, prefix) {
509
- let result = '';
510
- for (const rule of rules) {
511
- switch (rule.type) {
512
- case CSSRuleType.STYLE_RULE:
513
- result += scopedStyleRule(rule, prefix);
514
- break;
515
- case CSSRuleType.MEDIA_RULE:
516
- result += scopedPackRule(rule, prefix, 'media');
517
- break;
518
- case CSSRuleType.SUPPORTS_RULE:
519
- result += scopedPackRule(rule, prefix, 'supports');
520
- break;
521
- default:
522
- result += rule.cssText;
523
- break;
524
- }
525
- }
526
- return result.replace(/^\s+/, '');
666
+ this.cssText = this.cssText.slice(i);
667
+ this.matchLeadingSpaces();
668
+ return true;
669
+ }
670
+ commonMatch(reg, skip = false) {
671
+ const matchArray = reg.exec(this.cssText);
672
+ if (!matchArray)
673
+ return;
674
+ const matchStr = matchArray[0];
675
+ this.cssText = this.cssText.slice(matchStr.length);
676
+ if (!skip)
677
+ this.result += matchStr;
678
+ return matchArray;
679
+ }
680
+ matchOpenBrace() {
681
+ return this.commonMatch(/^{\s*/);
682
+ }
683
+ matchCloseBrace() {
684
+ return this.commonMatch(/^}/);
685
+ }
686
+ // match and slice the leading spaces
687
+ matchLeadingSpaces() {
688
+ this.commonMatch(/^\s*/);
689
+ }
527
690
  }
528
691
  /**
529
692
  * common method of bind CSS
530
693
  */
531
- function commonAction(templateStyle, styleElement, originContent, prefix, baseURI, linkpath) {
532
- var _a, _b;
694
+ function commonAction(styleElement, appName, prefix, baseURI, linkpath) {
533
695
  if (!styleElement.__MICRO_APP_HAS_SCOPED__) {
534
- const rules = Array.from((_b = (_a = templateStyle.sheet) === null || _a === void 0 ? void 0 : _a.cssRules) !== null && _b !== void 0 ? _b : []);
535
- let result = scopedHost(scopedRule(rules, prefix), baseURI, originContent, linkpath);
536
- /**
537
- * Solve the problem of missing content quotes in some Safari browsers
538
- * docs: https://developer.mozilla.org/zh-CN/docs/Web/CSS/content
539
- * If there are still problems, it is recommended to use the attr()
540
- */
541
- if (isSafari()) {
542
- result = result.replace(/([;{]\s*content:\s*)([^\s"][^";}]*)/gm, (all, $1, $2) => {
543
- if ($2 === 'none' ||
544
- /^(url\()|(counter\()|(attr\()|(open-quote)|(close-quote)/.test($2)) {
545
- return all;
546
- }
547
- return `${$1}"${$2}"`;
548
- });
549
- }
550
- styleElement.textContent = result;
551
696
  styleElement.__MICRO_APP_HAS_SCOPED__ = true;
697
+ let result = null;
698
+ try {
699
+ result = parser.exec(styleElement.textContent, prefix, baseURI, linkpath);
700
+ parser.reset();
701
+ }
702
+ catch (e) {
703
+ parser.reset();
704
+ logError('CSSParser: An error occurred while parsing CSS', appName, e);
705
+ }
706
+ if (result)
707
+ styleElement.textContent = result;
552
708
  }
553
709
  }
710
+ let parser;
554
711
  /**
555
712
  * scopedCSS
556
713
  * @param styleElement target style element
@@ -559,27 +716,18 @@ function commonAction(templateStyle, styleElement, originContent, prefix, baseUR
559
716
  function scopedCSS(styleElement, app) {
560
717
  if (app.scopecss) {
561
718
  const prefix = `${microApp.tagName}[name=${app.name}]`;
562
- let templateStyle = globalEnv.templateStyle;
563
- if (!templateStyle) {
564
- globalEnv.templateStyle = templateStyle = pureCreateElement('style');
565
- templateStyle.setAttribute('id', 'micro-app-template-style');
566
- globalEnv.rawDocument.body.appendChild(templateStyle);
567
- templateStyle.sheet.disabled = true;
568
- }
719
+ if (!parser)
720
+ parser = new CSSParser();
569
721
  if (styleElement.textContent) {
570
- templateStyle.textContent = styleElement.textContent;
571
- commonAction(templateStyle, styleElement, styleElement.textContent, prefix, app.url, styleElement.__MICRO_APP_LINK_PATH__);
572
- templateStyle.textContent = '';
722
+ commonAction(styleElement, app.name, prefix, app.url, styleElement.__MICRO_APP_LINK_PATH__);
573
723
  }
574
724
  else {
575
725
  const observer = new MutationObserver(function () {
576
- var _a, _b;
577
726
  observer.disconnect();
578
- // styled-component will not be processed temporarily
579
- if ((!styleElement.textContent && ((_b = (_a = styleElement.sheet) === null || _a === void 0 ? void 0 : _a.cssRules) === null || _b === void 0 ? void 0 : _b.length)) ||
580
- styleElement.hasAttribute('data-styled'))
581
- return;
582
- commonAction(styleElement, styleElement, styleElement.textContent, prefix, app.url, styleElement.__MICRO_APP_LINK_PATH__);
727
+ // styled-component will be ignore
728
+ if (styleElement.textContent && !styleElement.hasAttribute('data-styled')) {
729
+ commonAction(styleElement, app.name, prefix, app.url, styleElement.__MICRO_APP_LINK_PATH__);
730
+ }
583
731
  });
584
732
  observer.observe(styleElement, { childList: true });
585
733
  }
@@ -718,7 +866,12 @@ function fetchLinkSuccess(url, info, data, microAppHead, app) {
718
866
  styleLink.textContent = data;
719
867
  styleLink.__MICRO_APP_LINK_PATH__ = url;
720
868
  styleLink.setAttribute('data-origin-href', url);
721
- microAppHead.replaceChild(scopedCSS(styleLink, app), info.placeholder);
869
+ if (info.placeholder.parentNode) {
870
+ info.placeholder.parentNode.replaceChild(scopedCSS(styleLink, app), info.placeholder);
871
+ }
872
+ else {
873
+ microAppHead.appendChild(scopedCSS(styleLink, app));
874
+ }
722
875
  info.placeholder = null;
723
876
  info.code = data;
724
877
  }
@@ -759,6 +912,95 @@ function foramtDynamicLink(url, info, app, originLink, replaceStyle) {
759
912
  });
760
913
  }
761
914
 
915
+ const globalEnv = {};
916
+ /**
917
+ * Note loop nesting
918
+ * Only prototype or unique values can be put here
919
+ */
920
+ function initGlobalEnv() {
921
+ if (isBrowser) {
922
+ /**
923
+ * save patch raw methods
924
+ * pay attention to this binding
925
+ */
926
+ const rawSetAttribute = Element.prototype.setAttribute;
927
+ const rawAppendChild = Element.prototype.appendChild;
928
+ const rawInsertBefore = Element.prototype.insertBefore;
929
+ const rawReplaceChild = Element.prototype.replaceChild;
930
+ const rawRemoveChild = Element.prototype.removeChild;
931
+ const rawAppend = Element.prototype.append;
932
+ const rawPrepend = Element.prototype.prepend;
933
+ const rawCloneNode = Element.prototype.cloneNode;
934
+ const rawCreateElement = Document.prototype.createElement;
935
+ const rawCreateElementNS = Document.prototype.createElementNS;
936
+ const rawCreateDocumentFragment = Document.prototype.createDocumentFragment;
937
+ const rawQuerySelector = Document.prototype.querySelector;
938
+ const rawQuerySelectorAll = Document.prototype.querySelectorAll;
939
+ const rawGetElementById = Document.prototype.getElementById;
940
+ const rawGetElementsByClassName = Document.prototype.getElementsByClassName;
941
+ const rawGetElementsByTagName = Document.prototype.getElementsByTagName;
942
+ const rawGetElementsByName = Document.prototype.getElementsByName;
943
+ const ImageProxy = new Proxy(Image, {
944
+ construct(Target, args) {
945
+ const elementImage = new Target(...args);
946
+ elementImage.__MICRO_APP_NAME__ = getCurrentAppName();
947
+ return elementImage;
948
+ },
949
+ });
950
+ const rawWindow = Function('return window')();
951
+ const rawDocument = Function('return document')();
952
+ const supportModuleScript = isSupportModuleScript();
953
+ /**
954
+ * save effect raw methods
955
+ * pay attention to this binding, especially setInterval, setTimeout, clearInterval, clearTimeout
956
+ */
957
+ const rawWindowAddEventListener = rawWindow.addEventListener;
958
+ const rawWindowRemoveEventListener = rawWindow.removeEventListener;
959
+ const rawSetInterval = rawWindow.setInterval;
960
+ const rawSetTimeout = rawWindow.setTimeout;
961
+ const rawClearInterval = rawWindow.clearInterval;
962
+ const rawClearTimeout = rawWindow.clearTimeout;
963
+ const rawDocumentAddEventListener = rawDocument.addEventListener;
964
+ const rawDocumentRemoveEventListener = rawDocument.removeEventListener;
965
+ // mark current application as base application
966
+ window.__MICRO_APP_BASE_APPLICATION__ = true;
967
+ Object.assign(globalEnv, {
968
+ // source/patch
969
+ rawSetAttribute,
970
+ rawAppendChild,
971
+ rawInsertBefore,
972
+ rawReplaceChild,
973
+ rawRemoveChild,
974
+ rawAppend,
975
+ rawPrepend,
976
+ rawCloneNode,
977
+ rawCreateElement,
978
+ rawCreateElementNS,
979
+ rawCreateDocumentFragment,
980
+ rawQuerySelector,
981
+ rawQuerySelectorAll,
982
+ rawGetElementById,
983
+ rawGetElementsByClassName,
984
+ rawGetElementsByTagName,
985
+ rawGetElementsByName,
986
+ ImageProxy,
987
+ // common global vars
988
+ rawWindow,
989
+ rawDocument,
990
+ supportModuleScript,
991
+ // sandbox/effect
992
+ rawWindowAddEventListener,
993
+ rawWindowRemoveEventListener,
994
+ rawSetInterval,
995
+ rawSetTimeout,
996
+ rawClearInterval,
997
+ rawClearTimeout,
998
+ rawDocumentAddEventListener,
999
+ rawDocumentRemoveEventListener,
1000
+ });
1001
+ }
1002
+ }
1003
+
762
1004
  // Global scripts, reuse across apps
763
1005
  const globalScripts = new Map();
764
1006
  /**
@@ -909,17 +1151,21 @@ function execScripts(scriptList, app, initedHook) {
909
1151
  }
910
1152
  }
911
1153
  if (deferScriptPromise.length) {
912
- Promise.all(deferScriptPromise).then((res) => {
913
- res.forEach((code, index) => {
914
- const [url, info] = deferScriptInfo[index];
915
- info.code = info.code || code;
916
- runScript(url, app, info, false, initedHook);
917
- !info.module && initedHook(false);
918
- });
919
- initedHook(isUndefined(initedHook.moduleCount));
920
- }).catch((err) => {
1154
+ promiseStream(deferScriptPromise, (res) => {
1155
+ const info = deferScriptInfo[res.index][1];
1156
+ info.code = info.code || res.data;
1157
+ }, (err) => {
1158
+ initedHook.errorCount = initedHook.errorCount ? ++initedHook.errorCount : 1;
921
1159
  logError(err, app.name);
922
- initedHook(true);
1160
+ }, () => {
1161
+ deferScriptInfo.forEach(([url, info]) => {
1162
+ if (info.code) {
1163
+ runScript(url, app, info, false, initedHook);
1164
+ !info.module && initedHook(false);
1165
+ }
1166
+ });
1167
+ initedHook(isUndefined(initedHook.moduleCount) ||
1168
+ initedHook.errorCount === deferScriptPromise.length);
923
1169
  });
924
1170
  }
925
1171
  else {
@@ -1054,7 +1300,7 @@ function bindScope(url, app, code, module) {
1054
1300
  }
1055
1301
  if (app.sandBox && !module) {
1056
1302
  globalEnv.rawWindow.__MICRO_APP_PROXY_WINDOW__ = app.sandBox.proxyWindow;
1057
- return `;(function(window, self){with(window){;${code}\n}}).call(window.__MICRO_APP_PROXY_WINDOW__, window.__MICRO_APP_PROXY_WINDOW__, window.__MICRO_APP_PROXY_WINDOW__);`;
1303
+ return `;(function(proxyWindow){with(proxyWindow.__MICRO_APP_WINDOW__){(function(${globalKeyToBeCached}){;${code}\n}).call(proxyWindow,${globalKeyToBeCached})}})(window.__MICRO_APP_PROXY_WINDOW__);`;
1058
1304
  }
1059
1305
  return code;
1060
1306
  }
@@ -1473,46 +1719,41 @@ function rebuildDataCenterSnapshot(microAppEventCneter) {
1473
1719
  }
1474
1720
  }
1475
1721
 
1476
- const boundedMap = new WeakMap();
1722
+ /* eslint-disable no-return-assign */
1477
1723
  function isBoundedFunction(value) {
1478
- if (boundedMap.has(value)) {
1479
- return boundedMap.get(value);
1480
- }
1481
- // bind function
1482
- const boundFunction = isBoundFunction(value);
1483
- boundedMap.set(value, boundFunction);
1484
- return boundFunction;
1724
+ if (isBoolean(value.__MICRO_APP_ISBOUND_FUNCTION))
1725
+ return value.__MICRO_APP_ISBOUND_FUNCTION;
1726
+ return value.__MICRO_APP_ISBOUND_FUNCTION = isBoundFunction(value);
1485
1727
  }
1486
- const constructorMap = new WeakMap();
1487
1728
  function isConstructor(value) {
1488
- if (constructorMap.has(value)) {
1489
- return constructorMap.get(value);
1490
- }
1729
+ var _a;
1730
+ if (isBoolean(value.__MICRO_APP_ISCONSTRUCTOR))
1731
+ return value.__MICRO_APP_ISCONSTRUCTOR;
1491
1732
  const valueStr = value.toString();
1492
- const result = (value.prototype &&
1493
- value.prototype.constructor === value &&
1733
+ const result = (((_a = value.prototype) === null || _a === void 0 ? void 0 : _a.constructor) === value &&
1494
1734
  Object.getOwnPropertyNames(value.prototype).length > 1) ||
1495
1735
  /^function\s+[A-Z]/.test(valueStr) ||
1496
1736
  /^class\s+/.test(valueStr);
1497
- constructorMap.set(value, result);
1498
- return result;
1737
+ return value.__MICRO_APP_ISCONSTRUCTOR = result;
1499
1738
  }
1500
- const rawWindowMethodMap = new WeakMap();
1501
1739
  // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
1502
- function bindFunctionToRawWidow(rawWindow, value) {
1503
- if (rawWindowMethodMap.has(value)) {
1504
- return rawWindowMethodMap.get(value);
1505
- }
1506
- if (isFunction(value) && !isConstructor(value) && !isBoundedFunction(value)) {
1740
+ function bindFunctionToRawWindow(rawWindow, value) {
1741
+ if (value.__MICRO_APP_BOUND_WINDOW_FUNCTION)
1742
+ return value.__MICRO_APP_BOUND_WINDOW_FUNCTION;
1743
+ if (!isConstructor(value) && !isBoundedFunction(value)) {
1507
1744
  const bindRawWindowValue = value.bind(rawWindow);
1508
1745
  for (const key in value) {
1509
1746
  bindRawWindowValue[key] = value[key];
1510
1747
  }
1511
- if (value.hasOwnProperty('prototype') && !bindRawWindowValue.hasOwnProperty('prototype')) {
1512
- bindRawWindowValue.prototype = value.prototype;
1748
+ if (value.hasOwnProperty('prototype')) {
1749
+ rawDefineProperty(bindRawWindowValue, 'prototype', {
1750
+ value: value.prototype,
1751
+ configurable: true,
1752
+ enumerable: false,
1753
+ writable: true,
1754
+ });
1513
1755
  }
1514
- rawWindowMethodMap.set(value, bindRawWindowValue);
1515
- return bindRawWindowValue;
1756
+ return value.__MICRO_APP_BOUND_WINDOW_FUNCTION = bindRawWindowValue;
1516
1757
  }
1517
1758
  return value;
1518
1759
  }
@@ -1536,7 +1777,7 @@ function overwriteDocumentOnClick() {
1536
1777
  isFunction(f) && f.call(document, e);
1537
1778
  });
1538
1779
  }
1539
- Object.defineProperty(document, 'onclick', {
1780
+ rawDefineProperty(document, 'onclick', {
1540
1781
  configurable: true,
1541
1782
  enumerable: true,
1542
1783
  get() {
@@ -1586,7 +1827,7 @@ function effectDocumentEvent() {
1586
1827
  else {
1587
1828
  documentEventListenerMap.set(appName, new Map([[type, new Set([listener])]]));
1588
1829
  }
1589
- listener && (listener.__MICRO_MARK_OPTIONS__ = options);
1830
+ listener && (listener.__MICRO_APP_MARK_OPTIONS__ = options);
1590
1831
  }
1591
1832
  rawDocumentAddEventListener.call(rawDocument, type, listener, options);
1592
1833
  };
@@ -1615,27 +1856,27 @@ const formatEventList = ['unmount', 'appstate-change'];
1615
1856
  /**
1616
1857
  * Format event name
1617
1858
  * @param type event name
1618
- * @param microWindow micro window
1859
+ * @param microAppWindow micro window
1619
1860
  */
1620
- function formatEventType(type, microWindow) {
1861
+ function formatEventType(type, microAppWindow) {
1621
1862
  if (formatEventList.includes(type)) {
1622
- return `${type}-${microWindow.__MICRO_APP_NAME__}`;
1863
+ return `${type}-${microAppWindow.__MICRO_APP_NAME__}`;
1623
1864
  }
1624
1865
  return type;
1625
1866
  }
1626
1867
  /**
1627
1868
  * Rewrite side-effect events
1628
- * @param microWindow micro window
1869
+ * @param microAppWindow micro window
1629
1870
  */
1630
- function effect(microWindow) {
1631
- const appName = microWindow.__MICRO_APP_NAME__;
1871
+ function effect(microAppWindow) {
1872
+ const appName = microAppWindow.__MICRO_APP_NAME__;
1632
1873
  const eventListenerMap = new Map();
1633
1874
  const intervalIdMap = new Map();
1634
1875
  const timeoutIdMap = new Map();
1635
1876
  const { rawWindow, rawDocument, rawWindowAddEventListener, rawWindowRemoveEventListener, rawSetInterval, rawSetTimeout, rawClearInterval, rawClearTimeout, rawDocumentRemoveEventListener, } = globalEnv;
1636
1877
  // listener may be null, e.g test-passive
1637
- microWindow.addEventListener = function (type, listener, options) {
1638
- type = formatEventType(type, microWindow);
1878
+ microAppWindow.addEventListener = function (type, listener, options) {
1879
+ type = formatEventType(type, microAppWindow);
1639
1880
  const listenerList = eventListenerMap.get(type);
1640
1881
  if (listenerList) {
1641
1882
  listenerList.add(listener);
@@ -1643,32 +1884,32 @@ function effect(microWindow) {
1643
1884
  else {
1644
1885
  eventListenerMap.set(type, new Set([listener]));
1645
1886
  }
1646
- listener && (listener.__MICRO_MARK_OPTIONS__ = options);
1887
+ listener && (listener.__MICRO_APP_MARK_OPTIONS__ = options);
1647
1888
  rawWindowAddEventListener.call(rawWindow, type, listener, options);
1648
1889
  };
1649
- microWindow.removeEventListener = function (type, listener, options) {
1650
- type = formatEventType(type, microWindow);
1890
+ microAppWindow.removeEventListener = function (type, listener, options) {
1891
+ type = formatEventType(type, microAppWindow);
1651
1892
  const listenerList = eventListenerMap.get(type);
1652
1893
  if ((listenerList === null || listenerList === void 0 ? void 0 : listenerList.size) && listenerList.has(listener)) {
1653
1894
  listenerList.delete(listener);
1654
1895
  }
1655
1896
  rawWindowRemoveEventListener.call(rawWindow, type, listener, options);
1656
1897
  };
1657
- microWindow.setInterval = function (handler, timeout, ...args) {
1898
+ microAppWindow.setInterval = function (handler, timeout, ...args) {
1658
1899
  const intervalId = rawSetInterval.call(rawWindow, handler, timeout, ...args);
1659
1900
  intervalIdMap.set(intervalId, { handler, timeout, args });
1660
1901
  return intervalId;
1661
1902
  };
1662
- microWindow.setTimeout = function (handler, timeout, ...args) {
1903
+ microAppWindow.setTimeout = function (handler, timeout, ...args) {
1663
1904
  const timeoutId = rawSetTimeout.call(rawWindow, handler, timeout, ...args);
1664
1905
  timeoutIdMap.set(timeoutId, { handler, timeout, args });
1665
1906
  return timeoutId;
1666
1907
  };
1667
- microWindow.clearInterval = function (intervalId) {
1908
+ microAppWindow.clearInterval = function (intervalId) {
1668
1909
  intervalIdMap.delete(intervalId);
1669
1910
  rawClearInterval.call(rawWindow, intervalId);
1670
1911
  };
1671
- microWindow.clearTimeout = function (timeoutId) {
1912
+ microAppWindow.clearTimeout = function (timeoutId) {
1672
1913
  timeoutIdMap.delete(timeoutId);
1673
1914
  rawClearTimeout.call(rawWindow, timeoutId);
1674
1915
  };
@@ -1709,15 +1950,15 @@ function effect(microWindow) {
1709
1950
  // rebuild window event
1710
1951
  umdWindowListenerMap.forEach((listenerList, type) => {
1711
1952
  for (const listener of listenerList) {
1712
- microWindow.addEventListener(type, listener, listener === null || listener === void 0 ? void 0 : listener.__MICRO_MARK_OPTIONS__);
1953
+ microAppWindow.addEventListener(type, listener, listener === null || listener === void 0 ? void 0 : listener.__MICRO_APP_MARK_OPTIONS__);
1713
1954
  }
1714
1955
  });
1715
1956
  // rebuild timer
1716
1957
  umdIntervalIdMap.forEach((info) => {
1717
- microWindow.setInterval(info.handler, info.timeout, ...info.args);
1958
+ microAppWindow.setInterval(info.handler, info.timeout, ...info.args);
1718
1959
  });
1719
1960
  umdTimeoutIdMap.forEach((info) => {
1720
- microWindow.setTimeout(info.handler, info.timeout, ...info.args);
1961
+ microAppWindow.setTimeout(info.handler, info.timeout, ...info.args);
1721
1962
  });
1722
1963
  // rebuild onclick event
1723
1964
  umdOnClickHandler && documentClickListMap.set(appName, umdOnClickHandler);
@@ -1725,7 +1966,7 @@ function effect(microWindow) {
1725
1966
  setCurrentAppName(appName);
1726
1967
  umdDocumentListenerMap.forEach((listenerList, type) => {
1727
1968
  for (const listener of listenerList) {
1728
- document.addEventListener(type, listener, listener === null || listener === void 0 ? void 0 : listener.__MICRO_MARK_OPTIONS__);
1969
+ document.addEventListener(type, listener, listener === null || listener === void 0 ? void 0 : listener.__MICRO_APP_MARK_OPTIONS__);
1729
1970
  }
1730
1971
  });
1731
1972
  setCurrentAppName(null);
@@ -1773,189 +2014,70 @@ function effect(microWindow) {
1773
2014
  releaseEffect,
1774
2015
  };
1775
2016
  }
1776
-
1777
- const ImageProxy = new Proxy(Image, {
1778
- construct(Target, args) {
1779
- const elementImage = new Target(...args);
1780
- elementImage.__MICRO_APP_NAME__ = getCurrentAppName();
1781
- return elementImage;
1782
- },
1783
- });
2017
+ // window.addEventListener('mousedown', (e: Event) => {
2018
+ // const targetNode = e.target
2019
+ // const activeApps = getActiveApps(true)
2020
+ // let isScopeOfMicroApp = false
2021
+ // for (const appName of activeApps) {
2022
+ // const app = appInstanceMap.get(appName)!
2023
+ // if (targetNode instanceof Node && app.container!.contains(targetNode)) {
2024
+ // isScopeOfMicroApp = true
2025
+ // // console.log(111111, appName)
2026
+ // setCurrentAppName(appName)
2027
+ // break
2028
+ // }
2029
+ // }
2030
+ // if (!isScopeOfMicroApp) {
2031
+ // setCurrentAppName(null)
2032
+ // }
2033
+ // }, false)
2034
+ // let isWaitingForMacroReset = false
2035
+ // window.addEventListener('mouseup', () => {
2036
+ // if (!isWaitingForMacroReset && getCurrentAppName()) {
2037
+ // isWaitingForMacroReset = true
2038
+ // setTimeout(() => {
2039
+ // setCurrentAppName(null)
2040
+ // isWaitingForMacroReset = false
2041
+ // })
2042
+ // }
2043
+ // }, false)
1784
2044
 
1785
2045
  // Variables that can escape to rawWindow
1786
2046
  const staticEscapeProperties = [
1787
2047
  'System',
1788
2048
  '__cjsWrapper',
1789
- '__REACT_ERROR_OVERLAY_GLOBAL_HOOK__',
1790
2049
  ];
1791
2050
  // Variables that can only assigned to rawWindow
1792
2051
  const escapeSetterKeyList = [
1793
2052
  'location',
1794
2053
  ];
1795
- const unscopables = {
1796
- undefined: true,
1797
- Array: true,
1798
- Object: true,
1799
- String: true,
1800
- Boolean: true,
1801
- Math: true,
1802
- Number: true,
1803
- Symbol: true,
1804
- parseFloat: true,
1805
- Float32Array: true,
1806
- };
1807
- /**
1808
- * macro task to solve the rendering problem of vue3
1809
- */
1810
- let macroTimer;
1811
- function macroTask(fn) {
1812
- macroTimer && clearTimeout(macroTimer);
1813
- macroTimer = setTimeout(fn, 0);
1814
- }
2054
+ const globalPropertyList = ['window', 'self', 'globalThis'];
1815
2055
  class SandBox {
1816
- constructor(appName, url, macro) {
1817
- // Scoped global Properties(Properties that can only get and set in microWindow, will not escape to rawWindow)
2056
+ constructor(appName, url) {
2057
+ // Scoped global Properties(Properties that can only get and set in microAppWindow, will not escape to rawWindow)
1818
2058
  this.scopeProperties = ['webpackJsonp'];
1819
2059
  // Properties that can be escape to rawWindow
1820
2060
  this.escapeProperties = [];
1821
- // Properties newly added to microWindow
2061
+ // Properties newly added to microAppWindow
1822
2062
  this.injectedKeys = new Set();
1823
2063
  // Properties escape to rawWindow, cleared when unmount
1824
- this.escapeKeys = new Set();
1825
- // sandbox state
1826
- this.active = false;
1827
- this.microWindow = {}; // Proxy target
1828
- const rawWindow = globalEnv.rawWindow;
1829
- const rawDocument = globalEnv.rawDocument;
1830
- const descriptorTargetMap = new Map();
1831
- const hasOwnProperty = (key) => this.microWindow.hasOwnProperty(key) || rawWindow.hasOwnProperty(key);
1832
- // get scopeProperties and escapeProperties from plugins
1833
- this.getScopeProperties(appName);
1834
- // inject global properties
1835
- this.inject(this.microWindow, appName, url);
1836
- // Rewrite global event listener & timeout
1837
- Object.assign(this, effect(this.microWindow));
1838
- this.proxyWindow = new Proxy(this.microWindow, {
1839
- get: (target, key) => {
1840
- if (key === Symbol.unscopables)
1841
- return unscopables;
1842
- if (['window', 'self', 'globalThis'].includes(key)) {
1843
- return this.proxyWindow;
1844
- }
1845
- if (key === 'top' || key === 'parent') {
1846
- if (rawWindow === rawWindow.parent) { // not in iframe
1847
- return this.proxyWindow;
1848
- }
1849
- return Reflect.get(rawWindow, key); // iframe
1850
- }
1851
- if (key === 'hasOwnProperty')
1852
- return hasOwnProperty;
1853
- if (key === 'document' || key === 'eval' || key === 'Image') {
1854
- if (this.active) {
1855
- setCurrentAppName(appName);
1856
- (macro ? macroTask : defer)(() => setCurrentAppName(null));
1857
- }
1858
- switch (key) {
1859
- case 'document':
1860
- return rawDocument;
1861
- case 'eval':
1862
- return eval;
1863
- case 'Image':
1864
- return ImageProxy;
1865
- }
1866
- }
1867
- if (Reflect.has(target, key)) {
1868
- return Reflect.get(target, key);
1869
- }
1870
- if (this.scopeProperties.includes(key) ||
1871
- (isString(key) && /^__MICRO_APP_/.test(key))) {
1872
- return Reflect.get(target, key);
1873
- }
1874
- const rawValue = Reflect.get(rawWindow, key);
1875
- return bindFunctionToRawWidow(rawWindow, rawValue);
1876
- },
1877
- set: (target, key, value) => {
1878
- if (this.active) {
1879
- if (escapeSetterKeyList.includes(key)) {
1880
- Reflect.set(rawWindow, key, value);
1881
- }
1882
- else if (!target.hasOwnProperty(key) &&
1883
- rawWindow.hasOwnProperty(key) &&
1884
- !this.scopeProperties.includes(key)) {
1885
- const descriptor = Object.getOwnPropertyDescriptor(rawWindow, key);
1886
- const { writable, configurable, enumerable } = descriptor;
1887
- if (writable) {
1888
- Object.defineProperty(target, key, {
1889
- configurable,
1890
- enumerable,
1891
- writable,
1892
- value,
1893
- });
1894
- this.injectedKeys.add(key);
1895
- }
1896
- }
1897
- else {
1898
- Reflect.set(target, key, value);
1899
- this.injectedKeys.add(key);
1900
- }
1901
- if ((this.escapeProperties.includes(key) ||
1902
- (staticEscapeProperties.includes(key) && !Reflect.has(rawWindow, key))) &&
1903
- !this.scopeProperties.includes(key)) {
1904
- Reflect.set(rawWindow, key, value);
1905
- this.escapeKeys.add(key);
1906
- }
1907
- }
1908
- return true;
1909
- },
1910
- has: (target, key) => {
1911
- if (this.scopeProperties.includes(key))
1912
- return key in target;
1913
- return key in unscopables || key in target || key in rawWindow;
1914
- },
1915
- // Object.getOwnPropertyDescriptor(window, key)
1916
- // TODO: use set
1917
- getOwnPropertyDescriptor: (target, key) => {
1918
- if (target.hasOwnProperty(key)) {
1919
- descriptorTargetMap.set(key, 'target');
1920
- return Object.getOwnPropertyDescriptor(target, key);
1921
- }
1922
- if (rawWindow.hasOwnProperty(key)) {
1923
- // like console, alert ...
1924
- descriptorTargetMap.set(key, 'rawWindow');
1925
- const descriptor = Object.getOwnPropertyDescriptor(rawWindow, key);
1926
- if (descriptor && !descriptor.configurable) {
1927
- descriptor.configurable = true;
1928
- }
1929
- return descriptor;
1930
- }
1931
- return undefined;
1932
- },
1933
- // Object.defineProperty(window, key, Descriptor)
1934
- defineProperty: (target, key, value) => {
1935
- const from = descriptorTargetMap.get(key);
1936
- if (from === 'rawWindow') {
1937
- return Reflect.defineProperty(rawWindow, key, value);
1938
- }
1939
- return Reflect.defineProperty(target, key, value);
1940
- },
1941
- // Object.getOwnPropertyNames(window)
1942
- ownKeys: (target) => {
1943
- return unique(Reflect.ownKeys(rawWindow).concat(Reflect.ownKeys(target)));
1944
- },
1945
- deleteProperty: (target, key) => {
1946
- if (target.hasOwnProperty(key)) {
1947
- this.injectedKeys.has(key) && this.injectedKeys.delete(key);
1948
- this.escapeKeys.has(key) && Reflect.deleteProperty(rawWindow, key);
1949
- return Reflect.deleteProperty(target, key);
1950
- }
1951
- return true;
1952
- },
1953
- });
2064
+ this.escapeKeys = new Set();
2065
+ // sandbox state
2066
+ this.active = false;
2067
+ this.microAppWindow = {}; // Proxy target
2068
+ // get scopeProperties and escapeProperties from plugins
2069
+ this.getScopeProperties(appName);
2070
+ // create proxyWindow with Proxy(microAppWindow)
2071
+ this.proxyWindow = this.createProxyWindow();
2072
+ // inject global properties
2073
+ this.initMicroAppWindow(this.microAppWindow, appName, url);
2074
+ // Rewrite global event listener & timeout
2075
+ Object.assign(this, effect(this.microAppWindow));
1954
2076
  }
1955
2077
  start(baseroute) {
1956
2078
  if (!this.active) {
1957
2079
  this.active = true;
1958
- this.microWindow.__MICRO_APP_BASE_ROUTE__ = this.microWindow.__MICRO_APP_BASE_URL__ = baseroute;
2080
+ this.microAppWindow.__MICRO_APP_BASE_ROUTE__ = this.microAppWindow.__MICRO_APP_BASE_URL__ = baseroute;
1959
2081
  // BUG FIX: bable-polyfill@6.x
1960
2082
  globalEnv.rawWindow._babelPolyfill && (globalEnv.rawWindow._babelPolyfill = false);
1961
2083
  if (++SandBox.activeCount === 1) {
@@ -1967,10 +2089,10 @@ class SandBox {
1967
2089
  if (this.active) {
1968
2090
  this.active = false;
1969
2091
  this.releaseEffect();
1970
- this.microWindow.microApp.clearDataListener();
1971
- this.microWindow.microApp.clearGlobalDataListener();
2092
+ this.microAppWindow.microApp.clearDataListener();
2093
+ this.microAppWindow.microApp.clearGlobalDataListener();
1972
2094
  this.injectedKeys.forEach((key) => {
1973
- Reflect.deleteProperty(this.microWindow, key);
2095
+ Reflect.deleteProperty(this.microAppWindow, key);
1974
2096
  });
1975
2097
  this.injectedKeys.clear();
1976
2098
  this.escapeKeys.forEach((key) => {
@@ -1984,12 +2106,12 @@ class SandBox {
1984
2106
  }
1985
2107
  // record umd snapshot before the first execution of umdHookMount
1986
2108
  recordUmdSnapshot() {
1987
- this.microWindow.__MICRO_APP_UMD_MODE__ = true;
2109
+ this.microAppWindow.__MICRO_APP_UMD_MODE__ = true;
1988
2110
  this.recordUmdEffect();
1989
- recordDataCenterSnapshot(this.microWindow.microApp);
2111
+ recordDataCenterSnapshot(this.microAppWindow.microApp);
1990
2112
  this.recordUmdinjectedValues = new Map();
1991
2113
  this.injectedKeys.forEach((key) => {
1992
- this.recordUmdinjectedValues.set(key, Reflect.get(this.microWindow, key));
2114
+ this.recordUmdinjectedValues.set(key, Reflect.get(this.microAppWindow, key));
1993
2115
  });
1994
2116
  }
1995
2117
  // rebuild umd snapshot before remount umd app
@@ -1998,7 +2120,7 @@ class SandBox {
1998
2120
  Reflect.set(this.proxyWindow, key, value);
1999
2121
  });
2000
2122
  this.rebuildUmdEffect();
2001
- rebuildDataCenterSnapshot(this.microWindow.microApp);
2123
+ rebuildDataCenterSnapshot(this.microAppWindow.microApp);
2002
2124
  }
2003
2125
  /**
2004
2126
  * get scopeProperties and escapeProperties from plugins
@@ -2033,20 +2155,178 @@ class SandBox {
2033
2155
  }
2034
2156
  }
2035
2157
  }
2158
+ // create proxyWindow with Proxy(microAppWindow)
2159
+ createProxyWindow() {
2160
+ const rawWindow = globalEnv.rawWindow;
2161
+ const descriptorTargetMap = new Map();
2162
+ // window.xxx will trigger proxy
2163
+ return new Proxy(this.microAppWindow, {
2164
+ get: (target, key) => {
2165
+ if (Reflect.has(target, key) ||
2166
+ (isString(key) && /^__MICRO_APP_/.test(key)) ||
2167
+ this.scopeProperties.includes(key))
2168
+ return Reflect.get(target, key);
2169
+ const rawValue = Reflect.get(rawWindow, key);
2170
+ return isFunction(rawValue) ? bindFunctionToRawWindow(rawWindow, rawValue) : rawValue;
2171
+ },
2172
+ set: (target, key, value) => {
2173
+ if (this.active) {
2174
+ if (escapeSetterKeyList.includes(key)) {
2175
+ Reflect.set(rawWindow, key, value);
2176
+ }
2177
+ else if (
2178
+ // target.hasOwnProperty has been rewritten
2179
+ !rawHasOwnProperty.call(target, key) &&
2180
+ rawHasOwnProperty.call(rawWindow, key) &&
2181
+ !this.scopeProperties.includes(key)) {
2182
+ const descriptor = Object.getOwnPropertyDescriptor(rawWindow, key);
2183
+ const { configurable, enumerable, writable, set } = descriptor;
2184
+ // set value because it can be set
2185
+ rawDefineProperty(target, key, {
2186
+ value,
2187
+ configurable,
2188
+ enumerable,
2189
+ writable: writable !== null && writable !== void 0 ? writable : !!set,
2190
+ });
2191
+ this.injectedKeys.add(key);
2192
+ }
2193
+ else {
2194
+ Reflect.set(target, key, value);
2195
+ this.injectedKeys.add(key);
2196
+ }
2197
+ if ((this.escapeProperties.includes(key) ||
2198
+ (staticEscapeProperties.includes(key) && !Reflect.has(rawWindow, key))) &&
2199
+ !this.scopeProperties.includes(key)) {
2200
+ Reflect.set(rawWindow, key, value);
2201
+ this.escapeKeys.add(key);
2202
+ }
2203
+ }
2204
+ return true;
2205
+ },
2206
+ has: (target, key) => {
2207
+ if (this.scopeProperties.includes(key))
2208
+ return key in target;
2209
+ return key in target || key in rawWindow;
2210
+ },
2211
+ // Object.getOwnPropertyDescriptor(window, key)
2212
+ getOwnPropertyDescriptor: (target, key) => {
2213
+ if (rawHasOwnProperty.call(target, key)) {
2214
+ descriptorTargetMap.set(key, 'target');
2215
+ return Object.getOwnPropertyDescriptor(target, key);
2216
+ }
2217
+ if (rawHasOwnProperty.call(rawWindow, key)) {
2218
+ descriptorTargetMap.set(key, 'rawWindow');
2219
+ const descriptor = Object.getOwnPropertyDescriptor(rawWindow, key);
2220
+ if (descriptor && !descriptor.configurable) {
2221
+ descriptor.configurable = true;
2222
+ }
2223
+ return descriptor;
2224
+ }
2225
+ return undefined;
2226
+ },
2227
+ // Object.defineProperty(window, key, Descriptor)
2228
+ defineProperty: (target, key, value) => {
2229
+ const from = descriptorTargetMap.get(key);
2230
+ if (from === 'rawWindow') {
2231
+ return Reflect.defineProperty(rawWindow, key, value);
2232
+ }
2233
+ return Reflect.defineProperty(target, key, value);
2234
+ },
2235
+ // Object.getOwnPropertyNames(window)
2236
+ ownKeys: (target) => {
2237
+ return unique(Reflect.ownKeys(rawWindow).concat(Reflect.ownKeys(target)));
2238
+ },
2239
+ deleteProperty: (target, key) => {
2240
+ if (rawHasOwnProperty.call(target, key)) {
2241
+ this.injectedKeys.has(key) && this.injectedKeys.delete(key);
2242
+ this.escapeKeys.has(key) && Reflect.deleteProperty(rawWindow, key);
2243
+ return Reflect.deleteProperty(target, key);
2244
+ }
2245
+ return true;
2246
+ },
2247
+ });
2248
+ }
2036
2249
  /**
2037
- * inject global properties to microWindow
2038
- * @param microWindow micro window
2250
+ * inject global properties to microAppWindow
2251
+ * @param microAppWindow micro window
2039
2252
  * @param appName app name
2040
2253
  * @param url app url
2041
2254
  */
2042
- inject(microWindow, appName, url) {
2043
- microWindow.__MICRO_APP_ENVIRONMENT__ = true;
2044
- microWindow.__MICRO_APP_NAME__ = appName;
2045
- microWindow.__MICRO_APP_PUBLIC_PATH__ = getEffectivePath(url);
2046
- microWindow.microApp = new EventCenterForMicroApp(appName);
2047
- microWindow.rawWindow = globalEnv.rawWindow;
2048
- microWindow.rawDocument = globalEnv.rawDocument;
2049
- microWindow.removeDomScope = removeDomScope;
2255
+ initMicroAppWindow(microAppWindow, appName, url) {
2256
+ microAppWindow.__MICRO_APP_ENVIRONMENT__ = true;
2257
+ microAppWindow.__MICRO_APP_NAME__ = appName;
2258
+ microAppWindow.__MICRO_APP_PUBLIC_PATH__ = getEffectivePath(url);
2259
+ microAppWindow.__MICRO_APP_WINDOW__ = microAppWindow;
2260
+ microAppWindow.microApp = new EventCenterForMicroApp(appName);
2261
+ microAppWindow.rawWindow = globalEnv.rawWindow;
2262
+ microAppWindow.rawDocument = globalEnv.rawDocument;
2263
+ microAppWindow.removeDomScope = removeDomScope;
2264
+ microAppWindow.hasOwnProperty = (key) => rawHasOwnProperty.call(microAppWindow, key) || rawHasOwnProperty.call(globalEnv.rawWindow, key);
2265
+ this.setMappingPropertiesWithRawDescriptor(microAppWindow);
2266
+ this.setHijackProperties(microAppWindow, appName);
2267
+ }
2268
+ // properties associated with the native window
2269
+ setMappingPropertiesWithRawDescriptor(microAppWindow) {
2270
+ let topValue, parentValue;
2271
+ const rawWindow = globalEnv.rawWindow;
2272
+ if (rawWindow === rawWindow.parent) { // not in iframe
2273
+ topValue = parentValue = this.proxyWindow;
2274
+ }
2275
+ else { // in iframe
2276
+ topValue = rawWindow.top;
2277
+ parentValue = rawWindow.parent;
2278
+ }
2279
+ rawDefineProperty(microAppWindow, 'top', this.createDescriptorFormicroAppWindow('top', topValue));
2280
+ rawDefineProperty(microAppWindow, 'parent', this.createDescriptorFormicroAppWindow('parent', parentValue));
2281
+ globalPropertyList.forEach((key) => {
2282
+ rawDefineProperty(microAppWindow, key, this.createDescriptorFormicroAppWindow(key, this.proxyWindow));
2283
+ });
2284
+ }
2285
+ createDescriptorFormicroAppWindow(key, value) {
2286
+ const { configurable = true, enumerable = true, writable, set } = Object.getOwnPropertyDescriptor(globalEnv.rawWindow, key) || { writable: true };
2287
+ const descriptor = {
2288
+ value,
2289
+ configurable,
2290
+ enumerable,
2291
+ writable: writable !== null && writable !== void 0 ? writable : !!set
2292
+ };
2293
+ return descriptor;
2294
+ }
2295
+ // set hijack Properties to microAppWindow
2296
+ setHijackProperties(microAppWindow, appName) {
2297
+ let modifiedEval, modifiedImage;
2298
+ rawDefineProperties(microAppWindow, {
2299
+ document: {
2300
+ get() {
2301
+ throttleDeferForSetAppName(appName);
2302
+ return globalEnv.rawDocument;
2303
+ },
2304
+ configurable: false,
2305
+ enumerable: true,
2306
+ },
2307
+ eval: {
2308
+ get() {
2309
+ throttleDeferForSetAppName(appName);
2310
+ return modifiedEval || eval;
2311
+ },
2312
+ set: (value) => {
2313
+ modifiedEval = value;
2314
+ },
2315
+ configurable: true,
2316
+ enumerable: false,
2317
+ },
2318
+ Image: {
2319
+ get() {
2320
+ throttleDeferForSetAppName(appName);
2321
+ return modifiedImage || globalEnv.ImageProxy;
2322
+ },
2323
+ set: (value) => {
2324
+ modifiedImage = value;
2325
+ },
2326
+ configurable: true,
2327
+ enumerable: false,
2328
+ },
2329
+ });
2050
2330
  }
2051
2331
  }
2052
2332
  SandBox.activeCount = 0; // number of active sandbox
@@ -2115,7 +2395,7 @@ function dispatchCustomEventToMicroApp(eventName, appName, detail = {}) {
2115
2395
  // micro app instances
2116
2396
  const appInstanceMap = new Map();
2117
2397
  class CreateApp {
2118
- constructor({ name, url, ssrUrl, container, inline, scopecss, useSandbox, macro, baseroute, }) {
2398
+ constructor({ name, url, ssrUrl, container, inline, scopecss, useSandbox, baseroute, }) {
2119
2399
  this.state = appStates.NOT_LOADED;
2120
2400
  this.keepAliveState = null;
2121
2401
  this.keepAliveContainer = null;
@@ -2126,7 +2406,6 @@ class CreateApp {
2126
2406
  this.umdMode = false;
2127
2407
  this.isPrefetch = false;
2128
2408
  this.container = null;
2129
- this.macro = false;
2130
2409
  this.baseroute = '';
2131
2410
  this.sandBox = null;
2132
2411
  this.container = container !== null && container !== void 0 ? container : null;
@@ -2138,13 +2417,12 @@ class CreateApp {
2138
2417
  this.url = url;
2139
2418
  this.useSandbox = useSandbox;
2140
2419
  this.scopecss = this.useSandbox && scopecss;
2141
- this.macro = macro !== null && macro !== void 0 ? macro : false;
2142
2420
  this.source = {
2143
2421
  links: new Map(),
2144
2422
  scripts: new Map(),
2145
2423
  };
2146
2424
  this.loadSourceCode();
2147
- this.useSandbox && (this.sandBox = new SandBox(name, url, this.macro));
2425
+ this.useSandbox && (this.sandBox = new SandBox(name, url));
2148
2426
  }
2149
2427
  // Load resources
2150
2428
  loadSourceCode() {
@@ -2312,7 +2590,7 @@ class CreateApp {
2312
2590
  var _a;
2313
2591
  (_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.stop();
2314
2592
  if (destroy) {
2315
- this.actionsForCompletelyDestory();
2593
+ this.actionsForCompletelyDestroy();
2316
2594
  }
2317
2595
  else if (this.umdMode && this.container.childElementCount) {
2318
2596
  cloneContainer(this.container, this.source.html, false);
@@ -2324,7 +2602,7 @@ class CreateApp {
2324
2602
  unmountcb && unmountcb();
2325
2603
  }
2326
2604
  // actions for completely destroy
2327
- actionsForCompletelyDestory() {
2605
+ actionsForCompletelyDestroy() {
2328
2606
  if (!this.useSandbox && this.umdMode) {
2329
2607
  delete window[this.libraryName];
2330
2608
  }
@@ -2390,92 +2668,6 @@ class CreateApp {
2390
2668
  return {};
2391
2669
  }
2392
2670
  }
2393
- // if app not prefetch & not unmount, then app is active
2394
- function getActiveApps() {
2395
- const activeApps = [];
2396
- appInstanceMap.forEach((app, appName) => {
2397
- if (appStates.UNMOUNT !== app.getAppState() && !app.isPrefetch) {
2398
- activeApps.push(appName);
2399
- }
2400
- });
2401
- return activeApps;
2402
- }
2403
- // get all registered apps
2404
- function getAllApps() {
2405
- return Array.from(appInstanceMap.keys());
2406
- }
2407
- /**
2408
- * unmount app by appname
2409
- * @param appName
2410
- * @param options unmountAppParams
2411
- * @returns Promise<void>
2412
- */
2413
- function unmountApp(appName, options) {
2414
- const app = appInstanceMap.get(formatAppName(appName));
2415
- return new Promise((reslove) => {
2416
- if (app) {
2417
- if (app.getAppState() === appStates.UNMOUNT || app.isPrefetch) {
2418
- if (options === null || options === void 0 ? void 0 : options.destroy) {
2419
- app.actionsForCompletelyDestory();
2420
- }
2421
- reslove();
2422
- }
2423
- else if (app.getKeepAliveState() === keepAliveStates.KEEP_ALIVE_HIDDEN) {
2424
- if (options === null || options === void 0 ? void 0 : options.destroy) {
2425
- app.unmount(true, reslove);
2426
- }
2427
- else if (options === null || options === void 0 ? void 0 : options.clearAliveState) {
2428
- app.unmount(false, reslove);
2429
- }
2430
- else {
2431
- reslove();
2432
- }
2433
- }
2434
- else {
2435
- const container = getRootContainer(app.container);
2436
- const unmountHandler = () => {
2437
- container.removeEventListener('unmount', unmountHandler);
2438
- container.removeEventListener('afterhidden', afterhiddenHandler);
2439
- reslove();
2440
- };
2441
- const afterhiddenHandler = () => {
2442
- container.removeEventListener('unmount', unmountHandler);
2443
- container.removeEventListener('afterhidden', afterhiddenHandler);
2444
- reslove();
2445
- };
2446
- container.addEventListener('unmount', unmountHandler);
2447
- container.addEventListener('afterhidden', afterhiddenHandler);
2448
- if (options === null || options === void 0 ? void 0 : options.destroy) {
2449
- let destroyAttrValue, destoryAttrValue;
2450
- container.hasAttribute('destroy') && (destroyAttrValue = container.getAttribute('destroy'));
2451
- container.hasAttribute('destory') && (destoryAttrValue = container.getAttribute('destory'));
2452
- container.setAttribute('destroy', 'true');
2453
- container.parentNode.removeChild(container);
2454
- container.removeAttribute('destroy');
2455
- typeof destroyAttrValue === 'string' && container.setAttribute('destroy', destroyAttrValue);
2456
- typeof destoryAttrValue === 'string' && container.setAttribute('destory', destoryAttrValue);
2457
- }
2458
- else if ((options === null || options === void 0 ? void 0 : options.clearAliveState) && container.hasAttribute('keep-alive')) {
2459
- const keepAliveAttrValue = container.getAttribute('keep-alive');
2460
- container.removeAttribute('keep-alive');
2461
- container.parentNode.removeChild(container);
2462
- container.setAttribute('keep-alive', keepAliveAttrValue);
2463
- }
2464
- else {
2465
- container.parentNode.removeChild(container);
2466
- }
2467
- }
2468
- }
2469
- else {
2470
- logWarn(`app ${appName} does not exist`);
2471
- reslove();
2472
- }
2473
- });
2474
- }
2475
- // unmount all apps in turn
2476
- function unmountAllApps(options) {
2477
- return Array.from(appInstanceMap.keys()).reduce((pre, next) => pre.then(() => unmountApp(next, options)), Promise.resolve());
2478
- }
2479
2671
 
2480
2672
  // Record element and map element
2481
2673
  const dynamicElementInMicroAppMap = new WeakMap();
@@ -2946,7 +3138,6 @@ function defineElement(tagName) {
2946
3138
  // inline: whether js runs in inline script mode, default is false
2947
3139
  // disableScopecss: whether disable css scoped, default is false
2948
3140
  // disableSandbox: whether disable sandbox, default is false
2949
- // macro: used to solve the async render problem of vue3, default is false
2950
3141
  // baseRoute: route prefix, default is ''
2951
3142
  // keep-alive: open keep-alive mode
2952
3143
  connectedCallback() {
@@ -3144,7 +3335,7 @@ function defineElement(tagName) {
3144
3335
  * fix of unmounted umd app with disableSandbox
3145
3336
  */
3146
3337
  if (appInstanceMap.has(this.appName)) {
3147
- appInstanceMap.get(this.appName).actionsForCompletelyDestory();
3338
+ appInstanceMap.get(this.appName).actionsForCompletelyDestroy();
3148
3339
  }
3149
3340
  const instance = new CreateApp({
3150
3341
  name: this.appName,
@@ -3154,7 +3345,6 @@ function defineElement(tagName) {
3154
3345
  inline: this.getDisposeResult('inline'),
3155
3346
  scopecss: !(this.getDisposeResult('disableScopecss') || this.getDisposeResult('shadowDOM')),
3156
3347
  useSandbox: !this.getDisposeResult('disableSandbox'),
3157
- macro: this.getDisposeResult('macro'),
3158
3348
  baseroute: this.getBaseRouteCompatible(),
3159
3349
  });
3160
3350
  appInstanceMap.set(this.appName, instance);
@@ -3279,13 +3469,12 @@ function filterPreFetchTarget(apps) {
3279
3469
  * url: string,
3280
3470
  * disableScopecss?: boolean,
3281
3471
  * disableSandbox?: boolean,
3282
- * macro?: boolean,
3283
3472
  * },
3284
3473
  * ...
3285
3474
  * ])
3286
3475
  * Note:
3287
3476
  * 1: preFetch is asynchronous and is performed only when the browser is idle
3288
- * 2: disableScopecss, disableSandbox, macro must be same with micro-app element, if conflict, the one who executes first shall prevail
3477
+ * 2: disableScopecss, disableSandbox must be same with micro-app element, if conflict, the one who executes first shall prevail
3289
3478
  * @param apps micro apps
3290
3479
  */
3291
3480
  function preFetch(apps) {
@@ -3295,13 +3484,12 @@ function preFetch(apps) {
3295
3484
  requestIdleCallback(() => {
3296
3485
  isFunction(apps) && (apps = apps());
3297
3486
  filterPreFetchTarget(apps).forEach((item) => {
3298
- var _a, _b, _c;
3487
+ var _a, _b;
3299
3488
  const app = new CreateApp({
3300
3489
  name: item.name,
3301
3490
  url: item.url,
3302
3491
  scopecss: !((_a = item.disableScopecss) !== null && _a !== void 0 ? _a : microApp.disableScopecss),
3303
3492
  useSandbox: !((_b = item.disableSandbox) !== null && _b !== void 0 ? _b : microApp.disableSandbox),
3304
- macro: (_c = item.macro) !== null && _c !== void 0 ? _c : microApp.macro,
3305
3493
  });
3306
3494
  app.isPrefetch = true;
3307
3495
  appInstanceMap.set(item.name, app);
@@ -3351,6 +3539,99 @@ function getGlobalAssets(assets) {
3351
3539
  }
3352
3540
  }
3353
3541
 
3542
+ /**
3543
+ * if app not prefetch & not unmount, then app is active
3544
+ * @param excludeHiddenApp exclude hidden keep-alive app
3545
+ * @returns active apps
3546
+ */
3547
+ function getActiveApps(excludeHiddenApp) {
3548
+ const activeApps = [];
3549
+ appInstanceMap.forEach((app, appName) => {
3550
+ if (appStates.UNMOUNT !== app.getAppState() &&
3551
+ !app.isPrefetch &&
3552
+ (!excludeHiddenApp ||
3553
+ keepAliveStates.KEEP_ALIVE_HIDDEN !== app.getKeepAliveState())) {
3554
+ activeApps.push(appName);
3555
+ }
3556
+ });
3557
+ return activeApps;
3558
+ }
3559
+ // get all registered apps
3560
+ function getAllApps() {
3561
+ return Array.from(appInstanceMap.keys());
3562
+ }
3563
+ /**
3564
+ * unmount app by appname
3565
+ * @param appName
3566
+ * @param options unmountAppParams
3567
+ * @returns Promise<void>
3568
+ */
3569
+ function unmountApp(appName, options) {
3570
+ const app = appInstanceMap.get(formatAppName(appName));
3571
+ return new Promise((reslove) => {
3572
+ if (app) {
3573
+ if (app.getAppState() === appStates.UNMOUNT || app.isPrefetch) {
3574
+ if (options === null || options === void 0 ? void 0 : options.destroy) {
3575
+ app.actionsForCompletelyDestroy();
3576
+ }
3577
+ reslove();
3578
+ }
3579
+ else if (app.getKeepAliveState() === keepAliveStates.KEEP_ALIVE_HIDDEN) {
3580
+ if (options === null || options === void 0 ? void 0 : options.destroy) {
3581
+ app.unmount(true, reslove);
3582
+ }
3583
+ else if (options === null || options === void 0 ? void 0 : options.clearAliveState) {
3584
+ app.unmount(false, reslove);
3585
+ }
3586
+ else {
3587
+ reslove();
3588
+ }
3589
+ }
3590
+ else {
3591
+ const container = getRootContainer(app.container);
3592
+ const unmountHandler = () => {
3593
+ container.removeEventListener('unmount', unmountHandler);
3594
+ container.removeEventListener('afterhidden', afterhiddenHandler);
3595
+ reslove();
3596
+ };
3597
+ const afterhiddenHandler = () => {
3598
+ container.removeEventListener('unmount', unmountHandler);
3599
+ container.removeEventListener('afterhidden', afterhiddenHandler);
3600
+ reslove();
3601
+ };
3602
+ container.addEventListener('unmount', unmountHandler);
3603
+ container.addEventListener('afterhidden', afterhiddenHandler);
3604
+ if (options === null || options === void 0 ? void 0 : options.destroy) {
3605
+ let destroyAttrValue, destoryAttrValue;
3606
+ container.hasAttribute('destroy') && (destroyAttrValue = container.getAttribute('destroy'));
3607
+ container.hasAttribute('destory') && (destoryAttrValue = container.getAttribute('destory'));
3608
+ container.setAttribute('destroy', 'true');
3609
+ container.parentNode.removeChild(container);
3610
+ container.removeAttribute('destroy');
3611
+ typeof destroyAttrValue === 'string' && container.setAttribute('destroy', destroyAttrValue);
3612
+ typeof destoryAttrValue === 'string' && container.setAttribute('destory', destoryAttrValue);
3613
+ }
3614
+ else if ((options === null || options === void 0 ? void 0 : options.clearAliveState) && container.hasAttribute('keep-alive')) {
3615
+ const keepAliveAttrValue = container.getAttribute('keep-alive');
3616
+ container.removeAttribute('keep-alive');
3617
+ container.parentNode.removeChild(container);
3618
+ container.setAttribute('keep-alive', keepAliveAttrValue);
3619
+ }
3620
+ else {
3621
+ container.parentNode.removeChild(container);
3622
+ }
3623
+ }
3624
+ }
3625
+ else {
3626
+ logWarn(`app ${appName} does not exist`);
3627
+ reslove();
3628
+ }
3629
+ });
3630
+ }
3631
+ // unmount all apps in turn
3632
+ function unmountAllApps(options) {
3633
+ return Array.from(appInstanceMap.keys()).reduce((pre, next) => pre.then(() => unmountApp(next, options)), Promise.resolve());
3634
+ }
3354
3635
  class MicroApp extends EventCenterForBaseApp {
3355
3636
  constructor() {
3356
3637
  super(...arguments);
@@ -3385,7 +3666,6 @@ class MicroApp extends EventCenterForBaseApp {
3385
3666
  this.inline = options.inline;
3386
3667
  this.disableScopecss = options.disableScopecss;
3387
3668
  this.disableSandbox = options.disableSandbox;
3388
- this.macro = options.macro;
3389
3669
  this.ssr = options.ssr;
3390
3670
  isFunction(options.fetch) && (this.fetch = options.fetch);
3391
3671
  isPlainObject(options.lifeCycles) && (this.lifeCycles = options.lifeCycles);
@@ -3414,5 +3694,5 @@ class MicroApp extends EventCenterForBaseApp {
3414
3694
  var microApp = new MicroApp();
3415
3695
 
3416
3696
  export default microApp;
3417
- export { EventCenterForMicroApp, getActiveApps, getAllApps, preFetch, pureCreateElement, removeDomScope, unmountAllApps, unmountApp, version };
3697
+ export { EventCenterForMicroApp, MicroApp, getActiveApps, getAllApps, preFetch, pureCreateElement, removeDomScope, unmountAllApps, unmountApp, version };
3418
3698
  //# sourceMappingURL=index.esm.js.map