summaryrefslogtreecommitdiff
path: root/ext/node/polyfills/01_require.js
diff options
context:
space:
mode:
authorMarvin Hagemeister <hello@marvinh.dev>2023-03-27 21:54:22 +0200
committerGitHub <noreply@github.com>2023-03-27 21:54:22 +0200
commit8c051dbd1a075ad3c228f78b29b13f0e455972a7 (patch)
tree5f17ffd87ca6e0febab5fa64803570eca4dfb4f5 /ext/node/polyfills/01_require.js
parent101abf35411d26342e6855dc3432cc7f9695dbc8 (diff)
fix(ext/node): add missing _preloadModules hook (#18447)
This internal node hook is used by libraries such as `ts-node` when used as a require hook `node -r ts-node/register`. That combination is often used with test frameworks like `mocha` or `jasmine`. We had a reference to `Module._preloadModules` in our code, but the implementation was missing. While fixing this I also noticed that the `fakeParent` module that we create internally always threw because of the `pathDirname` check on the module id in the constructor of `Mdoule`. So this code path was probably broken for a while. ```txt ✖ ERROR: Error: Empty filepath. at pathDirname (ext:deno_node/01_require.js:245:11) at new Module (ext:deno_node/01_require.js:446:15) at Function.Module._resolveFilename (ext:deno_node/01_require.js:754:28) at Function.resolve (ext:deno_node/01_require.js:1015:19) ```
Diffstat (limited to 'ext/node/polyfills/01_require.js')
-rw-r--r--ext/node/polyfills/01_require.js30
1 files changed, 25 insertions, 5 deletions
diff --git a/ext/node/polyfills/01_require.js b/ext/node/polyfills/01_require.js
index 68398df69..42ead05e3 100644
--- a/ext/node/polyfills/01_require.js
+++ b/ext/node/polyfills/01_require.js
@@ -241,8 +241,10 @@ setupBuiltinModules();
const cjsParseCache = new SafeWeakMap();
function pathDirname(filepath) {
- if (filepath == null || filepath === "") {
+ if (filepath == null) {
throw new Error("Empty filepath.");
+ } else if (filepath === "") {
+ return ".";
}
return ops.op_require_path_dirname(filepath);
}
@@ -605,10 +607,10 @@ Module._nodeModulePaths = function (fromPath) {
Module._resolveLookupPaths = function (request, parent) {
const paths = [];
- if (ops.op_require_is_request_relative(request) && parent?.filename) {
+ if (ops.op_require_is_request_relative(request)) {
ArrayPrototypePush(
paths,
- ops.op_require_path_dirname(parent.filename),
+ parent?.filename ? ops.op_require_path_dirname(parent.filename) : ".",
);
return paths;
}
@@ -752,7 +754,6 @@ Module._resolveFilename = function (
paths = options.paths;
} else {
const fakeParent = new Module("", null);
-
paths = [];
for (let i = 0; i < options.paths.length; i++) {
@@ -828,6 +829,25 @@ Module._resolveFilename = function (
throw err;
};
+/**
+ * Internal CommonJS API to always require modules before requiring the actual
+ * one when calling `require("my-module")`. This is used by require hooks such
+ * as `ts-node/register`.
+ * @param {string[]} requests List of modules to preload
+ */
+Module._preloadModules = function (requests) {
+ if (!ArrayIsArray(requests) || requests.length === 0) {
+ return;
+ }
+
+ const parent = new Module("internal/preload", null);
+ // All requested files must be resolved against cwd
+ parent.paths = Module._nodeModulePaths(process.cwd());
+ for (let i = 0; i < requests.length; i++) {
+ parent.require(requests[i]);
+ }
+};
+
Module.prototype.load = function (filename) {
if (this.loaded) {
throw Error("Module already loaded");
@@ -954,7 +974,7 @@ Module._extensions[".js"] = function (module, filename) {
const content = ops.op_require_read_file(filename);
if (StringPrototypeEndsWith(filename, ".js")) {
- const pkg = ops.op_require_read_closest_package_json(filename);
+ const pkg = ops.op_require_read_package_scope(filename);
if (pkg && pkg.exists && pkg.typ == "module") {
let message = `Trying to import ESM module: ${filename}`;