Skip to content

resolve hook is not run for require #55878

Open
@BadIdeaException

Description

@BadIdeaException

Version

23.0.0

Platform

Linux hooks 6.8.0-47-generic #47~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Wed Oct  2 16:16:55 UTC 2 x86_64 x86_64 x86_64 GNU/Linux

Subsystem

customization hooks

What steps will reproduce the bug?

Set up a module resolution hook that replaces the core fs import with fake.js. Then try to import and require fs, respectively. When importing, fs is replaced as expected. When requiring, the hook is never run.

For the setup:

register.js:

import { register } from 'node:module';
register('./hook.js', import.meta.url);

hook.js:

import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';

export async function resolve(specifier, context, nextResolve) {	
	const path = fileURLToPath(import.meta.url);
	const dir = dirname(path);
	
	if (/fs/.test(specifier)) specifier = join(dir, 'fake.js');

	return nextResolve(specifier, context);
};

fake.js:

export function readFileSync() { return 'foo'; }

Now we're ready for the money part:

index.js

import  {readFileSync} from 'fs';
import { fileURLToPath } from 'node:url';

console.log(readFileSync(fileURLToPath(import.meta.url), 'utf8')); // 'foo'

index.cjs:

const readFileSync = require('fs').readFileSync;

console.log(readFileSync(__filename, 'utf8')); // Prints out the source file

NB: type is set to module in package.json.

How often does it reproduce? Is there a required condition?

Can be reliably reproduced every time.

What is the expected behavior? Why is that the expected behavior?

Resolve hook should be run even for require, and replace fs with fake.js. The output should be foo.

I am basing this expectation off of the documentation (emphasis mine):

module#resolve

The resolve hook chain is responsible for telling Node.js where to find and how to cache a given import statement or expression, or require call.

section "enabling":

my-app.js can also be CommonJS. Customization hooks will run for any modules that it references via import (and optionally require).

What do you see instead?

node --import=./register.js index.js produces foo, as expected.

node --import=./register.js index.cjs prints out the source file - bad. Annotating the resolve hook with a console.log statement shows it is never run.

Additional information

I have asked about this on Stack Overflow but not received any answers.

Metadata

Metadata

Assignees

No one assigned

    Labels

    loadersIssues and PRs related to ES module loaders

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions