diff options
author | snek <snek@deno.com> | 2024-09-10 13:12:36 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-10 20:12:36 +0000 |
commit | f9007d3386bbe9f709ce413ac0cf099b86d4c4bf (patch) | |
tree | 3254119b37ef434062c431b2b4964d9317fb5f1a /ext/node/polyfills | |
parent | ee3829a7787b337b2a7e98251b40d5937b2c255b (diff) |
feat: require(esm) (#25501)
implement require(esm) using `op_import_sync` from deno_core.
possible future changes:
- cts and mts
- replace Deno.core.evalContext to optimize esm syntax detection
Fixes: https://github.com/denoland/deno/issues/25487
Diffstat (limited to 'ext/node/polyfills')
-rw-r--r-- | ext/node/polyfills/01_require.js | 65 |
1 files changed, 24 insertions, 41 deletions
diff --git a/ext/node/polyfills/01_require.js b/ext/node/polyfills/01_require.js index e4a781cc4..b84765d31 100644 --- a/ext/node/polyfills/01_require.js +++ b/ext/node/polyfills/01_require.js @@ -4,9 +4,11 @@ import { core, internals, primordials } from "ext:core/mod.js"; import { + op_import_sync, op_napi_open, op_require_as_file_path, op_require_break_on_next_statement, + op_require_can_parse_as_esm, op_require_init_paths, op_require_is_deno_dir_package, op_require_is_request_relative, @@ -900,16 +902,6 @@ Module.prototype.load = function (filename) { pathDirname(this.filename), ); const extension = findLongestRegisteredExtension(filename); - // allow .mjs to be overridden - if ( - StringPrototypeEndsWith(filename, ".mjs") && !Module._extensions[".mjs"] - ) { - throw createRequireEsmError( - filename, - moduleParentCache.get(this)?.filename, - ); - } - Module._extensions[extension](this, this.filename); this.loaded = true; @@ -987,27 +979,24 @@ function wrapSafe( if (process.mainModule === cjsModuleInstance) { enrichCJSError(err.thrown); } - if (isEsmSyntaxError(err.thrown)) { - throw createRequireEsmError( - filename, - moduleParentCache.get(cjsModuleInstance)?.filename, - ); - } else { - throw err.thrown; - } + throw err.thrown; } return f; } Module.prototype._compile = function (content, filename, format) { - const compiledWrapper = wrapSafe(filename, content, this, format); - if (format === "module") { - // TODO(https://github.com/denoland/deno/issues/24822): implement require esm - throw createRequireEsmError( - filename, - moduleParentCache.get(module)?.filename, - ); + return loadESMFromCJS(this, filename, content); + } + + let compiledWrapper; + try { + compiledWrapper = wrapSafe(filename, content, this, format); + } catch (err) { + if (err instanceof SyntaxError && op_require_can_parse_as_esm(content)) { + return loadESMFromCJS(this, filename, content); + } + throw err; } const dirname = pathDirname(filename); @@ -1065,12 +1054,7 @@ Module._extensions[".js"] = function (module, filename) { if (StringPrototypeEndsWith(filename, ".js")) { const pkg = op_require_read_closest_package_json(filename); if (pkg?.typ === "module") { - // TODO(https://github.com/denoland/deno/issues/24822): implement require esm format = "module"; - throw createRequireEsmError( - filename, - moduleParentCache.get(module)?.filename, - ); } else if (pkg?.type === "commonjs") { format = "commonjs"; } @@ -1081,20 +1065,19 @@ Module._extensions[".js"] = function (module, filename) { module._compile(content, filename, format); }; -function createRequireEsmError(filename, parent) { - let message = `require() of ES Module ${filename}`; - - if (parent) { - message += ` from ${parent}`; - } +function loadESMFromCJS(module, filename, code) { + const namespace = op_import_sync( + url.pathToFileURL(filename).toString(), + code, + ); - message += - ` not supported. Instead change the require to a dynamic import() which is available in all CommonJS modules.`; - const err = new Error(message); - err.code = "ERR_REQUIRE_ESM"; - return err; + module.exports = namespace; } +Module._extensions[".mjs"] = function (module, filename) { + loadESMFromCJS(module, filename); +}; + function stripBOM(content) { if (StringPrototypeCharCodeAt(content, 0) === 0xfeff) { content = StringPrototypeSlice(content, 1); |