From f0d5aa65895f708fc804c11b3e47bf5abe963fc4 Mon Sep 17 00:00:00 2001 From: eight04 Date: Sun, 11 Aug 2024 21:41:05 +0800 Subject: [PATCH 1/3] Fix: add globals, eslint/js --- package-lock.json | 37 +++++++++++++++++++++++++++++++------ package.json | 2 ++ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1a76961..1f5da34 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,10 +15,12 @@ "magic-string": "^0.30.10" }, "devDependencies": { + "@eslint/js": "^9.9.0", "@rollup/plugin-commonjs": "^26.0.1", "c8": "^10.1.2", "endent": "^2.1.0", "eslint": "^9.5.0", + "globals": "^15.9.0", "mocha": "^10.5.2", "rollup": "^4.18.0", "tempdir-yaml": "^0.3.0" @@ -105,10 +107,23 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@eslint/js": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.5.0.tgz", - "integrity": "sha512-A7+AOT2ICkodvtsWnxZP4Xxk3NbZ3VMHd8oihydLRGrJgqqdEz1qSeEgXYyT/Cu8h1TWWsQRejIx48mtjZ5y1w==", + "version": "9.9.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.9.0.tgz", + "integrity": "sha512-hhetes6ZHP3BlXLxmd8K2SNgkhNSi+UcecbnwWKwpP7kyi/uC75DJ1lOOBO3xrC4jyojtGE3YxKZPHfk4yrgug==", "dev": true, "license": "MIT", "engines": { @@ -1177,6 +1192,16 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/@eslint/js": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.5.0.tgz", + "integrity": "sha512-A7+AOT2ICkodvtsWnxZP4Xxk3NbZ3VMHd8oihydLRGrJgqqdEz1qSeEgXYyT/Cu8h1TWWsQRejIx48mtjZ5y1w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/eslint/node_modules/eslint-visitor-keys": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", @@ -1491,9 +1516,9 @@ } }, "node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "version": "15.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", + "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==", "dev": true, "license": "MIT", "engines": { diff --git a/package.json b/package.json index 0ec219b..cf356a0 100644 --- a/package.json +++ b/package.json @@ -36,10 +36,12 @@ "author": "eight04 ", "license": "MIT", "devDependencies": { + "@eslint/js": "^9.9.0", "@rollup/plugin-commonjs": "^26.0.1", "c8": "^10.1.2", "endent": "^2.1.0", "eslint": "^9.5.0", + "globals": "^15.9.0", "mocha": "^10.5.2", "rollup": "^4.18.0", "tempdir-yaml": "^0.3.0" From 6420a484d1a22cf91abcccfae9e41c443f6b365c Mon Sep 17 00:00:00 2001 From: eight04 Date: Sun, 11 Aug 2024 22:00:45 +0800 Subject: [PATCH 2/3] Add: constBindings option --- README.md | 5 ++++- index.d.ts | 5 +++++ index.js | 5 +++-- lib/import-to-globals.js | 14 +++++++------- test/test.js | 36 ++++++++++++++++++++++++++---------- 5 files changed, 45 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 63a5359..cf913cc 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,8 @@ const plugin = createPlugin( { include?: Array, exclude?: Array, - dynamicWrapper?: Function + dynamicWrapper?: Function, + constBindings?: Boolean } = {} ); ``` @@ -119,6 +120,8 @@ const dynamicWrapper = (id) => { Virtual modules are always transformed. +`constBindings` is a boolean. If true, the plugin will use `const` instead of `var` to declare the variable. This usually happens when you try to re-export the global variable. + Changelog --------- diff --git a/index.d.ts b/index.d.ts index c913e0e..583ad7b 100644 --- a/index.d.ts +++ b/index.d.ts @@ -22,6 +22,11 @@ export type ExternalGlobalsOptions = { * [dynamicWrapper] is used to specify dynamic imports. It accepts a variable name and returns an expression */ dynamicWrapper?: (variableName: VariableName) => string; + + /** + * [constBindings] is used to decide whether to use `const` to declare variables. + */ + constBindings?: boolean; }; export declare function externalGlobals( diff --git a/index.js b/index.js index 99712b8..1139568 100644 --- a/index.js +++ b/index.js @@ -8,7 +8,7 @@ function isVirtualModule(id) { return id.startsWith("\0"); } -function createPlugin(globals, {include, exclude, dynamicWrapper = defaultDynamicWrapper} = {}) { +function createPlugin(globals, {include, exclude, dynamicWrapper = defaultDynamicWrapper, constBindings = false} = {}) { if (!globals) { throw new TypeError("Missing mandatory option 'globals'"); } @@ -70,7 +70,8 @@ function createPlugin(globals, {include, exclude, dynamicWrapper = defaultDynami ast, code, getName, - getDynamicWrapper: dynamicWrapper + getDynamicWrapper: dynamicWrapper, + constBindings }); return isTouched ? { code: code.toString(), diff --git a/lib/import-to-globals.js b/lib/import-to-globals.js index 508dbdb..c633cb9 100644 --- a/lib/import-to-globals.js +++ b/lib/import-to-globals.js @@ -32,13 +32,13 @@ function makeGlobalName(prop, name) { return `${name}.${prop}`; } -function writeSpecLocal(code, root, spec, name, tempNames) { +function writeSpecLocal(code, root, spec, name, tempNames, constBindings) { if (spec.isOverwritten) return; // we always need an extra assignment for named export statement // https://github.com/eight04/rollup-plugin-external-globals/issues/19 const localName = `_global_${makeLegalIdentifier(name)}`; if (!tempNames.has(localName)) { - code.appendRight(root.start, `const ${localName} = ${name};\n`); + code.appendRight(root.start, `${constBindings ? "const" : "var"} ${localName} = ${name};\n`); tempNames.add(localName); } if (spec.local.name === localName) { @@ -72,7 +72,7 @@ function writeIdentifier(code, node, parent, name) { } } -function analyzeExportNamed(node, code, getName, tempNames) { +function analyzeExportNamed(node, code, getName, tempNames, constBindings) { if (node.declaration || !node.source || !node.source.value) { return false; } @@ -82,7 +82,7 @@ function analyzeExportNamed(node, code, getName, tempNames) { } for (const spec of node.specifiers) { const globalName = makeGlobalName(spec.local.name, name); - writeSpecLocal(code, node, spec, globalName, tempNames); + writeSpecLocal(code, node, spec, globalName, tempNames, constBindings); } if (node.specifiers.length) { code.overwrite(node.specifiers[node.specifiers.length - 1].end, node.source.end, "}"); @@ -126,7 +126,7 @@ class ExportLeftHand { } } -async function importToGlobals({ast, code, getName, getDynamicWrapper}) { +async function importToGlobals({ast, code, getName, getDynamicWrapper, constBindings}) { await prepare(); let scope = attachScopes(ast, "scope"); const bindings = new Map; @@ -139,7 +139,7 @@ async function importToGlobals({ast, code, getName, getDynamicWrapper}) { if (node.type === "ImportDeclaration") { isTouched = analyzeImport(node, bindings, code, getName, globals) || isTouched; } else if (node.type === "ExportNamedDeclaration") { - isTouched = analyzeExportNamed(node, code, getName, tempNames) || isTouched; + isTouched = analyzeExportNamed(node, code, getName, tempNames, constBindings) || isTouched; } } @@ -160,7 +160,7 @@ async function importToGlobals({ast, code, getName, getDynamicWrapper}) { if (isReference(node, parent)) { if (bindings.has(node.name) && !scope.contains(node.name)) { if (parent.type === "ExportSpecifier") { - writeSpecLocal(code, topStatement, parent, bindings.get(node.name), tempNames); + writeSpecLocal(code, topStatement, parent, bindings.get(node.name), tempNames, constBindings); } else { writeIdentifier(code, node, parent, bindings.get(node.name)); } diff --git a/test/test.js b/test/test.js index 69a8372..5e3d1ea 100644 --- a/test/test.js +++ b/test/test.js @@ -309,8 +309,8 @@ describe("main", () => { mud: "MUD" }); assert.equal(code.trim(), endent` - const _global_FOO_foo = FOO.foo; - const _global_MUD_mud = MUD.mud; + var _global_FOO_foo = FOO.foo; + var _global_MUD_mud = MUD.mud; export { _global_FOO_foo as bar, _global_MUD_mud as mud }; `); @@ -327,7 +327,7 @@ describe("main", () => { foo: "FOO" }); assert.equal(code.trim(), endent` - const _global_FOO_foo = FOO.foo; + var _global_FOO_foo = FOO.foo; export { _global_FOO_foo as bar, _global_FOO_foo as baz }; `); @@ -346,8 +346,8 @@ describe("main", () => { boo: "BOO", }); assert.equal(code.trim(), endent` - const _global_BAK = BAK; - const _global_BOO = BOO; + var _global_BAK = BAK; + var _global_BOO = BOO; export { _global_BOO as BOO, _global_BAK as baz }; `); @@ -383,6 +383,22 @@ describe("main", () => { export {foo}; `, async resolve => { const {output: {"entry.js": {code}}} = await bundle(resolve("entry.js"), {foo: "FOO"}); + assert.equal(code.trim(), endent` + var _global_FOO = FOO; + + export { _global_FOO as foo }; + `); + }) + ); + + it("constBindings", () => + withDir(` + - entry.js: | + import foo from "foo"; + + export {foo}; + `, async resolve => { + const {output: {"entry.js": {code}}} = await bundle(resolve("entry.js"), {foo: "FOO"}, undefined, {constBindings: true}); assert.equal(code.trim(), endent` const _global_FOO = FOO; @@ -401,7 +417,7 @@ describe("main", () => { `, async resolve => { const {output: {"entry.js": {code}}} = await bundle(resolve("entry.js"), {foo: "FOO"}); assert.equal(code.trim(), endent` - const _global_FOO = FOO; + var _global_FOO = FOO; export { _global_FOO as bar, _global_FOO as foo }; `); @@ -418,7 +434,7 @@ describe("main", () => { const {output: {"entry.js": {code}}} = await bundle(resolve("entry.js"), {foo: "FOO"}); assert.equal(code.trim(), endent` console.log(FOO); - const _global_FOO = FOO; + var _global_FOO = FOO; export { _global_FOO as foo }; `); @@ -521,7 +537,7 @@ describe("main", () => { } ); assert.equal(code.trim(), endent` - const _global_BAR = BAR; + var _global_BAR = BAR; const bar = _global_BAR; console.log('foo'); @@ -563,7 +579,7 @@ describe("main", () => { assert.equal(code.trim(), endent` var entry = {}; - const _global_BAR = BAR; + var _global_BAR = BAR; const { a } = _global_BAR; console.log(a); @@ -609,7 +625,7 @@ describe("main", () => { } ); assert.equal(code.trim(), endent` - const _global_BAR = BAR; + var _global_BAR = BAR; var foo = (val) => { const { a } = _global_BAR; From f564f4728f0148e5f8148d799f75730b97d3fe00 Mon Sep 17 00:00:00 2001 From: eight04 Date: Sun, 11 Aug 2024 22:04:35 +0800 Subject: [PATCH 3/3] Add: default --- README.md | 2 +- index.d.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cf913cc..cb90401 100644 --- a/README.md +++ b/README.md @@ -120,7 +120,7 @@ const dynamicWrapper = (id) => { Virtual modules are always transformed. -`constBindings` is a boolean. If true, the plugin will use `const` instead of `var` to declare the variable. This usually happens when you try to re-export the global variable. +`constBindings` is a boolean. If true, the plugin will use `const` instead of `var` to declare the variable. This usually happens when you try to re-export the global variable. Default is false. Changelog --------- diff --git a/index.d.ts b/index.d.ts index 583ad7b..5b852f9 100644 --- a/index.d.ts +++ b/index.d.ts @@ -24,7 +24,7 @@ export type ExternalGlobalsOptions = { dynamicWrapper?: (variableName: VariableName) => string; /** - * [constBindings] is used to decide whether to use `const` to declare variables. + * [constBindings] is used to decide whether to use `const` to declare variables. Default is `false` */ constBindings?: boolean; };