107ac75b1Sopenharmony_ci/*
207ac75b1Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
307ac75b1Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
407ac75b1Sopenharmony_ci * you may not use this file except in compliance with the License.
507ac75b1Sopenharmony_ci * You may obtain a copy of the License at
607ac75b1Sopenharmony_ci *
707ac75b1Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
807ac75b1Sopenharmony_ci *
907ac75b1Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1007ac75b1Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1107ac75b1Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1207ac75b1Sopenharmony_ci * See the License for the specific language governing permissions and
1307ac75b1Sopenharmony_ci * limitations under the License.
1407ac75b1Sopenharmony_ci */
1507ac75b1Sopenharmony_ci
1607ac75b1Sopenharmony_ciimport path from 'path';
1707ac75b1Sopenharmony_ciimport ts from 'typescript';
1807ac75b1Sopenharmony_ciimport fs from 'fs';
1907ac75b1Sopenharmony_ci
2007ac75b1Sopenharmony_ciimport { SourceMapGenerator } from './fast_build/ark_compiler/generate_sourcemap';
2107ac75b1Sopenharmony_ciimport {
2207ac75b1Sopenharmony_ci  EXTNAME_TS,
2307ac75b1Sopenharmony_ci  EXTNAME_ETS,
2407ac75b1Sopenharmony_ci} from './pre_define';
2507ac75b1Sopenharmony_ciimport {
2607ac75b1Sopenharmony_ci  genTemporaryPath,
2707ac75b1Sopenharmony_ci  mkdirsSync,
2807ac75b1Sopenharmony_ci  toUnixPath,
2907ac75b1Sopenharmony_ci} from './utils';
3007ac75b1Sopenharmony_ciimport {
3107ac75b1Sopenharmony_ci  genSourceMapFileName,
3207ac75b1Sopenharmony_ci  newSourceMaps as webpackNewSourceMaps,
3307ac75b1Sopenharmony_ci  transformModuleSpecifier,
3407ac75b1Sopenharmony_ci  writeObfuscatedSourceCode,
3507ac75b1Sopenharmony_ci  createAndStartEvent,
3607ac75b1Sopenharmony_ci  stopEvent
3707ac75b1Sopenharmony_ci} from './ark_utils';
3807ac75b1Sopenharmony_ciimport { processSystemApi } from './validate_ui_syntax';
3907ac75b1Sopenharmony_ciimport { isDebug } from './fast_build/ark_compiler/utils';
4007ac75b1Sopenharmony_ciimport { getRelativeSourcePath } from './fast_build/ark_compiler/common/ob_config_resolver';
4107ac75b1Sopenharmony_ci
4207ac75b1Sopenharmony_ciexport const SRC_MAIN: string = 'src/main';
4307ac75b1Sopenharmony_ci
4407ac75b1Sopenharmony_ciexport async function writeFileSyncByNode(node: ts.SourceFile, projectConfig: Object, metaInfo: Object, moduleId?: string,
4507ac75b1Sopenharmony_ci  parentEvent?: Object, logger?: Object): Promise<void> {
4607ac75b1Sopenharmony_ci  const eventWriteFileSyncByNode = createAndStartEvent(parentEvent, 'write file sync by node');
4707ac75b1Sopenharmony_ci  const eventGenContentAndSourceMapInfo = createAndStartEvent(eventWriteFileSyncByNode, 'generate content and source map information');
4807ac75b1Sopenharmony_ci  const mixedInfo: { content: string, sourceMapJson: ts.RawSourceMap } = genContentAndSourceMapInfo(node, moduleId, projectConfig, metaInfo);
4907ac75b1Sopenharmony_ci  const sourceMapGenerator = SourceMapGenerator.getInstance();
5007ac75b1Sopenharmony_ci  stopEvent(eventGenContentAndSourceMapInfo);
5107ac75b1Sopenharmony_ci
5207ac75b1Sopenharmony_ci  /**
5307ac75b1Sopenharmony_ci   * In the following situation:
5407ac75b1Sopenharmony_ci   * A typescript source file whose name is 'Test.ts', which is used via `import xxx for 'test'` in another source file.
5507ac75b1Sopenharmony_ci
5607ac75b1Sopenharmony_ci   * 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.
5707ac75b1Sopenharmony_ci   * The value of moduleId is same as the actual file name, so it would be used here for locating the target source file.
5807ac75b1Sopenharmony_ci
5907ac75b1Sopenharmony_ci   * Note: current realization is related to the moduleId mechanism in the rollup framework, which is needed to be reconsidered to improve the code robustness.
6007ac75b1Sopenharmony_ci   * In the current realization, when moduleId mechanism is changed, there would be a compilation error.
6107ac75b1Sopenharmony_ci   */
6207ac75b1Sopenharmony_ci  let temporaryFile: string = genTemporaryPath(moduleId ? moduleId : node.fileName, projectConfig.projectPath, process.env.cachePath,
6307ac75b1Sopenharmony_ci    projectConfig, metaInfo);
6407ac75b1Sopenharmony_ci  if (temporaryFile.length === 0) {
6507ac75b1Sopenharmony_ci    return;
6607ac75b1Sopenharmony_ci  }
6707ac75b1Sopenharmony_ci  if (temporaryFile.endsWith(EXTNAME_ETS)) {
6807ac75b1Sopenharmony_ci    temporaryFile = temporaryFile.replace(/\.ets$/, EXTNAME_TS);
6907ac75b1Sopenharmony_ci  }
7007ac75b1Sopenharmony_ci  let relativeFilePath = getRelativeSourcePath(moduleId ? moduleId : node.fileName, projectConfig.projectRootPath, metaInfo?.belongProjectPath);
7107ac75b1Sopenharmony_ci  let sourceMaps: Object;
7207ac75b1Sopenharmony_ci  if (process.env.compileTool === 'rollup') {
7307ac75b1Sopenharmony_ci    const key = sourceMapGenerator.isNewSourceMaps() ? moduleId! : relativeFilePath;
7407ac75b1Sopenharmony_ci    sourceMapGenerator.fillSourceMapPackageInfo(moduleId!, mixedInfo.sourceMapJson);
7507ac75b1Sopenharmony_ci    sourceMapGenerator.updateSourceMap(key, mixedInfo.sourceMapJson);
7607ac75b1Sopenharmony_ci    sourceMaps = sourceMapGenerator.getSourceMaps();
7707ac75b1Sopenharmony_ci  } else {
7807ac75b1Sopenharmony_ci    webpackNewSourceMaps[relativeFilePath] = mixedInfo.sourceMapJson;
7907ac75b1Sopenharmony_ci    sourceMaps = webpackNewSourceMaps;
8007ac75b1Sopenharmony_ci  }
8107ac75b1Sopenharmony_ci  if (!isDebug(projectConfig)) {
8207ac75b1Sopenharmony_ci    const eventWriteObfuscatedSourceCode = createAndStartEvent(eventWriteFileSyncByNode, 'write obfuscated source code');
8307ac75b1Sopenharmony_ci    await writeObfuscatedSourceCode({
8407ac75b1Sopenharmony_ci        content: mixedInfo.content,
8507ac75b1Sopenharmony_ci        buildFilePath: temporaryFile,
8607ac75b1Sopenharmony_ci        relativeSourceFilePath: relativeFilePath,
8707ac75b1Sopenharmony_ci        originSourceFilePath: node.fileName,
8807ac75b1Sopenharmony_ci        rollupModuleId: moduleId ? moduleId : undefined
8907ac75b1Sopenharmony_ci      }, logger, projectConfig, sourceMaps);
9007ac75b1Sopenharmony_ci    stopEvent(eventWriteObfuscatedSourceCode);
9107ac75b1Sopenharmony_ci    return;
9207ac75b1Sopenharmony_ci  }
9307ac75b1Sopenharmony_ci  mkdirsSync(path.dirname(temporaryFile));
9407ac75b1Sopenharmony_ci  fs.writeFileSync(temporaryFile, mixedInfo.content);
9507ac75b1Sopenharmony_ci  stopEvent(eventWriteFileSyncByNode);
9607ac75b1Sopenharmony_ci}
9707ac75b1Sopenharmony_ci
9807ac75b1Sopenharmony_cifunction genContentAndSourceMapInfo(node: ts.SourceFile, moduleId: string | undefined, projectConfig: Object, metaInfo: Object): Object {
9907ac75b1Sopenharmony_ci  const printer: ts.Printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
10007ac75b1Sopenharmony_ci  const options: ts.CompilerOptions = {
10107ac75b1Sopenharmony_ci    sourceMap: true
10207ac75b1Sopenharmony_ci  };
10307ac75b1Sopenharmony_ci  const mapOpions: Object = {
10407ac75b1Sopenharmony_ci    sourceMap: true,
10507ac75b1Sopenharmony_ci    inlineSourceMap: false,
10607ac75b1Sopenharmony_ci    inlineSources: false,
10707ac75b1Sopenharmony_ci    sourceRoot: '',
10807ac75b1Sopenharmony_ci    mapRoot: '',
10907ac75b1Sopenharmony_ci    extendedDiagnostics: false
11007ac75b1Sopenharmony_ci  };
11107ac75b1Sopenharmony_ci  const host: ts.CompilerHost = ts.createCompilerHost(options);
11207ac75b1Sopenharmony_ci  const fileName: string = moduleId ? moduleId : node.fileName;
11307ac75b1Sopenharmony_ci  // @ts-ignore
11407ac75b1Sopenharmony_ci  const sourceMapGenerator: ts.SourceMapGenerator = ts.createSourceMapGenerator(
11507ac75b1Sopenharmony_ci    host,
11607ac75b1Sopenharmony_ci    // @ts-ignore
11707ac75b1Sopenharmony_ci    ts.getBaseFileName(fileName),
11807ac75b1Sopenharmony_ci    '',
11907ac75b1Sopenharmony_ci    '',
12007ac75b1Sopenharmony_ci    mapOpions
12107ac75b1Sopenharmony_ci  );
12207ac75b1Sopenharmony_ci  // @ts-ignore
12307ac75b1Sopenharmony_ci  const writer: ts.EmitTextWriter = ts.createTextWriter(
12407ac75b1Sopenharmony_ci    // @ts-ignore
12507ac75b1Sopenharmony_ci    ts.getNewLineCharacter({ newLine: ts.NewLineKind.LineFeed, removeComments: false }));
12607ac75b1Sopenharmony_ci  printer.writeFile(node, writer, sourceMapGenerator);
12707ac75b1Sopenharmony_ci  const sourceMapJson: ts.RawSourceMap = sourceMapGenerator.toJSON();
12807ac75b1Sopenharmony_ci  sourceMapJson.sources = [
12907ac75b1Sopenharmony_ci    toUnixPath(fileName).startsWith(toUnixPath(projectConfig.projectRootPath)) ?
13007ac75b1Sopenharmony_ci    toUnixPath(fileName).replace(toUnixPath(projectConfig.projectRootPath) + '/', '') :
13107ac75b1Sopenharmony_ci    toUnixPath(fileName).replace(toUnixPath(metaInfo.belongProjectPath) + '/', '')
13207ac75b1Sopenharmony_ci  ];
13307ac75b1Sopenharmony_ci  let content: string = writer.getText();
13407ac75b1Sopenharmony_ci  if (process.env.compileTool !== 'rollup') {
13507ac75b1Sopenharmony_ci    content = transformModuleSpecifier(fileName, processSystemApi(content, true), projectConfig);
13607ac75b1Sopenharmony_ci  }
13707ac75b1Sopenharmony_ci
13807ac75b1Sopenharmony_ci  return {
13907ac75b1Sopenharmony_ci    content: content,
14007ac75b1Sopenharmony_ci    sourceMapJson: sourceMapJson
14107ac75b1Sopenharmony_ci  };
14207ac75b1Sopenharmony_ci}
143