@lwrjs/loader 0.17.2-alpha.3 → 0.17.2-alpha.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/README.md +1 -0
  2. package/build/assets/prod/lwr-error-shim.js +1 -1
  3. package/build/assets/prod/lwr-loader-shim-legacy.bundle.js +168 -46
  4. package/build/assets/prod/lwr-loader-shim-legacy.bundle.min.js +4 -3
  5. package/build/assets/prod/lwr-loader-shim-legacy.js +58 -16
  6. package/build/assets/prod/lwr-loader-shim.bundle.js +180 -54
  7. package/build/assets/prod/lwr-loader-shim.bundle.min.js +4 -3
  8. package/build/assets/prod/lwr-loader-shim.js +58 -16
  9. package/build/cjs/modules/lwr/loader/constants/constants.cjs +8 -1
  10. package/build/cjs/modules/lwr/loader/moduleRegistry/importMetadataResolver.cjs +2 -2
  11. package/build/cjs/modules/lwr/loader/moduleRegistry/moduleRegistry.cjs +49 -7
  12. package/build/cjs/modules/lwr/loaderLegacy/constants/constants.cjs +8 -1
  13. package/build/cjs/modules/lwr/loaderLegacy/moduleRegistry/moduleRegistry.cjs +50 -8
  14. package/build/modules/lwr/esmLoader/esmLoader.js +1 -1
  15. package/build/modules/lwr/loader/constants/constants.d.ts +5 -0
  16. package/build/modules/lwr/loader/constants/constants.js +6 -0
  17. package/build/modules/lwr/loader/loader.d.ts +1 -0
  18. package/build/modules/lwr/loader/loader.js +122 -38
  19. package/build/modules/lwr/loader/moduleRegistry/importMetadataResolver.js +7 -7
  20. package/build/modules/lwr/loader/moduleRegistry/moduleRegistry.d.ts +4 -0
  21. package/build/modules/lwr/loader/moduleRegistry/moduleRegistry.js +66 -15
  22. package/build/modules/lwr/loaderLegacy/constants/constants.d.ts +5 -0
  23. package/build/modules/lwr/loaderLegacy/constants/constants.js +6 -0
  24. package/build/modules/lwr/loaderLegacy/loaderLegacy.d.ts +1 -0
  25. package/build/modules/lwr/loaderLegacy/loaderLegacy.js +110 -30
  26. package/build/modules/lwr/loaderLegacy/moduleRegistry/moduleRegistry.d.ts +4 -0
  27. package/build/modules/lwr/loaderLegacy/moduleRegistry/moduleRegistry.js +67 -16
  28. package/build/shim/shim.d.ts +2 -0
  29. package/build/shim/shim.js +45 -8
  30. package/build/shim-legacy/shimLegacy.d.ts +2 -0
  31. package/build/shim-legacy/shimLegacy.js +45 -8
  32. package/build/types.d.ts +1 -0
  33. package/package.json +8 -8
@@ -4,7 +4,7 @@
4
4
  * SPDX-License-Identifier: MIT
5
5
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
6
6
  */
7
- /* LWR Legacy Module Loader v0.17.2-alpha.3 */
7
+ /* LWR Legacy Module Loader v0.17.2-alpha.31 */
8
8
  const templateRegex = /\{([0-9]+)\}/g;
