• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2021 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
16const ts = require('typescript');
17const path = require('path');
18const chai = require('chai');
19const mocha = require('mocha');
20const fs = require('fs');
21const expect = chai.expect;
22const {
23  processUISyntax,
24  transformLog
25} = require('../lib/process_ui_syntax');
26const {
27  validateUISyntax,
28  preprocessExtend,
29  resetComponentCollection,
30  componentCollection
31} = require('../lib/validate_ui_syntax');
32const {
33  componentInfo,
34  readFile,
35  storedFileInfo
36} = require('../lib/utils');
37const {
38  BUILD_ON,
39  OHOS_PLUGIN,
40  NATIVE_MODULE,
41  SYSTEM_PLUGIN
42} = require('../lib/pre_define');
43const {
44  projectConfig,
45  resources
46} = require('../main');
47const processStructComponentV2 = require('../lib/process_struct_componentV2');
48const { getCompilerHost } = require('../lib/fast_build/ets_ui/rollup-plugin-ets-typescript');
49const { processKitImport } = require('../lib/process_kit_import');
50const { ModuleSourceFile } = require('../lib/fast_build/ark_compiler/module/module_source_file');
51
52projectConfig.projectPath = path.resolve(process.cwd());
53
54function processModule(compilerOptions, etsFilePath) {
55  const compilerHost = getCompilerHost();
56  const tsProgram = ts.createProgram([etsFilePath], compilerOptions, compilerHost);
57  tsProgram.emit(tsProgram.getSourceFile(etsFilePath), undefined, undefined, undefined,
58    {
59      before: [
60        processUISyntax(null, true),
61        processKitImport(etsFilePath, undefined, undefined, false)
62      ]
63    }
64  );
65}
66
67function processIntermediateTS(content, filePath, afterProcess) {
68  projectConfig.processTs = true;
69  const etsCheckerCompilerOptions = require('../lib/ets_checker').compilerOptions;
70  etsCheckerCompilerOptions.lib = ["lib.es2021.d.ts"];
71  if (content.etsAnnotationsEnable) {
72    Object.assign(etsCheckerCompilerOptions, {
73      'etsAnnotationsEnable': true
74    });
75  }
76  const etsFilePath = filePath.replace('.ts', '.ets');
77  fs.writeFileSync(etsFilePath, afterProcess.content);
78  processModule(etsCheckerCompilerOptions, etsFilePath);
79  sourceFile = ModuleSourceFile.getSourceFiles().find((element) => element.moduleId.includes(etsFilePath));
80  result = generateIntermediateContent(sourceFile);
81  fs.unlinkSync(etsFilePath);
82  projectConfig.processTs = false;
83  return result;
84}
85
86function expectActual(name, filePath, checkError = false) {
87  transformLog.errors = [];
88  resources.app["media"] = {icon:16777222};
89  resources.app["font"] = {song:16777223};
90  process.env.rawFileResource = './';
91  process.env.compileMode = 'moduleJson';
92  const content = require(filePath);
93  const source = content.source;
94  process.env.compiler = BUILD_ON;
95  componentInfo.id = 0;
96  componentCollection.customComponents.clear();
97  resetComponentCollection();
98  storedFileInfo.setCurrentArkTsFile();
99  const afterProcess = sourceReplace(source);
100  if (checkError) {
101    transformLog.errors.push(...validateUISyntax(source, afterProcess.content, `${name}.ets`, "?entry"));
102  } else {
103    validateUISyntax(source, afterProcess.content, `${name}.ets`);
104  }
105  const compilerOptions = ts.readConfigFile(
106    path.resolve(__dirname, '../tsconfig.json'), ts.sys.readFile).config.compilerOptions;
107  Object.assign(compilerOptions, {
108    'sourceMap': false
109  });
110  let actualResult = '';
111  if (content.emitIntermediateTS) {
112    actualResult = processIntermediateTS(content, filePath, afterProcess);
113  } else {
114    const result = ts.transpileModule(afterProcess.content, {
115      compilerOptions: compilerOptions,
116      fileName: `${name}.ets`,
117      transformers: { before: [processUISyntax(null, true)] }
118    });
119    actualResult = result.outputText;
120  }
121  processStructComponentV2.default.resetStructMapInEts();
122  expect(actualResult).eql(content.expectResult);
123}
124
125function generateIntermediateContent(sourceFile) {
126  const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
127  const writer = ts.createTextWriter(
128    ts.getNewLineCharacter({ newLine: ts.NewLineKind.LineFeed, removeComments: false }));
129  printer.writeFile(sourceFile.source, writer, undefined);
130  return writer.getText();
131}
132
133mocha.describe('compiler', () => {
134  let utPath = path.resolve(__dirname, './ut');
135  const utFiles = [];
136  readFile(utPath, utFiles);
137  utFiles.forEach((item) => {
138    const fileName = path.basename(item, '.ts');
139    mocha.it(fileName, () => {
140      expectActual(fileName, item);
141    });
142  });
143});
144
145function sourceReplace(source) {
146  let content = source;
147  const log = [];
148  content = preprocessExtend(content);
149  content = processSystemApi(content);
150  return {
151    content: content,
152    log: log
153  };
154}
155
156function processSystemApi(content) {
157  const REG_SYSTEM =
158    /import\s+(.+)\s+from\s+['"]@(system|ohos)\.(\S+)['"]|import\s+(.+)\s*=\s*require\(\s*['"]@(system|ohos)\.(\S+)['"]\s*\)/g;
159  const REG_LIB_SO =
160    /import\s+(.+)\s+from\s+['"]lib(\S+)\.so['"]|import\s+(.+)\s*=\s*require\(\s*['"]lib(\S+)\.so['"]\s*\)/g;
161  const newContent = content.replace(REG_LIB_SO, (_, item1, item2, item3, item4) => {
162    const libSoValue = item1 || item3;
163    const libSoKey = item2 || item4;
164    return `var ${libSoValue} = globalThis.requireNapi("${libSoKey}", true);`;
165  }).replace(REG_SYSTEM, (item, item1, item2, item3, item4, item5, item6, item7) => {
166    let moduleType = item2 || item5;
167    let systemKey = item3 || item6;
168    let systemValue = item1 || item4;
169    if (NATIVE_MODULE.has(`${moduleType}.${systemKey}`)) {
170      item = `var ${systemValue} = globalThis.requireNativeModule('${moduleType}.${systemKey}')`;
171    } else if (moduleType === SYSTEM_PLUGIN) {
172      item = `var ${systemValue} = isSystemplugin('${systemKey}', '${SYSTEM_PLUGIN}') ? ` +
173        `globalThis.systemplugin.${systemKey} : globalThis.requireNapi('${systemKey}')`;
174    } else if (moduleType === OHOS_PLUGIN) {
175      item = `var ${systemValue} = globalThis.requireNapi('${systemKey}') || ` +
176        `(isSystemplugin('${systemKey}', '${OHOS_PLUGIN}') ? ` +
177        `globalThis.ohosplugin.${systemKey} : isSystemplugin('${systemKey}', '${SYSTEM_PLUGIN}') ` +
178        `? globalThis.systemplugin.${systemKey} : undefined)`;
179    }
180    return item;
181  });
182  return newContent;
183}
184