@lwrjs/everywhere 0.22.11 → 0.22.13

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 (23) hide show
  1. package/build/__generated_site_amd_modules__/1/application/amd/l/en-US/ai/amd-bootstrap/configuration/ci/-/-/s/e2db3283c6dbc0903b2cf61cdefce644/config.js +12 -0
  2. package/build/__generated_site_amd_modules__/1/module/amd/1/l/en-US/mi/@lwrjs/app-service/amd-bootstrap/module/amd/v/{0_22_11 → 0_22_13}/s/d4022ae1b3a47f5bb62c600fd6b8f139/@lwrjs_app-service_amd-bootstrap_module_amd.js +5 -5
  3. package/build/__generated_site_amd_modules__/1/module/amd/1/l/en-US/mi/lwr/everywhereAmd/v/{0_22_11 → 0_22_13}/s/cb931ebef2b89dcf8ab51456e3a68864/lwr_everywhereAmd.js +3 -3
  4. package/build/__generated_site_amd_modules__/1/module/amd/1/l/en-US/mi/lwr/init/v/{0_22_11 → 0_22_13}/s/c5c8bdc0e87baf3d6b68b0603d670664/lwr_init.js +20 -20
  5. package/build/__generated_site_amd_modules__/1/module/amd/1/l/en-US/mi/lwr/loader/v/{0_22_11/s/6c345d6d2c76f860c9b15b845d1042de → 0_22_13/s/14273a6a9acc9325957be8c0dad67c13}/lwr_loader.js +160 -9
  6. package/build/__generated_site_amd_modules__/1/module/amd/1/l/en-US/mi/lwr/metrics/v/{0_22_11 → 0_22_13}/s/fb8c5dd340c69fdf7ded52d3eba633b9/lwr_metrics.js +1 -1
  7. package/build/__generated_site_amd_modules__/1/module/amd/1/l/en-US/mi/lwr/preInit/v/{0_22_11 → 0_22_13}/s/9120455810adf1ca6b429479490a4b0d/lwr_preInit.js +1 -1
  8. package/build/__generated_site_amd_modules__/1/module/amd/1/l/en-US/mi/lwr/profiler/v/{0_22_11 → 0_22_13}/s/9f74c8370534ce02c6e7637abdcffedf/lwr_profiler.js +1 -1
  9. package/build/__generated_site_amd_modules__/1/module/amd/1/l/en-US/mi/lwr/scheduler/v/{0_22_11 → 0_22_13}/s/fd3fe53248b540ca046ead92862ca496/lwr_scheduler.js +1 -1
  10. package/build/__generated_site_amd_modules__/1/module/amd/1/l/en-US/mi/lwr/vault/v/{0_22_11 → 0_22_13}/s/c92abd8c1fec2d7eff62e4b097abbe14/lwr_vault.js +1 -1
  11. package/build/__generated_site_amd_modules__/1/resource/amd/lwr-error-shim.js/v/{0_22_11 → 0_22_13}/lwr-error-shim.js +1 -1
  12. package/build/__generated_site_amd_modules__/1/resource/amd/lwr-loader-shim.bundle.js/v/{0_22_11 → 0_22_13}/lwr-loader-shim.bundle.js +191 -19
  13. package/build/assets/amd/lwr-everywhere-debug.js +185 -15
  14. package/build/assets/amd/lwr-everywhere-min.js +2 -2
  15. package/build/assets/amd/lwr-everywhere.js +185 -15
  16. package/build/assets/core/lwr-everywhere-debug.js +181 -11
  17. package/build/assets/core/lwr-everywhere-min.js +2 -2
  18. package/build/assets/core/lwr-everywhere.js +181 -11
  19. package/build/assets/esm/lwr-everywhere-debug.js +1 -1
  20. package/build/assets/esm/lwr-everywhere-min.js +1 -1
  21. package/build/assets/esm/lwr-everywhere.js +1 -1
  22. package/package.json +6 -6
  23. package/build/__generated_site_amd_modules__/1/application/amd/l/en-US/ai/amd-bootstrap/configuration/ci/-/-/s/19a69dbdb3c9e1cf22a735ed3a7b00f9/config.js +0 -12
