bare-module-traverse 2.4.1 → 2.4.3

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 CHANGED
@@ -72,6 +72,8 @@ options = {
72
72
  }
73
73
  ```
74
74
 
75
+ When a module URL uses the `data:` protocol, its source is decoded directly from the specifier rather than read via `readModule()`, so no source module effect is emitted for it. base64 encoded data is decoded to a `Buffer`, other data is percent-decoded to a string, and the module type is derived from the media type (`text/javascript` and `application/javascript` map to a script or module, `application/json` to JSON, and anything else to `defaultType`). A JavaScript `data:` URL inherits the type of the module that imports it, so it is a script when imported from a script and a module when imported from a module, falling back to `defaultType` when it has no referrer, such as a `data:` entry. Only the UTF-8 charset is supported; a `data:` URL specifying any other charset throws.
76
+
75
77
  `visited` is a `Set` of already visited module hrefs. If provided, modules whose href is already in the set are skipped and the set is updated in place as traversal proceeds. This allows a single set to be shared across several traversals so that a later traversal, such as one rooted at a dynamically imported module, does not revisit modules already seen by an earlier one.
76
78
 
77
79
  Options supported by <https://github.com/holepunchto/bare-module-resolve> and <https://github.com/holepunchto/bare-addon-resolve> may also be specified.
package/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  const { lookupPackageScope, conditionMatches } = require('bare-module-resolve')
2
2
  const lex = require('bare-module-lexer')
3
+ const MIME = require('bare-mime')
3
4
  const resolve = require('./lib/resolve')
4
5
  const errors = require('./lib/errors')
5
6
 
@@ -196,16 +197,20 @@ exports.module = function* (url, source, attributes, artifacts, visited, opts =
196
197
  const artifact = asset === true || moduleType(url, attributes, null, opts) === constants.ADDON
197
198
 
198
199
  if (source === null) {
199
- const exists = probed !== undefined ? probed : artifact ? yield { probe: url } : undefined
200
+ if (url.protocol === 'data:') {
201
+ source = decodeDataURL(url)
202
+ } else {
203
+ const exists = probed !== undefined ? probed : artifact ? yield { probe: url } : undefined
200
204
 
201
- if (exists === false) {
202
- throw errors.MODULE_NOT_FOUND(`Cannot find module '${url.href}'`, url.href)
203
- }
205
+ if (exists === false) {
206
+ throw errors.MODULE_NOT_FOUND(`Cannot find module '${url.href}'`, url.href)
207
+ }
204
208
 
205
- source = yield { module: url, artifact }
209
+ source = yield { module: url, artifact }
206
210
 
207
- if (exists !== true && source === null) {
208
- throw errors.MODULE_NOT_FOUND(`Cannot find module '${url.href}'`, url.href)
211
+ if (exists !== true && source === null) {
212
+ throw errors.MODULE_NOT_FOUND(`Cannot find module '${url.href}'`, url.href)
213
+ }
209
214
  }
210
215
  }
211
216
 
@@ -219,20 +224,22 @@ exports.module = function* (url, source, attributes, artifacts, visited, opts =
219
224
 
220
225
  let info = null
221
226
 
222
- for (const packageURL of lookupPackageScope(url, opts)) {
223
- const source = yield { module: packageURL, artifact: false }
227
+ if (url.protocol !== 'data:') {
228
+ for (const packageURL of lookupPackageScope(url, opts)) {
229
+ const source = yield { module: packageURL, artifact: false }
224
230
 
225
- if (source !== null) {
226
- info = JSON.parse(source)
231
+ if (source !== null) {
232
+ info = JSON.parse(source)
227
233
 
228
- imports['#package'] = packageURL.href
234
+ imports['#package'] = packageURL.href
229
235
 
230
- yield {
231
- children: exports.package(packageURL, source, artifacts, visited, opts),
232
- deferred: false
233
- }
236
+ yield {
237
+ children: exports.package(packageURL, source, artifacts, visited, opts),
238
+ deferred: false
239
+ }
234
240
 
235
- break
241
+ break
242
+ }
236
243
  }
237
244
  }
238
245
 
@@ -255,7 +262,10 @@ exports.module = function* (url, source, attributes, artifacts, visited, opts =
255
262
 
256
263
  if (asset === false) {
257
264
  if (type === constants.SCRIPT || type === constants.MODULE) {
258
- yield* exports.imports(url, source, imports, artifacts, lexer, visited, opts)
265
+ yield* exports.imports(url, source, imports, artifacts, lexer, visited, {
266
+ ...opts,
267
+ referrerType: type
268
+ })
259
269
  } else if (type === constants.ADDON) {
260
270
  yield* exports.addons(url, artifacts, visited, opts)
261
271
  }
@@ -322,6 +332,8 @@ exports.preresolved = function* (url, source, resolutions, artifacts, visited, o
322
332
 
323
333
  if (typeof imports !== 'object' || imports === null) return false
324
334
 
335
+ const type = moduleType(url, {}, null, opts)
336
+
325
337
  for (const [specifier, entry] of Object.entries(imports)) {
326
338
  const stack = [{ entry, asset: false }]
327
339
 
@@ -342,7 +354,8 @@ exports.preresolved = function* (url, source, resolutions, artifacts, visited, o
342
354
  yield {
343
355
  children: exports.module(url, null, {}, artifacts, visited, {
344
356
  ...opts,
345
- asset: true
357
+ asset: true,
358
+ referrerType: type
346
359
  }),
347
360
  deferred: true
348
361
  }
@@ -352,7 +365,10 @@ exports.preresolved = function* (url, source, resolutions, artifacts, visited, o
352
365
  url.protocol !== deferredProtocol
353
366
  ) {
354
367
  yield {
355
- children: exports.module(url, null, {}, artifacts, visited, opts),
368
+ children: exports.module(url, null, {}, artifacts, visited, {
369
+ ...opts,
370
+ referrerType: type
371
+ }),
356
372
  deferred: false
357
373
  }
358
374
  }
@@ -364,8 +380,6 @@ exports.preresolved = function* (url, source, resolutions, artifacts, visited, o
364
380
  }
365
381
  }
366
382
 
367
- const type = moduleType(url, {}, null, opts)
368
-
369
383
  const lexer = { imports: [], exports: [] }
370
384
 
371
385
  if (type === constants.SCRIPT || type === constants.MODULE) {
@@ -534,7 +548,13 @@ function* resolveImport(entry, specifier, condition, parentURL, imports, artifac
534
548
  resolved = true
535
549
  }
536
550
  } else {
537
- const source = yield { module: url, artifact: false }
551
+ let source
552
+
553
+ if (url.protocol === 'data:') {
554
+ source = decodeDataURL(url)
555
+ } else {
556
+ source = yield { module: url, artifact: false }
557
+ }
538
558
 
539
559
  if (source !== null) {
540
560
  resolution = yield* postresolve(url)
@@ -706,7 +726,7 @@ function* postresolve(url) {
706
726
  }
707
727
 
708
728
  function moduleType(url, attributes, info, opts = {}) {
709
- const { defaultType = constants.SCRIPT, aliases = null } = opts
729
+ const { defaultType = constants.SCRIPT, referrerType, aliases = null } = opts
710
730
 
711
731
  if (typeof attributes.type === 'string') {
712
732
  switch (attributes.type) {
@@ -729,6 +749,20 @@ function moduleType(url, attributes, info, opts = {}) {
729
749
  return 0
730
750
  }
731
751
 
752
+ if (url.protocol === 'data:') {
753
+ const { mime } = parseDataURL(url)
754
+
755
+ if (mime === null || mime.subtype === 'javascript') {
756
+ if (referrerType) return referrerType
757
+
758
+ return defaultType === constants.MODULE ? constants.MODULE : constants.SCRIPT
759
+ }
760
+
761
+ if (mime.subtype === 'json') return constants.JSON
762
+
763
+ return defaultType
764
+ }
765
+
732
766
  const match = url.pathname.match(/\.[a-z]+$/)
733
767
 
734
768
  if (match === null) return defaultType
@@ -765,6 +799,36 @@ function moduleType(url, attributes, info, opts = {}) {
765
799
  return defaultType
766
800
  }
767
801
 
802
+ function parseDataURL(url) {
803
+ const { pathname } = url
804
+
805
+ const comma = pathname.indexOf(',')
806
+
807
+ const meta = comma === -1 ? pathname : pathname.slice(0, comma)
808
+ const data = comma === -1 ? '' : pathname.slice(comma + 1)
809
+
810
+ const base64 = /;base64$/i.test(meta)
811
+
812
+ return { mime: MIME.parse(meta), base64, data }
813
+ }
814
+
815
+ function decodeDataURL(url) {
816
+ const { mime, base64, data } = parseDataURL(url)
817
+
818
+ const charset = mime === null ? undefined : mime.parameters.get('charset')
819
+
820
+ if (charset !== undefined && !/^utf-?8$/i.test(charset)) {
821
+ throw errors.UNKNOWN_DATA_URL_CHARSET(
822
+ `Unsupported charset '${charset}' in data URL '${url.href}'`,
823
+ charset
824
+ )
825
+ }
826
+
827
+ if (base64) return Buffer.from(data, 'base64')
828
+
829
+ return decodeURIComponent(data)
830
+ }
831
+
768
832
  function addURL(collection, url) {
769
833
  if (Array.isArray(collection)) {
770
834
  let lo = 0
package/lib/errors.js CHANGED
@@ -45,4 +45,12 @@ module.exports = class ModuleTraverseError extends Error {
45
45
  static INVALID_IMPORTS_MAP(msg) {
46
46
  return new ModuleTraverseError(msg, ModuleTraverseError.INVALID_IMPORTS_MAP)
47
47
  }
48
+
49
+ static UNKNOWN_DATA_URL_CHARSET(msg, charset) {
50
+ const err = new ModuleTraverseError(msg, ModuleTraverseError.UNKNOWN_DATA_URL_CHARSET)
51
+
52
+ err.charset = charset
53
+
54
+ return err
55
+ }
48
56
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bare-module-traverse",
3
- "version": "2.4.1",
3
+ "version": "2.4.3",
4
4
  "description": "Low-level module graph traversal for Bare",
5
5
  "exports": {
6
6
  ".": {
@@ -55,6 +55,7 @@
55
55
  "homepage": "https://github.com/holepunchto/bare-module-traverse#readme",
56
56
  "dependencies": {
57
57
  "bare-addon-resolve": "^1.5.0",
58
+ "bare-mime": "^1.0.0",
58
59
  "bare-module-lexer": "^1.6.0",
59
60
  "bare-module-resolve": "^1.7.0"
60
61
  },