1/* 2 * Copyright (c) 2023 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 16import path from 'path'; 17 18import { 19 ESMODULE, 20 GEN_ABC_PLUGIN_NAME 21} from './common/ark_define'; 22import { ModuleSourceFile } from './module/module_source_file'; 23import { 24 isAotMode, 25 isCommonJsPluginVirtualFile, 26 isDebug, 27 isJsonSourceFile, 28 isJsSourceFile, 29 isTsOrEtsSourceFile, 30 shouldETSOrTSFileTransformToJS 31} from './utils'; 32import { 33 toUnixPath, 34 emitLogInfo, 35 getTransformLog 36} from '../../utils'; 37import { 38 resetReExportCheckLog, 39 reExportNoCheckMode, 40 processJsCodeLazyImport, 41 reExportCheckLog, 42 LazyImportOptions 43} from '../../process_lazy_import'; 44import { SourceMapGenerator } from './generate_sourcemap'; 45import { MemoryMonitor } from '../meomry_monitor/rollup-plugin-memory-monitor'; 46import { MemoryDefine } from '../meomry_monitor/memory_define'; 47import { 48 getHookEventFactory, 49 createAndStartEvent, 50 stopEvent, 51 CompileEvent 52} from '../../performance'; 53 54/** 55 * rollup transform hook 56 * @param {string} code: transformed source code of an input file 57 * @param {string} id: absolute path of an input file 58 */ 59export function transformForModule(code: string, id: string): string { 60 const hookEventFactory: CompileEvent | undefined = getHookEventFactory(this.share, 'genAbc', 'transform'); 61 const eventTransformForModule = createAndStartEvent(hookEventFactory, 'transform for module'); 62 const { 63 autoLazyImport, 64 reExportCheckMode 65 }: LazyImportOptions = { 66 autoLazyImport: this.share.projectConfig?.autoLazyImport ?? false, 67 reExportCheckMode: this.share.projectConfig?.reExportCheckMode ?? reExportNoCheckMode 68 }; 69 if (this.share.projectConfig.compileMode === ESMODULE) { 70 const metaInfo: Object = this.getModuleInfo(id).meta; 71 const projectConfig: Object = Object.assign(this.share.arkProjectConfig, this.share.projectConfig); 72 if (isTsOrEtsSourceFile(id) && shouldETSOrTSFileTransformToJS(id, projectConfig, metaInfo)) { 73 preserveSourceMap(id, this.getCombinedSourcemap(), projectConfig, metaInfo, eventTransformForModule); 74 // when ets/ts -> js, we need to convert lazy-import based on the js code generated after tsc conversion 75 code = processJsCodeLazyImport(id, code, autoLazyImport, reExportCheckMode); 76 const newSourceFileRecordInfo = MemoryMonitor.recordStage(MemoryDefine.MODULE_SOURCE_FILE_NEW_SOURCE_FILE); 77 ModuleSourceFile.newSourceFile(id, code, metaInfo, projectConfig.singleFileEmit); 78 MemoryMonitor.stopRecordStage(newSourceFileRecordInfo); 79 } 80 81 if (isJsSourceFile(id) || isJsonSourceFile(id)) { 82 let code: string = this.getModuleInfo(id).originalCode; 83 if (isJsSourceFile(id)) { 84 code = processJsCodeLazyImport(id, code, autoLazyImport, reExportCheckMode); 85 if (projectConfig.compatibleSdkVersion <= 10) { 86 const transformedResult: object = transformJsByBabelPlugin(code, eventTransformForModule); 87 code = transformedResult.code; 88 preserveSourceMap(id, transformedResult.map, projectConfig, metaInfo, eventTransformForModule); 89 } else { 90 // preserve sourceMap of js file without transforming 91 preserveSourceMap(id, this.getCombinedSourcemap(), projectConfig, metaInfo, eventTransformForModule); 92 } 93 } 94 const recordInfo = MemoryMonitor.recordStage(MemoryDefine.MODULE_SOURCE_FILE_NEW_SOURCE_FILE); 95 ModuleSourceFile.newSourceFile(id, code, metaInfo, projectConfig.singleFileEmit); 96 MemoryMonitor.stopRecordStage(recordInfo); 97 } 98 } 99 stopEvent(eventTransformForModule); 100 101 if (reExportCheckLog && reExportCheckLog.errors.length && 102 reExportCheckMode !== reExportNoCheckMode && !this.share.projectConfig.ignoreWarning) { 103 emitLogInfo(this.share.getLogger(GEN_ABC_PLUGIN_NAME), [...getTransformLog(reExportCheckLog)], true, id); 104 resetReExportCheckLog(); 105 } 106 107 // if we perform lazy-import conversion, we need to return the converted js code 108 return code; 109} 110 111function preserveSourceMap(sourceFilePath: string, sourcemap: Object, projectConfig: Object, metaInfo: Object, parentEvent: CompileEvent): void { 112 if (isCommonJsPluginVirtualFile(sourceFilePath)) { 113 // skip automatic generated files like 'jsfile.js?commonjs-exports' 114 return; 115 } 116 117 const eventAddSourceMapInfo = createAndStartEvent(parentEvent, 'preserve source map for ts/ets files'); 118 const relativeSourceFilePath = sourceFilePath.startsWith(projectConfig.projectRootPath) ? 119 toUnixPath(sourceFilePath.replace(projectConfig.projectRootPath + path.sep, '')) : 120 toUnixPath(sourceFilePath.replace(metaInfo.belongProjectPath + path.sep, '')); 121 sourcemap.sources = [relativeSourceFilePath]; 122 sourcemap.file = path.basename(relativeSourceFilePath); 123 sourcemap.sourcesContent && delete sourcemap.sourcesContent; 124 const sourceMapGenerator = SourceMapGenerator.getInstance(); 125 const key = sourceMapGenerator.isNewSourceMaps() ? sourceFilePath : relativeSourceFilePath; 126 sourceMapGenerator.fillSourceMapPackageInfo(sourceFilePath, sourcemap); 127 sourceMapGenerator.updateSourceMap(key, sourcemap); 128 stopEvent(eventAddSourceMapInfo); 129} 130 131function transformJsByBabelPlugin(code: string, parentEvent: CompileEvent): Object { 132 const eventTransformByBabel = createAndStartEvent(parentEvent, 'transform Js by babel plugin'); 133 const transformed: Object = require('@babel/core').transformSync(code, 134 { 135 plugins: [ 136 [require("@babel/plugin-proposal-class-properties"), { "loose": true }] 137 ], 138 compact: false, 139 sourceMaps: true 140 } 141 ); 142 stopEvent(eventTransformByBabel); 143 return transformed; 144}