176 lines
5.5 KiB
Python
176 lines
5.5 KiB
Python
"""
|
|
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")
|