@blueking/bk-weweb 0.0.35-beta.1 → 0.0.35-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.esm.js CHANGED
@@ -119,10 +119,11 @@ var WewebMode = /* @__PURE__ */ ((WewebMode2) => {
119
119
  // src/typings/sandbox.ts
120
120
  var WINDOW_WHITE_LIST = [
121
121
  "System",
122
- // SystemJS
122
+ // SystemJS 模块加载器
123
123
  "__cjsWrapper",
124
- // SystemJS CommonJS wrapper
125
- false ? "__REACT_DEVTOOLS_GLOBAL_HOOK__" : ""
124
+ // SystemJS CommonJS 包装器
125
+ // 开发环境下允许 React DevTools
126
+ ...false ? ["__REACT_DEVTOOLS_GLOBAL_HOOK__"] : []
126
127
  ];
127
128
  var BK_WEWEB_INJECT_KEY_LIST = [
128
129
  "__POWERED_BY_BK_WEWEB__",
@@ -137,18 +138,25 @@ var COMMON_MICRO_APP_WINDOW_KEY_MAP = {
137
138
  i18n: true
138
139
  };
139
140
  var DEV_MICRO_APP_WINDOW_KEY_MAP = false ? {
141
+ // 开发环境标识
140
142
  __DEV__: true,
143
+ // Vue DevTools 相关
141
144
  __VUE_DEVTOOLS_GLOBAL_HOOK__: true,
142
145
  __VUE_DEVTOOLS_HOOK_REPLAY__: true,
143
146
  __VUE_DEVTOOLS_PLUGINS__: true,
147
+ // Vue I18n 相关
144
148
  __VUE_I18N_FULL_INSTALL__: true,
145
149
  __VUE_I18N_LEGACY_API__: true,
150
+ // Vue 配置相关
146
151
  __VUE_OPTIONS_API__: true,
152
+ // Core-js 相关
147
153
  "__core-js_shared__": true,
154
+ // Webpack 相关
148
155
  webpackChunkapm: true,
149
156
  webpackChunkpc: true,
150
157
  webpackChunktrace: true,
151
158
  webpackJsonp: true,
159
+ // 包含通用配置
152
160
  ...COMMON_MICRO_APP_WINDOW_KEY_MAP
153
161
  } : COMMON_MICRO_APP_WINDOW_KEY_MAP;
154
162
 
@@ -198,10 +206,10 @@ var isJsonpUrl = (url) => {
198
206
  };
199
207
 
200
208
  // src/context/document.ts
201
- var SPECIAL_ELEMENT_TAG = ["body", "html", "head"];
202
- var createProxyDocument = (rawDocument, app) => {
203
- const fakeDocument = {};
204
- function shadowRootInsertAdjacentHTML(where, domString) {
209
+ var SPECIAL_ELEMENT_TAGS = ["body", "html", "head"];
210
+ var APP_KEY_PROPERTY = "__BK_WEWEB_APP_KEY__";
211
+ function createShadowRootInsertAdjacentHTML(app) {
212
+ return function shadowRootInsertAdjacentHTML(where, domString) {
205
213
  const temporaryContainer = document.createElement("div");
206
214
  temporaryContainer.innerHTML = domString;
207
215
  const elements = Array.from(temporaryContainer.childNodes);
@@ -228,16 +236,18 @@ var createProxyDocument = (rawDocument, app) => {
228
236
  }
229
237
  break;
230
238
  }
231
- }
232
- const proxyBody = new Proxy(
239
+ };
240
+ }
241
+ function createProxyBody(rawDocument, app) {
242
+ return new Proxy(
233
243
  {},
234
244
  {
235
245
  get(_, key) {
236
246
  if (app.container instanceof ShadowRoot) {
237
247
  if (key === "insertAdjacentHTML") {
238
- return shadowRootInsertAdjacentHTML.bind(app.container);
248
+ return createShadowRootInsertAdjacentHTML(app);
239
249
  }
240
- const value2 = app.container[key];
250
+ const value2 = Reflect.get(app.container, key);
241
251
  if (typeof value2 === "function") {
242
252
  return value2.bind(app.container);
243
253
  }
@@ -250,7 +260,7 @@ var createProxyDocument = (rawDocument, app) => {
250
260
  },
251
261
  set(_, key, value) {
252
262
  if (app.container instanceof ShadowRoot) {
253
- app.container[key] = value;
263
+ Reflect.set(app.container, key, value);
254
264
  return true;
255
265
  }
256
266
  Reflect.set(rawDocument.body, key, value);
@@ -258,60 +268,102 @@ var createProxyDocument = (rawDocument, app) => {
258
268
  }
259
269
  }
260
270
  );
261
- function createElement(tagName, options) {
271
+ }
272
+ function createElementWithAppKey(rawDocument, app) {
273
+ return function createElement(tagName, options) {
262
274
  const element = rawDocument.createElement(tagName, options);
263
- element.__BK_WEWEB_APP_KEY__ = app.appCacheKey;
275
+ element[APP_KEY_PROPERTY] = app.appCacheKey;
264
276
  return element;
277
+ };
278
+ }
279
+ function isSpecialElementTag(selector) {
280
+ return SPECIAL_ELEMENT_TAGS.includes(selector);
281
+ }
282
+ function safeQuerySelector(container, selector) {
283
+ try {
284
+ return container?.querySelector(selector) ?? null;
285
+ } catch {
286
+ return null;
287
+ }
288
+ }
289
+ function safeQuerySelectorAll(container, selector) {
290
+ try {
291
+ return container?.querySelectorAll(selector) ?? [];
292
+ } catch {
293
+ return [];
265
294
  }
266
- function querySelectorNew(selectors) {
295
+ }
296
+ function createProxyQuerySelector(rawDocument, app, proxyBody) {
297
+ return function querySelectorNew(selectors) {
267
298
  if (selectors === proxyBody) {
268
299
  return app.container instanceof ShadowRoot ? app.container : rawDocument.body;
269
300
  }
270
- if (SPECIAL_ELEMENT_TAG.includes(selectors)) {
301
+ if (isSpecialElementTag(selectors)) {
271
302
  if (app?.container instanceof ShadowRoot) {
272
303
  return app?.container;
273
304
  }
274
305
  return rawDocument.querySelector.call(this, selectors);
275
306
  }
276
- try {
277
- return app?.container?.querySelector(selectors) ?? null;
278
- } catch {
279
- return null;
280
- }
281
- }
282
- function querySelectorAllNew(selectors) {
283
- if (SPECIAL_ELEMENT_TAG.includes(selectors)) {
307
+ return safeQuerySelector(app?.container, selectors);
308
+ };
309
+ }
310
+ function createProxyQuerySelectorAll(rawDocument, app) {
311
+ return function querySelectorAllNew(selectors) {
312
+ if (isSpecialElementTag(selectors)) {
284
313
  if (app?.container instanceof ShadowRoot) {
285
- return app?.container;
314
+ return [app?.container];
286
315
  }
287
- return rawDocument.querySelector(selectors);
316
+ const result = rawDocument.querySelector(selectors);
317
+ return result ? [result] : [];
288
318
  }
289
- return app?.container?.querySelectorAll(selectors) ?? [];
290
- }
291
- function getElementByIdNew(key) {
292
- return querySelectorNew.call(rawDocument, `#${key}`);
293
- }
294
- function getElementsByClassName(key) {
295
- return querySelectorAllNew(`.${key}`);
296
- }
297
- function getElementsByTagName(key) {
298
- if (SPECIAL_ELEMENT_TAG.includes(key) || !app?.showSourceCode && key.toLocaleLowerCase() === "script") {
299
- return rawDocument.getElementsByTagName(key);
319
+ return safeQuerySelectorAll(app?.container, selectors);
320
+ };
321
+ }
322
+ function createProxyGetElementById(rawDocument, querySelector) {
323
+ return function getElementByIdNew(id) {
324
+ return querySelector.call(rawDocument, `#${id}`);
325
+ };
326
+ }
327
+ function createProxyGetElementsByClassName(querySelectorAll) {
328
+ return function getElementsByClassName(className) {
329
+ return querySelectorAll(`.${className}`);
330
+ };
331
+ }
332
+ function createProxyGetElementsByTagName(rawDocument, app, querySelectorAll) {
333
+ return function getElementsByTagName(tagName) {
334
+ if (isSpecialElementTag(tagName) || !app?.showSourceCode && tagName.toLowerCase() === "script") {
335
+ return rawDocument.getElementsByTagName(tagName);
300
336
  }
301
- return querySelectorAllNew(key);
302
- }
303
- function getElementsByNameNew(key) {
304
- return querySelectorAllNew(`[name=${key}]`);
305
- }
306
- const methodMap = {
337
+ return querySelectorAll(tagName);
338
+ };
339
+ }
340
+ function createProxyGetElementsByName(querySelectorAll) {
341
+ return function getElementsByNameNew(name) {
342
+ return querySelectorAll(`[name="${name}"]`);
343
+ };
344
+ }
345
+ function createProxyMethodMap(rawDocument, app, proxyBody) {
346
+ const createElement = createElementWithAppKey(rawDocument, app);
347
+ const querySelector = createProxyQuerySelector(rawDocument, app, proxyBody);
348
+ const querySelectorAll = createProxyQuerySelectorAll(rawDocument, app);
349
+ const getElementById = createProxyGetElementById(rawDocument, querySelector);
350
+ const getElementsByClassName = createProxyGetElementsByClassName(querySelectorAll);
351
+ const getElementsByTagName = createProxyGetElementsByTagName(rawDocument, app, querySelectorAll);
352
+ const getElementsByName = createProxyGetElementsByName(querySelectorAll);
353
+ return {
307
354
  createElement: createElement.bind(rawDocument),
308
- querySelector: querySelectorNew.bind(rawDocument),
309
- querySelectorAll: querySelectorAllNew.bind(rawDocument),
310
- getElementById: getElementByIdNew.bind(rawDocument),
355
+ querySelector: querySelector.bind(rawDocument),
356
+ querySelectorAll: querySelectorAll.bind(rawDocument),
357
+ getElementById: getElementById.bind(rawDocument),
311
358
  getElementsByClassName: getElementsByClassName.bind(rawDocument),
312
359
  getElementsByTagName: getElementsByTagName.bind(rawDocument),
313
- getElementsByName: getElementsByNameNew.bind(rawDocument)
360
+ getElementsByName: getElementsByName.bind(rawDocument)
314
361
  };
362
+ }
363
+ var createProxyDocument = (rawDocument, app) => {
364
+ const fakeDocument = {};
365
+ const proxyBody = createProxyBody(rawDocument, app);
366
+ const methodMap = createProxyMethodMap(rawDocument, app, proxyBody);
315
367
  return new Proxy(fakeDocument, {
316
368
  get(_, key) {
317
369
  if (key === "body") {
@@ -473,6 +525,7 @@ function rewriteWindowFunction(fakeWindow) {
473
525
 
474
526
  // src/context/sandbox.ts
475
527
  var SandBox = class {
528
+ /** 初始化沙箱环境 */
476
529
  constructor(app) {
477
530
  this.app = app;
478
531
  const windowDescriptorSet = /* @__PURE__ */ new Set();
@@ -488,63 +541,30 @@ var SandBox = class {
488
541
  this.fakeWindow = fakeWindow;
489
542
  const { resetWindowFunction } = rewriteWindowFunction(this.fakeWindow);
490
543
  this.resetWindowFunction = resetWindowFunction;
491
- this.windowSymbolKey = `__${(app.name || app.appCacheKey).replace(/(-|,|:|~|'|")/gim, "_")}_${random(
492
- 10
493
- )}__`;
544
+ const appIdentifier = (app.name || app.appCacheKey).replace(/[-,:~'"]/g, "_");
545
+ this.windowSymbolKey = `__${appIdentifier}_${random(10)}__`;
494
546
  this.proxyWindow = new Proxy(this.fakeWindow, {
495
- // 定义属性
496
547
  defineProperty: (target, key, value) => {
497
548
  if (windowDescriptorSet.has(key)) {
498
549
  return Reflect.defineProperty(rawWindow, key, value);
499
550
  }
500
551
  return Reflect.defineProperty(target, key, value);
501
552
  },
502
- // 删除属性
503
553
  deleteProperty: (target, key) => {
504
554
  if (Object.hasOwn(target, key)) {
505
- this.sameRawWindowKeySet.has(key) && this.sameRawWindowKeySet.delete(key);
506
- this.inRawWindowKeySet.has(key) && Reflect.deleteProperty(rawWindow, key);
555
+ if (this.sameRawWindowKeySet.has(key)) {
556
+ this.sameRawWindowKeySet.delete(key);
557
+ }
558
+ if (this.inRawWindowKeySet.has(key)) {
559
+ Reflect.deleteProperty(rawWindow, key);
560
+ }
507
561
  return Reflect.deleteProperty(target, key);
508
562
  }
509
563
  return true;
510
564
  },
511
- // 获取属性
512
565
  get: (target, key) => {
513
- if (key === Symbol.unscopables || windowNativeFuncMap.has(key)) return rawWindow[key];
514
- if (DEV_MICRO_APP_WINDOW_KEY_MAP[key]) return this.fakeWindow[key];
515
- if (WINDOW_ALIAS_LIST.includes(key)) return this.proxyWindow;
516
- if (key === "document") {
517
- app.registerRunningApp();
518
- return this.rawDocument;
519
- }
520
- if (key === "eval") {
521
- app.registerRunningApp();
522
- return eval;
523
- }
524
- if (BK_WEWEB_LOCATION_KEY_LIST.includes(key) && this.app instanceof MicroAppModel && this.app.iframe && this.app.scopeLocation) {
525
- return this.app.iframe.contentWindow?.[key];
526
- }
527
- if (key === "hasOwnProperty")
528
- return (key2) => Object.hasOwn(this.fakeWindow, key2) || Object.hasOwn(rawWindow, key2);
529
- if (key === "top" || key === "parent") {
530
- if (rawWindow === rawWindow.parent) {
531
- return this.proxyWindow;
532
- }
533
- return Reflect.get(rawWindow, key);
534
- }
535
- if (key === "getComputedStyle") {
536
- return (element, pseudoElt) => {
537
- if (element instanceof Element) {
538
- return rawWindow.getComputedStyle(element, pseudoElt);
539
- }
540
- return rawWindow.getComputedStyle(document.body, pseudoElt);
541
- };
542
- }
543
- if (Reflect.has(target, key) || BK_WEWEB_INJECT_KEY_LIST.includes(key)) return Reflect.get(target, key);
544
- const rawValue = Reflect.get(rawWindow, key);
545
- return bindFunctionToRawWindow(rawWindow, rawValue);
566
+ return this.handleProxyGet(target, key, rawWindow);
546
567
  },
547
- // 获取属性描述符
548
568
  getOwnPropertyDescriptor: (target, key) => {
549
569
  if (Object.hasOwn(target, key)) {
550
570
  return Object.getOwnPropertyDescriptor(target, key);
@@ -559,69 +579,188 @@ var SandBox = class {
559
579
  }
560
580
  return void 0;
561
581
  },
562
- // 检查属性是否存在
563
582
  has: (target, key) => windowNativeFuncMap.has(key) || key in target || key in rawWindow,
564
- // 获取所有属性名
565
583
  ownKeys: (target) => Array.from(new Set(Reflect.ownKeys(rawWindow).concat(Reflect.ownKeys(target)))),
566
- // 设置属性
567
584
  set: (target, key, value) => {
568
- if (this.active) {
569
- if (BK_WEWEB_LOCATION_KEY_LIST.includes(key) && this.app instanceof MicroAppModel && this.app.iframe && this.app.scopeLocation) {
570
- return Reflect.set(this.app.iframe.contentWindow, key, value);
571
- }
572
- if (key === "location") {
573
- Reflect.set(rawWindow, key, value);
574
- } else if (!Object.hasOwn(target, key) && Object.hasOwn(rawWindow, key) && !BK_WEWEB_INJECT_KEY_LIST.includes(key)) {
575
- const descriptor = Object.getOwnPropertyDescriptor(rawWindow, key);
576
- const { configurable, enumerable, writable } = descriptor;
577
- if (writable) {
578
- Object.defineProperty(target, key, {
579
- configurable,
580
- enumerable,
581
- value,
582
- writable
583
- });
584
- this.sameRawWindowKeySet.add(key);
585
- }
586
- } else {
587
- Reflect.set(target, key, value);
588
- this.sameRawWindowKeySet.add(key);
589
- }
590
- if (WINDOW_WHITE_LIST.includes(key) && !Reflect.has(rawWindow, key) && !BK_WEWEB_INJECT_KEY_LIST.includes(key)) {
591
- Reflect.set(rawWindow, key, value);
592
- this.inRawWindowKeySet.add(key);
593
- }
594
- }
595
- return true;
585
+ return this.handleProxySet(target, key, value, rawWindow);
596
586
  }
597
587
  });
598
588
  rawWindow[this.windowSymbolKey] = this.proxyWindow;
599
589
  }
600
- // 沙箱激活状态
590
+ /** 沙箱激活状态标识 */
601
591
  active = false;
602
- // 记录在原始window上新增的属性
592
+ /** 记录在原始 window 上新增的属性键集合 */
603
593
  inRawWindowKeySet = /* @__PURE__ */ new Set();
604
- // 重置文档和body事件的函数
594
+ /** 重置文档和 body 事件的函数 */
605
595
  resetDocumentAndBodyEvent;
606
- // 重置window函数的方法
596
+ /** 重置 window 函数的方法 */
607
597
  resetWindowFunction;
608
- // 记录与原始window相同的属性
598
+ /** 记录与原始 window 相同的属性键集合 */
609
599
  sameRawWindowKeySet = /* @__PURE__ */ new Set();
610
- // 伪造的window对象
600
+ /** 伪造的 window 对象 */
611
601
  fakeWindow;
612
- // 代理的document对象
602
+ /** 代理的 document 对象 */
613
603
  proxyDocument;
614
- // 代理的window对象
604
+ /** 代理的 window 对象 */
615
605
  proxyWindow;
616
- // 原始document对象
606
+ /** 原始 document 对象 */
617
607
  rawDocument;
618
- // 原始window对象
608
+ /** 原始 window 对象 */
619
609
  rawWindow;
620
- // window上的唯一标识key
610
+ /** window 上的唯一标识键 */
621
611
  windowSymbolKey;
612
+ /** 处理代理对象的 get 操作 */
613
+ handleProxyGet(target, key, rawWindow) {
614
+ if (key === Symbol.unscopables || windowNativeFuncMap.has(key)) {
615
+ return rawWindow[key];
616
+ }
617
+ if (DEV_MICRO_APP_WINDOW_KEY_MAP[key]) {
618
+ return this.fakeWindow[key];
619
+ }
620
+ if (WINDOW_ALIAS_LIST.includes(key)) {
621
+ return this.proxyWindow;
622
+ }
623
+ if (key === "document") {
624
+ this.app.registerRunningApp();
625
+ return this.rawDocument;
626
+ }
627
+ if (key === "eval") {
628
+ this.app.registerRunningApp();
629
+ return eval;
630
+ }
631
+ if (this.shouldUseIframeLocation(key)) {
632
+ if (this.app instanceof MicroAppModel && this.app.iframe?.contentWindow) {
633
+ return this.app.iframe.contentWindow[key];
634
+ }
635
+ return void 0;
636
+ }
637
+ if (key === "hasOwnProperty") {
638
+ return (checkKey) => Object.hasOwn(this.fakeWindow, checkKey) || Object.hasOwn(rawWindow, checkKey);
639
+ }
640
+ if (key === "top" || key === "parent") {
641
+ if (rawWindow === rawWindow.parent) {
642
+ return this.proxyWindow;
643
+ }
644
+ return Reflect.get(rawWindow, key);
645
+ }
646
+ if (key === "getComputedStyle") {
647
+ return this.createGetComputedStyleProxy(rawWindow);
648
+ }
649
+ if (Reflect.has(target, key) || BK_WEWEB_INJECT_KEY_LIST.includes(key)) {
650
+ return Reflect.get(target, key);
651
+ }
652
+ const rawValue = Reflect.get(rawWindow, key);
653
+ return bindFunctionToRawWindow(rawWindow, rawValue);
654
+ }
655
+ /**
656
+ * 处理代理对象的 set 操作
657
+ * @description 统一处理代理对象属性设置的复杂逻辑
658
+ * @param target - 目标对象
659
+ * @param key - 属性键
660
+ * @param value - 属性值
661
+ * @param rawWindow - 原始 window 对象
662
+ * @returns boolean - 设置是否成功
663
+ * @private
664
+ */
665
+ handleProxySet(target, key, value, rawWindow) {
666
+ if (!this.active) {
667
+ return true;
668
+ }
669
+ if (this.shouldUseIframeLocation(key)) {
670
+ const iframe = this.app instanceof MicroAppModel ? this.app.iframe : null;
671
+ return iframe?.contentWindow ? Reflect.set(iframe.contentWindow, key, value) : true;
672
+ }
673
+ if (key === "location") {
674
+ Reflect.set(rawWindow, key, value);
675
+ } else if (this.shouldSetOnTarget(target, key, rawWindow)) {
676
+ this.setPropertyOnTarget(target, key, value, rawWindow);
677
+ } else {
678
+ Reflect.set(target, key, value);
679
+ this.sameRawWindowKeySet.add(key);
680
+ }
681
+ this.handleWhiteListProperty(key, value, rawWindow);
682
+ return true;
683
+ }
684
+ /**
685
+ * 判断是否应该使用 iframe 的 location
686
+ * @description 检查是否在 iframe 模式下访问 location 相关属性
687
+ * @param key - 属性键
688
+ * @returns boolean - 是否使用 iframe location
689
+ * @private
690
+ */
691
+ shouldUseIframeLocation(key) {
692
+ return !!(BK_WEWEB_LOCATION_KEY_LIST.includes(key) && this.app instanceof MicroAppModel && this.app.iframe && this.app.scopeLocation);
693
+ }
694
+ /**
695
+ * 创建 getComputedStyle 方法的代理
696
+ * @description 为 getComputedStyle 方法创建安全的代理实现
697
+ * @param rawWindow - 原始 window 对象
698
+ * @returns Function - 代理后的 getComputedStyle 方法
699
+ * @private
700
+ */
701
+ createGetComputedStyleProxy(rawWindow) {
702
+ return (element, pseudoElt) => {
703
+ if (element instanceof Element) {
704
+ return rawWindow.getComputedStyle(element, pseudoElt);
705
+ }
706
+ return rawWindow.getComputedStyle(document.body, pseudoElt);
707
+ };
708
+ }
709
+ /**
710
+ * 判断是否应该在目标对象上设置属性
711
+ * @description 检查属性设置的逻辑条件
712
+ * @param target - 目标对象
713
+ * @param key - 属性键
714
+ * @param rawWindow - 原始 window 对象
715
+ * @returns boolean - 是否在目标对象上设置
716
+ * @private
717
+ */
718
+ shouldSetOnTarget(target, key, rawWindow) {
719
+ return !Object.hasOwn(target, key) && Object.hasOwn(rawWindow, key) && !BK_WEWEB_INJECT_KEY_LIST.includes(key);
720
+ }
721
+ /**
722
+ * 在目标对象上设置属性
723
+ * @description 安全地在目标对象上设置属性,保持描述符特性
724
+ * @param target - 目标对象
725
+ * @param key - 属性键
726
+ * @param value - 属性值
727
+ * @param rawWindow - 原始 window 对象
728
+ * @private
729
+ */
730
+ setPropertyOnTarget(target, key, value, rawWindow) {
731
+ const descriptor = Object.getOwnPropertyDescriptor(rawWindow, key);
732
+ if (!descriptor) {
733
+ return;
734
+ }
735
+ const { configurable, enumerable, writable } = descriptor;
736
+ if (writable) {
737
+ Object.defineProperty(target, key, {
738
+ configurable,
739
+ enumerable,
740
+ value,
741
+ writable
742
+ });
743
+ this.sameRawWindowKeySet.add(key);
744
+ }
745
+ }
746
+ /**
747
+ * 处理白名单属性
748
+ * @description 处理需要在原始 window 上设置的白名单属性
749
+ * @param key - 属性键
750
+ * @param value - 属性值
751
+ * @param rawWindow - 原始 window 对象
752
+ * @private
753
+ */
754
+ handleWhiteListProperty(key, value, rawWindow) {
755
+ if (WINDOW_WHITE_LIST.includes(key) && !Reflect.has(rawWindow, key) && !BK_WEWEB_INJECT_KEY_LIST.includes(key)) {
756
+ Reflect.set(rawWindow, key, value);
757
+ this.inRawWindowKeySet.add(key);
758
+ }
759
+ }
622
760
  /**
623
761
  * 激活沙箱
624
- * @param data 传递给沙箱的数据
762
+ * @description 启动沙箱环境,初始化代理对象和事件处理
763
+ * @param data - 传递给沙箱的数据(可选)
625
764
  */
626
765
  activated(data) {
627
766
  if (!this.active) {
@@ -633,7 +772,8 @@ var SandBox = class {
633
772
  }
634
773
  }
635
774
  /**
636
- * 停用沙箱,清理所有副作用
775
+ * 停用沙箱
776
+ * @description 关闭沙箱环境,清理所有副作用和修改
637
777
  */
638
778
  deactivated() {
639
779
  if (!this.active) return;
@@ -1241,9 +1381,7 @@ var MicroInstanceModel = class {
1241
1381
  this.fetchSource = props.fetchSource;
1242
1382
  this.initializeSandBox();
1243
1383
  }
1244
- /**
1245
- * 激活微模块
1246
- */
1384
+ /** 激活微模块 */
1247
1385
  activated(container, callback) {
1248
1386
  this.isPreLoad = false;
1249
1387
  this.state = AppState.ACTIVATED;
@@ -1256,22 +1394,19 @@ var MicroInstanceModel = class {
1256
1394
  callback?.(this, scriptInfo?.exportInstance);
1257
1395
  }
1258
1396
  }
1259
- /**
1260
- * 停用微模块
1261
- */
1397
+ /** 停用微模块 */
1262
1398
  deactivated() {
1263
1399
  this.state = AppState.DEACTIVATED;
1264
1400
  this.sandBox?.deactivated();
1265
1401
  }
1266
- /**
1267
- * 挂载微模块
1268
- */
1402
+ /** 挂载微模块 */
1269
1403
  mount(container, callback) {
1270
1404
  this.isPreLoad = false;
1271
1405
  this.container = container ?? this.container;
1272
1406
  this.state = AppState.MOUNTING;
1273
1407
  this.setContainerAttribute(this.container);
1274
1408
  this.setupContainer();
1409
+ this.executeStyles();
1275
1410
  this.sandBox?.activated();
1276
1411
  execAppScripts(this).finally(() => {
1277
1412
  this.state = AppState.MOUNTED;
@@ -1280,39 +1415,29 @@ var MicroInstanceModel = class {
1280
1415
  callback?.(this, scriptInfo?.exportInstance);
1281
1416
  });
1282
1417
  }
1283
- /**
1284
- * 错误处理
1285
- */
1418
+ /** 错误处理 */
1286
1419
  onError() {
1287
1420
  this.state = AppState.ERROR;
1288
1421
  }
1289
- /**
1290
- * 挂载处理
1291
- */
1422
+ /** 挂载处理 */
1292
1423
  onMount() {
1293
1424
  if (this.isPreLoad) return;
1294
1425
  this.state = AppState.LOADED;
1295
1426
  this.mount();
1296
1427
  }
1297
- /**
1298
- * 注册运行中的应用
1299
- */
1428
+ /** 注册运行中的应用 */
1300
1429
  registerRunningApp() {
1301
1430
  setCurrentRunningApp(this);
1302
1431
  Promise.resolve().then(() => setCurrentRunningApp(null));
1303
1432
  }
1304
- /**
1305
- * 启动微模块
1306
- */
1433
+ /** 启动微模块 */
1307
1434
  async start() {
1308
1435
  if (!this.source || this.needsReload()) {
1309
1436
  this.source = new EntrySource(this.url);
1310
1437
  await this.source.importEntry(this);
1311
1438
  }
1312
1439
  }
1313
- /**
1314
- * 卸载微模块
1315
- */
1440
+ /** 卸载微模块 */
1316
1441
  unmount(needDestroy) {
1317
1442
  this.state = AppState.UNMOUNT;
1318
1443
  this.sandBox?.deactivated();
@@ -1324,37 +1449,25 @@ var MicroInstanceModel = class {
1324
1449
  this.container = void 0;
1325
1450
  }
1326
1451
  }
1327
- /**
1328
- * 设置微模块 状态
1329
- */
1330
1452
  set status(value) {
1331
1453
  this.state = value;
1332
1454
  }
1333
- /**
1334
- * 获取微模块 状态
1335
- */
1336
1455
  get status() {
1337
1456
  return this.state;
1338
1457
  }
1339
- /**
1340
- * 初始化沙盒
1341
- */
1458
+ /** 初始化沙盒 */
1342
1459
  initializeSandBox() {
1343
1460
  if (this.scopeJs) {
1344
1461
  this.sandBox = new SandBox(this);
1345
1462
  }
1346
1463
  }
1347
- /**
1348
- * 设置容器属性
1349
- */
1464
+ /** 设置容器属性 */
1350
1465
  setContainerAttribute(container) {
1351
1466
  if (container instanceof HTMLElement) {
1352
1467
  container.setAttribute(CSS_ATTRIBUTE_KEY, this.name);
1353
1468
  }
1354
1469
  }
1355
- /**
1356
- * 转移节点到新容器
1357
- */
1470
+ /** 转移节点到新容器 */
1358
1471
  transferNodes(container) {
1359
1472
  if (!this.container) return;
1360
1473
  const fragment = document.createDocumentFragment();
@@ -1364,51 +1477,46 @@ var MicroInstanceModel = class {
1364
1477
  }
1365
1478
  container.appendChild(fragment);
1366
1479
  }
1367
- /**
1368
- * 设置容器
1369
- */
1480
+ /** 设置容器 */
1370
1481
  setupContainer() {
1371
- if (!this.container) return;
1372
- this.container.innerHTML = "";
1373
- const instanceWrap = this.createInstanceWrapper();
1374
- if (this.source?.styles.size) {
1482
+ if (this.container) {
1483
+ this.container.innerHTML = "";
1484
+ if (this.showSourceCode) {
1485
+ const instanceWrapper = this.createInstanceWrapper();
1486
+ this.container.appendChild(instanceWrapper);
1487
+ }
1488
+ }
1489
+ }
1490
+ /** 执行样式 */
1491
+ executeStyles() {
1492
+ if (this.source?.styles.size && this.container) {
1375
1493
  executeAppStyles(this, this.container);
1376
1494
  }
1377
- this.container.appendChild(instanceWrap);
1378
1495
  }
1379
- /**
1380
- * 创建微模块 包装器
1381
- */
1496
+ /** 创建实例包装器 */
1382
1497
  createInstanceWrapper() {
1383
- const instanceWrap = document.createElement("div");
1384
- const wrapId = `${this.name}${WRAPPER_SUFFIX}`;
1385
- instanceWrap.setAttribute("id", wrapId);
1386
- return instanceWrap;
1498
+ const wrapper = document.createElement("div");
1499
+ wrapper.id = `${this.name}${WRAPPER_SUFFIX}`;
1500
+ return wrapper;
1387
1501
  }
1388
- /**
1389
- * 渲染微模块
1390
- */
1502
+ /** 渲染实例 */
1391
1503
  renderInstance() {
1392
1504
  const scriptInfo = this.getScriptInfo();
1393
- const renderFunction = scriptInfo?.exportInstance?.render;
1394
- if (typeof renderFunction === "function") {
1395
- const instanceWrap = this.container?.querySelector(`#${this.name}${WRAPPER_SUFFIX}`);
1396
- if (instanceWrap) {
1397
- renderFunction(instanceWrap, this.data);
1505
+ if (scriptInfo?.exportInstance?.render && this.container) {
1506
+ const targetContainer = this.showSourceCode ? this.container.querySelector(`#${this.name}${WRAPPER_SUFFIX}`) : this.container;
1507
+ if (targetContainer) {
1508
+ scriptInfo.exportInstance.render(targetContainer, this.data);
1398
1509
  }
1399
1510
  }
1400
1511
  }
1401
- /**
1402
- * 获取脚本信息
1403
- */
1512
+ /** 获取脚本信息 */
1404
1513
  getScriptInfo() {
1405
- return this.source?.getScript(this.url);
1514
+ const script = this.source?.getScript(this.url);
1515
+ return script ? { exportInstance: script.exportInstance } : void 0;
1406
1516
  }
1407
- /**
1408
- * 检查是否需要重新加载
1409
- */
1517
+ /** 检查是否需要重新加载 */
1410
1518
  needsReload() {
1411
- return [AppState.ERROR, AppState.UNSET].some((status) => status === this.status);
1519
+ return this.status === AppState.ERROR;
1412
1520
  }
1413
1521
  };
1414
1522
 
@@ -1437,12 +1545,7 @@ var Script = class {
1437
1545
  this.fromHtml = fromHtml ?? false;
1438
1546
  this.initial = initial ?? false;
1439
1547
  }
1440
- /**
1441
- * 执行脚本代码
1442
- * @param app 应用实例
1443
- * @param needReplaceScriptElement 是否需要替换script标签
1444
- * @returns 返回执行后的script标签或注释
1445
- */
1548
+ /** 执行脚本代码 */
1446
1549
  async executeCode(app, needReplaceScriptElement = false) {
1447
1550
  try {
1448
1551
  if (!this.code) await this.getCode(app);
@@ -1482,9 +1585,7 @@ var Script = class {
1482
1585
  }
1483
1586
  return;
1484
1587
  }
1485
- /**
1486
- * 内存脚本执行
1487
- */
1588
+ /** 内存脚本执行 */
1488
1589
  executeMemoryScript(app, scopedCode) {
1489
1590
  try {
1490
1591
  const isScopedLocation = app instanceof MicroAppModel && app.scopeLocation;
@@ -1498,9 +1599,7 @@ var Script = class {
1498
1599
  console.error(error);
1499
1600
  }
1500
1601
  }
1501
- /**
1502
- * 脚本标签执行
1503
- */
1602
+ /** 脚本标签执行 */
1504
1603
  executeSourceScript(scriptElement, scopedCode) {
1505
1604
  if (this.isModule) {
1506
1605
  scriptElement.src = `${this.url}?key=${Date.now()}`;
@@ -1510,9 +1609,7 @@ var Script = class {
1510
1609
  }
1511
1610
  this.url && scriptElement.setAttribute("origin-src", this.url);
1512
1611
  }
1513
- /**
1514
- * 获取脚本内容
1515
- */
1612
+ /** 获取脚本内容 */
1516
1613
  async getCode(app) {
1517
1614
  if (this.code.length || !this.url) {
1518
1615
  return this.code;
@@ -1537,9 +1634,7 @@ var Script = class {
1537
1634
  setCode(code) {
1538
1635
  this.code = code;
1539
1636
  }
1540
- /**
1541
- * 转换脚本内容
1542
- */
1637
+ /** 转换脚本内容 */
1543
1638
  transformCode(app) {
1544
1639
  const sourceMapUrl = "";
1545
1640
  if (app.sandBox) {
@@ -1684,9 +1779,7 @@ var MicroAppModel = class {
1684
1779
  this.initializeSandBox();
1685
1780
  this.setContainerAttribute();
1686
1781
  }
1687
- /**
1688
- * 激活微应用
1689
- */
1782
+ /** 激活微应用 */
1690
1783
  activated(container, callback) {
1691
1784
  this.isPreLoad = false;
1692
1785
  this.state = AppState.ACTIVATED;
@@ -1699,9 +1792,7 @@ var MicroAppModel = class {
1699
1792
  callback?.(this);
1700
1793
  }
1701
1794
  }
1702
- /**
1703
- * 创建隔离iframe
1704
- */
1795
+ /** 创建隔离iframe */
1705
1796
  createIframe() {
1706
1797
  return new Promise((resolve) => {
1707
1798
  const iframe = this.createIframeElement();
@@ -1713,16 +1804,12 @@ var MicroAppModel = class {
1713
1804
  }
1714
1805
  });
1715
1806
  }
1716
- /**
1717
- * 停用微应用
1718
- */
1807
+ /** 停用微应用 */
1719
1808
  deactivated() {
1720
1809
  this.state = AppState.DEACTIVATED;
1721
1810
  this.sandBox?.deactivated();
1722
1811
  }
1723
- /**
1724
- * 初始化ShadowRoot容器
1725
- */
1812
+ /** 初始化ShadowRoot容器 */
1726
1813
  initShadowRootContainer() {
1727
1814
  if (this.container instanceof ShadowRoot) {
1728
1815
  Object.defineProperties(this.container, {
@@ -1734,9 +1821,7 @@ var MicroAppModel = class {
1734
1821
  });
1735
1822
  }
1736
1823
  }
1737
- /**
1738
- * 挂载微应用
1739
- */
1824
+ /** 挂载微应用 */
1740
1825
  mount(container, callback) {
1741
1826
  this.isPreLoad = false;
1742
1827
  this.container = container ?? this.container;
@@ -1752,30 +1837,22 @@ var MicroAppModel = class {
1752
1837
  });
1753
1838
  }
1754
1839
  }
1755
- /**
1756
- * 错误处理
1757
- */
1840
+ /** 错误处理 */
1758
1841
  onError() {
1759
1842
  this.state = AppState.ERROR;
1760
1843
  }
1761
- /**
1762
- * 挂载处理
1763
- */
1844
+ /** 挂载处理 */
1764
1845
  onMount() {
1765
1846
  if (this.isPreLoad) return;
1766
1847
  this.state = AppState.LOADED;
1767
1848
  this.mount();
1768
1849
  }
1769
- /**
1770
- * 注册运行中的微应用
1771
- */
1850
+ /** 注册运行中的微应用 */
1772
1851
  registerRunningApp() {
1773
1852
  setCurrentRunningApp(this);
1774
1853
  Promise.resolve().then(() => setCurrentRunningApp(null));
1775
1854
  }
1776
- /**
1777
- * 启动微应用
1778
- */
1855
+ /** 启动微应用 */
1779
1856
  async start() {
1780
1857
  if (!this.source || this.needsReload()) {
1781
1858
  this.state = AppState.LOADING;
@@ -1787,9 +1864,7 @@ var MicroAppModel = class {
1787
1864
  await this.source.importEntry(this);
1788
1865
  }
1789
1866
  }
1790
- /**
1791
- * 卸载微应用
1792
- */
1867
+ /** 卸载微应用 */
1793
1868
  unmount(needDestroy = false) {
1794
1869
  this.state = AppState.UNMOUNT;
1795
1870
  this.sandBox?.deactivated();
@@ -1801,123 +1876,84 @@ var MicroAppModel = class {
1801
1876
  this.container = void 0;
1802
1877
  }
1803
1878
  }
1804
- /**
1805
- * 获取微应用缓存键
1806
- */
1807
1879
  get appCacheKey() {
1808
1880
  return this.url;
1809
1881
  }
1810
- /**
1811
- * 获取微应用状态
1812
- */
1813
1882
  get status() {
1814
1883
  return this.state;
1815
1884
  }
1816
- /**
1817
- * 设置微应用状态
1818
- */
1819
1885
  set status(value) {
1820
1886
  this.state = value;
1821
1887
  }
1822
- /**
1823
- * 初始化沙盒
1824
- */
1888
+ /** 初始化沙盒 */
1825
1889
  initializeSandBox() {
1826
1890
  if (this.scopeJs) {
1827
1891
  this.sandBox = new SandBox(this);
1828
1892
  }
1829
1893
  }
1830
- /**
1831
- * 设置容器属性
1832
- */
1894
+ /** 设置容器属性 */
1833
1895
  setContainerAttribute(container) {
1834
1896
  const targetContainer = container || this.container;
1835
1897
  if (targetContainer instanceof HTMLElement) {
1836
1898
  targetContainer.setAttribute(CSS_ATTRIBUTE_KEY, this.name);
1837
1899
  }
1838
1900
  }
1839
- /**
1840
- * 转移节点到新容器
1841
- */
1901
+ /** 转移节点到新容器 */
1842
1902
  transferNodes(container) {
1903
+ if (!this.container) return;
1843
1904
  const fragment = document.createDocumentFragment();
1844
1905
  const nodeList = Array.from(this.container.childNodes);
1845
1906
  for (const node of nodeList) {
1846
1907
  this.setupNodeProperties(node);
1847
1908
  fragment.appendChild(node);
1848
1909
  }
1849
- container.innerHTML = "";
1850
1910
  container.appendChild(fragment);
1851
1911
  }
1852
- /**
1853
- * 设置节点属性
1854
- */
1912
+ /** 设置节点属性 */
1855
1913
  setupNodeProperties(node) {
1856
- node.__BK_WEWEB_APP_KEY__ = this.appCacheKey;
1857
- Object.defineProperties(node, {
1858
- ownerDocument: {
1859
- get: () => this.sandBox?.rawDocument
1860
- }
1861
- });
1914
+ const nodeWithProps = node;
1915
+ if (this.keepAlive) {
1916
+ nodeWithProps.__KEEP_ALIVE__ = this.name;
1917
+ }
1918
+ nodeWithProps.__BK_WEWEB_APP_KEY__ = this.name;
1919
+ nodeWithProps.data = this.data;
1862
1920
  }
1863
- /**
1864
- * 创建iframe元素
1865
- */
1921
+ /** 创建iframe元素 */
1866
1922
  createIframeElement() {
1867
1923
  const iframe = document.createElement("iframe");
1868
1924
  const url = new URL(addUrlProtocol(this.url));
1869
- const srcUrl = this.buildIframeSrc(url);
1870
- iframe.setAttribute("src", srcUrl);
1925
+ iframe.src = this.buildIframeSrc(url);
1871
1926
  iframe.style.cssText = IFRAME_CONSTANTS.STYLE_HIDDEN;
1872
1927
  return iframe;
1873
1928
  }
1874
- /**
1875
- * 构建iframe的src地址
1876
- */
1929
+ /** 构建iframe源地址 */
1877
1930
  buildIframeSrc(url) {
1878
- const origin = this.isChromeUserAgent() ? IFRAME_CONSTANTS.BLANK_ORIGIN : location.origin;
1879
- return `${origin}${url.pathname || "/"}${url.search}${url.hash}`;
1931
+ return `${url.protocol}//${url.host}`;
1880
1932
  }
1881
- /**
1882
- * 检查是否为Chrome用户代理
1883
- */
1933
+ /** 检查是否为Chrome浏览器 */
1884
1934
  isChromeUserAgent() {
1885
- return navigator.userAgent.indexOf(IFRAME_CONSTANTS.CHROME_USER_AGENT) > -1;
1935
+ return navigator.userAgent.includes(IFRAME_CONSTANTS.CHROME_USER_AGENT);
1886
1936
  }
1887
- /**
1888
- * 处理非Chrome浏览器的iframe
1889
- */
1937
+ /** 处理非Chrome浏览器iframe */
1890
1938
  handleNonChromeIframe(iframe, resolve) {
1891
- const interval = setInterval(() => {
1892
- if (iframe.contentWindow && iframe.contentWindow.location.href !== IFRAME_CONSTANTS.BLANK_ORIGIN) {
1893
- iframe.contentWindow.stop();
1894
- const body = iframe.contentDocument?.body;
1895
- if (body?.parentElement) {
1896
- body.parentElement.innerHTML = IFRAME_CONSTANTS.DEFAULT_HTML;
1897
- }
1898
- clearInterval(interval);
1899
- resolve(iframe);
1900
- }
1901
- }, IFRAME_CONSTANTS.POLLING_INTERVAL);
1939
+ const iframeOnload = () => {
1940
+ resolve(iframe);
1941
+ };
1942
+ if (iframe.contentDocument?.readyState === "complete") {
1943
+ iframeOnload();
1944
+ } else {
1945
+ iframe.addEventListener("load", iframeOnload);
1946
+ }
1902
1947
  }
1903
- /**
1904
- * 渲染微应用内容
1905
- */
1948
+ /** 渲染应用内容 */
1906
1949
  renderAppContent() {
1907
- const clonedNode = this.source?.html?.cloneNode(true);
1908
- const fragment = document.createDocumentFragment();
1909
- for (const node of Array.from(clonedNode?.childNodes || [])) {
1910
- this.setupNodeProperties(node);
1911
- fragment.appendChild(node);
1950
+ if (this.showSourceCode && this.source) {
1951
+ this.container.innerHTML = this.source.rawHtml || IFRAME_CONSTANTS.DEFAULT_HTML;
1912
1952
  }
1913
- this.container.innerHTML = "";
1914
- this.container.appendChild(fragment);
1915
1953
  }
1916
- /**
1917
- * 检查是否需要重新加载
1918
- */
1954
+ /** 检查是否需要重新加载 */
1919
1955
  needsReload() {
1920
- return [AppState.ERROR, AppState.UNSET].some((status) => status === this.status);
1956
+ return this.status === AppState.ERROR;
1921
1957
  }
1922
1958
  };
1923
1959
 
@@ -2012,9 +2048,7 @@ var EntrySource = class {
2012
2048
  rawHtml;
2013
2049
  scripts;
2014
2050
  styles;
2015
- /**
2016
- * 收集链接元素
2017
- */
2051
+ /** 收集链接元素 */
2018
2052
  collectLink = (link, parent, needReplaceElement = false) => {
2019
2053
  if (link.hasAttribute("exclude")) {
2020
2054
  return {
@@ -2037,9 +2071,7 @@ var EntrySource = class {
2037
2071
  }
2038
2072
  return { replace: link };
2039
2073
  };
2040
- /**
2041
- * 收集脚本元素
2042
- */
2074
+ /** 收集脚本元素 */
2043
2075
  collectScript = (script, parent, needReplaceElement = false) => {
2044
2076
  if (this.shouldIgnoreScript(script)) {
2045
2077
  return;
@@ -2056,9 +2088,7 @@ var EntrySource = class {
2056
2088
  }
2057
2089
  return { replace: script };
2058
2090
  };
2059
- /**
2060
- * 收集样式和脚本
2061
- */
2091
+ /** 收集样式和脚本 */
2062
2092
  collectScriptAndStyle = (parent) => {
2063
2093
  this.processLinks(parent);
2064
2094
  this.processStyles(parent);
@@ -2070,9 +2100,7 @@ var EntrySource = class {
2070
2100
  getStyle = (urlOrCode) => {
2071
2101
  return this.styles.get(urlOrCode) || Array.from(this.styles.values()).find((style) => style.code === urlOrCode);
2072
2102
  };
2073
- /**
2074
- * 导入入口资源
2075
- */
2103
+ /** html entry */
2076
2104
  async importEntry(app) {
2077
2105
  await this.loadInitialSources(app);
2078
2106
  if (app instanceof MicroAppModel) {
@@ -2081,9 +2109,7 @@ var EntrySource = class {
2081
2109
  await this.importInstanceEntry(app);
2082
2110
  }
2083
2111
  }
2084
- /**
2085
- * 导入HTML入口
2086
- */
2112
+ /** 微应用入口 */
2087
2113
  async importHtmlEntry(app) {
2088
2114
  const htmlStr = await this.fetchHtmlContent(app);
2089
2115
  if (!htmlStr) {
@@ -2096,9 +2122,7 @@ var EntrySource = class {
2096
2122
  await executeAppStyles(app, wrapElement);
2097
2123
  this.html = wrapElement;
2098
2124
  }
2099
- /**
2100
- * 导入实例入口
2101
- */
2125
+ /** 微模块入口 */
2102
2126
  async importInstanceEntry(app) {
2103
2127
  const jsStr = await this.fetchJsContent(app);
2104
2128
  if (!jsStr) {
@@ -2123,9 +2147,7 @@ var EntrySource = class {
2123
2147
  setStyle = (url, style) => {
2124
2148
  this.styles.set(url, style);
2125
2149
  };
2126
- /**
2127
- * 处理样式表链接
2128
- */
2150
+ /** 处理样式表链接 */
2129
2151
  handleStylesheetLink = (link, parent, href, needReplaceElement) => {
2130
2152
  const fullHref = fillUpPath(href, this.url);
2131
2153
  const replaceElement = document.createComment(`\u3010bk-weweb\u3011style with href=${fullHref}`);
@@ -2320,37 +2342,76 @@ var EntrySource = class {
2320
2342
 
2321
2343
  // src/cache/app-cache.ts
2322
2344
  var AppCache = class {
2323
- // todo 主应用共享资源包
2345
+ /** 基础资源源,用于主应用共享资源包 */
2324
2346
  baseSource;
2347
+ /** 应用实例缓存映射表 */
2325
2348
  cache;
2349
+ /**
2350
+ * 构造函数
2351
+ * @description 初始化应用缓存管理器
2352
+ */
2326
2353
  constructor() {
2327
2354
  this.cache = /* @__PURE__ */ new Map();
2328
2355
  this.baseSource = new EntrySource(location.href);
2329
2356
  }
2330
- // 删除缓存
2331
- deleteApp(url) {
2332
- this.cache.delete(url);
2357
+ /**
2358
+ * 设置应用实例到缓存
2359
+ * @description 将应用实例添加到缓存中,使用应用的缓存键作为标识
2360
+ * @param app - 要缓存的应用实例
2361
+ */
2362
+ setApp(app) {
2363
+ this.cache.set(app.appCacheKey, app);
2333
2364
  }
2334
- // 获取缓存app
2365
+ /**
2366
+ * 获取缓存的应用实例
2367
+ * @description 根据名称或ID获取已缓存的应用实例
2368
+ * @param name - 应用名称或ID,为空时返回 undefined
2369
+ * @returns BaseModel | undefined - 应用实例或 undefined
2370
+ */
2335
2371
  getApp(name) {
2336
2372
  if (!name) return void 0;
2337
2373
  const app = this.cache.get(name);
2338
2374
  if (app) return app;
2339
2375
  return Array.from(this.cache.values()).find((item) => item.name === name);
2340
2376
  }
2341
- // 获取缓存app
2342
- getBaseAppStyle(urlOrCode) {
2343
- return this.baseSource.getStyle(urlOrCode);
2377
+ /**
2378
+ * 删除缓存的应用实例
2379
+ * @description 从缓存中移除指定URL的应用实例
2380
+ * @param url - 要删除的应用URL标识
2381
+ */
2382
+ deleteApp(url) {
2383
+ this.cache.delete(url);
2344
2384
  }
2385
+ /**
2386
+ * 获取缓存的HTML内容
2387
+ * @description 根据URL获取已缓存的HTML内容
2388
+ * @param url - 应用的URL
2389
+ * @returns string - HTML内容,未找到时返回空字符串
2390
+ */
2345
2391
  getCacheHtml(url) {
2346
2392
  const list = Array.from(this.cache.values());
2347
2393
  const app = list.find((item) => item.url === url);
2348
2394
  if (app) return app.source?.rawHtml || "";
2349
2395
  return "";
2350
2396
  }
2397
+ /**
2398
+ * 设置基础应用脚本
2399
+ * @description 将脚本添加到基础资源源中,供多个应用共享
2400
+ * @param url - 脚本的URL
2401
+ * @param script - 脚本实例
2402
+ */
2403
+ setBaseAppScript(url, script) {
2404
+ this.baseSource.setScript(url, script);
2405
+ }
2406
+ /**
2407
+ * 获取缓存的脚本资源
2408
+ * @description 从基础资源源或应用缓存中获取脚本资源
2409
+ * @param url - 脚本的URL
2410
+ * @returns Script | undefined - 脚本实例或 undefined
2411
+ */
2351
2412
  getCacheScript(url) {
2352
2413
  let script = this.baseSource.getScript(url);
2353
- if (script) return;
2414
+ if (script) return script;
2354
2415
  const list = Array.from(this.cache.values());
2355
2416
  list.some((app) => {
2356
2417
  script = app.source?.getScript(url);
@@ -2358,9 +2419,33 @@ var AppCache = class {
2358
2419
  });
2359
2420
  return script;
2360
2421
  }
2422
+ /**
2423
+ * 设置基础应用样式
2424
+ * @description 将样式添加到基础资源源中,供多个应用共享
2425
+ * @param url - 样式的URL
2426
+ * @param style - 样式实例
2427
+ */
2428
+ setBaseAppStyle(url, style) {
2429
+ this.baseSource.setStyle(url, style);
2430
+ }
2431
+ /**
2432
+ * 获取基础应用样式
2433
+ * @description 从基础资源源中获取样式资源
2434
+ * @param urlOrCode - 样式的URL或代码
2435
+ * @returns Style | undefined - 样式实例或 undefined
2436
+ */
2437
+ getBaseAppStyle(urlOrCode) {
2438
+ return this.baseSource.getStyle(urlOrCode);
2439
+ }
2440
+ /**
2441
+ * 获取缓存的样式资源
2442
+ * @description 从基础资源源或应用缓存中获取样式资源
2443
+ * @param url - 样式的URL
2444
+ * @returns Style | undefined - 样式实例或 undefined
2445
+ */
2361
2446
  getCacheStyle(url) {
2362
2447
  let style = this.baseSource.getStyle(url);
2363
- if (style) return;
2448
+ if (style) return style;
2364
2449
  const list = Array.from(this.cache.values());
2365
2450
  list.some((app) => {
2366
2451
  style = app.source?.getStyle(url);
@@ -2368,15 +2453,11 @@ var AppCache = class {
2368
2453
  });
2369
2454
  return style;
2370
2455
  }
2371
- setApp(app) {
2372
- this.cache.set(app.appCacheKey, app);
2373
- }
2374
- setBaseAppScript(url, script) {
2375
- this.baseSource.setScript(url, script);
2376
- }
2377
- setBaseAppStyle(url, style) {
2378
- this.baseSource.setStyle(url, style);
2379
- }
2456
+ /**
2457
+ * 检查是否存在活跃的应用
2458
+ * @description 判断当前是否有处于非卸载状态的应用实例
2459
+ * @returns boolean - 存在活跃应用时返回 true
2460
+ */
2380
2461
  get hasActiveApp() {
2381
2462
  return Array.from(this.cache.values()).some((app) => app.status !== AppState.UNMOUNT);
2382
2463
  }
@@ -2396,8 +2477,8 @@ function getStyleSource(url, style, originLink) {
2396
2477
  appCache.setBaseAppStyle(url, style);
2397
2478
  replaceStyle.textContent = data;
2398
2479
  dispatchLinkOrScriptLoad(originLink);
2399
- }).catch((err) => {
2400
- console.error(err);
2480
+ }).catch((error) => {
2481
+ console.error("Failed to load style resource:", error);
2401
2482
  dispatchLinkOrScriptError(originLink);
2402
2483
  });
2403
2484
  return replaceStyle;
@@ -2412,59 +2493,67 @@ function getScriptSource(url, script, originScript) {
2412
2493
  if (!url.startsWith("inline-")) {
2413
2494
  originScript.setAttribute("origin-src", url);
2414
2495
  }
2415
- } catch (e) {
2416
- console.error(e, url);
2496
+ } catch (error) {
2497
+ console.error("Failed to set script content:", error, url);
2417
2498
  }
2418
2499
  dispatchLinkOrScriptLoad(originScript);
2419
- }).catch((err) => {
2420
- console.error(err);
2500
+ }).catch((error) => {
2501
+ console.error("Failed to load script resource:", error);
2421
2502
  dispatchLinkOrScriptError(originScript);
2422
2503
  });
2423
2504
  return replaceScript;
2424
2505
  }
2506
+ function processLinkElement(linkElement) {
2507
+ const rel = linkElement.getAttribute("rel");
2508
+ let href = linkElement.getAttribute("href");
2509
+ if (rel === "stylesheet" && href) {
2510
+ href = fillUpPath(href, location.origin);
2511
+ const replaceStyle = document.createElement("style");
2512
+ const styleInstance = new Style({
2513
+ code: "",
2514
+ fromHtml: false,
2515
+ url: href
2516
+ });
2517
+ getStyleSource(href, styleInstance, linkElement);
2518
+ return replaceStyle;
2519
+ }
2520
+ return linkElement;
2521
+ }
2522
+ function processScriptElement(scriptElement) {
2523
+ let src = scriptElement.getAttribute("src");
2524
+ if (src && scriptElement.type !== "module") {
2525
+ src = fillUpPath(src, location.origin);
2526
+ const script = new Script({
2527
+ async: scriptElement.hasAttribute("async"),
2528
+ code: "",
2529
+ defer: scriptElement.defer || scriptElement.type === "module",
2530
+ fromHtml: false,
2531
+ isModule: false
2532
+ });
2533
+ appCache.setBaseAppScript(src, script);
2534
+ const replaceElement = getScriptSource(src, script, scriptElement);
2535
+ return replaceElement || scriptElement;
2536
+ }
2537
+ return scriptElement;
2538
+ }
2425
2539
  function createNewNode(child) {
2426
2540
  if (child instanceof HTMLLinkElement) {
2427
- const rel = child.getAttribute("rel");
2428
- let href = child.getAttribute("href");
2429
- if (rel === "stylesheet" && href) {
2430
- href = fillUpPath(href, location.origin);
2431
- const replaceStyle = document.createElement("style");
2432
- const styleInstance = new Style({
2433
- code: "",
2434
- fromHtml: false,
2435
- url: href
2436
- });
2437
- getStyleSource(href, styleInstance, child);
2438
- return replaceStyle;
2439
- }
2541
+ return processLinkElement(child);
2440
2542
  }
2441
2543
  if (child instanceof HTMLScriptElement) {
2442
- let src = child.getAttribute("src");
2443
- if (src && child.type !== "module") {
2444
- src = fillUpPath(src, location.origin);
2445
- const script = new Script({
2446
- async: child.hasAttribute("async"),
2447
- code: "",
2448
- defer: child.defer || child.type === "module",
2449
- fromHtml: false,
2450
- isModule: false
2451
- });
2452
- appCache.setBaseAppScript(src, script);
2453
- const replaceElement = getScriptSource(src, script, child);
2454
- return replaceElement || child;
2455
- }
2544
+ return processScriptElement(child);
2456
2545
  }
2457
2546
  return child;
2458
2547
  }
2459
2548
  function isLinkOrScript(node) {
2460
2549
  return node instanceof HTMLLinkElement || node instanceof HTMLScriptElement;
2461
2550
  }
2462
- function baseElementInertHandle(parent, newChild, passiveChild, rawMethod) {
2551
+ function baseElementInertHandle(parent, newChild, referenceChild, rawMethod) {
2463
2552
  if (isLinkOrScript(newChild)) {
2464
2553
  const targetChild = createNewNode(newChild);
2465
- return rawMethod.call(parent, targetChild, passiveChild);
2554
+ return rawMethod.call(parent, targetChild, referenceChild);
2466
2555
  }
2467
- return rawMethod.call(parent, newChild, passiveChild);
2556
+ return rawMethod.call(parent, newChild, referenceChild);
2468
2557
  }
2469
2558
  function baseElementAppendHandle(parent, newChild, rawMethod) {
2470
2559
  if (isLinkOrScript(newChild)) {
@@ -2475,10 +2564,15 @@ function baseElementAppendHandle(parent, newChild, rawMethod) {
2475
2564
  }
2476
2565
 
2477
2566
  // src/base-app/collect-source.ts
2478
- function collectBaseSource() {
2479
- const rawBodyAppendChild = HTMLBodyElement.prototype.appendChild;
2480
- const rawHeadAppendChild = HTMLHeadElement.prototype.appendChild;
2481
- const rawHeadInsertBefore = HTMLHeadElement.prototype.appendChild;
2567
+ function cacheOriginalDOMMethods() {
2568
+ return {
2569
+ rawBodyAppendChild: HTMLBodyElement.prototype.appendChild,
2570
+ rawHeadAppendChild: HTMLHeadElement.prototype.appendChild,
2571
+ rawHeadInsertBefore: HTMLHeadElement.prototype.insertBefore
2572
+ };
2573
+ }
2574
+ function overrideDOMMethods(originalMethods) {
2575
+ const { rawBodyAppendChild, rawHeadAppendChild, rawHeadInsertBefore } = originalMethods;
2482
2576
  HTMLBodyElement.prototype.appendChild = function(newChild) {
2483
2577
  return baseElementAppendHandle(this, newChild, rawBodyAppendChild);
2484
2578
  };
@@ -2488,22 +2582,39 @@ function collectBaseSource() {
2488
2582
  HTMLHeadElement.prototype.insertBefore = function(newChild, refChild) {
2489
2583
  return baseElementInertHandle(this, newChild, refChild, rawHeadInsertBefore);
2490
2584
  };
2491
- window.addEventListener("load", () => {
2492
- const nodeList = document.head.querySelectorAll("style");
2493
- for (const node of Array.from(nodeList)) {
2494
- node.textContent && appCache.setBaseAppStyle(
2495
- randomUrl(),
2496
- new Style({
2497
- code: node.textContent,
2585
+ }
2586
+ function collectExistingStyles() {
2587
+ const styleNodes = document.head.querySelectorAll("style");
2588
+ for (const styleNode of Array.from(styleNodes)) {
2589
+ const textContent = styleNode.textContent;
2590
+ if (textContent) {
2591
+ try {
2592
+ const style = new Style({
2593
+ code: textContent,
2498
2594
  fromHtml: false,
2499
2595
  url: ""
2500
- })
2501
- );
2596
+ });
2597
+ appCache.setBaseAppStyle(randomUrl(), style);
2598
+ } catch (error) {
2599
+ console.warn("Failed to collect style element:", error);
2600
+ }
2502
2601
  }
2503
- });
2602
+ }
2603
+ }
2604
+ function setupLoadEventListener() {
2605
+ window.addEventListener("load", collectExistingStyles);
2606
+ }
2607
+ function collectBaseSource() {
2608
+ const originalMethods = cacheOriginalDOMMethods();
2609
+ overrideDOMMethods(originalMethods);
2610
+ setupLoadEventListener();
2504
2611
  }
2505
2612
 
2506
2613
  // src/context/element.ts
2614
+ var RESOURCE_ATTRIBUTES = ["src", "srcset"];
2615
+ var LINK_ATTRIBUTES = ["href"];
2616
+ var RESOURCE_TAG_NAMES = ["IMG", "SCRIPT"];
2617
+ var LINK_TAG_NAMES = ["LINK"];
2507
2618
  var { setAttribute } = Element.prototype;
2508
2619
  var {
2509
2620
  append,
@@ -2518,47 +2629,84 @@ var {
2518
2629
  } = HTMLHeadElement.prototype;
2519
2630
  var rawHead = document.head;
2520
2631
  var hasRewrite = false;
2521
- function rewriteBodyAndHeaderMethods() {
2522
- if (hasRewrite) return;
2523
- hasRewrite = true;
2524
- Element.prototype.setAttribute = function(key, value) {
2525
- const tagName = this.tagName.toLocaleUpperCase();
2526
- if ((["src", "srcset"].includes(key) && ["IMG", "SCRIPT"].includes(tagName) || key === "href" && ["LINK"].includes(tagName)) && this.__BK_WEWEB_APP_KEY__ && appCache.getApp(this.__BK_WEWEB_APP_KEY__ || "")) {
2527
- setAttribute.call(this, key, fillUpPath(value, appCache.getApp(this.__BK_WEWEB_APP_KEY__).url));
2528
- } else {
2529
- setAttribute.call(this, key, value);
2632
+ function shouldProcessResourcePath(key, tagName) {
2633
+ const upperTagName = tagName.toUpperCase();
2634
+ return RESOURCE_ATTRIBUTES.includes(key) && RESOURCE_TAG_NAMES.includes(upperTagName) || LINK_ATTRIBUTES.includes(key) && LINK_TAG_NAMES.includes(upperTagName);
2635
+ }
2636
+ function getElementApp(element) {
2637
+ if (!element.__BK_WEWEB_APP_KEY__) {
2638
+ return null;
2639
+ }
2640
+ return appCache.getApp(element.__BK_WEWEB_APP_KEY__);
2641
+ }
2642
+ function createOverriddenSetAttribute() {
2643
+ return function(key, value) {
2644
+ const tagName = this.tagName.toUpperCase();
2645
+ if (shouldProcessResourcePath(key, tagName) && this.__BK_WEWEB_APP_KEY__) {
2646
+ const app = getElementApp(this);
2647
+ if (app) {
2648
+ setAttribute.call(this, key, fillUpPath(value, app.url));
2649
+ return;
2650
+ }
2530
2651
  }
2652
+ setAttribute.call(this, key, value);
2531
2653
  };
2532
- HTMLBodyElement.prototype.appendChild = function appendChildNew(newChild) {
2533
- if (newChild.__KEEP_ALIVE__ && isSpecialElement(newChild)) return headAppendChild.call(rawHead, newChild);
2654
+ }
2655
+ function handleKeepAliveElement(newChild) {
2656
+ if (newChild.__KEEP_ALIVE__ && isSpecialElement(newChild)) {
2657
+ return headAppendChild.call(rawHead, newChild);
2658
+ }
2659
+ return null;
2660
+ }
2661
+ function createOverriddenAppendChild() {
2662
+ return function(newChild) {
2663
+ const keepAliveResult = handleKeepAliveElement(newChild);
2664
+ if (keepAliveResult) {
2665
+ return keepAliveResult;
2666
+ }
2534
2667
  return elementAppendHandler(this, newChild, bodyAppendChild2);
2535
2668
  };
2536
- HTMLBodyElement.prototype.append = function(...nodes) {
2669
+ }
2670
+ function createOverriddenAppend() {
2671
+ return function(...nodes) {
2537
2672
  nodes.forEach((node) => {
2538
- if (node.__KEEP_ALIVE__ && isSpecialElement(node)) {
2539
- return headAppendChild.call(rawHead, node);
2673
+ const keepAliveResult = handleKeepAliveElement(node);
2674
+ if (keepAliveResult) {
2675
+ return;
2540
2676
  }
2541
2677
  elementAppendHandler(this, node, bodyAppendChild2);
2542
2678
  });
2543
2679
  };
2544
- HTMLHeadElement.prototype.appendChild = HTMLBodyElement.prototype.appendChild;
2545
- HTMLHeadElement.prototype.insertBefore = function(newChild, refChild) {
2546
- return elementInsertHandler(this, newChild, refChild, headInsertBefore);
2547
- };
2548
- HTMLBodyElement.prototype.insertBefore = function(newChild, refChild) {
2680
+ }
2681
+ function createOverriddenInsertBefore() {
2682
+ return function(newChild, refChild) {
2549
2683
  return elementInsertHandler(this, newChild, refChild, headInsertBefore);
2550
2684
  };
2551
- HTMLBodyElement.prototype.removeChild = function removeChildNew(oldChild) {
2552
- const app = appCache.getApp(oldChild.__BK_WEWEB_APP_KEY__);
2685
+ }
2686
+ function createOverriddenRemoveChild() {
2687
+ return function(oldChild) {
2688
+ const app = oldChild.__BK_WEWEB_APP_KEY__ ? appCache.getApp(oldChild.__BK_WEWEB_APP_KEY__) : null;
2553
2689
  if (app?.container?.contains(oldChild)) {
2554
- const node = bodyRemoveChild.call(app.container, oldChild);
2555
- return node;
2690
+ return bodyRemoveChild.call(app.container, oldChild);
2556
2691
  }
2557
2692
  if (this.contains(oldChild)) {
2558
2693
  return bodyRemoveChild.call(this, oldChild);
2559
2694
  }
2560
2695
  return oldChild;
2561
2696
  };
2697
+ }
2698
+ function rewriteBodyAndHeaderMethods() {
2699
+ if (hasRewrite) {
2700
+ return;
2701
+ }
2702
+ hasRewrite = true;
2703
+ Element.prototype.setAttribute = createOverriddenSetAttribute();
2704
+ HTMLBodyElement.prototype.appendChild = createOverriddenAppendChild();
2705
+ HTMLBodyElement.prototype.append = createOverriddenAppend();
2706
+ HTMLBodyElement.prototype.insertBefore = createOverriddenInsertBefore();
2707
+ HTMLBodyElement.prototype.removeChild = createOverriddenRemoveChild();
2708
+ HTMLHeadElement.prototype.appendChild = HTMLBodyElement.prototype.appendChild;
2709
+ HTMLHeadElement.prototype.insertBefore = createOverriddenInsertBefore();
2562
2710
  HTMLHeadElement.prototype.removeChild = HTMLBodyElement.prototype.removeChild;
2563
2711
  }
2564
2712
  function resetBodyAndHeaderMethods() {
@@ -2587,8 +2735,8 @@ function activated(appKey, container, callback) {
2587
2735
  beforeLoad();
2588
2736
  app.activated(container, callback);
2589
2737
  });
2590
- } else {
2591
- app && nextTask(() => {
2738
+ } else if (app) {
2739
+ nextTask(() => {
2592
2740
  beforeLoad();
2593
2741
  app.mount(container, callback);
2594
2742
  });
@@ -2607,9 +2755,12 @@ function deactivated(appKey) {
2607
2755
  }
2608
2756
 
2609
2757
  // src/lifecycle/load.ts
2758
+ var STATUS_CHECK_INTERVAL = 300;
2610
2759
  async function load(props) {
2611
2760
  beforeLoad();
2612
- if (props.mode === "js" /* INSTANCE */) return await loadInstance(props);
2761
+ if (props.mode === "js" /* INSTANCE */) {
2762
+ return await loadInstance(props);
2763
+ }
2613
2764
  return await loadApp(props);
2614
2765
  }
2615
2766
  async function loadApp(props) {
@@ -2638,7 +2789,7 @@ function loadInstance(props) {
2638
2789
  resolve(instance);
2639
2790
  clearInterval(timer);
2640
2791
  }
2641
- }, 300);
2792
+ }, STATUS_CHECK_INTERVAL);
2642
2793
  return;
2643
2794
  }
2644
2795
  resolve(instance);
@@ -2658,14 +2809,35 @@ function unmount(appKey) {
2658
2809
 
2659
2810
  // src/component/web-component.ts
2660
2811
  var BkWewebElement = class extends HTMLElement {
2812
+ /** 应用 URL 缓存 */
2661
2813
  appUrl = "";
2814
+ /** 组件连接状态标识 */
2662
2815
  connected = false;
2816
+ /**
2817
+ * 观察的属性列表
2818
+ * @description 定义需要监听变化的属性名称列表
2819
+ * @returns string[] - 属性名称数组
2820
+ */
2663
2821
  static get observedAttributes() {
2664
2822
  return ["url" /* url */];
2665
2823
  }
2824
+ /**
2825
+ * 获取布尔类型属性值
2826
+ * @description 解析布尔类型的自定义属性,支持驼峰和短横线命名
2827
+ * @param name - 属性名称
2828
+ * @returns boolean | undefined - 属性值或 undefined
2829
+ * @private
2830
+ */
2666
2831
  getBooleanAttr(name) {
2667
- return this.hasAttribute(name) || this.hasAttribute(name.replace(/([A-Z])/g, "-$1").toLocaleLowerCase()) ? this.getAttribute(name) !== "false" : void 0;
2832
+ const hasAttr = this.hasAttribute(name) || this.hasAttribute(name.replace(/([A-Z])/g, "-$1").toLocaleLowerCase());
2833
+ return hasAttr ? this.getAttribute(name) !== "false" : void 0;
2668
2834
  }
2835
+ /**
2836
+ * 处理属性变化的内部逻辑
2837
+ * @description 当属性发生变化时执行的处理逻辑
2838
+ * @returns Promise<void>
2839
+ * @private
2840
+ */
2669
2841
  async handleAttributeChanged() {
2670
2842
  if (!this.appKey) return;
2671
2843
  if (this.getBooleanAttr("setShodowDom" /* setShodowDom */)) {
@@ -2678,12 +2850,26 @@ var BkWewebElement = class extends HTMLElement {
2678
2850
  }
2679
2851
  await load(this.appProps);
2680
2852
  }
2853
+ /**
2854
+ * 属性变化回调
2855
+ * @description 当观察的属性发生变化时触发
2856
+ * @param attr - 变化的属性名
2857
+ * @param _oldVal - 旧值(未使用)
2858
+ * @param newVal - 新值
2859
+ */
2681
2860
  attributeChangedCallback(attr, _oldVal, newVal) {
2682
2861
  if (attr !== "url" /* url */ || this[attr] === newVal || !this.connected) return;
2683
2862
  this.appUrl = newVal;
2684
2863
  const cacheApp = appCache.getApp(this.appKey);
2685
- (this.connected || cacheApp) && this.handleAttributeChanged();
2864
+ if (this.connected || cacheApp) {
2865
+ this.handleAttributeChanged();
2866
+ }
2686
2867
  }
2868
+ /**
2869
+ * 组件连接到 DOM 时的回调
2870
+ * @description 当自定义元素被插入到 DOM 时触发
2871
+ * @returns Promise<void>
2872
+ */
2687
2873
  async connectedCallback() {
2688
2874
  if (this.getBooleanAttr("setShodowDom" /* setShodowDom */) && !this.shadowRoot) {
2689
2875
  this.attachShadow({ delegatesFocus: false, mode: "open" });
@@ -2692,12 +2878,23 @@ var BkWewebElement = class extends HTMLElement {
2692
2878
  activated(this.appKey, this.shadowRoot ?? this);
2693
2879
  this.connected = true;
2694
2880
  }
2881
+ /**
2882
+ * 组件从 DOM 断开时的回调
2883
+ * @description 当自定义元素从 DOM 中移除时触发
2884
+ */
2695
2885
  disconnectedCallback() {
2696
2886
  this.connected = false;
2697
2887
  if (this.appProps.keepAlive) {
2698
2888
  deactivated(this.appKey);
2699
- } else unmount(this.appKey);
2889
+ } else {
2890
+ unmount(this.appKey);
2891
+ }
2700
2892
  }
2893
+ /**
2894
+ * 获取应用数据
2895
+ * @description 解析 data 属性中的 JSON 数据
2896
+ * @returns Record<string, unknown> - 应用数据对象
2897
+ */
2701
2898
  get appData() {
2702
2899
  if (this.hasAttribute("data" /* data */)) {
2703
2900
  try {
@@ -2707,35 +2904,44 @@ var BkWewebElement = class extends HTMLElement {
2707
2904
  }
2708
2905
  return {};
2709
2906
  }
2710
- // 考虑到js模式下 需要js bundle的复用性 需用户设置id属性 如果单实例下则可以不用配置
2907
+ /**
2908
+ * 获取应用标识符
2909
+ * @description 优先使用 id 属性,其次使用 url 属性作为应用标识
2910
+ * 考虑到 JS 模式下需要 JS bundle 的复用性,需用户设置 id 属性
2911
+ * 如果是单实例应用则可以不用配置 id
2912
+ * @returns string | null - 应用标识符或 null
2913
+ */
2711
2914
  get appKey() {
2712
2915
  return this.getAttribute("id" /* id */) || this.getAttribute("url" /* url */);
2713
2916
  }
2917
+ /**
2918
+ * 获取应用配置属性
2919
+ * @description 根据模式返回相应的应用配置对象
2920
+ * @returns IAppModelProps | IJsModelProps - 应用配置对象
2921
+ */
2714
2922
  get appProps() {
2923
+ const commonProps = {
2924
+ container: this.shadowRoot ?? this,
2925
+ data: this.appData,
2926
+ id: this.appKey,
2927
+ keepAlive: this.getBooleanAttr("keepAlive" /* keepAlive */),
2928
+ showSourceCode: this.getBooleanAttr("showSourceCode" /* showSourceCode */),
2929
+ url: this.getAttribute("url" /* url */)
2930
+ };
2715
2931
  if (this.getAttribute("mode") === "js" /* INSTANCE */) {
2716
2932
  return {
2717
- container: this.shadowRoot ?? this,
2718
- data: this.appData,
2719
- id: this.appKey,
2720
- keepAlive: this.getBooleanAttr("keepAlive" /* keepAlive */),
2933
+ ...commonProps,
2721
2934
  mode: "js" /* INSTANCE */,
2722
2935
  scopeCss: this.getBooleanAttr("scopeCss" /* scopeCss */) && !this.getBooleanAttr("setShodowDom" /* setShodowDom */),
2723
- scopeJs: this.getBooleanAttr("scopeJs" /* scopeJs */),
2724
- showSourceCode: this.getBooleanAttr("showSourceCode" /* showSourceCode */),
2725
- url: this.getAttribute("url" /* url */)
2936
+ scopeJs: this.getBooleanAttr("scopeJs" /* scopeJs */)
2726
2937
  };
2727
2938
  }
2728
2939
  return {
2729
- container: this.shadowRoot ?? this,
2730
- data: this.appData,
2731
- id: this.appKey,
2732
- keepAlive: this.getBooleanAttr("keepAlive" /* keepAlive */),
2940
+ ...commonProps,
2733
2941
  mode: "app" /* APP */,
2734
2942
  scopeCss: !this.getBooleanAttr("setShodowDom" /* setShodowDom */),
2735
2943
  scopeJs: !this.getBooleanAttr("scopeJs" /* scopeJs */),
2736
- scopeLocation: this.getBooleanAttr("scopeLocation" /* scopeLocation */),
2737
- showSourceCode: this.getBooleanAttr("showSourceCode" /* showSourceCode */),
2738
- url: this.getAttribute("url" /* url */)
2944
+ scopeLocation: this.getBooleanAttr("scopeLocation" /* scopeLocation */)
2739
2945
  };
2740
2946
  }
2741
2947
  };
@@ -2743,10 +2949,12 @@ var BkWewebElement = class extends HTMLElement {
2743
2949
  // src/lifecycle/mount.ts
2744
2950
  function mount(appKey, container, callback) {
2745
2951
  const app = appCache.getApp(appKey);
2746
- app && nextTask(() => {
2747
- beforeLoad();
2748
- app.mount(container, callback);
2749
- });
2952
+ if (app) {
2953
+ nextTask(() => {
2954
+ beforeLoad();
2955
+ app.mount(container, callback);
2956
+ });
2957
+ }
2750
2958
  }
2751
2959
 
2752
2960
  // src/lifecycle/unload.ts
@@ -2787,13 +2995,13 @@ var WeWeb = class {
2787
2995
  window.customElements.define(CUSTOM_ELEMENT_TAG, BkWewebElement);
2788
2996
  }
2789
2997
  }
2790
- // 设置自定义dom标签名
2998
+ /** 设置自定义DOM标签名 */
2791
2999
  setWebComponentTag() {
2792
3000
  if (!window.customElements.get(this.webComponentTag)) {
2793
3001
  window.customElements.define(this.webComponentTag, BkWewebElement);
2794
3002
  }
2795
3003
  }
2796
- // todo set some global start props
3004
+ /** 启动WeWeb */
2797
3005
  start(option) {
2798
3006
  if (option?.collectBaseSource) {
2799
3007
  collectBaseSource();