9
9
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
10
10
  function templateString(template, args) {
@@ -108,7 +108,7 @@ const STALE_HOOK_ERROR = Object.freeze({
108
108
  level: 0,
109
109
  message: 'An error occurred handling module conflict',
110
110
  });
111
- const MODULE_ALREADY_LOADED = Object.freeze({
111
+ Object.freeze({
112
112
  code: 3017,
113
113
  level: 0,
114
114
  message: 'Marking module(s) as externally loaded, but they are already loaded: {0}',
@@ -320,20 +320,39 @@ if (hasDocument) {
320
320
 
321
321
  const MODULE_LOAD_TIMEOUT_TIMER = 60 * 1000; // 1m
322
322
 
323
+ var MODULE_WARNING; (function (MODULE_WARNING) {
324
+ const MODULE_REDEFINE = 'Module redefine attempted'; MODULE_WARNING["MODULE_REDEFINE"] = MODULE_REDEFINE;
325
+ const MODULE_ALREADY_LOADED = 'Marking module(s) as externally loaded, but they are already loaded'; MODULE_WARNING["MODULE_ALREADY_LOADED"] = MODULE_ALREADY_LOADED;
326
+ const ALIAS_UPDATE = 'Alias update attempt'; MODULE_WARNING["ALIAS_UPDATE"] = ALIAS_UPDATE;
327
+ })(MODULE_WARNING || (MODULE_WARNING = {}));
328
+
323
329
  /*!
324
330
  * Copyright (C) 2023 salesforce.com, inc.
325
331
  */
326
332
  // @ts-ignore: Prevent cannot find name 'trustedTypes' error.
327
333
  const SUPPORTS_TRUSTED_TYPES = typeof trustedTypes !== 'undefined';
328
- function createTrustedTypesPolicy(name, options) {
334
+ const trustedTypePolicyRegistry = {
335
+ __proto__: null
336
+ };
337
+ function createDuplicateSafeTrustedTypesPolicy(name, options) {
338
+ // istanbul ignore next: not testable in coverage collection
339
+ if (trustedTypePolicyRegistry[name]) {
340
+ return trustedTypePolicyRegistry[name];
341
+ }
329
342
  // @ts-ignore: Prevent cannot find name 'trustedTypes' error.
330
- return trustedTypes.createPolicy(name, options);
343
+ // eslint-disable-next-line no-return-assign
344
+ return trustedTypePolicyRegistry[name] = trustedTypes.createPolicy(name, options);
331
345
  }
332
- function createFallbackPolicy(_name, options) {
333
- return options;
346
+ function createDuplicateSafeFallbackPolicy(name, options) {
347
+ if (trustedTypePolicyRegistry[name]) {
348
+ return trustedTypePolicyRegistry[name];
349
+ }
350
+ // @ts-ignore: Prevent cannot find name 'trustedTypes' error.
351
+ // eslint-disable-next-line no-return-assign
352
+ return trustedTypePolicyRegistry[name] = options;
334
353
  }
335
354
  // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/trusted-types
336
- const createPolicy = SUPPORTS_TRUSTED_TYPES ? createTrustedTypesPolicy : createFallbackPolicy;
355
+ const createPolicy = SUPPORTS_TRUSTED_TYPES ? createDuplicateSafeTrustedTypesPolicy : createDuplicateSafeFallbackPolicy;
337
356
  const policyOptions = {
338
357
  createHTML(value) {
339
358
  return value;
@@ -381,7 +400,7 @@ try {
381
400
  // swallow
382
401
  }
383
402
  const trusted = createPolicy('trusted', policyOptions);
384
- /*! version: 0.23.6 */
403
+ /*! version: 0.24.6 */
385
404
 
386
405
  /* global console,process */
387
406
 
@@ -451,7 +470,7 @@ async function evaluateLoadHookResponse(response, id) {
451
470
  code = `${code}\n//# sourceURL=${id}`; // append sourceURL for debugging
452
471
  try {
453
472
  // TODO eval source maps for debugging
454
- eval(trusted.createScript(code));
473
+ eval(trusted.createScript(code) );
455
474
  } catch (e) {
456
475
  // eslint-disable-next-line lwr/no-unguarded-apis
457
476
  if (process.env.NODE_ENV !== 'production' && hasConsole) {
@@ -529,7 +548,7 @@ const MODULE_DYNAMIC_LOAD = `${LOADER_PREFIX}module.dynamicLoad`;
529
548
  const MODULE_FETCH = `${LOADER_PREFIX}module.fetch`;
530
549
  const MODULE_ERROR = `${LOADER_PREFIX}module.error`;
531
550
 
532
- /* global console,process */
551
+ /* global process console */
533
552
 
534
553
 
535
554
 
@@ -583,10 +602,17 @@ const MODULE_ERROR = `${LOADER_PREFIX}module.error`;
583
602
 
584
603
  class ModuleRegistry {
585
604
 
605
+
606
+ __init() {this.isAppMounted = false;}
586
607
 
587
- constructor(config) {ModuleRegistry.prototype.__init.call(this);ModuleRegistry.prototype.__init2.call(this);ModuleRegistry.prototype.__init3.call(this);
608
+ constructor(config) {ModuleRegistry.prototype.__init.call(this);ModuleRegistry.prototype.__init2.call(this);ModuleRegistry.prototype.__init3.call(this);ModuleRegistry.prototype.__init4.call(this);
588
609
  this.baseUrl = config.baseUrl || '';
589
610
  this.profiler = config.profiler;
611
+ this.warnings = {
612
+ [MODULE_WARNING.MODULE_REDEFINE]: [],
613
+ [MODULE_WARNING.MODULE_ALREADY_LOADED]: [],
614
+ [MODULE_WARNING.ALIAS_UPDATE]: [],
615
+ };
590
616
  }
591
617
 
592
618
  clearRegistry() {
@@ -723,11 +749,14 @@ class ModuleRegistry {
723
749
  // eslint-disable-next-line lwr/no-unguarded-apis
724
750
  process.env.NODE_ENV !== 'production' &&
725
751
  // eslint-disable-next-line lwr/no-unguarded-apis
726
- process.env.MRT_HMR !== 'true' &&
727
- hasConsole
752
+ process.env.MRT_HMR !== 'true'
728
753
  ) {
729
- // eslint-disable-next-line lwr/no-unguarded-apis
730
- console.warn(`Module redefine attempted: ${name}`);
754
+ if (!this.warnings[MODULE_WARNING.MODULE_REDEFINE].includes(name)) {
755
+ this.warnings[MODULE_WARNING.MODULE_REDEFINE].push(name);
756
+ }
757
+ if (this.isAppMounted) {
758
+ this.logMessage('warning', `${MODULE_WARNING.MODULE_REDEFINE}: ${name}`);
759
+ }
731
760
  }
732
761
  this.lastDefine = mod;
733
762
  return;
@@ -789,9 +818,13 @@ class ModuleRegistry {
789
818
  };
790
819
  this.namedDefineRegistry.set(id, moduleDef );
791
820
  // eslint-disable-next-line lwr/no-unguarded-apis
792
- } else if (process.env.NODE_ENV !== 'production' && hasConsole) {
793
- // eslint-disable-next-line lwr/no-unguarded-apis
794
- console.warn(MODULE_ALREADY_LOADED.message, id);
821
+ } else if (process.env.NODE_ENV !== 'production') {
822
+ if (!this.warnings[MODULE_WARNING.MODULE_ALREADY_LOADED].includes(id)) {
823
+ this.warnings[MODULE_WARNING.MODULE_ALREADY_LOADED].push(id);
824
+ }
825
+ if (this.isAppMounted) {
826
+ this.logMessage('warning', `${MODULE_WARNING.MODULE_ALREADY_LOADED}: ${id}`);
827
+ }
795
828
  }
796
829
  });
797
830
  }
@@ -840,13 +873,13 @@ class ModuleRegistry {
840
873
 
841
874
 
842
875
  // A registry for named AMD defines containing the *metadata* of AMD module
843
- __init() {this.namedDefineRegistry = new Map();}
876
+ __init2() {this.namedDefineRegistry = new Map();}
844
877
 
845
878
  // The evaluated module registry where the module identifier (name or URL?) is the key
846
- __init2() {this.moduleRegistry = new Map();}
879
+ __init3() {this.moduleRegistry = new Map();}
847
880
 
848
881
  // Aliases of modules in the registry
849
- __init3() {this.aliases = new Map();}
882
+ __init4() {this.aliases = new Map();}
850
883
 
851
884
 
852
885
 
@@ -916,14 +949,17 @@ class ModuleRegistry {
916
949
  if (aliasId !== resolvedId) {
917
950
  if (!this.aliases.has(aliasId)) {
918
951
  this.aliases.set(aliasId, resolvedId);
919
- } else if (hasConsole) {
952
+ // eslint-disable-next-line lwr/no-unguarded-apis
953
+ } else if (hasConsole && process.env.NODE_ENV !== 'production') {
920
954
  // Warn the user if they were not aliasing to the resolvedId
921
955
  const currentResolvedId = this.aliases.get(aliasId);
922
956
  if (currentResolvedId !== resolvedId) {
923
- // eslint-disable-next-line lwr/no-unguarded-apis
924
- if (process.env.NODE_ENV !== 'production' && hasConsole) {
925
- // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
926
- console.warn(`Alias update attempt: ${aliasId}=>${currentResolvedId}, ${resolvedId}`);
957
+ const warningMsg = `${aliasId}=>${currentResolvedId}, ${resolvedId}`;
958
+ if (!this.warnings[MODULE_WARNING.ALIAS_UPDATE].includes(warningMsg)) {
959
+ this.warnings[MODULE_WARNING.ALIAS_UPDATE].push(warningMsg);
960
+ }
961
+ if (this.isAppMounted) {
962
+ this.logMessage('warning', `${MODULE_WARNING.ALIAS_UPDATE}: ${warningMsg}`);
927
963
  }
928
964
  }
929
965
  }
@@ -931,7 +967,23 @@ class ModuleRegistry {
931
967
  }
932
968
 
933
969
  async getModuleDependencyRecord(dependency) {
934
- const resolvedDepId = await this.resolve(dependency);
970
+ let resolvedDepId = await this.resolve(dependency);
971
+ // If the resolved dependency ID is a URL, it indicates that the dependency
972
+ // is provided by a bundle that hasn't been fully instantiated yet.
973
+ if (isUrl(resolvedDepId)) {
974
+ // Retrieve the module record corresponding to the bundle URL.
975
+ const existingRecord = this.moduleRegistry.get(resolvedDepId);
976
+
977
+ // If a module record for the bundle exists and we haven't already created an alias for this dependency,
978
+ // then the bundle is still pending instantiation.
979
+ if (existingRecord && !this.aliases.has(dependency)) {
980
+ // Wait for the bundle's instantiation promise to resolve.
981
+ await existingRecord.instantiation;
982
+ // After instantiation, re-resolve the dependency.
983
+ // This should now return the final alias (the logical module ID) instead of the raw bundle URL.
984
+ resolvedDepId = await this.resolve(dependency);
985
+ }
986
+ }
935
987
  return this.getModuleRecord(resolvedDepId, dependency);
936
988
  }
937
989
 
@@ -1156,6 +1208,10 @@ class ModuleRegistry {
1156
1208
 
1157
1209
  // Fallback to the last loader.define call
1158
1210
  if (!moduleDef) {
1211
+ this.logMessage(
1212
+ 'warning',
1213
+ `${moduleName} not found, falling back to the last loader.define call`,
1214
+ );
1159
1215
  moduleDef = this.lastDefine;
1160
1216
  }
1161
1217
 
@@ -1216,6 +1272,28 @@ class ModuleRegistry {
1216
1272
  res === null || typeof res === 'string' || (res && typeof (res ).url === 'string')
1217
1273
  );
1218
1274
  }
1275
+
1276
+ getModuleWarnings(isAppMounted = false) {
1277
+ this.isAppMounted = isAppMounted;
1278
+ return this.warnings;
1279
+ }
1280
+
1281
+ logMessage(logType, message) {
1282
+ if (
1283
+ !hasProcessEnv ||
1284
+ !hasConsole || // eslint-disable-next-line lwr/no-unguarded-apis
1285
+ process.env.NODE_ENV === 'production'
1286
+ ) {
1287
+ return;
1288
+ }
1289
+ if (logType == 'warning') {
1290
+ // eslint-disable-next-line lwr/no-unguarded-apis
1291
+ console.warn(message);
1292
+ } else {
1293
+ // eslint-disable-next-line lwr/no-unguarded-apis
1294
+ console.log(message);
1295
+ }
1296
+ }
1219
1297
  }
1220
1298
 
1221
1299
  // find the longest set of segments from path which are a key in matchObj
@@ -1558,11 +1636,9 @@ class Loader {
1558
1636
  sigs = execute;
1559
1637
  }
1560
1638
 
1561
- sigs = sigs || {};
1562
-
1563
1639
  invariant(Array.isArray(deps), INVALID_DEPS);
1564
1640
 
1565
- this.registry.define(name, deps, ctor , sigs );
1641
+ this.registry.define(name, deps, ctor , (sigs || {}) );
1566
1642
  }
1567
1643
 
1568
1644
  /**
@@ -1629,6 +1705,10 @@ class Loader {
1629
1705
  registerExternalModules(modules) {
1630
1706
  this.registry.registerExternalModules(modules);
1631
1707
  }
1708
+
1709
+ getModuleWarnings(isAppMounted = false) {
1710
+ return this.registry.getModuleWarnings(isAppMounted);
1711
+ }
1632
1712
  }
1633
1713
 
1634
1714
  export { Loader };
@@ -13,6 +13,8 @@ export type Module = {
13
13
  };
14
14
  export declare class ModuleRegistry {
15
15
  private profiler;
16
+ private warnings;
17
+ private isAppMounted;
16
18
  constructor(config: LoaderConfig);
17
19
  clearRegistry(): void;
18
20
  load(id: string, importer?: string): Promise<Module>;
@@ -50,5 +52,7 @@ export declare class ModuleRegistry {
50
52
  private handleStaleModuleHook?;
51
53
  registerHandleStaleModuleHook(handleStaleModule: HandleStaleModuleHook): void;
52
54
  isValidResolveResponse(res: ResolveHookResponse): boolean;
55
+ getModuleWarnings(isAppMounted?: boolean): Record<string, string[]>;
56
+ logMessage(logType: string, message: string): void;
53
57
  }
54
58
  //# sourceMappingURL=moduleRegistry.d.ts.map
@@ -1,14 +1,15 @@
1
- /* global console,process */
2
- import { invariant, NO_AMD_REQUIRE, LoaderError, FAIL_INSTANTIATE, FAILED_DEP, UNRESOLVED, INVALID_HOOK, INVALID_LOADER_SERVICE_RESPONSE, MODULE_ALREADY_LOADED, MODULE_LOAD_TIMEOUT, EXPORTER_ERROR, } from '../errors/messages.js';
1
+ /* global process console */
2
+ import { invariant, NO_AMD_REQUIRE, LoaderError, FAIL_INSTANTIATE, FAILED_DEP, UNRESOLVED, INVALID_HOOK, INVALID_LOADER_SERVICE_RESPONSE, MODULE_LOAD_TIMEOUT, EXPORTER_ERROR, } from '../errors/messages.js';
3
3
  import { resolveIfNotPlainOrUrl, isUrl } from '../utils/url.js';
4
4
  import { hasDocument, hasConsole, hasProcessEnv } from '../utils/dom.js';
5
5
  import { loadModuleDef } from './scriptLoad.js';
6
6
  import { evaluateLoadHookResponse, evaluateLoadHook, isResponseAPromise, } from '../hooks/resolveAndLoadHook.js';
7
7
  import { evaluateHandleStaleModuleHooks } from '../hooks/moduleInvalidation.js';
8
- import { MODULE_LOAD_TIMEOUT_TIMER } from '../constants/constants.js';
8
+ import { MODULE_LOAD_TIMEOUT_TIMER, MODULE_WARNING } from '../constants/constants.js';
9
9
  import { MODULE_DEFINE, MODULE_ERROR, MODULE_FETCH, MODULE_DYNAMIC_LOAD } from 'lwr/metrics';
10
10
  export class ModuleRegistry {
11
11
  constructor(config) {
12
+ this.isAppMounted = false;
12
13
  // A registry for named AMD defines containing the *metadata* of AMD module
13
14
  this.namedDefineRegistry = new Map();
14
15
  // The evaluated module registry where the module identifier (name or URL?) is the key
@@ -17,6 +18,11 @@ export class ModuleRegistry {
17
18
  this.aliases = new Map();
18
19
  this.baseUrl = config.baseUrl || '';
19
20
  this.profiler = config.profiler;
21
+ this.warnings = {
22
+ [MODULE_WARNING.MODULE_REDEFINE]: [],
23
+ [MODULE_WARNING.MODULE_ALREADY_LOADED]: [],
24
+ [MODULE_WARNING.ALIAS_UPDATE]: [],
25
+ };
20
26
  }
21
27
  clearRegistry() {
22
28
  this.moduleRegistry = new Map();
@@ -134,10 +140,13 @@ export class ModuleRegistry {
134
140
  // eslint-disable-next-line lwr/no-unguarded-apis
135
141
  process.env.NODE_ENV !== 'production' &&
136
142
  // eslint-disable-next-line lwr/no-unguarded-apis
137
- process.env.MRT_HMR !== 'true' &&
138
- hasConsole) {
139
- // eslint-disable-next-line lwr/no-unguarded-apis
140
- console.warn(`Module redefine attempted: ${name}`);
143
+ process.env.MRT_HMR !== 'true') {
144
+ if (!this.warnings[MODULE_WARNING.MODULE_REDEFINE].includes(name)) {
145
+ this.warnings[MODULE_WARNING.MODULE_REDEFINE].push(name);
146
+ }
147
+ if (this.isAppMounted) {
148
+ this.logMessage('warning', `${MODULE_WARNING.MODULE_REDEFINE}: ${name}`);
149
+ }
141
150
  }
142
151
  this.lastDefine = mod;
143
152
  return;
@@ -195,9 +204,13 @@ export class ModuleRegistry {
195
204
  this.namedDefineRegistry.set(id, moduleDef);
196
205
  // eslint-disable-next-line lwr/no-unguarded-apis
197
206
  }
198
- else if (process.env.NODE_ENV !== 'production' && hasConsole) {
199
- // eslint-disable-next-line lwr/no-unguarded-apis
200
- console.warn(MODULE_ALREADY_LOADED.message, id);
207
+ else if (process.env.NODE_ENV !== 'production') {
208
+ if (!this.warnings[MODULE_WARNING.MODULE_ALREADY_LOADED].includes(id)) {
209
+ this.warnings[MODULE_WARNING.MODULE_ALREADY_LOADED].push(id);
210
+ }
211
+ if (this.isAppMounted) {
212
+ this.logMessage('warning', `${MODULE_WARNING.MODULE_ALREADY_LOADED}: ${id}`);
213
+ }
201
214
  }
202
215
  });
203
216
  }
@@ -296,22 +309,40 @@ export class ModuleRegistry {
296
309
  if (aliasId !== resolvedId) {
297
310
  if (!this.aliases.has(aliasId)) {
298
311
  this.aliases.set(aliasId, resolvedId);
312
+ // eslint-disable-next-line lwr/no-unguarded-apis
299
313
  }
300
- else if (hasConsole) {
314
+ else if (hasConsole && process.env.NODE_ENV !== 'production') {
301
315
  // Warn the user if they were not aliasing to the resolvedId
302
316
  const currentResolvedId = this.aliases.get(aliasId);
303
317
  if (currentResolvedId !== resolvedId) {
304
- // eslint-disable-next-line lwr/no-unguarded-apis
305
- if (process.env.NODE_ENV !== 'production' && hasConsole) {
306
- // eslint-disable-next-line lwr/no-unguarded-apis, no-undef
307
- console.warn(`Alias update attempt: ${aliasId}=>${currentResolvedId}, ${resolvedId}`);
318
+ const warningMsg = `${aliasId}=>${currentResolvedId}, ${resolvedId}`;
319
+ if (!this.warnings[MODULE_WARNING.ALIAS_UPDATE].includes(warningMsg)) {
320
+ this.warnings[MODULE_WARNING.ALIAS_UPDATE].push(warningMsg);
321
+ }
322
+ if (this.isAppMounted) {
323
+ this.logMessage('warning', `${MODULE_WARNING.ALIAS_UPDATE}: ${warningMsg}`);
308
324
  }
309
325
  }
310
326
  }
311
327
  }
312
328
  }
313
329
  async getModuleDependencyRecord(dependency) {
314
- const resolvedDepId = await this.resolve(dependency);
330
+ let resolvedDepId = await this.resolve(dependency);
331
+ // If the resolved dependency ID is a URL, it indicates that the dependency
332
+ // is provided by a bundle that hasn't been fully instantiated yet.
333
+ if (isUrl(resolvedDepId)) {
334
+ // Retrieve the module record corresponding to the bundle URL.
335
+ const existingRecord = this.moduleRegistry.get(resolvedDepId);
336
+ // If a module record for the bundle exists and we haven't already created an alias for this dependency,
337
+ // then the bundle is still pending instantiation.
338
+ if (existingRecord && !this.aliases.has(dependency)) {
339
+ // Wait for the bundle's instantiation promise to resolve.
340
+ await existingRecord.instantiation;
341
+ // After instantiation, re-resolve the dependency.
342
+ // This should now return the final alias (the logical module ID) instead of the raw bundle URL.
343
+ resolvedDepId = await this.resolve(dependency);
344
+ }
345
+ }
315
346
  return this.getModuleRecord(resolvedDepId, dependency);
316
347
  }
317
348
  // execute the "top-level code" (the code outside of functions) of a module
@@ -500,6 +531,7 @@ export class ModuleRegistry {
500
531
  moduleDef = moduleName && this.namedDefineRegistry.get(moduleName);
501
532
  // Fallback to the last loader.define call
502
533
  if (!moduleDef) {
534
+ this.logMessage('warning', `${moduleName} not found, falling back to the last loader.define call`);
503
535
  moduleDef = this.lastDefine;
504
536
  }
505
537
  // This should not happen
@@ -551,5 +583,24 @@ export class ModuleRegistry {
551
583
  isValidResolveResponse(res) {
552
584
  return (res === null || typeof res === 'string' || (res && typeof res.url === 'string'));
553
585
  }
586
+ getModuleWarnings(isAppMounted = false) {
587
+ this.isAppMounted = isAppMounted;
588
+ return this.warnings;
589
+ }
590
+ logMessage(logType, message) {
591
+ if (!hasProcessEnv ||
592
+ !hasConsole || // eslint-disable-next-line lwr/no-unguarded-apis
593
+ process.env.NODE_ENV === 'production') {
594
+ return;
595
+ }
596
+ if (logType == 'warning') {
597
+ // eslint-disable-next-line lwr/no-unguarded-apis
598
+ console.warn(message);
599
+ }
600
+ else {
601
+ // eslint-disable-next-line lwr/no-unguarded-apis
602
+ console.log(message);
603
+ }
604
+ }
554
605
  }
555
606
  //# sourceMappingURL=moduleRegistry.js.map
@@ -22,10 +22,12 @@ export default class LoaderShim {
22
22
  private tempDefine;
23
23
  private postCustomInit;
24
24
  private initApp;
25
+ private waitForBody;
25
26
  private waitForDOMContentLoaded;
26
27
  private createProfilerModule;
27
28
  private mountApp;
28
29
  private enterErrorState;
29
30
  private startWatchdogTimer;
31
+ private logWarnings;
30
32
  }
31
33
  //# sourceMappingURL=shim.d.ts.map
@@ -1,4 +1,4 @@
1
- /* global document */
1
+ /* global document, process, console */
2
2
  import { BOOTSTRAP_ERROR } from 'lwr/metrics';
3
3
  import { logOperationStart, logOperationEnd } from 'lwr/profiler';
4
4
  import { createLoader } from './loader.js';
@@ -7,6 +7,7 @@ import { customInit } from './customInit.js';
7
7
  /* eslint-disable lwr/no-unguarded-apis */
8
8
  const hasSetTimeout = typeof setTimeout === 'function';
9
9
  const hasConsole = typeof console !== 'undefined';
10
+ const hasProcess = typeof process !== 'undefined';
10
11
  /* eslint-enable lwr/no-unguarded-apis */
11
12
  export default class LoaderShim {
12
13
  constructor(global) {
@@ -101,16 +102,38 @@ export default class LoaderShim {
101
102
  };
102
103
  const loader = createLoader(this.loaderSpecifier, this.defineCache[this.loaderSpecifier], loaderConfig, this.config.preloadModules);
103
104
  this.mountApp(loader);
105
+ if (loader &&
106
+ typeof loader.getModuleWarnings === 'function' &&
107
+ hasProcess &&
108
+ hasConsole &&
109
+ // eslint-disable-next-line lwr/no-unguarded-apis
110
+ process.env.NODE_ENV !== 'production') {
111
+ this.logWarnings(loader.getModuleWarnings(true)); // the true indicates the app is mounted
112
+ }
104
113
  }
105
114
  catch (e) {
106
115
  this.enterErrorState(e);
107
116
  }
108
117
  }
118
+ waitForBody() {
119
+ return new Promise((resolve) => {
120
+ // eslint-disable-next-line lwr/no-unguarded-apis
121
+ if (document.body) {
122
+ resolve();
123
+ }
124
+ else {
125
+ const observer = new MutationObserver(() => {
126
+ // eslint-disable-next-line lwr/no-unguarded-apis
127
+ if (document.body) {
128
+ observer.disconnect();
129
+ resolve();
130
+ }
131
+ });
132
+ observer.observe(document.documentElement, { childList: true });
133
+ }
134
+ });
135
+ }
109
136
  waitForDOMContentLoaded() {
110
- // eslint-disable-next-line lwr/no-unguarded-apis
111
- if (typeof document === undefined) {
112
- return Promise.resolve();
113
- }
114
137
  // Resolve if document is already "ready" https://developer.mozilla.org/en-US/docs/Web/API/Document/readyState
115
138
  // eslint-disable-next-line lwr/no-unguarded-apis
116
139
  if (document.readyState === 'interactive' || document.readyState === 'complete') {
@@ -152,8 +175,9 @@ export default class LoaderShim {
152
175
  loader.define(...this.defineCache[specifier]);
153
176
  }
154
177
  });
155
- // by default, app initialization is gated on waiting for document to be parsed (via DOMContentLoaded)
156
- const { disableInitDefer } = this.config;
178
+ // by default, app initialization is gated on waiting for body to be available
179
+ // this flag uses the DOMContentLoaded event instead
180
+ const { initDeferDOM } = this.config;
157
181
  // Load the import mappings and application bootstrap module
158
182
  loader
159
183
  .registerImportMappings({ imports: importsObj, index }, [
@@ -161,9 +185,14 @@ export default class LoaderShim {
161
185
  rootComponent,
162
186
  ])
163
187
  .then(() => {
164
- if (!disableInitDefer) {
188
+ // eslint-disable-next-line lwr/no-unguarded-apis
189
+ if (typeof window === 'undefined' || typeof document === undefined) {
190
+ return Promise.resolve();
191
+ }
192
+ if (initDeferDOM) {
165
193
  return this.waitForDOMContentLoaded();
166
194
  }
195
+ return this.waitForBody();
167
196
  })
168
197
  .then(() => loader.load(bootstrapModule))
169
198
  .catch((reason) => {
@@ -190,5 +219,13 @@ export default class LoaderShim {
190
219
  this.enterErrorState(new Error('Failed to load required modules - timed out'));
191
220
  }, REQUIRED_MODULES_TIMEOUT);
192
221
  }
222
+ logWarnings(warnings) {
223
+ for (const warningKey in warnings) {
224
+ if (warnings[warningKey].length) {
225
+ // eslint-disable-next-line lwr/no-unguarded-apis
226
+ console.warn(warningKey, warnings[warningKey]);
227
+ }
228
+ }
229
+ }
193
230
  }
194
231
  //# sourceMappingURL=shim.js.map
@@ -22,10 +22,12 @@ export default class LoaderShim {
22
22
  private tempDefine;
23
23
  private postCustomInit;
24
24
  private initApp;
25
+ private waitForBody;
25
26
  private waitForDOMContentLoaded;
26
27
  private createProfilerModule;
27
28
  private mountApp;
28
29
  private enterErrorState;
29
30
  private startWatchdogTimer;
31
+ private logWarnings;
30
32
  }
31
33
  //# sourceMappingURL=shimLegacy.d.ts.map
@@ -1,4 +1,4 @@
1
- /* global document */
1
+ /* global document, process, console */
2
2
  import { BOOTSTRAP_ERROR } from 'lwr/metrics';
3
3
  import { logOperationStart, logOperationEnd } from 'lwr/profiler';
4
4
  import { createLoader } from './loaderLegacy.js';
@@ -7,6 +7,7 @@ import { customInit } from '../shim/customInit.js';
7
7
  /* eslint-disable lwr/no-unguarded-apis */
8
8
  const hasSetTimeout = typeof setTimeout === 'function';
9
9
  const hasConsole = typeof console !== 'undefined';
10
+ const hasProcess = typeof process !== 'undefined';
10
11
  /* eslint-enable lwr/no-unguarded-apis */
11
12
  export default class LoaderShim {
12
13
  constructor(global) {
@@ -100,16 +101,38 @@ export default class LoaderShim {
100
101
  };
101
102
  const loader = createLoader(this.loaderModule, this.defineCache[this.loaderModule], loaderConfig, this.config.preloadModules);
102
103
  this.mountApp(loader);
104
+ if (loader &&
105
+ typeof loader.getModuleWarnings === 'function' &&
106
+ hasProcess &&
107
+ hasConsole &&
108
+ // eslint-disable-next-line lwr/no-unguarded-apis
109
+ process.env.NODE_ENV !== 'production') {
110
+ this.logWarnings(loader.getModuleWarnings(true)); // the true indicates the app is mounted
111
+ }
103
112
  }
104
113
  catch (e) {
105
114
  this.enterErrorState(e);
106
115
  }
107
116
  }
117
+ waitForBody() {
118
+ return new Promise((resolve) => {
119
+ // eslint-disable-next-line lwr/no-unguarded-apis
120
+ if (document.body) {
121
+ resolve();
122
+ }
123
+ else {
124
+ const observer = new MutationObserver(() => {
125
+ // eslint-disable-next-line lwr/no-unguarded-apis
126
+ if (document.body) {
127
+ observer.disconnect();
128
+ resolve();
129
+ }
130
+ });
131
+ observer.observe(document.documentElement, { childList: true });
132
+ }
133
+ });
134
+ }
108
135
  waitForDOMContentLoaded() {
109
- // eslint-disable-next-line lwr/no-unguarded-apis
110
- if (typeof document === undefined) {
111
- return Promise.resolve();
112
- }
113
136
  // Resolve if document is already "ready" https://developer.mozilla.org/en-US/docs/Web/API/Document/readyState
114
137
  // eslint-disable-next-line lwr/no-unguarded-apis
115
138
  if (document.readyState === 'interactive' || document.readyState === 'complete') {
@@ -149,15 +172,21 @@ export default class LoaderShim {
149
172
  loader.define(...this.defineCache[specifier]);
150
173
  }
151
174
  });
152
- // by default, app initialization is gated on waiting for document to be parsed (via DOMContentLoaded)
153
- const { disableInitDefer } = this.config;
175
+ // by default, app initialization is gated on waiting for body to be available
176
+ // this flag uses the DOMContentLoaded event instead
177
+ const { initDeferDOM } = this.config;
154
178
  // Load the import mappings and application bootstrap module
155
179
  loader
156
180
  .registerImportMappings(importMappings)
157
181
  .then(() => {
158
- if (!disableInitDefer) {
182
+ // eslint-disable-next-line lwr/no-unguarded-apis
183
+ if (typeof window === 'undefined' || typeof document === undefined) {
184
+ return Promise.resolve();
185
+ }
186
+ if (initDeferDOM) {
159
187
  return this.waitForDOMContentLoaded();
160
188
  }
189
+ return this.waitForBody();
161
190
  })
162
191
  .then(() => loader.load(bootstrapModule))
163
192
  .catch((reason) => {
@@ -184,5 +213,13 @@ export default class LoaderShim {
184
213
  this.enterErrorState(new Error('Failed to load required modules - timed out'));
185
214
  }, REQUIRED_MODULES_TIMEOUT);
186
215
  }
216
+ logWarnings(warnings) {
217
+ for (const warningKey in warnings) {
218
+ if (warnings[warningKey].length) {
219
+ // eslint-disable-next-line lwr/no-unguarded-apis
220
+ console.warn(warningKey, warnings[warningKey]);
221
+ }
222
+ }
223
+ }
187
224
  }
188
225
  //# sourceMappingURL=shimLegacy.js.map
package/build/types.d.ts CHANGED
@@ -18,6 +18,7 @@ export interface BaseLoaderAPI {
18
18
  registerExternalModules(modules: string[]): void;
19
19
  services: Record<string, Function>;
20
20
  clearRegistry: Function;
21
+ getModuleWarnings(isAppMounted: boolean): Record<string, string[]>;
21
22
  }
22
23
  export interface LoaderAPI extends BaseLoaderAPI {
23
24
  registerImportMappings(mappings?: ImportMap): Promise<void>;