diff --git a/tools/package.json b/tools/package.json index c49a18f0a..be1e2633a 100644 --- a/tools/package.json +++ b/tools/package.json @@ -34,7 +34,6 @@ "rimraf": "^5.0.1", "@babel/core": "^7.22.5", "@babel/traverse": "^7.22.5", - "@types/rimraf": "^3.0.2", "uglify-js": "^3.17.0", "walkdir": "^0.4.0" }, diff --git a/tools/src/toggleESMFlagVariable.ts b/tools/src/toggleESMFlagVariable.ts new file mode 100644 index 000000000..36f0031bf --- /dev/null +++ b/tools/src/toggleESMFlagVariable.ts @@ -0,0 +1,44 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import {Visitor, types} from '@babel/core'; + +export interface PluginOptions { + opts?: { + variableIdentifier?: string; + replacementValue?: boolean; + }; +} + +export default function toggleESMFlagVariable(): { + visitor: Visitor; +} { + return { + visitor: { + VariableDeclarator(path, state) { + const opts = state.opts || {}; + const variableIdentifier = opts.variableIdentifier || 'isEsm'; + const replacementValue = opts.replacementValue || false; + const {node} = path; + const identifier = node.id as types.Identifier; + if ( + identifier.name === variableIdentifier && + node.init?.type === 'BooleanLiteral' + ) { + node.init.value = replacementValue; + } + }, + }, + }; +} diff --git a/tools/test/toggleESMFlagVariable.ts b/tools/test/toggleESMFlagVariable.ts new file mode 100644 index 000000000..830081013 --- /dev/null +++ b/tools/test/toggleESMFlagVariable.ts @@ -0,0 +1,73 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import {describe, it} from 'mocha'; +import * as babel from '@babel/core'; +import toggleESMFlagVariable from '../src/toggleESMFlagVariable'; +import * as assert from 'assert'; + +describe('toggle ESM flag variable', () => { + it('does not replace a non-boolean variable named isEsm', async () => { + const program = 'const isEsm = 100;'; + const result = await babel.transformAsync(program, { + plugins: [toggleESMFlagVariable], + }); + + assert.strictEqual(result?.code, program); + }); + + it('replaces isEsm with the default value of false when no argument provided', async () => { + const program = 'const isEsm = true;'; + const expected = 'const isEsm = false;'; + const result = await babel.transformAsync(program, { + plugins: [toggleESMFlagVariable], + }); + + assert.strictEqual(result?.code, expected); + }); + + it('does not replace the user defined variable name when it is non-boolean', async () => { + const program = 'const foo = 100;'; + const result = await babel.transformAsync(program, { + plugins: [[toggleESMFlagVariable, {variableIdentifier: 'foo'}]], + }); + + assert.strictEqual(result?.code, program); + }); + + it('replaces the user defined variable name with the default value of false', async () => { + const program = 'const foo = true;'; + const expected = 'const foo = false;'; + const result = await babel.transformAsync(program, { + plugins: [[toggleESMFlagVariable, {variableIdentifier: 'foo'}]], + }); + + assert.strictEqual(result?.code, expected); + }); + + it('replaces the user defined variable name with the user defined value', async () => { + const program = 'const foo = false;'; + const expected = 'const foo = true;'; + const result = await babel.transformAsync(program, { + plugins: [ + [ + toggleESMFlagVariable, + {variableIdentifier: 'foo', replacementValue: true}, + ], + ], + }); + + assert.strictEqual(result?.code, expected); + }); +}); diff --git a/tools/tsconfig.json b/tools/tsconfig.json index 20be3103a..c96e25a3c 100644 --- a/tools/tsconfig.json +++ b/tools/tsconfig.json @@ -7,5 +7,12 @@ "noImplicitAny": true, "resolveJsonModule": true, }, - "include": ["src/*.ts","test/minify.ts", "test/compileProtos.ts", "test/replaceImportMetaUrl.ts", "test/replaceESMMockingLib.ts"] + "include": [ + "src/*.ts", + "test/minify.ts", + "test/compileProtos.ts", + "test/replaceImportMetaUrl.ts", + "test/replaceESMMockingLib.ts", + "test/toggleESMFlagVariable.ts" + ] }