bare-module-traverse 2.7.2 → 2.7.4

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 (3) hide show
  1. package/index.d.ts +5 -0
  2. package/index.js +65 -1
  3. package/package.json +2 -2
package/index.d.ts CHANGED
@@ -77,6 +77,11 @@ interface TraverseOptions extends ResolveOptions {
77
77
  * than throwing, leaving it for whoever names it to resolve when they get
78
78
  * there. Only for callers that reach a resolver again, such as a module
79
79
  * system; a tool that only links wants the error.
80
+ *
81
+ * An addon resolved for several `hosts` must resolve for each of the native
82
+ * ones, as WebAssembly hosts are only a fallback. A host that it resolves
83
+ * nothing for is unresolved, and is deferred under its own conditions or
84
+ * else fails with `ADDON_NOT_FOUND`.
80
85
  */
81
86
  deferUnresolved?: boolean
82
87
  /**
package/index.js CHANGED
@@ -634,6 +634,18 @@ function* resolveImport(entry, specifier, condition, parentURL, imports, artifac
634
634
  )
635
635
  const candidates = []
636
636
 
637
+ // An addon resolved for several native hosts must resolve for each of them.
638
+ // The conditions of a native resolution say which of them it covers.
639
+ const native =
640
+ condition === 'addon' && !opts.addonHost && Array.isArray(opts.hosts)
641
+ ? opts.hosts.filter((host) => !isWebAssemblyHost(host))
642
+ : []
643
+ const covered = new Set()
644
+ const missed = []
645
+ const prefix = matchedConditions.length
646
+
647
+ let fallback = null
648
+
637
649
  let next = resolver.next()
638
650
  let resolutions = 0
639
651
 
@@ -738,7 +750,12 @@ function* resolveImport(entry, specifier, condition, parentURL, imports, artifac
738
750
  if (resolved) {
739
751
  if (condition === 'addon' && artifacts !== null) addURL(artifacts.addons, resolution)
740
752
 
753
+ if (isWebAssembly(resolution)) fallback = resolution
754
+ else cover(native, matchedConditions.slice(prefix), covered)
755
+
741
756
  resolutions++
757
+ } else {
758
+ missed.push(url)
742
759
  }
743
760
 
744
761
  next = resolver.next(resolved)
@@ -751,6 +768,35 @@ function* resolveImport(entry, specifier, condition, parentURL, imports, artifac
751
768
  resolutions++
752
769
  }
753
770
 
771
+ const uncovered =
772
+ native.length > 1 && resolutions > 0 ? native.filter((host) => !covered.has(host)) : []
773
+
774
+ // The WebAssembly fallback is resolved for the WebAssembly host, so it is
775
+ // also recorded for each native host that falls back to it, which would
776
+ // otherwise match the addon of another native host. Without one, those hosts
777
+ // are deferred or fail.
778
+ const substitute =
779
+ fallback !== null
780
+ ? exports.alias(fallback, opts)
781
+ : deferUnresolved
782
+ ? new URL(deferredProtocol + specifier)
783
+ : null
784
+
785
+ if (substitute !== null) {
786
+ for (const host of uncovered) {
787
+ addResolution(imports, specifier, [...matchedConditions, ...host.split('-')], substitute)
788
+ }
789
+ } else if (uncovered.length > 0) {
790
+ const hosts = uncovered.map((host) => `'${host}'`).join(', ')
791
+
792
+ let message = `Cannot find addon '${specifier}' imported from '${parentURL.href}' for ${uncovered.length === 1 ? 'host' : 'hosts'} ${hosts}`
793
+
794
+ message += '\nCandidates:'
795
+ message += '\n' + missed.map((url) => '- ' + url.href).join('\n')
796
+
797
+ throw errors.ADDON_NOT_FOUND(message, specifier, parentURL, missed)
798
+ }
799
+
754
800
  matchedConditions.pop()
755
801
 
756
802
  if (resolutions === 0) {
@@ -772,6 +818,20 @@ function* resolveImport(entry, specifier, condition, parentURL, imports, artifac
772
818
  }
773
819
  }
774
820
 
821
+ // A resolution covers the native hosts whose conditions start with its own,
822
+ // such as both architectures of a platform for a linked addon.
823
+ function cover(hosts, conditions, covered) {
824
+ for (const host of hosts) {
825
+ const parts = host.split('-')
826
+
827
+ if (conditions.every((condition, i) => parts[i] === condition)) covered.add(host)
828
+ }
829
+ }
830
+
831
+ function isWebAssemblyHost(host) {
832
+ return host.startsWith('wasi-')
833
+ }
834
+
775
835
  const ADDON_EXTENSION = /\.(bare|node|wasm)$/
776
836
 
777
837
  function importAttributes(lexed, specifier, imports) {
@@ -1380,7 +1440,11 @@ function addResolution(imports, specifier, conditions, url) {
1380
1440
 
1381
1441
  const last = conditions[conditions.length - 1]
1382
1442
 
1383
- current[last] = url.href
1443
+ // A resolution for fewer conditions than one already recorded, such as a
1444
+ // linked module for the platform of a host that another host has a prebuild
1445
+ // for, must not replace it.
1446
+ if (typeof current[last] === 'object') current[last].default = url.href
1447
+ else current[last] = url.href
1384
1448
 
1385
1449
  if ('default' in current) {
1386
1450
  const value = current.default
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bare-module-traverse",
3
- "version": "2.7.2",
3
+ "version": "2.7.4",
4
4
  "description": "Low-level module graph traversal for Bare",
5
5
  "exports": {
6
6
  ".": {
@@ -54,7 +54,7 @@
54
54
  },
55
55
  "homepage": "https://github.com/holepunchto/bare-module-traverse#readme",
56
56
  "dependencies": {
57
- "bare-addon-resolve": "^1.5.0",
57
+ "bare-addon-resolve": "^1.11.1",
58
58
  "bare-bundle": "^1.11.0",
59
59
  "bare-mime": "^1.0.0",
60
60
  "bare-module-lexer": "^1.6.0",