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