/* * Copyright (c) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ const ts = require('typescript'); const path = require('path'); const chai = require('chai'); const mocha = require('mocha'); const fs = require('fs'); const expect = chai.expect; const { processUISyntax, transformLog } = require('../lib/process_ui_syntax'); const { validateUISyntax, preprocessExtend, resetComponentCollection, componentCollection } = require('../lib/validate_ui_syntax'); const { componentInfo, readFile, storedFileInfo } = require('../lib/utils'); const { BUILD_ON, OHOS_PLUGIN, NATIVE_MODULE, SYSTEM_PLUGIN } = require('../lib/pre_define'); const { projectConfig, resources } = require('../main'); const processStructComponentV2 = require('../lib/process_struct_componentV2'); const { getCompilerHost } = require('../lib/fast_build/ets_ui/rollup-plugin-ets-typescript'); const { processKitImport } = require('../lib/process_kit_import'); const { ModuleSourceFile } = require('../lib/fast_build/ark_compiler/module/module_source_file'); projectConfig.projectPath = path.resolve(process.cwd()); function processModule(compilerOptions, etsFilePath) { const compilerHost = getCompilerHost(); const tsProgram = ts.createProgram([etsFilePath], compilerOptions, compilerHost); tsProgram.emit(tsProgram.getSourceFile(etsFilePath), undefined, undefined, undefined, { before: [ processUISyntax(null, true), processKitImport(etsFilePath, undefined, undefined, false) ] } ); } function processIntermediateTS(content, filePath, afterProcess) { projectConfig.processTs = true; const etsCheckerCompilerOptions = require('../lib/ets_checker').compilerOptions; etsCheckerCompilerOptions.lib = ["lib.es2021.d.ts"]; if (content.etsAnnotationsEnable) { Object.assign(etsCheckerCompilerOptions, { 'etsAnnotationsEnable': true }); } const etsFilePath = filePath.replace('.ts', '.ets'); fs.writeFileSync(etsFilePath, afterProcess.content); processModule(etsCheckerCompilerOptions, etsFilePath); sourceFile = ModuleSourceFile.getSourceFiles().find((element) => element.moduleId.includes(etsFilePath)); result = generateIntermediateContent(sourceFile); fs.unlinkSync(etsFilePath); projectConfig.processTs = false; return result; } function expectActual(name, filePath, checkError = false) { transformLog.errors = []; resources.app["media"] = {icon:16777222}; resources.app["font"] = {song:16777223}; process.env.rawFileResource = './'; process.env.compileMode = 'moduleJson'; const content = require(filePath); const source = content.source; process.env.compiler = BUILD_ON; componentInfo.id = 0; componentCollection.customComponents.clear(); resetComponentCollection(); storedFileInfo.setCurrentArkTsFile(); const afterProcess = sourceReplace(source); if (checkError) { transformLog.errors.push(...validateUISyntax(source, afterProcess.content, `${name}.ets`, "?entry")); } else { validateUISyntax(source, afterProcess.content, `${name}.ets`); } const compilerOptions = ts.readConfigFile( path.resolve(__dirname, '../tsconfig.json'), ts.sys.readFile).config.compilerOptions; Object.assign(compilerOptions, { 'sourceMap': false }); let actualResult = ''; if (content.emitIntermediateTS) { actualResult = processIntermediateTS(content, filePath, afterProcess); } else { const result = ts.transpileModule(afterProcess.content, { compilerOptions: compilerOptions, fileName: `${name}.ets`, transformers: { before: [processUISyntax(null, true)] } }); actualResult = result.outputText; } processStructComponentV2.default.resetStructMapInEts(); expect(actualResult).eql(content.expectResult); } function generateIntermediateContent(sourceFile) { const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed }); const writer = ts.createTextWriter( ts.getNewLineCharacter({ newLine: ts.NewLineKind.LineFeed, removeComments: false })); printer.writeFile(sourceFile.source, writer, undefined); return writer.getText(); } mocha.describe('compiler', () => { let utPath = path.resolve(__dirname, './ut'); const utFiles = []; readFile(utPath, utFiles); utFiles.forEach((item) => { const fileName = path.basename(item, '.ts'); mocha.it(fileName, () => { expectActual(fileName, item); }); }); }); function sourceReplace(source) { let content = source; const log = []; content = preprocessExtend(content); content = processSystemApi(content); return { content: content, log: log }; } function processSystemApi(content) { const REG_SYSTEM = /import\s+(.+)\s+from\s+['"]@(system|ohos)\.(\S+)['"]|import\s+(.+)\s*=\s*require\(\s*['"]@(system|ohos)\.(\S+)['"]\s*\)/g; const REG_LIB_SO = /import\s+(.+)\s+from\s+['"]lib(\S+)\.so['"]|import\s+(.+)\s*=\s*require\(\s*['"]lib(\S+)\.so['"]\s*\)/g; const newContent = content.replace(REG_LIB_SO, (_, item1, item2, item3, item4) => { const libSoValue = item1 || item3; const libSoKey = item2 || item4; return `var ${libSoValue} = globalThis.requireNapi("${libSoKey}", true);`; }).replace(REG_SYSTEM, (item, item1, item2, item3, item4, item5, item6, item7) => { let moduleType = item2 || item5; let systemKey = item3 || item6; let systemValue = item1 || item4; if (NATIVE_MODULE.has(`${moduleType}.${systemKey}`)) { item = `var ${systemValue} = globalThis.requireNativeModule('${moduleType}.${systemKey}')`; } else if (moduleType === SYSTEM_PLUGIN) { item = `var ${systemValue} = isSystemplugin('${systemKey}', '${SYSTEM_PLUGIN}') ? ` + `globalThis.systemplugin.${systemKey} : globalThis.requireNapi('${systemKey}')`; } else if (moduleType === OHOS_PLUGIN) { item = `var ${systemValue} = globalThis.requireNapi('${systemKey}') || ` + `(isSystemplugin('${systemKey}', '${OHOS_PLUGIN}') ? ` + `globalThis.ohosplugin.${systemKey} : isSystemplugin('${systemKey}', '${SYSTEM_PLUGIN}') ` + `? globalThis.systemplugin.${systemKey} : undefined)`; } return item; }); return newContent; }