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/. */
7 const _path = require("path");
8 const { getESMFiles } = require(_path.resolve(__dirname, "./is-esmified.js"));
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)) {
32 function isImportESModuleCall(node) {
33 return isMemberExpressionWithIdentifiers(node.callee, [
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(
48 if (!alwaysReplace && !inputFile.endsWith(".sys.mjs")) {
49 // Static import is available only in system ESM.
53 // Check if it's at the top-level.
54 if (path.parent.node.type !== "VariableDeclarator") {
58 if (path.parent.parent.node.type !== "VariableDeclaration") {
62 const decls = path.parent.parent.node;
63 if (decls.declarations.length !== 1) {
67 if (path.parent.parent.parent.node.type !== "Program") {
71 if (path.node.arguments.length !== 1) {
75 const resourceURI = resourceURINode.value;
77 // Collect imported symbols.
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) {
84 specs.push(jscodeshift.importSpecifier(prop.key));
85 } else if (prop.value.type === "Identifier") {
86 specs.push(jscodeshift.importSpecifier(prop.key, prop.value));
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);
107 function replaceImportESModuleCall(
113 if (path.node.arguments.length !== 1) {
117 `importESModule call should have only one argument`
122 const resourceURINode = path.node.arguments[0];
123 if (!isString(resourceURINode)) {
124 warnForPath(inputFile, path, `resource URI should be a string`);
128 if (!alwaysReplace) {
129 const resourceURI = resourceURINode.value;
130 if (!isTargetESM(resourceURI)) {
135 // If this cannot be replaced with static import, do nothing.
136 tryReplacingWithStaticImport(
145 exports.isImportESModuleCall = isImportESModuleCall;
146 exports.tryReplacingWithStaticImport = tryReplacingWithStaticImport;
147 exports.replaceImportESModuleCall = replaceImportESModuleCall;