@@ -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 Module Loader Shim v0.22.11 */
7
+ /* LWR Module Loader Shim v0.22.13 */
8
8
  (function () {
9
9
  'use strict';
10
10
 
@@ -283,6 +283,7 @@
283
283
 
284
284
 
285
285
 
286
+
286
287
  /* eslint-disable lwr/no-unguarded-apis */
287
288
  const hasSetTimeout = typeof setTimeout === 'function';
288
289
  const hasConsole = typeof console !== 'undefined';
@@ -309,7 +310,7 @@
309
310
  // Parse configuration
310
311
  this.global = global;
311
312
  this.config = global.LWR ;
312
- this.loaderSpecifier = 'lwr/loader/v/0_22_11';
313
+ this.loaderSpecifier = 'lwr/loader/v/0_22_13';
313
314
 
314
315
  // Set up error handler
315
316
  this.errorHandler = this.config.onError ;
@@ -317,7 +318,7 @@
317
318
  // Set up onAppInit handler
318
319
  this.initAppHandler = this.config.onInitApp ;
319
320
 
320
- // Set up the temporary LWR.define function and customInit hook
321
+ // Set up the temporary LWR.define function
321
322
  const tempDefine = this.tempDefine.bind(this);
322
323
  global.LWR.define = tempDefine;
323
324
  this.bootReady = this.config.autoBoot;
@@ -474,7 +475,7 @@
474
475
  const exporter = (exports) => {
475
476
  Object.assign(exports, { logOperationStart, logOperationEnd });
476
477
  };
477
- define('lwr/profiler/v/0_22_11', ['exports'], exporter);
478
+ define('lwr/profiler/v/0_22_13', ['exports'], exporter);
478
479
  }
479
480
 
480
481
  // Set up the application globals, import map, root custom element...
@@ -483,9 +484,13 @@
483
484
  this.config;
484
485
 
485
486
  const importsObj = imports || {};
486
- // Set global LWR.define to loader.define
487
+
488
+ // Set global LWR.define to loader.define and expose the public-only importMap.
489
+ // The wrapper intentionally omits the internal rootSpecifiers parameter so external
490
+ // callers cannot bypass runtime validation by triggering the bootstrap path.
487
491
  this.global.LWR = Object.freeze({
488
492
  define: loader.define.bind(loader),
493
+ importMap: (update) => loader.importMap(update),
489
494
  rootComponent,
490
495
  rootComponents,
491
496
  serverData: serverData || {},
@@ -508,10 +513,7 @@
508
513
 
509
514
  // Load the import mappings and application bootstrap module
510
515
  loader
511
- .registerImportMappings({ imports: importsObj, index }, [
512
- bootstrapModule,
513
- rootComponent ,
514
- ])
516
+ .importMap({ imports: importsObj, index }, [bootstrapModule, rootComponent ])
515
517
  .then(() => {
516
518
  // eslint-disable-next-line lwr/no-unguarded-apis
517
519
  if (typeof window === 'undefined' || typeof document === 'undefined') {
@@ -574,14 +576,14 @@
574
576
  // The loader module is ALWAYS required
575
577
  const GLOBAL = globalThis ;
576
578
  GLOBAL.LWR.requiredModules = GLOBAL.LWR.requiredModules || [];
577
- if (GLOBAL.LWR.requiredModules.indexOf('lwr/loader/v/0_22_11') < 0) {
578
- GLOBAL.LWR.requiredModules.push('lwr/loader/v/0_22_11');
579
+ if (GLOBAL.LWR.requiredModules.indexOf('lwr/loader/v/0_22_13') < 0) {
580
+ GLOBAL.LWR.requiredModules.push('lwr/loader/v/0_22_13');
579
581
  }
580
582
  new LoaderShim(GLOBAL);
581
583
 
582
584
  })();
583
585
 
584
- LWR.define('lwr/loader/v/0_22_11', ['exports'], (function (exports) { 'use strict';
586
+ LWR.define('lwr/loader/v/0_22_13', ['exports'], (function (exports) { 'use strict';
585
587
 
586
588
  const templateRegex = /\{([0-9]+)\}/g;
587
589
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -1014,11 +1016,7 @@ LWR.define('lwr/loader/v/0_22_11', ['exports'], (function (exports) { 'use stric
1014
1016
  return this.config.baseUrl || '';
1015
1017
  }
1016
1018
 
1017
- registerImportMappings(newImportMetadata, rootSpecifiers) {
1018
- if (!rootSpecifiers || rootSpecifiers.length === 0) {
1019
- const imports = newImportMetadata ? JSON.stringify(newImportMetadata) : 'undefined';
1020
- throw new LoaderError(BAD_IMPORT_METADATA, [imports, rootSpecifiers ? '[]' : 'undefined']);
1021
- }
1019
+ registerImportMappings(newImportMetadata, rootSpecifiers = []) {
1022
1020
  if (!newImportMetadata) {
1023
1021
  throw new LoaderError(BAD_IMPORT_METADATA, ['undefined', JSON.stringify(rootSpecifiers)]);
1024
1022
  }
@@ -1028,6 +1026,8 @@ LWR.define('lwr/loader/v/0_22_11', ['exports'], (function (exports) { 'use stric
1028
1026
  JSON.stringify(rootSpecifiers),
1029
1027
  ]);
1030
1028
  }
1029
+ // An empty rootSpecifiers list is valid for non-bootstrap registrations;
1030
+ // any specifier not in the list receives isRoot: false.
1031
1031
  const index = newImportMetadata.index || {};
1032
1032
  for (const [uri, specifiers] of Object.entries(newImportMetadata.imports)) {
1033
1033
  specifiers.forEach((specifier) => {
@@ -1050,6 +1050,16 @@ LWR.define('lwr/loader/v/0_22_11', ['exports'], (function (exports) { 'use stric
1050
1050
  }
1051
1051
  }
1052
1052
 
1053
+ /**
1054
+ * Returns the raw URI stored for a specifier, or `undefined` if not yet mapped.
1055
+ * Used by the runtime `importMap()` path to detect cross-call duplicates while
1056
+ * allowing truly idempotent re-registrations (same specifier, same URI) to pass
1057
+ * through silently.
1058
+ */
1059
+ getMappingUri(specifier) {
1060
+ return _optionalChain([this, 'access', _ => _.importURICache, 'access', _2 => _2.get, 'call', _3 => _3(specifier), 'optionalAccess', _4 => _4.uri]);
1061
+ }
1062
+
1053
1063
  // Get URL from the local cache or return undefiend
1054
1064
  getURI(specifier) {
1055
1065
  return this.importURICache && this.importURICache.has(specifier)
@@ -1147,7 +1157,7 @@ LWR.define('lwr/loader/v/0_22_11', ['exports'], (function (exports) { 'use stric
1147
1157
  }
1148
1158
 
1149
1159
  async fetchNewMappings(specifier) {
1150
- if (!hasSetTimeout || !_optionalChain([this, 'access', _ => _.config, 'optionalAccess', _2 => _2.flags, 'optionalAccess', _3 => _3.batchMappings])) {
1160
+ if (!hasSetTimeout || !_optionalChain([this, 'access', _5 => _5.config, 'optionalAccess', _6 => _6.flags, 'optionalAccess', _7 => _7.batchMappings])) {
1151
1161
  return this.fetchNewMappingsInner(specifier);
1152
1162
  }
1153
1163
 
@@ -2236,6 +2246,101 @@ LWR.define('lwr/loader/v/0_22_11', ['exports'], (function (exports) { 'use stric
2236
2246
  }
2237
2247
  }
2238
2248
 
2249
+ /**
2250
+ * Ensures the update object key is a safe, loader-supported script URL (not a bare specifier).
2251
+ * Covers dangerous schemes and URL-key shape in one place.
2252
+ */
2253
+ function assertValidImportMapUrlKey(moduleScriptURL) {
2254
+ const lowerUri = moduleScriptURL.toLowerCase();
2255
+
2256
+ if (lowerUri.startsWith('blob:')) {
2257
+ throw new Error(`Cannot map ${moduleScriptURL} to blob: URL`);
2258
+ }
2259
+
2260
+ if (lowerUri.startsWith('data:')) {
2261
+ throw new Error(`Cannot map ${moduleScriptURL} to data: URL`);
2262
+ }
2263
+
2264
+ if (!/^[./]|^https?:/.test(moduleScriptURL)) {
2265
+ throw new Error(
2266
+ `LWR.importMap(): "${moduleScriptURL}" is not a valid URL key. Keys must be URL paths (e.g. "/path/to/module.js"), not module specifiers. Transitive specifier aliasing is not supported by this loader.`,
2267
+ );
2268
+ }
2269
+ }
2270
+
2271
+ /**
2272
+ * Validates an ImportMapUpdate and wraps it as ImportMetadata for the fingerprints loader.
2273
+ *
2274
+ * Does not apply legacy-style protected-specifier blocking; system modules are expected to be
2275
+ * defined at bootstrap, and `importMap` write-once semantics handle redundant runtime entries.
2276
+ *
2277
+ * Duplicate specifiers in the same update are de-duplicated silently (first occurrence wins).
2278
+ * An empty object is a silent no-op (returns null).
2279
+ */
2280
+ function validateAndWrapAsImportMetadata(update) {
2281
+ if (!update || typeof update !== 'object') {
2282
+ throw new Error('LWR.importMap() requires an object argument');
2283
+ }
2284
+
2285
+ const entries = Object.entries(update);
2286
+ if (entries.length === 0) {
2287
+ return null;
2288
+ }
2289
+
2290
+ const seenSpecifiers = new Set();
2291
+ const validatedImports = {};
2292
+
2293
+ for (const [moduleScriptURL, moduleNames] of entries) {
2294
+ if (!moduleScriptURL || typeof moduleScriptURL !== 'string') {
2295
+ throw new Error('moduleScriptURL must be a string');
2296
+ }
2297
+
2298
+ if (!Array.isArray(moduleNames)) {
2299
+ throw new Error('moduleNames must be an array');
2300
+ }
2301
+
2302
+ assertValidImportMapUrlKey(moduleScriptURL);
2303
+
2304
+ const validatedNames = [];
2305
+ for (const moduleName of moduleNames) {
2306
+ if (typeof moduleName !== 'string' || moduleName.length === 0) {
2307
+ throw new Error('Specifier must be a non-empty string');
2308
+ }
2309
+
2310
+ if (!seenSpecifiers.has(moduleName)) {
2311
+ seenSpecifiers.add(moduleName);
2312
+ validatedNames.push(moduleName);
2313
+ }
2314
+ }
2315
+
2316
+ if (validatedNames.length > 0) {
2317
+ validatedImports[moduleScriptURL] = validatedNames;
2318
+ }
2319
+ }
2320
+
2321
+ if (Object.keys(validatedImports).length === 0) {
2322
+ return null;
2323
+ }
2324
+
2325
+ return { imports: validatedImports };
2326
+ }
2327
+
2328
+ /**
2329
+ * Returns true when `update` carries the `ImportMetadata` shape (an `imports` object key),
2330
+ * signalling that it should be passed through to the resolver directly rather than treated
2331
+ * as a public-API `ImportMapUpdate`.
2332
+ */
2333
+ function isImportMetadata(update) {
2334
+ const candidate = update ;
2335
+ return (
2336
+ candidate !== null &&
2337
+ typeof candidate === 'object' &&
2338
+ 'imports' in candidate &&
2339
+ typeof candidate.imports === 'object' &&
2340
+ !Array.isArray(candidate.imports)
2341
+ );
2342
+ }
2343
+
2239
2344
  /**
2240
2345
  * The LWR loader is inspired and borrows from the algorithms and native browser principles of https://github.com/systemjs/systemjs
2241
2346
  */
@@ -2369,8 +2474,75 @@ LWR.define('lwr/loader/v/0_22_11', ['exports'], (function (exports) { 'use stric
2369
2474
  return this.registry.resolve(id, importer);
2370
2475
  }
2371
2476
 
2477
+ /**
2478
+ * Apply import map updates at runtime, or register bootstrap import mappings.
2479
+ *
2480
+ * **Runtime usage** (public API, consistent with `LWR.importMap()` on the legacy loader):
2481
+ * `importMap({ [moduleScriptURL]: [moduleName1, moduleName2, ...] })`
2482
+ * Validates the update and registers the new mappings dynamically.
2483
+ *
2484
+ * **Bootstrap / internal usage** (replaces `registerImportMappings`):
2485
+ * `importMap(importMetadata)` or `importMap(importMetadata, rootSpecifiers)`
2486
+ * Detected at runtime by the `ImportMetadata` shape (presence of an `imports` object).
2487
+ * This branch **does not** run `validateAndWrapAsImportMetadata` (URL-key checks /
2488
+ * runtime-payload dedupe). That is intentional: bootstrap must preserve
2489
+ * `index` fingerprints and use `ImportMetadataResolver.registerImportMappings` merge
2490
+ * semantics unchanged from the pre-`importMap` API.
2491
+ *
2492
+ * **Who may use this branch:** Platform/shim code with trusted config (see
2493
+ * `shim/shim.ts`, which calls `loader.importMap({ imports, index }, roots)`). The
2494
+ * public `LWR.importMap` wrapper only forwards the flat runtime update shape; any
2495
+ * code with a direct `Loader` reference could still pass an `ImportMetadata`-shaped
2496
+ * object — same trust boundary as calling `registerImportMappings` before.
2497
+ *
2498
+ * @param update - Runtime: `ImportMapUpdate` mapping script URLs to the module names they define.
2499
+ * Bootstrap: `ImportMetadata` with an `imports` object (and optional `index`).
2500
+ * @param rootSpecifiers - Bootstrap only: root module specifiers for the initial registration.
2501
+ * Optional — omit when the root specifiers are not known.
2502
+ */
2503
+ async importMap(update, rootSpecifiers) {
2504
+ if (isImportMetadata(update)) {
2505
+ this.registry.getImportMetadataResolver().registerImportMappings(update, rootSpecifiers);
2506
+ return;
2507
+ }
2508
+ const resolver = this.registry.getImportMetadataResolver();
2509
+ const importMetadata = validateAndWrapAsImportMetadata(update );
2510
+ if (!importMetadata) {
2511
+ return;
2512
+ }
2513
+
2514
+ const dedupedImports = {};
2515
+ for (const [uri, specifiers] of Object.entries(importMetadata.imports)) {
2516
+ const newSpecifiers = [];
2517
+ for (const specifier of specifiers) {
2518
+ const existingUri = resolver.getMappingUri(specifier);
2519
+ if (existingUri !== undefined) ; else {
2520
+ newSpecifiers.push(specifier);
2521
+ }
2522
+ }
2523
+ if (newSpecifiers.length > 0) {
2524
+ dedupedImports[uri] = newSpecifiers;
2525
+ }
2526
+ }
2527
+
2528
+ if (Object.keys(dedupedImports).length === 0) {
2529
+ return;
2530
+ }
2531
+
2532
+ const filtered = { imports: dedupedImports };
2533
+ const specs = Object.values(filtered.imports).flat();
2534
+ resolver.registerImportMappings(filtered, specs);
2535
+ }
2536
+
2537
+ /**
2538
+ * @deprecated Use `importMap(metadata, rootSpecifiers)` instead.
2539
+ */
2372
2540
  async registerImportMappings(mappings, rootSpecifiers) {
2373
- this.registry.getImportMetadataResolver().registerImportMappings(mappings, rootSpecifiers);
2541
+ if (hasConsole) {
2542
+ // eslint-disable-next-line lwr/no-unguarded-apis
2543
+ console.warn('registerImportMappings() is deprecated. Use importMap() instead.');
2544
+ }
2545
+ return this.importMap(mappings, rootSpecifiers);
2374
2546
  }
2375
2547
 
2376
2548
  /**
@@ -20,7 +20,7 @@ function getConfiguration(options) {
20
20
  : `${ORIGIN}${PREFIX}/module/${format}/${POSTFIX}/mi/`;
21
21
 
22
22
  // Component specifiers and URIs
23
- const BOOT_MODULE = `lwr/everywhere${format === 'esm' ? 'Esm' : 'Amd'}/v/0_22_11`;
23
+ const BOOT_MODULE = `lwr/everywhere${format === 'esm' ? 'Esm' : 'Amd'}/v/0_22_13`;
24
24
  const BOOT_URI = `${ENDPOINT}${encodeURIComponent(BOOT_MODULE)}/latest${debug ? '?debug' : ''}`;
25
25
 
26
26
  // Client Bootstrap Config
@@ -52,7 +52,7 @@ function getConfiguration(options) {
52
52
  * SPDX-License-Identifier: MIT
53
53
  * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
54
54
  */
55
- /* LWR Module Loader v0.22.11 */
55
+ /* LWR Module Loader v0.22.13 */
56
56
  const templateRegex = /\{([0-9]+)\}/g;
57
57
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
58
58
  function templateString(template, args) {
@@ -484,11 +484,7 @@ class ImportMetadataResolver {
484
484
  return this.config.baseUrl || '';
485
485
  }
486
486
 
487
- registerImportMappings(newImportMetadata, rootSpecifiers) {
488
- if (!rootSpecifiers || rootSpecifiers.length === 0) {
489
- const imports = newImportMetadata ? JSON.stringify(newImportMetadata) : 'undefined';
490
- throw new LoaderError(BAD_IMPORT_METADATA, [imports, rootSpecifiers ? '[]' : 'undefined']);
491
- }
487
+ registerImportMappings(newImportMetadata, rootSpecifiers = []) {
492
488
  if (!newImportMetadata) {
493
489
  throw new LoaderError(BAD_IMPORT_METADATA, ['undefined', JSON.stringify(rootSpecifiers)]);
494
490
  }
@@ -498,6 +494,8 @@ class ImportMetadataResolver {
498
494
  JSON.stringify(rootSpecifiers),
499
495
  ]);
500
496
  }
497
+ // An empty rootSpecifiers list is valid for non-bootstrap registrations;
498
+ // any specifier not in the list receives isRoot: false.
501
499
  const index = newImportMetadata.index || {};
502
500
  for (const [uri, specifiers] of Object.entries(newImportMetadata.imports)) {
503
501
  specifiers.forEach((specifier) => {
@@ -520,6 +518,16 @@ class ImportMetadataResolver {
520
518
  }
521
519
  }
522
520
 
521
+ /**
522
+ * Returns the raw URI stored for a specifier, or `undefined` if not yet mapped.
523
+ * Used by the runtime `importMap()` path to detect cross-call duplicates while
524
+ * allowing truly idempotent re-registrations (same specifier, same URI) to pass
525
+ * through silently.
526
+ */
527
+ getMappingUri(specifier) {
528
+ return _optionalChain$1([this, 'access', _ => _.importURICache, 'access', _2 => _2.get, 'call', _3 => _3(specifier), 'optionalAccess', _4 => _4.uri]);
529
+ }
530
+
523
531
  // Get URL from the local cache or return undefiend
524
532
  getURI(specifier) {
525
533
  return this.importURICache && this.importURICache.has(specifier)
@@ -617,7 +625,7 @@ class ImportMetadataResolver {
617
625
  }
618
626
 
619
627
  async fetchNewMappings(specifier) {
620
- if (!hasSetTimeout || !_optionalChain$1([this, 'access', _ => _.config, 'optionalAccess', _2 => _2.flags, 'optionalAccess', _3 => _3.batchMappings])) {
628
+ if (!hasSetTimeout || !_optionalChain$1([this, 'access', _5 => _5.config, 'optionalAccess', _6 => _6.flags, 'optionalAccess', _7 => _7.batchMappings])) {
621
629
  return this.fetchNewMappingsInner(specifier);
622
630
  }
623
631
 
@@ -1707,6 +1715,101 @@ function validateLoadSpecifier(
1707
1715
  }
1708
1716
  }
1709
1717
 
1718
+ /**
1719
+ * Ensures the update object key is a safe, loader-supported script URL (not a bare specifier).
1720
+ * Covers dangerous schemes and URL-key shape in one place.
1721
+ */
1722
+ function assertValidImportMapUrlKey(moduleScriptURL) {
1723
+ const lowerUri = moduleScriptURL.toLowerCase();
1724
+
1725
+ if (lowerUri.startsWith('blob:')) {
1726
+ throw new Error(`Cannot map ${moduleScriptURL} to blob: URL`);
1727
+ }
1728
+
1729
+ if (lowerUri.startsWith('data:')) {
1730
+ throw new Error(`Cannot map ${moduleScriptURL} to data: URL`);
1731
+ }
1732
+
1733
+ if (!/^[./]|^https?:/.test(moduleScriptURL)) {
1734
+ throw new Error(
1735
+ `LWR.importMap(): "${moduleScriptURL}" is not a valid URL key. Keys must be URL paths (e.g. "/path/to/module.js"), not module specifiers. Transitive specifier aliasing is not supported by this loader.`,
1736
+ );
1737
+ }
1738
+ }
1739
+
1740
+ /**
1741
+ * Validates an ImportMapUpdate and wraps it as ImportMetadata for the fingerprints loader.
1742
+ *
1743
+ * Does not apply legacy-style protected-specifier blocking; system modules are expected to be
1744
+ * defined at bootstrap, and `importMap` write-once semantics handle redundant runtime entries.
1745
+ *
1746
+ * Duplicate specifiers in the same update are de-duplicated silently (first occurrence wins).
1747
+ * An empty object is a silent no-op (returns null).
1748
+ */
1749
+ function validateAndWrapAsImportMetadata(update) {
1750
+ if (!update || typeof update !== 'object') {
1751
+ throw new Error('LWR.importMap() requires an object argument');
1752
+ }
1753
+
1754
+ const entries = Object.entries(update);
1755
+ if (entries.length === 0) {
1756
+ return null;
1757
+ }
1758
+
1759
+ const seenSpecifiers = new Set();
1760
+ const validatedImports = {};
1761
+
1762
+ for (const [moduleScriptURL, moduleNames] of entries) {
1763
+ if (!moduleScriptURL || typeof moduleScriptURL !== 'string') {
1764
+ throw new Error('moduleScriptURL must be a string');
1765
+ }
1766
+
1767
+ if (!Array.isArray(moduleNames)) {
1768
+ throw new Error('moduleNames must be an array');
1769
+ }
1770
+
1771
+ assertValidImportMapUrlKey(moduleScriptURL);
1772
+
1773
+ const validatedNames = [];
1774
+ for (const moduleName of moduleNames) {
1775
+ if (typeof moduleName !== 'string' || moduleName.length === 0) {
1776
+ throw new Error('Specifier must be a non-empty string');
1777
+ }
1778
+
1779
+ if (!seenSpecifiers.has(moduleName)) {
1780
+ seenSpecifiers.add(moduleName);
1781
+ validatedNames.push(moduleName);
1782
+ }
1783
+ }
1784
+
1785
+ if (validatedNames.length > 0) {
1786
+ validatedImports[moduleScriptURL] = validatedNames;
1787
+ }
1788
+ }
1789
+
1790
+ if (Object.keys(validatedImports).length === 0) {
1791
+ return null;
1792
+ }
1793
+
1794
+ return { imports: validatedImports };
1795
+ }
1796
+
1797
+ /**
1798
+ * Returns true when `update` carries the `ImportMetadata` shape (an `imports` object key),
1799
+ * signalling that it should be passed through to the resolver directly rather than treated
1800
+ * as a public-API `ImportMapUpdate`.
1801
+ */
1802
+ function isImportMetadata(update) {
1803
+ const candidate = update ;
1804
+ return (
1805
+ candidate !== null &&
1806
+ typeof candidate === 'object' &&
1807
+ 'imports' in candidate &&
1808
+ typeof candidate.imports === 'object' &&
1809
+ !Array.isArray(candidate.imports)
1810
+ );
1811
+ }
1812
+
1710
1813
  /**
1711
1814
  * The LWR loader is inspired and borrows from the algorithms and native browser principles of https://github.com/systemjs/systemjs
1712
1815
  */
@@ -1840,8 +1943,75 @@ class Loader {
1840
1943
  return this.registry.resolve(id, importer);
1841
1944
  }
1842
1945
 
1946
+ /**
1947
+ * Apply import map updates at runtime, or register bootstrap import mappings.
1948
+ *
1949
+ * **Runtime usage** (public API, consistent with `LWR.importMap()` on the legacy loader):
1950
+ * `importMap({ [moduleScriptURL]: [moduleName1, moduleName2, ...] })`
1951
+ * Validates the update and registers the new mappings dynamically.
1952
+ *
1953
+ * **Bootstrap / internal usage** (replaces `registerImportMappings`):
1954
+ * `importMap(importMetadata)` or `importMap(importMetadata, rootSpecifiers)`
1955
+ * Detected at runtime by the `ImportMetadata` shape (presence of an `imports` object).
1956
+ * This branch **does not** run `validateAndWrapAsImportMetadata` (URL-key checks /
1957
+ * runtime-payload dedupe). That is intentional: bootstrap must preserve
1958
+ * `index` fingerprints and use `ImportMetadataResolver.registerImportMappings` merge
1959
+ * semantics unchanged from the pre-`importMap` API.
1960
+ *
1961
+ * **Who may use this branch:** Platform/shim code with trusted config (see
1962
+ * `shim/shim.ts`, which calls `loader.importMap({ imports, index }, roots)`). The
1963
+ * public `LWR.importMap` wrapper only forwards the flat runtime update shape; any
1964
+ * code with a direct `Loader` reference could still pass an `ImportMetadata`-shaped
1965
+ * object — same trust boundary as calling `registerImportMappings` before.
1966
+ *
1967
+ * @param update - Runtime: `ImportMapUpdate` mapping script URLs to the module names they define.
1968
+ * Bootstrap: `ImportMetadata` with an `imports` object (and optional `index`).
1969
+ * @param rootSpecifiers - Bootstrap only: root module specifiers for the initial registration.
1970
+ * Optional — omit when the root specifiers are not known.
1971
+ */
1972
+ async importMap(update, rootSpecifiers) {
1973
+ if (isImportMetadata(update)) {
1974
+ this.registry.getImportMetadataResolver().registerImportMappings(update, rootSpecifiers);
1975
+ return;
1976
+ }
1977
+ const resolver = this.registry.getImportMetadataResolver();
1978
+ const importMetadata = validateAndWrapAsImportMetadata(update );
1979
+ if (!importMetadata) {
1980
+ return;
1981
+ }
1982
+
1983
+ const dedupedImports = {};
1984
+ for (const [uri, specifiers] of Object.entries(importMetadata.imports)) {
1985
+ const newSpecifiers = [];
1986
+ for (const specifier of specifiers) {
1987
+ const existingUri = resolver.getMappingUri(specifier);
1988
+ if (existingUri !== undefined) ; else {
1989
+ newSpecifiers.push(specifier);
1990
+ }
1991
+ }
1992
+ if (newSpecifiers.length > 0) {
1993
+ dedupedImports[uri] = newSpecifiers;
1994
+ }
1995
+ }
1996
+
1997
+ if (Object.keys(dedupedImports).length === 0) {
1998
+ return;
1999
+ }
2000
+
2001
+ const filtered = { imports: dedupedImports };
2002
+ const specs = Object.values(filtered.imports).flat();
2003
+ resolver.registerImportMappings(filtered, specs);
2004
+ }
2005
+
2006
+ /**
2007
+ * @deprecated Use `importMap(metadata, rootSpecifiers)` instead.
2008
+ */
1843
2009
  async registerImportMappings(mappings, rootSpecifiers) {
1844
- this.registry.getImportMetadataResolver().registerImportMappings(mappings, rootSpecifiers);
2010
+ if (hasConsole) {
2011
+ // eslint-disable-next-line lwr/no-unguarded-apis
2012
+ console.warn('registerImportMappings() is deprecated. Use importMap() instead.');
2013
+ }
2014
+ return this.importMap(mappings, rootSpecifiers);
1845
2015
  }
1846
2016
 
1847
2017
  /**
@@ -1869,7 +2039,7 @@ const { bootstrapModule, endpoints, baseUrl, imports, index } = configuration;
1869
2039
 
1870
2040
  // Initialize the AMD loader (its code is bundled into the LWR Everywhere module)
1871
2041
  const loader = new Loader({ endpoints, baseUrl });
1872
- loader.define('lwr/loader/v/0_22_11', ['exports'], (exports) => {
2042
+ loader.define('lwr/loader/v/0_22_13', ['exports'], (exports) => {
1873
2043
  Object.assign(exports, {
1874
2044
  define: loader.define.bind(loader),
1875
2045
  load: loader.load.bind(loader),
@@ -1879,12 +2049,12 @@ await loader.registerImportMappings({ imports, index }, [bootstrapModule]);
1879
2049
  (globalThis ).LWR = Object.freeze({ define: loader.define.bind(loader) });
1880
2050
 
1881
2051
  // Define preload modules (ie: ABS, vault, etc) BEFORE loading them
1882
- LWR.define('lwr/everywhereAmd/v/0_22_11', ['exports', 'lwr/vault/v/0_22_11'], (function (exports, _0_22_11) {
2052
+ LWR.define('lwr/everywhereAmd/v/0_22_13', ['exports', 'lwr/vault/v/0_22_13'], (function (exports, _0_22_13) {
1883
2053
  // IMPORTANT: Do not add any static imports to this file that are not bundled with the amd-client
1884
2054
 
1885
2055
  // Do an OAuthed fetch
1886
2056
  async function authFetch(url, accept = 'javascript') {
1887
- const authInfo = _0_22_11.getAuthInfo();
2057
+ const authInfo = _0_22_13.getAuthInfo();
1888
2058
  if (authInfo) {
1889
2059
  return fetch(url, {
1890
2060
  headers: {
@@ -1933,7 +2103,7 @@ LWR.define('lwr/everywhereAmd/v/0_22_11', ['exports', 'lwr/vault/v/0_22_11'], (f
1933
2103
  function authenticate(authInfo) {
1934
2104
  // Put OAuth info into the vault
1935
2105
  if (authInfo) {
1936
- _0_22_11.setAuthInfo(authInfo);
2106
+ _0_22_13.setAuthInfo(authInfo);
1937
2107
  }
1938
2108
  }
1939
2109
 
@@ -1943,7 +2113,7 @@ LWR.define('lwr/everywhereAmd/v/0_22_11', ['exports', 'lwr/vault/v/0_22_11'], (f
1943
2113
  Object.defineProperty(exports, '__esModule', { value: true });
1944
2114
 
1945
2115
  }));
1946
- LWR.define('lwr/vault/v/0_22_11', ['exports'], (function (exports) {
2116
+ LWR.define('lwr/vault/v/0_22_13', ['exports'], (function (exports) {
1947
2117
  // Credential vault for storing setters and subscribers for OAuth info
1948
2118
  // This module is a SINGLETON and must be excluded from ESM bundling
1949
2119
 
@@ -1967,7 +2137,7 @@ LWR.define('lwr/vault/v/0_22_11', ['exports'], (function (exports) {
1967
2137
 
1968
2138
  // Set up the AMD loader hooks for OAuth
1969
2139
  const { initAmd, authenticate } = await loader.load(bootstrapModule);
1970
- initAmd(loader.services, _optionalChain([endpoints, 'optionalAccess', _ => _.uris, 'access', _2 => _2.mapping]), '0_22_11');
2140
+ initAmd(loader.services, _optionalChain([endpoints, 'optionalAccess', _ => _.uris, 'access', _2 => _2.mapping]), '0_22_13');
1971
2141
 
1972
2142
  // Wrap the createComponent API to allow proper ordering of module definitions:
1973
2143
  // 1. LWRE module bundle (this): lwr/loader, lwr/everywhereAmd, lwr/vault