@zstackui/qiankun 2.6.3-beta-5

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.
Files changed (155) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +116 -0
  3. package/dist/index.umd.js +8681 -0
  4. package/dist/index.umd.js.map +1 -0
  5. package/dist/index.umd.min.js +4 -0
  6. package/dist/index.umd.min.js.map +1 -0
  7. package/dist/src/__tests__/globalState.test.d.ts +5 -0
  8. package/dist/src/__tests__/utils.test.d.ts +1 -0
  9. package/dist/src/addons/engineFlag.d.ts +6 -0
  10. package/dist/src/addons/index.d.ts +6 -0
  11. package/dist/src/addons/runtimePublicPath.d.ts +6 -0
  12. package/dist/src/apis.d.ts +7 -0
  13. package/dist/src/effects.d.ts +3 -0
  14. package/dist/src/error.d.ts +3 -0
  15. package/dist/src/errorHandler.d.ts +7 -0
  16. package/dist/src/globalState.d.ts +7 -0
  17. package/dist/src/index.d.ts +11 -0
  18. package/dist/src/interfaces.d.ts +107 -0
  19. package/dist/src/loader.d.ts +8 -0
  20. package/dist/src/prefetch.d.ts +14 -0
  21. package/dist/src/sandbox/__tests__/common.test.d.ts +5 -0
  22. package/dist/src/sandbox/__tests__/proxySandbox.test.d.ts +10 -0
  23. package/dist/src/sandbox/common.d.ts +21 -0
  24. package/dist/src/sandbox/index.d.ts +40 -0
  25. package/dist/src/sandbox/legacy/__tests__/sandbox.test.d.ts +5 -0
  26. package/dist/src/sandbox/legacy/sandbox.d.ts +28 -0
  27. package/dist/src/sandbox/patchers/__tests__/css.test.d.ts +5 -0
  28. package/dist/src/sandbox/patchers/__tests__/interval.test.d.ts +5 -0
  29. package/dist/src/sandbox/patchers/css.d.ts +17 -0
  30. package/dist/src/sandbox/patchers/dynamicAppend/__tests__/common.test.d.ts +1 -0
  31. package/dist/src/sandbox/patchers/dynamicAppend/common.d.ts +22 -0
  32. package/dist/src/sandbox/patchers/dynamicAppend/forLooseSandbox.d.ts +17 -0
  33. package/dist/src/sandbox/patchers/dynamicAppend/forStrictSandbox.d.ts +12 -0
  34. package/dist/src/sandbox/patchers/dynamicAppend/index.d.ts +6 -0
  35. package/dist/src/sandbox/patchers/historyListener.d.ts +5 -0
  36. package/dist/src/sandbox/patchers/index.d.ts +9 -0
  37. package/dist/src/sandbox/patchers/interval.d.ts +5 -0
  38. package/dist/src/sandbox/patchers/windowListener.d.ts +5 -0
  39. package/dist/src/sandbox/proxySandbox.d.ts +23 -0
  40. package/dist/src/sandbox/snapshotSandbox.d.ts +20 -0
  41. package/dist/src/utils.d.ts +44 -0
  42. package/dist/src/version.d.ts +1 -0
  43. package/es/addons/engineFlag.d.ts +6 -0
  44. package/es/addons/engineFlag.js +50 -0
  45. package/es/addons/index.d.ts +6 -0
  46. package/es/addons/index.js +13 -0
  47. package/es/addons/runtimePublicPath.d.ts +6 -0
  48. package/es/addons/runtimePublicPath.js +57 -0
  49. package/es/apis.d.ts +7 -0
  50. package/es/apis.js +278 -0
  51. package/es/effects.d.ts +3 -0
  52. package/es/effects.js +33 -0
  53. package/es/error.d.ts +3 -0
  54. package/es/error.js +16 -0
  55. package/es/errorHandler.d.ts +7 -0
  56. package/es/errorHandler.js +13 -0
  57. package/es/globalState.d.ts +7 -0
  58. package/es/globalState.js +101 -0
  59. package/es/index.d.ts +11 -0
  60. package/es/index.js +11 -0
  61. package/es/interfaces.d.ts +107 -0
  62. package/es/interfaces.js +8 -0
  63. package/es/loader.d.ts +8 -0
  64. package/es/loader.js +600 -0
  65. package/es/prefetch.d.ts +14 -0
  66. package/es/prefetch.js +125 -0
  67. package/es/sandbox/common.d.ts +21 -0
  68. package/es/sandbox/common.js +157 -0
  69. package/es/sandbox/index.d.ts +40 -0
  70. package/es/sandbox/index.js +105 -0
  71. package/es/sandbox/legacy/sandbox.d.ts +28 -0
  72. package/es/sandbox/legacy/sandbox.js +142 -0
  73. package/es/sandbox/patchers/css.d.ts +17 -0
  74. package/es/sandbox/patchers/css.js +186 -0
  75. package/es/sandbox/patchers/dynamicAppend/common.d.ts +22 -0
  76. package/es/sandbox/patchers/dynamicAppend/common.js +306 -0
  77. package/es/sandbox/patchers/dynamicAppend/forLooseSandbox.d.ts +17 -0
  78. package/es/sandbox/patchers/dynamicAppend/forLooseSandbox.js +77 -0
  79. package/es/sandbox/patchers/dynamicAppend/forStrictSandbox.d.ts +12 -0
  80. package/es/sandbox/patchers/dynamicAppend/forStrictSandbox.js +103 -0
  81. package/es/sandbox/patchers/dynamicAppend/index.d.ts +6 -0
  82. package/es/sandbox/patchers/dynamicAppend/index.js +6 -0
  83. package/es/sandbox/patchers/historyListener.d.ts +5 -0
  84. package/es/sandbox/patchers/historyListener.js +54 -0
  85. package/es/sandbox/patchers/index.d.ts +9 -0
  86. package/es/sandbox/patchers/index.js +45 -0
  87. package/es/sandbox/patchers/interval.d.ts +5 -0
  88. package/es/sandbox/patchers/interval.js +34 -0
  89. package/es/sandbox/patchers/windowListener.d.ts +5 -0
  90. package/es/sandbox/patchers/windowListener.js +34 -0
  91. package/es/sandbox/proxySandbox.d.ts +23 -0
  92. package/es/sandbox/proxySandbox.js +315 -0
  93. package/es/sandbox/snapshotSandbox.d.ts +20 -0
  94. package/es/sandbox/snapshotSandbox.js +59 -0
  95. package/es/utils.d.ts +44 -0
  96. package/es/utils.js +215 -0
  97. package/es/version.d.ts +1 -0
  98. package/es/version.js +1 -0
  99. package/lib/addons/engineFlag.d.ts +6 -0
  100. package/lib/addons/engineFlag.js +55 -0
  101. package/lib/addons/index.d.ts +6 -0
  102. package/lib/addons/index.js +21 -0
  103. package/lib/addons/runtimePublicPath.d.ts +6 -0
  104. package/lib/addons/runtimePublicPath.js +63 -0
  105. package/lib/apis.d.ts +7 -0
  106. package/lib/apis.js +288 -0
  107. package/lib/effects.d.ts +3 -0
  108. package/lib/effects.js +42 -0
  109. package/lib/error.d.ts +3 -0
  110. package/lib/error.js +23 -0
  111. package/lib/errorHandler.d.ts +7 -0
  112. package/lib/errorHandler.js +33 -0
  113. package/lib/globalState.d.ts +7 -0
  114. package/lib/globalState.js +110 -0
  115. package/lib/index.d.ts +11 -0
  116. package/lib/index.js +89 -0
  117. package/lib/interfaces.d.ts +107 -0
  118. package/lib/interfaces.js +14 -0
  119. package/lib/loader.d.ts +8 -0
  120. package/lib/loader.js +606 -0
  121. package/lib/prefetch.d.ts +14 -0
  122. package/lib/prefetch.js +132 -0
  123. package/lib/sandbox/common.d.ts +21 -0
  124. package/lib/sandbox/common.js +169 -0
  125. package/lib/sandbox/index.d.ts +40 -0
  126. package/lib/sandbox/index.js +123 -0
  127. package/lib/sandbox/legacy/sandbox.d.ts +28 -0
  128. package/lib/sandbox/legacy/sandbox.js +148 -0
  129. package/lib/sandbox/patchers/css.d.ts +17 -0
  130. package/lib/sandbox/patchers/css.js +193 -0
  131. package/lib/sandbox/patchers/dynamicAppend/common.d.ts +22 -0
  132. package/lib/sandbox/patchers/dynamicAppend/common.js +322 -0
  133. package/lib/sandbox/patchers/dynamicAppend/forLooseSandbox.d.ts +17 -0
  134. package/lib/sandbox/patchers/dynamicAppend/forLooseSandbox.js +84 -0
  135. package/lib/sandbox/patchers/dynamicAppend/forStrictSandbox.d.ts +12 -0
  136. package/lib/sandbox/patchers/dynamicAppend/forStrictSandbox.js +110 -0
  137. package/lib/sandbox/patchers/dynamicAppend/index.d.ts +6 -0
  138. package/lib/sandbox/patchers/dynamicAppend/index.js +19 -0
  139. package/lib/sandbox/patchers/historyListener.d.ts +5 -0
  140. package/lib/sandbox/patchers/historyListener.js +62 -0
  141. package/lib/sandbox/patchers/index.d.ts +9 -0
  142. package/lib/sandbox/patchers/index.js +57 -0
  143. package/lib/sandbox/patchers/interval.d.ts +5 -0
  144. package/lib/sandbox/patchers/interval.js +42 -0
  145. package/lib/sandbox/patchers/windowListener.d.ts +5 -0
  146. package/lib/sandbox/patchers/windowListener.js +42 -0
  147. package/lib/sandbox/proxySandbox.d.ts +23 -0
  148. package/lib/sandbox/proxySandbox.js +321 -0
  149. package/lib/sandbox/snapshotSandbox.d.ts +20 -0
  150. package/lib/sandbox/snapshotSandbox.js +65 -0
  151. package/lib/utils.d.ts +44 -0
  152. package/lib/utils.js +240 -0
  153. package/lib/version.d.ts +1 -0
  154. package/lib/version.js +7 -0
  155. package/package.json +137 -0
