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