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 MagicString from 'magic-string'; 17import { createFilter } from '@rollup/pluginutils'; 18 19import { 20 NATIVE_MODULE, 21 SYSTEM_PLUGIN, 22 OHOS_PLUGIN 23} from '../../pre_define'; 24import { 25 systemModules, 26 projectConfig 27} from '../../../main'; 28import { writeUseOSFiles } from '../../utils'; 29import { visualTransform } from '../../process_visual'; 30 31const filter: any = createFilter(/(?<!\.d)\.(ets|ts|js)$/); 32 33export function apiTransform() { 34 const useOSFiles: Set<string> = new Set(); 35 return { 36 name: 'apiTransform', 37 transform(code: string, id: string) { 38 const magicString = new MagicString(code); 39 if (filter(id)) { 40 if (projectConfig.compileMode === "esmodule") { 41 code = processSystemApiAndLibso(code, id, useOSFiles); 42 } else { 43 code = processSystemApi(code, id); 44 code = processLibso(code, id, useOSFiles); 45 } 46 } 47 return { 48 code: code, 49 map: magicString.generateMap({ hires: true }) 50 }; 51 }, 52 buildEnd() { 53 if (projectConfig.isPreview && projectConfig.aceSoPath && 54 useOSFiles && useOSFiles.size > 0) { 55 writeUseOSFiles(useOSFiles); 56 } 57 } 58 }; 59} 60 61function processSystemApi(content: string, sourcePath: string): string { 62 const REG_SYSTEM: RegExp = 63 /import\s+(.+)\s+from\s+['"]@(system|ohos)\.(\S+)['"]|import\s+(.+)\s*=\s*require\(\s*['"]@(system|ohos)\.(\S+)['"]\s*\)/g; 64 return content.replace(REG_SYSTEM, (item, item1, item2, item3, item4, item5, item6) => { 65 const moduleType: string = item2 || item5; 66 const systemKey: string = item3 || item6; 67 const systemValue: string = item1 || item4; 68 const systemModule: string = `${moduleType}.${systemKey}`; 69 checkModuleExist(systemModule, sourcePath); 70 if (NATIVE_MODULE.has(systemModule)) { 71 item = `var ${systemValue} = globalThis.requireNativeModule('${moduleType}.${systemKey}')`; 72 } else if (moduleType === SYSTEM_PLUGIN || moduleType === OHOS_PLUGIN) { 73 item = `var ${systemValue} = globalThis.requireNapi('${systemKey}')`; 74 } 75 return item; 76 }); 77} 78 79function checkModuleExist(systemModule: string, sourcePath: string): void { 80 const module: string = `@${systemModule.trim()}.d.ts`; 81 if (/\.js$/.test(sourcePath) && !systemModules.includes(module)) { 82 const message: string = 83 `Cannot find module '${module}' or its corresponding type declarations.`; 84 console.error(`BUILDERROR File: ${sourcePath}\n ${message}`); 85 } 86} 87 88function processLibso(content: string, sourcePath: string, useOSFiles: Set<string>): string { 89 const REG_LIB_SO: RegExp = 90 /import\s+(.+)\s+from\s+['"]lib(\S+)\.so['"]|import\s+(.+)\s*=\s*require\(\s*['"]lib(\S+)\.so['"]\s*\)/g; 91 return content.replace(REG_LIB_SO, (_, item1, item2, item3, item4) => { 92 useOSFiles.add(sourcePath); 93 const libSoValue: string = item1 || item3; 94 const libSoKey: string = item2 || item4; 95 return projectConfig.bundleName && projectConfig.moduleName 96 ? `var ${libSoValue} = globalThis.requireNapi("${libSoKey}", true, "${projectConfig.bundleName}/${projectConfig.moduleName}");` 97 : `var ${libSoValue} = globalThis.requireNapi("${libSoKey}", true);`; 98 }); 99} 100 101// It is rare to use `import xxx = require('module')` for system module and user native library, 102// Here keep tackling with this for compatibility concern. 103function processSystemApiAndLibso(content: string, sourcePath: string, useOSFiles: Set<string>): string { 104 const REG_SYSTEM: RegExp = /import\s+(.+)\s*=\s*require\(\s*['"]@(system|ohos)\.(\S+)['"]\s*\)/g; 105 // Import libso should be recored in useOSFiles. 106 const REG_LIB_SO: RegExp = 107 /import\s+(.+)\s+from\s+['"]lib(\S+)\.so['"]|import\s+(.+)\s*=\s*require\(\s*['"]lib(\S+)\.so['"]\s*\)/g; 108 109 return content.replace(REG_SYSTEM, (_, item1, item2, item3, item4, item5, item6) => { 110 const moduleType: string = item2 || item5; 111 const systemKey: string = item3 || item6; 112 const systemValue: string = item1 || item4; 113 const systemModule: string = `${moduleType}.${systemKey}`; 114 checkModuleExist(systemModule, sourcePath); 115 return `import ${systemValue} from '@${moduleType}.${systemKey}'`; 116 }).replace(REG_LIB_SO, (_, item1, item2, item3, item4) => { 117 useOSFiles.add(sourcePath); 118 const libSoValue: string = item1 || item3; 119 const libSoKey: string = item2 || item4; 120 return `import ${libSoValue} from 'lib${libSoKey}.so'`; 121 }); 122}