diff --git a/packages/commonjs/src/transform.js b/packages/commonjs/src/transform.js index 93e727481..db8cc18f4 100644 --- a/packages/commonjs/src/transform.js +++ b/packages/commonjs/src/transform.js @@ -254,7 +254,7 @@ export function transformCommonjs( } function hasDynamicModuleForPath(source) { - if (!/[/\\]/.test(source)) { + if (!/^(?:\.{0,2}[/\\]|[A-Za-z]:[/\\])/.test(source)) { try { const resolvedPath = normalizePathSlashes( nodeResolveSync(source, { basedir: dirname(id) }) diff --git a/packages/commonjs/test/fixtures/function/dynamic-require-slash-access/_config.js b/packages/commonjs/test/fixtures/function/dynamic-require-slash-access/_config.js new file mode 100755 index 000000000..013229479 --- /dev/null +++ b/packages/commonjs/test/fixtures/function/dynamic-require-slash-access/_config.js @@ -0,0 +1,16 @@ +const { nodeResolve } = require('@rollup/plugin-node-resolve'); + +module.exports = { + description: 'resolves imports of node_modules module with halfway / subfolder access', + options: { + plugins: [nodeResolve()] + }, + pluginOptions: { + dynamicRequireTargets: [ + 'fixtures/function/dynamic-require-slash-access', + 'fixtures/function/dynamic-require-slash-access/sub', + 'fixtures/function/dynamic-require-slash-access/node_modules/custom-module', + 'fixtures/function/dynamic-require-slash-access/node_modules/custom-module2/*.js' + ] + } +}; diff --git a/packages/commonjs/test/fixtures/function/dynamic-require-slash-access/index.js b/packages/commonjs/test/fixtures/function/dynamic-require-slash-access/index.js new file mode 100755 index 000000000..496245dfd --- /dev/null +++ b/packages/commonjs/test/fixtures/function/dynamic-require-slash-access/index.js @@ -0,0 +1 @@ +module.exports = 'same-directory'; diff --git a/packages/commonjs/test/fixtures/function/dynamic-require-slash-access/main.js b/packages/commonjs/test/fixtures/function/dynamic-require-slash-access/main.js new file mode 100755 index 000000000..989622c67 --- /dev/null +++ b/packages/commonjs/test/fixtures/function/dynamic-require-slash-access/main.js @@ -0,0 +1,14 @@ +/* eslint-disable import/no-dynamic-require, global-require */ + +function takeModule(name) { + return require(name); +} + +t.is(takeModule('.'), 'same-directory'); +t.is(takeModule('./'), 'same-directory'); +t.is(takeModule('.//'), 'same-directory'); + +t.is(takeModule('./sub'), 'sub'); + +t.is(takeModule('custom-module'), 'custom-module + sub'); +t.deepEqual(require('./sub/sub'), { parent: 'same-directory', customModule: 'custom-module' }); diff --git a/packages/commonjs/test/fixtures/function/dynamic-require-slash-access/node_modules/custom-module/index.js b/packages/commonjs/test/fixtures/function/dynamic-require-slash-access/node_modules/custom-module/index.js new file mode 100755 index 000000000..26ecfeb0b --- /dev/null +++ b/packages/commonjs/test/fixtures/function/dynamic-require-slash-access/node_modules/custom-module/index.js @@ -0,0 +1 @@ +module.exports = 'custom-module' + ' + ' + require('custom-module2/sub'); diff --git a/packages/commonjs/test/fixtures/function/dynamic-require-slash-access/node_modules/custom-module2/sub.js b/packages/commonjs/test/fixtures/function/dynamic-require-slash-access/node_modules/custom-module2/sub.js new file mode 100755 index 000000000..e74342ce6 --- /dev/null +++ b/packages/commonjs/test/fixtures/function/dynamic-require-slash-access/node_modules/custom-module2/sub.js @@ -0,0 +1 @@ +module.exports = 'sub'; diff --git a/packages/commonjs/test/fixtures/function/dynamic-require-slash-access/sub/index.js b/packages/commonjs/test/fixtures/function/dynamic-require-slash-access/sub/index.js new file mode 100755 index 000000000..e74342ce6 --- /dev/null +++ b/packages/commonjs/test/fixtures/function/dynamic-require-slash-access/sub/index.js @@ -0,0 +1 @@ +module.exports = 'sub'; diff --git a/packages/commonjs/test/fixtures/function/dynamic-require-slash-access/sub/sub.js b/packages/commonjs/test/fixtures/function/dynamic-require-slash-access/sub/sub.js new file mode 100755 index 000000000..a401d8f73 --- /dev/null +++ b/packages/commonjs/test/fixtures/function/dynamic-require-slash-access/sub/sub.js @@ -0,0 +1,10 @@ +/* eslint-disable import/no-dynamic-require, global-require */ + +function takeModule(name) { + return require(name); +} + +module.exports = { + parent: takeModule('..'), + customModule: takeModule('custom-module') +}; diff --git a/packages/commonjs/test/snapshots/function.js.md b/packages/commonjs/test/snapshots/function.js.md index 05c8098dd..df9d83977 100644 --- a/packages/commonjs/test/snapshots/function.js.md +++ b/packages/commonjs/test/snapshots/function.js.md @@ -2750,6 +2750,206 @@ Generated by [AVA](https://avajs.dev). `, } +## dynamic-require-slash-access + +> Snapshot 1 + + { + 'main.js': `'use strict';␊ + ␊ + var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};␊ + ␊ + function commonjsRegister (path, loader) {␊ + DYNAMIC_REQUIRE_LOADERS[path] = loader;␊ + }␊ + ␊ + const DYNAMIC_REQUIRE_LOADERS = Object.create(null);␊ + const DYNAMIC_REQUIRE_CACHE = Object.create(null);␊ + const DEFAULT_PARENT_MODULE = {␊ + id: '<' + 'rollup>', exports: {}, parent: undefined, filename: null, loaded: false, children: [], paths: []␊ + };␊ + const CHECKED_EXTENSIONS = ['', '.js', '.json'];␊ + ␊ + function normalize (path) {␊ + path = path.replace(/\\\\/g, '/');␊ + const parts = path.split('/');␊ + const slashed = parts[0] === '';␊ + for (let i = 1; i < parts.length; i++) {␊ + if (parts[i] === '.' || parts[i] === '') {␊ + parts.splice(i--, 1);␊ + }␊ + }␊ + for (let i = 1; i < parts.length; i++) {␊ + if (parts[i] !== '..') continue;␊ + if (i > 0 && parts[i - 1] !== '..' && parts[i - 1] !== '.') {␊ + parts.splice(--i, 2);␊ + i--;␊ + }␊ + }␊ + path = parts.join('/');␊ + if (slashed && path[0] !== '/')␊ + path = '/' + path;␊ + else if (path.length === 0)␊ + path = '.';␊ + return path;␊ + }␊ + ␊ + function join () {␊ + if (arguments.length === 0)␊ + return '.';␊ + let joined;␊ + for (let i = 0; i < arguments.length; ++i) {␊ + let arg = arguments[i];␊ + if (arg.length > 0) {␊ + if (joined === undefined)␊ + joined = arg;␊ + else␊ + joined += '/' + arg;␊ + }␊ + }␊ + if (joined === undefined)␊ + return '.';␊ + ␊ + return joined;␊ + }␊ + ␊ + function isPossibleNodeModulesPath (modulePath) {␊ + let c0 = modulePath[0];␊ + if (c0 === '/' || c0 === '\\\\') return false;␊ + let c1 = modulePath[1], c2 = modulePath[2];␊ + if ((c0 === '.' && (!c1 || c1 === '/' || c1 === '\\\\')) ||␊ + (c0 === '.' && c1 === '.' && (!c2 || c2 === '/' || c2 === '\\\\'))) return false;␊ + if (c1 === ':' && (c2 === '/' || c2 === '\\\\'))␊ + return false;␊ + return true;␊ + }␊ + ␊ + function dirname (path) {␊ + if (path.length === 0)␊ + return '.';␊ + ␊ + let i = path.length - 1;␊ + while (i > 0) {␊ + const c = path.charCodeAt(i);␊ + if ((c === 47 || c === 92) && i !== path.length - 1)␊ + break;␊ + i--;␊ + }␊ + ␊ + if (i > 0)␊ + return path.substr(0, i);␊ + ␊ + if (path.chartCodeAt(0) === 47 || path.chartCodeAt(0) === 92)␊ + return path.charAt(0);␊ + ␊ + return '.';␊ + }␊ + ␊ + function commonjsRequire (path, originalModuleDir) {␊ + const shouldTryNodeModules = isPossibleNodeModulesPath(path);␊ + path = normalize(path);␊ + let relPath;␊ + while (true) {␊ + if (!shouldTryNodeModules) {␊ + relPath = originalModuleDir ? normalize(originalModuleDir + '/' + path) : path;␊ + } else if (originalModuleDir) {␊ + relPath = normalize(originalModuleDir + '/node_modules/' + path);␊ + } else {␊ + relPath = normalize(join('node_modules', path));␊ + }␊ + for (let extensionIndex = 0; extensionIndex < CHECKED_EXTENSIONS.length; extensionIndex++) {␊ + const resolvedPath = relPath + CHECKED_EXTENSIONS[extensionIndex];␊ + let cachedModule = DYNAMIC_REQUIRE_CACHE[resolvedPath];␊ + if (cachedModule) return cachedModule.exports;␊ + const loader = DYNAMIC_REQUIRE_LOADERS[resolvedPath];␊ + if (loader) {␊ + DYNAMIC_REQUIRE_CACHE[resolvedPath] = cachedModule = {␊ + id: resolvedPath,␊ + filename: resolvedPath,␊ + path: dirname(resolvedPath),␊ + exports: {},␊ + parent: DEFAULT_PARENT_MODULE,␊ + loaded: false,␊ + children: [],␊ + paths: [],␊ + require: function (path, base) {␊ + return commonjsRequire(path, (base === undefined || base === null) ? cachedModule.path : base);␊ + }␊ + };␊ + try {␊ + loader.call(commonjsGlobal, cachedModule, cachedModule.exports);␊ + } catch (error) {␊ + delete DYNAMIC_REQUIRE_CACHE[resolvedPath];␊ + throw error;␊ + }␊ + cachedModule.loaded = true;␊ + return cachedModule.exports;␊ + } }␊ + if (!shouldTryNodeModules) break;␊ + const nextDir = normalize(originalModuleDir + '/..');␊ + if (nextDir === originalModuleDir) break;␊ + originalModuleDir = nextDir;␊ + }␊ + return require(path);␊ + }␊ + ␊ + commonjsRequire.cache = DYNAMIC_REQUIRE_CACHE;␊ + ␊ + var dynamicRequireSlashAccess = 'same-directory';␊ + ␊ + var sub = 'sub';␊ + ␊ + var customModule = 'custom-module' + ' + ' + commonjsRequire("custom-module2/sub", "/$$rollup_base$$/fixtures/function/dynamic-require-slash-access/node_modules/custom-module");␊ + ␊ + commonjsRegister("/$$rollup_base$$/fixtures/function/dynamic-require-slash-access/node_modules/custom-module2/sub.js", function (module, exports) {␊ + module.exports = 'sub';␊ + ␊ + });␊ + ␊ + commonjsRegister("/$$rollup_base$$/fixtures/function/dynamic-require-slash-access", function (module, exports) {␊ + module.exports = dynamicRequireSlashAccess;␊ + });␊ + commonjsRegister("/$$rollup_base$$/fixtures/function/dynamic-require-slash-access/sub", function (module, exports) {␊ + module.exports = sub;␊ + });␊ + commonjsRegister("/$$rollup_base$$/fixtures/function/dynamic-require-slash-access/node_modules/custom-module", function (module, exports) {␊ + module.exports = customModule;␊ + });␊ + ␊ + /* eslint-disable import/no-dynamic-require, global-require */␊ + ␊ + function takeModule(name) {␊ + return commonjsRequire(name,"/$$rollup_base$$/fixtures/function/dynamic-require-slash-access/sub");␊ + }␊ + ␊ + var sub$1 = {␊ + parent: takeModule('..'),␊ + customModule: takeModule('custom-module')␊ + };␊ + ␊ + /* eslint-disable import/no-dynamic-require, global-require */␊ + ␊ + function takeModule$1(name) {␊ + return commonjsRequire(name,"/$$rollup_base$$/fixtures/function/dynamic-require-slash-access");␊ + }␊ + ␊ + t.is(takeModule$1('.'), 'same-directory');␊ + t.is(takeModule$1('./'), 'same-directory');␊ + t.is(takeModule$1('.//'), 'same-directory');␊ + ␊ + t.is(takeModule$1('./sub'), 'sub');␊ + ␊ + t.is(takeModule$1('custom-module'), 'custom-module + sub');␊ + t.deepEqual(sub$1, { parent: 'same-directory', customModule: 'custom-module' });␊ + ␊ + var main = {␊ + ␊ + };␊ + ␊ + module.exports = main;␊ + `, + } + ## es6-export-with-global-sniffing > Snapshot 1 diff --git a/packages/commonjs/test/snapshots/function.js.snap b/packages/commonjs/test/snapshots/function.js.snap index 9503cbcd6..f159e63c2 100644 Binary files a/packages/commonjs/test/snapshots/function.js.snap and b/packages/commonjs/test/snapshots/function.js.snap differ