aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/bindings/codegen/GlobalGen.py
diff options
context:
space:
mode:
authorSimon Sapin <simon.sapin@exyr.org>2019-09-27 06:37:54 +0200
committerSimon Sapin <simon.sapin@exyr.org>2019-09-27 13:53:19 +0200
commit5c60023cb8ad6f07927bd53f30c90873d07b300f (patch)
tree9ea739dbeb622a918b7636558f7ed81ff6f4bb49 /components/script/dom/bindings/codegen/GlobalGen.py
parent049527872e6dfadf3f69f0f9fa6fffee520a6f7b (diff)
downloadservo-5c60023cb8ad6f07927bd53f30c90873d07b300f.tar.gz
servo-5c60023cb8ad6f07927bd53f30c90873d07b300f.zip
WebIDL codegen: Replace cmake with a single Python script
When playing around with Cargo’s new timing visualization: https://internals.rust-lang.org/t/exploring-crate-graph-build-times-with-cargo-build-ztimings/10975/21 … I was surprised to see the `script` crate’s build script take 76 seconds. I did not expect WebIDL bindings generation to be *that* computationally intensive. It turns out almost all of this time is overhead. The build script uses CMake to generate bindings for each WebIDL file in parallel, but that causes a lot of work to be repeated 366 times: * Starting up a Python VM * Importing (parts of) the Python standard library * Importing ~16k lines of our Python code * Recompiling the latter to bytecode, since we used `python -B` to disable writing `.pyc` file * Deserializing with `cPickle` and recreating in memory the results of parsing all WebIDL files ---- This commit remove the use of CMake and cPickle for the `script` crate. Instead, all WebIDL bindings generation is done sequentially in a single Python process. This takes 2 to 3 seconds.
Diffstat (limited to 'components/script/dom/bindings/codegen/GlobalGen.py')
-rw-r--r--components/script/dom/bindings/codegen/GlobalGen.py143
1 files changed, 0 insertions, 143 deletions
diff --git a/components/script/dom/bindings/codegen/GlobalGen.py b/components/script/dom/bindings/codegen/GlobalGen.py
deleted file mode 100644
index 1850a41d5f3..00000000000
--- a/components/script/dom/bindings/codegen/GlobalGen.py
+++ /dev/null
@@ -1,143 +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 https://mozilla.org/MPL/2.0/.
-
-# We do one global pass over all the WebIDL to generate our prototype enum
-# and generate information for subsequent phases.
-
-import sys
-import os
-import json
-sys.path.append(os.path.join(".", "parser"))
-sys.path.append(os.path.join(".", "ply"))
-import WebIDL
-import cPickle
-from Configuration import Configuration
-from CodegenRust import GlobalGenRoots, replaceFileIfChanged
-
-
-def generate_file(config, name, filename):
- root = getattr(GlobalGenRoots, name)(config)
- code = root.define()
-
- if replaceFileIfChanged(filename, code):
- print "Generating %s" % (filename)
- else:
- print "%s hasn't changed - not touching it" % (filename)
-
-
-def main():
- # Parse arguments.
- from optparse import OptionParser
- usageString = "usage: %prog [options] configFile outputdir webidldir cssProperties.json docServoDir [files]"
- o = OptionParser(usage=usageString)
- o.add_option("--cachedir", dest='cachedir', default=None,
- help="Directory in which to cache lex/parse tables.")
- o.add_option("--filelist", dest='filelist', default=None,
- help="A file containing the list (one per line) of webidl files to process.")
- (options, args) = o.parse_args()
-
- if len(args) < 2:
- o.error(usageString)
-
- configFile = args[0]
- outputdir = args[1]
- baseDir = args[2]
- css_properties_json = args[3]
- doc_servo = args[4]
- if options.filelist is not None:
- fileList = [l.strip() for l in open(options.filelist).xreadlines()]
- else:
- fileList = args[3:]
-
- # Parse the WebIDL.
- parser = WebIDL.Parser(options.cachedir)
- for filename in fileList:
- fullPath = os.path.normpath(os.path.join(baseDir, filename))
- with open(fullPath, 'rb') as f:
- lines = f.readlines()
- parser.parse(''.join(lines), fullPath)
-
- add_css_properties_attributes(fileList, css_properties_json, parser)
-
- parserResults = parser.finish()
-
- # Write the parser results out to a pickle.
- resultsPath = os.path.join(outputdir, 'ParserResults.pkl')
- with open(resultsPath, 'wb') as resultsFile:
- cPickle.dump(parserResults, resultsFile, -1)
-
- # Load the configuration.
- config = Configuration(configFile, parserResults)
-
- to_generate = [
- ('PrototypeList', 'PrototypeList.rs'),
- ('RegisterBindings', 'RegisterBindings.rs'),
- ('InterfaceObjectMap', 'InterfaceObjectMap.rs'),
- ('InterfaceObjectMapData', 'InterfaceObjectMapData.json'),
- ('InterfaceTypes', 'InterfaceTypes.rs'),
- ('InheritTypes', 'InheritTypes.rs'),
- ('Bindings', os.path.join('Bindings', 'mod.rs')),
- ('UnionTypes', 'UnionTypes.rs'),
- ]
-
- for name, filename in to_generate:
- generate_file(config, name, os.path.join(outputdir, filename))
-
- generate_file(config, 'SupportedDomApis', os.path.join(doc_servo, 'apis.html'))
-
-
-def add_css_properties_attributes(webidl_files, css_properties_json, parser):
- for filename in webidl_files:
- if os.path.basename(filename) == "CSSStyleDeclaration.webidl":
- break
- else:
- return
-
- css_properties = json.load(open(css_properties_json, "rb"))
- idl = "partial interface CSSStyleDeclaration {\n%s\n};\n" % "\n".join(
- " [%sCEReactions, SetterThrows] attribute [TreatNullAs=EmptyString] DOMString %s;" % (
- ('Pref="%s", ' % data["pref"] if data["pref"] else ""),
- attribute_name
- )
- for (kind, properties_list) in sorted(css_properties.items())
- for (property_name, data) in sorted(properties_list.items())
- for attribute_name in attribute_names(property_name)
- )
- parser.parse(idl.encode("utf-8"), "CSSStyleDeclaration_generated.webidl")
-
-
-def attribute_names(property_name):
- # https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-dashed-attribute
- if property_name != "float":
- yield property_name
- else:
- yield "_float"
-
- # https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-camel-cased-attribute
- if "-" in property_name:
- yield "".join(camel_case(property_name))
-
- # https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-webkit-cased-attribute
- if property_name.startswith("-webkit-"):
- yield "".join(camel_case(property_name), True)
-
-
-# https://drafts.csswg.org/cssom/#css-property-to-idl-attribute
-def camel_case(chars, webkit_prefixed=False):
- if webkit_prefixed:
- chars = chars[1:]
- next_is_uppercase = False
- for c in chars:
- if c == '-':
- next_is_uppercase = True
- elif next_is_uppercase:
- next_is_uppercase = False
- # Should be ASCII-uppercase, but all non-custom CSS property names are within ASCII
- yield c.upper()
- else:
- yield c
-
-
-if __name__ == '__main__':
- main()