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