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 { newSourceMaps as rollupNewSourceMaps } from './fast_build/ark_compiler/transform'; 21import { 22 EXTNAME_TS, 23 EXTNAME_ETS, 24} from './pre_define'; 25import { 26 genTemporaryPath, 27 mkdirsSync, 28 toUnixPath, 29 harFilesRecord, 30 GeneratedFileInHar 31} from './utils'; 32import { 33 genSourceMapFileName, 34 newSourceMaps as webpackNewSourceMaps, 35 transformModuleSpecifier, 36 writeObfuscatedSourceCode, 37 createAndStartEvent, 38 stopEvent 39} from './ark_utils'; 40import { processSystemApi } from './validate_ui_syntax'; 41import { isAotMode, isDebug } from './fast_build/ark_compiler/utils'; 42 43export const SRC_MAIN: string = 'src/main'; 44 45export async function writeFileSyncByNode(node: ts.SourceFile, projectConfig: Object, parentEvent?: Object, logger?: Object): Promise<void> { 46 const eventWriteFileSyncByNode = createAndStartEvent(parentEvent, 'write file sync by node'); 47 const eventGenContentAndSourceMapInfo = createAndStartEvent(eventWriteFileSyncByNode, 'generate content and source map information'); 48 const mixedInfo: {content: string, sourceMapJson: ts.RawSourceMap} = genContentAndSourceMapInfo(node, projectConfig); 49 stopEvent(eventGenContentAndSourceMapInfo); 50 let temporaryFile: string = genTemporaryPath(node.fileName, projectConfig.projectPath, process.env.cachePath, 51 projectConfig); 52 if (temporaryFile.length === 0) { 53 return; 54 } 55 let temporarySourceMapFile: string = ''; 56 if (temporaryFile.endsWith(EXTNAME_ETS)) { 57 temporaryFile = temporaryFile.replace(/\.ets$/, EXTNAME_TS); 58 } 59 temporarySourceMapFile = genSourceMapFileName(temporaryFile); 60 mkdirsSync(path.dirname(temporaryFile)); 61 let relativeSourceFilePath = toUnixPath(node.fileName).replace(toUnixPath(projectConfig.projectRootPath) + '/', ''); 62 let sourceMaps: Object; 63 if (process.env.compileTool === 'rollup') { 64 rollupNewSourceMaps[relativeSourceFilePath] = mixedInfo.sourceMapJson; 65 sourceMaps = rollupNewSourceMaps; 66 } else { 67 webpackNewSourceMaps[relativeSourceFilePath] = mixedInfo.sourceMapJson; 68 sourceMaps = webpackNewSourceMaps; 69 } 70 if (projectConfig.compileHar || (!isDebug(projectConfig) && isAotMode(projectConfig))) { 71 const eventWriteObfuscatedSourceCode = createAndStartEvent(eventWriteFileSyncByNode, 'write obfuscated source code'); 72 await writeObfuscatedSourceCode(mixedInfo.content, temporaryFile, logger, projectConfig, relativeSourceFilePath, sourceMaps, node.fileName); 73 stopEvent(eventWriteObfuscatedSourceCode); 74 return; 75 } 76 fs.writeFileSync(temporaryFile, mixedInfo.content); 77 stopEvent(eventWriteFileSyncByNode); 78} 79 80function genContentAndSourceMapInfo(node: ts.SourceFile, projectConfig: Object): Object { 81 const printer: ts.Printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed }); 82 const options: ts.CompilerOptions = { 83 sourceMap: true 84 }; 85 const mapOpions: Object = { 86 sourceMap: true, 87 inlineSourceMap: false, 88 inlineSources: false, 89 sourceRoot: '', 90 mapRoot: '', 91 extendedDiagnostics: false 92 }; 93 const host: ts.CompilerHost = ts.createCompilerHost(options); 94 const fileName: string = node.fileName; 95 // @ts-ignore 96 const sourceMapGenerator: ts.SourceMapGenerator = ts.createSourceMapGenerator( 97 host, 98 // @ts-ignore 99 ts.getBaseFileName(fileName), 100 '', 101 '', 102 mapOpions 103 ); 104 // @ts-ignore 105 const writer: ts.EmitTextWriter = ts.createTextWriter( 106 // @ts-ignore 107 ts.getNewLineCharacter({newLine: ts.NewLineKind.LineFeed, removeComments: false})); 108 printer['writeFile'](node, writer, sourceMapGenerator); 109 const sourceMapJson: ts.RawSourceMap = sourceMapGenerator.toJSON(); 110 sourceMapJson['sources'] = [toUnixPath(fileName).replace(toUnixPath(projectConfig.projectRootPath) + '/', '')]; 111 let content: string = writer.getText(); 112 if (process.env.compileTool !== 'rollup') { 113 content = transformModuleSpecifier(fileName, processSystemApi(content, true), projectConfig); 114 } 115 116 return { 117 content: content, 118 sourceMapJson: sourceMapJson 119 }; 120} 121