diff --git a/.gitignore b/.gitignore index dc13f67..530f054 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ coverage .eslintcache .idea *.tgz +pnpm-lock.yaml \ No newline at end of file diff --git a/index.js b/index.js index 2289de3..99712b8 100644 --- a/index.js +++ b/index.js @@ -4,6 +4,10 @@ const {createFilter} = require("@rollup/pluginutils"); const importToGlobals = require("./lib/import-to-globals"); const defaultDynamicWrapper = id => `Promise.resolve(${id})`; +function isVirtualModule(id) { + return id.startsWith("\0"); +} + function createPlugin(globals, {include, exclude, dynamicWrapper = defaultDynamicWrapper} = {}) { if (!globals) { throw new TypeError("Missing mandatory option 'globals'"); @@ -24,14 +28,31 @@ function createPlugin(globals, {include, exclude, dynamicWrapper = defaultDynami if (dynamicWrapperType !== "function") { throw new TypeError(`Unexpected type of 'dynamicWrapper', got '${dynamicWrapperType}'`); } + async function resolveId(importee, _, options) { + if (isVirtualModule(importee) || options.isEntry) return null; + const globalName = getName(importee) + return globalName ? false : null; + } const filter = createFilter(include, exclude); return { name: "rollup-plugin-external-globals", + options, transform }; - + async function options(rawOptions) { + const plugins = Array.isArray(rawOptions.plugins) + ? [...rawOptions.plugins] + : rawOptions.plugins + ? [rawOptions.plugins] + : []; + plugins.unshift({ + name: 'rollup-plugin-external-globals--resolver', + resolveId + }); + return { ...rawOptions, plugins }; + } async function transform(code, id) { - if ((id[0] !== "\0" && !filter(id)) || (isGlobalsObj && Object.keys(globals).every(id => !code.includes(id)))) { + if ((!isVirtualModule(id) && !filter(id)) || (isGlobalsObj && Object.keys(globals).every(id => !code.includes(id)))) { return; } let ast; diff --git a/package-lock.json b/package-lock.json index 28d2a71..1a76961 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "magic-string": "^0.30.10" }, "devDependencies": { + "@rollup/plugin-commonjs": "^26.0.1", "c8": "^10.1.2", "endent": "^2.1.0", "eslint": "^9.5.0", @@ -334,6 +335,96 @@ "node": ">=14" } }, + "node_modules/@rollup/plugin-commonjs": { + "version": "26.0.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-26.0.1.tgz", + "integrity": "sha512-UnsKoZK6/aGIH6AdkptXhNvhaqftcjq3zZdT+LY5Ftms6JR06nADcDsYp5hTU9E2lbJUEOhdlY5J4DNTneM+jQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "commondir": "^1.0.1", + "estree-walker": "^2.0.2", + "glob": "^10.4.1", + "is-reference": "1.2.1", + "magic-string": "^0.30.3" + }, + "engines": { + "node": ">=16.0.0 || 14 >= 14.17" + }, + "peerDependencies": { + "rollup": "^2.68.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-commonjs/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@rollup/plugin-commonjs/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/plugin-commonjs/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@rollup/plugin-commonjs/node_modules/is-reference": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", + "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@rollup/plugin-commonjs/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@rollup/pluginutils": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", @@ -877,6 +968,13 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true, + "license": "MIT" + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", diff --git a/package.json b/package.json index 45bbbd3..0ec219b 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "author": "eight04 ", "license": "MIT", "devDependencies": { + "@rollup/plugin-commonjs": "^26.0.1", "c8": "^10.1.2", "endent": "^2.1.0", "eslint": "^9.5.0", diff --git a/test/test.js b/test/test.js index 0f4a284..69a8372 100644 --- a/test/test.js +++ b/test/test.js @@ -4,6 +4,7 @@ const assert = require("assert"); const rollup = require("rollup"); const {withDir} = require("tempdir-yaml"); const {default: endent} = require("endent"); +const commonjs = require("@rollup/plugin-commonjs"); const createPlugin = require(".."); @@ -482,4 +483,141 @@ describe("main", () => { `); }) ); + + it("require from default", () => + withDir(` + - node_modules: + - bar: + - index.js: | + module.exports = "BAR"; + - foo: + - index.js: | + const bar = require("bar"); + console.log('foo'); + module.exports = (val) => console.log(val || bar); + - entry.js: | + import log from "foo"; + import bar from "bar" + log(bar); + `, async resolve => { + const {output: {"entry.js": {code}}} = await bundle( + resolve("entry.js"), + { + bar: "BAR" + }, + { + plugins: [ + commonjs({ + defaultIsModuleExports: true + }), + { + name: "test", + resolveId(importee) { + if (["foo", "bar"].includes(importee)) { + return resolve(`node_modules/${importee}/index.js`) + } + } + }] + } + ); + assert.equal(code.trim(), endent` + const _global_BAR = BAR; + + const bar = _global_BAR; + console.log('foo'); + var foo = (val) => console.log(val || bar); + + foo(BAR); + `); + }) + ); + + it("require from named exports", () => + withDir(` + - bar.js: | + module.a = "A"; + - entry.js: | + const { a } = require("bar"); + console.log(a); + `, async resolve => { + const {output: {"entry.js": {code}}} = await bundle( + resolve("entry.js"), + { + bar: "BAR" + }, + { + plugins: [ + commonjs({ + defaultIsModuleExports: true + }), + { + name: "test", + resolveId(importee) { + if (["bar"].includes(importee)) { + return resolve(`${importee}.js`) + } + } + }] + } + ); + assert.equal(code.trim(), endent` + var entry = {}; + + const _global_BAR = BAR; + + const { a } = _global_BAR; + console.log(a); + + export { entry as default }; + `); + }) + ); + + it("require in function", () => + withDir(` + - bar.js: | + module.a = "A"; + - foo.js: | + const a = "A" + module.exports = (val) => { + const { a } = require("bar"); + console.log(a); + } + - entry.js: | + import log from "foo"; + import { a } from "bar"; + log(a); + `, async resolve => { + const {output: {"entry.js": {code}}} = await bundle( + resolve("entry.js"), + { + bar: "BAR" + }, + { + plugins: [ + commonjs({ + defaultIsModuleExports: true + }), + { + name: "test", + resolveId(importee) { + if (["foo", "bar"].includes(importee)) { + return resolve(`${importee}.js`) + } + } + }] + } + ); + assert.equal(code.trim(), endent` + const _global_BAR = BAR; + + var foo = (val) => { + const { a } = _global_BAR; + console.log(a); + }; + + foo(BAR.a); + `); + }) + ); });