• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Modules: ECMAScript modules
2
3<!--introduced_in=v8.5.0-->
4<!-- type=misc -->
5<!-- YAML
6added: v8.5.0
7changes:
8  - version:
9    - v14.17.0
10    pr-url: https://github.com/nodejs/node/pull/35781
11    description: Stabilize modules implementation.
12  - version:
13    - v14.13.0
14    pr-url: https://github.com/nodejs/node/pull/35249
15    description: Support for detection of CommonJS named exports.
16  - version: v14.8.0
17    pr-url: https://github.com/nodejs/node/pull/34558
18    description: Unflag Top-Level Await.
19  - version:
20    - v14.0.0
21    - v13.14.0
22    pr-url: https://github.com/nodejs/node/pull/31974
23    description: Remove experimental modules warning.
24  - version:
25    - v13.2.0
26    - v12.17.0
27    pr-url: https://github.com/nodejs/node/pull/29866
28    description: Loading ECMAScript modules no longer requires a command-line flag.
29  - version: v12.0.0
30    pr-url: https://github.com/nodejs/node/pull/26745
31    description:
32      Add support for ES modules using `.js` file extension via `package.json`
33      `"type"` field.
34-->
35
36> Stability: 2 - Stable
37
38## Introduction
39
40<!--name=esm-->
41
42ECMAScript modules are [the official standard format][] to package JavaScript
43code for reuse. Modules are defined using a variety of [`import`][] and
44[`export`][] statements.
45
46The following example of an ES module exports a function:
47
48```js
49// addTwo.mjs
50function addTwo(num) {
51  return num + 2;
52}
53
54export { addTwo };
55```
56
57The following example of an ES module imports the function from `addTwo.mjs`:
58
59```js
60// app.mjs
61import { addTwo } from './addTwo.mjs';
62
63// Prints: 6
64console.log(addTwo(4));
65```
66
67Node.js fully supports ECMAScript modules as they are currently specified and
68provides interoperability between them and its original module format,
69[CommonJS][].
70
71<!-- Anchors to make sure old links find a target -->
72<i id="esm_package_json_type_field"></i>
73<i id="esm_package_scope_and_file_extensions"></i>
74<i id="esm_input_type_flag"></i>
75
76## Enabling
77
78<!-- type=misc -->
79
80Node.js treats JavaScript code as CommonJS modules by default.
81Authors can tell Node.js to treat JavaScript code as ECMAScript modules
82via the `.mjs` file extension, the `package.json` [`"type"`][] field, or the
83`--input-type` flag. See
84[Modules: Packages](packages.md#packages_determining_module_system) for more
85details.
86
87<!-- Anchors to make sure old links find a target -->
88<i id="esm_package_entry_points"></i>
89<i id="esm_main_entry_point_export"></i>
90<i id="esm_subpath_exports"></i>
91<i id="esm_package_exports_fallbacks"></i>
92<i id="esm_exports_sugar"></i>
93<i id="esm_conditional_exports"></i>
94<i id="esm_nested_conditions"></i>
95<i id="esm_self_referencing_a_package_using_its_name"></i>
96<i id="esm_internal_package_imports"></i>
97<i id="esm_dual_commonjs_es_module_packages"></i>
98<i id="esm_dual_package_hazard"></i>
99<i id="esm_writing_dual_packages_while_avoiding_or_minimizing_hazards"></i>
100<i id="esm_approach_1_use_an_es_module_wrapper"></i>
101<i id="esm_approach_2_isolate_state"></i>
102
103## Packages
104
105This section was moved to [Modules: Packages](packages.md).
106
107## `import` Specifiers
108
109### Terminology
110
111The _specifier_ of an `import` statement is the string after the `from` keyword,
112e.g. `'path'` in `import { sep } from 'path'`. Specifiers are also used in
113`export from` statements, and as the argument to an `import()` expression.
114
115There are three types of specifiers:
116
117* _Relative specifiers_ like `'./startup.js'` or `'../config.mjs'`. They refer
118  to a path relative to the location of the importing file. _The file extension
119  is always necessary for these._
120
121* _Bare specifiers_ like `'some-package'` or `'some-package/shuffle'`. They can
122  refer to the main entry point of a package by the package name, or a
123  specific feature module within a package prefixed by the package name as per
124  the examples respectively. _Including the file extension is only necessary
125  for packages without an [`"exports"`][] field._
126
127* _Absolute specifiers_ like `'file:///opt/nodejs/config.js'`. They refer
128  directly and explicitly to a full path.
129
130Bare specifier resolutions are handled by the [Node.js module resolution
131algorithm][]. All other specifier resolutions are always only resolved with
132the standard relative [URL][] resolution semantics.
133
134Like in CommonJS, module files within packages can be accessed by appending a
135path to the package name unless the package’s [`package.json`][] contains an
136[`"exports"`][] field, in which case files within packages can only be accessed
137via the paths defined in [`"exports"`][].
138
139For details on these package resolution rules that apply to bare specifiers in
140the Node.js module resolution, see the [packages documentation](packages.md).
141
142### Mandatory file extensions
143
144A file extension must be provided when using the `import` keyword to resolve
145relative or absolute specifiers. Directory indexes (e.g. `'./startup/index.js'`)
146must also be fully specified.
147
148This behavior matches how `import` behaves in browser environments, assuming a
149typically configured server.
150
151### URLs
152
153ES modules are resolved and cached as URLs. This means that files containing
154special characters such as `#` and `?` need to be escaped.
155
156`file:`, `node:`, and `data:` URL schemes are supported. A specifier like
157`'https://example.com/app.js'` is not supported natively in Node.js unless using
158a [custom HTTPS loader][].
159
160#### `file:` URLs
161
162Modules are loaded multiple times if the `import` specifier used to resolve
163them has a different query or fragment.
164
165```js
166import './foo.mjs?query=1'; // loads ./foo.mjs with query of "?query=1"
167import './foo.mjs?query=2'; // loads ./foo.mjs with query of "?query=2"
168```
169
170The volume root may be referenced via `/`, `//` or `file:///`. Given the
171differences between [URL][] and path resolution (such as percent encoding
172details), it is recommended to use [url.pathToFileURL][] when importing a path.
173
174#### `data:` Imports
175
176<!-- YAML
177added: v12.10.0
178-->
179
180[`data:` URLs][] are supported for importing with the following MIME types:
181
182* `text/javascript` for ES Modules
183* `application/json` for JSON (requires [`--experimental-json-modules`](cli.md#cli_experimental_json_modules) flag)
184* `application/wasm` for Wasm (requires [`--experimental-wasm-modules`](cli.md#cli_experimental_wasm_modules) flag)
185
186`data:` URLs only resolve [_Bare specifiers_][Terminology] for builtin modules
187and [_Absolute specifiers_][Terminology]. Resolving
188[_Relative specifiers_][Terminology] does not work because `data:` is not a
189[special scheme][]. For example, attempting to load `./foo`
190from `data:text/javascript,import "./foo";` fails to resolve because there
191is no concept of relative resolution for `data:` URLs. An example of a `data:`
192URLs being used is:
193
194```js
195import 'data:text/javascript,console.log("hello!");';
196import _ from 'data:application/json,"world!"';
197```
198
199#### `node:` Imports
200
201<!-- YAML
202added:
203  - v14.13.1
204  - v12.20.0
205changes:
206  - version: v14.18.0
207    pr-url: https://github.com/nodejs/node/pull/37246
208    description: Added `node:` import support to `require(...)`.
209-->
210
211`node:` URLs are supported as an alternative means to load Node.js builtin
212modules. This URL scheme allows for builtin modules to be referenced by valid
213absolute URL strings.
214
215```js
216import fs from 'node:fs/promises';
217```
218
219## Builtin modules
220
221[Core modules][] provide named exports of their public API. A
222default export is also provided which is the value of the CommonJS exports.
223The default export can be used for, among other things, modifying the named
224exports. Named exports of builtin modules are updated only by calling
225[`module.syncBuiltinESMExports()`][].
226
227```js
228import EventEmitter from 'events';
229const e = new EventEmitter();
230```
231
232```js
233import { readFile } from 'fs';
234readFile('./foo.txt', (err, source) => {
235  if (err) {
236    console.error(err);
237  } else {
238    console.log(source);
239  }
240});
241```
242
243```js
244import fs, { readFileSync } from 'fs';
245import { syncBuiltinESMExports } from 'module';
246
247fs.readFileSync = () => Buffer.from('Hello, ESM');
248syncBuiltinESMExports();
249
250fs.readFileSync === readFileSync;
251```
252
253## `import()` expressions
254
255[Dynamic `import()`][] is supported in both CommonJS and ES modules. In CommonJS
256modules it can be used to load ES modules.
257
258## `import.meta`
259
260* {Object}
261
262The `import.meta` meta property is an `Object` that contains the following
263properties.
264
265### `import.meta.url`
266
267* {string} The absolute `file:` URL of the module.
268
269This is defined exactly the same as it is in browsers providing the URL of the
270current module file.
271
272This enables useful patterns such as relative file loading:
273
274```js
275import { readFileSync } from 'fs';
276const buffer = readFileSync(new URL('./data.proto', import.meta.url));
277```
278
279### `import.meta.resolve(specifier[, parent])`
280<!--
281added:
282  - v13.9.0
283  - v12.16.2
284changes:
285  - version: v14.18.0
286    pr-url: https://github.com/nodejs/node/pull/38587
287    description: Add support for WHATWG `URL` object to `parentURL` parameter.
288-->
289
290> Stability: 1 - Experimental
291
292This feature is only available with the `--experimental-import-meta-resolve`
293command flag enabled.
294
295* `specifier` {string} The module specifier to resolve relative to `parent`.
296* `parent` {string} The absolute parent module URL to resolve from. If none
297  is specified, the value of `import.meta.url` is used as the default.
298* Returns: {Promise}
299
300Provides a module-relative resolution function scoped to each module, returning
301the URL string.
302
303<!-- eslint-skip -->
304```js
305const dependencyAsset = await import.meta.resolve('component-lib/asset.css');
306```
307
308`import.meta.resolve` also accepts a second argument which is the parent module
309from which to resolve from:
310
311<!-- eslint-skip -->
312```js
313await import.meta.resolve('./dep', import.meta.url);
314```
315
316This function is asynchronous because the ES module resolver in Node.js is
317allowed to be asynchronous.
318
319## Interoperability with CommonJS
320
321### `import` statements
322
323An `import` statement can reference an ES module or a CommonJS module.
324`import` statements are permitted only in ES modules, but dynamic [`import()`][]
325expressions are supported in CommonJS for loading ES modules.
326
327When importing [CommonJS modules](#esm_commonjs_namespaces), the
328`module.exports` object is provided as the default export. Named exports may be
329available, provided by static analysis as a convenience for better ecosystem
330compatibility.
331
332### `require`
333
334The CommonJS module `require` always treats the files it references as CommonJS.
335
336Using `require` to load an ES module is not supported because ES modules have
337asynchronous execution. Instead, use [`import()`][] to load an ES module
338from a CommonJS module.
339
340### CommonJS Namespaces
341
342CommonJS modules consist of a `module.exports` object which can be of any type.
343
344When importing a CommonJS module, it can be reliably imported using the ES
345module default import or its corresponding sugar syntax:
346
347<!-- eslint-disable no-duplicate-imports -->
348```js
349import { default as cjs } from 'cjs';
350
351// The following import statement is "syntax sugar" (equivalent but sweeter)
352// for `{ default as cjsSugar }` in the above import statement:
353import cjsSugar from 'cjs';
354
355console.log(cjs);
356console.log(cjs === cjsSugar);
357// Prints:
358//   <module.exports>
359//   true
360```
361
362The ECMAScript Module Namespace representation of a CommonJS module is always
363a namespace with a `default` export key pointing to the CommonJS
364`module.exports` value.
365
366This Module Namespace Exotic Object can be directly observed either when using
367`import * as m from 'cjs'` or a dynamic import:
368
369<!-- eslint-skip -->
370```js
371import * as m from 'cjs';
372console.log(m);
373console.log(m === await import('cjs'));
374// Prints:
375//   [Module] { default: <module.exports> }
376//   true
377```
378
379For better compatibility with existing usage in the JS ecosystem, Node.js
380in addition attempts to determine the CommonJS named exports of every imported
381CommonJS module to provide them as separate ES module exports using a static
382analysis process.
383
384For example, consider a CommonJS module written:
385
386```cjs
387// cjs.cjs
388exports.name = 'exported';
389```
390
391The preceding module supports named imports in ES modules:
392
393<!-- eslint-disable no-duplicate-imports -->
394```js
395import { name } from './cjs.cjs';
396console.log(name);
397// Prints: 'exported'
398
399import cjs from './cjs.cjs';
400console.log(cjs);
401// Prints: { name: 'exported' }
402
403import * as m from './cjs.cjs';
404console.log(m);
405// Prints: [Module] { default: { name: 'exported' }, name: 'exported' }
406```
407
408As can be seen from the last example of the Module Namespace Exotic Object being
409logged, the `name` export is copied off of the `module.exports` object and set
410directly on the ES module namespace when the module is imported.
411
412Live binding updates or new exports added to `module.exports` are not detected
413for these named exports.
414
415The detection of named exports is based on common syntax patterns but does not
416always correctly detect named exports. In these cases, using the default
417import form described above can be a better option.
418
419Named exports detection covers many common export patterns, reexport patterns
420and build tool and transpiler outputs. See [cjs-module-lexer][] for the exact
421semantics implemented.
422
423### Differences between ES modules and CommonJS
424
425#### No `require`, `exports` or `module.exports`
426
427In most cases, the ES module `import` can be used to load CommonJS modules.
428
429If needed, a `require` function can be constructed within an ES module using
430[`module.createRequire()`][].
431
432#### No `__filename` or `__dirname`
433
434These CommonJS variables are not available in ES modules.
435
436`__filename` and `__dirname` use cases can be replicated via
437[`import.meta.url`][].
438
439#### No JSON Module Loading
440
441JSON imports are still experimental and only supported via the
442`--experimental-json-modules` flag.
443
444Local JSON files can be loaded relative to `import.meta.url` with `fs` directly:
445
446<!-- eslint-skip -->
447```js
448import { readFile } from 'fs/promises';
449const json = JSON.parse(await readFile(new URL('./dat.json', import.meta.url)));
450```
451
452Alternatively `module.createRequire()` can be used.
453
454#### No Native Module Loading
455
456Native modules are not currently supported with ES module imports.
457
458They can instead be loaded with [`module.createRequire()`][] or
459[`process.dlopen`][].
460
461#### No `require.resolve`
462
463Relative resolution can be handled via `new URL('./local', import.meta.url)`.
464
465For a complete `require.resolve` replacement, there is a flagged experimental
466[`import.meta.resolve`][] API.
467
468Alternatively `module.createRequire()` can be used.
469
470#### No `NODE_PATH`
471
472`NODE_PATH` is not part of resolving `import` specifiers. Please use symlinks
473if this behavior is desired.
474
475#### No `require.extensions`
476
477`require.extensions` is not used by `import`. The expectation is that loader
478hooks can provide this workflow in the future.
479
480#### No `require.cache`
481
482`require.cache` is not used by `import` as the ES module loader has its own
483separate cache.
484
485<i id="esm_experimental_json_modules"></i>
486
487## JSON modules
488
489> Stability: 1 - Experimental
490
491Currently importing JSON modules are only supported in the `commonjs` mode
492and are loaded using the CJS loader. [WHATWG JSON modules specification][] are
493still being standardized, and are experimentally supported by including the
494additional flag `--experimental-json-modules` when running Node.js.
495
496When the `--experimental-json-modules` flag is included, both the
497`commonjs` and `module` mode use the new experimental JSON
498loader. The imported JSON only exposes a `default`. There is no
499support for named exports. A cache entry is created in the CommonJS
500cache to avoid duplication. The same object is returned in
501CommonJS if the JSON module has already been imported from the
502same path.
503
504Assuming an `index.mjs` with
505
506<!-- eslint-skip -->
507```js
508import packageConfig from './package.json';
509```
510
511The `--experimental-json-modules` flag is needed for the module
512to work.
513
514```bash
515node index.mjs # fails
516node --experimental-json-modules index.mjs # works
517```
518
519<i id="esm_experimental_wasm_modules"></i>
520
521## Wasm modules
522
523> Stability: 1 - Experimental
524
525Importing Web Assembly modules is supported under the
526`--experimental-wasm-modules` flag, allowing any `.wasm` files to be
527imported as normal modules while also supporting their module imports.
528
529This integration is in line with the
530[ES Module Integration Proposal for Web Assembly][].
531
532For example, an `index.mjs` containing:
533
534```js
535import * as M from './module.wasm';
536console.log(M);
537```
538
539executed under:
540
541```bash
542node --experimental-wasm-modules index.mjs
543```
544
545would provide the exports interface for the instantiation of `module.wasm`.
546
547<i id="esm_experimental_top_level_await"></i>
548
549## Top-level `await`
550
551<!-- YAML
552added: v14.8.0
553-->
554
555> Stability: 1 - Experimental
556
557The `await` keyword may be used in the top level body of an ECMAScript module.
558
559Assuming an `a.mjs` with
560
561```js
562export const five = await Promise.resolve(5);
563```
564
565And a `b.mjs` with
566
567```js
568import { five } from './a.mjs';
569
570console.log(five); // Logs `5`
571```
572
573```bash
574node b.mjs # works
575```
576
577If a top level `await` expression never resolves, the `node` process will exit
578with a `13` [status code][].
579
580```js
581import { spawn } from 'child_process';
582import { execPath } from 'process';
583
584spawn(execPath, [
585  '--input-type=module',
586  '--eval',
587  // Never-resolving Promise:
588  'await new Promise(() => {})',
589]).once('exit', (code) => {
590  console.log(code); // Logs `13`
591});
592```
593
594<i id="esm_experimental_loaders"></i>
595
596## Loaders
597
598> Stability: 1 - Experimental
599
600**Note: This API is currently being redesigned and will still change.**
601
602<!-- type=misc -->
603
604To customize the default module resolution, loader hooks can optionally be
605provided via a `--experimental-loader ./loader-name.mjs` argument to Node.js.
606
607When hooks are used they only apply to ES module loading and not to any
608CommonJS modules loaded.
609
610### Hooks
611
612#### `resolve(specifier, context, defaultResolve)`
613
614> Note: The loaders API is being redesigned. This hook may disappear or its
615> signature may change. Do not rely on the API described below.
616
617* `specifier` {string}
618* `context` {Object}
619  * `conditions` {string[]}
620  * `parentURL` {string}
621* `defaultResolve` {Function}
622* Returns: {Object}
623  * `url` {string}
624
625The `resolve` hook returns the resolved file URL for a given module specifier
626and parent URL. The module specifier is the string in an `import` statement or
627`import()` expression, and the parent URL is the URL of the module that imported
628this one, or `undefined` if this is the main entry point for the application.
629
630The `conditions` property on the `context` is an array of conditions for
631[Conditional exports][] that apply to this resolution request. They can be used
632for looking up conditional mappings elsewhere or to modify the list when calling
633the default resolution logic.
634
635The current [package exports conditions][Conditional Exports] are always in
636the `context.conditions` array passed into the hook. To guarantee _default
637Node.js module specifier resolution behavior_ when calling `defaultResolve`, the
638`context.conditions` array passed to it _must_ include _all_ elements of the
639`context.conditions` array originally passed into the `resolve` hook.
640
641```js
642/**
643 * @param {string} specifier
644 * @param {{
645 *   conditions: !Array<string>,
646 *   parentURL: !(string | undefined),
647 * }} context
648 * @param {Function} defaultResolve
649 * @returns {Promise<{ url: string }>}
650 */
651export async function resolve(specifier, context, defaultResolve) {
652  const { parentURL = null } = context;
653  if (Math.random() > 0.5) { // Some condition.
654    // For some or all specifiers, do some custom logic for resolving.
655    // Always return an object of the form {url: <string>}.
656    return {
657      url: parentURL ?
658        new URL(specifier, parentURL).href :
659        new URL(specifier).href,
660    };
661  }
662  if (Math.random() < 0.5) { // Another condition.
663    // When calling `defaultResolve`, the arguments can be modified. In this
664    // case it's adding another value for matching conditional exports.
665    return defaultResolve(specifier, {
666      ...context,
667      conditions: [...context.conditions, 'another-condition'],
668    });
669  }
670  // Defer to Node.js for all other specifiers.
671  return defaultResolve(specifier, context, defaultResolve);
672}
673```
674
675#### `getFormat(url, context, defaultGetFormat)`
676
677> Note: The loaders API is being redesigned. This hook may disappear or its
678> signature may change. Do not rely on the API described below.
679
680* `url` {string}
681* `context` {Object}
682* `defaultGetFormat` {Function}
683* Returns: {Object}
684  * `format` {string}
685
686The `getFormat` hook provides a way to define a custom method of determining how
687a URL should be interpreted. The `format` returned also affects what the
688acceptable forms of source values are for a module when parsing. This can be one
689of the following:
690
691| `format`     | Description                    | Acceptable Types For `source` Returned by `getSource` or `transformSource` |
692| ------------ | ------------------------------ | -------------------------------------------------------------------------- |
693| `'builtin'`  | Load a Node.js builtin module  | Not applicable                                                             |
694| `'commonjs'` | Load a Node.js CommonJS module | Not applicable                                                             |
695| `'json'`     | Load a JSON file               | { [`string`][], [`ArrayBuffer`][], [`TypedArray`][] }                      |
696| `'module'`   | Load an ES module              | { [`string`][], [`ArrayBuffer`][], [`TypedArray`][] }                      |
697| `'wasm'`     | Load a WebAssembly module      | { [`ArrayBuffer`][], [`TypedArray`][] }                                    |
698
699Note: These types all correspond to classes defined in ECMAScript.
700
701* The specific [`ArrayBuffer`][] object is a [`SharedArrayBuffer`][].
702* The specific [`TypedArray`][] object is a [`Uint8Array`][].
703
704Note: If the source value of a text-based format (i.e., `'json'`, `'module'`) is
705not a string, it is converted to a string using [`util.TextDecoder`][].
706
707```js
708/**
709 * @param {string} url
710 * @param {Object} context (currently empty)
711 * @param {Function} defaultGetFormat
712 * @returns {Promise<{ format: string }>}
713 */
714export async function getFormat(url, context, defaultGetFormat) {
715  if (Math.random() > 0.5) { // Some condition.
716    // For some or all URLs, do some custom logic for determining format.
717    // Always return an object of the form {format: <string>}, where the
718    // format is one of the strings in the preceding table.
719    return {
720      format: 'module',
721    };
722  }
723  // Defer to Node.js for all other URLs.
724  return defaultGetFormat(url, context, defaultGetFormat);
725}
726```
727
728#### `getSource(url, context, defaultGetSource)`
729
730> Note: The loaders API is being redesigned. This hook may disappear or its
731> signature may change. Do not rely on the API described below.
732
733* `url` {string}
734* `context` {Object}
735  * `format` {string}
736* `defaultGetSource` {Function}
737* Returns: {Object}
738  * `source` {string|SharedArrayBuffer|Uint8Array}
739
740The `getSource` hook provides a way to define a custom method for retrieving
741the source code of an ES module specifier. This would allow a loader to
742potentially avoid reading files from disk.
743
744```js
745/**
746 * @param {string} url
747 * @param {{ format: string }} context
748 * @param {Function} defaultGetSource
749 * @returns {Promise<{ source: !(string | SharedArrayBuffer | Uint8Array) }>}
750 */
751export async function getSource(url, context, defaultGetSource) {
752  const { format } = context;
753  if (Math.random() > 0.5) { // Some condition.
754    // For some or all URLs, do some custom logic for retrieving the source.
755    // Always return an object of the form {source: <string|buffer>}.
756    return {
757      source: '...',
758    };
759  }
760  // Defer to Node.js for all other URLs.
761  return defaultGetSource(url, context, defaultGetSource);
762}
763```
764
765#### `transformSource(source, context, defaultTransformSource)`
766
767> Note: The loaders API is being redesigned. This hook may disappear or its
768> signature may change. Do not rely on the API described below.
769
770* `source` {string|SharedArrayBuffer|Uint8Array}
771* `context` {Object}
772  * `format` {string}
773  * `url` {string}
774* Returns: {Object}
775  * `source` {string|SharedArrayBuffer|Uint8Array}
776
777The `transformSource` hook provides a way to modify the source code of a loaded
778ES module file after the source string has been loaded but before Node.js has
779done anything with it.
780
781If this hook is used to convert unknown-to-Node.js file types into executable
782JavaScript, a resolve hook is also necessary in order to register any
783unknown-to-Node.js file extensions. See the [transpiler loader example][] below.
784
785```js
786/**
787 * @param {!(string | SharedArrayBuffer | Uint8Array)} source
788 * @param {{
789 *   format: string,
790 *   url: string,
791 * }} context
792 * @param {Function} defaultTransformSource
793 * @returns {Promise<{ source: !(string | SharedArrayBuffer | Uint8Array) }>}
794 */
795export async function transformSource(source, context, defaultTransformSource) {
796  const { url, format } = context;
797  if (Math.random() > 0.5) { // Some condition.
798    // For some or all URLs, do some custom logic for modifying the source.
799    // Always return an object of the form {source: <string|buffer>}.
800    return {
801      source: '...',
802    };
803  }
804  // Defer to Node.js for all other sources.
805  return defaultTransformSource(source, context, defaultTransformSource);
806}
807```
808
809#### `getGlobalPreloadCode()`
810
811> Note: The loaders API is being redesigned. This hook may disappear or its
812> signature may change. Do not rely on the API described below.
813
814* Returns: {string}
815
816Sometimes it might be necessary to run some code inside of the same global scope
817that the application runs in. This hook allows the return of a string that is
818run as sloppy-mode script on startup.
819
820Similar to how CommonJS wrappers work, the code runs in an implicit function
821scope. The only argument is a `require`-like function that can be used to load
822builtins like "fs": `getBuiltin(request: string)`.
823
824If the code needs more advanced `require` features, it has to construct
825its own `require` using  `module.createRequire()`.
826
827```js
828/**
829 * @returns {string} Code to run before application startup
830 */
831export function getGlobalPreloadCode() {
832  return `\
833globalThis.someInjectedProperty = 42;
834console.log('I just set some globals!');
835
836const { createRequire } = getBuiltin('module');
837
838const require = createRequire(process.cwd() + '/<preload>');
839// [...]
840`;
841}
842```
843
844### Examples
845
846The various loader hooks can be used together to accomplish wide-ranging
847customizations of Node.js’ code loading and evaluation behaviors.
848
849#### HTTPS loader
850
851In current Node.js, specifiers starting with `https://` are unsupported. The
852loader below registers hooks to enable rudimentary support for such specifiers.
853While this may seem like a significant improvement to Node.js core
854functionality, there are substantial downsides to actually using this loader:
855performance is much slower than loading files from disk, there is no caching,
856and there is no security.
857
858```js
859// https-loader.mjs
860import { get } from 'https';
861
862export function resolve(specifier, context, defaultResolve) {
863  const { parentURL = null } = context;
864
865  // Normally Node.js would error on specifiers starting with 'https://', so
866  // this hook intercepts them and converts them into absolute URLs to be
867  // passed along to the later hooks below.
868  if (specifier.startsWith('https://')) {
869    return {
870      url: specifier
871    };
872  } else if (parentURL && parentURL.startsWith('https://')) {
873    return {
874      url: new URL(specifier, parentURL).href
875    };
876  }
877
878  // Let Node.js handle all other specifiers.
879  return defaultResolve(specifier, context, defaultResolve);
880}
881
882export function getFormat(url, context, defaultGetFormat) {
883  // This loader assumes all network-provided JavaScript is ES module code.
884  if (url.startsWith('https://')) {
885    return {
886      format: 'module'
887    };
888  }
889
890  // Let Node.js handle all other URLs.
891  return defaultGetFormat(url, context, defaultGetFormat);
892}
893
894export function getSource(url, context, defaultGetSource) {
895  // For JavaScript to be loaded over the network, we need to fetch and
896  // return it.
897  if (url.startsWith('https://')) {
898    return new Promise((resolve, reject) => {
899      get(url, (res) => {
900        let data = '';
901        res.on('data', (chunk) => data += chunk);
902        res.on('end', () => resolve({ source: data }));
903      }).on('error', (err) => reject(err));
904    });
905  }
906
907  // Let Node.js handle all other URLs.
908  return defaultGetSource(url, context, defaultGetSource);
909}
910```
911
912```js
913// main.mjs
914import { VERSION } from 'https://coffeescript.org/browser-compiler-modern/coffeescript.js';
915
916console.log(VERSION);
917```
918
919With the preceding loader, running
920`node --experimental-loader ./https-loader.mjs ./main.mjs`
921prints the current version of CoffeeScript per the module at the URL in
922`main.mjs`.
923
924#### Transpiler loader
925
926Sources that are in formats Node.js doesn’t understand can be converted into
927JavaScript using the [`transformSource` hook][]. Before that hook gets called,
928however, other hooks need to tell Node.js not to throw an error on unknown file
929types; and to tell Node.js how to load this new file type.
930
931This is less performant than transpiling source files before running
932Node.js; a transpiler loader should only be used for development and testing
933purposes.
934
935```js
936// coffeescript-loader.mjs
937import { URL, pathToFileURL } from 'url';
938import CoffeeScript from 'coffeescript';
939
940const baseURL = pathToFileURL(`${process.cwd()}/`).href;
941
942// CoffeeScript files end in .coffee, .litcoffee or .coffee.md.
943const extensionsRegex = /\.coffee$|\.litcoffee$|\.coffee\.md$/;
944
945export function resolve(specifier, context, defaultResolve) {
946  const { parentURL = baseURL } = context;
947
948  // Node.js normally errors on unknown file extensions, so return a URL for
949  // specifiers ending in the CoffeeScript file extensions.
950  if (extensionsRegex.test(specifier)) {
951    return {
952      url: new URL(specifier, parentURL).href
953    };
954  }
955
956  // Let Node.js handle all other specifiers.
957  return defaultResolve(specifier, context, defaultResolve);
958}
959
960export function getFormat(url, context, defaultGetFormat) {
961  // Now that we patched resolve to let CoffeeScript URLs through, we need to
962  // tell Node.js what format such URLs should be interpreted as. For the
963  // purposes of this loader, all CoffeeScript URLs are ES modules.
964  if (extensionsRegex.test(url)) {
965    return {
966      format: 'module'
967    };
968  }
969
970  // Let Node.js handle all other URLs.
971  return defaultGetFormat(url, context, defaultGetFormat);
972}
973
974export function transformSource(source, context, defaultTransformSource) {
975  const { url, format } = context;
976
977  if (extensionsRegex.test(url)) {
978    return {
979      source: CoffeeScript.compile(source, { bare: true })
980    };
981  }
982
983  // Let Node.js handle all other sources.
984  return defaultTransformSource(source, context, defaultTransformSource);
985}
986```
987
988```coffee
989# main.coffee
990import { scream } from './scream.coffee'
991console.log scream 'hello, world'
992
993import { version } from 'process'
994console.log "Brought to you by Node.js version #{version}"
995```
996
997```coffee
998# scream.coffee
999export scream = (str) -> str.toUpperCase()
1000```
1001
1002With the preceding loader, running
1003`node --experimental-loader ./coffeescript-loader.mjs main.coffee`
1004causes `main.coffee` to be turned into JavaScript after its source code is
1005loaded from disk but before Node.js executes it; and so on for any `.coffee`,
1006`.litcoffee` or `.coffee.md` files referenced via `import` statements of any
1007loaded file.
1008
1009## Resolution algorithm
1010
1011### Features
1012
1013The resolver has the following properties:
1014
1015* FileURL-based resolution as is used by ES modules
1016* Support for builtin module loading
1017* Relative and absolute URL resolution
1018* No default extensions
1019* No folder mains
1020* Bare specifier package resolution lookup through node_modules
1021
1022### Resolver algorithm
1023
1024The algorithm to load an ES module specifier is given through the
1025**ESM_RESOLVE** method below. It returns the resolved URL for a
1026module specifier relative to a parentURL.
1027
1028The algorithm to determine the module format of a resolved URL is
1029provided by **ESM_FORMAT**, which returns the unique module
1030format for any file. The _"module"_ format is returned for an ECMAScript
1031Module, while the _"commonjs"_ format is used to indicate loading through the
1032legacy CommonJS loader. Additional formats such as _"addon"_ can be extended in
1033future updates.
1034
1035In the following algorithms, all subroutine errors are propagated as errors
1036of these top-level routines unless stated otherwise.
1037
1038_defaultConditions_ is the conditional environment name array,
1039`["node", "import"]`.
1040
1041The resolver can throw the following errors:
1042* _Invalid Module Specifier_: Module specifier is an invalid URL, package name
1043  or package subpath specifier.
1044* _Invalid Package Configuration_: package.json configuration is invalid or
1045  contains an invalid configuration.
1046* _Invalid Package Target_: Package exports or imports define a target module
1047  for the package that is an invalid type or string target.
1048* _Package Path Not Exported_: Package exports do not define or permit a target
1049  subpath in the package for the given module.
1050* _Package Import Not Defined_: Package imports do not define the specifier.
1051* _Module Not Found_: The package or module requested does not exist.
1052* _Unsupported Directory Import_: The resolved path corresponds to a directory,
1053  which is not a supported target for module imports.
1054
1055### Resolver Algorithm Specification
1056
1057**ESM_RESOLVE**(_specifier_, _parentURL_)
1058
1059> 1. Let _resolved_ be **undefined**.
1060> 1. If _specifier_ is a valid URL, then
1061>    1. Set _resolved_ to the result of parsing and reserializing
1062>       _specifier_ as a URL.
1063> 1. Otherwise, if _specifier_ starts with _"/"_, _"./"_ or _"../"_, then
1064>    1. Set _resolved_ to the URL resolution of _specifier_ relative to
1065>       _parentURL_.
1066> 1. Otherwise, if _specifier_ starts with _"#"_, then
1067>    1. Set _resolved_ to the destructured value of the result of
1068>       **PACKAGE_IMPORTS_RESOLVE**(_specifier_, _parentURL_,
1069>       _defaultConditions_).
1070> 1. Otherwise,
1071>    1. Note: _specifier_ is now a bare specifier.
1072>    1. Set _resolved_ the result of
1073>       **PACKAGE_RESOLVE**(_specifier_, _parentURL_).
1074> 1. If _resolved_ contains any percent encodings of _"/"_ or _"\\"_ (_"%2f"_
1075>    and _"%5C"_ respectively), then
1076>    1. Throw an _Invalid Module Specifier_ error.
1077> 1. If the file at _resolved_ is a directory, then
1078>    1. Throw an _Unsupported Directory Import_ error.
1079> 1. If the file at _resolved_ does not exist, then
1080>    1. Throw a _Module Not Found_ error.
1081> 1. Set _resolved_ to the real path of _resolved_.
1082> 1. Let _format_ be the result of **ESM_FORMAT**(_resolved_).
1083> 1. Load _resolved_ as module format, _format_.
1084> 1. Return _resolved_.
1085
1086**PACKAGE_RESOLVE**(_packageSpecifier_, _parentURL_)
1087
1088> 1. Let _packageName_ be **undefined**.
1089> 1. If _packageSpecifier_ is an empty string, then
1090>    1. Throw an _Invalid Module Specifier_ error.
1091> 1. If _packageSpecifier_ does not start with _"@"_, then
1092>    1. Set _packageName_ to the substring of _packageSpecifier_ until the first
1093>       _"/"_ separator or the end of the string.
1094> 1. Otherwise,
1095>    1. If _packageSpecifier_ does not contain a _"/"_ separator, then
1096>       1. Throw an _Invalid Module Specifier_ error.
1097>    1. Set _packageName_ to the substring of _packageSpecifier_
1098>       until the second _"/"_ separator or the end of the string.
1099> 1. If _packageName_ starts with _"."_ or contains _"\\"_ or _"%"_, then
1100>    1. Throw an _Invalid Module Specifier_ error.
1101> 1. Let _packageSubpath_ be _"."_ concatenated with the substring of
1102>       _packageSpecifier_ from the position at the length of _packageName_.
1103> 1. Let _selfUrl_ be the result of
1104>    **PACKAGE_SELF_RESOLVE**(_packageName_, _packageSubpath_, _parentURL_).
1105> 1. If _selfUrl_ is not **undefined**, return _selfUrl_.
1106> 1. If _packageSubpath_ is _"."_ and _packageName_ is a Node.js builtin
1107>    module, then
1108>    1. Return the string _"node:"_ concatenated with _packageSpecifier_.
1109> 1. While _parentURL_ is not the file system root,
1110>    1. Let _packageURL_ be the URL resolution of _"node_modules/"_
1111>       concatenated with _packageSpecifier_, relative to _parentURL_.
1112>    1. Set _parentURL_ to the parent folder URL of _parentURL_.
1113>    1. If the folder at _packageURL_ does not exist, then
1114>       1. Set _parentURL_ to the parent URL path of _parentURL_.
1115>       1. Continue the next loop iteration.
1116>    1. Let _pjson_ be the result of **READ_PACKAGE_JSON**(_packageURL_).
1117>    1. If _pjson_ is not **null** and _pjson_._exports_ is not **null** or
1118>       **undefined**, then
1119>       1. Let _exports_ be _pjson.exports_.
1120>       1. Return the _resolved_ destructured value of the result of
1121>          **PACKAGE_EXPORTS_RESOLVE**(_packageURL_, _packageSubpath_,
1122>           _pjson.exports_, _defaultConditions_).
1123>    1. Otherwise, if _packageSubpath_ is equal to _"."_, then
1124>       1. Return the result applying the legacy **LOAD_AS_DIRECTORY**
1125>          CommonJS resolver to _packageURL_, throwing a _Module Not Found_
1126>          error for no resolution.
1127>    1. Otherwise,
1128>       1. Return the URL resolution of _packageSubpath_ in _packageURL_.
1129> 1. Throw a _Module Not Found_ error.
1130
1131**PACKAGE_SELF_RESOLVE**(_packageName_, _packageSubpath_, _parentURL_)
1132
1133> 1. Let _packageURL_ be the result of **READ_PACKAGE_SCOPE**(_parentURL_).
1134> 1. If _packageURL_ is **null**, then
1135>    1. Return **undefined**.
1136> 1. Let _pjson_ be the result of **READ_PACKAGE_JSON**(_packageURL_).
1137> 1. If _pjson_ is **null** or if _pjson_._exports_ is **null** or
1138>    **undefined**, then
1139>    1. Return **undefined**.
1140> 1. If _pjson.name_ is equal to _packageName_, then
1141>    1. Return the _resolved_ destructured value of the result of
1142>       **PACKAGE_EXPORTS_RESOLVE**(_packageURL_, _subpath_, _pjson.exports_,
1143>       _defaultConditions_).
1144> 1. Otherwise, return **undefined**.
1145
1146**PACKAGE_EXPORTS_RESOLVE**(_packageURL_, _subpath_, _exports_, _conditions_)
1147
1148> 1. If _exports_ is an Object with both a key starting with _"."_ and a key not
1149>    starting with _"."_, throw an _Invalid Package Configuration_ error.
1150> 1. If _subpath_ is equal to _"."_, then
1151>    1. Let _mainExport_ be **undefined**.
1152>    1. If _exports_ is a String or Array, or an Object containing no keys
1153>       starting with _"."_, then
1154>       1. Set _mainExport_ to _exports_.
1155>    1. Otherwise if _exports_ is an Object containing a _"."_ property, then
1156>       1. Set _mainExport_ to _exports_\[_"."_\].
1157>    1. If _mainExport_ is not **undefined**, then
1158>       1. Let _resolved_ be the result of **PACKAGE_TARGET_RESOLVE**(
1159>          _packageURL_, _mainExport_, _""_, **false**, **false**,
1160>          _conditions_).
1161>       1. If _resolved_ is not **null** or **undefined**, then
1162>          1. Return _resolved_.
1163> 1. Otherwise, if _exports_ is an Object and all keys of _exports_ start with
1164>    _"."_, then
1165>    1. Let _matchKey_ be the string _"./"_ concatenated with _subpath_.
1166>    1. Let _resolvedMatch_ be result of **PACKAGE_IMPORTS_EXPORTS_RESOLVE**(
1167>       _matchKey_, _exports_, _packageURL_, **false**, _conditions_).
1168>    1. If _resolvedMatch_._resolve_ is not **null** or **undefined**, then
1169>       1. Return _resolvedMatch_.
1170> 1. Throw a _Package Path Not Exported_ error.
1171
1172**PACKAGE_IMPORTS_RESOLVE**(_specifier_, _parentURL_, _conditions_)
1173
1174> 1. Assert: _specifier_ begins with _"#"_.
1175> 1. If _specifier_ is exactly equal to _"#"_ or starts with _"#/"_, then
1176>    1. Throw an _Invalid Module Specifier_ error.
1177> 1. Let _packageURL_ be the result of **READ_PACKAGE_SCOPE**(_parentURL_).
1178> 1. If _packageURL_ is not **null**, then
1179>    1. Let _pjson_ be the result of **READ_PACKAGE_JSON**(_packageURL_).
1180>    1. If _pjson.imports_ is a non-null Object, then
1181>       1. Let _resolvedMatch_ be the result of
1182>          **PACKAGE_IMPORTS_EXPORTS_RESOLVE**(_specifier_, _pjson.imports_,
1183>          _packageURL_, **true**, _conditions_).
1184>       1. If _resolvedMatch_._resolve_ is not **null** or **undefined**, then
1185>          1. Return _resolvedMatch_.
1186> 1. Throw a _Package Import Not Defined_ error.
1187
1188**PACKAGE_IMPORTS_EXPORTS_RESOLVE**(_matchKey_, _matchObj_, _packageURL_,
1189_isImports_, _conditions_)
1190
1191> 1. If _matchKey_ is a key of _matchObj_ and does not end in _"/"_ or contain
1192>    _"*"_, then
1193>    1. Let _target_ be the value of _matchObj_\[_matchKey_\].
1194>    1. Let _resolved_ be the result of **PACKAGE_TARGET_RESOLVE**(
1195>       _packageURL_, _target_, _""_, **false**, _isImports_, _conditions_).
1196>    1. Return the object _{ resolved, exact: **true** }_.
1197> 1. Let _expansionKeys_ be the list of keys of _matchObj_ either ending in
1198>    _"/"_ or containing only a single _"*"_, sorted by the sorting function
1199>    **PATTERN_KEY_COMPARE** which orders in descending order of specificity.
1200> 1. For each key _expansionKey_ in _expansionKeys_, do
1201>    1. Let _patternBase_ be **null**.
1202>    1. If _expansionKey_ contains _"*"_, set _patternBase_ to the substring of
1203>       _expansionKey_ up to but excluding the first _"*"_ character.
1204>    1. If _patternBase_ is not **null** and _matchKey_ starts with but is not
1205>       equal to _patternBase_, then
1206>       1. Let _patternTrailer_ be the substring of _expansionKey_ from the
1207>          index after the first _"*"_ character.
1208>       1. If _patternTrailer_ has zero length, or if _matchKey_ ends with
1209>          _patternTrailer_ and the length of _matchKey_ is greater than or
1210>          equal to the length of _expansionKey_, then
1211>          1. Let _target_ be the value of _matchObj_\[_expansionKey_\].
1212>          1. Let _subpath_ be the substring of _matchKey_ starting at the
1213>             index of the length of _patternBase_ up to the length of
1214>             _matchKey_ minus the length of _patternTrailer_.
1215>          1. Let _resolved_ be the result of **PACKAGE_TARGET_RESOLVE**(
1216>             _packageURL_, _target_, _subpath_, **true**, _isImports_,
1217>             _conditions_).
1218>          1. Return the object _{ resolved, exact: **true** }_.
1219>    1. Otherwise if _patternBase_ is **null** and _matchKey_ starts with
1220>       _expansionKey_, then
1221>       1. Let _target_ be the value of _matchObj_\[_expansionKey_\].
1222>       1. Let _subpath_ be the substring of _matchKey_ starting at the
1223>          index of the length of _expansionKey_.
1224>       1. Let _resolved_ be the result of **PACKAGE_TARGET_RESOLVE**(
1225>          _packageURL_, _target_, _subpath_, **false**, _isImports_,
1226>          _conditions_).
1227>       1. Return the object _{ resolved, exact: **false** }_.
1228> 1. Return the object _{ resolved: **null**, exact: **true** }_.
1229
1230**PATTERN_KEY_COMPARE**(_keyA_, _keyB_)
1231
1232> 1. Assert: _keyA_ ends with _"/"_ or contains only a single _"*"_.
1233> 1. Assert: _keyB_ ends with _"/"_ or contains only a single _"*"_.
1234> 1. Let _baseLengthA_ be the index of _"*"_ in _keyA_ plus one, if _keyA_
1235>    contains _"*"_, or the length of _keyA_ otherwise.
1236> 1. Let _baseLengthB_ be the index of _"*"_ in _keyB_ plus one, if _keyB_
1237>    contains _"*"_, or the length of _keyB_ otherwise.
1238> 1. If _baseLengthA_ is greater than _baseLengthB_, return -1.
1239> 1. If _baseLengthB_ is greater than _baseLengthA_, return 1.
1240> 1. If _keyA_ does not contain _"*"_, return 1.
1241> 1. If _keyB_ does not contain _"*"_, return -1.
1242> 1. If the length of _keyA_ is greater than the length of _keyB_, return -1.
1243> 1. If the length of _keyB_ is greater than the length of _keyA_, return 1.
1244> 1. Return 0.
1245
1246**PACKAGE_TARGET_RESOLVE**(_packageURL_, _target_, _subpath_, _pattern_,
1247_internal_, _conditions_)
1248
1249> 1. If _target_ is a String, then
1250>    1. If _pattern_ is **false**, _subpath_ has non-zero length and _target_
1251>       does not end with _"/"_, throw an _Invalid Module Specifier_ error.
1252>    1. If _target_ does not start with _"./"_, then
1253>       1. If _internal_ is **true** and _target_ does not start with _"../"_ or
1254>          _"/"_ and is not a valid URL, then
1255>          1. If _pattern_ is **true**, then
1256>             1. Return **PACKAGE_RESOLVE**(_target_ with every instance of
1257>                _"*"_ replaced by _subpath_, _packageURL_ + _"/"_)_.
1258>          1. Return **PACKAGE_RESOLVE**(_target_ + _subpath_,
1259>             _packageURL_ + _"/"_)_.
1260>       1. Otherwise, throw an _Invalid Package Target_ error.
1261>    1. If _target_ split on _"/"_ or _"\\"_ contains any _"."_, _".."_ or
1262>       _"node_modules"_ segments after the first segment, throw an
1263>       _Invalid Package Target_ error.
1264>    1. Let _resolvedTarget_ be the URL resolution of the concatenation of
1265>       _packageURL_ and _target_.
1266>    1. Assert: _resolvedTarget_ is contained in _packageURL_.
1267>    1. If _subpath_ split on _"/"_ or _"\\"_ contains any _"."_, _".."_ or
1268>       _"node_modules"_ segments, throw an _Invalid Module Specifier_ error.
1269>    1. If _pattern_ is **true**, then
1270>       1. Return the URL resolution of _resolvedTarget_ with every instance of
1271>          _"*"_ replaced with _subpath_.
1272>    1. Otherwise,
1273>       1. Return the URL resolution of the concatenation of _subpath_ and
1274>          _resolvedTarget_.
1275> 1. Otherwise, if _target_ is a non-null Object, then
1276>    1. If _exports_ contains any index property keys, as defined in ECMA-262
1277>       [6.1.7 Array Index][], throw an _Invalid Package Configuration_ error.
1278>    1. For each property _p_ of _target_, in object insertion order as,
1279>       1. If _p_ equals _"default"_ or _conditions_ contains an entry for _p_,
1280>          then
1281>          1. Let _targetValue_ be the value of the _p_ property in _target_.
1282>          1. Let _resolved_ be the result of **PACKAGE_TARGET_RESOLVE**(
1283>             _packageURL_, _targetValue_, _subpath_, _pattern_, _internal_,
1284>             _conditions_).
1285>          1. If _resolved_ is equal to **undefined**, continue the loop.
1286>          1. Return _resolved_.
1287>    1. Return **undefined**.
1288> 1. Otherwise, if _target_ is an Array, then
1289>    1. If _target.length is zero, return **null**.
1290>    1. For each item _targetValue_ in _target_, do
1291>       1. Let _resolved_ be the result of **PACKAGE_TARGET_RESOLVE**(
1292>          _packageURL_, _targetValue_, _subpath_, _pattern_, _internal_,
1293>          _conditions_), continuing the loop on any _Invalid Package Target_
1294>          error.
1295>       1. If _resolved_ is **undefined**, continue the loop.
1296>       1. Return _resolved_.
1297>    1. Return or throw the last fallback resolution **null** return or error.
1298> 1. Otherwise, if _target_ is _null_, return **null**.
1299> 1. Otherwise throw an _Invalid Package Target_ error.
1300
1301**ESM_FORMAT**(_url_)
1302
1303> 1. Assert: _url_ corresponds to an existing file.
1304> 1. Let _pjson_ be the result of **READ_PACKAGE_SCOPE**(_url_).
1305> 1. If _url_ ends in _".mjs"_, then
1306>    1. Return _"module"_.
1307> 1. If _url_ ends in _".cjs"_, then
1308>    1. Return _"commonjs"_.
1309> 1. If _pjson?.type_ exists and is _"module"_, then
1310>    1. If _url_ ends in _".js"_, then
1311>       1. Return _"module"_.
1312>    1. Throw an _Unsupported File Extension_ error.
1313> 1. Otherwise,
1314>    1. Throw an _Unsupported File Extension_ error.
1315
1316**READ_PACKAGE_SCOPE**(_url_)
1317
1318> 1. Let _scopeURL_ be _url_.
1319> 1. While _scopeURL_ is not the file system root,
1320>    1. Set _scopeURL_ to the parent URL of _scopeURL_.
1321>    1. If _scopeURL_ ends in a _"node_modules"_ path segment, return **null**.
1322>    1. Let _pjson_ be the result of **READ_PACKAGE_JSON**(_scopeURL_).
1323>    1. If _pjson_ is not **null**, then
1324>       1. Return _pjson_.
1325> 1. Return **null**.
1326
1327**READ_PACKAGE_JSON**(_packageURL_)
1328
1329> 1. Let _pjsonURL_ be the resolution of _"package.json"_ within _packageURL_.
1330> 1. If the file at _pjsonURL_ does not exist, then
1331>    1. Return **null**.
1332> 1. If the file at _packageURL_ does not parse as valid JSON, then
1333>    1. Throw an _Invalid Package Configuration_ error.
1334> 1. Return the parsed JSON source of the file at _pjsonURL_.
1335
1336### Customizing ESM specifier resolution algorithm
1337
1338> Stability: 1 - Experimental
1339
1340The current specifier resolution does not support all default behavior of
1341the CommonJS loader. One of the behavior differences is automatic resolution
1342of file extensions and the ability to import directories that have an index
1343file.
1344
1345The `--experimental-specifier-resolution=[mode]` flag can be used to customize
1346the extension resolution algorithm. The default mode is `explicit`, which
1347requires the full path to a module be provided to the loader. To enable the
1348automatic extension resolution and importing from directories that include an
1349index file use the `node` mode.
1350
1351```console
1352$ node index.mjs
1353success!
1354$ node index # Failure!
1355Error: Cannot find module
1356$ node --experimental-specifier-resolution=node index
1357success!
1358```
1359
1360<!-- Note: The cjs-module-lexer link should be kept in-sync with the deps version -->
1361[6.1.7 Array Index]: https://tc39.es/ecma262/#integer-index
1362[CommonJS]: modules.md
1363[Conditional exports]: packages.md#packages_conditional_exports
1364[Core modules]: modules.md#modules_core_modules
1365[Dynamic `import()`]: https://wiki.developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Dynamic_Imports
1366[ES Module Integration Proposal for Web Assembly]: https://github.com/webassembly/esm-integration
1367[Node.js Module Resolution Algorithm]: #esm_resolver_algorithm_specification
1368[Terminology]: #esm_terminology
1369[URL]: https://url.spec.whatwg.org/
1370[WHATWG JSON modules specification]: https://html.spec.whatwg.org/#creating-a-json-module-script
1371[`"exports"`]: packages.md#packages_exports
1372[`"type"`]: packages.md#packages_type
1373[`ArrayBuffer`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer
1374[`SharedArrayBuffer`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer
1375[`TypedArray`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray
1376[`Uint8Array`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array
1377[`data:` URLs]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs
1378[`export`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export
1379[`import()`]: #esm_import_expressions
1380[`import.meta.resolve`]: #esm_import_meta_resolve_specifier_parent
1381[`import.meta.url`]: #esm_import_meta_url
1382[`import`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
1383[`module.createRequire()`]: module.md#module_module_createrequire_filename
1384[`module.syncBuiltinESMExports()`]: module.md#module_module_syncbuiltinesmexports
1385[`package.json`]: packages.md#packages_node_js_package_json_field_definitions
1386[`process.dlopen`]: process.md#process_process_dlopen_module_filename_flags
1387[`string`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String
1388[`transformSource` hook]: #esm_transformsource_source_context_defaulttransformsource
1389[`util.TextDecoder`]: util.md#util_class_util_textdecoder
1390[cjs-module-lexer]: https://github.com/guybedford/cjs-module-lexer/tree/1.2.2
1391[custom https loader]: #esm_https_loader
1392[special scheme]: https://url.spec.whatwg.org/#special-scheme
1393[status code]: process.md#process_exit_codes
1394[the official standard format]: https://tc39.github.io/ecma262/#sec-modules
1395[transpiler loader example]: #esm_transpiler_loader
1396[url.pathToFileURL]: url.md#url_url_pathtofileurl_path
1397