Bug 1829125 - Align the PHC area to the jemalloc chunk size r=glandium
[gecko.git] / tools / esmify / static-import.js
blobe99bfb33800d653d5d597a101875cfaa04b6a5ca
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 /* eslint-env node */
7 const _path = require("path");
8 const { getESMFiles } = require(_path.resolve(__dirname, "./is-esmified.js"));
9 const {
10   esmifyExtension,
11   isString,
12   warnForPath,
13   isMemberExpressionWithIdentifiers,
14 } = require(_path.resolve(__dirname, "./utils.js"));
16 function isTargetESM(resourceURI) {
17   if ("ESMIFY_TARGET_PREFIX" in process.env) {
18     const files = getESMFiles(resourceURI);
19     const targetPrefix = process.env.ESMIFY_TARGET_PREFIX;
20     for (const esm of files) {
21       if (esm.startsWith(targetPrefix)) {
22         return true;
23       }
24     }
26     return false;
27   }
29   return true;
32 function isImportESModuleCall(node) {
33   return isMemberExpressionWithIdentifiers(node.callee, [
34     "ChromeUtils",
35     "importESModule",
36   ]);
39 // Replace `ChromeUtils.import`, `Cu.import`, and `ChromeUtils.importESModule`
40 // with static import if it's at the top-level of system ESM file.
41 function tryReplacingWithStaticImport(
42   jscodeshift,
43   inputFile,
44   path,
45   resourceURINode,
46   alwaysReplace
47 ) {
48   if (!alwaysReplace && !inputFile.endsWith(".sys.mjs")) {
49     // Static import is available only in system ESM.
50     return false;
51   }
53   // Check if it's at the top-level.
54   if (path.parent.node.type !== "VariableDeclarator") {
55     return false;
56   }
58   if (path.parent.parent.node.type !== "VariableDeclaration") {
59     return false;
60   }
62   const decls = path.parent.parent.node;
63   if (decls.declarations.length !== 1) {
64     return false;
65   }
67   if (path.parent.parent.parent.node.type !== "Program") {
68     return false;
69   }
71   if (path.node.arguments.length !== 1) {
72     return false;
73   }
75   const resourceURI = resourceURINode.value;
77   // Collect imported symbols.
78   const specs = [];
79   if (path.parent.node.id.type === "Identifier") {
80     specs.push(jscodeshift.importNamespaceSpecifier(path.parent.node.id));
81   } else if (path.parent.node.id.type === "ObjectPattern") {
82     for (const prop of path.parent.node.id.properties) {
83       if (prop.shorthand) {
84         specs.push(jscodeshift.importSpecifier(prop.key));
85       } else if (prop.value.type === "Identifier") {
86         specs.push(jscodeshift.importSpecifier(prop.key, prop.value));
87       } else {
88         return false;
89       }
90     }
91   } else {
92     return false;
93   }
95   // If this is `ChromeUtils.import` or `Cu.import`, replace the extension.
96   // no-op for `ChromeUtils.importESModule`.
97   resourceURINode.value = esmifyExtension(resourceURI);
99   const e = jscodeshift.importDeclaration(specs, resourceURINode);
100   e.comments = path.parent.parent.node.comments;
101   path.parent.parent.node.comments = [];
102   path.parent.parent.replace(e);
104   return true;
107 function replaceImportESModuleCall(
108   inputFile,
109   jscodeshift,
110   path,
111   alwaysReplace
112 ) {
113   if (path.node.arguments.length !== 1) {
114     warnForPath(
115       inputFile,
116       path,
117       `importESModule call should have only one argument`
118     );
119     return;
120   }
122   const resourceURINode = path.node.arguments[0];
123   if (!isString(resourceURINode)) {
124     warnForPath(inputFile, path, `resource URI should be a string`);
125     return;
126   }
128   if (!alwaysReplace) {
129     const resourceURI = resourceURINode.value;
130     if (!isTargetESM(resourceURI)) {
131       return;
132     }
133   }
135   // If this cannot be replaced with static import, do nothing.
136   tryReplacingWithStaticImport(
137     jscodeshift,
138     inputFile,
139     path,
140     resourceURINode,
141     alwaysReplace
142   );
145 exports.isImportESModuleCall = isImportESModuleCall;
146 exports.tryReplacingWithStaticImport = tryReplacingWithStaticImport;
147 exports.replaceImportESModuleCall = replaceImportESModuleCall;