107ac75b1Sopenharmony_ci/* 207ac75b1Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 307ac75b1Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 407ac75b1Sopenharmony_ci * you may not use this file except in compliance with the License. 507ac75b1Sopenharmony_ci * You may obtain a copy of the License at 607ac75b1Sopenharmony_ci * 707ac75b1Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 807ac75b1Sopenharmony_ci * 907ac75b1Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1007ac75b1Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1107ac75b1Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1207ac75b1Sopenharmony_ci * See the License for the specific language governing permissions and 1307ac75b1Sopenharmony_ci * limitations under the License. 1407ac75b1Sopenharmony_ci */ 1507ac75b1Sopenharmony_ci 1607ac75b1Sopenharmony_ciimport cluster from 'cluster'; 1707ac75b1Sopenharmony_ciimport fs from 'fs'; 1807ac75b1Sopenharmony_ciimport path from 'path'; 1907ac75b1Sopenharmony_ciimport ts from 'typescript'; 2007ac75b1Sopenharmony_ciimport os from 'os'; 2107ac75b1Sopenharmony_ciimport sourceMap from 'source-map'; 2207ac75b1Sopenharmony_ci 2307ac75b1Sopenharmony_ciimport { 2407ac75b1Sopenharmony_ci DEBUG, 2507ac75b1Sopenharmony_ci ESMODULE, 2607ac75b1Sopenharmony_ci EXTNAME_ETS, 2707ac75b1Sopenharmony_ci EXTNAME_JS, 2807ac75b1Sopenharmony_ci EXTNAME_TS, 2907ac75b1Sopenharmony_ci EXTNAME_JSON, 3007ac75b1Sopenharmony_ci EXTNAME_CJS, 3107ac75b1Sopenharmony_ci EXTNAME_MJS, 3207ac75b1Sopenharmony_ci TEMPORARY 3307ac75b1Sopenharmony_ci} from './common/ark_define'; 3407ac75b1Sopenharmony_ciimport { 3507ac75b1Sopenharmony_ci nodeLargeOrEqualTargetVersion, 3607ac75b1Sopenharmony_ci genTemporaryPath, 3707ac75b1Sopenharmony_ci mkdirsSync, 3807ac75b1Sopenharmony_ci validateFilePathLength, 3907ac75b1Sopenharmony_ci toUnixPath, 4007ac75b1Sopenharmony_ci isPackageModulesFile, 4107ac75b1Sopenharmony_ci isFileInProject 4207ac75b1Sopenharmony_ci} from '../../utils'; 4307ac75b1Sopenharmony_ciimport { 4407ac75b1Sopenharmony_ci tryMangleFileName, 4507ac75b1Sopenharmony_ci writeObfuscatedSourceCode, 4607ac75b1Sopenharmony_ci cleanUpUtilsObjects, 4707ac75b1Sopenharmony_ci createAndStartEvent, 4807ac75b1Sopenharmony_ci stopEvent 4907ac75b1Sopenharmony_ci} from '../../ark_utils'; 5007ac75b1Sopenharmony_ciimport { AOT_FULL, AOT_PARTIAL, AOT_TYPE } from '../../pre_define'; 5107ac75b1Sopenharmony_ciimport { SourceMapGenerator } from './generate_sourcemap'; 5207ac75b1Sopenharmony_ciimport { 5307ac75b1Sopenharmony_ci handleObfuscatedFilePath, 5407ac75b1Sopenharmony_ci enableObfuscateFileName, 5507ac75b1Sopenharmony_ci enableObfuscatedFilePathConfig, 5607ac75b1Sopenharmony_ci getRelativeSourcePath 5707ac75b1Sopenharmony_ci} from './common/ob_config_resolver'; 5807ac75b1Sopenharmony_ci 5907ac75b1Sopenharmony_ciexport let hasTsNoCheckOrTsIgnoreFiles: string[] = []; 6007ac75b1Sopenharmony_ciexport let compilingEtsOrTsFiles: string[] = []; 6107ac75b1Sopenharmony_ci 6207ac75b1Sopenharmony_ciexport function cleanUpFilesList(): void { 6307ac75b1Sopenharmony_ci hasTsNoCheckOrTsIgnoreFiles = []; 6407ac75b1Sopenharmony_ci compilingEtsOrTsFiles = []; 6507ac75b1Sopenharmony_ci} 6607ac75b1Sopenharmony_ci 6707ac75b1Sopenharmony_ciexport function needAotCompiler(projectConfig: Object): boolean { 6807ac75b1Sopenharmony_ci return projectConfig.compileMode === ESMODULE && (projectConfig.anBuildMode === AOT_FULL || 6907ac75b1Sopenharmony_ci projectConfig.anBuildMode === AOT_PARTIAL); 7007ac75b1Sopenharmony_ci} 7107ac75b1Sopenharmony_ci 7207ac75b1Sopenharmony_ciexport function isAotMode(projectConfig: Object): boolean { 7307ac75b1Sopenharmony_ci return projectConfig.compileMode === ESMODULE && (projectConfig.anBuildMode === AOT_FULL || 7407ac75b1Sopenharmony_ci projectConfig.anBuildMode === AOT_PARTIAL || projectConfig.anBuildMode === AOT_TYPE); 7507ac75b1Sopenharmony_ci} 7607ac75b1Sopenharmony_ci 7707ac75b1Sopenharmony_ciexport function isDebug(projectConfig: Object): boolean { 7807ac75b1Sopenharmony_ci return projectConfig.buildMode.toLowerCase() === DEBUG; 7907ac75b1Sopenharmony_ci} 8007ac75b1Sopenharmony_ci 8107ac75b1Sopenharmony_ciexport function isBranchElimination(projectConfig: Object): boolean { 8207ac75b1Sopenharmony_ci return projectConfig.branchElimination; 8307ac75b1Sopenharmony_ci} 8407ac75b1Sopenharmony_ci 8507ac75b1Sopenharmony_ciexport function isMasterOrPrimary() { 8607ac75b1Sopenharmony_ci return ((nodeLargeOrEqualTargetVersion(16) && cluster.isPrimary) || 8707ac75b1Sopenharmony_ci (!nodeLargeOrEqualTargetVersion(16) && cluster.isMaster)); 8807ac75b1Sopenharmony_ci} 8907ac75b1Sopenharmony_ci 9007ac75b1Sopenharmony_ciexport function changeFileExtension(file: string, targetExt: string, originExt = ''): string { 9107ac75b1Sopenharmony_ci let currentExt = originExt.length === 0 ? path.extname(file) : originExt; 9207ac75b1Sopenharmony_ci let fileWithoutExt = file.substring(0, file.lastIndexOf(currentExt)); 9307ac75b1Sopenharmony_ci return fileWithoutExt + targetExt; 9407ac75b1Sopenharmony_ci} 9507ac75b1Sopenharmony_ci 9607ac75b1Sopenharmony_cifunction removeCacheFile(cacheFilePath: string, ext: string): void { 9707ac75b1Sopenharmony_ci let filePath = toUnixPath(changeFileExtension(cacheFilePath, ext)); 9807ac75b1Sopenharmony_ci if (fs.existsSync(filePath)) { 9907ac75b1Sopenharmony_ci fs.rmSync(filePath); 10007ac75b1Sopenharmony_ci } 10107ac75b1Sopenharmony_ci} 10207ac75b1Sopenharmony_ci 10307ac75b1Sopenharmony_ciexport function shouldETSOrTSFileTransformToJS(filePath: string, projectConfig: Object, metaInfo?: Object): boolean { 10407ac75b1Sopenharmony_ci let cacheFilePath: string = genTemporaryPath(filePath, projectConfig.projectPath, projectConfig.cachePath, 10507ac75b1Sopenharmony_ci projectConfig, metaInfo); 10607ac75b1Sopenharmony_ci 10707ac75b1Sopenharmony_ci if (!projectConfig.processTs) { 10807ac75b1Sopenharmony_ci removeCacheFile(cacheFilePath, EXTNAME_TS); 10907ac75b1Sopenharmony_ci return true; 11007ac75b1Sopenharmony_ci } 11107ac75b1Sopenharmony_ci 11207ac75b1Sopenharmony_ci if (compilingEtsOrTsFiles.indexOf(filePath) !== -1) { 11307ac75b1Sopenharmony_ci // file involves in compilation 11407ac75b1Sopenharmony_ci const hasTsNoCheckOrTsIgnore = hasTsNoCheckOrTsIgnoreFiles.indexOf(filePath) !== -1; 11507ac75b1Sopenharmony_ci // Remove cacheFile whose extension is different the target file 11607ac75b1Sopenharmony_ci removeCacheFile(cacheFilePath, hasTsNoCheckOrTsIgnore ? EXTNAME_TS : EXTNAME_JS); 11707ac75b1Sopenharmony_ci return hasTsNoCheckOrTsIgnore; 11807ac75b1Sopenharmony_ci } 11907ac75b1Sopenharmony_ci 12007ac75b1Sopenharmony_ci cacheFilePath = updateCacheFilePathIfEnableObuscatedFilePath(filePath, cacheFilePath, projectConfig); 12107ac75b1Sopenharmony_ci cacheFilePath = toUnixPath(changeFileExtension(cacheFilePath, EXTNAME_JS)); 12207ac75b1Sopenharmony_ci return fs.existsSync(cacheFilePath); 12307ac75b1Sopenharmony_ci} 12407ac75b1Sopenharmony_ci 12507ac75b1Sopenharmony_ci// This API is used exclusively to determine whether a file needs to be converted into a JS file without removing the cached files, 12607ac75b1Sopenharmony_ci// which differs from API 'shouldETSOrTSFileTransformToJS'. 12707ac75b1Sopenharmony_ciexport function shouldETSOrTSFileTransformToJSWithoutRemove(filePath: string, projectConfig: Object, metaInfo?: Object): boolean { 12807ac75b1Sopenharmony_ci if (!projectConfig.processTs) { 12907ac75b1Sopenharmony_ci return true; 13007ac75b1Sopenharmony_ci } 13107ac75b1Sopenharmony_ci 13207ac75b1Sopenharmony_ci if (compilingEtsOrTsFiles.indexOf(filePath) !== -1) { 13307ac75b1Sopenharmony_ci // file involves in compilation 13407ac75b1Sopenharmony_ci return hasTsNoCheckOrTsIgnoreFiles.indexOf(filePath) !== -1; 13507ac75b1Sopenharmony_ci } 13607ac75b1Sopenharmony_ci 13707ac75b1Sopenharmony_ci let cacheFilePath: string = genTemporaryPath(filePath, projectConfig.projectPath, projectConfig.cachePath, 13807ac75b1Sopenharmony_ci projectConfig, metaInfo); 13907ac75b1Sopenharmony_ci cacheFilePath = updateCacheFilePathIfEnableObuscatedFilePath(filePath, cacheFilePath, projectConfig); 14007ac75b1Sopenharmony_ci cacheFilePath = toUnixPath(changeFileExtension(cacheFilePath, EXTNAME_JS)); 14107ac75b1Sopenharmony_ci return fs.existsSync(cacheFilePath); 14207ac75b1Sopenharmony_ci} 14307ac75b1Sopenharmony_ci 14407ac75b1Sopenharmony_cifunction updateCacheFilePathIfEnableObuscatedFilePath(filePath: string, cacheFilePath: string, projectConfig: Object): string { 14507ac75b1Sopenharmony_ci const isPackageModules = isPackageModulesFile(filePath, projectConfig); 14607ac75b1Sopenharmony_ci if (enableObfuscatedFilePathConfig(isPackageModules, projectConfig) && enableObfuscateFileName(isPackageModules, projectConfig)) { 14707ac75b1Sopenharmony_ci return handleObfuscatedFilePath(cacheFilePath, isPackageModules, projectConfig); 14807ac75b1Sopenharmony_ci } 14907ac75b1Sopenharmony_ci return cacheFilePath; 15007ac75b1Sopenharmony_ci} 15107ac75b1Sopenharmony_ci 15207ac75b1Sopenharmony_ciexport async function writeFileContentToTempDir(id: string, content: string, projectConfig: Object, 15307ac75b1Sopenharmony_ci logger: Object, parentEvent: Object, metaInfo: Object): Promise<void> { 15407ac75b1Sopenharmony_ci if (isCommonJsPluginVirtualFile(id)) { 15507ac75b1Sopenharmony_ci return; 15607ac75b1Sopenharmony_ci } 15707ac75b1Sopenharmony_ci 15807ac75b1Sopenharmony_ci if (!isCurrentProjectFiles(id, projectConfig)) { 15907ac75b1Sopenharmony_ci return; 16007ac75b1Sopenharmony_ci } 16107ac75b1Sopenharmony_ci 16207ac75b1Sopenharmony_ci let filePath: string; 16307ac75b1Sopenharmony_ci if (projectConfig.compileHar) { 16407ac75b1Sopenharmony_ci // compileShared: compile shared har of project 16507ac75b1Sopenharmony_ci filePath = genTemporaryPath(id, 16607ac75b1Sopenharmony_ci projectConfig.compileShared ? projectConfig.projectRootPath : projectConfig.moduleRootPath, 16707ac75b1Sopenharmony_ci projectConfig.compileShared ? path.resolve(projectConfig.aceModuleBuild, '../etsFortgz') : projectConfig.cachePath, 16807ac75b1Sopenharmony_ci projectConfig, metaInfo, projectConfig.compileShared); 16907ac75b1Sopenharmony_ci } else { 17007ac75b1Sopenharmony_ci filePath = genTemporaryPath(id, projectConfig.projectPath, projectConfig.cachePath, projectConfig, metaInfo); 17107ac75b1Sopenharmony_ci } 17207ac75b1Sopenharmony_ci 17307ac75b1Sopenharmony_ci const eventWriteFileContent = createAndStartEvent(parentEvent, 'write file content'); 17407ac75b1Sopenharmony_ci switch (path.extname(id)) { 17507ac75b1Sopenharmony_ci case EXTNAME_ETS: 17607ac75b1Sopenharmony_ci case EXTNAME_TS: 17707ac75b1Sopenharmony_ci case EXTNAME_JS: 17807ac75b1Sopenharmony_ci case EXTNAME_MJS: 17907ac75b1Sopenharmony_ci case EXTNAME_CJS: 18007ac75b1Sopenharmony_ci await writeFileContent(id, filePath, content, projectConfig, logger, metaInfo); 18107ac75b1Sopenharmony_ci break; 18207ac75b1Sopenharmony_ci case EXTNAME_JSON: 18307ac75b1Sopenharmony_ci const newFilePath: string = tryMangleFileName(filePath, projectConfig, id); 18407ac75b1Sopenharmony_ci mkdirsSync(path.dirname(newFilePath)); 18507ac75b1Sopenharmony_ci fs.writeFileSync(newFilePath, content ?? ''); 18607ac75b1Sopenharmony_ci break; 18707ac75b1Sopenharmony_ci default: 18807ac75b1Sopenharmony_ci break; 18907ac75b1Sopenharmony_ci } 19007ac75b1Sopenharmony_ci stopEvent(eventWriteFileContent); 19107ac75b1Sopenharmony_ci} 19207ac75b1Sopenharmony_ci 19307ac75b1Sopenharmony_ciasync function writeFileContent(sourceFilePath: string, filePath: string, content: string, 19407ac75b1Sopenharmony_ci projectConfig: Object, logger: Object, metaInfo?: Object): Promise<void> { 19507ac75b1Sopenharmony_ci if (!isSpecifiedExt(sourceFilePath, EXTNAME_JS)) { 19607ac75b1Sopenharmony_ci filePath = changeFileExtension(filePath, EXTNAME_JS); 19707ac75b1Sopenharmony_ci } 19807ac75b1Sopenharmony_ci 19907ac75b1Sopenharmony_ci if (!isDebug(projectConfig)) { 20007ac75b1Sopenharmony_ci const relativeSourceFilePath: string = getRelativeSourcePath(sourceFilePath, projectConfig.projectRootPath, 20107ac75b1Sopenharmony_ci metaInfo?.belongProjectPath); 20207ac75b1Sopenharmony_ci await writeObfuscatedSourceCode({content: content, buildFilePath: filePath, 20307ac75b1Sopenharmony_ci relativeSourceFilePath: relativeSourceFilePath, originSourceFilePath: sourceFilePath, rollupModuleId: sourceFilePath}, 20407ac75b1Sopenharmony_ci logger, projectConfig, SourceMapGenerator.getInstance().getSourceMaps()); 20507ac75b1Sopenharmony_ci return; 20607ac75b1Sopenharmony_ci } 20707ac75b1Sopenharmony_ci mkdirsSync(path.dirname(filePath)); 20807ac75b1Sopenharmony_ci fs.writeFileSync(filePath, content, 'utf-8'); 20907ac75b1Sopenharmony_ci} 21007ac75b1Sopenharmony_ci 21107ac75b1Sopenharmony_ciexport function getEs2abcFileThreadNumber(): number { 21207ac75b1Sopenharmony_ci const fileThreads: number = os.cpus().length < 16 ? os.cpus().length : 16; 21307ac75b1Sopenharmony_ci return fileThreads; 21407ac75b1Sopenharmony_ci} 21507ac75b1Sopenharmony_ci 21607ac75b1Sopenharmony_ciexport function isCommonJsPluginVirtualFile(filePath: string): boolean { 21707ac75b1Sopenharmony_ci // rollup uses commonjs plugin to handle commonjs files, 21807ac75b1Sopenharmony_ci // which will automatic generate files like 'jsfile.js?commonjs-exports' 21907ac75b1Sopenharmony_ci return filePath.includes('\x00'); 22007ac75b1Sopenharmony_ci} 22107ac75b1Sopenharmony_ci 22207ac75b1Sopenharmony_ciexport function isCurrentProjectFiles(filePath: string, projectConfig: Object): boolean { 22307ac75b1Sopenharmony_ci if (projectConfig.rootPathSet) { 22407ac75b1Sopenharmony_ci for (const projectRootPath of projectConfig.rootPathSet) { 22507ac75b1Sopenharmony_ci if (isFileInProject(filePath, projectRootPath)) { 22607ac75b1Sopenharmony_ci return true; 22707ac75b1Sopenharmony_ci } 22807ac75b1Sopenharmony_ci } 22907ac75b1Sopenharmony_ci return false; 23007ac75b1Sopenharmony_ci } 23107ac75b1Sopenharmony_ci return isFileInProject(filePath, projectConfig.projectRootPath); 23207ac75b1Sopenharmony_ci} 23307ac75b1Sopenharmony_ci 23407ac75b1Sopenharmony_ciexport function genTemporaryModuleCacheDirectoryForBundle(projectConfig: Object): string { 23507ac75b1Sopenharmony_ci const buildDirArr: string[] = projectConfig.aceModuleBuild.split(path.sep); 23607ac75b1Sopenharmony_ci const abilityDir: string = buildDirArr[buildDirArr.length - 1]; 23707ac75b1Sopenharmony_ci const temporaryModuleCacheDirPath: string = path.join(projectConfig.cachePath, TEMPORARY, abilityDir); 23807ac75b1Sopenharmony_ci mkdirsSync(temporaryModuleCacheDirPath); 23907ac75b1Sopenharmony_ci 24007ac75b1Sopenharmony_ci return temporaryModuleCacheDirPath; 24107ac75b1Sopenharmony_ci} 24207ac75b1Sopenharmony_ci 24307ac75b1Sopenharmony_ciexport function isSpecifiedExt(filePath: string, fileExtendName: string) { 24407ac75b1Sopenharmony_ci return path.extname(filePath) === fileExtendName; 24507ac75b1Sopenharmony_ci} 24607ac75b1Sopenharmony_ci 24707ac75b1Sopenharmony_ciexport function genCachePath(tailName: string, projectConfig: Object, logger: Object): string { 24807ac75b1Sopenharmony_ci const pathName: string = projectConfig.cachePath !== undefined ? 24907ac75b1Sopenharmony_ci path.join(projectConfig.cachePath, TEMPORARY, tailName) : path.join(projectConfig.aceModuleBuild, tailName); 25007ac75b1Sopenharmony_ci mkdirsSync(path.dirname(pathName)); 25107ac75b1Sopenharmony_ci 25207ac75b1Sopenharmony_ci validateFilePathLength(pathName, logger); 25307ac75b1Sopenharmony_ci return pathName; 25407ac75b1Sopenharmony_ci} 25507ac75b1Sopenharmony_ci 25607ac75b1Sopenharmony_ciexport function isTsOrEtsSourceFile(file: string): boolean { 25707ac75b1Sopenharmony_ci return /(?<!\.d)\.[e]?ts$/.test(file); 25807ac75b1Sopenharmony_ci} 25907ac75b1Sopenharmony_ci 26007ac75b1Sopenharmony_ciexport function isJsSourceFile(file: string): boolean { 26107ac75b1Sopenharmony_ci return /\.[cm]?js$/.test(file); 26207ac75b1Sopenharmony_ci} 26307ac75b1Sopenharmony_ci 26407ac75b1Sopenharmony_ciexport function isJsonSourceFile(file: string): boolean { 26507ac75b1Sopenharmony_ci return /\.json$/.test(file); 26607ac75b1Sopenharmony_ci} 26707ac75b1Sopenharmony_ci 26807ac75b1Sopenharmony_ciexport async function updateSourceMap(originMap: sourceMap.RawSourceMap, newMap: sourceMap.RawSourceMap): Promise<any> { 26907ac75b1Sopenharmony_ci if (!originMap) { 27007ac75b1Sopenharmony_ci return newMap; 27107ac75b1Sopenharmony_ci } 27207ac75b1Sopenharmony_ci if (!newMap) { 27307ac75b1Sopenharmony_ci return originMap; 27407ac75b1Sopenharmony_ci } 27507ac75b1Sopenharmony_ci const originConsumer: sourceMap.SourceMapConsumer = await new sourceMap.SourceMapConsumer(originMap); 27607ac75b1Sopenharmony_ci const newConsumer: sourceMap.SourceMapConsumer = await new sourceMap.SourceMapConsumer(newMap); 27707ac75b1Sopenharmony_ci const newMappingList: sourceMap.MappingItem[] = []; 27807ac75b1Sopenharmony_ci newConsumer.eachMapping((mapping: sourceMap.MappingItem) => { 27907ac75b1Sopenharmony_ci if (mapping.originalLine == null) { 28007ac75b1Sopenharmony_ci return; 28107ac75b1Sopenharmony_ci } 28207ac75b1Sopenharmony_ci const originalPos = 28307ac75b1Sopenharmony_ci originConsumer.originalPositionFor({ line: mapping.originalLine, column: mapping.originalColumn }); 28407ac75b1Sopenharmony_ci if (originalPos.source == null) { 28507ac75b1Sopenharmony_ci return; 28607ac75b1Sopenharmony_ci } 28707ac75b1Sopenharmony_ci mapping.originalLine = originalPos.line; 28807ac75b1Sopenharmony_ci mapping.originalColumn = originalPos.column; 28907ac75b1Sopenharmony_ci newMappingList.push(mapping); 29007ac75b1Sopenharmony_ci }); 29107ac75b1Sopenharmony_ci const updatedGenerator: sourceMap.SourceMapGenerator = sourceMap.SourceMapGenerator.fromSourceMap(newConsumer); 29207ac75b1Sopenharmony_ci updatedGenerator._file = originMap.file; 29307ac75b1Sopenharmony_ci updatedGenerator._mappings._array = newMappingList; 29407ac75b1Sopenharmony_ci return JSON.parse(updatedGenerator.toString()); 29507ac75b1Sopenharmony_ci} 29607ac75b1Sopenharmony_ci 29707ac75b1Sopenharmony_ciexport function hasArkDecorator(node: ts.MethodDeclaration | ts.FunctionDeclaration | 29807ac75b1Sopenharmony_ci ts.StructDeclaration | ts.ClassDeclaration | ts.TypeAliasDeclaration, decortorName: string): boolean { 29907ac75b1Sopenharmony_ci const decorators: readonly ts.Decorator[] = ts.getAllDecorators(node); 30007ac75b1Sopenharmony_ci if (decorators && decorators.length) { 30107ac75b1Sopenharmony_ci for (let i = 0; i < decorators.length; i++) { 30207ac75b1Sopenharmony_ci const originalDecortor: string = decorators[i].getText().replace(/\(.*\)$/, '').replace(/\s*/g, '').trim(); 30307ac75b1Sopenharmony_ci return originalDecortor === decortorName; 30407ac75b1Sopenharmony_ci } 30507ac75b1Sopenharmony_ci } 30607ac75b1Sopenharmony_ci return false; 30707ac75b1Sopenharmony_ci} 30807ac75b1Sopenharmony_ci 30907ac75b1Sopenharmony_ciexport const utUtils = { 31007ac75b1Sopenharmony_ci writeFileContent 31107ac75b1Sopenharmony_ci};