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_JS, 23 EXTNAME_TS, 24 EXTNAME_ETS, 25 TS_NOCHECK 26} from './pre_define'; 27import { 28 genTemporaryPath, 29 mkdirsSync, 30 toUnixPath, 31} from './utils'; 32import { 33 genSourceMapFileName, 34 newSourceMaps as webpackNewSourceMaps, 35 transformModuleSpecifier, 36 getBuildModeInLowerCase 37} from './ark_utils'; 38import { processSystemApi } from './validate_ui_syntax'; 39import { DEBUG } from './fast_build/ark_compiler/common/ark_define'; 40 41export const SRC_MAIN: string = 'src/main'; 42 43export function writeFileSyncByNode(node: ts.SourceFile, toTsFile: boolean, projectConfig: any): void { 44 if (toTsFile) { 45 const newStatements: ts.Node[] = []; 46 const tsIgnoreNode: ts.Node = ts.factory.createExpressionStatement(ts.factory.createIdentifier(TS_NOCHECK)); 47 newStatements.push(tsIgnoreNode); 48 if (node.statements && node.statements.length) { 49 newStatements.push(...node.statements); 50 } 51 52 node = ts.factory.updateSourceFile(node, newStatements); 53 } 54 const mixedInfo: {content: string, sourceMapJson: any} = genContentAndSourceMapInfo(node, toTsFile, projectConfig); 55 let temporaryFile: string = genTemporaryPath(node.fileName, projectConfig.projectPath, process.env.cachePath, 56 projectConfig); 57 if (temporaryFile.length === 0) { 58 return; 59 } 60 let temporarySourceMapFile: string = ''; 61 if (temporaryFile.endsWith(EXTNAME_ETS)) { 62 if (toTsFile) { 63 temporaryFile = temporaryFile.replace(/\.ets$/, EXTNAME_TS); 64 } else { 65 temporaryFile = temporaryFile.replace(/\.ets$/, EXTNAME_JS); 66 } 67 temporarySourceMapFile = genSourceMapFileName(temporaryFile); 68 } else { 69 if (!toTsFile) { 70 temporaryFile = temporaryFile.replace(/\.ts$/, EXTNAME_JS); 71 temporarySourceMapFile = genSourceMapFileName(temporaryFile); 72 } 73 } 74 mkdirsSync(path.dirname(temporaryFile)); 75 if (temporarySourceMapFile.length > 0 && getBuildModeInLowerCase(projectConfig) === DEBUG) { 76 let source = toUnixPath(node.fileName).replace(toUnixPath(projectConfig.projectRootPath) + '/', ''); 77 process.env.compileTool === 'rollup' ? rollupNewSourceMaps[source] = mixedInfo.sourceMapJson : 78 webpackNewSourceMaps[source] = mixedInfo.sourceMapJson; 79 } 80 fs.writeFileSync(temporaryFile, mixedInfo.content); 81} 82 83function genContentAndSourceMapInfo(node: ts.SourceFile, toTsFile: boolean, projectConfig: any): any { 84 const printer: ts.Printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed }); 85 const options: ts.CompilerOptions = { 86 sourceMap: true 87 }; 88 const mapOpions: any = { 89 sourceMap: true, 90 inlineSourceMap: false, 91 inlineSources: false, 92 sourceRoot: '', 93 mapRoot: '', 94 extendedDiagnostics: false 95 }; 96 const host: ts.CompilerHost = ts.createCompilerHost(options); 97 const fileName: string = node.fileName; 98 // @ts-ignore 99 const sourceMapGenerator: any = ts.createSourceMapGenerator( 100 host, 101 // @ts-ignore 102 ts.getBaseFileName(fileName), 103 '', 104 '', 105 mapOpions 106 ); 107 // @ts-ignore 108 const writer: any = ts.createTextWriter( 109 // @ts-ignore 110 ts.getNewLineCharacter({newLine: ts.NewLineKind.LineFeed, removeComments: false})); 111 printer['writeFile'](node, writer, sourceMapGenerator); 112 const sourceMapJson: any = sourceMapGenerator.toJSON(); 113 sourceMapJson['sources'] = [fileName.replace(toUnixPath(projectConfig.projectRootPath) + '/', '')]; 114 let content: string = writer.getText(); 115 if (toTsFile) { 116 content = content.replace(`${TS_NOCHECK};`, TS_NOCHECK); 117 } 118 if (process.env.compileTool !== 'rollup') { 119 content = transformModuleSpecifier(fileName, processSystemApi(content, true), projectConfig); 120 } 121 122 return { 123 content: content, 124 sourceMapJson: sourceMapJson 125 }; 126} 127