• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 fs from 'fs';
17import path from 'path';
18
19import {
20  HASH_FILE_NAME,
21  IS_CACHE_INVALID,
22  GEN_ABC_PLUGIN_NAME,
23  GEN_ABC_SCRIPT,
24  blue,
25  reset,
26  ES2ABC,
27  TS2ABC
28} from './ark_define';
29import { initArkConfig } from './process_ark_config';
30import {
31  nodeLargeOrEqualTargetVersion,
32  mkdirsSync,
33  validateFilePathLength
34} from '../../../utils';
35import {
36  isEs2Abc,
37  isOhModules,
38  isTs2Abc
39} from '../../../ark_utils';
40import {
41  genTemporaryModuleCacheDirectoryForBundle
42} from '../utils';
43import {
44  CommonLogger,
45  LogData,
46  LogDataFactory
47} from '../logger';
48import {
49  ArkTSInternalErrorDescription,
50  ErrorCode
51} from '../error_code';
52
53export abstract class CommonMode {
54  projectConfig: Object;
55  arkConfig: Object;
56  cmdArgs: string[] = [];
57  logger: CommonLogger;
58  hashJsonFilePath: string;
59  genAbcScriptPath: string;
60  triggerAsync: Object;
61  triggerEndSignal: Object;
62  isArkguardEnabled: boolean;
63  isBytecodeObfEnabled: boolean;
64
65  constructor(rollupObject: Object) {
66    this.projectConfig = Object.assign(rollupObject.share.arkProjectConfig, rollupObject.share.projectConfig);
67    this.arkConfig = initArkConfig(this.projectConfig);
68    this.logger = CommonLogger.getInstance(rollupObject);
69    this.cmdArgs = this.initCmdEnv();
70    this.hashJsonFilePath = this.genHashJsonFilePath();
71    this.genAbcScriptPath = path.resolve(__dirname, GEN_ABC_SCRIPT);
72    // Each time triggerAsync() was called, IDE will wait for asynchronous operation to finish before continue excuting.
73    // The finish signal was passed to IDE by calling triggerEndSignal() in the child process created by triggerAsync()
74    // When multiple workers were invoked by triggerAsync(), IDE will wait until the times of calling
75    // triggerEndSignal() matches the number of workers invoked.
76    // If the child process throws an error by calling throwArkTsCompilerError(), IDE will reset the counting state.
77    this.triggerAsync = rollupObject.async;
78    this.triggerEndSignal = rollupObject.signal;
79    this.isArkguardEnabled = rollupObject.share.arkProjectConfig.isArkguardEnabled;
80    this.isBytecodeObfEnabled = rollupObject.share.arkProjectConfig.isBytecodeObfEnabled;
81  }
82
83  initCmdEnv() {
84    let args: string[] = [];
85
86    if (isTs2Abc(this.projectConfig)) {
87      let ts2abc: string = this.arkConfig.ts2abcPath;
88      validateFilePathLength(ts2abc, this.logger);
89
90      ts2abc = '"' + ts2abc + '"';
91      args = [`${this.arkConfig.nodePath}`, '--expose-gc', ts2abc];
92      if (this.arkConfig.isDebug) {
93        args.push('--debug');
94      }
95      if (isOhModules(this.projectConfig)) {
96        args.push('--oh-modules');
97      }
98    } else if (isEs2Abc(this.projectConfig)) {
99      const es2abc: string = this.arkConfig.es2abcPath;
100      validateFilePathLength(es2abc, this.logger);
101
102      args = ['"' + es2abc + '"'];
103      // compile options added here affect both bundle mode and module mode
104      if (this.arkConfig.isDebug) {
105        args.push('--debug-info');
106      }
107    } else {
108      const errInfo: LogData = LogDataFactory.newInstance(
109        ErrorCode.ETS2BUNDLE_INTERNAL_INVALID_COMPILE_MODE,
110        ArkTSInternalErrorDescription,
111        'Invalid compilation mode. ' +
112        `ProjectConfig.pandaMode should be either ${TS2ABC} or ${ES2ABC}.`
113      );
114      this.logger.printErrorAndExit(errInfo);
115    }
116
117    return args;
118  }
119
120  private genHashJsonFilePath() {
121    if (this.projectConfig.cachePath) {
122      if (!fs.existsSync(this.projectConfig.cachePath) || !fs.statSync(this.projectConfig.cachePath).isDirectory()) {
123        this.logger.debug(blue, `ArkTS:WARN cache path does bit exist or is not directory`, reset);
124        return '';
125      }
126      const hashJsonPath: string = path.join(genTemporaryModuleCacheDirectoryForBundle(this.projectConfig), HASH_FILE_NAME);
127      validateFilePathLength(hashJsonPath, this.logger);
128      mkdirsSync(path.dirname(hashJsonPath));
129      return hashJsonPath;
130    } else {
131      this.logger.debug(blue, `ArkTS:WARN cache path not specified`, reset);
132      return '';
133    }
134  }
135
136  setupCluster(cluster: Object): void {
137    cluster.removeAllListeners('exit');
138    if (nodeLargeOrEqualTargetVersion(16)) {
139      cluster.setupPrimary({
140        exec: this.genAbcScriptPath,
141        windowsHide: true
142      });
143    } else {
144      cluster.setupMaster({
145        exec: this.genAbcScriptPath,
146        windowsHide: true
147      });
148    }
149  }
150
151  protected needRemoveCacheInfo(rollupObject: Object): boolean {
152    return rollupObject.cache.get(IS_CACHE_INVALID) || rollupObject.cache.get(IS_CACHE_INVALID) === undefined;
153  }
154
155  protected removeCacheInfo(rollupObject: Object): void {
156    if (this.needRemoveCacheInfo(rollupObject)) {
157      this.removeCompilationCache();
158    }
159    rollupObject.cache.set(IS_CACHE_INVALID, false);
160  }
161
162  abstract removeCompilationCache(): void;
163}
164