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} from './common/ark_define'; 21import { ModuleSourceFile } from './module/module_source_file'; 22import { 23 isAotMode, 24 isCommonJsPluginVirtualFile, 25 isDebug, 26 isJsonSourceFile, 27 isJsSourceFile, 28 isTsOrEtsSourceFile, 29 shouldETSOrTSFileTransformToJS 30} from './utils'; 31import { toUnixPath } from '../../utils'; 32import { 33 getHookEventFactory, 34 createAndStartEvent, 35 stopEvent, 36 transformLazyImport 37} from '../../ark_utils'; 38import { SourceMapGenerator } from './generate_sourcemap'; 39 40/** 41 * rollup transform hook 42 * @param {string} code: transformed source code of an input file 43 * @param {string} id: absolute path of an input file 44 */ 45export function transformForModule(code: string, id: string): string { 46 const hookEventFactory = getHookEventFactory(this.share, 'genAbc', 'transform'); 47 const eventTransformForModule = createAndStartEvent(hookEventFactory, 'transform for module'); 48 if (this.share.projectConfig.compileMode === ESMODULE) { 49 const metaInfo: Object = this.getModuleInfo(id).meta; 50 const projectConfig: Object = Object.assign(this.share.arkProjectConfig, this.share.projectConfig); 51 if (isTsOrEtsSourceFile(id) && shouldETSOrTSFileTransformToJS(id, projectConfig, metaInfo)) { 52 preserveSourceMap(id, this.getCombinedSourcemap(), projectConfig, metaInfo, eventTransformForModule); 53 // when ets/ts -> js, we need to convert lazy-import based on the js code generated after tsc conversion 54 if (this.share.projectConfig?.autoLazyImport) { 55 code = <string> transformLazyImport(code, undefined, id); 56 } 57 ModuleSourceFile.newSourceFile(id, code, metaInfo); 58 } 59 60 if (isJsSourceFile(id) || isJsonSourceFile(id)) { 61 let code: string = this.getModuleInfo(id).originalCode; 62 if (isJsSourceFile(id)) { 63 if (this.share.projectConfig?.autoLazyImport) { 64 code = <string> transformLazyImport(code, undefined, id); 65 } 66 if (projectConfig.compatibleSdkVersion <= 10) { 67 const transformedResult: object = transformJsByBabelPlugin(code, eventTransformForModule); 68 code = transformedResult.code; 69 preserveSourceMap(id, transformedResult.map, projectConfig, metaInfo, eventTransformForModule); 70 } else { 71 // preserve sourceMap of js file without transforming 72 preserveSourceMap(id, this.getCombinedSourcemap(), projectConfig, metaInfo, eventTransformForModule); 73 } 74 } 75 ModuleSourceFile.newSourceFile(id, code, metaInfo); 76 } 77 } 78 stopEvent(eventTransformForModule); 79 // if we perform lazy-import conversion, we need to return the converted js code 80 return code; 81} 82 83function preserveSourceMap(sourceFilePath: string, sourcemap: Object, projectConfig: Object, metaInfo: Object, parentEvent: Object): void { 84 if (isCommonJsPluginVirtualFile(sourceFilePath)) { 85 // skip automatic generated files like 'jsfile.js?commonjs-exports' 86 return; 87 } 88 89 const eventAddSourceMapInfo = createAndStartEvent(parentEvent, 'preserve source map for ts/ets files'); 90 const relativeSourceFilePath = sourceFilePath.startsWith(projectConfig.projectRootPath) ? 91 toUnixPath(sourceFilePath.replace(projectConfig.projectRootPath + path.sep, '')) : 92 toUnixPath(sourceFilePath.replace(metaInfo.belongProjectPath + path.sep, '')); 93 sourcemap.sources = [relativeSourceFilePath]; 94 sourcemap.file = path.basename(relativeSourceFilePath); 95 sourcemap.sourcesContent && delete sourcemap.sourcesContent; 96 const sourceMapGenerator = SourceMapGenerator.getInstance(); 97 const key = sourceMapGenerator.isNewSourceMaps() ? sourceFilePath : relativeSourceFilePath; 98 sourceMapGenerator.fillSourceMapPackageInfo(sourceFilePath, sourcemap); 99 sourceMapGenerator.updateSourceMap(key, sourcemap); 100 stopEvent(eventAddSourceMapInfo); 101} 102 103function transformJsByBabelPlugin(code: string, parentEvent: Object): Object { 104 const eventTransformByBabel = createAndStartEvent(parentEvent, 'transform Js by babel plugin'); 105 const transformed: Object = require('@babel/core').transformSync(code, 106 { 107 plugins: [ 108 [require("@babel/plugin-proposal-class-properties"), { "loose": true }] 109 ], 110 compact: false, 111 sourceMaps: true 112 } 113 ); 114 stopEvent(eventTransformByBabel); 115 return transformed; 116}