@blueking/bk-weweb 0.0.23 → 0.0.26
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/dist/collect-source.js +521 -311
- package/dist/collect-source.js.map +1 -1
- package/dist/index.esm.js +488 -276
- package/dist/index.esm.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/package.json +38 -42
- package/typings/base-app/collect-source.d.ts +3 -0
- package/typings/base-app/element.d.ts +13 -0
- package/typings/cache/app-cache.d.ts +1 -1
- package/typings/common/state.d.ts +8 -8
- package/typings/component/web-compnent.d.ts +12 -12
- package/typings/context/cache.d.ts +0 -1
- package/typings/context/document.d.ts +8 -4
- package/typings/context/sandbox.d.ts +2 -1
- package/typings/entry/entry.d.ts +1 -1
- package/typings/entry/script.d.ts +6 -1
- package/typings/entry/style.d.ts +9 -1
- package/typings/index.d.ts +2 -2
- package/typings/mode/app.d.ts +4 -2
- package/typings/mode/instance.d.ts +1 -1
- package/typings/typings/model.d.ts +2 -1
- package/CHANGELOG.md +0 -0
package/dist/collect-source.js
CHANGED
|
@@ -37,6 +37,7 @@ var AppState;
|
|
|
37
37
|
AppState["UNSET"] = "UNSET";
|
|
38
38
|
})(AppState || (AppState = {}));
|
|
39
39
|
|
|
40
|
+
// 当前正在运行的app
|
|
40
41
|
let currentRunningApp = null;
|
|
41
42
|
function getCurrentRunningApp() {
|
|
42
43
|
return currentRunningApp;
|
|
@@ -44,12 +45,6 @@ function getCurrentRunningApp() {
|
|
|
44
45
|
function setCurrentRunningApp(appInstance) {
|
|
45
46
|
currentRunningApp = appInstance;
|
|
46
47
|
}
|
|
47
|
-
const SCOPED_CSS_STYLE_ID = 'SCOPED_CSS_STYLE_ID';
|
|
48
|
-
const templateStyle = document.createElement('style');
|
|
49
|
-
templateStyle.setAttribute('id', SCOPED_CSS_STYLE_ID);
|
|
50
|
-
document.body.appendChild(templateStyle);
|
|
51
|
-
templateStyle.sheet.disabled = true;
|
|
52
|
-
const disabledStyleDom = templateStyle;
|
|
53
48
|
const windowNativeFuncMap = new Map();
|
|
54
49
|
/**
|
|
55
50
|
* 收集原生window方法
|
|
@@ -164,122 +159,6 @@ const isJsonpUrl = (url) => {
|
|
|
164
159
|
return !pathname.match(/\.js$/);
|
|
165
160
|
};
|
|
166
161
|
|
|
167
|
-
const { document: document$1 } = window;
|
|
168
|
-
const { createElement, getElementById, getElementsByClassName, getElementsByName, getElementsByTagName, querySelector, querySelectorAll, } = Document.prototype;
|
|
169
|
-
const { querySelector: bodyQuerySelector } = HTMLBodyElement.prototype;
|
|
170
|
-
const SPECIAL_ELEMENT_TAG = ['body', 'html', 'head'];
|
|
171
|
-
let hasRewrite$1 = false;
|
|
172
|
-
function rewriteDocumentPrototypeMethods() {
|
|
173
|
-
if (hasRewrite$1)
|
|
174
|
-
return;
|
|
175
|
-
hasRewrite$1 = true;
|
|
176
|
-
Document.prototype.createElement = function (tagName, options) {
|
|
177
|
-
const element = createElement.call(this, tagName, options);
|
|
178
|
-
const app = getCurrentRunningApp();
|
|
179
|
-
// img.src = 'xxx' iframe.src = 'xxx' 均不能在setAttributes上监听 但是这里所有的src都是 全地址 无法判断是否需要添加子应用域名
|
|
180
|
-
// if (tagName.toLocaleLowerCase() === 'img') {
|
|
181
|
-
// const observer = new MutationObserver((list, observer) => {
|
|
182
|
-
// observer.disconnect();
|
|
183
|
-
// const url = new URL((element as HTMLImageElement).src)
|
|
184
|
-
// (element as HTMLImageElement).src = `${}`
|
|
185
|
-
// });
|
|
186
|
-
// observer.observe(element, { attributeFilter: ['src'], subtree: false, childList: false });
|
|
187
|
-
// }
|
|
188
|
-
if (app)
|
|
189
|
-
element.__BK_WEWEB_APP_KEY__ = app.appCacheKey;
|
|
190
|
-
return element;
|
|
191
|
-
};
|
|
192
|
-
/**
|
|
193
|
-
* 查询选择器的新方法
|
|
194
|
-
* @param selectors 选择器字符串
|
|
195
|
-
* @returns 匹配的元素或 null
|
|
196
|
-
*/
|
|
197
|
-
function querySelectorNew(selectors) {
|
|
198
|
-
const app = getCurrentRunningApp();
|
|
199
|
-
// 如果选择器是特殊元素标签
|
|
200
|
-
if (SPECIAL_ELEMENT_TAG.includes(selectors)) {
|
|
201
|
-
// 如果当前应用程序容器是 ShadowRoot 类型
|
|
202
|
-
if (app?.container instanceof ShadowRoot) {
|
|
203
|
-
return app?.container;
|
|
204
|
-
}
|
|
205
|
-
if (this instanceof HTMLBodyElement)
|
|
206
|
-
return bodyQuerySelector.call(this, selectors);
|
|
207
|
-
// 否则调用原始的 querySelector 方法
|
|
208
|
-
return querySelector.call(this, selectors);
|
|
209
|
-
}
|
|
210
|
-
// 如果没有当前应用程序或选择器为空或文档不是当前文档
|
|
211
|
-
if (!app || !selectors || ![document$1, document$1.body].includes(this)) {
|
|
212
|
-
if (this instanceof HTMLBodyElement)
|
|
213
|
-
return bodyQuerySelector.call(this, selectors);
|
|
214
|
-
// 调用原始的 querySelector 方法
|
|
215
|
-
return querySelector.call(this, selectors);
|
|
216
|
-
}
|
|
217
|
-
// 返回当前应用程序容器中匹配选择器的元素,如果没有匹配的元素则返回 null
|
|
218
|
-
return app?.container?.querySelector(selectors) ?? null;
|
|
219
|
-
}
|
|
220
|
-
/**
|
|
221
|
-
* 重写了 Document 类的 querySelectorAll 方法
|
|
222
|
-
* @param selectors - 要查询的选择器
|
|
223
|
-
* @returns 匹配到的元素列表或空数组
|
|
224
|
-
*/
|
|
225
|
-
function querySelectorAllNew(selectors) {
|
|
226
|
-
const app = getCurrentRunningApp();
|
|
227
|
-
// 如果选择器是特殊元素标签,则返回容器元素或调用原生 querySelector 方法
|
|
228
|
-
if (SPECIAL_ELEMENT_TAG.includes(selectors)) {
|
|
229
|
-
if (app?.container instanceof ShadowRoot) {
|
|
230
|
-
return app?.container;
|
|
231
|
-
}
|
|
232
|
-
return querySelector.call(this, selectors);
|
|
233
|
-
}
|
|
234
|
-
// 如果没有运行中的应用程序、选择器为空或文档不是当前文档,则调用原生 querySelectorAll 方法
|
|
235
|
-
if (!app || !selectors || document$1 !== this) {
|
|
236
|
-
return querySelectorAll.call(this, selectors);
|
|
237
|
-
}
|
|
238
|
-
// 返回运行中应用程序的容器元素中匹配到的元素列表或空数组
|
|
239
|
-
return app?.container?.querySelectorAll(selectors) ?? [];
|
|
240
|
-
}
|
|
241
|
-
Document.prototype.querySelector = querySelectorNew;
|
|
242
|
-
Document.prototype.querySelectorAll = querySelectorAllNew;
|
|
243
|
-
HTMLBodyElement.prototype.querySelector = querySelectorNew;
|
|
244
|
-
Document.prototype.getElementById = function getElementByIdNew(key) {
|
|
245
|
-
return getCurrentRunningApp() ? querySelectorNew.call(this, `#${key}`) : getElementById.call(this, key);
|
|
246
|
-
};
|
|
247
|
-
Document.prototype.getElementsByClassName = function (key) {
|
|
248
|
-
return getCurrentRunningApp() ? querySelectorAllNew.call(this, `.${key}`) : getElementsByClassName.call(this, key);
|
|
249
|
-
};
|
|
250
|
-
// eslint-disable-next-line max-len
|
|
251
|
-
Document.prototype.getElementsByTagName = function (key) {
|
|
252
|
-
const app = getCurrentRunningApp();
|
|
253
|
-
if (!app || SPECIAL_ELEMENT_TAG.includes(key) || (!app?.showSourceCode && key.toLocaleLowerCase() === 'script')) {
|
|
254
|
-
return getElementsByTagName.call(this, key);
|
|
255
|
-
}
|
|
256
|
-
return querySelectorAllNew.call(this, key);
|
|
257
|
-
};
|
|
258
|
-
Document.prototype.getElementsByName = function (key) {
|
|
259
|
-
return getCurrentRunningApp() ? querySelectorAllNew.call(this, `[name=${key}]`) : getElementsByName.call(this, key);
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
function resetDocumentPrototypeMethods() {
|
|
263
|
-
Document.prototype.createElement = createElement;
|
|
264
|
-
Document.prototype.querySelector = querySelector;
|
|
265
|
-
HTMLBodyElement.prototype.querySelector = bodyQuerySelector;
|
|
266
|
-
Document.prototype.querySelectorAll = querySelectorAll;
|
|
267
|
-
Document.prototype.getElementById = getElementById;
|
|
268
|
-
Document.prototype.getElementsByClassName = getElementsByClassName;
|
|
269
|
-
Document.prototype.getElementsByTagName = getElementsByTagName;
|
|
270
|
-
Document.prototype.getElementsByName = getElementsByName;
|
|
271
|
-
hasRewrite$1 = false;
|
|
272
|
-
}
|
|
273
|
-
// vue3.3之后会换成document 这些需要初始化调用的app
|
|
274
|
-
function createRewriteDocument(rawDocument, app) {
|
|
275
|
-
return Object.defineProperty(rawDocument, 'createElement', {
|
|
276
|
-
get() {
|
|
277
|
-
app?.registerRunningApp();
|
|
278
|
-
return Document.prototype.createElement;
|
|
279
|
-
},
|
|
280
|
-
});
|
|
281
|
-
}
|
|
282
|
-
|
|
283
162
|
/*
|
|
284
163
|
* Tencent is pleased to support the open source community by making
|
|
285
164
|
* 蓝鲸智云PaaS平台 (BlueKing PaaS) available.
|
|
@@ -350,6 +229,42 @@ function dispatchLinkOrScriptError(element) {
|
|
|
350
229
|
element.dispatchEvent(event);
|
|
351
230
|
}
|
|
352
231
|
|
|
232
|
+
/*
|
|
233
|
+
* Tencent is pleased to support the open source community by making
|
|
234
|
+
* 蓝鲸智云PaaS平台 (BlueKing PaaS) available.
|
|
235
|
+
*
|
|
236
|
+
* Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
|
|
237
|
+
*
|
|
238
|
+
* 蓝鲸智云PaaS平台 (BlueKing PaaS) is licensed under the MIT License.
|
|
239
|
+
*
|
|
240
|
+
* License for 蓝鲸智云PaaS平台 (BlueKing PaaS):
|
|
241
|
+
*
|
|
242
|
+
* ---------------------------------------------------
|
|
243
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
|
244
|
+
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation
|
|
245
|
+
* the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
|
|
246
|
+
* to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
247
|
+
*
|
|
248
|
+
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of
|
|
249
|
+
* the Software.
|
|
250
|
+
*
|
|
251
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
|
252
|
+
* THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
253
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
|
254
|
+
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
255
|
+
* IN THE SOFTWARE.
|
|
256
|
+
*/
|
|
257
|
+
// deactivated
|
|
258
|
+
function deactivated(appKey) {
|
|
259
|
+
const app = appCache.getApp(appKey);
|
|
260
|
+
if (app && [AppState.ACTIVATED, AppState.MOUNTED].includes(app.status)) {
|
|
261
|
+
app.keepAlive ? app.deactivated() : app.unmount();
|
|
262
|
+
}
|
|
263
|
+
if (!appCache.hasActiveApp) {
|
|
264
|
+
resetBodyAndHeaderMethods();
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
353
268
|
/*
|
|
354
269
|
* Tencent is pleased to support the open source community by making
|
|
355
270
|
* 蓝鲸智云PaaS平台 (BlueKing PaaS) available.
|
|
@@ -441,6 +356,7 @@ function loadInstance(props) {
|
|
|
441
356
|
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
442
357
|
* IN THE SOFTWARE.
|
|
443
358
|
*/
|
|
359
|
+
// unmount
|
|
444
360
|
function unmount(appKey) {
|
|
445
361
|
const app = appCache.getApp(appKey);
|
|
446
362
|
if (app && app.status !== AppState.UNMOUNT) {
|
|
@@ -448,43 +364,6 @@ function unmount(appKey) {
|
|
|
448
364
|
}
|
|
449
365
|
if (!appCache.hasActiveApp) {
|
|
450
366
|
resetBodyAndHeaderMethods();
|
|
451
|
-
resetDocumentPrototypeMethods();
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
/*
|
|
456
|
-
* Tencent is pleased to support the open source community by making
|
|
457
|
-
* 蓝鲸智云PaaS平台 (BlueKing PaaS) available.
|
|
458
|
-
*
|
|
459
|
-
* Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
|
|
460
|
-
*
|
|
461
|
-
* 蓝鲸智云PaaS平台 (BlueKing PaaS) is licensed under the MIT License.
|
|
462
|
-
*
|
|
463
|
-
* License for 蓝鲸智云PaaS平台 (BlueKing PaaS):
|
|
464
|
-
*
|
|
465
|
-
* ---------------------------------------------------
|
|
466
|
-
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
|
467
|
-
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation
|
|
468
|
-
* the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
|
|
469
|
-
* to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
470
|
-
*
|
|
471
|
-
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of
|
|
472
|
-
* the Software.
|
|
473
|
-
*
|
|
474
|
-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
|
475
|
-
* THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
476
|
-
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
|
477
|
-
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
478
|
-
* IN THE SOFTWARE.
|
|
479
|
-
*/
|
|
480
|
-
function deactivated(appKey) {
|
|
481
|
-
const app = appCache.getApp(appKey);
|
|
482
|
-
if (app && [AppState.ACTIVATED, AppState.MOUNTED].includes(app.status)) {
|
|
483
|
-
app.keepAlive ? app.deactivated() : app.unmount();
|
|
484
|
-
}
|
|
485
|
-
if (!appCache.hasActiveApp) {
|
|
486
|
-
resetBodyAndHeaderMethods();
|
|
487
|
-
resetDocumentPrototypeMethods();
|
|
488
367
|
}
|
|
489
368
|
}
|
|
490
369
|
|
|
@@ -675,7 +554,6 @@ function fetchSource(url, options = {}) {
|
|
|
675
554
|
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
676
555
|
* IN THE SOFTWARE.
|
|
677
556
|
*/
|
|
678
|
-
/* eslint-disable no-param-reassign */
|
|
679
557
|
class Style {
|
|
680
558
|
code = '';
|
|
681
559
|
fromHtml;
|
|
@@ -694,9 +572,15 @@ class Style {
|
|
|
694
572
|
this.fromHtml = fromHtml;
|
|
695
573
|
this.initial = initial ?? false;
|
|
696
574
|
}
|
|
697
|
-
|
|
575
|
+
/**
|
|
576
|
+
* @param styleElement 样式node
|
|
577
|
+
* @param app 应用实例
|
|
578
|
+
*/
|
|
579
|
+
commonScoped(styleElement, app) {
|
|
698
580
|
if (app.scopeCss && !(app.container instanceof ShadowRoot)) {
|
|
699
|
-
const
|
|
581
|
+
const cssStyleSheet = new CSSStyleSheet({ disabled: true });
|
|
582
|
+
cssStyleSheet.replaceSync(styleElement.textContent || this.code);
|
|
583
|
+
const rules = Array.from(cssStyleSheet?.cssRules ?? []);
|
|
700
584
|
const cssPrefix = `#${app.name}`;
|
|
701
585
|
const scopedCss = this.scopeRule(rules, cssPrefix);
|
|
702
586
|
const cssText = this.resetUrlHost(scopedCss, app.url, this.url);
|
|
@@ -704,7 +588,7 @@ class Style {
|
|
|
704
588
|
this.scopedCode = cssText;
|
|
705
589
|
}
|
|
706
590
|
else {
|
|
707
|
-
const cssText = this.resetUrlHost(styleElement.textContent ||
|
|
591
|
+
const cssText = this.resetUrlHost(styleElement.textContent || this.code || '', app.url, this.url);
|
|
708
592
|
// fix https://bugs.chromium.org/p/chromium/issues/detail?id=336876
|
|
709
593
|
if (cssText && app.container instanceof ShadowRoot) {
|
|
710
594
|
let fontContent = '';
|
|
@@ -730,6 +614,10 @@ class Style {
|
|
|
730
614
|
delete styleElement.__BK_WEWEB_APP_KEY__;
|
|
731
615
|
return styleElement;
|
|
732
616
|
}
|
|
617
|
+
/**
|
|
618
|
+
* @param app 应用实例
|
|
619
|
+
* @returns 返回执行后的style标签
|
|
620
|
+
*/
|
|
733
621
|
async excuteCode(app) {
|
|
734
622
|
app.registerRunningApp();
|
|
735
623
|
let styleElement = this.createStyleElement();
|
|
@@ -837,11 +725,9 @@ class Style {
|
|
|
837
725
|
const container = needKeepAlive ? document.head : app.container;
|
|
838
726
|
try {
|
|
839
727
|
if (this.code) {
|
|
840
|
-
|
|
841
|
-
this.commonScoped(disabledStyleDom, styleElement, app);
|
|
728
|
+
this.commonScoped(styleElement, app);
|
|
842
729
|
container?.prepend(styleElement);
|
|
843
730
|
linkElement && dispatchLinkOrScriptLoad(linkElement);
|
|
844
|
-
disabledStyleDom.textContent = '';
|
|
845
731
|
}
|
|
846
732
|
else if (linkElement.getAttribute('href')) {
|
|
847
733
|
this.url = fillUpPath(linkElement.getAttribute('href'), app.url);
|
|
@@ -885,9 +771,7 @@ class Style {
|
|
|
885
771
|
}
|
|
886
772
|
if (this.linkedBaseStyle(styleElement, app))
|
|
887
773
|
return styleElement;
|
|
888
|
-
|
|
889
|
-
this.commonScoped(disabledStyleDom, styleElement, app);
|
|
890
|
-
disabledStyleDom.textContent = '';
|
|
774
|
+
this.commonScoped(styleElement, app);
|
|
891
775
|
}
|
|
892
776
|
else {
|
|
893
777
|
const observer = new MutationObserver(() => {
|
|
@@ -895,7 +779,7 @@ class Style {
|
|
|
895
779
|
return;
|
|
896
780
|
observer.disconnect();
|
|
897
781
|
if (!this.linkedBaseStyle(styleElement, app)) {
|
|
898
|
-
this.commonScoped(styleElement,
|
|
782
|
+
this.commonScoped(styleElement, app);
|
|
899
783
|
}
|
|
900
784
|
});
|
|
901
785
|
observer.observe(styleElement, { attributes: false, characterData: true, childList: true, subtree: true });
|
|
@@ -946,21 +830,22 @@ async function excuteAppStyles(app, container) {
|
|
|
946
830
|
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
947
831
|
* IN THE SOFTWARE.
|
|
948
832
|
*/
|
|
833
|
+
// bk-kweweb 微模块模式
|
|
949
834
|
class MicroInstanceModel {
|
|
950
|
-
state = AppState.UNSET;
|
|
951
|
-
appCacheKey;
|
|
952
|
-
container;
|
|
953
|
-
data;
|
|
954
|
-
initSource;
|
|
955
|
-
isPreLoad = false;
|
|
956
|
-
keepAlive;
|
|
957
|
-
name;
|
|
958
|
-
sandBox;
|
|
959
|
-
scopeCss = true;
|
|
960
|
-
scopeJs = false;
|
|
961
|
-
showSourceCode = true;
|
|
962
|
-
source;
|
|
963
|
-
url;
|
|
835
|
+
state = AppState.UNSET; // 当前实例状态
|
|
836
|
+
appCacheKey; // 缓存key
|
|
837
|
+
container; // 容器
|
|
838
|
+
data; // 数据
|
|
839
|
+
initSource; // 初始资源
|
|
840
|
+
isPreLoad = false; // 是否预加载
|
|
841
|
+
keepAlive; // 是否缓存
|
|
842
|
+
name; // 名称
|
|
843
|
+
sandBox; // 沙箱
|
|
844
|
+
scopeCss = true; // 是否隔离样式
|
|
845
|
+
scopeJs = false; // 是否隔离js
|
|
846
|
+
showSourceCode = true; // 是否显示源码
|
|
847
|
+
source; // 入口资源
|
|
848
|
+
url; // url
|
|
964
849
|
constructor(props) {
|
|
965
850
|
this.name = props.id !== props.url ? props.id : random(5);
|
|
966
851
|
this.appCacheKey = props.id || this.name;
|
|
@@ -1042,12 +927,6 @@ class MicroInstanceModel {
|
|
|
1042
927
|
await this.source.importEntery(this);
|
|
1043
928
|
}
|
|
1044
929
|
}
|
|
1045
|
-
set status(v) {
|
|
1046
|
-
this.state = v;
|
|
1047
|
-
}
|
|
1048
|
-
get status() {
|
|
1049
|
-
return this.state;
|
|
1050
|
-
}
|
|
1051
930
|
unmount(needDestroy) {
|
|
1052
931
|
this.state = AppState.UNMOUNT;
|
|
1053
932
|
this.sandBox?.deactivated();
|
|
@@ -1055,6 +934,12 @@ class MicroInstanceModel {
|
|
|
1055
934
|
this.container.innerHTML = '';
|
|
1056
935
|
this.container = undefined;
|
|
1057
936
|
}
|
|
937
|
+
set status(v) {
|
|
938
|
+
this.state = v;
|
|
939
|
+
}
|
|
940
|
+
get status() {
|
|
941
|
+
return this.state;
|
|
942
|
+
}
|
|
1058
943
|
}
|
|
1059
944
|
|
|
1060
945
|
/*
|
|
@@ -1082,9 +967,6 @@ class MicroInstanceModel {
|
|
|
1082
967
|
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
1083
968
|
* IN THE SOFTWARE.
|
|
1084
969
|
*/
|
|
1085
|
-
/* eslint-disable no-restricted-syntax */
|
|
1086
|
-
/* eslint-disable no-prototype-builtins */
|
|
1087
|
-
/* eslint-disable no-param-reassign */
|
|
1088
970
|
let firstGlobalProp;
|
|
1089
971
|
let secondGlobalProp;
|
|
1090
972
|
let lastGlobalProp;
|
|
@@ -1109,6 +991,11 @@ class Script {
|
|
|
1109
991
|
this.fromHtml = fromHtml ?? false;
|
|
1110
992
|
this.initial = initial ?? false;
|
|
1111
993
|
}
|
|
994
|
+
/**
|
|
995
|
+
* @param app 应用
|
|
996
|
+
* @param needRelaceScriptElement 是否需要替换script标签
|
|
997
|
+
* @returns 返回执行后的script标签或注释
|
|
998
|
+
*/
|
|
1112
999
|
async excuteCode(app, needRelaceScriptElement = false) {
|
|
1113
1000
|
try {
|
|
1114
1001
|
if (!this.code)
|
|
@@ -1154,26 +1041,27 @@ class Script {
|
|
|
1154
1041
|
}
|
|
1155
1042
|
return;
|
|
1156
1043
|
}
|
|
1044
|
+
// 内存脚本执行
|
|
1157
1045
|
executeMemoryScript(app, scopedCode) {
|
|
1158
1046
|
try {
|
|
1159
1047
|
const isScopedLocation = app instanceof MicroAppModel && app.scopeLocation;
|
|
1160
1048
|
app.registerRunningApp();
|
|
1161
|
-
// eslint-disable-next-line no-new-func
|
|
1162
1049
|
new Function('window', 'location', 'history', scopedCode)(app.sandBox.proxyWindow, isScopedLocation ? app.iframe.contentWindow.location : window.location, isScopedLocation ? app.iframe.contentWindow.history : window.history);
|
|
1163
1050
|
}
|
|
1164
1051
|
catch (e) {
|
|
1165
1052
|
console.error(e);
|
|
1166
1053
|
}
|
|
1167
1054
|
}
|
|
1055
|
+
// 脚本标签执行
|
|
1168
1056
|
executeSourceScript(scriptElement, scopedCode) {
|
|
1169
1057
|
if (this.isModule) {
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
else {
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
}
|
|
1058
|
+
scriptElement.src = this.url + '?key=' + Date.now();
|
|
1059
|
+
// if (this.url?.match(/\.ts$/)) {
|
|
1060
|
+
// // scriptElement.src = this.url + '?key=' + Date.now()!;
|
|
1061
|
+
// } else {
|
|
1062
|
+
// // const blob = new Blob([this.code], { type: 'text/javascript' });
|
|
1063
|
+
// // scriptElement.src = URL.createObjectURL(blob);
|
|
1064
|
+
// }
|
|
1177
1065
|
scriptElement.setAttribute('type', 'module');
|
|
1178
1066
|
}
|
|
1179
1067
|
else {
|
|
@@ -1181,6 +1069,7 @@ class Script {
|
|
|
1181
1069
|
}
|
|
1182
1070
|
this.url && scriptElement.setAttribute('origin-src', this.url);
|
|
1183
1071
|
}
|
|
1072
|
+
// 获取脚本内容
|
|
1184
1073
|
async getCode(app) {
|
|
1185
1074
|
if (this.code.length || !this.url) {
|
|
1186
1075
|
return this.code;
|
|
@@ -1204,9 +1093,15 @@ class Script {
|
|
|
1204
1093
|
setCode(code) {
|
|
1205
1094
|
this.code = code;
|
|
1206
1095
|
}
|
|
1096
|
+
// 转换脚本内容
|
|
1207
1097
|
transformCode(app) {
|
|
1208
1098
|
if (app.sandBox) {
|
|
1209
|
-
if (
|
|
1099
|
+
if (this.isModule) {
|
|
1100
|
+
return ` with(window.${app.sandBox.windowSymbolKey}){
|
|
1101
|
+
;${this.code}\n
|
|
1102
|
+
}`;
|
|
1103
|
+
}
|
|
1104
|
+
if (app.showSourceCode) {
|
|
1210
1105
|
return `;(function(window, self){
|
|
1211
1106
|
with(window){
|
|
1212
1107
|
;${this.code}\n
|
|
@@ -1277,14 +1172,15 @@ function noteGlobalProps(global) {
|
|
|
1277
1172
|
}
|
|
1278
1173
|
// app初始化dom 脚本执行
|
|
1279
1174
|
async function execAppScripts(app) {
|
|
1280
|
-
const appInitialScriptList = Array.from(app.source
|
|
1281
|
-
// 初始化脚本最先执行
|
|
1282
|
-
if (appInitialScriptList.length) {
|
|
1283
|
-
|
|
1284
|
-
}
|
|
1285
|
-
const appScriptList = Array.from(app.source.scripts.values()).filter(script => script.fromHtml
|
|
1175
|
+
// const appInitialScriptList = Array.from(app.source!.scripts.values()).filter(script => script.initial);
|
|
1176
|
+
// // 初始化脚本最先执行
|
|
1177
|
+
// if (appInitialScriptList.length) {
|
|
1178
|
+
// await Promise.all(appInitialScriptList.map(script => script.excuteCode(app)));
|
|
1179
|
+
// }
|
|
1180
|
+
const appScriptList = Array.from(app.source.scripts.values()).filter(script => script.fromHtml || script.initial);
|
|
1286
1181
|
const commomList = appScriptList.filter(script => (!script.async && !script.defer) || script.isModule);
|
|
1287
1182
|
// 保证同步脚本 和 module类型 最先执行
|
|
1183
|
+
await Promise.all(commomList.map(script => script.getCode(app)));
|
|
1288
1184
|
await Promise.all(commomList.map(script => script.excuteCode(app)));
|
|
1289
1185
|
// 最后执行 defer 和 async 脚本
|
|
1290
1186
|
const deferScriptList = [];
|
|
@@ -1600,9 +1496,9 @@ function resetBodyAndHeaderMethods() {
|
|
|
1600
1496
|
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
1601
1497
|
* IN THE SOFTWARE.
|
|
1602
1498
|
*/
|
|
1499
|
+
// before load
|
|
1603
1500
|
function beforeLoad() {
|
|
1604
1501
|
rewriteBodyAndHeaderMethods();
|
|
1605
|
-
rewriteDocumentPrototypeMethods();
|
|
1606
1502
|
}
|
|
1607
1503
|
|
|
1608
1504
|
/*
|
|
@@ -1630,6 +1526,7 @@ function beforeLoad() {
|
|
|
1630
1526
|
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
1631
1527
|
* IN THE SOFTWARE.
|
|
1632
1528
|
*/
|
|
1529
|
+
// 激活应用
|
|
1633
1530
|
function activated(appKey, container, callback) {
|
|
1634
1531
|
const app = appCache.getApp(appKey);
|
|
1635
1532
|
if (app?.status === AppState.DEACTIVATED && app.keepAlive) {
|
|
@@ -1647,6 +1544,8 @@ function activated(appKey, container, callback) {
|
|
|
1647
1544
|
}
|
|
1648
1545
|
}
|
|
1649
1546
|
|
|
1547
|
+
/* eslint-disable @typescript-eslint/member-ordering */
|
|
1548
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
1650
1549
|
/*
|
|
1651
1550
|
* Tencent is pleased to support the open source community by making
|
|
1652
1551
|
* 蓝鲸智云PaaS平台 (BlueKing PaaS) available.
|
|
@@ -1693,7 +1592,9 @@ class BkWewebElement extends HTMLElement {
|
|
|
1693
1592
|
return [WewebCustomAttrs.url];
|
|
1694
1593
|
}
|
|
1695
1594
|
getBooleanAttr(name) {
|
|
1696
|
-
return this.hasAttribute(name)
|
|
1595
|
+
return this.hasAttribute(name) || this.hasAttribute(name.replace(/([A-Z])/g, `-$1`).toLocaleLowerCase())
|
|
1596
|
+
? this.getAttribute(name) !== 'false'
|
|
1597
|
+
: undefined;
|
|
1697
1598
|
}
|
|
1698
1599
|
async handleAttributeChanged() {
|
|
1699
1600
|
if (!this.appKey)
|
|
@@ -1708,6 +1609,29 @@ class BkWewebElement extends HTMLElement {
|
|
|
1708
1609
|
}
|
|
1709
1610
|
await load(this.appProps);
|
|
1710
1611
|
}
|
|
1612
|
+
attributeChangedCallback(attr, _oldVal, newVal) {
|
|
1613
|
+
if (attr !== WewebCustomAttrs.url || this[attr] === newVal || !this.connected)
|
|
1614
|
+
return;
|
|
1615
|
+
this.appUrl = newVal;
|
|
1616
|
+
const cacheApp = appCache.getApp(this.appKey);
|
|
1617
|
+
(this.connected || cacheApp) && this.handleAttributeChanged();
|
|
1618
|
+
}
|
|
1619
|
+
async connectedCallback() {
|
|
1620
|
+
if (this.getBooleanAttr(WewebCustomAttrs.setShodowDom) && !this.shadowRoot) {
|
|
1621
|
+
this.attachShadow({ delegatesFocus: false, mode: 'open' });
|
|
1622
|
+
}
|
|
1623
|
+
await load(this.appProps);
|
|
1624
|
+
activated(this.appKey, this.shadowRoot ?? this);
|
|
1625
|
+
this.connected = true;
|
|
1626
|
+
}
|
|
1627
|
+
disconnectedCallback() {
|
|
1628
|
+
this.connected = false;
|
|
1629
|
+
if (this.appProps.keepAlive) {
|
|
1630
|
+
deactivated(this.appKey);
|
|
1631
|
+
}
|
|
1632
|
+
else
|
|
1633
|
+
unmount(this.appKey);
|
|
1634
|
+
}
|
|
1711
1635
|
get appData() {
|
|
1712
1636
|
if (this.hasAttribute(WewebCustomAttrs.data)) {
|
|
1713
1637
|
try {
|
|
@@ -1748,29 +1672,6 @@ class BkWewebElement extends HTMLElement {
|
|
|
1748
1672
|
url: this.getAttribute(WewebCustomAttrs.url),
|
|
1749
1673
|
};
|
|
1750
1674
|
}
|
|
1751
|
-
attributeChangedCallback(attr, _oldVal, newVal) {
|
|
1752
|
-
if (attr !== WewebCustomAttrs.url || this[attr] === newVal || !this.connected)
|
|
1753
|
-
return;
|
|
1754
|
-
this.appUrl = newVal;
|
|
1755
|
-
const cacheApp = appCache.getApp(this.appKey);
|
|
1756
|
-
(this.connected || cacheApp) && this.handleAttributeChanged();
|
|
1757
|
-
}
|
|
1758
|
-
async connectedCallback() {
|
|
1759
|
-
if (this.getBooleanAttr(WewebCustomAttrs.setShodowDom) && !this.shadowRoot) {
|
|
1760
|
-
this.attachShadow({ delegatesFocus: false, mode: 'open' });
|
|
1761
|
-
}
|
|
1762
|
-
await load(this.appProps);
|
|
1763
|
-
activated(this.appKey, this.shadowRoot ?? this);
|
|
1764
|
-
this.connected = true;
|
|
1765
|
-
}
|
|
1766
|
-
disconnectedCallback() {
|
|
1767
|
-
this.connected = false;
|
|
1768
|
-
if (this.appProps.keepAlive) {
|
|
1769
|
-
deactivated(this.appKey);
|
|
1770
|
-
}
|
|
1771
|
-
else
|
|
1772
|
-
unmount(this.appKey);
|
|
1773
|
-
}
|
|
1774
1675
|
}
|
|
1775
1676
|
|
|
1776
1677
|
var WewebMode;
|
|
@@ -1806,8 +1707,8 @@ var WewebMode;
|
|
|
1806
1707
|
* IN THE SOFTWARE.
|
|
1807
1708
|
*/
|
|
1808
1709
|
const WINDOW_WHITE_LIST = [
|
|
1809
|
-
'System',
|
|
1810
|
-
'__cjsWrapper',
|
|
1710
|
+
'System', // SystemJS
|
|
1711
|
+
'__cjsWrapper', // SystemJS CommonJS wrapper
|
|
1811
1712
|
process.env.NODE_ENV !== 'production' ? '__REACT_DEVTOOLS_GLOBAL_HOOK__' : '',
|
|
1812
1713
|
];
|
|
1813
1714
|
// 一定需要在子应用自身上下文获取的属性名
|
|
@@ -1819,6 +1720,11 @@ const BK_WEWEB_INJECT_KEY_LIST = [
|
|
|
1819
1720
|
const WINDOW_ALIAS_LIST = ['window', 'self', 'globalThis'];
|
|
1820
1721
|
// 设置了scopedLocation 后需要监听属性名
|
|
1821
1722
|
const BK_WEWEB_LOCATION_KEY_LIST = ['location', 'history'];
|
|
1723
|
+
const COMMON_MICRO_APP_WINDOE_KEY_MAP = {
|
|
1724
|
+
__bk_pop_manager: true,
|
|
1725
|
+
__bk_zIndex_manager: true,
|
|
1726
|
+
i18n: true,
|
|
1727
|
+
};
|
|
1822
1728
|
const DEV_MICRO_APP_WINDOE_KEY_MAP = process.env.NODE_ENV !== 'production'
|
|
1823
1729
|
? {
|
|
1824
1730
|
__DEV__: true,
|
|
@@ -1828,16 +1734,185 @@ const DEV_MICRO_APP_WINDOE_KEY_MAP = process.env.NODE_ENV !== 'production'
|
|
|
1828
1734
|
__VUE_I18N_FULL_INSTALL__: true,
|
|
1829
1735
|
__VUE_I18N_LEGACY_API__: true,
|
|
1830
1736
|
__VUE_OPTIONS_API__: true,
|
|
1831
|
-
__bk_pop_manager: true,
|
|
1832
|
-
__bk_zIndex_manager: true,
|
|
1833
1737
|
'__core-js_shared__': true,
|
|
1834
|
-
i18n: true,
|
|
1835
1738
|
webpackChunkapm: true,
|
|
1836
1739
|
webpackChunkpc: true,
|
|
1837
1740
|
webpackChunktrace: true,
|
|
1838
1741
|
webpackJsonp: true,
|
|
1742
|
+
...COMMON_MICRO_APP_WINDOE_KEY_MAP,
|
|
1839
1743
|
}
|
|
1840
|
-
:
|
|
1744
|
+
: COMMON_MICRO_APP_WINDOE_KEY_MAP;
|
|
1745
|
+
|
|
1746
|
+
const SPECIAL_ELEMENT_TAG = ['body', 'html', 'head'];
|
|
1747
|
+
/**
|
|
1748
|
+
* 创建代理的document
|
|
1749
|
+
* @param rawDocument 原始document
|
|
1750
|
+
* @param app 应用实例
|
|
1751
|
+
* @returns 代理的document
|
|
1752
|
+
*/
|
|
1753
|
+
const createProxyDocument = (rawDocument, app) => {
|
|
1754
|
+
const fakeDocument = {};
|
|
1755
|
+
function shadowRootInsertAdjacentHTML(where, domString) {
|
|
1756
|
+
const temporaryContainer = document.createElement('div');
|
|
1757
|
+
temporaryContainer.innerHTML = domString;
|
|
1758
|
+
const elements = Array.from(temporaryContainer.childNodes);
|
|
1759
|
+
const shadow = app.container;
|
|
1760
|
+
switch (where) {
|
|
1761
|
+
case 'beforebegin':
|
|
1762
|
+
elements.forEach(el => shadow.host.parentNode?.insertBefore(el, shadow.host));
|
|
1763
|
+
break;
|
|
1764
|
+
case 'afterbegin':
|
|
1765
|
+
elements.reverse().forEach(el => shadow.insertBefore(el, shadow.firstChild));
|
|
1766
|
+
break;
|
|
1767
|
+
case 'beforeend':
|
|
1768
|
+
elements.forEach(el => shadow.appendChild(el));
|
|
1769
|
+
break;
|
|
1770
|
+
case 'afterend':
|
|
1771
|
+
elements.forEach(el => shadow.host.parentNode?.insertBefore(el, shadow.host.nextSibling));
|
|
1772
|
+
break;
|
|
1773
|
+
}
|
|
1774
|
+
}
|
|
1775
|
+
const proxyBody = new Proxy({}, {
|
|
1776
|
+
get(_, key) {
|
|
1777
|
+
// ShadowRoot 处理逻辑简化
|
|
1778
|
+
if (app.container instanceof ShadowRoot) {
|
|
1779
|
+
if (key === 'insertAdjacentHTML') {
|
|
1780
|
+
// shadowRoot 中没有 insertAdjacentHTML
|
|
1781
|
+
return shadowRootInsertAdjacentHTML.bind(app.container);
|
|
1782
|
+
}
|
|
1783
|
+
const value = app.container[key];
|
|
1784
|
+
if (typeof value === 'function') {
|
|
1785
|
+
return value.bind(app.container);
|
|
1786
|
+
}
|
|
1787
|
+
if (value !== undefined) {
|
|
1788
|
+
return value;
|
|
1789
|
+
}
|
|
1790
|
+
}
|
|
1791
|
+
// 直接返回 rawDocument.body 的属性或绑定函数
|
|
1792
|
+
const value = Reflect.get(rawDocument.body, key);
|
|
1793
|
+
return typeof value === 'function' ? value.bind(rawDocument.body) : value;
|
|
1794
|
+
},
|
|
1795
|
+
set(_, key, value) {
|
|
1796
|
+
// ShadowRoot 处理逻辑简化
|
|
1797
|
+
if (app.container instanceof ShadowRoot) {
|
|
1798
|
+
app.container[key] = value;
|
|
1799
|
+
return true;
|
|
1800
|
+
}
|
|
1801
|
+
// 直接设置 rawDocument.body 的属性
|
|
1802
|
+
Reflect.set(rawDocument.body, key, value);
|
|
1803
|
+
return true;
|
|
1804
|
+
},
|
|
1805
|
+
});
|
|
1806
|
+
/**
|
|
1807
|
+
* @param tagName 标签名
|
|
1808
|
+
* @param options 选项
|
|
1809
|
+
* @returns
|
|
1810
|
+
*/
|
|
1811
|
+
function createElement(tagName, options) {
|
|
1812
|
+
const element = rawDocument.createElement(tagName, options);
|
|
1813
|
+
// img.src = 'xxx' iframe.src = 'xxx' 均不能在setAttributes上监听 但是这里所有的src都是 全地址 无法判断是否需要添加子应用域名
|
|
1814
|
+
// if (tagName.toLocaleLowerCase() === 'img') {
|
|
1815
|
+
// const observer = new MutationObserver((list, observer) => {
|
|
1816
|
+
// observer.disconnect();
|
|
1817
|
+
// const url = new URL((element as HTMLImageElement).src)
|
|
1818
|
+
// (element as HTMLImageElement).src = `${}`
|
|
1819
|
+
// });
|
|
1820
|
+
// observer.observe(element, { attributeFilter: ['src'], subtree: false, childList: false });
|
|
1821
|
+
// }
|
|
1822
|
+
element.__BK_WEWEB_APP_KEY__ = app.appCacheKey;
|
|
1823
|
+
return element;
|
|
1824
|
+
}
|
|
1825
|
+
/**
|
|
1826
|
+
* 查询选择器的新方法
|
|
1827
|
+
* @param selectors 选择器字符串
|
|
1828
|
+
* @returns 匹配的元素或 null
|
|
1829
|
+
*/
|
|
1830
|
+
function querySelectorNew(selectors) {
|
|
1831
|
+
if (selectors === proxyBody) {
|
|
1832
|
+
return app.container instanceof ShadowRoot ? app.container : rawDocument.body;
|
|
1833
|
+
}
|
|
1834
|
+
// 如果选择器是特殊元素标签
|
|
1835
|
+
if (SPECIAL_ELEMENT_TAG.includes(selectors)) {
|
|
1836
|
+
// 如果当前应用程序容器是 ShadowRoot 类型
|
|
1837
|
+
if (app?.container instanceof ShadowRoot) {
|
|
1838
|
+
return app?.container;
|
|
1839
|
+
}
|
|
1840
|
+
// 否则调用原始的 querySelector 方法
|
|
1841
|
+
return rawDocument.querySelector.call(this, selectors);
|
|
1842
|
+
}
|
|
1843
|
+
// 返回当前应用程序容器中匹配选择器的元素,如果没有匹配的元素则返回 null
|
|
1844
|
+
try {
|
|
1845
|
+
return app?.container?.querySelector(selectors) ?? null;
|
|
1846
|
+
}
|
|
1847
|
+
catch {
|
|
1848
|
+
return null;
|
|
1849
|
+
}
|
|
1850
|
+
}
|
|
1851
|
+
/**
|
|
1852
|
+
* 重写了 Document 类的 querySelectorAll 方法
|
|
1853
|
+
* @param selectors - 要查询的选择器
|
|
1854
|
+
* @returns 匹配到的元素列表或空数组
|
|
1855
|
+
*/
|
|
1856
|
+
function querySelectorAllNew(selectors) {
|
|
1857
|
+
// 如果选择器是特殊元素标签,则返回容器元素或调用原生 querySelector 方法
|
|
1858
|
+
if (SPECIAL_ELEMENT_TAG.includes(selectors)) {
|
|
1859
|
+
if (app?.container instanceof ShadowRoot) {
|
|
1860
|
+
return app?.container;
|
|
1861
|
+
}
|
|
1862
|
+
return rawDocument.querySelector(selectors);
|
|
1863
|
+
}
|
|
1864
|
+
// 返回运行中应用程序的容器元素中匹配到的元素列表或空数组
|
|
1865
|
+
return app?.container?.querySelectorAll(selectors) ?? [];
|
|
1866
|
+
}
|
|
1867
|
+
function getElementByIdNew(key) {
|
|
1868
|
+
return querySelectorNew.call(rawDocument, `#${key}`);
|
|
1869
|
+
}
|
|
1870
|
+
function getElementsByClassName(key) {
|
|
1871
|
+
return querySelectorAllNew(`.${key}`);
|
|
1872
|
+
}
|
|
1873
|
+
function getElementsByTagName(key) {
|
|
1874
|
+
if (SPECIAL_ELEMENT_TAG.includes(key) || (!app?.showSourceCode && key.toLocaleLowerCase() === 'script')) {
|
|
1875
|
+
return rawDocument.getElementsByTagName(key);
|
|
1876
|
+
}
|
|
1877
|
+
return querySelectorAllNew(key);
|
|
1878
|
+
}
|
|
1879
|
+
function getElementsByNameNew(key) {
|
|
1880
|
+
return querySelectorAllNew(`[name=${key}]`);
|
|
1881
|
+
}
|
|
1882
|
+
return new Proxy(fakeDocument, {
|
|
1883
|
+
get(_, key) {
|
|
1884
|
+
if (key === 'createElement') {
|
|
1885
|
+
return createElement.bind(rawDocument);
|
|
1886
|
+
}
|
|
1887
|
+
if (key === 'querySelector') {
|
|
1888
|
+
return querySelectorNew.bind(rawDocument);
|
|
1889
|
+
}
|
|
1890
|
+
if (key === 'querySelectorAll') {
|
|
1891
|
+
return querySelectorAllNew.bind(rawDocument);
|
|
1892
|
+
}
|
|
1893
|
+
if (key === 'getElementById') {
|
|
1894
|
+
return getElementByIdNew.bind(rawDocument);
|
|
1895
|
+
}
|
|
1896
|
+
if (key === 'getElementsByClassName') {
|
|
1897
|
+
return getElementsByClassName.bind(rawDocument);
|
|
1898
|
+
}
|
|
1899
|
+
if (key === 'getElementsByTagName') {
|
|
1900
|
+
return getElementsByTagName.bind(rawDocument);
|
|
1901
|
+
}
|
|
1902
|
+
if (key === 'getElementsByName') {
|
|
1903
|
+
return getElementsByNameNew.bind(rawDocument);
|
|
1904
|
+
}
|
|
1905
|
+
if (key === 'body') {
|
|
1906
|
+
return proxyBody;
|
|
1907
|
+
}
|
|
1908
|
+
const result = Reflect.get(rawDocument, key);
|
|
1909
|
+
if (typeof result === 'function') {
|
|
1910
|
+
return result.bind(rawDocument);
|
|
1911
|
+
}
|
|
1912
|
+
return result;
|
|
1913
|
+
},
|
|
1914
|
+
});
|
|
1915
|
+
};
|
|
1841
1916
|
|
|
1842
1917
|
/*
|
|
1843
1918
|
* Tencent is pleased to support the open source community by making
|
|
@@ -1934,8 +2009,6 @@ function rewriteDocumentAndBodyEvent() {
|
|
|
1934
2009
|
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
1935
2010
|
* IN THE SOFTWARE.
|
|
1936
2011
|
*/
|
|
1937
|
-
/* eslint-disable max-len */
|
|
1938
|
-
/* eslint-disable no-prototype-builtins */
|
|
1939
2012
|
// 正则表达式,用于匹配类定义
|
|
1940
2013
|
const CLASS_REGEX = /^class\b/;
|
|
1941
2014
|
// 正则表达式,用于匹配以大写字母开头的函数定义
|
|
@@ -2009,6 +2082,31 @@ function bindFunctionToRawWindow(rawWindow, value) {
|
|
|
2009
2082
|
return value;
|
|
2010
2083
|
}
|
|
2011
2084
|
|
|
2085
|
+
/*
|
|
2086
|
+
* Tencent is pleased to support the open source community by making
|
|
2087
|
+
* 蓝鲸智云PaaS平台 (BlueKing PaaS) available.
|
|
2088
|
+
*
|
|
2089
|
+
* Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
|
|
2090
|
+
*
|
|
2091
|
+
* 蓝鲸智云PaaS平台 (BlueKing PaaS) is licensed under the MIT License.
|
|
2092
|
+
*
|
|
2093
|
+
* License for 蓝鲸智云PaaS平台 (BlueKing PaaS):
|
|
2094
|
+
*
|
|
2095
|
+
* ---------------------------------------------------
|
|
2096
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
|
2097
|
+
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation
|
|
2098
|
+
* the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
|
|
2099
|
+
* to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
2100
|
+
*
|
|
2101
|
+
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of
|
|
2102
|
+
* the Software.
|
|
2103
|
+
*
|
|
2104
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
|
2105
|
+
* THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
2106
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
|
2107
|
+
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
2108
|
+
* IN THE SOFTWARE.
|
|
2109
|
+
*/
|
|
2012
2110
|
// rewrite window funtion like settimeout setinterval ...
|
|
2013
2111
|
function rewriteWindowFunction(fakeWindow) {
|
|
2014
2112
|
const windowEventLisenerMap = new Map();
|
|
@@ -2083,9 +2181,6 @@ function rewriteWindowFunction(fakeWindow) {
|
|
|
2083
2181
|
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
2084
2182
|
* IN THE SOFTWARE.
|
|
2085
2183
|
*/
|
|
2086
|
-
/* eslint-disable no-new-func */
|
|
2087
|
-
/* eslint-disable no-param-reassign */
|
|
2088
|
-
/* eslint-disable no-prototype-builtins */
|
|
2089
2184
|
class SandBox {
|
|
2090
2185
|
app;
|
|
2091
2186
|
active = false;
|
|
@@ -2093,7 +2188,8 @@ class SandBox {
|
|
|
2093
2188
|
resetDocumentAndBodyEvent;
|
|
2094
2189
|
resetWindowFunction;
|
|
2095
2190
|
sameRawWindowKeySet = new Set();
|
|
2096
|
-
fakeWindow
|
|
2191
|
+
fakeWindow;
|
|
2192
|
+
proxyDocument;
|
|
2097
2193
|
proxyWindow;
|
|
2098
2194
|
rawDocument;
|
|
2099
2195
|
rawWindow;
|
|
@@ -2102,13 +2198,15 @@ class SandBox {
|
|
|
2102
2198
|
this.app = app;
|
|
2103
2199
|
const windowDescriptorSet = new Set();
|
|
2104
2200
|
const rawWindow = window;
|
|
2105
|
-
const rawDocument = createRewriteDocument(document, this.app);
|
|
2106
|
-
this.fakeWindow.__POWERED_BY_BK_WEWEB__ = true;
|
|
2107
|
-
this.fakeWindow.__BK_WEWEB_APP_KEY__ = app.appCacheKey;
|
|
2108
2201
|
this.rawWindow = rawWindow;
|
|
2109
|
-
this.rawDocument =
|
|
2110
|
-
|
|
2111
|
-
|
|
2202
|
+
this.rawDocument = createProxyDocument(document, app);
|
|
2203
|
+
const fakeWindow = Object.create({});
|
|
2204
|
+
fakeWindow.__BK_WEWEB_APP_KEY__ = app.appCacheKey;
|
|
2205
|
+
fakeWindow.__POWERED_BY_BK_WEWEB__ = true;
|
|
2206
|
+
fakeWindow.rawDocument = document;
|
|
2207
|
+
fakeWindow.rawWindow = rawWindow;
|
|
2208
|
+
fakeWindow.__proto__ = Window;
|
|
2209
|
+
this.fakeWindow = fakeWindow;
|
|
2112
2210
|
const { resetWindowFunction } = rewriteWindowFunction(this.fakeWindow);
|
|
2113
2211
|
this.resetWindowFunction = resetWindowFunction;
|
|
2114
2212
|
this.windowSymbolKey = `__${(app.name || app.appCacheKey).replace(/(-|,|:|~|'|")/gim, '_')}_${random(10)}__`;
|
|
@@ -2137,11 +2235,10 @@ class SandBox {
|
|
|
2137
2235
|
return this.proxyWindow;
|
|
2138
2236
|
if (key === 'document') {
|
|
2139
2237
|
app.registerRunningApp();
|
|
2140
|
-
return rawDocument;
|
|
2238
|
+
return this.rawDocument;
|
|
2141
2239
|
}
|
|
2142
2240
|
if (key === 'eval') {
|
|
2143
2241
|
app.registerRunningApp();
|
|
2144
|
-
// eslint-disable-next-line no-eval
|
|
2145
2242
|
return eval;
|
|
2146
2243
|
}
|
|
2147
2244
|
if (BK_WEWEB_LOCATION_KEY_LIST.includes(key) &&
|
|
@@ -2158,6 +2255,14 @@ class SandBox {
|
|
|
2158
2255
|
}
|
|
2159
2256
|
return Reflect.get(rawWindow, key); // iframe
|
|
2160
2257
|
}
|
|
2258
|
+
if (key === 'getComputedStyle') {
|
|
2259
|
+
return (element, pseudoElt) => {
|
|
2260
|
+
if (element instanceof Element) {
|
|
2261
|
+
return rawWindow.getComputedStyle(element, pseudoElt);
|
|
2262
|
+
}
|
|
2263
|
+
return rawWindow.getComputedStyle(document.body, pseudoElt);
|
|
2264
|
+
};
|
|
2265
|
+
}
|
|
2161
2266
|
if (Reflect.has(target, key) || BK_WEWEB_INJECT_KEY_LIST.includes(key))
|
|
2162
2267
|
return Reflect.get(target, key);
|
|
2163
2268
|
const rawValue = Reflect.get(rawWindow, key);
|
|
@@ -2234,6 +2339,7 @@ class SandBox {
|
|
|
2234
2339
|
activeated(data) {
|
|
2235
2340
|
if (!this.active) {
|
|
2236
2341
|
this.active = true;
|
|
2342
|
+
this.rawDocument = createProxyDocument(document, this.app);
|
|
2237
2343
|
this.fakeWindow.__BK_WEWEB_DATA__ = data ?? {};
|
|
2238
2344
|
const { resetDocumentAndBodyEvent } = rewriteDocumentAndBodyEvent();
|
|
2239
2345
|
this.resetDocumentAndBodyEvent = resetDocumentAndBodyEvent;
|
|
@@ -2280,23 +2386,25 @@ class SandBox {
|
|
|
2280
2386
|
* IN THE SOFTWARE.
|
|
2281
2387
|
*/
|
|
2282
2388
|
const BLANK_ORIGN = 'about:blank';
|
|
2389
|
+
// bk-weweb 微应用模式
|
|
2283
2390
|
class MicroAppModel {
|
|
2284
|
-
state = AppState.UNSET;
|
|
2285
|
-
container;
|
|
2286
|
-
data;
|
|
2287
|
-
iframe = null;
|
|
2288
|
-
initSource;
|
|
2289
|
-
|
|
2391
|
+
state = AppState.UNSET; // 状态
|
|
2392
|
+
container; // 容器
|
|
2393
|
+
data; // 数据
|
|
2394
|
+
iframe = null; // scoped iframe
|
|
2395
|
+
initSource; // 初始资源
|
|
2396
|
+
isModuleApp = false; // 是否预加载
|
|
2397
|
+
isPreLoad = false; // 是否缓存
|
|
2290
2398
|
keepAlive;
|
|
2291
|
-
mode = WewebMode.APP;
|
|
2292
|
-
name;
|
|
2293
|
-
sandBox;
|
|
2294
|
-
scopeCss;
|
|
2295
|
-
scopeJs;
|
|
2296
|
-
scopeLocation;
|
|
2297
|
-
showSourceCode;
|
|
2298
|
-
source;
|
|
2299
|
-
url;
|
|
2399
|
+
mode = WewebMode.APP; // 名称
|
|
2400
|
+
name; // 沙箱
|
|
2401
|
+
sandBox; // 是否隔离样式
|
|
2402
|
+
scopeCss; // 是否隔离js
|
|
2403
|
+
scopeJs; // 是否隔离location
|
|
2404
|
+
scopeLocation; // 是否显示源码
|
|
2405
|
+
showSourceCode; // 入口资源
|
|
2406
|
+
source; // url
|
|
2407
|
+
url; // 是否是esm应用
|
|
2300
2408
|
constructor(props) {
|
|
2301
2409
|
this.name = props.id !== props.url ? props.id : random(5);
|
|
2302
2410
|
this.mode = props.mode ?? WewebMode.APP;
|
|
@@ -2317,26 +2425,35 @@ class MicroAppModel {
|
|
|
2317
2425
|
this.container.setAttribute(CSS_ATTRIBUTE_KEY, this.name);
|
|
2318
2426
|
}
|
|
2319
2427
|
}
|
|
2428
|
+
// 激活
|
|
2320
2429
|
activated(container, callback) {
|
|
2321
2430
|
this.isPreLoad = false;
|
|
2322
2431
|
this.state = AppState.ACTIVATED;
|
|
2432
|
+
const app = this;
|
|
2323
2433
|
if (container && this.container) {
|
|
2324
2434
|
if (container instanceof Element)
|
|
2325
2435
|
container.setAttribute(CSS_ATTRIBUTE_KEY, this.name);
|
|
2326
2436
|
const fragment = document.createDocumentFragment();
|
|
2327
2437
|
Array.from(this.container.childNodes).forEach((node) => {
|
|
2438
|
+
node.__BK_WEWEB_APP_KEY__ = this.appCacheKey;
|
|
2439
|
+
Object.defineProperties(node, {
|
|
2440
|
+
ownerDocument: {
|
|
2441
|
+
get() {
|
|
2442
|
+
return app.sandBox?.rawDocument;
|
|
2443
|
+
},
|
|
2444
|
+
},
|
|
2445
|
+
});
|
|
2328
2446
|
fragment.appendChild(node);
|
|
2329
2447
|
});
|
|
2330
2448
|
container.innerHTML = '';
|
|
2331
2449
|
container.appendChild(fragment);
|
|
2332
2450
|
this.container = container;
|
|
2451
|
+
this.initShadowRootContainer();
|
|
2333
2452
|
this.sandBox?.activeated(this.data);
|
|
2334
2453
|
callback?.(this);
|
|
2335
2454
|
}
|
|
2336
2455
|
}
|
|
2337
|
-
|
|
2338
|
-
return this.url;
|
|
2339
|
-
}
|
|
2456
|
+
// 创建隔离iframe
|
|
2340
2457
|
createIframe() {
|
|
2341
2458
|
return new Promise(resolve => {
|
|
2342
2459
|
const iframe = document.createElement('iframe');
|
|
@@ -2365,16 +2482,38 @@ class MicroAppModel {
|
|
|
2365
2482
|
this.state = AppState.DEACTIVATED;
|
|
2366
2483
|
this.sandBox?.deactivated();
|
|
2367
2484
|
}
|
|
2485
|
+
initShadowRootContainer() {
|
|
2486
|
+
if (this.container instanceof ShadowRoot) {
|
|
2487
|
+
// inject echarts in shadowRoot
|
|
2488
|
+
Object.defineProperties(this.container, {
|
|
2489
|
+
getBoundingClientRect: {
|
|
2490
|
+
get() {
|
|
2491
|
+
return this.host.getBoundingClientRect;
|
|
2492
|
+
},
|
|
2493
|
+
},
|
|
2494
|
+
});
|
|
2495
|
+
}
|
|
2496
|
+
}
|
|
2368
2497
|
mount(container, callback) {
|
|
2369
2498
|
this.isPreLoad = false;
|
|
2370
2499
|
this.container = container ?? this.container;
|
|
2500
|
+
this.initShadowRootContainer();
|
|
2371
2501
|
this.state = AppState.MOUNTING;
|
|
2502
|
+
const app = this;
|
|
2372
2503
|
if (this.container) {
|
|
2373
2504
|
if (this.container instanceof Element)
|
|
2374
2505
|
this.container.setAttribute(CSS_ATTRIBUTE_KEY, this.name);
|
|
2375
2506
|
const clonedNode = this.source.html.cloneNode(true);
|
|
2376
2507
|
const fragment = document.createDocumentFragment();
|
|
2377
2508
|
Array.from(clonedNode.childNodes).forEach((node) => {
|
|
2509
|
+
node.__BK_WEWEB_APP_KEY__ = this.appCacheKey;
|
|
2510
|
+
Object.defineProperties(node, {
|
|
2511
|
+
ownerDocument: {
|
|
2512
|
+
get() {
|
|
2513
|
+
return app.sandBox?.rawDocument;
|
|
2514
|
+
},
|
|
2515
|
+
},
|
|
2516
|
+
});
|
|
2378
2517
|
fragment.appendChild(node);
|
|
2379
2518
|
});
|
|
2380
2519
|
this.container.innerHTML = '';
|
|
@@ -2402,7 +2541,7 @@ class MicroAppModel {
|
|
|
2402
2541
|
async start() {
|
|
2403
2542
|
if (!this.source || [AppState.ERROR, AppState.UNSET].includes(this.status)) {
|
|
2404
2543
|
this.state = AppState.LOADING;
|
|
2405
|
-
if (this.scopeLocation) {
|
|
2544
|
+
if (this.scopeLocation || this.isModuleApp) {
|
|
2406
2545
|
const iframe = await this.createIframe();
|
|
2407
2546
|
this.iframe = iframe;
|
|
2408
2547
|
}
|
|
@@ -2410,12 +2549,6 @@ class MicroAppModel {
|
|
|
2410
2549
|
await this.source.importEntery(this);
|
|
2411
2550
|
}
|
|
2412
2551
|
}
|
|
2413
|
-
get status() {
|
|
2414
|
-
return this.state;
|
|
2415
|
-
}
|
|
2416
|
-
set status(v) {
|
|
2417
|
-
this.state = v;
|
|
2418
|
-
}
|
|
2419
2552
|
unmount(needDestroy = false) {
|
|
2420
2553
|
this.state = AppState.UNMOUNT;
|
|
2421
2554
|
this.sandBox?.deactivated();
|
|
@@ -2423,6 +2556,15 @@ class MicroAppModel {
|
|
|
2423
2556
|
this.container.innerHTML = '';
|
|
2424
2557
|
this.container = undefined;
|
|
2425
2558
|
}
|
|
2559
|
+
get appCacheKey() {
|
|
2560
|
+
return this.url;
|
|
2561
|
+
}
|
|
2562
|
+
get status() {
|
|
2563
|
+
return this.state;
|
|
2564
|
+
}
|
|
2565
|
+
set status(v) {
|
|
2566
|
+
this.state = v;
|
|
2567
|
+
}
|
|
2426
2568
|
}
|
|
2427
2569
|
|
|
2428
2570
|
/*
|
|
@@ -2509,7 +2651,7 @@ class EntrySource {
|
|
|
2509
2651
|
}
|
|
2510
2652
|
collectScript(script, parent, needReplaceELement = false) {
|
|
2511
2653
|
if (script.hasAttribute('ignore') ||
|
|
2512
|
-
isJsonpUrl(script.getAttribute('src')) ||
|
|
2654
|
+
(script.type !== 'module' && isJsonpUrl(script.getAttribute('src'))) ||
|
|
2513
2655
|
(script.hasAttribute('type') && !SCRIPT_TYPE_NAMES.includes(script.type))) {
|
|
2514
2656
|
return;
|
|
2515
2657
|
}
|
|
@@ -2542,9 +2684,11 @@ class EntrySource {
|
|
|
2542
2684
|
const nonceStr = randomUrl();
|
|
2543
2685
|
const scriptInstance = new Script({
|
|
2544
2686
|
async: false,
|
|
2687
|
+
// code: script.textContent.replace(/var\s+(\w+)=/gm, `window.$1 = `),
|
|
2545
2688
|
code: script.textContent,
|
|
2546
2689
|
defer: script.type === 'module',
|
|
2547
2690
|
fromHtml: !needReplaceELement,
|
|
2691
|
+
initial: false,
|
|
2548
2692
|
isModule: script.type === 'module',
|
|
2549
2693
|
url: nonceStr,
|
|
2550
2694
|
});
|
|
@@ -2558,36 +2702,64 @@ class EntrySource {
|
|
|
2558
2702
|
}
|
|
2559
2703
|
return { replace: script };
|
|
2560
2704
|
}
|
|
2561
|
-
collectScriptAndStyle(parent
|
|
2562
|
-
const
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
if (
|
|
2569
|
-
this.
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
fromHtml: true,
|
|
2576
|
-
url: '',
|
|
2577
|
-
}));
|
|
2578
|
-
dom.remove();
|
|
2579
|
-
}
|
|
2580
|
-
}
|
|
2581
|
-
else if (dom instanceof HTMLScriptElement) {
|
|
2582
|
-
this.collectScript(dom, parent);
|
|
2583
|
-
}
|
|
2584
|
-
else if (dom instanceof HTMLMetaElement || dom instanceof HTMLTitleElement) {
|
|
2585
|
-
parent.removeChild(dom);
|
|
2705
|
+
collectScriptAndStyle(parent) {
|
|
2706
|
+
const links = Array.from(parent.querySelectorAll('link'));
|
|
2707
|
+
links?.forEach(link => {
|
|
2708
|
+
this.collectLink(link, link.parentElement);
|
|
2709
|
+
});
|
|
2710
|
+
const styles = Array.from(parent.querySelectorAll('style'));
|
|
2711
|
+
styles?.forEach(style => {
|
|
2712
|
+
if (!style.hasAttribute('exclude') && !style.hasAttribute('ignore')) {
|
|
2713
|
+
this.styles.set(randomUrl(), new Style({
|
|
2714
|
+
code: style.textContent || '',
|
|
2715
|
+
fromHtml: true,
|
|
2716
|
+
url: '',
|
|
2717
|
+
}));
|
|
2718
|
+
style.remove();
|
|
2586
2719
|
}
|
|
2587
|
-
|
|
2588
|
-
|
|
2720
|
+
});
|
|
2721
|
+
const scripts = Array.from(parent.querySelectorAll('script'));
|
|
2722
|
+
scripts?.forEach(script => {
|
|
2723
|
+
this.collectScript(script, script.parentElement);
|
|
2724
|
+
});
|
|
2725
|
+
const metas = Array.from(parent.querySelectorAll('meta'));
|
|
2726
|
+
metas?.forEach(meta => {
|
|
2727
|
+
meta.parentElement.removeChild(meta);
|
|
2728
|
+
});
|
|
2729
|
+
const imgs = Array.from(parent.querySelectorAll('img'));
|
|
2730
|
+
imgs?.forEach(img => {
|
|
2731
|
+
if (img.hasAttribute('src')) {
|
|
2732
|
+
img.setAttribute('src', fillUpPath(img.getAttribute('src'), this.url));
|
|
2589
2733
|
}
|
|
2590
2734
|
});
|
|
2735
|
+
// const children = Array.from(parent.children);
|
|
2736
|
+
// children?.forEach(dom => {
|
|
2737
|
+
// if (dom instanceof HTMLLinkElement) {
|
|
2738
|
+
// this.collectLink(dom, parent);
|
|
2739
|
+
// } else if (dom instanceof HTMLStyleElement) {
|
|
2740
|
+
// if (!dom.hasAttribute('exclude') && !dom.hasAttribute('ignore')) {
|
|
2741
|
+
// this.styles.set(
|
|
2742
|
+
// randomUrl(),
|
|
2743
|
+
// new Style({
|
|
2744
|
+
// code: dom.textContent || '',
|
|
2745
|
+
// fromHtml: true,
|
|
2746
|
+
// url: '',
|
|
2747
|
+
// }),
|
|
2748
|
+
// );
|
|
2749
|
+
// dom.remove();
|
|
2750
|
+
// }
|
|
2751
|
+
// } else if (dom instanceof HTMLScriptElement) {
|
|
2752
|
+
// this.collectScript(dom, parent);
|
|
2753
|
+
// } else if (dom instanceof HTMLMetaElement || dom instanceof HTMLTitleElement) {
|
|
2754
|
+
// parent.removeChild(dom);
|
|
2755
|
+
// } else if (dom instanceof HTMLImageElement && dom.hasAttribute('src')) {
|
|
2756
|
+
// dom.setAttribute('src', fillUpPath(dom.getAttribute('src')!, this.url));
|
|
2757
|
+
// }
|
|
2758
|
+
// });
|
|
2759
|
+
// children.length &&
|
|
2760
|
+
// children.forEach(child => {
|
|
2761
|
+
// this.collectScriptAndStyle(child as HTMLElement, app);
|
|
2762
|
+
// });
|
|
2591
2763
|
}
|
|
2592
2764
|
getScript(url) {
|
|
2593
2765
|
return this.scripts.get(url);
|
|
@@ -2625,7 +2797,7 @@ class EntrySource {
|
|
|
2625
2797
|
if (wrapElement.__BK_WEWEB_APP_KEY__)
|
|
2626
2798
|
delete wrapElement.__BK_WEWEB_APP_KEY__;
|
|
2627
2799
|
wrapElement.innerHTML = htmlStr.replace(/<\/?head>/gim, '').replace(/<\/?body>/i, '');
|
|
2628
|
-
this.collectScriptAndStyle(wrapElement
|
|
2800
|
+
this.collectScriptAndStyle(wrapElement);
|
|
2629
2801
|
await excuteAppStyles(app, wrapElement);
|
|
2630
2802
|
this.html = wrapElement;
|
|
2631
2803
|
}
|
|
@@ -2688,11 +2860,12 @@ class AppCache {
|
|
|
2688
2860
|
constructor() {
|
|
2689
2861
|
this.cache = new Map();
|
|
2690
2862
|
this.baseSource = new EntrySource(location.href);
|
|
2691
|
-
// this.baseApp = new
|
|
2692
2863
|
}
|
|
2864
|
+
// 删除缓存
|
|
2693
2865
|
deleteApp(url) {
|
|
2694
2866
|
this.cache.delete(url);
|
|
2695
2867
|
}
|
|
2868
|
+
// 获取缓存app
|
|
2696
2869
|
getApp(name) {
|
|
2697
2870
|
if (!name)
|
|
2698
2871
|
return undefined;
|
|
@@ -2701,6 +2874,7 @@ class AppCache {
|
|
|
2701
2874
|
return app;
|
|
2702
2875
|
return Array.from(this.cache.values()).find((item) => item.name === name);
|
|
2703
2876
|
}
|
|
2877
|
+
// 获取缓存app
|
|
2704
2878
|
getBaseAppStyle(urlOrCode) {
|
|
2705
2879
|
return this.baseSource.getStyle(urlOrCode);
|
|
2706
2880
|
}
|
|
@@ -2733,9 +2907,6 @@ class AppCache {
|
|
|
2733
2907
|
});
|
|
2734
2908
|
return style;
|
|
2735
2909
|
}
|
|
2736
|
-
get hasActiveApp() {
|
|
2737
|
-
return Array.from(this.cache.values()).some((app) => app.status !== AppState.UNMOUNT);
|
|
2738
|
-
}
|
|
2739
2910
|
setApp(app) {
|
|
2740
2911
|
this.cache.set(app.appCacheKey, app);
|
|
2741
2912
|
}
|
|
@@ -2745,6 +2916,9 @@ class AppCache {
|
|
|
2745
2916
|
setBaseAppStyle(url, style) {
|
|
2746
2917
|
this.baseSource.setStyle(url, style);
|
|
2747
2918
|
}
|
|
2919
|
+
get hasActiveApp() {
|
|
2920
|
+
return Array.from(this.cache.values()).some((app) => app.status !== AppState.UNMOUNT);
|
|
2921
|
+
}
|
|
2748
2922
|
}
|
|
2749
2923
|
const appCache = new AppCache();
|
|
2750
2924
|
// 注册全局获取缓存app 或者 instance
|
|
@@ -2779,6 +2953,12 @@ window.__getAppOrInstance__ = function (id) {
|
|
|
2779
2953
|
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
2780
2954
|
* IN THE SOFTWARE.
|
|
2781
2955
|
*/
|
|
2956
|
+
/**
|
|
2957
|
+
* @param url 资源地址
|
|
2958
|
+
* @param style 样式实例
|
|
2959
|
+
* @param originLink 原始link标签
|
|
2960
|
+
* @returns 返回替换的style标签
|
|
2961
|
+
*/
|
|
2782
2962
|
function getStyleSource(url, style, originLink) {
|
|
2783
2963
|
const replaceStyle = document.createElement('style');
|
|
2784
2964
|
setMarkElement(replaceStyle);
|
|
@@ -2795,6 +2975,12 @@ function getStyleSource(url, style, originLink) {
|
|
|
2795
2975
|
});
|
|
2796
2976
|
return replaceStyle;
|
|
2797
2977
|
}
|
|
2978
|
+
/**
|
|
2979
|
+
* @param url 资源地址
|
|
2980
|
+
* @param script 脚本实例
|
|
2981
|
+
* @param originScript 原始script标签
|
|
2982
|
+
* @returns 返回替换的script标签
|
|
2983
|
+
*/
|
|
2798
2984
|
function getScriptSource(url, script, originScript) {
|
|
2799
2985
|
const replaceScript = document.createElement('script');
|
|
2800
2986
|
setMarkElement(replaceScript);
|
|
@@ -2818,6 +3004,10 @@ function getScriptSource(url, script, originScript) {
|
|
|
2818
3004
|
});
|
|
2819
3005
|
return replaceScript;
|
|
2820
3006
|
}
|
|
3007
|
+
/**
|
|
3008
|
+
* @param child link或者script标签
|
|
3009
|
+
* @returns 返回替换的link或者script标签
|
|
3010
|
+
*/
|
|
2821
3011
|
function createNewNode(child) {
|
|
2822
3012
|
if (child instanceof HTMLLinkElement) {
|
|
2823
3013
|
const rel = child.getAttribute('rel');
|
|
@@ -2852,9 +3042,20 @@ function createNewNode(child) {
|
|
|
2852
3042
|
}
|
|
2853
3043
|
return child;
|
|
2854
3044
|
}
|
|
3045
|
+
/**
|
|
3046
|
+
* @param node 节点
|
|
3047
|
+
* @returns 返回是否是link或者script标签
|
|
3048
|
+
*/
|
|
2855
3049
|
function isLinkOrScript(node) {
|
|
2856
3050
|
return node instanceof HTMLLinkElement || node instanceof HTMLScriptElement;
|
|
2857
3051
|
}
|
|
3052
|
+
/**
|
|
3053
|
+
* @param parent 父节点
|
|
3054
|
+
* @param newChild 新节点
|
|
3055
|
+
* @param passiveChild 被动节点
|
|
3056
|
+
* @param rawMethod 原始方法
|
|
3057
|
+
* @returns 返回原始方法的执行结果
|
|
3058
|
+
*/
|
|
2858
3059
|
function baseElementInertHandle(parent, newChild, passiveChild, rawMethod) {
|
|
2859
3060
|
if (isLinkOrScript(newChild)) {
|
|
2860
3061
|
const targetChild = createNewNode(newChild);
|
|
@@ -2862,6 +3063,12 @@ function baseElementInertHandle(parent, newChild, passiveChild, rawMethod) {
|
|
|
2862
3063
|
}
|
|
2863
3064
|
return rawMethod.call(parent, newChild, passiveChild);
|
|
2864
3065
|
}
|
|
3066
|
+
/**
|
|
3067
|
+
* @param parent 父节点
|
|
3068
|
+
* @param newChild 新节点
|
|
3069
|
+
* @param rawMethod 原始方法
|
|
3070
|
+
* @returns 返回原始方法的执行结果
|
|
3071
|
+
*/
|
|
2865
3072
|
function baseElementAppendHandle(parent, newChild, rawMethod) {
|
|
2866
3073
|
if (isLinkOrScript(newChild)) {
|
|
2867
3074
|
const targetChild = createNewNode(newChild);
|
|
@@ -2895,6 +3102,9 @@ function baseElementAppendHandle(parent, newChild, rawMethod) {
|
|
|
2895
3102
|
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
2896
3103
|
* IN THE SOFTWARE.
|
|
2897
3104
|
*/
|
|
3105
|
+
/**
|
|
3106
|
+
* 收集主应用的资源
|
|
3107
|
+
*/
|
|
2898
3108
|
function collectBaseSource() {
|
|
2899
3109
|
const rawBodyAppendChild = HTMLBodyElement.prototype.appendChild;
|
|
2900
3110
|
const rawHeadAppendChild = HTMLHeadElement.prototype.appendChild;
|