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