• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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}