1/* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import path from 'path'; 17import ts from 'typescript'; 18import fs from 'fs'; 19 20import { SourceMapGenerator } from './fast_build/ark_compiler/generate_sourcemap'; 21import { 22 EXTNAME_TS, 23 EXTNAME_ETS 24} from './pre_define'; 25import { 26 genTemporaryPath, 27 mkdirsSync, 28 toUnixPath, 29} from './utils'; 30import { 31 newSourceMaps as webpackNewSourceMaps, 32 transformModuleSpecifier, 33 writeObfuscatedSourceCode, 34} from './ark_utils'; 35import { processSystemApi } from './validate_ui_syntax'; 36import { isDebug } from './fast_build/ark_compiler/utils'; 37import { getRelativeSourcePath } from './fast_build/ark_compiler/common/ob_config_resolver'; 38import { 39 CompileEvent, 40 createAndStartEvent, 41 stopEvent, 42 } from './performance'; 43 44export const SRC_MAIN: string = 'src/main'; 45 46export async function writeFileSyncByNode(node: ts.SourceFile, projectConfig: Object, metaInfo: Object, moduleId?: string, 47 parentEvent?: CompileEvent, logger?: Object): Promise<void> { 48 const eventWriteFileSyncByNode = createAndStartEvent(parentEvent, 'write file sync by node'); 49 const eventGenContentAndSourceMapInfo = createAndStartEvent(eventWriteFileSyncByNode, 'generate content and source map information'); 50 const mixedInfo: { content: string, sourceMapJson: ts.RawSourceMap } = genContentAndSourceMapInfo(node, moduleId, projectConfig, metaInfo); 51 const sourceMapGenerator = SourceMapGenerator.getInstance(); 52 stopEvent(eventGenContentAndSourceMapInfo); 53 54 /** 55 * In the following situation: 56 * A typescript source file whose name is 'Test.ts', which is used via `import xxx for 'test'` in another source file. 57 58 * The value of "node.fileName" consists of "test.ts", which does not correspond with the source file's actual name and would lead to a compilation error. 59 * The value of moduleId is same as the actual file name, so it would be used here for locating the target source file. 60 61 * Note: current realization is related to the moduleId mechanism in the rollup framework, which is needed to be reconsidered to improve the code robustness. 62 * In the current realization, when moduleId mechanism is changed, there would be a compilation error. 63 */ 64 let filePath: string = moduleId ? moduleId : node.fileName; 65 let temporaryFile: string = genTemporaryPath(filePath, projectConfig.projectPath, process.env.cachePath, 66 projectConfig, metaInfo); 67 if (temporaryFile.length === 0) { 68 return; 69 } 70 if (temporaryFile.endsWith(EXTNAME_ETS)) { 71 temporaryFile = temporaryFile.replace(/\.ets$/, EXTNAME_TS); 72 } 73 let relativeFilePath = getRelativeSourcePath(filePath, projectConfig.projectRootPath, metaInfo?.belongProjectPath); 74 let sourceMaps: Object; 75 if (process.env.compileTool === 'rollup') { 76 const key = sourceMapGenerator.isNewSourceMaps() ? moduleId! : relativeFilePath; 77 sourceMapGenerator.fillSourceMapPackageInfo(moduleId!, mixedInfo.sourceMapJson); 78 sourceMapGenerator.updateSourceMap(key, mixedInfo.sourceMapJson); 79 sourceMaps = sourceMapGenerator.getSourceMaps(); 80 } else { 81 webpackNewSourceMaps[relativeFilePath] = mixedInfo.sourceMapJson; 82 sourceMaps = webpackNewSourceMaps; 83 } 84 if (!isDebug(projectConfig)) { 85 const eventWriteObfuscatedSourceCode = createAndStartEvent(eventWriteFileSyncByNode, 'write obfuscated source code'); 86 await writeObfuscatedSourceCode({ 87 content: mixedInfo.content, 88 buildFilePath: temporaryFile, 89 relativeSourceFilePath: relativeFilePath, 90 originSourceFilePath: node.fileName, 91 rollupModuleId: moduleId ? moduleId : undefined 92 }, logger, projectConfig, sourceMaps); 93 stopEvent(eventWriteObfuscatedSourceCode); 94 return; 95 } 96 mkdirsSync(path.dirname(temporaryFile)); 97 fs.writeFileSync(temporaryFile, mixedInfo.content); 98 stopEvent(eventWriteFileSyncByNode); 99} 100 101function genContentAndSourceMapInfo(node: ts.SourceFile, moduleId: string | undefined, projectConfig: Object, metaInfo: Object): Object { 102 const printer: ts.Printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed }); 103 const options: ts.CompilerOptions = { 104 sourceMap: true 105 }; 106 const mapOpions: Object = { 107 sourceMap: true, 108 inlineSourceMap: false, 109 inlineSources: false, 110 sourceRoot: '', 111 mapRoot: '', 112 extendedDiagnostics: false 113 }; 114 const host: ts.CompilerHost = ts.createCompilerHost(options); 115 const fileName: string = moduleId ? moduleId : node.fileName; 116 // @ts-ignore 117 const sourceMapGenerator: ts.SourceMapGenerator = ts.createSourceMapGenerator( 118 host, 119 // @ts-ignore 120 ts.getBaseFileName(fileName), 121 '', 122 '', 123 mapOpions 124 ); 125 // @ts-ignore 126 const writer: ts.EmitTextWriter = ts.createTextWriter( 127 // @ts-ignore 128 ts.getNewLineCharacter({ newLine: ts.NewLineKind.LineFeed, removeComments: false })); 129 printer.writeFile(node, writer, sourceMapGenerator); 130 const sourceMapJson: ts.RawSourceMap = sourceMapGenerator.toJSON(); 131 sourceMapJson.sources = [ 132 toUnixPath(fileName).startsWith(toUnixPath(projectConfig.projectRootPath)) ? 133 toUnixPath(fileName).replace(toUnixPath(projectConfig.projectRootPath) + '/', '') : 134 toUnixPath(fileName).replace(toUnixPath(metaInfo.belongProjectPath) + '/', '') 135 ]; 136 let content: string = writer.getText(); 137 if (process.env.compileTool !== 'rollup') { 138 content = transformModuleSpecifier(fileName, processSystemApi(content, true), projectConfig); 139 } 140 141 return { 142 content: content, 143 sourceMapJson: sourceMapJson 144 }; 145} 146