diff --git a/hook.js b/hook.js index 80a3032..09933f9 100644 --- a/hook.js +++ b/hook.js @@ -4,6 +4,7 @@ const { URL } = require('url') const { inspect } = require('util') +const { builtinModules } = require('module') const specifiers = new Map() const isWin = process.platform === 'win32' @@ -131,7 +132,8 @@ function isBareSpecifierFileUrlOrRegex (input) { try { // eslint-disable-next-line no-new const url = new URL(input) - return url.protocol === 'file:' + // We consider node: URLs bare specifiers in this context + return url.protocol === 'file:' || url.protocol === 'node:' } catch (err) { // Anything that fails parsing is a bare specifier return true @@ -149,6 +151,14 @@ function ensureArrayWithBareSpecifiersFileUrlsAndRegex (array, type) { throw new Error(`'${type}' option only supports bare specifiers, file URLs or regular expressions. Invalid entries: ${inspect(invalid)}`) } + // Rather than evaluate whether we have a node: scoped built-in-module for + // every call to resolve, we just add them to include/exclude now. + for (const each of array) { + if (typeof each === 'string' && !each.startsWith('node:') && builtinModules.includes(each)) { + array.push(`node:${each}`) + } + } + return array } diff --git a/test/register/v18.19-include-builtin.mjs b/test/register/v18.19-include-builtin.mjs new file mode 100644 index 0000000..244ad9d --- /dev/null +++ b/test/register/v18.19-include-builtin.mjs @@ -0,0 +1,20 @@ +import { register } from 'module' +import Hook from '../../index.js' +import { strictEqual } from 'assert' + +register('../../hook.mjs', import.meta.url, { data: { include: ['node:util', 'os'] } }) + +const hooked = [] + +Hook((exports, name) => { + hooked.push(name) +}) + +await import('util') +await import('node:os') +await import('fs') +await import('path') + +strictEqual(hooked.length, 2) +strictEqual(hooked[0], 'util') +strictEqual(hooked[1], 'os')