From b8db3b11a9d6a39dd32b23804f73a9abda0fa7de Mon Sep 17 00:00:00 2001 From: wuhailong Date: Sat, 7 Jun 2025 20:04:12 +0800 Subject: [PATCH] Fix symbols info loss in AST Issue: #ICFWAR Signed-off-by: wuhailong Change-Id: Idfa825b1530d2aae2f45e2c931167651f04209f8 --- compiler/src/process_lazy_import.ts | 11 +-- .../common/process_lazy_import.test.ts | 77 ++++++++++++++++++- 2 files changed, 82 insertions(+), 6 deletions(-) diff --git a/compiler/src/process_lazy_import.ts b/compiler/src/process_lazy_import.ts index 5e87a2e4f..a7004df8a 100644 --- a/compiler/src/process_lazy_import.ts +++ b/compiler/src/process_lazy_import.ts @@ -90,8 +90,8 @@ function updateImportDecl(node: ts.ImportDeclaration, resolver: Object): ts.Impo // eliminate the type symbol // eg: import { type t, x } from '...' --> import { x } from '...' const newNameBindings: ts.ImportSpecifier[] = eliminateTypeSymbol(namedBindings, resolver); - newImportClause = ts.factory.createImportClause(false, importClause.name, - ts.factory.createNamedImports(newNameBindings)); + newImportClause = ts.factory.updateImportClause(importClause, false, importClause.name, + ts.factory.updateNamedImports(namedBindings, newNameBindings)); } else { newImportClause = importClause; } @@ -113,10 +113,11 @@ function eliminateTypeSymbol(namedBindings: ts.NamedImportBindings, resolver: Ob // import { x } from './y' --> propertyName is undefined // import { x as a } from './y' --> propertyName is x newNameBindings.push( - ts.factory.createImportSpecifier( + ts.factory.updateImportSpecifier( + element, false, - element.propertyName ? ts.factory.createIdentifier(element.propertyName.text) : undefined, - ts.factory.createIdentifier(element.name.text) + element.propertyName, + element.name ) ); } diff --git a/compiler/test/ark_compiler_ut/common/process_lazy_import.test.ts b/compiler/test/ark_compiler_ut/common/process_lazy_import.test.ts index ca4b2e72a..2fc025d0b 100644 --- a/compiler/test/ark_compiler_ut/common/process_lazy_import.test.ts +++ b/compiler/test/ark_compiler_ut/common/process_lazy_import.test.ts @@ -25,7 +25,8 @@ import { processJsCodeLazyImport, reExportNoCheckMode, reExportCheckLog, - resetReExportCheckLog + resetReExportCheckLog, + transformLazyImport } from '../../../lib/process_lazy_import'; import { RELEASE } from '../../../lib/fast_build/ark_compiler/common/ark_define'; import { ModuleSourceFile } from '../../../lib/fast_build/ark_compiler/module/module_source_file'; @@ -389,4 +390,78 @@ mocha.describe('process Lazy Imports tests', function () { const result: string = processJsCodeLazyImport('index.js', code, true, 'strict'); expect(result === expectCode).to.be.true; }); + + mocha.it('3-1: test transformLazyImport: the symbol exist after conversion', function () { + const files: Record = { + 'main.ts': ` + import { foo } from './lib'; + console.log(foo); + `, + 'lib.ts': ` + export const foo = 42; + ` + }; + + const fileNames = Object.keys(files); + + const compilerHost = ts.createCompilerHost({}, true); + const getFileKey = (filePath: string) => path.basename(filePath); + + compilerHost.getSourceFile = (filePath, languageVersion) => { + const key = getFileKey(filePath); + const sourceText = files[key]; + return sourceText !== undefined + ? ts.createSourceFile(filePath, sourceText, languageVersion, true) + : undefined; + }; + + compilerHost.readFile = (filePath) => { + const key = getFileKey(filePath); + return files[key]; + }; + + compilerHost.fileExists = (filePath) => { + const key = getFileKey(filePath); + return key in files; + }; + + compilerHost.getCanonicalFileName = fileName => + ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(); + + const program = ts.createProgram(['main.ts'], { + target: ts.ScriptTarget.ESNext, + module: ts.ModuleKind.ESNext + }, compilerHost); + + const checker = program.getTypeChecker(); + + const originalSource = program.getSourceFile('main.ts')!; + const libSource = program.getSourceFile('lib.ts')!; + + const libFooSymbol = (() => { + for (const stmt of libSource.statements) { + if (ts.isVariableStatement(stmt)) { + const decl = stmt.declarationList.declarations[0]; + if (ts.isIdentifier(decl.name) && decl.name.text === 'foo') { + return checker.getSymbolAtLocation(decl.name)!; + } + } + } + })(); + const mockResolver = { + isReferencedAliasDeclaration() { + return true; + } + }; + + const transformed = transformLazyImport(originalSource, mockResolver); + + const importDecl = transformed.statements.find(ts.isImportDeclaration)!; + const specifiers = (importDecl.importClause!.namedBindings as ts.NamedImports).elements; + + for (const spec of specifiers) { + const transformedSymbol = checker.getSymbolAtLocation(spec.name); + expect(transformedSymbol).to.exist; + } + }); }); \ No newline at end of file -- Gitee