bare-module-traverse 2.5.3 → 2.5.5
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 +3 -0
- package/index.d.ts +14 -5
- package/index.js +79 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -128,6 +128,9 @@ next.value = {
|
|
|
128
128
|
url: URL,
|
|
129
129
|
source: 'string' | Buffer,
|
|
130
130
|
type: constants.SCRIPT,
|
|
131
|
+
// The type the module has on its own, ignoring import attributes, or 0 if
|
|
132
|
+
// it has no type of its own.
|
|
133
|
+
naturalType: constants.SCRIPT,
|
|
131
134
|
imports: {
|
|
132
135
|
// See https://github.com/holepunchto/bare-module#imports
|
|
133
136
|
},
|
package/index.d.ts
CHANGED
|
@@ -11,7 +11,15 @@ import { type Import, type Export } from 'bare-module-lexer'
|
|
|
11
11
|
interface Dependency {
|
|
12
12
|
url: URL
|
|
13
13
|
source: string | Buffer
|
|
14
|
+
/** The type the module is loaded as. See `constants` for possible values. */
|
|
14
15
|
type: number
|
|
16
|
+
/**
|
|
17
|
+
* The type the module has on its own, ignoring import attributes, or `0` if
|
|
18
|
+
* it has no type of its own. This differs from `type` only when an import
|
|
19
|
+
* attribute asked for a different type, so a loader can use it to tell
|
|
20
|
+
* whether an attribute changed the type.
|
|
21
|
+
*/
|
|
22
|
+
naturalType: number
|
|
15
23
|
imports: ImportsMap
|
|
16
24
|
lexer: {
|
|
17
25
|
imports: Import[]
|
|
@@ -35,15 +43,16 @@ type AliasableExtension =
|
|
|
35
43
|
|
|
36
44
|
interface TraverseOptions extends ResolveOptions {
|
|
37
45
|
/**
|
|
38
|
-
* The type
|
|
39
|
-
* ambiguous extension or a `data:` URL that no import reaches. See
|
|
46
|
+
* The type to assume for a module that has no type of its own, such as one
|
|
47
|
+
* with an ambiguous extension or a `data:` URL that no import reaches. See
|
|
40
48
|
* `constants` for possible values.
|
|
41
49
|
*/
|
|
42
50
|
defaultType?: number
|
|
43
51
|
/**
|
|
44
|
-
* The type of the import that
|
|
45
|
-
* takes its type from this: `REQUIRE`
|
|
46
|
-
* while `IMPORT | DYNAMIC`
|
|
52
|
+
* The type of the import that led to the entry. A JavaScript `data:` URL
|
|
53
|
+
* takes its type from this: `REQUIRE` means a script and `IMPORT` a module,
|
|
54
|
+
* while `IMPORT | DYNAMIC` could mean either and so needs a `type`
|
|
55
|
+
* attribute.
|
|
47
56
|
*/
|
|
48
57
|
importType?: number
|
|
49
58
|
artifacts?: boolean
|
package/index.js
CHANGED
|
@@ -192,9 +192,19 @@ exports.alias = function alias(url, opts = {}) {
|
|
|
192
192
|
}
|
|
193
193
|
|
|
194
194
|
exports.module = function* (url, source, attributes, artifacts, visited, opts = {}) {
|
|
195
|
-
const { resolutions = null, asset = false, probed } = opts
|
|
195
|
+
const { resolutions = null, asset = false, probed, types } = opts
|
|
196
196
|
|
|
197
|
-
|
|
197
|
+
attributes = attributes || {}
|
|
198
|
+
|
|
199
|
+
if (visited.has(url.href)) {
|
|
200
|
+
// An asset is only read for its bytes, so it doesn't care what type the
|
|
201
|
+
// module is imported as elsewhere.
|
|
202
|
+
if (asset === false && types !== undefined) {
|
|
203
|
+
assertTypeAgrees(url, attributes, types.get(url.href), opts)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return false
|
|
207
|
+
}
|
|
198
208
|
|
|
199
209
|
visited.add(url.href)
|
|
200
210
|
|
|
@@ -202,8 +212,7 @@ exports.module = function* (url, source, attributes, artifacts, visited, opts =
|
|
|
202
212
|
|
|
203
213
|
if (opts.packages === undefined) opts = { ...opts, packages: new Map() }
|
|
204
214
|
if (opts.prefixes === undefined) opts = { ...opts, prefixes: new Map() }
|
|
205
|
-
|
|
206
|
-
attributes = attributes || {}
|
|
215
|
+
if (opts.types === undefined) opts = { ...opts, types: new Map() }
|
|
207
216
|
|
|
208
217
|
const artifact = asset === true || moduleType(url, attributes, null, opts) === constants.ADDON
|
|
209
218
|
|
|
@@ -264,6 +273,9 @@ exports.module = function* (url, source, attributes, artifacts, visited, opts =
|
|
|
264
273
|
}
|
|
265
274
|
|
|
266
275
|
const type = moduleType(url, attributes, info, opts)
|
|
276
|
+
const naturalType = naturalModuleType(url, attributes, info, type, opts)
|
|
277
|
+
|
|
278
|
+
if (asset === false) opts.types.set(url.href, { type, asserted: attributes.type, info })
|
|
267
279
|
|
|
268
280
|
const lexer = { imports: [], exports: [] }
|
|
269
281
|
|
|
@@ -283,6 +295,7 @@ exports.module = function* (url, source, attributes, artifacts, visited, opts =
|
|
|
283
295
|
url: exports.alias(url, opts),
|
|
284
296
|
source,
|
|
285
297
|
type,
|
|
298
|
+
naturalType,
|
|
286
299
|
imports: compressImportsMap(imports),
|
|
287
300
|
lexer
|
|
288
301
|
}
|
|
@@ -310,6 +323,7 @@ exports.package = function* (url, source, artifacts, visited, opts = {}) {
|
|
|
310
323
|
url,
|
|
311
324
|
source,
|
|
312
325
|
type: constants.JSON,
|
|
326
|
+
naturalType: constants.JSON,
|
|
313
327
|
imports: {},
|
|
314
328
|
lexer: { imports: [], exports: [] }
|
|
315
329
|
}
|
|
@@ -392,7 +406,10 @@ exports.preresolved = function* (url, source, resolutions, artifacts, visited, o
|
|
|
392
406
|
const lexer = { imports: [], exports: [] }
|
|
393
407
|
|
|
394
408
|
if (type === constants.SCRIPT || type === constants.MODULE) {
|
|
395
|
-
|
|
409
|
+
const lexed = lex(source)
|
|
410
|
+
|
|
411
|
+
lexer.imports = lexed.imports
|
|
412
|
+
lexer.exports = lexed.exports
|
|
396
413
|
}
|
|
397
414
|
|
|
398
415
|
yield {
|
|
@@ -400,6 +417,7 @@ exports.preresolved = function* (url, source, resolutions, artifacts, visited, o
|
|
|
400
417
|
url: exports.alias(url, opts),
|
|
401
418
|
source,
|
|
402
419
|
type,
|
|
420
|
+
naturalType: type,
|
|
403
421
|
imports: compressImportsMap(imports),
|
|
404
422
|
lexer
|
|
405
423
|
}
|
|
@@ -810,6 +828,17 @@ function* postresolve(url) {
|
|
|
810
828
|
return (yield { resolution: url }) || url
|
|
811
829
|
}
|
|
812
830
|
|
|
831
|
+
// The type a module has on its own, ignoring import attributes. A JavaScript
|
|
832
|
+
// data: URL has no type of its own, so this returns 0; its type depends on how
|
|
833
|
+
// it is imported.
|
|
834
|
+
function naturalModuleType(url, attributes, info, type, opts) {
|
|
835
|
+
if (attributes.type === undefined) return type
|
|
836
|
+
|
|
837
|
+
if (url.protocol === 'data:') return 0
|
|
838
|
+
|
|
839
|
+
return moduleType(url, {}, info, opts)
|
|
840
|
+
}
|
|
841
|
+
|
|
813
842
|
function moduleType(url, attributes, info, opts = {}) {
|
|
814
843
|
const { defaultType = constants.SCRIPT, aliases = null } = opts
|
|
815
844
|
|
|
@@ -857,6 +886,46 @@ function moduleType(url, attributes, info, opts = {}) {
|
|
|
857
886
|
return defaultType
|
|
858
887
|
}
|
|
859
888
|
|
|
889
|
+
// A URL has a single type within a graph, and the first import to reach it
|
|
890
|
+
// decides what that is. Later imports have to agree, so an attribute on one
|
|
891
|
+
// import cannot quietly change the type another import sees.
|
|
892
|
+
function assertTypeAgrees(url, attributes, recorded, opts) {
|
|
893
|
+
if (recorded === undefined) return
|
|
894
|
+
if (attributes.type === recorded.asserted) return
|
|
895
|
+
|
|
896
|
+
const expected =
|
|
897
|
+
typeof attributes.type === 'string'
|
|
898
|
+
? typeForAttribute(attributes.type)
|
|
899
|
+
: moduleType(url, {}, recorded.info, opts)
|
|
900
|
+
|
|
901
|
+
if (expected === recorded.type) return
|
|
902
|
+
|
|
903
|
+
throw errors.TYPE_INCOMPATIBLE(
|
|
904
|
+
`Module '${url.href}' is already of type '${attributeForType(recorded.type)}' in the graph`
|
|
905
|
+
)
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
function attributeForType(type) {
|
|
909
|
+
switch (type) {
|
|
910
|
+
case constants.SCRIPT:
|
|
911
|
+
return 'script'
|
|
912
|
+
case constants.MODULE:
|
|
913
|
+
return 'module'
|
|
914
|
+
case constants.JSON:
|
|
915
|
+
return 'json'
|
|
916
|
+
case constants.BUNDLE:
|
|
917
|
+
return 'bundle'
|
|
918
|
+
case constants.ADDON:
|
|
919
|
+
return 'addon'
|
|
920
|
+
case constants.BINARY:
|
|
921
|
+
return 'binary'
|
|
922
|
+
case constants.TEXT:
|
|
923
|
+
return 'text'
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
return 'unknown'
|
|
927
|
+
}
|
|
928
|
+
|
|
860
929
|
function typeForAttribute(type) {
|
|
861
930
|
switch (type) {
|
|
862
931
|
case 'script':
|
|
@@ -918,11 +987,11 @@ function dataURLModuleType(url, attributes, opts = {}) {
|
|
|
918
987
|
return type
|
|
919
988
|
}
|
|
920
989
|
|
|
921
|
-
// A data URL
|
|
922
|
-
// systems, so the type follows how the module was
|
|
923
|
-
// script and `import` a module. A dynamic `import()`
|
|
924
|
-
// say which
|
|
925
|
-
//
|
|
990
|
+
// A data URL has no extension, and 'text/javascript' covers both module
|
|
991
|
+
// systems, so the type follows how the module was imported: `require()` means a
|
|
992
|
+
// script and `import` a module. A dynamic `import()` could mean either, so it
|
|
993
|
+
// has to say which. When there is no import to read at all, `defaultType`
|
|
994
|
+
// decides.
|
|
926
995
|
function javaScriptDataURLModuleType(url, opts) {
|
|
927
996
|
const { defaultType = constants.SCRIPT, importType = 0 } = opts
|
|
928
997
|
|