• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2020 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 fs = require('fs');
17const path = require('path');
18const crypto = require('crypto');
19const JSON5 = require('json5');
20
21const {
22  readFile,
23  writeFileSync,
24  resourcesRawfile,
25  getStoredFileInfo
26} = require('./lib/utils');
27
28const {
29  COLD_RELOAD_MODE,
30  ES2ABC,
31  FAIL,
32  TEST_RUNNER_DIR_SET,
33  TS2ABC,
34  WORKERS_DIR
35} = require('./lib/pre_define');
36
37const {
38  checkAotConfig
39} = require('./lib/gen_aot');
40
41const {
42  configure,
43  getLogger
44} = require('log4js');
45
46configure({
47  appenders: { 'ETS': {type: 'stderr', layout: {type: 'messagePassThrough'}}},
48  categories: {'default': {appenders: ['ETS'], level: 'info'}}
49});
50const logger = getLogger('ETS');
51
52let staticPreviewPage = process.env.aceStaticPreview;
53let aceCompileMode = process.env.aceCompileMode || 'page';
54const abilityConfig = {
55  abilityType: process.env.abilityType || 'page',
56  abilityEntryFile: null,
57  projectAbilityPath: [],
58  testRunnerFile: []
59};
60const projectConfig = {};
61const resources = {
62  app: {},
63  sys: {}
64};
65const systemModules = [];
66const abilityPagesFullPath = new Set();
67let globalModulePaths = [];
68let sdkConfigs = [];
69let defaultSdkConfigs = [];
70let extendSdkConfigs = [];
71let sdkConfigPrefix = 'ohos|system|kit|arkts';
72let ohosSystemModulePaths = [];
73let ohosSystemModuleSubDirPaths = [];
74let allModulesPaths = [];
75
76function initProjectConfig(projectConfig) {
77  initProjectPathConfig(projectConfig);
78  projectConfig.entryObj = {};
79  projectConfig.entryArrayForObf = []; // Only used for arkguard
80  projectConfig.cardObj = {};
81  projectConfig.aceBuildJson = projectConfig.aceBuildJson || process.env.aceBuildJson;
82  projectConfig.xtsMode = /ets_loader_ark$/.test(__dirname) || process.env.xtsMode === 'true';
83  projectConfig.isPreview = projectConfig.isPreview || process.env.isPreview === 'true';
84  projectConfig.compileMode = projectConfig.compileMode || process.env.compileMode || 'jsbundle';
85  projectConfig.runtimeOS = projectConfig.runtimeOS || process.env.runtimeOS || 'default';
86  projectConfig.sdkInfo = projectConfig.sdkInfo || process.env.sdkInfo || 'default';
87  projectConfig.compileHar = false;
88  projectConfig.compileShared = false;
89  projectConfig.splitCommon = false;
90  projectConfig.checkEntry = projectConfig.checkEntry || process.env.checkEntry;
91  projectConfig.obfuscateHarType = projectConfig.obfuscateHarType || process.env.obfuscate;
92  projectConfig.packageDir = 'node_modules';
93  projectConfig.packageJson = 'package.json';
94  projectConfig.packageManagerType = 'npm';
95  projectConfig.cardEntryObj = {};
96  projectConfig.compilerTypes = [];
97  projectConfig.isCrossplatform = projectConfig.isCrossplatform || false;
98  projectConfig.enableDebugLine = projectConfig.enableDebugLine || process.env.enableDebugLine || false;
99  projectConfig.bundleType = projectConfig.bundleType || process.env.bundleType || '';
100  projectConfig.optLazyForEach = false;
101  projectConfig.hspResourcesMap = false;
102  projectConfig.useArkoala = false;
103  projectConfig.resetBundleName = false;
104  projectConfig.integratedHsp = false;
105  projectConfig.useTsHar = false;
106  projectConfig.optTryCatchFunc = true;
107  // All files which dependent on bytecode har, and should be added to compilation entries.
108  projectConfig.otherCompileFiles = {};
109  // Packages which need to update version in bytecode har
110  projectConfig.updateVersionInfo = undefined;
111  projectConfig.allowEmptyBundleName = false;
112}
113
114function initProjectPathConfig(projectConfig) {
115  projectConfig.projectPath = projectConfig.projectPath || process.env.aceModuleRoot ||
116  path.join(process.cwd(), 'sample');
117  projectConfig.buildPath = projectConfig.buildPath || process.env.aceModuleBuild ||
118  path.resolve(projectConfig.projectPath, 'build');
119  projectConfig.aceModuleBuild = projectConfig.buildPath; // To be compatible with both webpack and rollup
120  projectConfig.manifestFilePath = projectConfig.manifestFilePath || process.env.aceManifestPath ||
121  path.join(projectConfig.projectPath, 'manifest.json');
122  projectConfig.aceProfilePath = projectConfig.aceProfilePath || process.env.aceProfilePath;
123  projectConfig.aceModuleJsonPath = projectConfig.aceModuleJsonPath || process.env.aceModuleJsonPath;
124  projectConfig.aceSuperVisualPath = projectConfig.aceSuperVisualPath ||
125  process.env.aceSuperVisualPath;
126  projectConfig.hashProjectPath = projectConfig.hashProjectPath ||
127  hashProjectPath(projectConfig.projectPath);
128  projectConfig.cachePath = projectConfig.cachePath || process.env.cachePath ||
129    path.resolve(__dirname, 'node_modules/.cache');
130  projectConfig.aceSoPath = projectConfig.aceSoPath || process.env.aceSoPath;
131  projectConfig.localPropertiesPath = projectConfig.localPropertiesPath || process.env.localPropertiesPath;
132  projectConfig.projectProfilePath = projectConfig.projectProfilePath || process.env.projectProfilePath;
133}
134
135function loadEntryObj(projectConfig) {
136  let manifest = {};
137  initMain();
138  initProjectConfig(projectConfig);
139  loadBuildJson();
140  if (process.env.aceManifestPath && aceCompileMode === 'page') {
141    setEntryFile(projectConfig);
142    setFaTestRunnerFile(projectConfig);
143  }
144  if (process.env.aceModuleJsonPath) {
145    setIntentEntryPages(projectConfig);
146    setAbilityPages(projectConfig);
147    setStageTestRunnerFile(projectConfig);
148    loadNavigationConfig(aceBuildJson);
149  }
150
151  if (staticPreviewPage) {
152    projectConfig.entryObj['./' + staticPreviewPage] = projectConfig.projectPath + path.sep +
153      staticPreviewPage + '.ets?entry';
154    setEntryArrayForObf(staticPreviewPage);
155  } else if (abilityConfig.abilityType === 'page') {
156    if (fs.existsSync(projectConfig.manifestFilePath)) {
157      const jsonString = fs.readFileSync(projectConfig.manifestFilePath).toString();
158      manifest = JSON.parse(jsonString);
159      if (manifest && manifest.minPlatformVersion) {
160        process.env.minPlatformVersion = manifest.minPlatformVersion;
161        partialUpdateController(manifest.minPlatformVersion);
162      }
163      projectConfig.pagesJsonFileName = 'config.json';
164    } else if (projectConfig.aceModuleJsonPath && fs.existsSync(projectConfig.aceModuleJsonPath)) {
165      process.env.compileMode = 'moduleJson';
166      buildManifest(manifest, projectConfig.aceModuleJsonPath);
167    } else {
168      throw Error('\u001b[31m ERROR: the manifest file ' + projectConfig.manifestFilePath.replace(/\\/g, '/') +
169        ' or module.json is lost or format is invalid. \u001b[39m').message;
170    }
171    if (!projectConfig.compileHar) {
172      if (manifest.pages) {
173        const pages = manifest.pages;
174        pages.forEach((element) => {
175          const sourcePath = element.replace(/^\.\/ets\//, '');
176          const fileName = path.resolve(projectConfig.projectPath, sourcePath + '.ets');
177          if (fs.existsSync(fileName)) {
178            projectConfig.entryObj['./' + sourcePath] = fileName + '?entry';
179            // Collect the file paths in main_pages.json
180            setEntryArrayForObf(sourcePath);
181          } else {
182            throw Error(`\u001b[31m ERROR: page '${fileName.replace(/\\/g, '/')}' does not exist. \u001b[39m`)
183              .message;
184          }
185        });
186      } else {
187        throw Error('\u001b[31m ERROR: missing pages attribute in ' +
188          projectConfig.manifestFilePath.replace(/\\/g, '/') +
189          '. \u001b[39m').message;
190      }
191    }
192  }
193}
194
195function loadNavigationConfig(aceBuildJson) {
196  if (aceBuildJson && aceBuildJson.routerMap && Array.isArray(aceBuildJson.routerMap)) {
197    aceBuildJson.routerMap.forEach((item) => {
198      if (item.pageSourceFile && item.name && item.buildFunction) {
199        const filePath = path.resolve(item.pageSourceFile);
200        const storedFileInfo = getStoredFileInfo();
201        if (storedFileInfo.routerInfo.has(filePath)) {
202          storedFileInfo.routerInfo.get(filePath).push({name: item.name, buildFunction: item.buildFunction});
203        } else {
204          storedFileInfo.routerInfo.set(filePath, [{name: item.name, buildFunction: item.buildFunction}]);
205        }
206      }
207    });
208  }
209}
210
211function buildManifest(manifest, aceConfigPath) {
212  try {
213    const moduleConfigJson = JSON.parse(fs.readFileSync(aceConfigPath).toString());
214    manifest.type = process.env.abilityType;
215    if (moduleConfigJson && moduleConfigJson.app && moduleConfigJson.app.minAPIVersion) {
216      if (moduleConfigJson.module && moduleConfigJson.module.metadata) {
217        partialUpdateController(moduleConfigJson.app.minAPIVersion, moduleConfigJson.module.metadata,
218          moduleConfigJson.module.type);
219        stageOptimization(moduleConfigJson.module.metadata);
220      } else {
221        partialUpdateController(moduleConfigJson.app.minAPIVersion);
222      }
223    }
224    if (moduleConfigJson.module) {
225      switch (moduleConfigJson.module.type) {
226        case 'har':
227          projectConfig.compileHar = true;
228          getPackageJsonEntryPath();
229          break;
230        case 'shared':
231          projectConfig.compileShared = true;
232          getPackageJsonEntryPath();
233          manifest.pages = getPages(moduleConfigJson);
234          break;
235        default:
236          manifest.pages = getPages(moduleConfigJson);
237          break;
238      }
239    } else {
240      throw Error('\u001b[31m' +
241        'BUIDERROR: the config.json file miss key word module || module[abilities].' +
242        '\u001b[39m').message;
243    }
244  } catch (e) {
245    if (/BUIDERROR/.test(e)) {
246      throw Error(e.replace('BUIDERROR', 'ERROR')).message;
247    } else {
248      throw Error('\x1B[31m' + 'ERROR: the module.json file is lost or format is invalid.' +
249        '\x1B[39m').message;
250    }
251  }
252}
253
254function getPackageJsonEntryPath() {
255  const rootPackageJsonPath = path.resolve(projectConfig.projectPath, '../../../' + projectConfig.packageJson);
256  if (fs.existsSync(rootPackageJsonPath)) {
257    let rootPackageJsonContent;
258    try {
259      rootPackageJsonContent = (projectConfig.packageManagerType === 'npm' ?
260        JSON : JSON5).parse(fs.readFileSync(rootPackageJsonPath, 'utf-8'));
261    } catch (e) {
262      throw Error('\u001b[31m' + 'BUIDERROR: ' + rootPackageJsonPath + ' format is invalid.' + '\u001b[39m').message;
263    }
264    if (rootPackageJsonContent) {
265      if (rootPackageJsonContent.module) {
266        getEntryPath(rootPackageJsonContent.module, rootPackageJsonPath);
267      } else if (rootPackageJsonContent.main) {
268        getEntryPath(rootPackageJsonContent.main, rootPackageJsonPath);
269      } else {
270        getEntryPath('', rootPackageJsonPath);
271      }
272    } else if (projectConfig.compileHar) {
273      throw Error('\u001b[31m' + 'BUIDERROR: lack message in ' + projectConfig.packageJson + '.' +
274        '\u001b[39m').message;
275    }
276  }
277}
278
279function supportSuffix(mainEntryPath) {
280  if (fs.existsSync(path.join(mainEntryPath, 'index.ets'))) {
281    mainEntryPath = path.join(mainEntryPath, 'index.ets');
282  } else if (fs.existsSync(path.join(mainEntryPath, 'index.ts'))) {
283    mainEntryPath = path.join(mainEntryPath, 'index.ts');
284  } else if (fs.existsSync(path.join(mainEntryPath, 'index.js'))) {
285    mainEntryPath = path.join(mainEntryPath, 'index.js');
286  } else if (projectConfig.compileHar) {
287    throw Error('\u001b[31m' + 'BUIDERROR: not find entry file in ' + projectConfig.packageJson +
288      '.' + '\u001b[39m').message;
289  }
290  return mainEntryPath;
291}
292
293function supportExtName(mainEntryPath) {
294  if (path.extname(mainEntryPath) === '') {
295    if (fs.existsSync(mainEntryPath + '.ets')) {
296      mainEntryPath = mainEntryPath + '.ets';
297    } else if (fs.existsSync(mainEntryPath + '.ts')) {
298      mainEntryPath = mainEntryPath + '.ts';
299    } else if (fs.existsSync(mainEntryPath + '.js')) {
300      mainEntryPath = mainEntryPath + '.js';
301    }
302  }
303  return mainEntryPath;
304}
305
306function getEntryPath(entryPath, rootPackageJsonPath) {
307  let mainEntryPath = path.resolve(rootPackageJsonPath, '../', entryPath);
308  if (fs.existsSync(mainEntryPath) && fs.statSync(mainEntryPath).isDirectory()) {
309    mainEntryPath = supportSuffix(mainEntryPath);
310  } else {
311    mainEntryPath = supportExtName(mainEntryPath);
312  }
313  if (fs.existsSync(mainEntryPath) && fs.statSync(mainEntryPath).isFile()) {
314    const entryKey = path.relative(projectConfig.projectPath, mainEntryPath);
315    projectConfig.entryObj[entryKey] = mainEntryPath;
316    setEntryArrayForObf(entryKey);
317    abilityPagesFullPath.add(path.resolve(mainEntryPath).toLowerCase());
318  } else if (projectConfig.compileHar) {
319    throw Error('\u001b[31m' + `BUIDERROR: not find entry file in ${rootPackageJsonPath}.` + '\u001b[39m').message;
320  }
321}
322
323function stageOptimization(metadata) {
324  if (Array.isArray(metadata) && metadata.length) {
325    metadata.some(item => {
326      if (item.name && item.name === 'USE_COMMON_CHUNK' &&
327        item.value && item.value === 'true') {
328        projectConfig.splitCommon = true;
329        return true;
330      }
331    });
332  }
333}
334
335function getPages(configJson) {
336  const pages = [];
337  let pagesJsonFileName = '';
338  // pages is not necessary in stage
339  if (process.env.compileMode === 'moduleJson' && configJson.module && configJson.module.pages) {
340    pagesJsonFileName = `${configJson.module.pages.replace(/\$profile\:/, '')}.json`;
341  } else {
342    return pages;
343  }
344  const modulePagePath = path.resolve(projectConfig.aceProfilePath, pagesJsonFileName);
345  if (fs.existsSync(modulePagePath)) {
346    try {
347      const pagesConfig = JSON.parse(fs.readFileSync(modulePagePath, 'utf-8'));
348      if (pagesConfig && pagesConfig.src) {
349        projectConfig.pagesJsonFileName = pagesJsonFileName;
350        return pagesConfig.src;
351      }
352    } catch (e) {
353      throw Error('\x1B[31m' + `BUIDERROR: the ${modulePagePath} file format is invalid.` +
354        '\x1B[39m').message;
355    }
356  }
357  return pages;
358}
359
360function setEntryFile(projectConfig) {
361  const entryFileName = abilityConfig.abilityType === 'page' ? 'app' : abilityConfig.abilityType;
362  const extendFile = entryFileName === 'app' ? '.ets' : '.ts';
363  const entryFileRealPath = entryFileName + extendFile;
364  const entryFilePath = path.resolve(projectConfig.projectPath, entryFileRealPath);
365  abilityConfig.abilityEntryFile = entryFilePath;
366  if (!fs.existsSync(entryFilePath) && aceCompileMode === 'page') {
367    throw Error(`\u001b[31m ERROR: missing ${entryFilePath.replace(/\\/g, '/')}. \u001b[39m`).message;
368  }
369  projectConfig.entryObj[`./${entryFileName}`] = entryFilePath + '?entry';
370  setEntryArrayForObf(entryFileName);
371}
372
373function setIntentEntryPages(projectConfig) {
374  projectConfig.intentEntry.forEach(pages => {
375    const entryKey = path.relative(projectConfig.projectPath, pages).replace(/\.(ets|ts|js)$/, '');
376    projectConfig.entryObj[entryKey] = pages;
377    if (/\.ets$/.test(pages)) {
378      abilityPagesFullPath.add(path.resolve(pages).toLowerCase());
379    }
380  });
381}
382
383function setAbilityPages(projectConfig) {
384  let abilityPages = [];
385  if (projectConfig.aceModuleJsonPath && fs.existsSync(projectConfig.aceModuleJsonPath)) {
386    const moduleJson = JSON.parse(fs.readFileSync(projectConfig.aceModuleJsonPath).toString());
387    abilityPages = readAbilityEntrance(moduleJson);
388    setAbilityFile(projectConfig, abilityPages);
389    setBundleModuleInfo(projectConfig, moduleJson);
390  }
391}
392
393function setTestRunnerFile(projectConfig, isStageBased) {
394  const index = projectConfig.projectPath.split(path.sep).join('/').lastIndexOf('\/');
395  TEST_RUNNER_DIR_SET.forEach((dir) => {
396    const projectPath = isStageBased ? projectConfig.projectPath : projectConfig.projectPath.substring(0, index + 1);
397    const testRunnerPath = path.resolve(projectPath, dir);
398    if (fs.existsSync(testRunnerPath) && folderExistsCaseSensitive(testRunnerPath)) {
399      const testRunnerFiles = [];
400      readFile(testRunnerPath, testRunnerFiles);
401      testRunnerFiles.forEach((item) => {
402        if (/\.(ts|js|ets)$/.test(item)) {
403          if (/\.ets$/.test(item)) {
404            abilityPagesFullPath.add(path.resolve(item).toLowerCase());
405          }
406          const relativePath = path.relative(testRunnerPath, item).replace(/\.(ts|js|ets)$/, '');
407          if (isStageBased) {
408            projectConfig.entryObj[`./${dir}/${relativePath}`] = item;
409          } else {
410            projectConfig.entryObj[`../${dir}/${relativePath}`] = item;
411          }
412          setEntryArrayForObf(dir, relativePath);
413          abilityConfig.testRunnerFile.push(item);
414        }
415      });
416    }
417  });
418}
419
420// entryPath: the filename of the entry file and the name of the outer directory.
421// The directory should be placed before the filename, and the filename must be the last argument.
422function setEntryArrayForObf(...entryPath) {
423  projectConfig.entryArrayForObf?.push(entryPath.join('/'));
424}
425
426function folderExistsCaseSensitive(folderPath) {
427  try {
428    const folders = fs.readdirSync(path.dirname(folderPath), { withFileTypes: true })
429      .filter(entry => entry.isDirectory())
430      .map(entry => entry.name);
431    const targetFolderName = path.basename(folderPath);
432    return folders.includes(targetFolderName);
433  } catch (error) {
434    return false;
435  }
436}
437
438function setFaTestRunnerFile(projectConfig) {
439  setTestRunnerFile(projectConfig, false);
440}
441
442function setStageTestRunnerFile(projectConfig) {
443  setTestRunnerFile(projectConfig, true);
444}
445
446function setBundleModuleInfo(projectConfig, moduleJson) {
447  if (moduleJson.module) {
448    projectConfig.moduleName = moduleJson.module.name;
449  }
450  if (moduleJson.app) {
451    projectConfig.bundleName = moduleJson.app.bundleName;
452  }
453}
454
455function setAbilityFile(projectConfig, abilityPages) {
456  abilityPages.forEach(abilityPath => {
457    const projectAbilityPath = path.resolve(projectConfig.projectPath, '../', abilityPath);
458    if (path.isAbsolute(abilityPath)) {
459      abilityPath = '.' + abilityPath.slice(projectConfig.projectPath.length);
460    }
461    const entryPageKey = abilityPath.replace(/^\.\/ets\//, './').replace(/\.ts$/, '').replace(/\.ets$/, '');
462    if (fs.existsSync(projectAbilityPath)) {
463      abilityConfig.projectAbilityPath.push(projectAbilityPath);
464      projectConfig.entryObj[entryPageKey] = projectAbilityPath + '?entry';
465      setEntryArrayForObf(entryPageKey);
466    } else {
467      throw Error(
468        `\u001b[31m ERROR: srcEntry file '${projectAbilityPath.replace(/\\/g, '/')}' does not exist. \u001b[39m`
469      ).message;
470    }
471  });
472}
473
474function readAbilityEntrance(moduleJson) {
475  const abilityPages = [];
476  if (moduleJson.module) {
477    const moduleSrcEntrance = moduleJson.module.srcEntrance;
478    const moduleSrcEntry = moduleJson.module.srcEntry;
479    if (moduleSrcEntry) {
480      abilityPages.push(moduleSrcEntry);
481      abilityPagesFullPath.add(getAbilityFullPath(projectConfig.projectPath, moduleSrcEntry));
482    } else if (moduleSrcEntrance) {
483      abilityPages.push(moduleSrcEntrance);
484      abilityPagesFullPath.add(getAbilityFullPath(projectConfig.projectPath, moduleSrcEntrance));
485    }
486    if (moduleJson.module.abilities && moduleJson.module.abilities.length > 0) {
487      setEntrance(moduleJson.module.abilities, abilityPages);
488    }
489    if (moduleJson.module.extensionAbilities && moduleJson.module.extensionAbilities.length > 0) {
490      setEntrance(moduleJson.module.extensionAbilities, abilityPages);
491      setCardPages(moduleJson.module.extensionAbilities);
492    }
493  }
494  return abilityPages;
495}
496
497function setEntrance(abilityConfig, abilityPages) {
498  if (abilityConfig && abilityConfig.length > 0) {
499    abilityConfig.forEach(ability => {
500      if (ability.srcEntry) {
501        abilityPages.push(ability.srcEntry);
502        abilityPagesFullPath.add(getAbilityFullPath(projectConfig.projectPath, ability.srcEntry));
503      } else if (ability.srcEntrance) {
504        abilityPages.push(ability.srcEntrance);
505        abilityPagesFullPath.add(getAbilityFullPath(projectConfig.projectPath, ability.srcEntrance));
506      }
507    });
508  }
509}
510
511function setCardPages(extensionAbilities) {
512  if (extensionAbilities && extensionAbilities.length > 0) {
513    extensionAbilities.forEach(extensionAbility => {
514      if (extensionAbility.metadata) {
515        extensionAbility.metadata.forEach(metadata => {
516          if (metadata.resource) {
517            readCardResource(metadata.resource);
518          }
519        });
520      }
521    });
522  }
523}
524
525function readCardResource(resource) {
526  const cardJsonFileName = `${resource.replace(/\$profile\:/, '')}.json`;
527  const modulePagePath = path.resolve(projectConfig.aceProfilePath, cardJsonFileName);
528  if (fs.existsSync(modulePagePath)) {
529    const cardConfig = JSON.parse(fs.readFileSync(modulePagePath, 'utf-8'));
530    if (cardConfig.forms) {
531      cardConfig.forms.forEach(form => {
532        readCardForm(form);
533      });
534    }
535  }
536}
537
538function readCardForm(form) {
539  if ((form.type && form.type === 'eTS') ||
540    (form.uiSyntax && form.uiSyntax === 'arkts')) {
541    const sourcePath = form.src.replace(/\.ets$/, '');
542    const cardPath = path.resolve(projectConfig.projectPath, '..', sourcePath + '.ets');
543    if (cardPath && fs.existsSync(cardPath)) {
544      projectConfig.entryObj['../' + sourcePath] = cardPath + '?entry';
545      setEntryArrayForObf(sourcePath);
546      projectConfig.cardEntryObj['../' + sourcePath] = cardPath;
547      projectConfig.cardObj[cardPath] = sourcePath.replace(/^\.\//, '');
548    }
549  }
550}
551
552function getAbilityFullPath(projectPath, abilityPath) {
553  const finalPath = path.resolve(path.resolve(projectPath, '../'), abilityPath);
554  if (fs.existsSync(finalPath)) {
555    return finalPath.toLowerCase();
556  } else {
557    return path.resolve(abilityPath).toLowerCase();
558  }
559}
560
561function loadWorker(projectConfig, workerFileEntry) {
562  if (workerFileEntry) {
563    projectConfig.entryObj = Object.assign(projectConfig.entryObj, workerFileEntry);
564    const keys = Object.keys(workerFileEntry);
565    for (const key of keys) {
566      setEntryArrayForObf(key);
567    }
568  } else {
569    const workerPath = path.resolve(projectConfig.projectPath, WORKERS_DIR);
570    if (fs.existsSync(workerPath)) {
571      const workerFiles = [];
572      readFile(workerPath, workerFiles);
573      workerFiles.forEach((item) => {
574        if (/\.(ts|js|ets)$/.test(item)) {
575          const relativePath = path.relative(workerPath, item)
576            .replace(/\.(ts|js|ets)$/, '').replace(/\\/g, '/');
577          projectConfig.entryObj[`./${WORKERS_DIR}/` + relativePath] = item;
578          setEntryArrayForObf(WORKERS_DIR, relativePath);
579          abilityPagesFullPath.add(path.resolve(item).toLowerCase());
580        }
581      });
582    }
583  }
584}
585
586let aceBuildJson = {};
587function loadBuildJson() {
588  if (projectConfig.aceBuildJson && fs.existsSync(projectConfig.aceBuildJson)) {
589    aceBuildJson = JSON.parse(fs.readFileSync(projectConfig.aceBuildJson).toString());
590  }
591  if (aceBuildJson.packageManagerType === 'ohpm') {
592    projectConfig.packageManagerType = 'ohpm';
593    projectConfig.packageDir = 'oh_modules';
594    projectConfig.packageJson = 'oh-package.json5';
595  }
596  // add intent framework entry file
597  projectConfig.intentEntry = aceBuildJson.compileEntry || [];
598  if (!!aceBuildJson.otherCompileFiles) {
599    aceBuildJson.otherCompileFiles.forEach(pages => {
600      const entryKey = path.relative(projectConfig.projectPath, pages).replace(/\.(ets|ts|js|mjs|cjs)$/, '');
601      projectConfig.otherCompileFiles[entryKey] = pages;
602      if (/\.ets$/.test(pages)) {
603        abilityPagesFullPath.add(path.resolve(pages).toLowerCase());
604      }
605    });
606  }
607  if (!!aceBuildJson.byteCodeHar) {
608    projectConfig.useTsHar = true;
609  }
610  if (aceBuildJson.updateVersionInfo) {
611    projectConfig.updateVersionInfo = aceBuildJson.updateVersionInfo;
612  }
613}
614
615function initBuildInfo() {
616  projectConfig.projectRootPath = aceBuildJson.projectRootPath;
617  if (projectConfig.compileHar && aceBuildJson.moduleName &&
618    aceBuildJson.modulePathMap[aceBuildJson.moduleName]) {
619    projectConfig.moduleRootPath = aceBuildJson.modulePathMap[aceBuildJson.moduleName];
620  }
621}
622
623function readWorkerFile() {
624  const workerFileEntry = {};
625  if (aceBuildJson.workers) {
626    aceBuildJson.workers.forEach(worker => {
627      if (!/\.(ts|js|ets)$/.test(worker)) {
628        throw Error(
629          '\u001b[31mArkTS:ERROR: File: ' + worker + '.' + '\n' +
630          "  The worker file can only be an '.ets', '.ts', or '.js' file.\u001b[39m"
631        ).message;
632      }
633      const relativePath = path.relative(projectConfig.projectPath, worker);
634      if (filterWorker(relativePath)) {
635        const workerKey = relativePath.replace(/\.(ts|js)$/, '').replace(/\\/g, '/');
636        if (workerFileEntry[workerKey]) {
637          throw Error(
638            '\u001b[31m ERROR: The worker file cannot use the same file name: \n' +
639            workerFileEntry[workerKey] + '\n' + worker + '\u001b[39m'
640          ).message;
641        } else {
642          workerFileEntry[workerKey] = worker;
643          abilityPagesFullPath.add(path.resolve(workerFileEntry[workerKey]).toLowerCase());
644        }
645      }
646    });
647    return workerFileEntry;
648  }
649  return null;
650}
651
652function readPatchConfig() {
653  if (aceBuildJson.patchConfig) {
654    projectConfig.hotReload = process.env.watchMode === 'true' && !projectConfig.isPreview;
655    projectConfig.coldReload = aceBuildJson.patchConfig.mode === COLD_RELOAD_MODE ? true : false;
656    // The "isFirstBuild" field indicates whether it is the first compilation of cold reload mode
657    // It is determined by hvigor and passed via env
658    projectConfig.isFirstBuild = process.env.isFirstBuild === 'false' ? false : true;
659    projectConfig.patchAbcPath = aceBuildJson.patchConfig.patchAbcPath;
660    projectConfig.changedFileList = aceBuildJson.patchConfig.changedFileList ?
661      aceBuildJson.patchConfig.changedFileList : path.join(projectConfig.cachePath, 'changedFileList.json');
662    if (projectConfig.hotReload) {
663      writeFileSync(projectConfig.changedFileList, JSON.stringify({
664        modifiedFiles: [],
665        removedFiles: []
666      }));
667    }
668  }
669}
670
671function filterWorker(workerPath) {
672  return /\.(ts|js|ets)$/.test(workerPath);
673}
674
675;(function initSystemResource() {
676  const sysResourcePath = path.resolve(__dirname, './sysResource.js');
677  if (fs.existsSync(sysResourcePath)) {
678    resources.sys = require(sysResourcePath).sys;
679  }
680  if (process.env.externalApiPaths) {
681    const sysResourceExtPath = path.resolve(__dirname, process.env.externalApiPaths, 'sysResource.js');
682    if (fs.existsSync(sysResourceExtPath)) {
683      Object.entries(require(sysResourceExtPath).sys).forEach(([key, value]) => {
684        if (key in resources.sys) {
685          Object.assign(resources.sys[key], value);
686        }
687      });
688    }
689  }
690})();
691
692;(function readSystemModules() {
693  const apiDirPath = path.resolve(__dirname, '../../api');
694  const arktsDirPath = path.resolve(__dirname, '../../arkts');
695  const kitsDirPath = path.resolve(__dirname, '../../kits');
696  const systemModulePathArray = [apiDirPath];
697  if (!process.env.isFaMode) {
698    systemModulePathArray.push(arktsDirPath, kitsDirPath);
699  }
700  systemModulePathArray.forEach(systemModulesPath => {
701    if (fs.existsSync(systemModulesPath)) {
702      globalModulePaths.push(systemModulesPath);
703      const modulePaths = [];
704      readFile(systemModulesPath, modulePaths);
705      systemModules.push(...fs.readdirSync(systemModulesPath));
706      ohosSystemModulePaths.push(...modulePaths);
707      const moduleSubdir = modulePaths.filter(filePath => {
708        const dirName = path.dirname(filePath);
709        return !(dirName === apiDirPath || dirName === arktsDirPath || dirName === kitsDirPath);
710      }).map(filePath => {
711        return filePath
712          .replace(apiDirPath, '')
713          .replace(arktsDirPath, '')
714          .replace(kitsDirPath, '')
715          .replace(/(^\\)|(.d.e?ts$)/g, '')
716          .replace(/\\/g, '/');
717      });
718      ohosSystemModuleSubDirPaths.push(...moduleSubdir);
719      allModulesPaths.push(...modulePaths);
720    }
721  });
722  defaultSdkConfigs = [
723    {
724      'apiPath': systemModulePathArray,
725      'prefix': '@ohos'
726    }, {
727      'apiPath': systemModulePathArray,
728      'prefix': '@system'
729    }, {
730      'apiPath': systemModulePathArray,
731      'prefix': '@arkts'
732    }
733  ];
734  const externalApiPathStr = process.env.externalApiPaths || '';
735  const externalApiPaths = externalApiPathStr.split(path.delimiter);
736  collectExternalModules(externalApiPaths);
737  sdkConfigs = [...defaultSdkConfigs, ...extendSdkConfigs];
738})();
739
740function collectExternalModules(sdkPaths) {
741  for (let i = 0; i < sdkPaths.length; i++) {
742    const sdkPath = sdkPaths[i];
743    const sdkConfigPath = path.resolve(sdkPath, 'sdkConfig.json');
744    if (!fs.existsSync(sdkConfigPath)) {
745      continue;
746    }
747    const sdkConfig = JSON.parse(fs.readFileSync(sdkConfigPath, 'utf-8'));
748    if (!sdkConfig.apiPath) {
749      continue;
750    }
751    let externalApiPathArray = [];
752    if (Array.isArray(sdkConfig.apiPath)) {
753      externalApiPathArray = sdkConfig.apiPath;
754    } else {
755      externalApiPathArray.push(sdkConfig.apiPath);
756    }
757    const resolveApiPathArray = [];
758    externalApiPathArray.forEach(element => {
759      const resolvePath = path.resolve(sdkPath, element);
760      resolveApiPathArray.push(resolvePath);
761      if (fs.existsSync(resolvePath)) {
762        const extrenalModulePaths = [];
763        globalModulePaths.push(resolvePath);
764        systemModules.push(...fs.readdirSync(resolvePath));
765        readFile(resolvePath, extrenalModulePaths);
766        allModulesPaths.push(...extrenalModulePaths);
767      }
768    });
769    sdkConfigPrefix += `|${sdkConfig.prefix.replace(/^@/, '')}`;
770    sdkConfig.apiPath = resolveApiPathArray;
771    extendSdkConfigs.push(sdkConfig);
772  }
773}
774
775function readHspResource() {
776  if (aceBuildJson.hspResourcesMap) {
777    projectConfig.hspResourcesMap = true;
778    for (const hspName in aceBuildJson.hspResourcesMap) {
779      if (fs.existsSync(aceBuildJson.hspResourcesMap[hspName])) {
780        const resourceMap = new Map();
781        const hspResourceCollect = resources[hspName] = {};
782        const hspResource = fs.readFileSync(aceBuildJson.hspResourcesMap[hspName], 'utf-8');
783        const resourceArr = hspResource.split(/\n/);
784        processResourceArr(resourceArr, resourceMap, aceBuildJson.hspResourcesMap[hspName]);
785        for (const [key, value] of resourceMap) {
786          hspResourceCollect[key] = value;
787        }
788      }
789    }
790  }
791}
792
793function readAppResource(filePath) {
794  readHspResource();
795  if (fs.existsSync(filePath)) {
796    const appResource = fs.readFileSync(filePath, 'utf-8');
797    const resourceArr = appResource.split(/\n/);
798    const resourceMap = new Map();
799    processResourceArr(resourceArr, resourceMap, filePath);
800    for (let [key, value] of resourceMap) {
801      resources.app[key] = value;
802    }
803  }
804  if (process.env.rawFileResource && process.env.compileMode === 'moduleJson') {
805    resourcesRawfile(process.env.rawFileResource, getStoredFileInfo().resourcesArr);
806  }
807}
808
809function processResourceArr(resourceArr, resourceMap, filePath) {
810  for (let i = 0; i < resourceArr.length; i++) {
811    if (!resourceArr[i].length) {
812      continue;
813    }
814    const resourceData = resourceArr[i].split(/\s/);
815    if (resourceData.length === 3 && !isNaN(Number(resourceData[2]))) {
816      if (resourceMap.get(resourceData[0])) {
817        const resourceKeys = resourceMap.get(resourceData[0]);
818        if (!resourceKeys[resourceData[1]] || resourceKeys[resourceData[1]] !== Number(resourceData[2])) {
819          resourceKeys[resourceData[1]] = Number(resourceData[2]);
820        }
821      } else {
822        let obj = {};
823        obj[resourceData[1]] = Number(resourceData[2]);
824        resourceMap.set(resourceData[0], obj);
825      }
826      if (process.env.compileTool === 'rollup' && process.env.compileMode === 'moduleJson') {
827        getStoredFileInfo().updateResourceList(resourceData[0] + '_' + resourceData[1]);
828      }
829    } else {
830      logger.warn(`\u001b[31m ArkTS:WARN The format of file '${filePath}' is incorrect. \u001b[39m`);
831      break;
832    }
833  }
834}
835
836function hashProjectPath(projectPath) {
837  const hash = crypto.createHash('sha256');
838  hash.update(projectPath.toString());
839  process.env.hashProjectPath = '_' + hash.digest('hex');
840  return process.env.hashProjectPath;
841}
842
843function loadModuleInfo(projectConfig, envArgs) {
844  if (projectConfig.aceBuildJson && fs.existsSync(projectConfig.aceBuildJson)) {
845    const buildJsonInfo = JSON.parse(fs.readFileSync(projectConfig.aceBuildJson).toString());
846    if (buildJsonInfo.compileMode) {
847      projectConfig.compileMode = buildJsonInfo.compileMode;
848    }
849    projectConfig.projectRootPath = buildJsonInfo.projectRootPath;
850    projectConfig.modulePathMap = buildJsonInfo.modulePathMap;
851    projectConfig.isOhosTest = buildJsonInfo.isOhosTest;
852    let faultHandler = function (error) {
853      // rollup's error will be handled in fast build
854      if (process.env.compileTool === 'rollup') {
855        return;
856      }
857      logger.error(error);
858      process.exit(FAIL);
859    };
860    projectConfig.es2abcCompileTsInAotMode = true;
861    projectConfig.es2abcCompileTsInNonAotMode = false;
862    const compileMode = process.env.compileTool === 'rollup' ? projectConfig.compileMode : buildJsonInfo.compileMode;
863    if (checkAotConfig(compileMode, buildJsonInfo, faultHandler)) {
864      projectConfig.processTs = true;
865      projectConfig.pandaMode = TS2ABC;
866      projectConfig.anBuildOutPut = buildJsonInfo.anBuildOutPut;
867      projectConfig.anBuildMode = buildJsonInfo.anBuildMode;
868      projectConfig.apPath = buildJsonInfo.apPath;
869      if (projectConfig.es2abcCompileTsInAotMode) {
870        projectConfig.pandaMode = ES2ABC;
871      }
872    } else {
873      projectConfig.processTs = false;
874      projectConfig.pandaMode = buildJsonInfo.pandaMode;
875      if (projectConfig.es2abcCompileTsInNonAotMode) {
876        projectConfig.pandaMode = ES2ABC;
877        projectConfig.processTs = true;
878      }
879    }
880    if (envArgs !== undefined) {
881      projectConfig.buildArkMode = envArgs.buildMode;
882    }
883    if (compileMode === 'esmodule') {
884      projectConfig.nodeModulesPath = buildJsonInfo.nodeModulesPath;
885      projectConfig.harNameOhmMap = buildJsonInfo.harNameOhmMap;
886    }
887    if (projectConfig.compileHar && buildJsonInfo.moduleName &&
888      buildJsonInfo.modulePathMap[buildJsonInfo.moduleName]) {
889      if (projectConfig.useTsHar) {
890        projectConfig.processTs = true;
891      }
892      projectConfig.moduleRootPath = buildJsonInfo.modulePathMap[buildJsonInfo.moduleName];
893    }
894  }
895}
896
897function checkAppResourcePath(appResourcePath, config) {
898  if (appResourcePath) {
899    readAppResource(appResourcePath);
900    if (fs.existsSync(appResourcePath) && config.cache) {
901      config.cache.buildDependencies.config.push(appResourcePath);
902    }
903    if (!projectConfig.xtsMode) {
904      const appResourcePathSavePath = path.resolve(projectConfig.cachePath, 'resource_path.txt');
905      saveAppResourcePath(appResourcePath, appResourcePathSavePath);
906      if (fs.existsSync(appResourcePathSavePath) && config.cache) {
907        config.cache.buildDependencies.config.push(appResourcePathSavePath);
908      }
909    }
910  }
911}
912
913function saveAppResourcePath(appResourcePath, appResourcePathSavePath) {
914  let isSave = false;
915  if (fs.existsSync(appResourcePathSavePath)) {
916    const saveContent = fs.readFileSync(appResourcePathSavePath);
917    if (appResourcePath !== saveContent) {
918      isSave = true;
919    }
920  } else {
921    isSave = true;
922  }
923  if (isSave) {
924    fs.writeFileSync(appResourcePathSavePath, appResourcePath);
925  }
926}
927
928function addSDKBuildDependencies(config) {
929  if (projectConfig.localPropertiesPath &&
930    fs.existsSync(projectConfig.localPropertiesPath) && config.cache) {
931    config.cache.buildDependencies.config.push(projectConfig.localPropertiesPath);
932  }
933  if (projectConfig.projectProfilePath &&
934    fs.existsSync(projectConfig.projectProfilePath) && config.cache) {
935    config.cache.buildDependencies.config.push(projectConfig.projectProfilePath);
936  }
937}
938
939function getCleanConfig(workerFile) {
940  const cleanPath = [];
941  if (projectConfig.compileMode === 'esmodule') {
942    return cleanPath;
943  }
944  cleanPath.push(projectConfig.buildPath);
945  if (workerFile) {
946    const workerFilesPath = Object.keys(workerFile);
947    for (const workerFilePath of workerFilesPath) {
948      cleanPath.push(path.join(projectConfig.buildPath, workerFilePath, '..'));
949    }
950  }
951  return cleanPath;
952}
953
954function isPartialUpdate(metadata, moduleType) {
955  if (!Array.isArray(metadata) || !metadata.length) {
956    return;
957  }
958  metadata.some(item => {
959    if (item.name && item.value) {
960      if (item.name === 'ArkTSPartialUpdate' && item.value === 'false') {
961        partialUpdateConfig.partialUpdateMode = false;
962        if (projectConfig.aceModuleJsonPath) {
963          logger.warn('\u001b[33m ArkTS:WARN File: ' + projectConfig.aceModuleJsonPath + '.' + '\n' +
964          " The 'ArkTSPartialUpdate' field will no longer be supported in the future. \u001b[39m");
965        }
966      }
967      if (item.name === 'ArkTSBuilderCheck' && item.value === 'false') {
968        partialUpdateConfig.builderCheck = false;
969      }
970      if (item.name === 'Api11ArkTSCheck' && item.value === 'SkipArkTSCheckInApi11') {
971        partialUpdateConfig.executeArkTSLinter = false;
972      }
973      if (item.name === 'Api11ArkTSCheckMode' && item.value === 'DoArkTSCheckInCompatibleModeInApi11') {
974        partialUpdateConfig.standardArkTSLinter = false;
975      }
976      if (item.name === 'ArkoalaPlugin' && item.value === 'true') {
977        projectConfig.useArkoala = true;
978      }
979      if (item.name === 'ArkTSVersion') {
980        partialUpdateConfig.arkTSVersion = item.value;
981      }
982      if (item.name === 'OPTLazyForEach' && item.value === 'true') {
983        projectConfig.optLazyForEach = true;
984      }
985      if (item.name === 'SkipTscOhModuleCheck' && item.value === 'true') {
986        partialUpdateConfig.skipTscOhModuleCheck = true;
987      }
988      if (item.name === 'SkipArkTSStaticBlocksCheck' && item.value === 'true') {
989        partialUpdateConfig.skipArkTSStaticBlocksCheck = true;
990      }
991      if (item.name === 'UseTsHar' && item.value === 'true' && moduleType === 'har') {
992        projectConfig.useTsHar = true;
993      }
994      if (item.name === 'OptTryCatchFunc' && item.value === 'false') {
995        projectConfig.optTryCatchFunc = false;
996      }
997    }
998    return !partialUpdateConfig.partialUpdateMode && !partialUpdateConfig.builderCheck &&
999      !partialUpdateConfig.executeArkTSLinter && !partialUpdateConfig.standardArkTSLinter &&
1000      partialUpdateConfig.arkTSVersion !== undefined && projectConfig.optLazyForEach &&
1001      partialUpdateConfig.skipTscOhModuleCheck && partialUpdateConfig.skipArkTSStaticBlocksCheck;
1002  });
1003}
1004
1005function applicationConfig() {
1006  const localProperties = path.resolve(aceBuildJson.projectRootPath, 'local.properties');
1007  if (fs.existsSync(localProperties)) {
1008    try {
1009      const localPropertiesFile = fs.readFileSync(localProperties, {encoding: 'utf-8'}).split(/\r?\n/);
1010      localPropertiesFile.some((item) => {
1011        const builderCheckValue = item.replace(/\s+|;/g, '');
1012        if (builderCheckValue === 'ArkTSConfig.ArkTSBuilderCheck=false') {
1013          partialUpdateConfig.builderCheck = false;
1014          return true;
1015        }
1016      });
1017    } catch (err) {
1018    }
1019  }
1020}
1021
1022function partialUpdateController(minAPIVersion, metadata = null, moduleType = '') {
1023  projectConfig.minAPIVersion = minAPIVersion;
1024  if (minAPIVersion >= 9) {
1025    partialUpdateConfig.partialUpdateMode = true;
1026  }
1027  const MIN_VERSION_OPTIMIZE_COMPONENT = 10;
1028  if (minAPIVersion < MIN_VERSION_OPTIMIZE_COMPONENT) {
1029    partialUpdateConfig.optimizeComponent = false;
1030  }
1031  if (metadata) {
1032    isPartialUpdate(metadata, moduleType);
1033  }
1034  if (aceBuildJson.projectRootPath) {
1035    applicationConfig();
1036  }
1037}
1038
1039const globalProgram = {
1040  builderProgram: null,
1041  program: null,
1042  watchProgram: null,
1043  checker: null,
1044  strictChecker: null,
1045  strictLanguageService: null,
1046};
1047
1048const partialUpdateConfig = {
1049  partialUpdateMode: false,
1050  builderCheck: true,
1051  executeArkTSLinter: true,
1052  standardArkTSLinter: true,
1053  optimizeComponent: true,
1054  arkTSVersion: undefined,
1055  skipTscOhModuleCheck: false,
1056  skipArkTSStaticBlocksCheck: false,
1057};
1058
1059function resetMain() {
1060  staticPreviewPage = undefined;
1061  aceCompileMode = 'page';
1062  resetAbilityConfig();
1063  resetProjectConfig();
1064  resources.app = {};
1065  abilityPagesFullPath.clear();
1066  aceBuildJson = {};
1067  partialUpdateConfig.builderCheck = true;
1068  globalModulePaths = [];
1069  sdkConfigs = [];
1070  defaultSdkConfigs = [];
1071  extendSdkConfigs = [];
1072  sdkConfigPrefix = 'ohos|system|kit';
1073  ohosSystemModulePaths = [];
1074  ohosSystemModuleSubDirPaths = [];
1075  allModulesPaths = [];
1076}
1077
1078function resetAbilityConfig() {
1079  abilityConfig.abilityType = 'page';
1080  abilityConfig.abilityEntryFile = null;
1081  abilityConfig.projectAbilityPath = [];
1082  abilityConfig.testRunnerFile = [];
1083}
1084
1085function resetProjectConfig() {
1086  projectConfig.entryObj = {};
1087  projectConfig.entryArrayForObf = [];
1088  projectConfig.cardObj = {};
1089  projectConfig.compileHar = false;
1090  projectConfig.compileShared = false;
1091  projectConfig.packageDir = 'node_modules';
1092  projectConfig.packageJson = 'package.json';
1093  projectConfig.packageManagerType = 'npm';
1094  projectConfig.cardEntryObj = {};
1095  projectConfig.compilerTypes = [];
1096  projectConfig.optLazyForEach = false;
1097  projectConfig.hspResourcesMap = false;
1098  projectConfig.coldReload = undefined;
1099  projectConfig.isFirstBuild = undefined;
1100  projectConfig.changedFileList = undefined;
1101  projectConfig.patchAbcPath = undefined;
1102  projectConfig.allowEmptyBundleName = false;
1103  const props = ['projectPath', 'buildPath', 'aceModuleBuild', 'manifestFilePath', 'aceProfilePath',
1104    'aceModuleJsonPath', 'aceSuperVisualPath', 'hashProjectPath', 'aceBuildJson', 'cachePath',
1105    'aceSoPath', 'localPropertiesPath', 'projectProfilePath', 'isPreview', 'compileMode', 'runtimeOS',
1106    'sdkInfo', 'checkEntry', 'obfuscateHarType', 'isCrossplatform', 'enableDebugLine', 'bundleType'
1107  ];
1108  for (let key in projectConfig) {
1109    if (props.includes(key)) {
1110      projectConfig[key] = undefined;
1111    }
1112  }
1113  projectConfig.otherCompileFiles = {};
1114  projectConfig.updateVersionInfo = undefined;
1115}
1116
1117function resetGlobalProgram() {
1118  globalProgram.builderProgram = null;
1119  globalProgram.program = null;
1120  globalProgram.checker = null;
1121  globalProgram.strictChecker = null;
1122  globalProgram.strictLanguageService = null;
1123}
1124
1125function initMain() {
1126  staticPreviewPage = process.env.aceStaticPreview;
1127  aceCompileMode = process.env.aceCompileMode || 'page';
1128  abilityConfig.abilityType = process.env.abilityType || 'page';
1129}
1130
1131exports.globalProgram = globalProgram;
1132exports.projectConfig = projectConfig;
1133exports.loadEntryObj = loadEntryObj;
1134exports.readAppResource = readAppResource;
1135exports.resources = resources;
1136exports.loadWorker = loadWorker;
1137exports.abilityConfig = abilityConfig;
1138exports.readWorkerFile = readWorkerFile;
1139exports.abilityPagesFullPath = abilityPagesFullPath;
1140exports.loadModuleInfo = loadModuleInfo;
1141exports.systemModules = systemModules;
1142exports.checkAppResourcePath = checkAppResourcePath;
1143exports.addSDKBuildDependencies = addSDKBuildDependencies;
1144exports.partialUpdateConfig = partialUpdateConfig;
1145exports.readPatchConfig = readPatchConfig;
1146exports.initBuildInfo = initBuildInfo;
1147exports.getCleanConfig = getCleanConfig;
1148exports.globalModulePaths = globalModulePaths;
1149exports.defaultSdkConfigs = defaultSdkConfigs;
1150exports.extendSdkConfigs = extendSdkConfigs;
1151exports.sdkConfigs = sdkConfigs;
1152exports.sdkConfigPrefix = sdkConfigPrefix;
1153exports.ohosSystemModulePaths = ohosSystemModulePaths;
1154exports.resetMain = resetMain;
1155exports.ohosSystemModuleSubDirPaths = ohosSystemModuleSubDirPaths;
1156exports.allModulesPaths = allModulesPaths;
1157exports.resetProjectConfig = resetProjectConfig;
1158exports.resetGlobalProgram = resetGlobalProgram;
1159exports.setEntryArrayForObf = setEntryArrayForObf;
1160