From 6c9f9497c7ee1820b849d7f4719a2d6b278a556c Mon Sep 17 00:00:00 2001 From: Julio Souza Date: Sat, 2 Sep 2023 17:48:29 -0300 Subject: [PATCH] Add workaround for loading ESM --- bench/esm/import-chalk.js | 5 +++++ bench/esm/import-local-file.js | 5 +++++ bench/esm/local-file.mjs | 3 +++ bench/require-import-chalk.js | 15 +++++++++++++++ bench/require-import-local-file.js | 15 +++++++++++++++ package.json | 1 + sandbox-esm/index.js | 5 +++++ v8-compile-cache.js | 24 ++++++++++++++++++++++++ 8 files changed, 73 insertions(+) create mode 100755 bench/esm/import-chalk.js create mode 100755 bench/esm/import-local-file.js create mode 100755 bench/esm/local-file.mjs create mode 100755 bench/require-import-chalk.js create mode 100755 bench/require-import-local-file.js create mode 100755 sandbox-esm/index.js diff --git a/bench/esm/import-chalk.js b/bench/esm/import-chalk.js new file mode 100755 index 0000000..7c10113 --- /dev/null +++ b/bench/esm/import-chalk.js @@ -0,0 +1,5 @@ +(async () => { + // Evaluating the dynamic import is a workaround for loading ESM in CJS files + const { default: chalk } = await (Function(`return import("chalk")`)()); + console.log(chalk.blue("Hello World")); +})(); diff --git a/bench/esm/import-local-file.js b/bench/esm/import-local-file.js new file mode 100755 index 0000000..215d5f2 --- /dev/null +++ b/bench/esm/import-local-file.js @@ -0,0 +1,5 @@ +(async () => { + // Evaluating the dynamic import is a workaround for loading ESM in CJS files + const {default: log} = await (Function(`return import("./local-file.mjs")`)()); + log(); +})(); diff --git a/bench/esm/local-file.mjs b/bench/esm/local-file.mjs new file mode 100755 index 0000000..c2e5d18 --- /dev/null +++ b/bench/esm/local-file.mjs @@ -0,0 +1,3 @@ +export default function () { + console.log('Hello World') +} \ No newline at end of file diff --git a/bench/require-import-chalk.js b/bench/require-import-chalk.js new file mode 100755 index 0000000..8525f66 --- /dev/null +++ b/bench/require-import-chalk.js @@ -0,0 +1,15 @@ +#!/usr/bin/env node +'use strict'; + +const WITH_CACHE = true; + +require('./_measure.js')('require-chalk', WITH_CACHE, () => { + // Node introduced support for dynamics import in v12 + const NODE_MAJOR_VERSION = process.versions.node.split('.')[0]; + if (NODE_MAJOR_VERSION < 12) { + return; + } + + process.argv.push('config', 'get', 'init.author.name'); + require('./esm/import-chalk.js'); +}); diff --git a/bench/require-import-local-file.js b/bench/require-import-local-file.js new file mode 100755 index 0000000..d94f878 --- /dev/null +++ b/bench/require-import-local-file.js @@ -0,0 +1,15 @@ +#!/usr/bin/env node +'use strict'; + +const WITH_CACHE = true; + +require('./_measure.js')('require-local-file', WITH_CACHE, () => { + // Node introduced support for dynamics import in v12 + const NODE_MAJOR_VERSION = process.versions.node.split('.')[0]; + if (NODE_MAJOR_VERSION < 12) { + return; + } + + process.argv.push('config', 'get', 'init.author.name'); + require('./esm/import-local-file.js'); +}); diff --git a/package.json b/package.json index 60be2f1..90ff877 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "dependencies": {}, "devDependencies": { "babel-core": "6.26.3", + "chalk": "^5.3.0", "eslint": "^7.12.1", "flow-parser": "0.136.0", "rimraf": "^2.5.4", diff --git a/sandbox-esm/index.js b/sandbox-esm/index.js new file mode 100755 index 0000000..a853b17 --- /dev/null +++ b/sandbox-esm/index.js @@ -0,0 +1,5 @@ +(async () => { + require("../v8-compile-cache.js"); + require('../bench/esm/import-chalk.js'); + require('./requires-local-file/requires-local-file.js'); +})(); diff --git a/v8-compile-cache.js b/v8-compile-cache.js index 56fd061..9e82466 100644 --- a/v8-compile-cache.js +++ b/v8-compile-cache.js @@ -237,12 +237,36 @@ class NativeCompileCache { var buffer = this._cacheStore.get(filename, invalidationKey); + var _this = this; + var script = new vm.Script(wrapper, { filename: filename, lineOffset: 0, displayErrors: true, cachedData: buffer, produceCachedData: true, + // Allow importing ESM with import() (otherwise throws "A dynamic import callback was not specified.") + // See https://nodejs.org/dist/latest-v20.x/docs/api/vm.html#new-vmscriptcode-options + // See https://github.com/nodejs/node/blob/3a6a80a4e1ad3fc3f1b181e1c94ecfd0b17e6dd1/test/parallel/test-vm-module-dynamic-import.js#L10 + importModuleDynamically: function(specifier) { + // Disable cache if script uses dynamic imports (otherwise throws "Invalid host defined options") + _this._cacheStore.delete(filename); + + // Resolve specifier in filename directory to allow importing local files + // There might be other paths to be included here + const paths = [ + path.dirname(filename), + ...require.resolve.paths(filename), + ] + const resolved = require.resolve(specifier, { paths }); + + // This will only work on Node >=10.12.0 + const url = require('url'); + const importSpecifier = url.pathToFileURL(resolved) + + // Dynamic import, should be supported by Node if importModuleDynamically is called + return import(importSpecifier); + }, }); if (script.cachedDataProduced) {