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.cmdArgs = this.initCmdEnv(); 59 this.logger = rollupObject.share.getLogger(GEN_ABC_PLUGIN_NAME); 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 if (this.arkConfig.isDebug) { 93 args.push('--debug-info'); 94 } 95 if (this.arkConfig.isBranchElimination) { 96 args.push('--branch-elimination'); 97 } 98 } else { 99 this.throwArkTsCompilerError(`ArkTS:INTERNAL ERROR: Invalid compilation mode.`); 100 } 101 102 return args; 103 } 104 105 private genHashJsonFilePath() { 106 if (this.projectConfig.cachePath) { 107 if (!fs.existsSync(this.projectConfig.cachePath) || !fs.statSync(this.projectConfig.cachePath).isDirectory()) { 108 this.logger.debug(blue, `ArkTS:WARN cache path does bit exist or is not directory`, reset); 109 return ''; 110 } 111 const hashJsonPath: string = path.join(genTemporaryModuleCacheDirectoryForBundle(this.projectConfig), HASH_FILE_NAME); 112 validateFilePathLength(hashJsonPath, this.logger); 113 mkdirsSync(path.dirname(hashJsonPath)); 114 return hashJsonPath; 115 } else { 116 this.logger.debug(blue, `ArkTS:WARN cache path not specified`, reset); 117 return ''; 118 } 119 } 120 121 setupCluster(cluster: Object): void { 122 cluster.removeAllListeners('exit'); 123 if (nodeLargeOrEqualTargetVersion(16)) { 124 cluster.setupPrimary({ 125 exec: this.genAbcScriptPath, 126 windowsHide: true 127 }); 128 } else { 129 cluster.setupMaster({ 130 exec: this.genAbcScriptPath, 131 windowsHide: true 132 }); 133 } 134 } 135 136 protected needRemoveCacheInfo(rollupObject: Object): boolean { 137 return rollupObject.cache.get(IS_CACHE_INVALID) || rollupObject.cache.get(IS_CACHE_INVALID) === undefined; 138 } 139 140 protected removeCacheInfo(rollupObject: Object): void { 141 if (this.needRemoveCacheInfo(rollupObject)) { 142 this.removeCompilationCache(); 143 } 144 rollupObject.cache.set(IS_CACHE_INVALID, false); 145 } 146 147 abstract removeCompilationCache(): void; 148} 149