@@ -0,0 +1,186 @@
1
+ import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
2
+ import _createClass from "@babel/runtime/helpers/esm/createClass";
3
+ /**
4
+ * @author Saviio
5
+ * @since 2020-4-19
6
+ */
7
+ // https://developer.mozilla.org/en-US/docs/Web/API/CSSRule
8
+ var RuleType;
9
+ (function (RuleType) {
10
+ // type: rule will be rewrote
11
+ RuleType[RuleType["STYLE"] = 1] = "STYLE";
12
+ RuleType[RuleType["MEDIA"] = 4] = "MEDIA";
13
+ RuleType[RuleType["SUPPORTS"] = 12] = "SUPPORTS";
14
+ // type: value will be kept
15
+ RuleType[RuleType["IMPORT"] = 3] = "IMPORT";
16
+ RuleType[RuleType["FONT_FACE"] = 5] = "FONT_FACE";
17
+ RuleType[RuleType["PAGE"] = 6] = "PAGE";
18
+ RuleType[RuleType["KEYFRAMES"] = 7] = "KEYFRAMES";
19
+ RuleType[RuleType["KEYFRAME"] = 8] = "KEYFRAME";
20
+ })(RuleType || (RuleType = {}));
21
+ var arrayify = function arrayify(list) {
22
+ return [].slice.call(list, 0);
23
+ };
24
+ var rawDocumentBodyAppend = HTMLBodyElement.prototype.appendChild;
25
+ export var ScopedCSS = /*#__PURE__*/function () {
26
+ function ScopedCSS() {
27
+ _classCallCheck(this, ScopedCSS);
28
+ var styleNode = document.createElement('style');
29
+ rawDocumentBodyAppend.call(document.body, styleNode);
30
+ this.swapNode = styleNode;
31
+ this.sheet = styleNode.sheet;
32
+ this.sheet.disabled = true;
33
+ }
34
+ return _createClass(ScopedCSS, [{
35
+ key: "process",
36
+ value: function process(styleNode) {
37
+ var _this = this;
38
+ var prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
39
+ var _a;
40
+ if (styleNode.textContent !== '') {
41
+ var textNode = document.createTextNode(styleNode.textContent || '');
42
+ this.swapNode.appendChild(textNode);
43
+ var sheet = this.swapNode.sheet; // type is missing
44
+ var rules = arrayify((_a = sheet === null || sheet === void 0 ? void 0 : sheet.cssRules) !== null && _a !== void 0 ? _a : []);
45
+ var css = this.rewrite(rules, prefix);
46
+ // eslint-disable-next-line no-param-reassign
47
+ styleNode.textContent = css;
48
+ // cleanup
49
+ this.swapNode.removeChild(textNode);
50
+ return;
51
+ }
52
+ var mutator = new MutationObserver(function (mutations) {
53
+ var _a;
54
+ for (var i = 0; i < mutations.length; i += 1) {
55
+ var mutation = mutations[i];
56
+ if (ScopedCSS.ModifiedTag in styleNode) {
57
+ return;
58
+ }
59
+ if (mutation.type === 'childList') {
60
+ var _sheet = styleNode.sheet;
61
+ var _rules = arrayify((_a = _sheet === null || _sheet === void 0 ? void 0 : _sheet.cssRules) !== null && _a !== void 0 ? _a : []);
62
+ var _css = _this.rewrite(_rules, prefix);
63
+ // eslint-disable-next-line no-param-reassign
64
+ styleNode.textContent = _css;
65
+ // eslint-disable-next-line no-param-reassign
66
+ styleNode[ScopedCSS.ModifiedTag] = true;
67
+ }
68
+ }
69
+ });
70
+ // since observer will be deleted when node be removed
71
+ // we dont need create a cleanup function manually
72
+ // see https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver/disconnect
73
+ mutator.observe(styleNode, {
74
+ childList: true
75
+ });
76
+ }
77
+ }, {
78
+ key: "rewrite",
79
+ value: function rewrite(rules) {
80
+ var _this2 = this;
81
+ var prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
82
+ var css = '';
83
+ rules.forEach(function (rule) {
84
+ switch (rule.type) {
85
+ case RuleType.STYLE:
86
+ css += _this2.ruleStyle(rule, prefix);
87
+ break;
88
+ case RuleType.MEDIA:
89
+ css += _this2.ruleMedia(rule, prefix);
90
+ break;
91
+ case RuleType.SUPPORTS:
92
+ css += _this2.ruleSupport(rule, prefix);
93
+ break;
94
+ default:
95
+ css += "".concat(rule.cssText);
96
+ break;
97
+ }
98
+ });
99
+ return css;
100
+ }
101
+ // handle case:
102
+ // .app-main {}
103
+ // html, body {}
104
+ // eslint-disable-next-line class-methods-use-this
105
+ }, {
106
+ key: "ruleStyle",
107
+ value: function ruleStyle(rule, prefix) {
108
+ var rootSelectorRE = /((?:[^\w\-.#]|^)(body|html|:root))/gm;
109
+ var rootCombinationRE = /(html[^\w{[]+)/gm;
110
+ var selector = rule.selectorText.trim();
111
+ var cssText = rule.cssText;
112
+ // handle html { ... }
113
+ // handle body { ... }
114
+ // handle :root { ... }
115
+ if (selector === 'html' || selector === 'body' || selector === ':root') {
116
+ return cssText.replace(rootSelectorRE, prefix);
117
+ }
118
+ // handle html body { ... }
119
+ // handle html > body { ... }
120
+ if (rootCombinationRE.test(rule.selectorText)) {
121
+ var siblingSelectorRE = /(html[^\w{]+)(\+|~)/gm;
122
+ // since html + body is a non-standard rule for html
123
+ // transformer will ignore it
124
+ if (!siblingSelectorRE.test(rule.selectorText)) {
125
+ cssText = cssText.replace(rootCombinationRE, '');
126
+ }
127
+ }
128
+ // handle grouping selector, a,span,p,div { ... }
129
+ cssText = cssText.replace(/^[\s\S]+{/, function (selectors) {
130
+ return selectors.replace(/(^|,\n?)([^,]+)/g, function (item, p, s) {
131
+ // handle div,body,span { ... }
132
+ if (rootSelectorRE.test(item)) {
133
+ return item.replace(rootSelectorRE, function (m) {
134
+ // do not discard valid previous character, such as body,html or *:not(:root)
135
+ var whitePrevChars = [',', '('];
136
+ if (m && whitePrevChars.includes(m[0])) {
137
+ return "".concat(m[0]).concat(prefix);
138
+ }
139
+ // replace root selector with prefix
140
+ return prefix;
141
+ });
142
+ }
143
+ return "".concat(p).concat(prefix, " ").concat(s.replace(/^ */, ''));
144
+ });
145
+ });
146
+ return cssText;
147
+ }
148
+ // handle case:
149
+ // @media screen and (max-width: 300px) {}
150
+ }, {
151
+ key: "ruleMedia",
152
+ value: function ruleMedia(rule, prefix) {
153
+ var css = this.rewrite(arrayify(rule.cssRules), prefix);
154
+ return "@media ".concat(rule.conditionText, " {").concat(css, "}");
155
+ }
156
+ // handle case:
157
+ // @supports (display: grid) {}
158
+ }, {
159
+ key: "ruleSupport",
160
+ value: function ruleSupport(rule, prefix) {
161
+ var css = this.rewrite(arrayify(rule.cssRules), prefix);
162
+ return "@supports ".concat(rule.conditionText, " {").concat(css, "}");
163
+ }
164
+ }]);
165
+ }();
166
+ ScopedCSS.ModifiedTag = 'Symbol(style-modified-qiankun)';
167
+ var processor;
168
+ export var QiankunCSSRewriteAttr = 'data-qiankun';
169
+ export var process = function process(appWrapper, stylesheetElement, appName) {
170
+ // lazy singleton pattern
171
+ if (!processor) {
172
+ processor = new ScopedCSS();
173
+ }
174
+ if (stylesheetElement.tagName === 'LINK') {
175
+ console.warn('Feature: sandbox.experimentalStyleIsolation is not support for link element yet.');
176
+ }
177
+ var mountDOM = appWrapper;
178
+ if (!mountDOM) {
179
+ return;
180
+ }
181
+ var tag = (mountDOM.tagName || '').toLowerCase();
182
+ if (tag && stylesheetElement.tagName === 'STYLE') {
183
+ var prefix = "".concat(tag, "[").concat(QiankunCSSRewriteAttr, "=\"").concat(appName, "\"]");
184
+ processor.process(stylesheetElement, prefix);
185
+ }
186
+ };
@@ -0,0 +1,22 @@
1
+ export declare const rawHeadAppendChild: <T extends Node>(node: T) => T;
2
+ export declare function isHijackingTag(tagName?: string): boolean;
3
+ /**
4
+ * Check if a style element is a styled-component liked.
5
+ * A styled-components liked element is which not have textContext but keep the rules in its styleSheet.cssRules.
6
+ * Such as the style element generated by styled-components and emotion.
7
+ * @param element
8
+ */
9
+ export declare function isStyledComponentsLike(element: HTMLStyleElement): number | false | undefined;
10
+ export declare function recordStyledComponentsCSSRules(styleElements: HTMLStyleElement[]): void;
11
+ export declare function getStyledElementCSSRules(styledElement: HTMLStyleElement): CSSRuleList | undefined;
12
+ export type ContainerConfig = {
13
+ appName: string;
14
+ proxy: WindowProxy;
15
+ strictGlobal: boolean;
16
+ dynamicStyleSheetElements: HTMLStyleElement[];
17
+ appWrapperGetter: CallableFunction;
18
+ scopedCSS: boolean;
19
+ excludeAssetFilter?: CallableFunction;
20
+ };
21
+ export declare function patchHTMLDynamicAppendPrototypeFunctions(isInvokedByMicroApp: (element: HTMLElement) => boolean, containerConfigGetter: (element: HTMLElement) => ContainerConfig): () => void;
22
+ export declare function rebuildCSSRules(styleSheetElements: HTMLStyleElement[], reAppendElement: (stylesheetElement: HTMLStyleElement) => boolean): void;
@@ -0,0 +1,306 @@
1
+ import _isFunction from "lodash/isFunction";
2
+ /**
3
+ * @author Kuitos
4
+ * @since 2019-10-21
5
+ */
6
+ import { execScripts } from 'import-html-entry';
7
+ import { frameworkConfiguration } from '../../../apis';
8
+ import * as css from '../css';
9
+ export var rawHeadAppendChild = HTMLHeadElement.prototype.appendChild;
10
+ var rawHeadRemoveChild = HTMLHeadElement.prototype.removeChild;
11
+ var rawBodyAppendChild = HTMLBodyElement.prototype.appendChild;
12
+ var rawBodyRemoveChild = HTMLBodyElement.prototype.removeChild;
13
+ var rawHeadInsertBefore = HTMLHeadElement.prototype.insertBefore;
14
+ var rawRemoveChild = HTMLElement.prototype.removeChild;
15
+ var SCRIPT_TAG_NAME = 'SCRIPT';
16
+ var LINK_TAG_NAME = 'LINK';
17
+ var STYLE_TAG_NAME = 'STYLE';
18
+ export function isHijackingTag(tagName) {
19
+ return (tagName === null || tagName === void 0 ? void 0 : tagName.toUpperCase()) === LINK_TAG_NAME || (tagName === null || tagName === void 0 ? void 0 : tagName.toUpperCase()) === STYLE_TAG_NAME || (tagName === null || tagName === void 0 ? void 0 : tagName.toUpperCase()) === SCRIPT_TAG_NAME;
20
+ }
21
+ /**
22
+ * Check if a style element is a styled-component liked.
23
+ * A styled-components liked element is which not have textContext but keep the rules in its styleSheet.cssRules.
24
+ * Such as the style element generated by styled-components and emotion.
25
+ * @param element
26
+ */
27
+ export function isStyledComponentsLike(element) {
28
+ var _a, _b;
29
+ return !element.textContent && (((_a = element.sheet) === null || _a === void 0 ? void 0 : _a.cssRules.length) || ((_b = getStyledElementCSSRules(element)) === null || _b === void 0 ? void 0 : _b.length));
30
+ }
31
+ function patchCustomEvent(e, elementGetter) {
32
+ Object.defineProperties(e, {
33
+ srcElement: {
34
+ get: elementGetter
35
+ },
36
+ target: {
37
+ get: elementGetter
38
+ }
39
+ });
40
+ return e;
41
+ }
42
+ function manualInvokeElementOnLoad(element) {
43
+ // we need to invoke the onload event manually to notify the event listener that the script was completed
44
+ // here are the two typical ways of dynamic script loading
45
+ // 1. element.onload callback way, which webpack and loadjs used, see https://github.com/muicss/loadjs/blob/master/src/loadjs.js#L138
46
+ // 2. addEventListener way, which toast-loader used, see https://github.com/pyrsmk/toast/blob/master/src/Toast.ts#L64
47
+ var loadEvent = new CustomEvent('load');
48
+ var patchedEvent = patchCustomEvent(loadEvent, function () {
49
+ return element;
50
+ });
51
+ if (_isFunction(element.onload)) {
52
+ element.onload(patchedEvent);
53
+ } else {
54
+ element.dispatchEvent(patchedEvent);
55
+ }
56
+ }
57
+ function manualInvokeElementOnError(element) {
58
+ var errorEvent = new CustomEvent('error');
59
+ var patchedEvent = patchCustomEvent(errorEvent, function () {
60
+ return element;
61
+ });
62
+ if (_isFunction(element.onerror)) {
63
+ element.onerror(patchedEvent);
64
+ } else {
65
+ element.dispatchEvent(patchedEvent);
66
+ }
67
+ }
68
+ function convertLinkAsStyle(element, postProcess) {
69
+ var fetchFn = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : fetch;
70
+ var styleElement = document.createElement('style');
71
+ var href = element.href;
72
+ // add source link element href
73
+ styleElement.dataset.qiankunHref = href;
74
+ fetchFn(href).then(function (res) {
75
+ return res.text();
76
+ }).then(function (styleContext) {
77
+ styleElement.appendChild(document.createTextNode(styleContext));
78
+ postProcess(styleElement);
79
+ manualInvokeElementOnLoad(element);
80
+ }).catch(function () {
81
+ return manualInvokeElementOnError(element);
82
+ });
83
+ return styleElement;
84
+ }
85
+ var styledComponentCSSRulesMap = new WeakMap();
86
+ var dynamicScriptAttachedCommentMap = new WeakMap();
87
+ var dynamicLinkAttachedInlineStyleMap = new WeakMap();
88
+ export function recordStyledComponentsCSSRules(styleElements) {
89
+ styleElements.forEach(function (styleElement) {
90
+ /*
91
+ With a styled-components generated style element, we need to record its cssRules for restore next re-mounting time.
92
+ We're doing this because the sheet of style element is going to be cleaned automatically by browser after the style element dom removed from document.
93
+ see https://www.w3.org/TR/cssom-1/#associated-css-style-sheet
94
+ */
95
+ if (styleElement instanceof HTMLStyleElement && isStyledComponentsLike(styleElement)) {
96
+ if (styleElement.sheet) {
97
+ // record the original css rules of the style element for restore
98
+ styledComponentCSSRulesMap.set(styleElement, styleElement.sheet.cssRules);
99
+ }
100
+ }
101
+ });
102
+ }
103
+ export function getStyledElementCSSRules(styledElement) {
104
+ return styledComponentCSSRulesMap.get(styledElement);
105
+ }
106
+ function getOverwrittenAppendChildOrInsertBefore(opts) {
107
+ return function appendChildOrInsertBefore(newChild) {
108
+ var refChild = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
109
+ var _a, _b;
110
+ var element = newChild;
111
+ var rawDOMAppendOrInsertBefore = opts.rawDOMAppendOrInsertBefore,
112
+ isInvokedByMicroApp = opts.isInvokedByMicroApp,
113
+ containerConfigGetter = opts.containerConfigGetter;
114
+ if (!isHijackingTag(element.tagName) || !isInvokedByMicroApp(element)) {
115
+ return rawDOMAppendOrInsertBefore.call(this, element, refChild);
116
+ }
117
+ if (element.tagName) {
118
+ var containerConfig = containerConfigGetter(element);
119
+ var appName = containerConfig.appName,
120
+ appWrapperGetter = containerConfig.appWrapperGetter,
121
+ proxy = containerConfig.proxy,
122
+ strictGlobal = containerConfig.strictGlobal,
123
+ dynamicStyleSheetElements = containerConfig.dynamicStyleSheetElements,
124
+ scopedCSS = containerConfig.scopedCSS,
125
+ excludeAssetFilter = containerConfig.excludeAssetFilter;
126
+ switch (element.tagName) {
127
+ case LINK_TAG_NAME:
128
+ case STYLE_TAG_NAME:
129
+ {
130
+ var stylesheetElement = newChild;
131
+ var _stylesheetElement = stylesheetElement,
132
+ href = _stylesheetElement.href;
133
+ if (excludeAssetFilter && href && excludeAssetFilter(href)) {
134
+ return rawDOMAppendOrInsertBefore.call(this, element, refChild);
135
+ }
136
+ var mountDOM = appWrapperGetter();
137
+ if (scopedCSS) {
138
+ // exclude link elements like <link rel="icon" href="favicon.ico">
139
+ var linkElementUsingStylesheet = ((_a = element.tagName) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === LINK_TAG_NAME && element.rel === 'stylesheet' && element.href;
140
+ if (linkElementUsingStylesheet) {
141
+ var _fetch = typeof frameworkConfiguration.fetch === 'function' ? frameworkConfiguration.fetch : (_b = frameworkConfiguration.fetch) === null || _b === void 0 ? void 0 : _b.fn;
142
+ stylesheetElement = convertLinkAsStyle(element, function (styleElement) {
143
+ return css.process(mountDOM, styleElement, appName);
144
+ }, _fetch);
145
+ dynamicLinkAttachedInlineStyleMap.set(element, stylesheetElement);
146
+ } else {
147
+ css.process(mountDOM, stylesheetElement, appName);
148
+ }
149
+ }
150
+ // eslint-disable-next-line no-shadow
151
+ dynamicStyleSheetElements.push(stylesheetElement);
152
+ var referenceNode = mountDOM.contains(refChild) ? refChild : null;
153
+ return rawDOMAppendOrInsertBefore.call(mountDOM, stylesheetElement, referenceNode);
154
+ }
155
+ case SCRIPT_TAG_NAME:
156
+ {
157
+ var _element = element,
158
+ src = _element.src,
159
+ text = _element.text;
160
+ // some script like jsonp maybe not support cors which should't use execScripts
161
+ if (excludeAssetFilter && src && excludeAssetFilter(src)) {
162
+ return rawDOMAppendOrInsertBefore.call(this, element, refChild);
163
+ }
164
+ var _mountDOM = appWrapperGetter();
165
+ var _fetch2 = frameworkConfiguration.fetch;
166
+ var _referenceNode = _mountDOM.contains(refChild) ? refChild : null;
167
+ if (src) {
168
+ execScripts(null, [src], proxy, {
169
+ fetch: _fetch2,
170
+ strictGlobal: strictGlobal,
171
+ beforeExec: function beforeExec() {
172
+ var isCurrentScriptConfigurable = function isCurrentScriptConfigurable() {
173
+ var descriptor = Object.getOwnPropertyDescriptor(document, 'currentScript');
174
+ return !descriptor || descriptor.configurable;
175
+ };
176
+ if (isCurrentScriptConfigurable()) {
177
+ Object.defineProperty(document, 'currentScript', {
178
+ get: function get() {
179
+ return element;
180
+ },
181
+ configurable: true
182
+ });
183
+ }
184
+ },
185
+ success: function success() {
186
+ manualInvokeElementOnLoad(element);
187
+ element = null;
188
+ },
189
+ error: function error() {
190
+ manualInvokeElementOnError(element);
191
+ element = null;
192
+ }
193
+ });
194
+ var dynamicScriptCommentElement = document.createComment("dynamic script ".concat(src, " replaced by qiankun"));
195
+ dynamicScriptAttachedCommentMap.set(element, dynamicScriptCommentElement);
196
+ return rawDOMAppendOrInsertBefore.call(_mountDOM, dynamicScriptCommentElement, _referenceNode);
197
+ }
198
+ // inline script never trigger the onload and onerror event
199
+ execScripts(null, ["<script>".concat(text, "</script>")], proxy, {
200
+ strictGlobal: strictGlobal
201
+ });
202
+ var dynamicInlineScriptCommentElement = document.createComment('dynamic inline script replaced by qiankun');
203
+ dynamicScriptAttachedCommentMap.set(element, dynamicInlineScriptCommentElement);
204
+ return rawDOMAppendOrInsertBefore.call(_mountDOM, dynamicInlineScriptCommentElement, _referenceNode);
205
+ }
206
+ default:
207
+ break;
208
+ }
209
+ }
210
+ return rawDOMAppendOrInsertBefore.call(this, element, refChild);
211
+ };
212
+ }
213
+ function getNewRemoveChild(headOrBodyRemoveChild, appWrapperGetterGetter) {
214
+ return function removeChild(child) {
215
+ var tagName = child.tagName;
216
+ if (!isHijackingTag(tagName)) return headOrBodyRemoveChild.call(this, child);
217
+ try {
218
+ var attachedElement;
219
+ switch (tagName) {
220
+ case LINK_TAG_NAME:
221
+ {
222
+ attachedElement = dynamicLinkAttachedInlineStyleMap.get(child) || child;
223
+ break;
224
+ }
225
+ case SCRIPT_TAG_NAME:
226
+ {
227
+ attachedElement = dynamicScriptAttachedCommentMap.get(child) || child;
228
+ break;
229
+ }
230
+ default:
231
+ {
232
+ attachedElement = child;
233
+ }
234
+ }
235
+ // container may had been removed while app unmounting if the removeChild action was async
236
+ var appWrapperGetter = appWrapperGetterGetter(child);
237
+ var container = appWrapperGetter();
238
+ if (container.contains(attachedElement)) {
239
+ return rawRemoveChild.call(container, attachedElement);
240
+ }
241
+ } catch (e) {
242
+ console.warn(e);
243
+ }
244
+ return headOrBodyRemoveChild.call(this, child);
245
+ };
246
+ }
247
+ export function patchHTMLDynamicAppendPrototypeFunctions(isInvokedByMicroApp, containerConfigGetter) {
248
+ // Just overwrite it while it have not been overwrite
249
+ if (HTMLHeadElement.prototype.appendChild === rawHeadAppendChild && HTMLBodyElement.prototype.appendChild === rawBodyAppendChild && HTMLHeadElement.prototype.insertBefore === rawHeadInsertBefore) {
250
+ HTMLHeadElement.prototype.appendChild = getOverwrittenAppendChildOrInsertBefore({
251
+ rawDOMAppendOrInsertBefore: rawHeadAppendChild,
252
+ containerConfigGetter: containerConfigGetter,
253
+ isInvokedByMicroApp: isInvokedByMicroApp
254
+ });
255
+ HTMLBodyElement.prototype.appendChild = getOverwrittenAppendChildOrInsertBefore({
256
+ rawDOMAppendOrInsertBefore: rawBodyAppendChild,
257
+ containerConfigGetter: containerConfigGetter,
258
+ isInvokedByMicroApp: isInvokedByMicroApp
259
+ });
260
+ HTMLHeadElement.prototype.insertBefore = getOverwrittenAppendChildOrInsertBefore({
261
+ rawDOMAppendOrInsertBefore: rawHeadInsertBefore,
262
+ containerConfigGetter: containerConfigGetter,
263
+ isInvokedByMicroApp: isInvokedByMicroApp
264
+ });
265
+ }
266
+ // Just overwrite it while it have not been overwrite
267
+ if (HTMLHeadElement.prototype.removeChild === rawHeadRemoveChild && HTMLBodyElement.prototype.removeChild === rawBodyRemoveChild) {
268
+ HTMLHeadElement.prototype.removeChild = getNewRemoveChild(rawHeadRemoveChild, function (element) {
269
+ return containerConfigGetter(element).appWrapperGetter;
270
+ });
271
+ HTMLBodyElement.prototype.removeChild = getNewRemoveChild(rawBodyRemoveChild, function (element) {
272
+ return containerConfigGetter(element).appWrapperGetter;
273
+ });
274
+ }
275
+ return function unpatch() {
276
+ HTMLHeadElement.prototype.appendChild = rawHeadAppendChild;
277
+ HTMLHeadElement.prototype.removeChild = rawHeadRemoveChild;
278
+ HTMLBodyElement.prototype.appendChild = rawBodyAppendChild;
279
+ HTMLBodyElement.prototype.removeChild = rawBodyRemoveChild;
280
+ HTMLHeadElement.prototype.insertBefore = rawHeadInsertBefore;
281
+ };
282
+ }
283
+ export function rebuildCSSRules(styleSheetElements, reAppendElement) {
284
+ styleSheetElements.forEach(function (stylesheetElement) {
285
+ // re-append the dynamic stylesheet to sub-app container
286
+ var appendSuccess = reAppendElement(stylesheetElement);
287
+ if (appendSuccess) {
288
+ /*
289
+ get the stored css rules from styled-components generated element, and the re-insert rules for them.
290
+ note that we must do this after style element had been added to document, which stylesheet would be associated to the document automatically.
291
+ check the spec https://www.w3.org/TR/cssom-1/#associated-css-style-sheet
292
+ */
293
+ if (stylesheetElement instanceof HTMLStyleElement && isStyledComponentsLike(stylesheetElement)) {
294
+ var cssRules = getStyledElementCSSRules(stylesheetElement);
295
+ if (cssRules) {
296
+ // eslint-disable-next-line no-plusplus
297
+ for (var i = 0; i < cssRules.length; i++) {
298
+ var cssRule = cssRules[i];
299
+ var cssStyleSheetElement = stylesheetElement.sheet;
300
+ cssStyleSheetElement.insertRule(cssRule.cssText, cssStyleSheetElement.cssRules.length);
301
+ }
302
+ }
303
+ }
304
+ }
305
+ });
306
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @author Kuitos
3
+ * @since 2020-10-13
4
+ */
5
+ import type { Freer } from '../../../interfaces';
6
+ /**
7
+ * Just hijack dynamic head append, that could avoid accidentally hijacking the insertion of elements except in head.
8
+ * Such a case: ReactDOM.createPortal(<style>.test{color:blue}</style>, container),
9
+ * this could made we append the style element into app wrapper but it will cause an error while the react portal unmounting, as ReactDOM could not find the style in body children list.
10
+ * @param appName
11
+ * @param appWrapperGetter
12
+ * @param proxy
13
+ * @param mounting
14
+ * @param scopedCSS
15
+ * @param excludeAssetFilter
16
+ */
17
+ export declare function patchLooseSandbox(appName: string, appWrapperGetter: () => HTMLElement | ShadowRoot, proxy: Window, mounting?: boolean, scopedCSS?: boolean, excludeAssetFilter?: CallableFunction): Freer;
@@ -0,0 +1,77 @@
1
+ /**
2
+ * @author Kuitos
3
+ * @since 2020-10-13
4
+ */
5
+ import { checkActivityFunctions } from 'single-spa';
6
+ import { patchHTMLDynamicAppendPrototypeFunctions, rebuildCSSRules, recordStyledComponentsCSSRules } from './common';
7
+ var bootstrappingPatchCount = 0;
8
+ var mountingPatchCount = 0;
9
+ /**
10
+ * Just hijack dynamic head append, that could avoid accidentally hijacking the insertion of elements except in head.
11
+ * Such a case: ReactDOM.createPortal(<style>.test{color:blue}</style>, container),
12
+ * this could made we append the style element into app wrapper but it will cause an error while the react portal unmounting, as ReactDOM could not find the style in body children list.
13
+ * @param appName
14
+ * @param appWrapperGetter
15
+ * @param proxy
16
+ * @param mounting
17
+ * @param scopedCSS
18
+ * @param excludeAssetFilter
19
+ */
20
+ export function patchLooseSandbox(appName, appWrapperGetter, proxy) {
21
+ var mounting = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
22
+ var scopedCSS = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
23
+ var excludeAssetFilter = arguments.length > 5 ? arguments[5] : undefined;
24
+ var dynamicStyleSheetElements = [];
25
+ var unpatchDynamicAppendPrototypeFunctions = patchHTMLDynamicAppendPrototypeFunctions(
26
+ /*
27
+ check if the currently specified application is active
28
+ While we switch page from qiankun app to a normal react routing page, the normal one may load stylesheet dynamically while page rendering,
29
+ but the url change listener must to wait until the current call stack is flushed.
30
+ This scenario may cause we record the stylesheet from react routing page dynamic injection,
31
+ and remove them after the url change triggered and qiankun app is unmouting
32
+ see https://github.com/ReactTraining/history/blob/master/modules/createHashHistory.js#L222-L230
33
+ */
34
+ function () {
35
+ return checkActivityFunctions(window.location).some(function (name) {
36
+ return name === appName;
37
+ });
38
+ }, function () {
39
+ return {
40
+ appName: appName,
41
+ appWrapperGetter: appWrapperGetter,
42
+ proxy: proxy,
43
+ strictGlobal: false,
44
+ scopedCSS: scopedCSS,
45
+ dynamicStyleSheetElements: dynamicStyleSheetElements,
46
+ excludeAssetFilter: excludeAssetFilter
47
+ };
48
+ });
49
+ if (!mounting) bootstrappingPatchCount++;
50
+ if (mounting) mountingPatchCount++;
51
+ return function free() {
52
+ // bootstrap patch just called once but its freer will be called multiple times
53
+ if (!mounting && bootstrappingPatchCount !== 0) bootstrappingPatchCount--;
54
+ if (mounting) mountingPatchCount--;
55
+ var allMicroAppUnmounted = mountingPatchCount === 0 && bootstrappingPatchCount === 0;
56
+ // release the overwrite prototype after all the micro apps unmounted
57
+ if (allMicroAppUnmounted) unpatchDynamicAppendPrototypeFunctions();
58
+ recordStyledComponentsCSSRules(dynamicStyleSheetElements);
59
+ // As now the sub app content all wrapped with a special id container,
60
+ // the dynamic style sheet would be removed automatically while unmoutting
61
+ return function rebuild() {
62
+ rebuildCSSRules(dynamicStyleSheetElements, function (stylesheetElement) {
63
+ var appWrapper = appWrapperGetter();
64
+ if (!appWrapper.contains(stylesheetElement)) {
65
+ // Using document.head.appendChild ensures that appendChild invocation can also directly use the HTMLHeadElement.prototype.appendChild method which is overwritten at mounting phase
66
+ document.head.appendChild.call(appWrapper, stylesheetElement);
67
+ return true;
68
+ }
69
+ return false;
70
+ });
71
+ // As the patcher will be invoked every mounting phase, we could release the cache for gc after rebuilding
72
+ if (mounting) {
73
+ dynamicStyleSheetElements = [];
74
+ }
75
+ };
76
+ };
77
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @author Kuitos
3
+ * @since 2020-10-13
4
+ */
5
+ import type { Freer } from '../../../interfaces';
6
+ import type { ContainerConfig } from './common';
7
+ declare global {
8
+ interface Window {
9
+ __proxyAttachContainerConfigMap__: WeakMap<WindowProxy, ContainerConfig>;
10
+ }
11
+ }
12
+ export declare function patchStrictSandbox(appName: string, appWrapperGetter: () => HTMLElement | ShadowRoot, proxy: Window, mounting?: boolean, scopedCSS?: boolean, excludeAssetFilter?: CallableFunction): Freer;