From 6c9f5ebedec05c8391b3f14c2502b1c05c3cb58f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Mon, 5 Feb 2018 17:45:12 +0100 Subject: [PATCH 1/5] module: add import.meta.require This adds require to the import.meta object This can be used as a mechanism to get interoperability between common.js and esm. --- lib/internal/process/esm_loader.js | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/lib/internal/process/esm_loader.js b/lib/internal/process/esm_loader.js index c622084415..7c24ead200 100644 --- a/lib/internal/process/esm_loader.js +++ b/lib/internal/process/esm_loader.js @@ -1,12 +1,16 @@ 'use strict'; +const { makeRequireFunction } = require('internal/modules/cjs/helpers'); +const Module = require('module'); const { internalBinding } = require('internal/bootstrap/loaders'); + const { setImportModuleDynamicallyCallback, setInitializeImportMetaObjectCallback } = internalBinding('module_wrap'); +const { defineProperty } = Object; -const { getURLFromFilePath } = require('internal/url'); +const { getURLFromFilePath, getPathFromURL } = require('internal/url'); const Loader = require('internal/modules/esm/loader'); const path = require('path'); const { URL } = require('url'); @@ -27,6 +31,27 @@ function initializeImportMetaObject(wrap, meta) { if (vmModule === undefined) { // This ModuleWrap belongs to the Loader. meta.url = wrap.url; + let req; + defineProperty(meta, 'require', { + enumerable: true, + configurable: true, + get() { + if (req !== undefined) + return req; + const url = new URL(meta.url); + const path = getPathFromURL(url); + const mod = new Module(path, null); + mod.filename = path; + req = makeRequireFunction(mod).bind(null); + + // remove properties that don't affect ESM loading + // delete req.cache; + // delete req.extensions; + // delete req.main; + // delete req.resolve.paths; + return req; + } + }); } else { const initializeImportMeta = initImportMetaMap.get(vmModule); if (initializeImportMeta !== undefined) { From f1336db750fe225cb3303d8b8dcf9fd8db2ecc90 Mon Sep 17 00:00:00 2001 From: Myles Borins Date: Wed, 13 Jun 2018 13:53:45 -0400 Subject: [PATCH 2/5] test: add tests for import.meta.require --- test/es-module/test-esm-import-meta.mjs | 39 +++++++++++++++++++++---- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/test/es-module/test-esm-import-meta.mjs b/test/es-module/test-esm-import-meta.mjs index c17e0e20d4..cc4d729ef9 100644 --- a/test/es-module/test-esm-import-meta.mjs +++ b/test/es-module/test-esm-import-meta.mjs @@ -3,20 +3,47 @@ import '../common'; import assert from 'assert'; +const fixtures = import.meta.require('../common/fixtures'); + assert.strictEqual(Object.getPrototypeOf(import.meta), null); -const keys = ['url']; +const keys = ['url', 'require']; assert.deepStrictEqual(Reflect.ownKeys(import.meta), keys); const descriptors = Object.getOwnPropertyDescriptors(import.meta); + for (const descriptor of Object.values(descriptors)) { delete descriptor.value; // Values are verified below. - assert.deepStrictEqual(descriptor, { - enumerable: true, - writable: true, - configurable: true - }); } +assert.deepStrictEqual(descriptors.url, { + enumerable: true, + writable: true, + configurable: true +}); + +assert.deepStrictEqual(descriptors.require, { + get: descriptors.require.get, + set: undefined, + enumerable: true, + configurable: true +}); + +assert.strictEqual(import.meta.require.cache, undefined); +assert.strictEqual(import.meta.require.extensions, undefined); +assert.strictEqual(import.meta.require.main, undefined); +assert.strictEqual(import.meta.require.paths, undefined); + const urlReg = /^file:\/\/\/.*\/test\/es-module\/test-esm-import-meta\.mjs$/; assert(import.meta.url.match(urlReg)); + +const a = import.meta.require( + fixtures.path('module-require', 'relative', 'dot.js') +); +const b = import.meta.require( + fixtures.path('module-require', 'relative', 'dot-slash.js') +); + +assert.strictEqual(a.value, 42); +// require(".") should resolve like require("./") +assert.strictEqual(a, b); From b597a3ae86cf81ef74e6042c925b64bc25a40a6e Mon Sep 17 00:00:00 2001 From: Myles Borins Date: Wed, 13 Jun 2018 15:28:12 -0400 Subject: [PATCH 3/5] doc: document import.meta.require --- doc/api/esm.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/api/esm.md b/doc/api/esm.md index 459f877718..d197998b2b 100644 --- a/doc/api/esm.md +++ b/doc/api/esm.md @@ -45,6 +45,9 @@ The `import.meta` metaproperty is an `Object` that contains the following property: * `url` {string} The absolute `file:` URL of the module. +* `require` {Function} To require CommonJS modules. This function enables + interoperability between CJS and ESM. See [`require()`]. None of the properties + generally exposed on require are available via `import.meta.require`. ### Unsupported @@ -256,3 +259,4 @@ in the import tree. [Node.js EP for ES Modules]: https://github.com/nodejs/node-eps/blob/master/002-es-modules.md [addons]: addons.html [dynamic instantiate hook]: #esm_dynamic_instantiate_hook +[`require()`]: modules.html#modules_require From 6218ffb8dda84b5e80201d3847d040b3a3fb347d Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Sun, 1 Jul 2018 23:25:53 -0700 Subject: [PATCH 4/5] module: Add node_modules paths lookup to import.meta.require --- lib/internal/process/esm_loader.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/lib/internal/process/esm_loader.js b/lib/internal/process/esm_loader.js index 7c24ead200..dfae71dae6 100644 --- a/lib/internal/process/esm_loader.js +++ b/lib/internal/process/esm_loader.js @@ -42,13 +42,8 @@ function initializeImportMetaObject(wrap, meta) { const path = getPathFromURL(url); const mod = new Module(path, null); mod.filename = path; + mod.paths = Module._nodeModulePaths(path); req = makeRequireFunction(mod).bind(null); - - // remove properties that don't affect ESM loading - // delete req.cache; - // delete req.extensions; - // delete req.main; - // delete req.resolve.paths; return req; } }); From 6769efa29e847c824bc0f2a7b7fe865b76f8b78b Mon Sep 17 00:00:00 2001 From: Myles Borins Date: Fri, 13 Jul 2018 16:00:32 -0400 Subject: [PATCH 5/5] fixup: doc fix --- doc/api/esm.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/api/esm.md b/doc/api/esm.md index d197998b2b..f20b6516b3 100644 --- a/doc/api/esm.md +++ b/doc/api/esm.md @@ -46,8 +46,9 @@ property: * `url` {string} The absolute `file:` URL of the module. * `require` {Function} To require CommonJS modules. This function enables - interoperability between CJS and ESM. See [`require()`]. None of the properties - generally exposed on require are available via `import.meta.require`. + interoperability between CJS and ESM. See [`require()`]. None of the + properties generally exposed on require are available via + `import.meta.require`. ### Unsupported