107ac75b1Sopenharmony_ci/* 207ac75b1Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 307ac75b1Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 407ac75b1Sopenharmony_ci * you may not use this file except in compliance with the License. 507ac75b1Sopenharmony_ci * You may obtain a copy of the License at 607ac75b1Sopenharmony_ci * 707ac75b1Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 807ac75b1Sopenharmony_ci * 907ac75b1Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1007ac75b1Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1107ac75b1Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1207ac75b1Sopenharmony_ci * See the License for the specific language governing permissions and 1307ac75b1Sopenharmony_ci * limitations under the License. 1407ac75b1Sopenharmony_ci */ 1507ac75b1Sopenharmony_ci 1607ac75b1Sopenharmony_ciimport MagicString from 'magic-string'; 1707ac75b1Sopenharmony_ciimport { createFilter } from '@rollup/pluginutils'; 1807ac75b1Sopenharmony_ciimport path from 'path'; 1907ac75b1Sopenharmony_ciimport { 2007ac75b1Sopenharmony_ci NATIVE_MODULE, 2107ac75b1Sopenharmony_ci ARKUI_X_PLUGIN, 2207ac75b1Sopenharmony_ci GLOBAL_THIS_REQUIRE_NATIVE_MODULE, 2307ac75b1Sopenharmony_ci GLOBAL_THIS_REQUIRE_NAPI 2407ac75b1Sopenharmony_ci} from '../../pre_define'; 2507ac75b1Sopenharmony_ciimport { 2607ac75b1Sopenharmony_ci systemModules, 2707ac75b1Sopenharmony_ci projectConfig, 2807ac75b1Sopenharmony_ci sdkConfigs, 2907ac75b1Sopenharmony_ci sdkConfigPrefix, 3007ac75b1Sopenharmony_ci extendSdkConfigs 3107ac75b1Sopenharmony_ci} from '../../../main'; 3207ac75b1Sopenharmony_ci 3307ac75b1Sopenharmony_ciimport { 3407ac75b1Sopenharmony_ci writeUseOSFiles, 3507ac75b1Sopenharmony_ci writeCollectionFile, 3607ac75b1Sopenharmony_ci getAllComponentsOrModules 3707ac75b1Sopenharmony_ci} from '../../utils'; 3807ac75b1Sopenharmony_ciimport { hasTsNoCheckOrTsIgnoreFiles } from '../ark_compiler/utils'; 3907ac75b1Sopenharmony_ci 4007ac75b1Sopenharmony_ciconst filter: any = createFilter(/(?<!\.d)\.(ets|ts|js)$/); 4107ac75b1Sopenharmony_ciconst allFiles: Set<string> = new Set(); 4207ac75b1Sopenharmony_ci 4307ac75b1Sopenharmony_ciexport const appImportModuleCollection: Map<string, Set<string>> = new Map(); 4407ac75b1Sopenharmony_ciexport const kitModules: Map<string, Map<string, Set<string>>> = new Map(); 4507ac75b1Sopenharmony_ci 4607ac75b1Sopenharmony_ciexport function apiTransform() { 4707ac75b1Sopenharmony_ci const useOSFiles: Set<string> = new Set(); 4807ac75b1Sopenharmony_ci let hiresStatus: boolean = true; 4907ac75b1Sopenharmony_ci return { 5007ac75b1Sopenharmony_ci name: 'apiTransform', 5107ac75b1Sopenharmony_ci load(id: string) { 5207ac75b1Sopenharmony_ci allFiles.add(path.join(id)); 5307ac75b1Sopenharmony_ci }, 5407ac75b1Sopenharmony_ci transform(code: string, id: string) { 5507ac75b1Sopenharmony_ci const magicString = new MagicString(code); 5607ac75b1Sopenharmony_ci if (filter(id)) { 5707ac75b1Sopenharmony_ci if (projectConfig.compileMode === 'esmodule') { 5807ac75b1Sopenharmony_ci code = processSystemApiAndLibso(code, id, useOSFiles); 5907ac75b1Sopenharmony_ci hiresStatus = this.share.projectConfig.needCompleteSourcesMap || hasTsNoCheckOrTsIgnoreFiles.includes(id) ? 6007ac75b1Sopenharmony_ci true : 6107ac75b1Sopenharmony_ci false; 6207ac75b1Sopenharmony_ci } else { 6307ac75b1Sopenharmony_ci code = processSystemApi(code, id); 6407ac75b1Sopenharmony_ci code = processLibso(code, id, useOSFiles); 6507ac75b1Sopenharmony_ci hiresStatus = true; 6607ac75b1Sopenharmony_ci } 6707ac75b1Sopenharmony_ci } 6807ac75b1Sopenharmony_ci return { 6907ac75b1Sopenharmony_ci code: code, 7007ac75b1Sopenharmony_ci map: magicString.generateMap({ hires: hiresStatus }) 7107ac75b1Sopenharmony_ci }; 7207ac75b1Sopenharmony_ci }, 7307ac75b1Sopenharmony_ci beforeBuildEnd() { 7407ac75b1Sopenharmony_ci this.share.allComponents = getAllComponentsOrModules(allFiles, 'component_collection.json'); 7507ac75b1Sopenharmony_ci this.share.allFiles = allFiles; 7607ac75b1Sopenharmony_ci }, 7707ac75b1Sopenharmony_ci buildEnd() { 7807ac75b1Sopenharmony_ci if (projectConfig.isPreview && projectConfig.aceSoPath && 7907ac75b1Sopenharmony_ci useOSFiles && useOSFiles.size > 0) { 8007ac75b1Sopenharmony_ci writeUseOSFiles(useOSFiles); 8107ac75b1Sopenharmony_ci } 8207ac75b1Sopenharmony_ci if (process.env.watchMode !== 'true' && !projectConfig.xtsMode) { 8307ac75b1Sopenharmony_ci replaceKitModules(); 8407ac75b1Sopenharmony_ci const allModules: Map<string, Array<string>> = getAllComponentsOrModules(allFiles, 'module_collection.json'); 8507ac75b1Sopenharmony_ci writeCollectionFile(projectConfig.cachePath, appImportModuleCollection, allModules, 'module_collection.json'); 8607ac75b1Sopenharmony_ci } 8707ac75b1Sopenharmony_ci }, 8807ac75b1Sopenharmony_ci cleanUp(): void { 8907ac75b1Sopenharmony_ci allFiles.clear(); 9007ac75b1Sopenharmony_ci appImportModuleCollection.clear(); 9107ac75b1Sopenharmony_ci useOSFiles.clear(); 9207ac75b1Sopenharmony_ci kitModules.clear(); 9307ac75b1Sopenharmony_ci } 9407ac75b1Sopenharmony_ci }; 9507ac75b1Sopenharmony_ci} 9607ac75b1Sopenharmony_ci 9707ac75b1Sopenharmony_ci 9807ac75b1Sopenharmony_cifunction processSystemApi(content: string, sourcePath: string): string { 9907ac75b1Sopenharmony_ci // 'arkui-x' represents cross platform related APIs, processed as 'ohos' 10007ac75b1Sopenharmony_ci const REG_SYSTEM: RegExp = 10107ac75b1Sopenharmony_ci new RegExp(`import\\s+(.+)\\s+from\\s+['"]@(${sdkConfigPrefix})\\.(\\S+)['"]|import\\s+(.+)\\s*=\\s*require\\(\\s*['"]@(${sdkConfigPrefix})\\.(\\S+)['"]\\s*\\)`, 'g'); 10207ac75b1Sopenharmony_ci appImportModuleCollection.set(path.join(sourcePath), new Set()); 10307ac75b1Sopenharmony_ci return content.replace(REG_SYSTEM, (item, item1, item2, item3, item4, item5, item6) => { 10407ac75b1Sopenharmony_ci const moduleType: string = item2 || item5; 10507ac75b1Sopenharmony_ci const systemKey: string = item3 || item6; 10607ac75b1Sopenharmony_ci const systemValue: string = item1 || item4; 10707ac75b1Sopenharmony_ci const systemModule: string = `${moduleType}.${systemKey}`; 10807ac75b1Sopenharmony_ci appImportModuleCollection.get(path.join(sourcePath)).add(systemModule); 10907ac75b1Sopenharmony_ci checkModuleExist(systemModule, sourcePath); 11007ac75b1Sopenharmony_ci const externalModuleParam: string = isExtendModuleType(moduleType) && 11107ac75b1Sopenharmony_ci moduleType !== ARKUI_X_PLUGIN ? `, false, '', '${moduleType}'` : ``; 11207ac75b1Sopenharmony_ci if (NATIVE_MODULE.has(systemModule)) { 11307ac75b1Sopenharmony_ci item = `var ${systemValue} = ${GLOBAL_THIS_REQUIRE_NATIVE_MODULE}('${moduleType}.${systemKey}')`; 11407ac75b1Sopenharmony_ci } else if (checkModuleType(moduleType)) { 11507ac75b1Sopenharmony_ci item = `var ${systemValue} = ${GLOBAL_THIS_REQUIRE_NAPI}('${systemKey}'${externalModuleParam})`; 11607ac75b1Sopenharmony_ci } 11707ac75b1Sopenharmony_ci return item; 11807ac75b1Sopenharmony_ci }); 11907ac75b1Sopenharmony_ci} 12007ac75b1Sopenharmony_ci 12107ac75b1Sopenharmony_ciinterface SdkConfig { 12207ac75b1Sopenharmony_ci apiPath: string; 12307ac75b1Sopenharmony_ci prefix: string; 12407ac75b1Sopenharmony_ci} 12507ac75b1Sopenharmony_ci 12607ac75b1Sopenharmony_cifunction isExtendModuleType(moduleType: string): boolean { 12707ac75b1Sopenharmony_ci for (let i = 0; i < extendSdkConfigs.length; i++) { 12807ac75b1Sopenharmony_ci const config: SdkConfig = extendSdkConfigs[i]; 12907ac75b1Sopenharmony_ci if (config.prefix === `@${moduleType}`) { 13007ac75b1Sopenharmony_ci return true; 13107ac75b1Sopenharmony_ci } 13207ac75b1Sopenharmony_ci } 13307ac75b1Sopenharmony_ci return false; 13407ac75b1Sopenharmony_ci} 13507ac75b1Sopenharmony_ci 13607ac75b1Sopenharmony_cifunction checkModuleType(moduleType: string): boolean { 13707ac75b1Sopenharmony_ci for (let i = 0; i < sdkConfigs.length; i++) { 13807ac75b1Sopenharmony_ci const config = sdkConfigs[i]; 13907ac75b1Sopenharmony_ci if (config.prefix === `@${moduleType}`) { 14007ac75b1Sopenharmony_ci return true; 14107ac75b1Sopenharmony_ci } 14207ac75b1Sopenharmony_ci } 14307ac75b1Sopenharmony_ci return false; 14407ac75b1Sopenharmony_ci} 14507ac75b1Sopenharmony_ci 14607ac75b1Sopenharmony_cifunction checkModuleExist(systemModule: string, sourcePath: string): void { 14707ac75b1Sopenharmony_ci const module: string = `@${systemModule.trim()}.d.ts`; 14807ac75b1Sopenharmony_ci if (/\.js$/.test(sourcePath) && !systemModules.includes(module)) { 14907ac75b1Sopenharmony_ci const message: string = 15007ac75b1Sopenharmony_ci `Cannot find module '${module}' or its corresponding type declarations.`; 15107ac75b1Sopenharmony_ci console.error(`BUILDERROR File: ${sourcePath}\n ${message}`); 15207ac75b1Sopenharmony_ci } 15307ac75b1Sopenharmony_ci} 15407ac75b1Sopenharmony_ci 15507ac75b1Sopenharmony_cifunction processLibso(content: string, sourcePath: string, useOSFiles: Set<string>): string { 15607ac75b1Sopenharmony_ci const REG_LIB_SO: RegExp = 15707ac75b1Sopenharmony_ci /import\s+(.+)\s+from\s+['"]lib(\S+)\.so['"]|import\s+(.+)\s*=\s*require\(\s*['"]lib(\S+)\.so['"]\s*\)/g; 15807ac75b1Sopenharmony_ci return content.replace(REG_LIB_SO, (_, item1, item2, item3, item4) => { 15907ac75b1Sopenharmony_ci useOSFiles.add(sourcePath); 16007ac75b1Sopenharmony_ci const libSoValue: string = item1 || item3; 16107ac75b1Sopenharmony_ci const libSoKey: string = item2 || item4; 16207ac75b1Sopenharmony_ci return projectConfig.bundleName && projectConfig.moduleName 16307ac75b1Sopenharmony_ci ? `var ${libSoValue} = globalThis.requireNapi("${libSoKey}", true, "${projectConfig.bundleName}/${projectConfig.moduleName}");` 16407ac75b1Sopenharmony_ci : `var ${libSoValue} = globalThis.requireNapi("${libSoKey}", true);`; 16507ac75b1Sopenharmony_ci }); 16607ac75b1Sopenharmony_ci} 16707ac75b1Sopenharmony_ci 16807ac75b1Sopenharmony_ci// It is rare to use `import xxx = require('module')` for system module and user native library, 16907ac75b1Sopenharmony_ci// Here keep tackling with this for compatibility concern. 17007ac75b1Sopenharmony_cifunction processSystemApiAndLibso(content: string, sourcePath: string, useOSFiles: Set<string>): string { 17107ac75b1Sopenharmony_ci // 'arkui-x' represents cross platform related APIs, processed as 'ohos' 17207ac75b1Sopenharmony_ci const REG_REQUIRE_SYSTEM: RegExp = new RegExp(`import\\s+(.+)\\s*=\\s*require\\(\\s*['"]@(${sdkConfigPrefix})\\.(\\S+)['"]\\s*\\)`, 'g'); 17307ac75b1Sopenharmony_ci // Import libso should be recored in useOSFiles. 17407ac75b1Sopenharmony_ci const REG_LIB_SO: RegExp = 17507ac75b1Sopenharmony_ci /import\s+(.+)\s+from\s+['"]lib(\S+)\.so['"]|import\s+(.+)\s*=\s*require\(\s*['"]lib(\S+)\.so['"]\s*\)/g; 17607ac75b1Sopenharmony_ci // 'arkui-x' represents cross platform related APIs, processed as 'ohos' 17707ac75b1Sopenharmony_ci const REG_IMPORT_SYSTEM = new RegExp(`import\\s+(.+)\\s+from\\s+['"]@(${sdkConfigPrefix})\\.(\\S+)['"]`, 'g'); 17807ac75b1Sopenharmony_ci appImportModuleCollection.set(path.join(sourcePath), new Set()); 17907ac75b1Sopenharmony_ci content.replace(REG_IMPORT_SYSTEM, (_, item1, item2, item3, item4, item5, item6) => { 18007ac75b1Sopenharmony_ci const moduleType: string = item2 || item5; 18107ac75b1Sopenharmony_ci const systemKey: string = item3 || item6; 18207ac75b1Sopenharmony_ci const systemValue: string = item1 || item4; 18307ac75b1Sopenharmony_ci const systemModule: string = `${moduleType}.${systemKey}`; 18407ac75b1Sopenharmony_ci appImportModuleCollection.get(path.join(sourcePath)).add(systemModule); 18507ac75b1Sopenharmony_ci return _; 18607ac75b1Sopenharmony_ci }); 18707ac75b1Sopenharmony_ci return content.replace(REG_REQUIRE_SYSTEM, (_, item1, item2, item3, item4, item5, item6) => { 18807ac75b1Sopenharmony_ci const moduleType: string = item2 || item5; 18907ac75b1Sopenharmony_ci const systemKey: string = item3 || item6; 19007ac75b1Sopenharmony_ci const systemValue: string = item1 || item4; 19107ac75b1Sopenharmony_ci const systemModule: string = `${moduleType}.${systemKey}`; 19207ac75b1Sopenharmony_ci appImportModuleCollection.get(path.join(sourcePath)).add(systemModule); 19307ac75b1Sopenharmony_ci checkModuleExist(systemModule, sourcePath); 19407ac75b1Sopenharmony_ci return `import ${systemValue} from '@${moduleType}.${systemKey}'`; 19507ac75b1Sopenharmony_ci }).replace(REG_LIB_SO, (_, item1, item2, item3, item4) => { 19607ac75b1Sopenharmony_ci useOSFiles.add(sourcePath); 19707ac75b1Sopenharmony_ci const libSoValue: string = item1 || item3; 19807ac75b1Sopenharmony_ci const libSoKey: string = item2 || item4; 19907ac75b1Sopenharmony_ci return `import ${libSoValue} from 'lib${libSoKey}.so'`; 20007ac75b1Sopenharmony_ci }); 20107ac75b1Sopenharmony_ci} 20207ac75b1Sopenharmony_ci 20307ac75b1Sopenharmony_ciexport function collectKitModules(fileName: string, key: string, value: string): void { 20407ac75b1Sopenharmony_ci key = key.replace('@', ''); 20507ac75b1Sopenharmony_ci value = value.replace('@', ''); 20607ac75b1Sopenharmony_ci const currentValue: Map<string, Set<string>> = kitModules.get(fileName); 20707ac75b1Sopenharmony_ci if (currentValue) { 20807ac75b1Sopenharmony_ci const currentModuleName: Set<string> = currentValue.get(key); 20907ac75b1Sopenharmony_ci if (currentModuleName && !currentModuleName.has(value)) { 21007ac75b1Sopenharmony_ci currentModuleName.add(value); 21107ac75b1Sopenharmony_ci currentValue.set(key, currentModuleName); 21207ac75b1Sopenharmony_ci } else if (!currentModuleName) { 21307ac75b1Sopenharmony_ci const moduleSet: Set<string> = new Set(); 21407ac75b1Sopenharmony_ci currentValue.set(key, moduleSet.add(value)); 21507ac75b1Sopenharmony_ci } 21607ac75b1Sopenharmony_ci } else { 21707ac75b1Sopenharmony_ci const moduleMap: Map<string, Set<string>> = new Map(); 21807ac75b1Sopenharmony_ci const moduleSet: Set<string> = new Set(); 21907ac75b1Sopenharmony_ci moduleMap.set(key, moduleSet.add(value)); 22007ac75b1Sopenharmony_ci kitModules.set(fileName, moduleMap); 22107ac75b1Sopenharmony_ci } 22207ac75b1Sopenharmony_ci} 22307ac75b1Sopenharmony_ci 22407ac75b1Sopenharmony_cifunction compareKitModules(value: Set<string>, kitKey: string, kitValue: Map<string, Set<string>>): void { 22507ac75b1Sopenharmony_ci const realModules: Set<string> = new Set(); 22607ac75b1Sopenharmony_ci value.forEach((element: string) => { 22707ac75b1Sopenharmony_ci if (kitValue.get(element)) { 22807ac75b1Sopenharmony_ci kitValue.get(element).forEach((kitModuleRequest: string) => { 22907ac75b1Sopenharmony_ci realModules.add(kitModuleRequest.replace(/\.d\.e?ts$/, '')); 23007ac75b1Sopenharmony_ci }); 23107ac75b1Sopenharmony_ci } else { 23207ac75b1Sopenharmony_ci realModules.add(element); 23307ac75b1Sopenharmony_ci } 23407ac75b1Sopenharmony_ci }); 23507ac75b1Sopenharmony_ci appImportModuleCollection.set(kitKey, realModules); 23607ac75b1Sopenharmony_ci} 23707ac75b1Sopenharmony_ci 23807ac75b1Sopenharmony_cifunction replaceKitModules(): void { 23907ac75b1Sopenharmony_ci appImportModuleCollection.forEach((value: Set<string>, key: string) => { 24007ac75b1Sopenharmony_ci kitModules.forEach((kitValue: Map<string, Set<string>>, kitKey: string) => { 24107ac75b1Sopenharmony_ci if (key === kitKey && value && value.size > 0) { 24207ac75b1Sopenharmony_ci compareKitModules(value, kitKey, kitValue); 24307ac75b1Sopenharmony_ci } 24407ac75b1Sopenharmony_ci }); 24507ac75b1Sopenharmony_ci }); 24607ac75b1Sopenharmony_ci} 247