summaryrefslogtreecommitdiffstats
path: root/tools/esmify/mach_commands.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/esmify/mach_commands.py')
-rw-r--r--tools/esmify/mach_commands.py908
1 files changed, 0 insertions, 908 deletions
diff --git a/tools/esmify/mach_commands.py b/tools/esmify/mach_commands.py
deleted file mode 100644
index 7b72c7b0e3..0000000000
--- a/tools/esmify/mach_commands.py
+++ /dev/null
@@ -1,908 +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/.
-
-import json
-import logging
-import os
-import pathlib
-import re
-import subprocess
-import sys
-
-from mach.decorators import Command, CommandArgument
-
-
-def path_sep_to_native(path_str):
- """Make separators in the path OS native."""
- return pathlib.os.sep.join(path_str.split("/"))
-
-
-def path_sep_from_native(path):
- """Make separators in the path OS native."""
- return "/".join(str(path).split(pathlib.os.sep))
-
-
-excluded_from_convert_prefix = list(
- map(
- path_sep_to_native,
- [
- # Testcases for actors.
- "toolkit/actors/TestProcessActorChild.jsm",
- "toolkit/actors/TestProcessActorParent.jsm",
- "toolkit/actors/TestWindowChild.jsm",
- "toolkit/actors/TestWindowParent.jsm",
- "js/xpconnect/tests/unit/",
- # Testcase for build system.
- "python/mozbuild/mozbuild/test/",
- ],
- )
-)
-
-
-def is_excluded_from_convert(path):
- """Returns true if the JSM file shouldn't be converted to ESM."""
- path_str = str(path)
- for prefix in excluded_from_convert_prefix:
- if path_str.startswith(prefix):
- return True
-
- return False
-
-
-excluded_from_imports_prefix = list(
- map(
- path_sep_to_native,
- [
- # Vendored or auto-generated files.
- "browser/components/pocket/content/panels/js/vendor.bundle.js",
- "devtools/client/debugger/dist/parser-worker.js",
- "devtools/client/debugger/test/mochitest/examples/react/build/main.js",
- "devtools/client/debugger/test/mochitest/examples/sourcemapped/polyfill-bundle.js",
- "devtools/client/inspector/markup/test/shadowdom_open_debugger.min.js",
- "devtools/client/shared/source-map-loader/test/browser/fixtures/bundle.js",
- "layout/style/test/property_database.js",
- "services/fxaccounts/FxAccountsPairingChannel.js",
- "testing/web-platform/",
- # Unrelated testcases that has edge case syntax.
- "browser/components/sessionstore/test/unit/data/",
- "devtools/client/debugger/src/workers/parser/tests/fixtures/",
- "devtools/client/debugger/test/mochitest/examples/sourcemapped/fixtures/",
- "devtools/client/webconsole/test/browser/test-syntaxerror-worklet.js",
- "devtools/server/tests/xpcshell/test_framebindings-03.js",
- "devtools/server/tests/xpcshell/test_framebindings-04.js",
- "devtools/shared/tests/xpcshell/test_eventemitter_basic.js",
- "devtools/shared/tests/xpcshell/test_eventemitter_static.js",
- "dom/base/crashtests/module-with-syntax-error.js",
- "dom/base/test/file_bug687859-16.js",
- "dom/base/test/file_bug687859-16.js",
- "dom/base/test/file_js_cache_syntax_error.js",
- "dom/base/test/jsmodules/module_badSyntax.js",
- "dom/canvas/test/reftest/webgl-utils.js",
- "dom/encoding/test/file_utf16_be_bom.js",
- "dom/encoding/test/file_utf16_le_bom.js",
- "dom/html/test/bug649134/file_bug649134-1.sjs",
- "dom/html/test/bug649134/file_bug649134-2.sjs",
- "dom/media/webrtc/tests/mochitests/identity/idp-bad.js",
- "dom/serviceworkers/test/file_js_cache_syntax_error.js",
- "dom/serviceworkers/test/parse_error_worker.js",
- "dom/workers/test/importScripts_worker_imported3.js",
- "dom/workers/test/invalid.js",
- "dom/workers/test/threadErrors_worker1.js",
- "dom/xhr/tests/browser_blobFromFile.js",
- "image/test/browser/browser_image.js",
- "js/xpconnect/tests/chrome/test_bug732665_meta.js",
- "js/xpconnect/tests/mochitest/class_static_worker.js",
- "js/xpconnect/tests/unit/bug451678_subscript.js",
- "js/xpconnect/tests/unit/error_other.sys.mjs",
- "js/xpconnect/tests/unit/es6module_parse_error.js",
- "js/xpconnect/tests/unit/recursive_importA.jsm",
- "js/xpconnect/tests/unit/recursive_importB.jsm",
- "js/xpconnect/tests/unit/syntax_error.jsm",
- "js/xpconnect/tests/unit/test_defineModuleGetter.js",
- "js/xpconnect/tests/unit/test_import.js",
- "js/xpconnect/tests/unit/test_import_shim.js",
- "js/xpconnect/tests/unit/test_recursive_import.js",
- "js/xpconnect/tests/unit/test_unload.js",
- "modules/libpref/test/unit/data/testParser.js",
- "python/mozbuild/mozbuild/test/",
- "remote/shared/messagehandler/test/browser/resources/modules/root/invalid.sys.mjs",
- "testing/talos/talos/startup_test/sessionrestore/profile-manywindows/sessionstore.js",
- "testing/talos/talos/startup_test/sessionrestore/profile/sessionstore.js",
- "toolkit/components/reader/Readerable.sys.mjs",
- "toolkit/components/workerloader/tests/moduleF-syntax-error.js",
- "tools/lint/test/",
- "tools/update-packaging/test/",
- # SpiderMonkey internals.
- "js/examples/",
- "js/src/",
- # Files has macro.
- "browser/app/profile/firefox.js",
- "browser/branding/official/pref/firefox-branding.js",
- "browser/components/enterprisepolicies/schemas/schema.sys.mjs",
- "browser/locales/en-US/firefox-l10n.js",
- "mobile/android/app/geckoview-prefs.js",
- "mobile/android/locales/en-US/mobile-l10n.js",
- "modules/libpref/greprefs.js",
- "modules/libpref/init/all.js",
- "testing/condprofile/condprof/tests/profile/user.js",
- "testing/mozbase/mozprofile/tests/files/prefs_with_comments.js",
- "toolkit/modules/AppConstants.sys.mjs",
- "toolkit/mozapps/update/tests/data/xpcshellConstantsPP.js",
- # Uniffi templates
- "toolkit/components/uniffi-bindgen-gecko-js/src/templates/js/",
- ],
- )
-)
-
-EXCLUSION_FILES = [
- os.path.join("tools", "rewriting", "Generated.txt"),
- os.path.join("tools", "rewriting", "ThirdPartyPaths.txt"),
-]
-
-
-def load_exclusion_files():
- for path in EXCLUSION_FILES:
- with open(path, "r") as f:
- for line in f:
- p = path_sep_to_native(re.sub(r"\*$", "", line.strip()))
- excluded_from_imports_prefix.append(p)
-
-
-def is_excluded_from_imports(path):
- """Returns true if the JS file content shouldn't be handled by
- jscodeshift.
-
- This filter is necessary because jscodeshift cannot handle some
- syntax edge cases and results in unexpected rewrite."""
- path_str = str(path)
- for prefix in excluded_from_imports_prefix:
- if path_str.startswith(prefix):
- return True
-
- return False
-
-
-# Wrapper for hg/git operations
-class VCSUtils:
- def run(self, cmd):
- # Do not pass check=True because the pattern can match no file.
- lines = subprocess.run(cmd, stdout=subprocess.PIPE).stdout.decode()
- return filter(lambda x: x != "", lines.split("\n"))
-
-
-class HgUtils(VCSUtils):
- def is_available():
- return pathlib.Path(".hg").exists()
-
- def rename(self, before, after):
- cmd = ["hg", "rename", before, after]
- subprocess.run(cmd, check=True)
-
- def find_jsms(self, path):
- jsms = []
-
- # NOTE: `set:glob:` syntax does not accept backslash on windows.
- path = path_sep_from_native(path)
-
- cmd = ["hg", "files", f'set:glob:"{path}/**/*.jsm"']
- for line in self.run(cmd):
- jsm = pathlib.Path(line)
- if is_excluded_from_convert(jsm):
- continue
- jsms.append(jsm)
-
- cmd = [
- "hg",
- "files",
- rf"set:grep('EXPORTED_SYMBOLS = \[') and glob:\"{path}/**/*.js\"",
- ]
- for line in self.run(cmd):
- jsm = pathlib.Path(line)
- if is_excluded_from_convert(jsm):
- continue
- jsms.append(jsm)
-
- return jsms
-
- def find_all_jss(self, path):
- jss = []
-
- # NOTE: `set:glob:` syntax does not accept backslash on windows.
- path = path_sep_from_native(path)
-
- cmd = [
- "hg",
- "files",
- f'set:glob:"{path}/**/*.jsm" or glob:"{path}/**/*.js" or '
- + f'glob:"{path}/**/*.mjs" or glob:"{path}/**/*.sjs"',
- ]
- for line in self.run(cmd):
- js = pathlib.Path(line)
- if is_excluded_from_imports(js):
- continue
- jss.append(js)
-
- return jss
-
-
-class GitUtils(VCSUtils):
- def is_available():
- return pathlib.Path(".git").exists()
-
- def rename(self, before, after):
- cmd = ["git", "mv", before, after]
- subprocess.run(cmd, check=True)
-
- def find_jsms(self, path):
- jsms = []
-
- cmd = ["git", "ls-files", f"{path}/*.jsm"]
- for line in self.run(cmd):
- jsm = pathlib.Path(line)
- if is_excluded_from_convert(jsm):
- continue
- jsms.append(jsm)
-
- handled = {}
- cmd = ["git", "grep", "EXPORTED_SYMBOLS = \\[", f"{path}/*.js"]
- for line in self.run(cmd):
- m = re.search("^([^:]+):", line)
- if not m:
- continue
- filename = m.group(1)
- if filename in handled:
- continue
- handled[filename] = True
- jsm = pathlib.Path(filename)
- if is_excluded_from_convert(jsm):
- continue
- jsms.append(jsm)
-
- return jsms
-
- def find_all_jss(self, path):
- jss = []
-
- cmd = [
- "git",
- "ls-files",
- f"{path}/*.jsm",
- f"{path}/*.js",
- f"{path}/*.mjs",
- f"{path}/*.sjs",
- ]
- for line in self.run(cmd):
- js = pathlib.Path(line)
- if is_excluded_from_imports(js):
- continue
- jss.append(js)
-
- return jss
-
-
-class Summary:
- def __init__(self):
- self.convert_errors = []
- self.import_errors = []
- self.rename_errors = []
- self.no_refs = []
-
-
-@Command(
- "esmify",
- category="misc",
- description="ESMify JSM files.",
-)
-@CommandArgument(
- "path",
- nargs=1,
- help="Path to the JSM file to ESMify, or the directory that contains "
- "JSM files and/or JS files that imports ESM-ified JSM.",
-)
-@CommandArgument(
- "--convert",
- action="store_true",
- help="Only perform the step 1 = convert part",
-)
-@CommandArgument(
- "--imports",
- action="store_true",
- help="Only perform the step 2 = import calls part",
-)
-@CommandArgument(
- "--prefix",
- default="",
- help="Restrict the target of import in the step 2 to ESM-ified JSM, by the "
- "prefix match for the JSM file's path. e.g. 'browser/'.",
-)
-def esmify(command_context, path=None, convert=False, imports=False, prefix=""):
- """
- This command does the following 2 steps:
- 1. Convert the JSM file specified by `path` to ESM file, or the JSM files
- inside the directory specified by `path` to ESM files, and also
- fix references in build files and test definitions
- 2. Convert import calls inside file(s) specified by `path` for ESM-ified
- files to use new APIs
-
- Example 1:
- # Convert all JSM files inside `browser/components/pagedata` directory,
- # and replace all references for ESM-ified files in the entire tree to use
- # new APIs
-
- $ ./mach esmify --convert browser/components/pagedata
- $ ./mach esmify --imports . --prefix=browser/components/pagedata
-
- Example 2:
- # Convert all JSM files inside `browser` directory, and replace all
- # references for the JSM files inside `browser` directory to use
- # new APIs
-
- $ ./mach esmify browser
- """
-
- def error(text):
- command_context.log(logging.ERROR, "esmify", {}, f"[ERROR] {text}")
-
- def warn(text):
- command_context.log(logging.WARN, "esmify", {}, f"[WARN] {text}")
-
- def info(text):
- command_context.log(logging.INFO, "esmify", {}, f"[INFO] {text}")
-
- # If no options is specified, perform both.
- if not convert and not imports:
- convert = True
- imports = True
-
- path = pathlib.Path(path[0])
-
- if not verify_path(command_context, path):
- return 1
-
- if HgUtils.is_available():
- vcs_utils = HgUtils()
- elif GitUtils.is_available():
- vcs_utils = GitUtils()
- else:
- error(
- "This script needs to be run inside mozilla-central "
- "checkout of either mercurial or git."
- )
- return 1
-
- load_exclusion_files()
-
- info("Setting up jscodeshift...")
- setup_jscodeshift()
-
- is_single_file = path.is_file()
-
- modified_files = []
- summary = Summary()
-
- if convert:
- info("Searching files to convert to ESM...")
- if is_single_file:
- jsms = [path]
- else:
- jsms = vcs_utils.find_jsms(path)
-
- info(f"Found {len(jsms)} file(s) to convert to ESM.")
-
- info("Converting to ESM...")
- jsms = convert_module(jsms, summary)
- if jsms is None:
- error("Failed to rewrite exports.")
- return 1
-
- info("Renaming...")
- esms = rename_jsms(command_context, vcs_utils, jsms, summary)
-
- modified_files += esms
-
- if imports:
- info("Searching files to rewrite imports...")
-
- if is_single_file:
- if convert:
- # Already converted above
- jss = esms
- else:
- jss = [path]
- else:
- jss = vcs_utils.find_all_jss(path)
-
- info(f"Checking {len(jss)} JS file(s). Rewriting any matching imports...")
-
- result = rewrite_imports(jss, prefix, summary)
- if result is None:
- return 1
-
- info(f"Rewritten {len(result)} file(s).")
-
- # Only modified files needs eslint fix
- modified_files += result
-
- modified_files = list(set(modified_files))
-
- info(f"Applying eslint --fix for {len(modified_files)} file(s)...")
- eslint_fix(command_context, modified_files)
-
- def print_files(f, errors):
- for [path, message] in errors:
- f(f" * {path}")
- if message:
- f(f" {message}")
-
- if len(summary.convert_errors):
- error("========")
- error("Following files are not converted into ESM due to error:")
- print_files(error, summary.convert_errors)
-
- if len(summary.import_errors):
- warn("========")
- warn("Following files are not rewritten to import ESMs due to error:")
- warn(
- "(NOTE: Errors related to 'private names' are mostly due to "
- " preprocessor macros in the file):"
- )
- print_files(warn, summary.import_errors)
-
- if len(summary.rename_errors):
- error("========")
- error("Following files are not renamed due to error:")
- print_files(error, summary.rename_errors)
-
- if len(summary.no_refs):
- warn("========")
- warn("Following files are not found in any build files.")
- warn("Please update references to those files manually:")
- print_files(warn, summary.rename_errors)
-
- return 0
-
-
-def verify_path(command_context, path):
- """Check if the path passed to the command is valid relative path."""
-
- def error(text):
- command_context.log(logging.ERROR, "esmify", {}, f"[ERROR] {text}")
-
- if not path.exists():
- error(f"{path} does not exist.")
- return False
-
- if path.is_absolute():
- error("Path must be a relative path from mozilla-central checkout.")
- return False
-
- return True
-
-
-def find_file(path, target):
- """Find `target` file in ancestor of path."""
- target_path = path.parent / target
- if not target_path.exists():
- if path.parent == path:
- return None
-
- return find_file(path.parent, target)
-
- return target_path
-
-
-def try_rename_in(command_context, path, target, jsm_name, esm_name, jsm_path):
- """Replace the occurrences of `jsm_name` with `esm_name` in `target`
- file."""
-
- def info(text):
- command_context.log(logging.INFO, "esmify", {}, f"[INFO] {text}")
-
- if type(target) is str:
- # Target is specified by filename, that may exist somewhere in
- # the jsm's directory or ancestor directories.
- target_path = find_file(path, target)
- if not target_path:
- return False
-
- # JSM should be specified with relative path in the file.
- #
- # Single moz.build or jar.mn can contain multiple files with same name.
- # Search for relative path.
- jsm_relative_path = jsm_path.relative_to(target_path.parent)
- jsm_path_str = path_sep_from_native(str(jsm_relative_path))
- else:
- # Target is specified by full path.
- target_path = target
-
- # JSM should be specified with full path in the file.
- jsm_path_str = path_sep_from_native(str(jsm_path))
-
- jsm_path_re = re.compile(r"\b" + jsm_path_str.replace(".", r"\.") + r"\b")
- jsm_name_re = re.compile(r"\b" + jsm_name.replace(".", r"\.") + r"\b")
-
- modified = False
- content = ""
- with open(target_path, "r") as f:
- for line in f:
- if jsm_path_re.search(line):
- modified = True
- line = jsm_name_re.sub(esm_name, line)
-
- content += line
-
- if modified:
- info(f" {str(target_path)}")
- info(f" {jsm_name} => {esm_name}")
- with open(target_path, "w", newline="\n") as f:
- f.write(content)
-
- return True
-
-
-def try_rename_uri_in(command_context, target, jsm_name, esm_name, jsm_uri, esm_uri):
- """Replace the occurrences of `jsm_uri` with `esm_uri` in `target` file."""
-
- def info(text):
- command_context.log(logging.INFO, "esmify", {}, f"[INFO] {text}")
-
- modified = False
- content = ""
- with open(target, "r") as f:
- for line in f:
- if jsm_uri in line:
- modified = True
- line = line.replace(jsm_uri, esm_uri)
-
- content += line
-
- if modified:
- info(f" {str(target)}")
- info(f" {jsm_name} => {esm_name}")
- with open(target, "w", newline="\n") as f:
- f.write(content)
-
- return True
-
-
-def try_rename_components_conf(command_context, path, jsm_name, esm_name):
- """Replace the occurrences of `jsm_name` with `esm_name` in components.conf
- file."""
-
- def info(text):
- command_context.log(logging.INFO, "esmify", {}, f"[INFO] {text}")
-
- target_path = find_file(path, "components.conf")
- if not target_path:
- return False
-
- # Unlike try_rename_in, components.conf contains the URL instead of
- # relative path, and also there are no known files with same name.
- # Simply replace the filename.
-
- with open(target_path, "r") as f:
- content = f.read()
-
- prop_re = re.compile(
- "[\"']jsm[\"']:(.*)" + r"\b" + jsm_name.replace(".", r"\.") + r"\b"
- )
-
- if not prop_re.search(content):
- return False
-
- info(f" {str(target_path)}")
- info(f" {jsm_name} => {esm_name}")
-
- content = prop_re.sub(r"'esModule':\1" + esm_name, content)
- with open(target_path, "w", newline="\n") as f:
- f.write(content)
-
- return True
-
-
-def esmify_name(name):
- return re.sub(r"\.(jsm|js|jsm\.js)$", ".sys.mjs", name)
-
-
-def esmify_path(jsm_path):
- jsm_name = jsm_path.name
- esm_name = re.sub(r"\.(jsm|js|jsm\.js)$", ".sys.mjs", jsm_name)
- esm_path = jsm_path.parent / esm_name
- return esm_path
-
-
-path_to_uri_map = None
-
-
-def load_path_to_uri_map():
- global path_to_uri_map
-
- if path_to_uri_map:
- return
-
- if "ESMIFY_MAP_JSON" in os.environ:
- json_map = pathlib.Path(os.environ["ESMIFY_MAP_JSON"])
- else:
- json_map = pathlib.Path(__file__).parent / "map.json"
-
- with open(json_map, "r") as f:
- uri_to_path_map = json.loads(f.read())
-
- path_to_uri_map = dict()
-
- for uri, paths in uri_to_path_map.items():
- if type(paths) is str:
- paths = [paths]
-
- for path in paths:
- path_to_uri_map[path] = uri
-
-
-def find_jsm_uri(jsm_path):
- load_path_to_uri_map()
-
- path = path_sep_from_native(jsm_path)
-
- if path in path_to_uri_map:
- return path_to_uri_map[path]
-
- return None
-
-
-def rename_single_file(command_context, vcs_utils, jsm_path, summary):
- """Rename `jsm_path` to .sys.mjs, and fix references to the file in build
- and test definitions."""
-
- def info(text):
- command_context.log(logging.INFO, "esmify", {}, f"[INFO] {text}")
-
- esm_path = esmify_path(jsm_path)
-
- jsm_name = jsm_path.name
- esm_name = esm_path.name
-
- target_files = [
- ".eslintignore",
- "moz.build",
- "jar.mn",
- "browser.toml",
- "browser-common.toml",
- "chrome.toml",
- "mochitest.toml",
- "xpcshell.toml",
- "xpcshell-child-process.toml",
- "xpcshell-common.toml",
- "xpcshell-parent-process.toml",
- pathlib.Path("tools", "lint", "eslint.yml"),
- pathlib.Path("tools", "lint", "rejected-words.yml"),
- ]
-
- info(f"{jsm_path} => {esm_path}")
-
- renamed = False
- for target in target_files:
- if try_rename_in(
- command_context, jsm_path, target, jsm_name, esm_name, jsm_path
- ):
- renamed = True
-
- if try_rename_components_conf(command_context, jsm_path, jsm_name, esm_name):
- renamed = True
-
- uri_target_files = [
- pathlib.Path(
- "browser", "base", "content", "test", "performance", "browser_startup.js"
- ),
- pathlib.Path(
- "browser",
- "base",
- "content",
- "test",
- "performance",
- "browser_startup_content.js",
- ),
- pathlib.Path(
- "browser",
- "base",
- "content",
- "test",
- "performance",
- "browser_startup_content_subframe.js",
- ),
- pathlib.Path(
- "toolkit",
- "components",
- "backgroundtasks",
- "tests",
- "browser",
- "browser_xpcom_graph_wait.js",
- ),
- ]
-
- jsm_uri = find_jsm_uri(jsm_path)
- if jsm_uri:
- esm_uri = re.sub(r"\.(jsm|js|jsm\.js)$", ".sys.mjs", jsm_uri)
-
- for target in uri_target_files:
- if try_rename_uri_in(
- command_context, target, jsm_uri, esm_uri, jsm_name, esm_name
- ):
- renamed = True
-
- if not renamed:
- summary.no_refs.append([jsm_path, None])
-
- if not esm_path.exists():
- vcs_utils.rename(jsm_path, esm_path)
- else:
- summary.rename_errors.append([jsm_path, f"{esm_path} already exists"])
-
- return esm_path
-
-
-def rename_jsms(command_context, vcs_utils, jsms, summary):
- esms = []
- for jsm in jsms:
- esm = rename_single_file(command_context, vcs_utils, jsm, summary)
- esms.append(esm)
-
- return esms
-
-
-npm_prefix = pathlib.Path("tools") / "esmify"
-path_from_npm_prefix = pathlib.Path("..") / ".."
-
-
-def setup_jscodeshift():
- """Install jscodeshift."""
- cmd = [
- sys.executable,
- "./mach",
- "npm",
- "install",
- "jscodeshift",
- "--save-dev",
- "--prefix",
- str(npm_prefix),
- ]
- subprocess.run(cmd, check=True)
-
-
-def run_npm_command(args, env, stdin):
- cmd = [
- sys.executable,
- "./mach",
- "npm",
- "run",
- ] + args
- p = subprocess.Popen(cmd, env=env, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
- p.stdin.write(stdin)
- p.stdin.close()
-
- ok_files = []
- errors = []
- while True:
- line = p.stdout.readline()
- if not line:
- break
- line = line.rstrip().decode()
-
- if line.startswith(" NOC "):
- continue
-
- print(line)
-
- m = re.search(r"^ (OKK|ERR) ([^ ]+)(?: (.+))?", line)
- if not m:
- continue
-
- result = m.group(1)
- # NOTE: path is written from `tools/esmify`.
- path = pathlib.Path(m.group(2)).relative_to(path_from_npm_prefix)
- error = m.group(3)
-
- if result == "OKK":
- ok_files.append(path)
-
- if result == "ERR":
- errors.append([path, error])
-
- if p.wait() != 0:
- return [None, None]
-
- return ok_files, errors
-
-
-def convert_module(jsms, summary):
- """Replace EXPORTED_SYMBOLS with export declarations, and replace
- ChromeUtils.importESModule with static import as much as possible,
- and return the list of successfully rewritten files."""
-
- if len(jsms) == 0:
- return []
-
- env = os.environ.copy()
-
- stdin = "\n".join(map(str, paths_from_npm_prefix(jsms))).encode()
-
- ok_files, errors = run_npm_command(
- [
- "convert_module",
- "--prefix",
- str(npm_prefix),
- ],
- env=env,
- stdin=stdin,
- )
-
- if ok_files is None and errors is None:
- return None
-
- summary.convert_errors.extend(errors)
-
- return ok_files
-
-
-def rewrite_imports(jss, prefix, summary):
- """Replace import calls for JSM with import calls for ESM or static import
- for ESM."""
-
- if len(jss) == 0:
- return []
-
- env = os.environ.copy()
- env["ESMIFY_TARGET_PREFIX"] = prefix
-
- stdin = "\n".join(map(str, paths_from_npm_prefix(jss))).encode()
-
- ok_files, errors = run_npm_command(
- [
- "rewrite_imports",
- "--prefix",
- str(npm_prefix),
- ],
- env=env,
- stdin=stdin,
- )
-
- if ok_files is None and errors is None:
- return None
-
- summary.import_errors.extend(errors)
-
- return ok_files
-
-
-def paths_from_npm_prefix(paths):
- """Convert relative path from mozilla-central to relative path from
- tools/esmify."""
- return list(map(lambda path: path_from_npm_prefix / path, paths))
-
-
-def eslint_fix(command_context, files):
- """Auto format files."""
-
- def info(text):
- command_context.log(logging.INFO, "esmify", {}, f"[INFO] {text}")
-
- if len(files) == 0:
- return
-
- remaining = files[0:]
-
- # There can be too many files for single command line, perform by chunk.
- max_files = 16
- while len(remaining) > max_files:
- info(f"{len(remaining)} files remaining")
-
- chunk = remaining[0:max_files]
- remaining = remaining[max_files:]
-
- cmd = [sys.executable, "./mach", "eslint", "--fix"] + chunk
- subprocess.run(cmd, check=True)
-
- info(f"{len(remaining)} files remaining")
- chunk = remaining
- cmd = [sys.executable, "./mach", "eslint", "--fix"] + chunk
- subprocess.run(cmd, check=True)