bare-module-traverse 2.6.0 → 2.7.0

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/index.d.ts CHANGED
@@ -3,9 +3,10 @@ import Buffer from 'bare-buffer'
3
3
  import {
4
4
  type ConditionalSpecifier,
5
5
  type ImportsMap,
6
- type ResolutionsMap
6
+ type ResolutionsMap,
7
+ type ResolveOptions as ModuleResolveOptions
7
8
  } from 'bare-module-resolve'
8
- import { type ResolveOptions, type Resolver } from 'bare-addon-resolve'
9
+ import { type ResolveOptions as AddonResolveOptions, type Resolver } from 'bare-addon-resolve'
9
10
  import { type Import, type Export } from 'bare-module-lexer'
10
11
 
11
12
  interface Dependency {
@@ -41,6 +42,8 @@ type AliasableExtension =
41
42
  | '.bin'
42
43
  | '.txt'
43
44
 
45
+ interface ResolveOptions extends ModuleResolveOptions, AddonResolveOptions {}
46
+
44
47
  interface TraverseOptions extends ResolveOptions {
45
48
  /**
46
49
  * The type to assume for a module that has no type of its own, such as one
package/index.js CHANGED
@@ -98,7 +98,7 @@ module.exports = exports = function traverse(
98
98
  }
99
99
 
100
100
  while (queue.length > 0 || deferred.length > 0) {
101
- yield* drive(queue.length > 0 ? queue.pop() : deferred.shift())
101
+ yield* drive(queue.length > 0 ? queue.shift() : deferred.shift())
102
102
  }
103
103
 
104
104
  return artifacts
@@ -160,7 +160,7 @@ module.exports = exports = function traverse(
160
160
  }
161
161
 
162
162
  while (queue.length > 0 || deferred.length > 0) {
163
- yield* drive(queue.length > 0 ? queue.pop() : deferred.shift())
163
+ yield* drive(queue.length > 0 ? queue.shift() : deferred.shift())
164
164
  }
165
165
 
166
166
  return artifacts
@@ -196,10 +196,13 @@ exports.module = function* (url, source, attributes, artifacts, visited, opts =
196
196
 
197
197
  if (opts.contexts === undefined) opts = { ...opts, contexts: new Map() }
198
198
  if (opts.addonContexts === undefined) opts = { ...opts, addonContexts: new Map() }
199
+ if (opts.resolvedImports === undefined) opts = { ...opts, resolvedImports: new Map() }
199
200
 
200
201
  // The host and WASI attributes set the context that the addons of the module
201
202
  // and everything it imports load in. A graph is walked again for each context
202
- // it is imported under, even where it was visited before.
203
+ // it is imported under, even where it was visited before. The conditions of
204
+ // the host are added to those that may be targeted, so that the order of the
205
+ // conditions in a package still decides between them and the native ones.
203
206
  if (attributes.host !== undefined || attributes.wasi !== undefined) {
204
207
  const { addonHost = null, addonWASI = null } = opts
205
208
 
@@ -209,7 +212,11 @@ exports.module = function* (url, source, attributes, artifacts, visited, opts =
209
212
  if (host !== addonHost || wasi !== addonWASI) {
210
213
  opts = { ...opts, addonHost: host, addonWASI: wasi }
211
214
 
212
- visited = visitedFor(opts.contexts, contextKey(host, wasi))
215
+ if (host !== addonHost) {
216
+ opts.conditions = withConditions(opts.conditions, host.split('-'))
217
+ }
218
+
219
+ visited = visitedFor(opts.contexts, host, wasi)
213
220
  }
214
221
  }
215
222
 
@@ -255,9 +262,16 @@ exports.module = function* (url, source, attributes, artifacts, visited, opts =
255
262
  }
256
263
  }
257
264
 
258
- if (resolutions) {
265
+ // A module resolves its imports once, however many contexts it is loaded in,
266
+ // so a context that reaches it after another walks what the other resolved.
267
+ // The addons that are reached are then checked against the context.
268
+ const resolved = opts.resolvedImports.get(url.href)
269
+
270
+ const preresolved = resolved === undefined ? resolutions : { [url.href]: resolved }
271
+
272
+ if (preresolved) {
259
273
  if (
260
- yield* exports.preresolved(url, source, attributes, resolutions, artifacts, visited, opts)
274
+ yield* exports.preresolved(url, source, attributes, preresolved, artifacts, visited, opts)
261
275
  ) {
262
276
  return true
263
277
  }
@@ -313,6 +327,10 @@ exports.module = function* (url, source, attributes, artifacts, visited, opts =
313
327
  }
314
328
  }
315
329
 
330
+ const compressed = compressImportsMap(imports)
331
+
332
+ opts.resolvedImports.set(url.href, compressed)
333
+
316
334
  yield {
317
335
  dependency: withWASI(
318
336
  {
@@ -320,7 +338,7 @@ exports.module = function* (url, source, attributes, artifacts, visited, opts =
320
338
  source,
321
339
  type,
322
340
  naturalType,
323
- imports: compressImportsMap(imports),
341
+ imports: compressed,
324
342
  lexer
325
343
  },
326
344
  opts
@@ -767,16 +785,22 @@ function addonHostForAttribute(host) {
767
785
  throw errors.UNKNOWN_ADDON_HOST(`Addon host '${host}' is not supported`)
768
786
  }
769
787
 
770
- function contextKey(host, wasi) {
771
- return JSON.stringify([host, wasi])
788
+ function withConditions(conditions = [], added) {
789
+ if (conditions.every((condition) => typeof condition === 'string')) {
790
+ return [...conditions, ...added]
791
+ }
792
+
793
+ return conditions.map((subset) => withConditions(subset, added))
772
794
  }
773
795
 
774
- function visitedFor(contexts, key) {
775
- let visited = contexts.get(key)
796
+ function visitedFor(contexts, host, wasi) {
797
+ const key = JSON.stringify([host, wasi])
798
+
799
+ let context = contexts.get(key)
776
800
 
777
- if (visited === undefined) contexts.set(key, (visited = new Set()))
801
+ if (context === undefined) contexts.set(key, (context = { host, wasi, visited: new Set() }))
778
802
 
779
- return visited
803
+ return context.visited
780
804
  }
781
805
 
782
806
  function withWASI(dependency, opts) {
@@ -0,0 +1,23 @@
1
+ // One set of conditions for each host, each with the targeted conditions. A
2
+ // host whose conditions are targeted in every set already has its resolutions,
3
+ // so it gets no set of its own.
4
+ module.exports = function conditions(base, hosts, targets) {
5
+ const subsets = leaves(targets)
6
+
7
+ const own = hosts.filter(
8
+ (host) =>
9
+ !subsets.every((subset) => host.split('-').every((condition) => subset.includes(condition)))
10
+ )
11
+
12
+ return (own.length > 0 ? own : hosts).flatMap((host) =>
13
+ subsets.map((subset) => [...base, ...host.split('-'), ...subset])
14
+ )
15
+ }
16
+
17
+ // Conditions nest to any depth and are tried depth first, so they match as
18
+ // their innermost lists would in order.
19
+ function leaves(conditions) {
20
+ if (conditions.every((condition) => typeof condition === 'string')) return [conditions]
21
+
22
+ return conditions.flatMap(leaves)
23
+ }
@@ -1,10 +1,17 @@
1
+ import URL from 'bare-url'
1
2
  import { type Import } from 'bare-module-lexer'
2
- import { type ResolveOptions, type Resolver } from 'bare-addon-resolve'
3
+ import { type Conditions, type ResolveOptions as ModuleResolveOptions } from 'bare-module-resolve'
4
+ import { type ResolveOptions as AddonResolveOptions, type Resolver } from 'bare-addon-resolve'
3
5
 
4
- interface BareResolveOptions extends ResolveOptions {
6
+ interface BareResolveOptions extends ModuleResolveOptions, AddonResolveOptions {
5
7
  linked?: boolean
6
8
  host?: string
7
9
  hosts?: string[]
10
+ /**
11
+ * The conditions that may be targeted in addition to those of each host,
12
+ * either a list or nested lists to try in turn.
13
+ */
14
+ conditions?: Conditions
8
15
  }
9
16
 
10
17
  /**
@@ -1,13 +1,19 @@
1
1
  const lex = require('bare-module-lexer')
2
2
  const resolve = require('../resolve')
3
3
  const runtime = require('../runtime')
4
+ const hostConditions = require('../conditions')
4
5
 
5
6
  module.exports = function (entry, parentURL, opts = {}) {
6
- const { linked = false, host = runtime.host, hosts = [host, 'wasi-wasm32'] } = opts
7
+ const {
8
+ linked = false,
9
+ host = runtime.host,
10
+ hosts = [host, 'wasi-wasm32'],
11
+ conditions: targets = []
12
+ } = opts
7
13
 
8
14
  let directories = false
9
15
  let extensions
10
- let conditions = hosts.map((host) => ['bare', 'node', ...host.split('-')])
16
+ let conditions = hostConditions(['bare', 'node'], hosts, targets)
11
17
 
12
18
  if (entry.type & lex.constants.ADDON) {
13
19
  extensions = linked ? [] : ['.bare', '.node']
@@ -1,5 +1,9 @@
1
+ import URL from 'bare-url'
1
2
  import { type Import } from 'bare-module-lexer'
2
- import { type ResolveOptions, type Resolver } from 'bare-addon-resolve'
3
+ import { type ResolveOptions as ModuleResolveOptions } from 'bare-module-resolve'
4
+ import { type ResolveOptions as AddonResolveOptions, type Resolver } from 'bare-addon-resolve'
5
+
6
+ interface ResolveOptions extends ModuleResolveOptions, AddonResolveOptions {}
3
7
 
4
8
  /**
5
9
  * @param entry - The import to resolve, as produced by `bare-module-lexer`.
@@ -1,9 +1,16 @@
1
+ import URL from 'bare-url'
1
2
  import { type Import } from 'bare-module-lexer'
2
- import { type ResolveOptions, type Resolver } from 'bare-addon-resolve'
3
+ import { type Conditions, type ResolveOptions as ModuleResolveOptions } from 'bare-module-resolve'
4
+ import { type ResolveOptions as AddonResolveOptions, type Resolver } from 'bare-addon-resolve'
3
5
 
4
- interface NodeResolveOptions extends ResolveOptions {
6
+ interface NodeResolveOptions extends ModuleResolveOptions, AddonResolveOptions {
5
7
  host?: string
6
8
  hosts?: string[]
9
+ /**
10
+ * The conditions that may be targeted in addition to those of each host,
11
+ * either a list or nested lists to try in turn.
12
+ */
13
+ conditions?: Conditions
7
14
  }
8
15
 
9
16
  /**
@@ -1,13 +1,14 @@
1
1
  const lex = require('bare-module-lexer')
2
2
  const resolve = require('../resolve')
3
3
  const runtime = require('../runtime')
4
+ const hostConditions = require('../conditions')
4
5
 
5
6
  module.exports = function (entry, parentURL, opts = {}) {
6
- const { host = runtime.host, hosts = [host] } = opts
7
+ const { host = runtime.host, hosts = [host], conditions: targets = [] } = opts
7
8
 
8
9
  let directories = false
9
10
  let extensions
10
- let conditions = hosts.map((host) => ['node', ...host.split('-')])
11
+ let conditions = hostConditions(['node'], hosts, targets)
11
12
 
12
13
  if (entry.type & lex.constants.ADDON) {
13
14
  extensions = ['.node']
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bare-module-traverse",
3
- "version": "2.6.0",
3
+ "version": "2.7.0",
4
4
  "description": "Low-level module graph traversal for Bare",
5
5
  "exports": {
6
6
  ".": {