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