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 rollupObject 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'; 18import { 19 COMMONJS, 20 ESM, 21 EXTNAME_PROTO_BIN, 22 EXTNAME_JS, 23 EXTNAME_TS, 24 EXTNAME_ETS 25} from '../../../../lib/fast_build/ark_compiler/common/ark_define'; 26import { 27 ModuleMode, 28 PackageEntryInfo 29} from '../../../../lib/fast_build/ark_compiler/module/module_mode'; 30import { 31 getNormalizedOhmUrlByFilepath, 32 transformOhmurlToPkgName, 33 transformOhmurlToRecordName 34} from '../../../../lib/ark_utils'; 35import { changeFileExtension } from '../../../../lib/fast_build/ark_compiler/utils'; 36import { toUnixPath } from '../../../../lib/utils'; 37import { META } from '../rollup_mock/common'; 38import { sharedModuleSet } from '../../../../lib/fast_build/ark_compiler/check_shared_module'; 39import { SourceMapGenerator } from '../../../../lib/fast_build/ark_compiler/generate_sourcemap'; 40class ModuleModeMock extends ModuleMode { 41 collectModuleFileListMock(rollupObject: object) { 42 const fileList = Array.from(rollupObject.getModuleIds()); 43 this.collectModuleFileList(rollupObject, fileList); 44 } 45 46 addModuleInfoItemMock(rollupObject: object, isCommonJs: boolean, extName: string) { 47 const mockFileList = rollupObject.getModuleIds(); 48 for (const filePath of mockFileList) { 49 if (filePath.endsWith(EXTNAME_TS) || filePath.endsWith(EXTNAME_ETS) || filePath.endsWith(EXTNAME_JS)) { 50 const subStrings: string = filePath.split('.'); 51 52 const moduleInfo: object = rollupObject.getModuleInfo(filePath); 53 const metaInfo: object = moduleInfo[META]; 54 this.addModuleInfoItem(filePath, isCommonJs, extName, metaInfo, this.moduleInfos, subStrings[subStrings.length - 1]); 55 } 56 } 57 } 58 59 addSourceMapMock(rollupObject: object, sourceMapGenerator: SourceMapGenerator) { 60 for (const filePath of rollupObject.getModuleIds()) { 61 const isValidSuffix: boolean = 62 filePath.endsWith(EXTNAME_TS) || filePath.endsWith(EXTNAME_ETS) || filePath.endsWith(EXTNAME_JS); 63 if (!isValidSuffix) 64 continue; 65 if (sourceMapGenerator.isNewSourceMaps()) { 66 sourceMapGenerator.updateSourceMap(filePath, {}); 67 } else { 68 const filePathCache: string = this.genFileCachePath( 69 filePath, this.projectConfig.projectRootPath, this.projectConfig.cachePath) 70 sourceMapGenerator.updateSourceMap( 71 filePathCache.replace(this.projectConfig.projectRootPath + path.sep, ''), {}); 72 } 73 } 74 } 75 76 static getModuleInfosAndSourceMapMock(rollupObject: object, sourceMapGenerator: SourceMapGenerator) { 77 const moduleMode = new ModuleModeMock(rollupObject); 78 moduleMode.addSourceMapMock(rollupObject, sourceMapGenerator); 79 moduleMode.addModuleInfoItemMock(rollupObject, false, ''); 80 return { moduleInfos: moduleMode.moduleInfos, sourceMap: sourceMapGenerator.getSourceMaps() }; 81 } 82 83 generateCompileFilesInfoMock(includeByteCodeHarInfo: boolean) { 84 this.generateCompileFilesInfo(includeByteCodeHarInfo); 85 } 86 87 generateNpmEntriesInfoMock() { 88 this.generateNpmEntriesInfo(); 89 } 90 91 generateAbcCacheFilesInfoMock() { 92 this.generateAbcCacheFilesInfo(); 93 } 94 95 generateCompileContextInfoMock(rollupObject: object): void { 96 this.compileContextInfoPath = this.generateCompileContextInfo(rollupObject); 97 } 98 99 checkGenerateCompileContextInfo(rollupObject: object): boolean { 100 const cacheCompileContextInfo = fs.readFileSync(this.compileContextInfoPath, 'utf-8'); 101 102 let compileContextInfo: Object = {}; 103 let hspPkgNames: Array<string> = []; 104 for (const hspName in rollupObject.share.projectConfig.hspNameOhmMap) { 105 let hspPkgName: string = hspName; 106 if (rollupObject.share.projectConfig.dependencyAliasMap.has(hspName)) { 107 hspPkgName = rollupObject.share.projectConfig.dependencyAliasMap.get(hspName); 108 } 109 hspPkgNames.push(toUnixPath(hspPkgName)); 110 } 111 compileContextInfo.hspPkgNames = hspPkgNames; 112 let compileEntries: Set<string> = new Set(); 113 let entryObj: Object = this.projectConfig.entryObj; 114 if (this.projectConfig.widgetCompile) { 115 entryObj = this.projectConfig.cardEntryObj; 116 } 117 for (const key in entryObj) { 118 let moduleId: string = entryObj[key]; 119 let moduleInfo: Object = rollupObject.getModuleInfo(moduleId); 120 if (!moduleInfo) { 121 this.throwArkTsCompilerError(red, `ArkTS:INTERNAL ERROR: Failed to find module info.\n` + 122 `Error Message: Failed to find module info with '${moduleId}' from the context information.`, reset); 123 } 124 let metaInfo: Object = moduleInfo.meta; 125 if (!metaInfo) { 126 this.throwArkTsCompilerError(red, `ArkTS:INTERNAL ERROR: Failed to find meta info.\n` + 127 `Error Message: Failed to find meta info with '${moduleId}' from the module info.`, reset); 128 } 129 const pkgParams = { 130 pkgName: metaInfo.pkgName, 131 pkgPath: metaInfo.pkgPath, 132 isRecordName: true 133 }; 134 let recordName: string = getNormalizedOhmUrlByFilepath(moduleId, rollupObject.share.projectConfig, 135 rollupObject.share.logger, pkgParams, undefined); 136 compileEntries.add(recordName); 137 } 138 this.collectDeclarationFilesEntry(compileEntries, hspPkgNames); 139 compileContextInfo.compileEntries = Array.from(compileEntries); 140 if (rollupObject.share.projectConfig.updateVersionInfo) { 141 compileContextInfo.updateVersionInfo = this.projectConfig.updateVersionInfo; 142 } else if (rollupObject.share.projectConfig.pkgContextInfo) { 143 compileContextInfo.pkgContextInfo = this.projectConfig.pkgContextInfo; 144 } 145 if (this.projectConfig.bundleType === 'shared') { 146 compileContextInfo.needModifyRecord = true; 147 compileContextInfo.bundleName = this.projectConfig.bundleName; 148 } 149 if (JSON.stringify(compileContextInfo) === cacheCompileContextInfo) { 150 return true; 151 } 152 return false; 153 } 154 155 checkGenerateCompileFilesInfo(includeByteCodeHarInfo: boolean): boolean { 156 let mockfilesInfo: string = ''; 157 const filesInfo = fs.readFileSync(this.filesInfoPath, 'utf-8'); 158 this.moduleInfos.forEach((info) => { 159 const moduleType: string = info.isCommonJs ? COMMONJS : ESM; 160 const isSharedModule: boolean = sharedModuleSet.has(info.filePath); 161 mockfilesInfo += 162 `${info.cacheFilePath};${info.recordName};${moduleType};${info.sourceFile};${info.packageName};` + 163 `${isSharedModule};${info.originSourceLang}\n`; 164 }); 165 if (includeByteCodeHarInfo) { 166 Object.entries(this.projectConfig.byteCodeHarInfo).forEach(([pkgName, abcInfo]) => { 167 const abcPath: string = toUnixPath(abcInfo.abcPath); 168 mockfilesInfo += `${abcPath};;;;${pkgName};\n`; 169 }); 170 } 171 if (filesInfo === mockfilesInfo) { 172 return true; 173 } 174 return false; 175 } 176 177 checkGenerateNpmEntriesInfo(): boolean { 178 let mockentriesInfo: string = ''; 179 const filesInfo = fs.readFileSync(this.npmEntriesInfoPath, 'utf-8'); 180 for (const value of this.pkgEntryInfos.values()) { 181 mockentriesInfo += `${value.pkgEntryPath}:${value.pkgBuildPath}\n`; 182 } 183 if (filesInfo === mockentriesInfo) { 184 return true; 185 } 186 return false; 187 } 188 189 checkGenerateAbcCacheFilesInfo(): boolean { 190 let mockabcCacheFilesInfo: string = ''; 191 const filesInfo = fs.readFileSync(this.cacheFilePath, 'utf-8'); 192 this.moduleInfos.forEach((info) => { 193 const abcCacheFilePath: string = changeFileExtension(info.cacheFilePath, EXTNAME_PROTO_BIN); 194 mockabcCacheFilesInfo += `${info.cacheFilePath};${abcCacheFilePath}\n`; 195 }); 196 197 const npmEntriesCacheFilePath: string = changeFileExtension(this.npmEntriesInfoPath, EXTNAME_PROTO_BIN); 198 mockabcCacheFilesInfo += `${this.npmEntriesInfoPath};${npmEntriesCacheFilePath}\n`; 199 this.abcPaths.forEach((abcPath) => { 200 let abcCacheFilePath: string = changeFileExtension(abcPath, EXTNAME_PROTO_BIN); 201 mockabcCacheFilesInfo += `${abcPath};${abcCacheFilePath}\n`; 202 }); 203 if (filesInfo === mockabcCacheFilesInfo) { 204 return true; 205 } 206 return false; 207 } 208 209 checkGetPackageEntryInfo(rollup: object, isTestErrorLog: boolean = false) { 210 this.pkgEntryInfos = new Map<String, PackageEntryInfo>(); 211 const mockFileList = rollup.getModuleIds(); 212 for (const filePath of mockFileList) { 213 if (filePath.endsWith(EXTNAME_TS) || filePath.endsWith(EXTNAME_ETS) || filePath.endsWith(EXTNAME_JS)) { 214 const moduleInfos = rollup.getModuleInfo(filePath); 215 moduleInfos.setIsLocalDependency(false); 216 moduleInfos.setIsNodeEntryFile(true); 217 const metaInfo: object = moduleInfos[META]; 218 if (isTestErrorLog) { 219 metaInfo['pkgPath'] = ''; 220 } 221 this.getPackageEntryInfo(filePath, metaInfo, this.pkgEntryInfos); 222 } 223 } 224 } 225 226 updateCachedSourceMapsMock(sourceMapGenerator: Object) { 227 sourceMapGenerator.updateCachedSourceMaps(); 228 } 229 230 buildModuleSourceMapInfoMock(sourceMapGenerator: Object) { 231 sourceMapGenerator.buildModuleSourceMapInfo(); 232 } 233 234 checkModuleSourceMapInfoMock(): boolean { 235 const readSourceMap = fs.readFileSync(this.sourceMapPath, 'utf-8'); 236 const readCacheSourceMap = fs.readFileSync(this.cacheSourceMapPath, 'utf-8'); 237 if (readSourceMap.length == 0 && readCacheSourceMap.length == 0) { 238 return true; 239 } else if (readSourceMap === readCacheSourceMap) { 240 return true; 241 } else { 242 return false; 243 } 244 } 245 246 generateMergedAbcOfEs2AbcMock(parentEvent: Object) { 247 this.generateMergedAbcOfEs2Abc(parentEvent) 248 } 249 250 filterModulesByHashJsonMock() { 251 this.filterModulesByHashJson(); 252 } 253 254 invokeTs2AbcWorkersToGenProtoMock(splittedModules: Object) { 255 this.invokeTs2AbcWorkersToGenProto(splittedModules) 256 } 257 258 259} 260 261export default ModuleModeMock;