diff options
Diffstat (limited to '')
-rw-r--r-- | devtools/shared/webconsole/GenerateDataFromWebIdls.py | 176 |
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") |