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