diff --git a/package-lock.json b/package-lock.json index 9feb481..946a8fe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@knighted/specifier", - "version": "3.1.0", + "version": "3.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@knighted/specifier", - "version": "3.1.0", + "version": "3.2.0", "license": "MIT", "dependencies": { "magic-string": "^0.30.21", diff --git a/package.json b/package.json index cee1294..f614468 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@knighted/specifier", - "version": "3.1.0", + "version": "3.2.0", "description": "Node.js tool for updating your ES module and CommonJS specifiers.", "type": "module", "main": "dist", diff --git a/src/format.ts b/src/format.ts index cce2225..dd2b4ee 100644 --- a/src/format.ts +++ b/src/format.ts @@ -391,6 +391,30 @@ const format = async (src: string, ast: ParseResult, cb: Callback) => { 'BlockStatement:exit'() { popScope() }, + ForStatement() { + pushScope() + }, + 'ForStatement:exit'() { + popScope() + }, + ForInStatement() { + pushScope() + }, + 'ForInStatement:exit'() { + popScope() + }, + ForOfStatement() { + pushScope() + }, + 'ForOfStatement:exit'() { + popScope() + }, + SwitchStatement() { + pushScope() + }, + 'SwitchStatement:exit'() { + popScope() + }, CatchClause(node) { pushScope() diff --git a/test/updateSrc.ts b/test/updateSrc.ts index aa08dfe..068dda6 100644 --- a/test/updateSrc.ts +++ b/test/updateSrc.ts @@ -329,4 +329,102 @@ describe('updateSrc', () => { assert.ok(update.indexOf("loader('./outside.mjs')") > -1) }) + + it('does not rewrite require shadowed by for-of scope', async () => { + const update = await specifier.updateSrc( + ` + for (const require of [value => value]) { + require('./skip.js') + } + + require('./rewrite.js') + `, + 'js', + spec => { + return spec.value.replace('.js', '.mjs') + }, + ) + + assert.ok(update.indexOf("require('./skip.js')") > -1) + assert.ok(update.indexOf("require('./rewrite.mjs')") > -1) + }) + + it('does not rewrite require shadowed by for-in scope', async () => { + const update = await specifier.updateSrc( + ` + for (const require in { value: 1 }) { + require('./skip.js') + } + + require('./rewrite.js') + `, + 'js', + spec => { + return spec.value.replace('.js', '.mjs') + }, + ) + + assert.ok(update.indexOf("require('./skip.js')") > -1) + assert.ok(update.indexOf("require('./rewrite.mjs')") > -1) + }) + + it('does not rewrite require shadowed by for scope', async () => { + const update = await specifier.updateSrc( + ` + for (let require = value => value; false; ) { + require('./skip.js') + } + + require('./rewrite.js') + `, + 'js', + spec => { + return spec.value.replace('.js', '.mjs') + }, + ) + + assert.ok(update.indexOf("require('./skip.js')") > -1) + assert.ok(update.indexOf("require('./rewrite.mjs')") > -1) + }) + + it('does not rewrite require shadowed by switch scope', async () => { + const update = await specifier.updateSrc( + ` + switch (0) { + default: + const require = value => value + require('./skip.js') + } + + require('./rewrite.js') + `, + 'js', + spec => { + return spec.value.replace('.js', '.mjs') + }, + ) + + assert.ok(update.indexOf("require('./skip.js')") > -1) + assert.ok(update.indexOf("require('./rewrite.mjs')") > -1) + }) + + it('does not desync createRequire tracking after a re-export declaration', async () => { + const update = await specifier.updateSrc( + ` + export { foo } from './reexport.js' + + const { createRequire } = require('node:module') + const customRequire = createRequire(import.meta.url) + + customRequire('./rewrite.js') + `, + 'js', + spec => { + return spec.value.replace('.js', '.mjs') + }, + ) + + assert.ok(update.indexOf("from './reexport.mjs'") > -1) + assert.ok(update.indexOf("customRequire('./rewrite.mjs')") > -1) + }) })