bare-module 3.1.5 → 3.1.7

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
@@ -12,6 +12,157 @@ npm i bare-module
12
12
  const Module = require('bare-module')
13
13
  ````
14
14
 
15
+ ## Packages
16
+
17
+ A package is directory with a `package.json` file.
18
+
19
+ ### Fields
20
+
21
+ #### `"name"`
22
+
23
+ ```json
24
+ {
25
+ "name": "my-package"
26
+ }
27
+ ```
28
+
29
+ The name of the package. This is used for [addon resolution](https://github.com/holepunchto/bare-addon-resolve#algorithm), [self-referencing](#self-referencing), and importing packages by name.
30
+
31
+ #### `"version"`
32
+
33
+ ```json
34
+ {
35
+ "version": "1.2.3"
36
+ }
37
+ ```
38
+
39
+ The current version of the package. This is used for [addon resolution](https://github.com/holepunchto/bare-addon-resolve#algorithm).
40
+
41
+ #### `"type"`
42
+
43
+ ```json
44
+ {
45
+ "type": "module"
46
+ }
47
+ ```
48
+
49
+ The module format used for `.js` files. If not defined, `.js` files are interpreted as CommonJS. If set to `"module"`, `.js` files are instead interpreted as ES modules.
50
+
51
+ #### `"exports"`
52
+
53
+ ```json
54
+ {
55
+ "exports": {
56
+ ".": "./index.js"
57
+ }
58
+ }
59
+ ```
60
+
61
+ The entry points of the package. If defined, only the modules explicitly exported by the package may be imported when importing the package by name.
62
+
63
+ ##### Subpath exports
64
+
65
+ A package may define more than one entry point by declaring several subpaths with the main export being `"."`:
66
+
67
+ ```json
68
+ {
69
+ "exports": {
70
+ ".": "./index.js",
71
+ "./submodule": "./lib/submodule.js"
72
+ }
73
+ }
74
+ ```
75
+
76
+ When importing the package by name, `require('my-package')` will resolve to `<modules>/my-package/index.js` whereas `require('my-package/submodule')` will resolve to `<modules>/my-package/lib/submodule.js`.
77
+
78
+ ##### Conditional exports
79
+
80
+ Conditional exports allow packages to provide different exports for different conditions, such as the module format of the importing module:
81
+
82
+ ```json
83
+ {
84
+ "exports": {
85
+ ".": {
86
+ "import": "./index.mjs",
87
+ "require": "./index.cjs"
88
+ }
89
+ }
90
+ }
91
+ ```
92
+
93
+ When importing the package by name, `require('my-package')` will resolve to `<modules>/my-package/index.cjs` whereas `import 'my-package'` will resolve to `<modules>/my-package/index.mjs`.
94
+
95
+ Similarly, conditional exports can be used to provide different entry points for different runtimes:
96
+
97
+ ```json
98
+ {
99
+ "exports": {
100
+ ".": {
101
+ "bare": "./bare.js",
102
+ "node": "./node.js"
103
+ }
104
+ }
105
+ }
106
+ ```
107
+
108
+ To provide a fallback for when no other conditions match, the `"default"` condition can be declared:
109
+
110
+ ```json
111
+ {
112
+ "exports": {
113
+ ".": {
114
+ "bare": "./bare.js",
115
+ "node": "./node.js",
116
+ "default": "./fallback.js"
117
+ }
118
+ }
119
+ }
120
+ ```
121
+
122
+ The following conditions are supported, listed in order from most specific to least specific as conditions should be defined:
123
+
124
+ Condition | Description
125
+ :-- | :--
126
+ `"bare"` |
127
+ `"node"` |
128
+ `"import"` |
129
+ `"require"` |
130
+ `"default"` |
131
+
132
+ ##### Self-referencing
133
+
134
+ Within a package, exports defined in the `"exports"` field can be referenced by importing the package by name. For example, given the following `package.json`...
135
+
136
+ ```json
137
+ {
138
+ "name": "my-package",
139
+ "exports": {
140
+ ".": "./index.js",
141
+ "./submodule": "./lib/submodule.js"
142
+ }
143
+ }
144
+ ```
145
+
146
+ ...any module within `my-package` may reference these entry points using either `require('my-package')` or `require('my-package/submodule')`.
147
+
148
+ ##### Exports sugar
149
+
150
+ If a package defines only a single export, `"."`, it may leave out the subpath entirely:
151
+
152
+ ```json
153
+ {
154
+ "exports": "./index.js"
155
+ }
156
+ ```
157
+
158
+ #### `"imports"`
159
+
160
+ ##### Subpath imports
161
+
162
+ ##### Conditional imports
163
+
164
+ ##### Private imports
165
+
15
166
  ## API
16
167
 
17
168
  #### `Module.constants`
package/binding.c CHANGED
@@ -21,6 +21,10 @@ on_static_import (js_env_t *env, js_value_t *specifier, js_value_t *assertions,
21
21
 
22
22
  int err;
23
23
 
24
+ js_handle_scope_t *scope;
25
+ err = js_open_handle_scope(env, &scope);
26
+ assert(err == 0);
27
+
24
28
  js_value_t *ctx;
25
29
  err = js_get_reference_value(env, context->ctx, &ctx);
26
30
  assert(err == 0);
@@ -36,20 +40,29 @@ on_static_import (js_env_t *env, js_value_t *specifier, js_value_t *assertions,
36
40
  js_value_t *args[4] = {specifier, assertions};
37
41
 
38
42
  err = js_create_string_utf8(env, (utf8_t *) name, -1, &args[2]);
39
- if (err < 0) return NULL;
43
+ if (err < 0) goto err;
40
44
 
41
45
  err = js_get_boolean(env, false, &args[3]);
42
46
  assert(err == 0);
43
47
 
44
48
  js_value_t *result;
45
49
  err = js_call_function(env, ctx, on_import, 4, args, &result);
46
- if (err < 0) return NULL;
50
+ if (err < 0) goto err;
47
51
 
48
52
  js_module_t *module;
49
53
  err = js_get_value_external(env, result, (void **) &module);
50
- if (err < 0) return NULL;
54
+ if (err < 0) goto err;
55
+
56
+ err = js_close_handle_scope(env, scope);
57
+ assert(err == 0);
51
58
 
52
59
  return module;
60
+
61
+ err:
62
+ err = js_close_handle_scope(env, scope);
63
+ assert(err == 0);
64
+
65
+ return NULL;
53
66
  }
54
67
 
55
68
  static js_module_t *
@@ -58,6 +71,10 @@ on_dynamic_import (js_env_t *env, js_value_t *specifier, js_value_t *assertions,
58
71
 
59
72
  int err;
60
73
 
74
+ js_handle_scope_t *scope;
75
+ err = js_open_handle_scope(env, &scope);
76
+ assert(err == 0);
77
+
61
78
  js_value_t *ctx;
62
79
  err = js_get_reference_value(env, context->ctx, &ctx);
63
80
  assert(err == 0);
@@ -73,13 +90,22 @@ on_dynamic_import (js_env_t *env, js_value_t *specifier, js_value_t *assertions,
73
90
 
74
91
  js_value_t *result;
75
92
  err = js_call_function(env, ctx, on_import, 4, args, &result);
76
- if (err < 0) return NULL;
93
+ if (err < 0) goto err;
77
94
 
78
95
  js_module_t *module;
79
96
  err = js_get_value_external(env, result, (void **) &module);
80
- if (err < 0) return NULL;
97
+ if (err < 0) goto err;
98
+
99
+ err = js_close_handle_scope(env, scope);
100
+ assert(err == 0);
81
101
 
82
102
  return module;
103
+
104
+ err:
105
+ err = js_close_handle_scope(env, scope);
106
+ assert(err == 0);
107
+
108
+ return NULL;
83
109
  }
84
110
 
85
111
  static void
@@ -88,6 +114,10 @@ on_evaluate (js_env_t *env, js_module_t *module, void *data) {
88
114
 
89
115
  int err;
90
116
 
117
+ js_handle_scope_t *scope;
118
+ err = js_open_handle_scope(env, &scope);
119
+ assert(err == 0);
120
+
91
121
  js_value_t *ctx;
92
122
  err = js_get_reference_value(env, context->ctx, &ctx);
93
123
  assert(err == 0);
@@ -103,11 +133,20 @@ on_evaluate (js_env_t *env, js_module_t *module, void *data) {
103
133
  js_value_t *args[1];
104
134
 
105
135
  err = js_create_string_utf8(env, (utf8_t *) name, -1, &args[0]);
106
- if (err < 0) return;
136
+ if (err < 0) goto err;
107
137
 
108
138
  js_value_t *result;
109
139
  err = js_call_function(env, ctx, on_evaluate, 1, args, &result);
110
- if (err < 0) return;
140
+ if (err < 0) goto err;
141
+
142
+ err = js_close_handle_scope(env, scope);
143
+ assert(err == 0);
144
+
145
+ return;
146
+
147
+ err:
148
+ err = js_close_handle_scope(env, scope);
149
+ assert(err == 0);
111
150
  }
112
151
 
113
152
  static void
@@ -116,6 +155,10 @@ on_meta (js_env_t *env, js_module_t *module, js_value_t *meta, void *data) {
116
155
 
117
156
  int err;
118
157
 
158
+ js_handle_scope_t *scope;
159
+ err = js_open_handle_scope(env, &scope);
160
+ assert(err == 0);
161
+
119
162
  js_value_t *ctx;
120
163
  err = js_get_reference_value(env, context->ctx, &ctx);
121
164
  assert(err == 0);
@@ -131,13 +174,22 @@ on_meta (js_env_t *env, js_module_t *module, js_value_t *meta, void *data) {
131
174
  js_value_t *args[2];
132
175
 
133
176
  err = js_create_string_utf8(env, (utf8_t *) name, -1, &args[0]);
134
- if (err < 0) return;
177
+ if (err < 0) goto err;
135
178
 
136
179
  args[1] = meta;
137
180
 
138
181
  js_value_t *result;
139
182
  err = js_call_function(env, ctx, on_meta, 2, args, &result);
140
- if (err < 0) return;
183
+ if (err < 0) goto err;
184
+
185
+ err = js_close_handle_scope(env, scope);
186
+ assert(err == 0);
187
+
188
+ return;
189
+
190
+ err:
191
+ err = js_close_handle_scope(env, scope);
192
+ assert(err == 0);
141
193
  }
142
194
 
143
195
  static js_value_t *
package/index.js CHANGED
@@ -2,6 +2,7 @@
2
2
  const path = require('bare-path')
3
3
  const resolve = require('bare-module-resolve')
4
4
  const Bundle = require('bare-bundle')
5
+ const { parse } = require('cjs-module-lexer')
5
6
  const { fileURLToPath, pathToFileURL } = require('url-file-url')
6
7
  const Protocol = require('./lib/protocol')
7
8
  const constants = require('./lib/constants')
@@ -27,6 +28,7 @@ const Module = module.exports = exports = class Module {
27
28
  this._conditions = null
28
29
  this._protocol = null
29
30
  this._bundle = null
31
+ this._function = null
30
32
  this._handle = null
31
33
 
32
34
  Module._modules.add(this)
@@ -112,42 +114,100 @@ const Module = module.exports = exports = class Module {
112
114
  _transform (isImport, isDynamicImport) {
113
115
  if (isDynamicImport) {
114
116
  this._synthesize()
115
- this._evaluate()
117
+ this._evaluate(true /* eagerRun */)
116
118
  } else if (isImport) {
117
119
  this._synthesize()
118
- } else if (this._type === constants.types.MODULE) {
120
+ } else {
119
121
  this._evaluate()
120
122
  }
121
123
 
122
124
  return this
123
125
  }
124
126
 
125
- _evaluate () {
126
- if ((this._state & constants.states.EVALUATED) !== 0) return
127
+ _synthesize () {
128
+ if ((this._state & constants.states.SYNTHESIZED) !== 0) return
129
+
130
+ this._state |= constants.states.SYNTHESIZED
127
131
 
128
- binding.runModule(this._handle, Module._handle)
132
+ if (this._type === constants.types.MODULE) return
129
133
 
130
- if (this._type === constants.types.MODULE) {
131
- this._exports = binding.getNamespace(this._handle)
134
+ const names = ['default']
135
+ const queue = [this]
136
+ const seen = new Set()
137
+
138
+ while (queue.length) {
139
+ const module = queue.pop()
140
+
141
+ if (seen.has(module)) continue
142
+
143
+ seen.add(module)
144
+
145
+ switch (module._type) {
146
+ case constants.types.SCRIPT: {
147
+ const result = parse(module._function.toString())
148
+
149
+ names.push(...result.exports)
150
+
151
+ const referrer = module
152
+
153
+ for (const specifier of result.reexports) {
154
+ const resolved = Module.resolve(specifier, referrer._url, { isImport: true, referrer })
155
+
156
+ const module = Module.load(resolved, { isImport: true, referrer })
157
+
158
+ queue.push(module)
159
+ }
160
+
161
+ break
162
+ }
163
+
164
+ case constants.types.MODULE: {
165
+ module._evaluate()
166
+
167
+ for (const name of Object.keys(module._exports)) {
168
+ names.push(name)
169
+ }
170
+
171
+ break
172
+ }
173
+
174
+ case constants.types.JSON: {
175
+ for (const name of Object.keys(module._exports)) {
176
+ names.push(name)
177
+ }
178
+ }
179
+ }
132
180
  }
133
181
 
134
- this._state |= constants.states.EVALUATED
182
+ this._handle = binding.createSyntheticModule(this._url.href, names, Module._handle)
135
183
  }
136
184
 
137
- _synthesize () {
138
- if ((this._state & constants.states.SYNTHESIZED) !== 0) return
185
+ _evaluate (eagerRun = false) {
186
+ if ((this._state & constants.states.EVALUATED) !== 0) return
139
187
 
140
- if (this._type !== constants.types.MODULE) {
141
- const names = ['default']
188
+ this._state |= constants.states.EVALUATED
142
189
 
143
- for (const key of Object.keys(this._exports)) {
144
- if (key !== 'default') names.push(key)
145
- }
190
+ if (this._type === constants.types.SCRIPT) {
191
+ const require = createRequire(this._url, { module: this })
192
+
193
+ this._exports = {}
194
+
195
+ this._function(
196
+ require,
197
+ this,
198
+ this._exports,
199
+ urlToPath(this._url),
200
+ urlToDirname(this._url)
201
+ )
146
202
 
147
- this._handle = binding.createSyntheticModule(this._url.href, names, Module._handle)
203
+ if (eagerRun) binding.runModule(this._handle, Module._handle)
148
204
  }
149
205
 
150
- this._state |= constants.states.SYNTHESIZED
206
+ if (this._type === constants.types.MODULE) {
207
+ binding.runModule(this._handle, Module._handle)
208
+
209
+ this._exports = binding.getNamespace(this._handle)
210
+ }
151
211
  }
152
212
 
153
213
  [Symbol.for('bare.inspect')] () {
@@ -218,6 +278,8 @@ const Module = module.exports = exports = class Module {
218
278
  throw errors.MODULE_NOT_FOUND(`Cannot find module '${href}'`)
219
279
  }
220
280
 
281
+ module._evaluate()
282
+
221
283
  binding.setExport(module._handle, 'default', module._exports)
222
284
 
223
285
  for (const [key, value] of Object.entries(module._exports)) {
@@ -415,7 +477,7 @@ exports.isBuiltin = function isBuiltin () {
415
477
  return false
416
478
  }
417
479
 
418
- exports.createRequire = function createRequire (parentURL, opts = {}) {
480
+ const createRequire = exports.createRequire = function createRequire (parentURL, opts = {}) {
419
481
  const self = Module
420
482
 
421
483
  if (typeof parentURL === 'string') {
@@ -427,6 +489,8 @@ exports.createRequire = function createRequire (parentURL, opts = {}) {
427
489
  }
428
490
 
429
491
  let {
492
+ module = null,
493
+
430
494
  referrer = null,
431
495
  type = constants.types.SCRIPT,
432
496
  defaultType = referrer ? referrer._defaultType : constants.types.SCRIPT,
@@ -439,17 +503,19 @@ exports.createRequire = function createRequire (parentURL, opts = {}) {
439
503
  conditions = referrer ? referrer._conditions : self._conditions
440
504
  } = opts
441
505
 
442
- const module = new Module(parentURL)
506
+ if (module === null) {
507
+ module = new Module(parentURL)
443
508
 
444
- module._type = type
445
- module._defaultType = defaultType
446
- module._cache = cache
447
- module._main = main || module
448
- module._protocol = protocol
449
- module._imports = imports
450
- module._resolutions = resolutions
451
- module._builtins = builtins
452
- module._conditions = conditions
509
+ module._type = type
510
+ module._defaultType = defaultType
511
+ module._cache = cache
512
+ module._main = main || module
513
+ module._protocol = protocol
514
+ module._imports = imports
515
+ module._resolutions = resolutions
516
+ module._builtins = builtins
517
+ module._conditions = conditions
518
+ }
453
519
 
454
520
  referrer = module
455
521
 
@@ -522,8 +588,6 @@ Module._extensions['.js'] = function (module, source, referrer) {
522
588
  }
523
589
 
524
590
  Module._extensions['.cjs'] = function (module, source, referrer) {
525
- const self = Module
526
-
527
591
  const protocol = module._protocol
528
592
 
529
593
  module._type = constants.types.SCRIPT
@@ -535,49 +599,7 @@ Module._extensions['.cjs'] = function (module, source, referrer) {
535
599
 
536
600
  if (typeof source !== 'string') source = Buffer.coerce(source).toString()
537
601
 
538
- referrer = module
539
-
540
- addon.host = Bare.Addon.host
541
-
542
- require.main = module._main
543
- require.cache = module._cache
544
- require.resolve = resolve
545
- require.addon = addon
546
-
547
- module._exports = {}
548
-
549
- binding.createFunction(module._url.href, ['require', 'module', 'exports', '__filename', '__dirname'], source, 0)(
550
- require,
551
- module,
552
- module._exports,
553
- urlToPath(module._url),
554
- urlToDirname(module._url)
555
- )
556
-
557
- function require (specifier) {
558
- const resolved = self.resolve(specifier, referrer._url, { referrer })
559
-
560
- const module = self.load(resolved, { referrer })
561
-
562
- return module._exports
563
- }
564
-
565
- function resolve (specifier) {
566
- const resolved = self.resolve(specifier, referrer._url, { referrer })
567
-
568
- switch (resolved.protocol) {
569
- case 'builtin:': return resolved.pathname
570
- default: urlToPath(resolved)
571
- }
572
- }
573
-
574
- function addon (specifier = '.') {
575
- const resolved = Bare.Addon.resolve(specifier, referrer._url, { referrer })
576
-
577
- const addon = Bare.Addon.load(resolved, { referrer })
578
-
579
- return addon._exports
580
- }
602
+ module._function = binding.createFunction(module._url.href, ['require', 'module', 'exports', '__filename', '__dirname'], source, 0)
581
603
  }
582
604
  }
583
605
 
@@ -688,7 +710,7 @@ Bare
688
710
  })
689
711
 
690
712
  function urlToPath (url) {
691
- if (url.protocol) return fileURLToPath(url)
713
+ if (url.protocol === 'file:') return fileURLToPath(url)
692
714
 
693
715
  if (isWindows) {
694
716
  if (/%2f|%5c/i.test(url.pathname)) {
@@ -704,7 +726,7 @@ function urlToPath (url) {
704
726
  }
705
727
 
706
728
  function urlToDirname (url) {
707
- if (url.protocol) return path.dirname(fileURLToPath(url))
729
+ if (url.protocol === 'file:') return path.dirname(fileURLToPath(url))
708
730
 
709
731
  if (isWindows) {
710
732
  if (/%2f|%5c/i.test(url.pathname)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bare-module",
3
- "version": "3.1.5",
3
+ "version": "3.1.7",
4
4
  "description": "Module support for JavaScript",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -29,6 +29,7 @@
29
29
  "bare-bundle": "^1.0.0",
30
30
  "bare-module-resolve": "^1.4.4",
31
31
  "bare-path": "^2.0.0",
32
+ "cjs-module-lexer": "^1.2.3",
32
33
  "url-file-url": "^1.0.2"
33
34
  },
34
35
  "devDependencies": {