summaryrefslogtreecommitdiffstats
path: root/tools/esmify/import-to-import_esmodule.js
diff options
context:
space:
mode:
Diffstat (limited to 'tools/esmify/import-to-import_esmodule.js')
-rw-r--r--tools/esmify/import-to-import_esmodule.js472
1 files changed, 0 insertions, 472 deletions
diff --git a/tools/esmify/import-to-import_esmodule.js b/tools/esmify/import-to-import_esmodule.js
deleted file mode 100644
index d8e0aee5bb..0000000000
--- a/tools/esmify/import-to-import_esmodule.js
+++ /dev/null
@@ -1,472 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-// jscodeshift rule to replace import calls for JSM with import calls for ESM
-// or static import for ESM.
-
-/* eslint-env node */
-
-const _path = require("path");
-const { isESMified } = require(_path.resolve(__dirname, "./is-esmified.js"));
-const {
- jsmExtPattern,
- esmifyExtension,
- isIdentifier,
- isString,
- warnForPath,
- getPrevStatement,
- getNextStatement,
- isMemberExpressionWithIdentifiers,
- rewriteMemberExpressionWithIdentifiers,
- createMemberExpressionWithIdentifiers,
-} = require(_path.resolve(__dirname, "./utils.js"));
-const {
- isImportESModuleCall,
- replaceImportESModuleCall,
- tryReplacingWithStaticImport,
-} = require(_path.resolve(__dirname, "./static-import.js"));
-
-module.exports = function (fileInfo, api) {
- const { jscodeshift } = api;
- const root = jscodeshift(fileInfo.source);
- doTranslate(fileInfo.path, jscodeshift, root);
- return root.toSource({ lineTerminator: "\n" });
-};
-
-module.exports.doTranslate = doTranslate;
-
-function isESMifiedAndTarget(resourceURI) {
- const files = [];
- if (!isESMified(resourceURI, files)) {
- return false;
- }
-
- if ("ESMIFY_TARGET_PREFIX" in process.env) {
- const targetPrefix = process.env.ESMIFY_TARGET_PREFIX;
- for (const esm of files) {
- if (esm.startsWith(targetPrefix)) {
- return true;
- }
- }
-
- return false;
- }
-
- return true;
-}
-
-const importCalls = [
- {
- from: ["Cu", "import"],
- to: ["ChromeUtils", "importESModule"],
- },
- {
- from: ["ChromeUtils", "import"],
- to: ["ChromeUtils", "importESModule"],
- },
- {
- from: ["SpecialPowers", "ChromeUtils", "import"],
- to: ["SpecialPowers", "ChromeUtils", "importESModule"],
- },
-];
-
-const singleLazyGetterCalls = [
- {
- from: ["ChromeUtils", "defineModuleGetter"],
- to: ["ChromeUtils", "defineESModuleGetters"],
- },
- {
- from: ["SpecialPowers", "ChromeUtils", "defineModuleGetter"],
- to: ["SpecialPowers", "ChromeUtils", "defineESModuleGetters"],
- },
-];
-
-const multiLazyGettersCalls = [
- {
- from: ["XPCOMUtils", "defineLazyModuleGetters"],
- to: ["ChromeUtils", "defineESModuleGetters"],
- },
-];
-
-function isMemberExpressionMatchingPatterns(node, patterns) {
- for (const item of patterns) {
- if (isMemberExpressionWithIdentifiers(node, item.from)) {
- return item;
- }
- }
-
- return null;
-}
-
-function replaceImportCall(inputFile, jscodeshift, path, rewriteItem) {
- if (path.node.arguments.length !== 1) {
- warnForPath(inputFile, path, `import call should have only one argument`);
- return;
- }
-
- const resourceURINode = path.node.arguments[0];
- if (!isString(resourceURINode)) {
- warnForPath(inputFile, path, `resource URI should be a string`);
- return;
- }
-
- const resourceURI = resourceURINode.value;
- if (!resourceURI.match(jsmExtPattern)) {
- warnForPath(inputFile, path, `Non-jsm: ${resourceURI}`);
- return;
- }
-
- if (!isESMifiedAndTarget(resourceURI)) {
- return;
- }
-
- if (
- !tryReplacingWithStaticImport(
- jscodeshift,
- inputFile,
- path,
- resourceURINode,
- false
- )
- ) {
- rewriteMemberExpressionWithIdentifiers(path.node.callee, rewriteItem.to);
- resourceURINode.value = esmifyExtension(resourceURI);
- }
-}
-
-// Find `ChromeUtils.defineESModuleGetters` or variant statement specified by
-// expectedIDs, adjacent to `path` which uses the same target object.
-function findDefineESModuleGettersStmt(path, expectedIDs) {
- // `path` must be top-level.
- if (path.parent.node.type !== "ExpressionStatement") {
- return null;
- }
-
- if (path.parent.parent.node.type !== "Program") {
- return null;
- }
-
- // Get previous or next statement with ChromeUtils.defineESModuleGetters.
- let callStmt;
- const prev = getPrevStatement(path.parent);
- if (
- prev &&
- prev.type === "ExpressionStatement" &&
- prev.expression.type === "CallExpression" &&
- isMemberExpressionWithIdentifiers(prev.expression.callee, expectedIDs)
- ) {
- callStmt = prev;
- } else {
- const next = getNextStatement(path.parent);
- if (
- next &&
- next.type === "ExpressionStatement" &&
- next.expression.type === "CallExpression" &&
- isMemberExpressionWithIdentifiers(next.expression.callee, expectedIDs)
- ) {
- callStmt = next;
- } else {
- return null;
- }
- }
-
- const call = callStmt.expression;
-
- if (call.arguments.length !== 2) {
- return null;
- }
-
- const modulesNode = call.arguments[1];
- if (modulesNode.type !== "ObjectExpression") {
- return null;
- }
-
- // Check if the target object is same.
- if (
- path.node.arguments[0].type === "ThisExpression" &&
- call.arguments[0].type === "ThisExpression"
- ) {
- return callStmt;
- }
-
- if (
- path.node.arguments[0].type === "Identifier" &&
- call.arguments[0].type === "Identifier" &&
- path.node.arguments[0].name === call.arguments[0].name
- ) {
- return callStmt;
- }
-
- return null;
-}
-
-function getPropKeyString(prop) {
- if (prop.key.type === "Identifier") {
- return prop.key.name;
- }
-
- if (prop.key.type === "Literal") {
- return prop.key.value.toString();
- }
-
- return "";
-}
-
-function sortProps(obj) {
- obj.properties.sort((a, b) => {
- return getPropKeyString(a) < getPropKeyString(b) ? -1 : 1;
- });
-}
-
-// Move comments above `nodeFrom` before `nodeTo`.
-function moveComments(nodeTo, nodeFrom) {
- if (!nodeFrom.comments) {
- return;
- }
- if (nodeTo.comments) {
- nodeTo.comments = [...nodeTo.comments, ...nodeFrom.comments];
- } else {
- nodeTo.comments = nodeFrom.comments;
- }
- nodeFrom.comments = [];
-}
-
-function replaceLazyGetterCall(inputFile, jscodeshift, path, rewriteItem) {
- if (path.node.arguments.length !== 3) {
- warnForPath(inputFile, path, `lazy getter call should have 3 arguments`);
- return;
- }
-
- const nameNode = path.node.arguments[1];
- if (!isString(nameNode)) {
- warnForPath(inputFile, path, `name should be a string`);
- return;
- }
-
- const resourceURINode = path.node.arguments[2];
- if (!isString(resourceURINode)) {
- warnForPath(inputFile, path, `resource URI should be a string`);
- return;
- }
-
- const resourceURI = resourceURINode.value;
- if (!resourceURI.match(jsmExtPattern)) {
- warnForPath(inputFile, path, `Non-js/jsm: ${resourceURI}`);
- return;
- }
-
- if (!isESMifiedAndTarget(resourceURI)) {
- return;
- }
-
- resourceURINode.value = esmifyExtension(resourceURI);
- const prop = jscodeshift.property(
- "init",
- jscodeshift.identifier(nameNode.value),
- resourceURINode
- );
-
- const callStmt = findDefineESModuleGettersStmt(path, rewriteItem.to);
- if (callStmt) {
- // Move a property to existing ChromeUtils.defineESModuleGetters call.
-
- moveComments(callStmt, path.parent.node);
- path.parent.prune();
-
- callStmt.expression.arguments[1].properties.push(prop);
- sortProps(callStmt.expression.arguments[1]);
- } else {
- // Convert this call into ChromeUtils.defineESModuleGetters.
-
- rewriteMemberExpressionWithIdentifiers(path.node.callee, rewriteItem.to);
- path.node.arguments = [
- path.node.arguments[0],
- jscodeshift.objectExpression([prop]),
- ];
- }
-}
-
-function replaceLazyGettersCall(inputFile, jscodeshift, path, rewriteItem) {
- if (path.node.arguments.length !== 2) {
- warnForPath(inputFile, path, `lazy getters call should have 2 arguments`);
- return;
- }
-
- const modulesNode = path.node.arguments[1];
- if (modulesNode.type !== "ObjectExpression") {
- warnForPath(inputFile, path, `modules parameter should be an object`);
- return;
- }
-
- const esmProps = [];
- const jsmProps = [];
-
- for (const prop of modulesNode.properties) {
- const resourceURINode = prop.value;
- if (!isString(resourceURINode)) {
- warnForPath(inputFile, path, `resource URI should be a string`);
- jsmProps.push(prop);
- continue;
- }
-
- const resourceURI = resourceURINode.value;
- if (!resourceURI.match(jsmExtPattern)) {
- warnForPath(inputFile, path, `Non-js/jsm: ${resourceURI}`);
- jsmProps.push(prop);
- continue;
- }
-
- if (!isESMifiedAndTarget(resourceURI)) {
- jsmProps.push(prop);
- continue;
- }
-
- esmProps.push(prop);
- }
-
- if (esmProps.length === 0) {
- return;
- }
-
- let callStmt = findDefineESModuleGettersStmt(path, rewriteItem.to);
- if (jsmProps.length === 0) {
- if (callStmt) {
- // Move all properties to existing ChromeUtils.defineESModuleGetters call.
-
- moveComments(callStmt, path.parent.node);
- path.parent.prune();
-
- for (const prop of esmProps) {
- const resourceURINode = prop.value;
- resourceURINode.value = esmifyExtension(resourceURINode.value);
- callStmt.expression.arguments[1].properties.push(prop);
- }
- sortProps(callStmt.expression.arguments[1]);
- } else {
- // Convert this call into ChromeUtils.defineESModuleGetters.
-
- rewriteMemberExpressionWithIdentifiers(path.node.callee, rewriteItem.to);
- for (const prop of esmProps) {
- const resourceURINode = prop.value;
- resourceURINode.value = esmifyExtension(resourceURINode.value);
- }
- }
- } else {
- // Move some properties to ChromeUtils.defineESModuleGetters.
-
- if (path.parent.node.type !== "ExpressionStatement") {
- warnForPath(inputFile, path, `lazy getters call in unexpected context`);
- return;
- }
-
- if (!callStmt) {
- callStmt = jscodeshift.expressionStatement(
- jscodeshift.callExpression(
- createMemberExpressionWithIdentifiers(jscodeshift, rewriteItem.to),
- [path.node.arguments[0], jscodeshift.objectExpression([])]
- )
- );
- path.parent.insertBefore(callStmt);
- }
-
- moveComments(callStmt, path.parent.node);
-
- for (const prop of esmProps) {
- const resourceURINode = prop.value;
- resourceURINode.value = esmifyExtension(resourceURINode.value);
- callStmt.expression.arguments[1].properties.push(prop);
- }
- sortProps(callStmt.expression.arguments[1]);
-
- path.node.arguments[1].properties = jsmProps;
- }
-}
-
-function getProp(obj, key) {
- if (obj.type !== "ObjectExpression") {
- return null;
- }
-
- for (const prop of obj.properties) {
- if (prop.computed) {
- continue;
- }
-
- if (!prop.key) {
- continue;
- }
-
- if (isIdentifier(prop.key, key)) {
- return prop;
- }
- }
-
- return null;
-}
-
-function tryReplaceActorDefinition(inputFile, path, name) {
- const obj = path.node;
-
- const prop = getProp(obj, name);
- if (!prop) {
- return;
- }
-
- const moduleURIProp = getProp(prop.value, "moduleURI");
- if (!moduleURIProp) {
- return;
- }
-
- if (!isString(moduleURIProp.value)) {
- warnForPath(inputFile, path, `${name} moduleURI should be a string`);
- return;
- }
-
- const moduleURI = moduleURIProp.value.value;
- if (!moduleURI.match(jsmExtPattern)) {
- warnForPath(inputFile, path, `${name} Non-js/jsm: ${moduleURI}`);
- return;
- }
-
- if (!isESMifiedAndTarget(moduleURI)) {
- return;
- }
-
- moduleURIProp.key.name = "esModuleURI";
- moduleURIProp.value.value = esmifyExtension(moduleURI);
-}
-
-function doTranslate(inputFile, jscodeshift, root) {
- root.find(jscodeshift.CallExpression).forEach(path => {
- if (isImportESModuleCall(path.node)) {
- replaceImportESModuleCall(inputFile, jscodeshift, path, false);
- return;
- }
-
- const callee = path.node.callee;
-
- let item;
- item = isMemberExpressionMatchingPatterns(callee, importCalls);
- if (item) {
- replaceImportCall(inputFile, jscodeshift, path, item);
- return;
- }
-
- item = isMemberExpressionMatchingPatterns(callee, singleLazyGetterCalls);
- if (item) {
- replaceLazyGetterCall(inputFile, jscodeshift, path, item);
- return;
- }
-
- item = isMemberExpressionMatchingPatterns(callee, multiLazyGettersCalls);
- if (item) {
- replaceLazyGettersCall(inputFile, jscodeshift, path, item);
- }
- });
-
- root.find(jscodeshift.ObjectExpression).forEach(path => {
- tryReplaceActorDefinition(inputFile, path, "parent");
- tryReplaceActorDefinition(inputFile, path, "child");
- });
-}