From c24801bd65ae80dd4e2eef34a67c0759b211b3f7 Mon Sep 17 00:00:00 2001 From: HitkoDev Date: Fri, 15 Sep 2023 18:25:39 +0200 Subject: [PATCH 1/3] Fix ESM loader to work with Node 20 `process.send` is no longer accessible from ESM loader in Node 20, therefore loader needs to use `context.port` and a proxy function to send messages to the parent. See https://nodejs.org/api/esm.html#globalpreload --- .travis.yml | 1 + lib/loaders/ipc.mjs | 4 ++++ lib/loaders/load.mjs | 20 +++++++++++++++++-- .../index.mjs | 1 - test/fixture/resolution.mjs | 7 ------- test/spawn/esmodule.js | 14 ------------- 6 files changed, 23 insertions(+), 24 deletions(-) delete mode 100644 test/fixture/experimental-specifier-resolution/index.mjs delete mode 100644 test/fixture/resolution.mjs diff --git a/.travis.yml b/.travis.yml index 25d33de..a4ebd4d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ jobs: script: npm run lint language: node_js node_js: + - 20 - 18 - 16 - 14 diff --git a/lib/loaders/ipc.mjs b/lib/loaders/ipc.mjs index 61c48c4..8fc1aad 100644 --- a/lib/loaders/ipc.mjs +++ b/lib/loaders/ipc.mjs @@ -3,3 +3,7 @@ const cmd = 'NODE_DEV'; export const send = m => { if (process.connected) process.send({ ...m, cmd }); }; + +export const sendPort = (port, m) => { + if (port) port.postMessage({ ...m, cmd }); +}; diff --git a/lib/loaders/load.mjs b/lib/loaders/load.mjs index 2772f60..a1c4fb4 100644 --- a/lib/loaders/load.mjs +++ b/lib/loaders/load.mjs @@ -1,13 +1,17 @@ import { createRequire } from 'module'; import { fileURLToPath } from 'url'; -import { send } from './ipc.mjs'; +import { sendPort } from './ipc.mjs'; const require = createRequire(import.meta.url); +// Port used for communication between the loader and ESM modules +// https://nodejs.org/api/esm.html#globalpreload +let port; + export async function load(url, context, defaultLoad) { const required = url.startsWith('file://') ? fileURLToPath(url) : url; - send({ required }); + sendPort(port, { required }); try { return await defaultLoad(url, context, defaultLoad); @@ -19,3 +23,15 @@ export async function load(url, context, defaultLoad) { }); } } + +export const globalPreload = (context) => { + // Store port + port = context.port; + + // Inject code to forward loader events to the parent + return ` +port.on('message', (m) => { + if (process.connected) process.send(m); +}); + `; +}; diff --git a/test/fixture/experimental-specifier-resolution/index.mjs b/test/fixture/experimental-specifier-resolution/index.mjs deleted file mode 100644 index 0ac70ad..0000000 --- a/test/fixture/experimental-specifier-resolution/index.mjs +++ /dev/null @@ -1 +0,0 @@ -export default 'experimental-specifier-resolution'; diff --git a/test/fixture/resolution.mjs b/test/fixture/resolution.mjs deleted file mode 100644 index c4d373c..0000000 --- a/test/fixture/resolution.mjs +++ /dev/null @@ -1,7 +0,0 @@ -import resolution from './experimental-specifier-resolution'; -import message from './message'; - -setTimeout(() => {}, 10000); - -console.log(resolution); -console.log(message); diff --git a/test/spawn/esmodule.js b/test/spawn/esmodule.js index 1b6b816..1fa2c5f 100644 --- a/test/spawn/esmodule.js +++ b/test/spawn/esmodule.js @@ -2,20 +2,6 @@ const tap = require('tap'); const { spawn, touchFile } = require('../utils'); -tap.test('Supports ECMAScript modules with experimental-specifier-resolution', t => { - spawn('--experimental-specifier-resolution=node resolution.mjs', out => { - if (out.match(/touch message.js/)) { - touchFile('message.js'); - return out2 => { - if (out2.match(/Restarting/)) { - t.match(out2, /\[INFO\] \d{2}:\d{2}:\d{2} Restarting/); - return { exit: t.end.bind(t) }; - } - }; - } - }); -}); - tap.test('Supports ECMAScript modules', t => { spawn('ecma-script-modules.mjs', out => { if (out.match(/touch message.mjs/)) { From fd7abff3b237329a14c92c7779eb54248b6c0ee2 Mon Sep 17 00:00:00 2001 From: HitkoDev Date: Sat, 16 Sep 2023 20:11:10 +0200 Subject: [PATCH 2/3] Run test on node 20 --- .appveyor.yml | 1 + .github/workflows/nodejs.yml | 4 ++-- lib/loaders/load.mjs | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index bc20403..071d68c 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -2,6 +2,7 @@ build: off environment: matrix: + - nodejs_version: '20' - nodejs_version: '18' - nodejs_version: '16' - nodejs_version: '14' diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 8073209..e7593c3 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -13,7 +13,7 @@ jobs: strategy: matrix: - node-version: ["14.x", "16.x", "18.x"] + node-version: ["14.x", "16.x", "18.x", "20.x"] steps: - uses: actions/checkout@v2 @@ -29,7 +29,7 @@ jobs: strategy: matrix: - node-version: ["14.x", "16.x", "18.x"] + node-version: ["14.x", "16.x", "18.x", "20.x"] steps: - uses: actions/checkout@v2 diff --git a/lib/loaders/load.mjs b/lib/loaders/load.mjs index a1c4fb4..d31ff29 100644 --- a/lib/loaders/load.mjs +++ b/lib/loaders/load.mjs @@ -32,6 +32,6 @@ export const globalPreload = (context) => { return ` port.on('message', (m) => { if (process.connected) process.send(m); -}); +}).unref(); `; }; From 00f0137ac427a3b37562d4b6d3cbec257def3b9e Mon Sep 17 00:00:00 2001 From: HitkoDev Date: Sat, 16 Sep 2023 21:26:24 +0200 Subject: [PATCH 3/3] Resovle dependency issues --- .github/workflows/nodejs.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index e7593c3..2e4dde2 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -37,5 +37,7 @@ jobs: uses: actions/setup-node@v1 with: node-version: ${{ matrix.node-version }} + - if: matrix.node-version == '14.x' + run: npm install -g npm@9 # node 14 comes with npm 6, which has some known bugs with dependency resolution - run: npm i - run: npm test