From 976d80f2089a480e5c6f68c3e8fb485bc04106e7 Mon Sep 17 00:00:00 2001 From: Pionxzh Date: Sat, 30 Mar 2024 02:32:53 +0800 Subject: [PATCH] fix(un-indirect-call): better naming conflicts handling --- .../__tests__/un-indirect-call.spec.ts | 47 +++++++++++++++++-- .../src/transformations/un-indirect-call.ts | 10 +++- 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/packages/unminify/src/transformations/__tests__/un-indirect-call.spec.ts b/packages/unminify/src/transformations/__tests__/un-indirect-call.spec.ts index 2cd25f66..88a93696 100644 --- a/packages/unminify/src/transformations/__tests__/un-indirect-call.spec.ts +++ b/packages/unminify/src/transformations/__tests__/un-indirect-call.spec.ts @@ -3,7 +3,7 @@ import transform from '../un-indirect-call' const inlineTest = defineInlineTest(transform) -inlineTest('indirect call from a imported module', +inlineTest('indirect call from imported module', ` import s from "react"; @@ -16,6 +16,39 @@ var countRef = useRef(0); `, ) +inlineTest('indirect call from imported module with existing named import', + ` +import s from "react"; +import { useRef } from "react"; + +var countRef = (0, s.useRef)(0); +`, + ` +import { useRef } from "react"; + +var countRef = useRef(0); +`, +) + +inlineTest('indirect call from imported module with naming conflicts with local variables', + ` +import s from "react"; + +const fn = () => { + const useRef = 1; + (0, s.useRef)(0); +} +`, + ` +import { useRef as useRef_1 } from "react"; + +const fn = () => { + const useRef = 1; + useRef_1(0); +} +`, +) + inlineTest('multiple indirect call from different sources', ` import s from "react"; @@ -38,7 +71,7 @@ var thirdRef = useRef_1(0); `, ) -inlineTest('indirect call from a required module', +inlineTest('indirect call from required module', ` const s = require("react"); @@ -150,9 +183,9 @@ var thirdRef = useRef_1(0); `, ) -inlineTest.fixme('indirect call with naming conflicts with local variables', +inlineTest('indirect call from required module with naming conflicts with local variables', ` -import s from "react"; +const s = require("react"); const fn = () => { const useRef = 1; @@ -160,7 +193,11 @@ const fn = () => { } `, ` -import { useRef as useRef_1 } from "react"; +const s = require("react"); + +const { + useRef: useRef_1 +} = s; const fn = () => { const useRef = 1; diff --git a/packages/unminify/src/transformations/un-indirect-call.ts b/packages/unminify/src/transformations/un-indirect-call.ts index ccc8207c..52db3039 100644 --- a/packages/unminify/src/transformations/un-indirect-call.ts +++ b/packages/unminify/src/transformations/un-indirect-call.ts @@ -1,4 +1,5 @@ import { isTopLevel } from '@wakaru/ast-utils' +import { assertScopeExists } from '@wakaru/ast-utils/assert' import { generateName } from '@wakaru/ast-utils/identifier' import { ImportManager } from '@wakaru/ast-utils/imports' import { insertAfter } from '@wakaru/ast-utils/insert' @@ -71,6 +72,9 @@ export const transformAST: ASTTransformation = (context) => { }, }) .forEach((path) => { + const scope = path.scope + assertScopeExists(scope) + const { node } = path const callee = node.callee as SequenceExpression const memberExpression = callee.expressions[1] as MemberExpression @@ -103,12 +107,14 @@ export const transformAST: ASTTransformation = (context) => { const namedImportLocalName = [...(importManager.namedImports.get(source)?.get(namedSpecifierName) ?? [])][0] if (namedImportLocalName) { replaceMapping.set(key, namedImportLocalName) + processedImportSources.add(source) + const newCallExpression = j.callExpression(j.identifier(namedImportLocalName), node.arguments) path.replace(newCallExpression) return } - const namedSpecifierLocalName = generateName(namedSpecifierName, rootScope, importManager.getAllLocals()) + const namedSpecifierLocalName = generateName(namedSpecifierName, scope, importManager.getAllLocals()) importManager.addNamedImport(source, namedSpecifierName, namedSpecifierLocalName) replaceMapping.set(key, namedSpecifierLocalName) processedImportSources.add(source) @@ -154,7 +160,7 @@ export const transformAST: ASTTransformation = (context) => { if (propertyDecl.size() === 0) { // generate `const { useRef: useRef_1 } = react` const key = j.identifier(property.name) - const valueName = generateName(property.name, rootScope, [...replaceMapping.values()]) + const valueName = generateName(property.name, scope, [...replaceMapping.values()]) replaceMapping.set(`${defaultSpecifierName}.${namedSpecifierName}`, valueName) const value = j.identifier(valueName)