diff --git a/packages/commonjs/src/resolve-require-sources.js b/packages/commonjs/src/resolve-require-sources.js index db1603dd5..5f7fe0726 100644 --- a/packages/commonjs/src/resolve-require-sources.js +++ b/packages/commonjs/src/resolve-require-sources.js @@ -196,16 +196,21 @@ export function getRequireResolver(extensions, detectCyclesAndConditional, curre // Special-case external Node built-ins to be handled via a lazy __require // helper instead of hoisted ESM imports when strict wrapping is used. const isExternalWrapped = isWrappedId(dependencyId, EXTERNAL_SUFFIX); - if ( - parentMeta.initialCommonJSType === IS_WRAPPED_COMMONJS && - !allowProxy && - isExternalWrapped - ) { + let resolvedDependencyId = dependencyId; + if (parentMeta.isCommonJS === IS_WRAPPED_COMMONJS && !allowProxy && isExternalWrapped) { const actualExternalId = unwrapId(dependencyId, EXTERNAL_SUFFIX); if (actualExternalId.startsWith('node:')) { isCommonJS = IS_WRAPPED_COMMONJS; parentMeta.isRequiredCommonJS[dependencyId] = isCommonJS; } + } else if (isExternalWrapped && !allowProxy) { + // If the parent is not wrapped but the dependency is a node: builtin external, + // unwrap the EXTERNAL_SUFFIX so it's treated as a normal external. + // This avoids trying to load the lazy __require proxy for non-wrapped contexts. + const actualExternalId = unwrapId(dependencyId, EXTERNAL_SUFFIX); + if (actualExternalId.startsWith('node:')) { + resolvedDependencyId = actualExternalId; + } } const isWrappedCommonJS = isCommonJS === IS_WRAPPED_COMMONJS; fullyAnalyzedModules[dependencyId] = true; @@ -226,8 +231,8 @@ export function getRequireResolver(extensions, detectCyclesAndConditional, curre wrappedModuleSideEffects, source: sources[index].source, id: allowProxy - ? wrapId(dependencyId, isWrappedCommonJS ? WRAPPED_SUFFIX : PROXY_SUFFIX) - : dependencyId, + ? wrapId(resolvedDependencyId, isWrappedCommonJS ? WRAPPED_SUFFIX : PROXY_SUFFIX) + : resolvedDependencyId, isCommonJS }; }); diff --git a/packages/commonjs/test/fixtures/function/strict-requires-auto-external-node-builtin/_config.js b/packages/commonjs/test/fixtures/function/strict-requires-auto-external-node-builtin/_config.js new file mode 100644 index 000000000..6001fc98a --- /dev/null +++ b/packages/commonjs/test/fixtures/function/strict-requires-auto-external-node-builtin/_config.js @@ -0,0 +1,13 @@ +module.exports = { + description: 'handles node: builtins correctly with strictRequires: auto', + pluginOptions: { + strictRequires: 'auto' + }, + exports: (exports, t) => { + // Should be able to access properties of node:stream + t.truthy(exports.Readable); + t.is(typeof exports.Readable, 'function'); + // Should be able to instantiate + t.truthy(exports.readable); + } +}; diff --git a/packages/commonjs/test/fixtures/function/strict-requires-auto-external-node-builtin/main.js b/packages/commonjs/test/fixtures/function/strict-requires-auto-external-node-builtin/main.js new file mode 100644 index 000000000..d69942f74 --- /dev/null +++ b/packages/commonjs/test/fixtures/function/strict-requires-auto-external-node-builtin/main.js @@ -0,0 +1,4 @@ +const stream = require('node:stream'); +const readable = new stream.Readable({}); + +module.exports = { Readable: stream.Readable, readable }; diff --git a/packages/commonjs/test/snapshots/function.js.md b/packages/commonjs/test/snapshots/function.js.md index d42cefb65..324a7f2ca 100644 --- a/packages/commonjs/test/snapshots/function.js.md +++ b/packages/commonjs/test/snapshots/function.js.md @@ -8715,6 +8715,34 @@ Generated by [AVA](https://avajs.dev). `, } +## strict-requires-auto-external-node-builtin + +> Snapshot 1 + + { + 'main.js': `'use strict';␊ + ␊ + var require$$0 = require('node:stream');␊ + ␊ + function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }␊ + ␊ + var require$$0__default = /*#__PURE__*/_interopDefaultCompat(require$$0);␊ + ␊ + function getDefaultExportFromCjs (x) {␊ + return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;␊ + }␊ + ␊ + const stream = require$$0__default.default;␊ + const readable = new stream.Readable({});␊ + ␊ + var main = { Readable: stream.Readable, readable };␊ + ␊ + var main$1 = /*@__PURE__*/getDefaultExportFromCjs(main);␊ + ␊ + module.exports = main$1;␊ + `, + } + ## strict-requires-circular > Snapshot 1 diff --git a/packages/commonjs/test/snapshots/function.js.snap b/packages/commonjs/test/snapshots/function.js.snap index 591ed4029..3d1906593 100644 Binary files a/packages/commonjs/test/snapshots/function.js.snap and b/packages/commonjs/test/snapshots/function.js.snap differ