summaryrefslogtreecommitdiffstats
path: root/devtools/shared/webconsole/GenerateDataFromWebIdls.py
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/shared/webconsole/GenerateDataFromWebIdls.py')
-rw-r--r--devtools/shared/webconsole/GenerateDataFromWebIdls.py176
1 files changed, 176 insertions, 0 deletions
diff --git a/devtools/shared/webconsole/GenerateDataFromWebIdls.py b/devtools/shared/webconsole/GenerateDataFromWebIdls.py
new file mode 100644
index 0000000000..467f30faa8
--- /dev/null
+++ b/devtools/shared/webconsole/GenerateDataFromWebIdls.py
@@ -0,0 +1,176 @@
+"""
+This script parses mozilla-central's WebIDL bindings and writes a JSON-formatted
+subset of the function bindings to several files:
+- "devtools/server/actors/webconsole/webidl-pure-allowlist.js" (for eager evaluation processing)
+- "devtools/server/actors/webconsole/webidl-unsafe-getters-names.js" (for preventing automatically call getters that could emit warnings)
+
+Run this script via
+
+> ./mach python devtools/shared/webconsole/GenerateDataFromWebIdls.py
+
+with a mozconfig that references a built non-artifact build.
+"""
+
+from os import path, remove, system
+import json
+import WebIDL
+import buildconfig
+
+# This is an explicit list of interfaces to load [Pure] and [Constant]
+# annotation for. There are a bunch of things that are pure in other interfaces
+# that we don't care about in the context of the devtools.
+PURE_INTERFACE_ALLOWLIST = set(
+ [
+ "Document",
+ "Node",
+ "DOMTokenList",
+ "Element",
+ "Performance",
+ "URLSearchParams",
+ "FormData",
+ "Headers",
+ ]
+)
+
+# This is an explicit list of interfaces to exclude.
+DEPRECATED_INTERFACE__EXCLUDE_LIST = set(
+ [
+ "External",
+ "TestExampleInterface",
+ "TestInterface",
+ "TestJSImplInterface",
+ "TestingDeprecatedInterface",
+ ]
+)
+
+FILE_TEMPLATE = """\
+/* 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/. */
+
+// This file is automatically generated by the GenerateDataFromWebIdls.py
+// script. Do not modify it manually.
+"use strict";
+
+module.exports = %(data)s;
+"""
+
+pure_output_file = path.join(
+ buildconfig.topsrcdir, "devtools/server/actors/webconsole/webidl-pure-allowlist.js"
+)
+unsafe_getters_names_file = path.join(
+ buildconfig.topsrcdir,
+ "devtools/server/actors/webconsole/webidl-unsafe-getters-names.js",
+)
+
+input_file = path.join(buildconfig.topobjdir, "dom/bindings/file-lists.json")
+
+if not path.isfile(input_file):
+ raise Exception(
+ "Script must be run with a mozconfig referencing a non-artifact OBJDIR"
+ )
+
+file_list = json.load(open(input_file))
+
+parser = WebIDL.Parser()
+for filepath in file_list["webidls"]:
+ with open(filepath, "r", encoding="utf8") as f:
+ parser.parse(f.read(), filepath)
+results = parser.finish()
+
+# TODO: Bug 1616013 - Move more of these to be part of the pure list.
+pure_output = {
+ "Document": {
+ "prototype": [
+ "getSelection",
+ "hasStorageAccess",
+ ],
+ },
+ "Range": {
+ "prototype": [
+ "isPointInRange",
+ "comparePoint",
+ "intersectsNode",
+ # These two functions aren't pure because they do trigger
+ # layout when they are called, but in the context of eager
+ # evaluation, that should be a totally fine thing to do.
+ "getClientRects",
+ "getBoundingClientRect",
+ ],
+ },
+ "Selection": {
+ "prototype": ["getRangeAt", "containsNode"],
+ },
+}
+unsafe_getters_names = []
+for result in results:
+ if isinstance(result, WebIDL.IDLInterface):
+ iface = result.identifier.name
+
+ is_global = result.getExtendedAttribute("Global")
+
+ for member in result.members:
+ name = member.identifier.name
+
+ if member.isMethod() and member.affects == "Nothing":
+ if (
+ PURE_INTERFACE_ALLOWLIST and not iface in PURE_INTERFACE_ALLOWLIST
+ ) or name.startswith("_"):
+ continue
+
+ if is_global:
+ raise Exception(
+ "Global methods and accessors are not supported: " + iface
+ )
+
+ if iface not in pure_output:
+ pure_output[iface] = {}
+
+ if member.isStatic():
+ owner_type = "static"
+ else:
+ owner_type = "prototype"
+
+ if owner_type not in pure_output[iface]:
+ pure_output[iface][owner_type] = []
+
+ # All DOM getters are considered eagerly-evaluate-able.
+ # Collect methods only.
+ #
+ # NOTE: We still need to calculate unsafe_getters_names for
+ # object preview.
+ if member.isMethod():
+ pure_output[iface][owner_type].append(name)
+
+ if (
+ not iface in DEPRECATED_INTERFACE__EXCLUDE_LIST
+ and not name in unsafe_getters_names
+ and member.isAttr()
+ and (
+ member.getExtendedAttribute("Deprecated")
+ or member.getExtendedAttribute("LegacyLenientThis")
+ )
+ ):
+ unsafe_getters_names.append(name)
+
+
+with open(pure_output_file, "w") as f:
+ f.write(FILE_TEMPLATE % {"data": json.dumps(pure_output, indent=2, sort_keys=True)})
+print("Successfully generated", pure_output_file)
+
+unsafe_getters_names.sort()
+with open(unsafe_getters_names_file, "w") as f:
+ f.write(
+ FILE_TEMPLATE
+ % {"data": json.dumps(unsafe_getters_names, indent=2, sort_keys=True)}
+ )
+print("Successfully generated", unsafe_getters_names_file)
+
+print("Formatting files...")
+system("./mach eslint --fix " + pure_output_file + " " + unsafe_getters_names_file)
+print("Files are now properly formatted")
+
+# Parsing the idls generate a parser.out file that we don't have any use of.
+if path.exists("parser.out"):
+ remove("parser.out")
+print("DONE")