bare-module-traverse 1.0.0 → 1.1.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/README.md +38 -1
- package/index.js +98 -33
- package/lib/errors.js +18 -0
- package/lib/resolve.js +66 -0
- package/lib/runtime/bare.js +3 -0
- package/lib/runtime/node.js +2 -0
- package/package.json +7 -1
package/README.md
CHANGED
|
@@ -50,6 +50,16 @@ for await (const dependency of traverse(new URL('file:///directory/file.js'), re
|
|
|
50
50
|
|
|
51
51
|
Traverse the module graph rooted at `url`, which must be a WHATWG `URL` instance. `readModule` is called with a `URL` instance for every module to be read and must either return the module source, if it exists, or `null`. `listPrefix` is called with a `URL` instance of every prefix to be listed and must return a list of `URL` instances that have the specified `URL` as a prefix. If not provided, prefixes won't be traversed. If one or both of `readModule` or `listPrefix` returns a promise, synchronous iteration is not supported.
|
|
52
52
|
|
|
53
|
+
Options include:
|
|
54
|
+
|
|
55
|
+
```js
|
|
56
|
+
{
|
|
57
|
+
resolve: resolve.default
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Options supported by <https://github.com/holepunchto/bare-module-resolve> and <https://github.com/holepunchto/bare-addon-resolve> may also be specified.
|
|
62
|
+
|
|
53
63
|
#### `for (const dependency of dependencies)`
|
|
54
64
|
|
|
55
65
|
Synchronously iterate the module graph. Each yielded dependency has the following shape:
|
|
@@ -68,6 +78,28 @@ Synchronously iterate the module graph. Each yielded dependency has the followin
|
|
|
68
78
|
|
|
69
79
|
Asynchronously iterate the module graph. If one or both of `readModule` or `listPrefix` returns promises, these will be awaited. The same comments as `for (const dependency of dependencies)` apply.
|
|
70
80
|
|
|
81
|
+
### Resolution
|
|
82
|
+
|
|
83
|
+
#### `resolve.module`
|
|
84
|
+
|
|
85
|
+
Convenience export from <https://github.com/holepunchto/bare-module-resolve>.
|
|
86
|
+
|
|
87
|
+
#### `resolve.addon`
|
|
88
|
+
|
|
89
|
+
Convenience export from <https://github.com/holepunchto/bare-addon-resolve>.
|
|
90
|
+
|
|
91
|
+
#### `resolve.default`
|
|
92
|
+
|
|
93
|
+
The default resolver, which simply forwards to <https://github.com/holepunchto/bare-module-resolve> and <https://github.com/holepunchto/bare-addon-resolve> with the literal options passed by the caller.
|
|
94
|
+
|
|
95
|
+
#### `resolve.bare`
|
|
96
|
+
|
|
97
|
+
The Bare resolver, which matches the options used by the Bare module system.
|
|
98
|
+
|
|
99
|
+
#### `resolve.node`
|
|
100
|
+
|
|
101
|
+
The Node.js resolver, which matches the options used by the Node.js module system.
|
|
102
|
+
|
|
71
103
|
### Algorithm
|
|
72
104
|
|
|
73
105
|
The following generator functions implement the traversal algorithm. To drive the generator functions, a loop like the following can be used:
|
|
@@ -106,13 +138,18 @@ while (queue.length > 0) {
|
|
|
106
138
|
|
|
107
139
|
Options are the same as `traverse()` for all functions.
|
|
108
140
|
|
|
141
|
+
> [!WARNING]
|
|
142
|
+
> These functions are currently subject to change between minor releases. If using them directly, make sure to specify a tilde range (`~1.2.3`) when declaring the module dependency.
|
|
143
|
+
|
|
109
144
|
#### `const generator = traverse.module(url, source, artifacts, visited[, options])`
|
|
110
145
|
|
|
111
146
|
#### `const generator = traverse.package(url, source, artifacts, visited[, options])`
|
|
112
147
|
|
|
113
148
|
#### `const generator = traverse.preresolved(url, source, resolutions, artifacts, visited[, options])`
|
|
114
149
|
|
|
115
|
-
#### `const generator = traverse.imports(
|
|
150
|
+
#### `const generator = traverse.imports(parentURL, source, imports, artifacts, visited[, options])`
|
|
151
|
+
|
|
152
|
+
#### `const generator = traverse.prebuilds(packageURL, artifacts, visited[, options])`
|
|
116
153
|
|
|
117
154
|
#### `const generator = traverse.assets(patterns, parentURL, artifacts, visited[, options])`
|
|
118
155
|
|
package/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
const { lookupPackageScope } = require('bare-module-resolve')
|
|
2
|
+
const { lookupPrebuildsScope } = require('bare-addon-resolve')
|
|
2
3
|
const lex = require('bare-module-lexer')
|
|
3
4
|
const resolve = require('./lib/resolve')
|
|
5
|
+
const errors = require('./lib/errors')
|
|
4
6
|
|
|
5
7
|
module.exports = exports = function traverse (entry, opts, readModule, listPrefix) {
|
|
6
8
|
if (typeof opts === 'function') {
|
|
@@ -15,9 +17,9 @@ module.exports = exports = function traverse (entry, opts, readModule, listPrefi
|
|
|
15
17
|
|
|
16
18
|
return {
|
|
17
19
|
* [Symbol.iterator] () {
|
|
18
|
-
const artifacts =
|
|
20
|
+
const artifacts = { addons: [], assets: [] }
|
|
19
21
|
|
|
20
|
-
const queue = [exports.module(entry,
|
|
22
|
+
const queue = [exports.module(entry, null, artifacts, new Set(), opts)]
|
|
21
23
|
|
|
22
24
|
while (queue.length > 0) {
|
|
23
25
|
const generator = queue.pop()
|
|
@@ -44,9 +46,9 @@ module.exports = exports = function traverse (entry, opts, readModule, listPrefi
|
|
|
44
46
|
},
|
|
45
47
|
|
|
46
48
|
async * [Symbol.asyncIterator] () {
|
|
47
|
-
const artifacts =
|
|
49
|
+
const artifacts = { addons: [], assets: [] }
|
|
48
50
|
|
|
49
|
-
const queue = [exports.module(entry,
|
|
51
|
+
const queue = [exports.module(entry, null, artifacts, new Set(), opts)]
|
|
50
52
|
|
|
51
53
|
while (queue.length > 0) {
|
|
52
54
|
const generator = queue.pop()
|
|
@@ -78,19 +80,27 @@ function defaultListPrefix () {
|
|
|
78
80
|
return []
|
|
79
81
|
}
|
|
80
82
|
|
|
81
|
-
function
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
83
|
+
function addURL (array, url) {
|
|
84
|
+
let lo = 0
|
|
85
|
+
let hi = array.length - 1
|
|
86
|
+
|
|
87
|
+
while (lo <= hi) {
|
|
88
|
+
const mid = lo + ((hi - lo) >> 1)
|
|
89
|
+
const found = array[mid]
|
|
90
|
+
|
|
91
|
+
if (found.href === url.href) return
|
|
92
|
+
|
|
93
|
+
if (found.href < url.href) {
|
|
94
|
+
lo = mid + 1
|
|
95
|
+
} else {
|
|
96
|
+
hi = mid - 1
|
|
97
|
+
}
|
|
86
98
|
}
|
|
87
|
-
}
|
|
88
99
|
|
|
89
|
-
|
|
90
|
-
return { addons: [], assets: [] }
|
|
100
|
+
array.splice(lo, 0, url)
|
|
91
101
|
}
|
|
92
102
|
|
|
93
|
-
function
|
|
103
|
+
function removeURL (array, url) {
|
|
94
104
|
let lo = 0
|
|
95
105
|
let hi = array.length - 1
|
|
96
106
|
|
|
@@ -98,7 +108,7 @@ function addURL (array, url) {
|
|
|
98
108
|
const mid = lo + ((hi - lo) >> 1)
|
|
99
109
|
const found = array[mid]
|
|
100
110
|
|
|
101
|
-
if (found.href === url.href)
|
|
111
|
+
if (found.href === url.href) break
|
|
102
112
|
|
|
103
113
|
if (found.href < url.href) {
|
|
104
114
|
lo = mid + 1
|
|
@@ -107,7 +117,7 @@ function addURL (array, url) {
|
|
|
107
117
|
}
|
|
108
118
|
}
|
|
109
119
|
|
|
110
|
-
array.splice(lo,
|
|
120
|
+
if (array[lo].href === url.href) array.splice(lo, 1)
|
|
111
121
|
}
|
|
112
122
|
|
|
113
123
|
exports.resolve = resolve
|
|
@@ -117,6 +127,14 @@ exports.module = function * (url, source, artifacts, visited, opts = {}) {
|
|
|
117
127
|
|
|
118
128
|
if (visited.has(url.href)) return false
|
|
119
129
|
|
|
130
|
+
if (source === null) {
|
|
131
|
+
source = yield { module: url }
|
|
132
|
+
|
|
133
|
+
if (source === null) {
|
|
134
|
+
throw errors.MODULE_NOT_FOUND(`Cannot find module '${url.href}'`)
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
120
138
|
visited.add(url.href)
|
|
121
139
|
|
|
122
140
|
if (resolutions) {
|
|
@@ -154,6 +172,10 @@ exports.package = function * (url, source, artifacts, visited, opts = {}) {
|
|
|
154
172
|
if (info) {
|
|
155
173
|
yield { dependency: { url, source, imports: {} } }
|
|
156
174
|
|
|
175
|
+
if (info.addon) {
|
|
176
|
+
yield { children: exports.prebuilds(url, artifacts, visited, opts) }
|
|
177
|
+
}
|
|
178
|
+
|
|
157
179
|
if (info.assets) {
|
|
158
180
|
yield { children: exports.assets(info.assets, url, artifacts, visited, opts) }
|
|
159
181
|
}
|
|
@@ -177,14 +199,11 @@ exports.preresolved = function * (url, source, resolutions, artifacts, visited,
|
|
|
177
199
|
|
|
178
200
|
if (typeof entry === 'string') {
|
|
179
201
|
const url = new URL(entry)
|
|
180
|
-
const source = yield { module: url }
|
|
181
|
-
|
|
182
|
-
if (source === null) continue
|
|
183
202
|
|
|
184
203
|
if (specifier === '#package') {
|
|
185
|
-
yield { children: exports.package(url,
|
|
204
|
+
yield { children: exports.package(url, null, artifacts, visited, opts) }
|
|
186
205
|
} else {
|
|
187
|
-
yield { children: exports.module(url,
|
|
206
|
+
yield { children: exports.module(url, null, artifacts, visited, opts) }
|
|
188
207
|
}
|
|
189
208
|
} else {
|
|
190
209
|
stack.unshift(...Object.values(entry))
|
|
@@ -197,13 +216,16 @@ exports.preresolved = function * (url, source, resolutions, artifacts, visited,
|
|
|
197
216
|
return true
|
|
198
217
|
}
|
|
199
218
|
|
|
200
|
-
exports.imports = function * (
|
|
201
|
-
const { resolve =
|
|
219
|
+
exports.imports = function * (parentURL, source, imports, artifacts, visited, opts = {}) {
|
|
220
|
+
const { resolve = exports.resolve.default } = opts
|
|
221
|
+
|
|
222
|
+
let yielded = false
|
|
202
223
|
|
|
203
224
|
for (const entry of lex(source).imports) {
|
|
204
|
-
const resolver = resolve(entry,
|
|
225
|
+
const resolver = resolve(entry, parentURL, opts)
|
|
205
226
|
|
|
206
227
|
let next = resolver.next()
|
|
228
|
+
let resolved = false
|
|
207
229
|
|
|
208
230
|
while (next.done !== true) {
|
|
209
231
|
const value = next.value
|
|
@@ -232,22 +254,51 @@ exports.imports = function * (url, source, imports, artifacts, visited, opts = {
|
|
|
232
254
|
|
|
233
255
|
yield { children: exports.module(url, source, artifacts, visited, opts) }
|
|
234
256
|
|
|
257
|
+
resolved = yielded = true
|
|
258
|
+
|
|
235
259
|
break
|
|
236
260
|
}
|
|
237
261
|
|
|
238
262
|
next = resolver.next()
|
|
239
263
|
}
|
|
240
264
|
}
|
|
265
|
+
|
|
266
|
+
if (!resolved) {
|
|
267
|
+
throw errors.MODULE_NOT_FOUND(`Cannot find module '${entry.specifier}' imported from '${parentURL.href}'`)
|
|
268
|
+
}
|
|
241
269
|
}
|
|
270
|
+
|
|
271
|
+
return yielded
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
exports.prebuilds = function * (packageURL, artifacts, visited, opts = {}) {
|
|
275
|
+
const [prefix = null] = lookupPrebuildsScope(packageURL, opts)
|
|
276
|
+
|
|
277
|
+
if (prefix === null) return false
|
|
278
|
+
|
|
279
|
+
let yielded = false
|
|
280
|
+
|
|
281
|
+
for (const url of yield { prefix }) {
|
|
282
|
+
const source = yield { module: url }
|
|
283
|
+
|
|
284
|
+
if (source !== null) {
|
|
285
|
+
addURL(artifacts.addons, url)
|
|
286
|
+
|
|
287
|
+
yield { children: exports.module(url, source, artifacts, visited, opts) }
|
|
288
|
+
|
|
289
|
+
yielded = true
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return yielded
|
|
242
294
|
}
|
|
243
295
|
|
|
244
296
|
exports.assets = function * (patterns, parentURL, artifacts, visited, opts = {}) {
|
|
245
|
-
const matches = yield * exports.
|
|
297
|
+
const matches = yield * exports.patternMatches(patterns, parentURL, [], opts)
|
|
246
298
|
|
|
247
299
|
let yielded = false
|
|
248
300
|
|
|
249
|
-
for (const
|
|
250
|
-
const url = new URL(href)
|
|
301
|
+
for (const url of matches) {
|
|
251
302
|
const source = yield { module: url }
|
|
252
303
|
|
|
253
304
|
if (source !== null) {
|
|
@@ -262,10 +313,10 @@ exports.assets = function * (patterns, parentURL, artifacts, visited, opts = {})
|
|
|
262
313
|
return yielded
|
|
263
314
|
}
|
|
264
315
|
|
|
265
|
-
exports.
|
|
266
|
-
const
|
|
316
|
+
exports.patternMatches = function * (pattern, parentURL, matches, opts = {}) {
|
|
317
|
+
const { conditions = [] } = opts
|
|
267
318
|
|
|
268
|
-
|
|
319
|
+
if (typeof pattern === 'string') {
|
|
269
320
|
let patternNegate = false
|
|
270
321
|
let patternBase
|
|
271
322
|
let patternTrailer
|
|
@@ -289,12 +340,26 @@ exports.matches = function * (patterns, parentURL) {
|
|
|
289
340
|
|
|
290
341
|
for (const url of yield { prefix }) {
|
|
291
342
|
if (patternIndex === -1) {
|
|
292
|
-
if (patternNegate) matches
|
|
293
|
-
else matches
|
|
343
|
+
if (patternNegate) removeURL(matches, url)
|
|
344
|
+
else addURL(matches, url)
|
|
294
345
|
} else if (patternTrailer === '' || url.href.endsWith(patternTrailer)) {
|
|
295
|
-
matches
|
|
346
|
+
addURL(matches, url)
|
|
296
347
|
} else if (patternNegate) {
|
|
297
|
-
matches
|
|
348
|
+
removeURL(matches, url)
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
} else if (Array.isArray(pattern)) {
|
|
352
|
+
for (const patternValue of pattern) {
|
|
353
|
+
yield * exports.patternMatches(patternValue, parentURL, matches, opts)
|
|
354
|
+
}
|
|
355
|
+
} else if (typeof pattern === 'object' && pattern !== null) {
|
|
356
|
+
const keys = Object.keys(pattern)
|
|
357
|
+
|
|
358
|
+
for (const p of keys) {
|
|
359
|
+
if (p === 'default' || conditions.includes(p)) {
|
|
360
|
+
const patternValue = pattern[p]
|
|
361
|
+
|
|
362
|
+
return yield * exports.patternMatches(patternValue, parentURL, matches, opts)
|
|
298
363
|
}
|
|
299
364
|
}
|
|
300
365
|
}
|
package/lib/errors.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module.exports = class ModuleTraverseError extends Error {
|
|
2
|
+
constructor (msg, code, fn = ModuleTraverseError) {
|
|
3
|
+
super(`${code}: ${msg}`)
|
|
4
|
+
this.code = code
|
|
5
|
+
|
|
6
|
+
if (Error.captureStackTrace) {
|
|
7
|
+
Error.captureStackTrace(this, fn)
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
get name () {
|
|
12
|
+
return 'ModuleTraverseError'
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
static MODULE_NOT_FOUND (msg) {
|
|
16
|
+
return new ModuleTraverseError(msg, 'MODULE_NOT_FOUND', ModuleTraverseError.MODULE_NOT_FOUND)
|
|
17
|
+
}
|
|
18
|
+
}
|
package/lib/resolve.js
CHANGED
|
@@ -1,2 +1,68 @@
|
|
|
1
|
+
const lex = require('bare-module-lexer')
|
|
2
|
+
|
|
1
3
|
exports.module = require('bare-module-resolve').module
|
|
2
4
|
exports.addon = require('bare-addon-resolve').addon
|
|
5
|
+
|
|
6
|
+
exports.default = function resolve (entry, parentURL, opts) {
|
|
7
|
+
if (entry.type & lex.constants.ADDON) {
|
|
8
|
+
return exports.addon(entry.specifier, parentURL, opts)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return exports.module(entry.specifier, parentURL, opts)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
exports.bare = function resolve (entry, parentURL, opts = {}) {
|
|
15
|
+
const runtime = require('#runtime')
|
|
16
|
+
|
|
17
|
+
const {
|
|
18
|
+
platform = runtime.platform,
|
|
19
|
+
arch = runtime.arch,
|
|
20
|
+
simulator = false
|
|
21
|
+
} = opts
|
|
22
|
+
|
|
23
|
+
let extensions
|
|
24
|
+
let conditions = ['bare', 'node', platform, arch]
|
|
25
|
+
|
|
26
|
+
if (simulator) conditions = [...conditions, 'simulator']
|
|
27
|
+
|
|
28
|
+
if (entry.type & lex.constants.ADDON) {
|
|
29
|
+
extensions = ['.bare', '.node']
|
|
30
|
+
conditions = ['addon', ...conditions]
|
|
31
|
+
|
|
32
|
+
return exports.addon(entry.specifier, parentURL, { extensions, conditions, ...opts })
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (entry.type & lex.constants.ASSET) {
|
|
36
|
+
conditions = ['asset', ...conditions]
|
|
37
|
+
} else {
|
|
38
|
+
extensions = ['.js', '.cjs', '.mjs', '.json', '.bare', '.node']
|
|
39
|
+
|
|
40
|
+
if (entry.type & lex.constants.REQUIRE) {
|
|
41
|
+
conditions = ['require', ...conditions]
|
|
42
|
+
} else if (entry.type & lex.constants.IMPORT) {
|
|
43
|
+
conditions = ['import', ...conditions]
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return exports.module(entry.specifier, parentURL, { extensions, conditions, ...opts })
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
exports.node = function resolve (entry, parentURL, opts) {
|
|
51
|
+
let extensions
|
|
52
|
+
let conditions
|
|
53
|
+
|
|
54
|
+
if (entry.type & lex.constants.ADDON) {
|
|
55
|
+
extensions = ['.node']
|
|
56
|
+
|
|
57
|
+
return exports.addon(entry.specifier, parentURL, { extensions, conditions, ...opts })
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (entry.type & lex.constants.REQUIRE) {
|
|
61
|
+
extensions = ['.js', '.json', '.node']
|
|
62
|
+
conditions = ['node', 'require']
|
|
63
|
+
} else if (entry.type & lex.constants.IMPORT) {
|
|
64
|
+
conditions = ['node', 'import']
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return exports.module(entry.specifier, parentURL, { extensions, conditions, ...opts })
|
|
68
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bare-module-traverse",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Low-level module graph traversal for Bare",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./index.js",
|
|
@@ -11,6 +11,12 @@
|
|
|
11
11
|
"index.js",
|
|
12
12
|
"lib"
|
|
13
13
|
],
|
|
14
|
+
"imports": {
|
|
15
|
+
"#runtime": {
|
|
16
|
+
"bare": "./lib/runtime/bare.js",
|
|
17
|
+
"node": "./lib/runtime/node.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
14
20
|
"scripts": {
|
|
15
21
|
"test": "standard && bare test.js"
|
|
16
22
|
},
|