--- a/devtools/shared/css/generated/mach_commands.py
+++ b/devtools/shared/css/generated/mach_commands.py
@@ -5,16 +5,17 @@
"""
This script implements the `mach devtools-css-db` command. It runs an xpcshell
script that uses InspectorUtils to query the CSS properties used by the browser.
This information is used to generate the properties-db.js file.
"""
import json
import os
+import runpy
import sys
import string
import subprocess
from mozbuild import shellutil
from mozbuild.base import (
MozbuildObject,
MachCommandBase,
)
@@ -48,25 +49,22 @@ class MachCommands(MachCommandBase):
'cssProperties': stringify(db['cssProperties']),
'pseudoElements': stringify(db['pseudoElements'])})
def get_preferences(self):
"""Get all of the preferences associated with enabling and disabling a property."""
# The data takes the following form:
# [ (name, prop, id, flags, pref, proptype), ... ]
dataPath = resolve_path(self.topobjdir, 'layout/style/ServoCSSPropList.py')
- with open(dataPath, "r") as f:
- data = eval(f.read())
+ data = runpy.run_path(dataPath)['data']
# Map this list
- # (name, prop, id, flags, pref, proptype) => (name, pref)
preferences = [
- (name, pref)
- for name, prop, id, flags, pref, proptype in data
- if 'CSSPropFlags::Internal' not in flags and pref]
+ (p.name, p.pref) for p in data
+ if 'CSSPropFlags::Internal' not in p.flags and p.pref]
return preferences
def get_properties_db_from_xpcshell(self):
"""Generate the static css properties db for devtools from an xpcshell script."""
build = MozbuildObject.from_environment()
# Get the paths
--- a/dom/bindings/GenerateCSS2PropertiesWebIDL.py
+++ b/dom/bindings/GenerateCSS2PropertiesWebIDL.py
@@ -1,35 +1,37 @@
# 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 sys
import string
import argparse
+import runpy
# Generates a line of WebIDL with the given spelling of the property name
# (whether camelCase, _underscorePrefixed, etc.) and the given array of
# extended attributes.
def generateLine(propName, extendedAttrs):
return " [%s] attribute DOMString %s;\n" % (", ".join(extendedAttrs),
propName)
def generate(output, idlFilename, dataFile):
- with open(dataFile, "r") as f:
- propList = eval(f.read())
+ propList = runpy.run_path(dataFile)["data"]
props = ""
- for name, prop, id, flags, pref, proptype in propList:
- if "CSSPropFlags::Internal" in flags:
+ for p in propList:
+ if "CSSPropFlags::Internal" in p.flags:
continue
# Unfortunately, even some of the getters here are fallible
# (e.g. on nsComputedDOMStyle).
extendedAttrs = ["CEReactions", "Throws", "TreatNullAs=EmptyString",
"SetterNeedsSubjectPrincipal=NonSystem"]
- if pref is not "":
- extendedAttrs.append('Pref="%s"' % pref)
+ if p.pref is not "":
+ extendedAttrs.append('Pref="%s"' % p.pref)
+
+ prop = p.method
# webkit properties get a camelcase "webkitFoo" accessor
# as well as a capitalized "WebkitFoo" alias (added here).
if (prop.startswith("Webkit")):
extendedAttrs.append('BindingAlias="%s"' % prop)
# Generate a name with camelCase spelling of property-name (or capitalized,
# for Moz-prefixed properties):
@@ -47,18 +49,18 @@ def generate(output, idlFilename, dataFi
# Note that "float" will cause a property called "float" to exist due to (1)
# in that list.
#
# In practice, cssFloat is the only case in which "name" doesn't contain
# "-" but also doesn't match "prop". So the generateLine() call will
# cover (3) and all of (1) except "float". If we now add an alias
# for all the cases where "name" doesn't match "prop", that will cover
# "float" and (2).
- if prop != name:
- extendedAttrs.append('BindingAlias="%s"' % name)
+ if prop != p.name:
+ extendedAttrs.append('BindingAlias="%s"' % p.name)
props += generateLine(prop, extendedAttrs)
idlFile = open(idlFilename, "r")
idlTemplate = idlFile.read()
idlFile.close()
--- a/layout/style/GenerateCSSPropertyID.py
+++ b/layout/style/GenerateCSSPropertyID.py
@@ -1,35 +1,35 @@
# 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 runpy
import string
def generate(output, template, dataFile):
with open(template, "r") as f:
template = string.Template(f.read())
- with open(dataFile, "r") as f:
- data = eval(f.read())
+ data = runpy.run_path(dataFile)["data"]
longhand_count = 0
shorthand_count = 0
alias_count = 0
property_ids = []
- for name, method, id, flags, pref, prototype in data:
- if prototype != "alias":
- if prototype == "longhand":
+ for prop in data:
+ if prop.type() != "alias":
+ if prop.type() == "longhand":
assert shorthand_count == 0
longhand_count += 1
else:
assert alias_count == 0
shorthand_count += 1
- property_ids.append("eCSSProperty_{}".format(id))
+ property_ids.append("eCSSProperty_{}".format(prop.id))
else:
alias_count += 1
- property_ids.append("eCSSPropertyAlias_{}".format(id[0]))
+ property_ids.append("eCSSPropertyAlias_{}".format(prop.alias_id))
output.write("/* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT */\n\n")
output.write(template.substitute({
"property_ids": "\n".join(" {},".format(p) for p in property_ids),
"longhand_count": property_ids[longhand_count],
"shorthand_count": property_ids[longhand_count + shorthand_count],
}))
--- a/layout/style/GenerateCSSPropsGenerated.py
+++ b/layout/style/GenerateCSSPropsGenerated.py
@@ -1,81 +1,72 @@
# 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 runpy
import sys
import string
import argparse
-def get_properties(dataFile):
- with open(dataFile, "r") as f:
- properties = eval(f.read())
- properties = [{"name":p[0], "prop":p[1], "id":p[2],
- "flags":p[3], "pref":p[4], "proptype":p[5]}
- for (i, p) in enumerate(properties)]
-
- # Sort the list so that longhand properties are intermingled first,
- # shorthand properties follow, then aliases appear last.
- # This matches the order of the nsCSSPropertyID enum.
+class PropertyWrapper(object):
+ __slots__ = ["index", "prop", "idlname"]
- def property_compare(x, y):
- property_order = {"longhand": 0, "shorthand": 1, "alias": 2}
- return property_order[x["proptype"]] - property_order[y["proptype"]]
-
- properties = sorted(properties, cmp=property_compare)
-
- for i, p in enumerate(properties):
- p["index"] = i
-
- # Record each property's IDL name.
- for p in properties:
- if "CSSPropFlags::Internal" in p["flags"]:
- p["idlname"] = None
+ def __init__(self, index, prop):
+ self.index = index
+ self.prop = prop
+ if "CSSPropFlags::Internal" in prop.flags:
+ self.idlname = None
else:
- idl_name = p["prop"]
+ idl_name = prop.method
if not idl_name.startswith("Moz"):
idl_name = idl_name[0].lower() + idl_name[1:]
- p["idlname"] = idl_name
+ self.idlname = idl_name
+
+ def __getattr__(self, name):
+ return getattr(self.prop, name)
- return properties
+
+def get_properties(dataFile):
+ properties = runpy.run_path(dataFile)["data"]
+ return [PropertyWrapper(i, p) for i, p in enumerate(properties)]
def generate_idl_names(properties):
names = []
for p in properties:
- if p["proptype"] is "alias":
+ if p.type() == "alias":
continue
- if p["idlname"] is None:
- names.append(" nullptr, // %s" % p["name"])
+ if p.idlname is None:
+ names.append(" nullptr, // %s" % p.name)
else:
- names.append(' "%s",' % p["idlname"])
+ names.append(' "%s",' % p.idlname)
return "\n".join(names)
def generate_assertions(properties):
def enum(p):
- if p["proptype"] is "alias":
- return "eCSSPropertyAlias_%s" % p["id"][0]
+ if p.type() == "alias":
+ return "eCSSPropertyAlias_%s" % p.alias_id
else:
- return "eCSSProperty_%s" % p["id"]
+ return "eCSSProperty_%s" % p.id
msg = ('static_assert(%s == %d, "GenerateCSSPropsGenerated.py did not list '
'properties in nsCSSPropertyID order");')
- return "\n".join(map(lambda p: msg % (enum(p), p["index"]), properties))
+ return "\n".join(map(lambda p: msg % (enum(p), p.index), properties))
def generate_idl_name_positions(properties):
# Skip aliases.
- ps = filter(lambda p: p["proptype"] is not "alias", properties)
+ ps = filter(lambda p: p.type() != "alias", properties)
# Sort alphabetically by IDL name.
- ps = sorted(ps, key=lambda p: p["idlname"])
+ ps = sorted(ps, key=lambda p: p.idlname)
# Annotate entries with the sorted position.
ps = [(p, position) for position, p in enumerate(ps)]
# Sort back to nsCSSPropertyID order.
- ps = sorted(ps, key=lambda (p, position): p["index"])
+ ps = sorted(ps, key=lambda (p, position): p.index)
return ",\n".join(map(lambda (p, position): " %d" % position, ps))
def generate(output, cppTemplate, dataFile):
cppFile = open(cppTemplate, "r")
cppTemplate = cppFile.read()
cppFile.close()
--- a/layout/style/GenerateServoCSSPropList.py
+++ b/layout/style/GenerateServoCSSPropList.py
@@ -1,15 +1,16 @@
# 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 buildconfig
import mozpack.path as mozpath
import os
+import runpy
import subprocess
import string
import sys
SERVO_BASE = mozpath.join(buildconfig.topsrcdir, "servo")
SERVO_PROP_BASE = mozpath.join(SERVO_BASE, "components", "style", "properties")
@@ -27,18 +28,17 @@ def generate_data(output, template):
for path, dirs, files in os.walk(SERVO_PROP_BASE):
for file in files:
if os.path.splitext(file)[1] in DEP_EXTS:
deps.add(mozpath.join(path, file))
return deps
def generate_header(output, data):
- with open(data, "r") as f:
- data = eval(f.read())
+ data = runpy.run_path(data)["data"]
output.write("""/* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT */
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
@@ -63,38 +63,39 @@ def generate_header(output, data):
""")
MACRO_NAMES = {
"longhand": "CSS_PROP_LONGHAND",
"shorthand": "CSS_PROP_SHORTHAND",
"alias": "CSS_PROP_ALIAS",
}
- for name, method, id, flags, pref, proptype in data:
- is_internal = "CSSPropFlags::Internal" in flags
- pref = '"' + pref + '"'
- if proptype == "alias":
- params = [name, id[0], id[1], method, pref]
+ for prop in data:
+ is_internal = "CSSPropFlags::Internal" in prop.flags
+ pref = '"' + prop.pref + '"'
+ if prop.type() == "alias":
+ params = [prop.name, prop.alias_id, prop.prop_id, prop.method, pref]
else:
+ method = prop.method
if method == "CssFloat":
method = "CSS_PROP_PUBLIC_OR_PRIVATE(CssFloat, Float)"
elif method.startswith("Moz"):
method = "CSS_PROP_DOMPROP_PREFIXED({})".format(method[3:])
- if flags:
- flags = " | ".join(flags)
+ if prop.flags:
+ flags = " | ".join(prop.flags)
else:
flags = "CSSPropFlags(0)"
- params = [name, id, method, flags, pref]
+ params = [prop.name, prop.id, method, flags, pref]
- is_component_of_all = not is_internal and name not in ["direction", "unicode-bidi"]
+ is_component_of_all = not is_internal and prop.name not in ["direction", "unicode-bidi"]
if not is_component_of_all:
output.write("#ifndef CSS_PROP_LIST_ONLY_COMPONENTS_OF_ALL_SHORTHAND\n")
if is_internal:
output.write("#ifndef CSS_PROP_LIST_EXCLUDE_INTERNAL\n")
- output.write("{}({})\n".format(MACRO_NAMES[proptype], ", ".join(params)))
+ output.write("{}({})\n".format(MACRO_NAMES[prop.type()], ", ".join(params)))
if is_internal:
output.write("#endif\n")
if not is_component_of_all:
output.write("#endif\n")
output.write("""
#ifdef DEFINED_CSS_PROP_ALIAS
#undef CSS_PROP_ALIAS
--- a/layout/style/ServoCSSPropList.mako.py
+++ b/layout/style/ServoCSSPropList.mako.py
@@ -1,12 +1,49 @@
# 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/.
+def _assign_slots(obj, args):
+ for i, attr in enumerate(obj.__slots__):
+ setattr(obj, attr, args[i])
+
+
+class Longhand(object):
+ __slots__ = ["name", "method", "id", "flags", "pref"]
+
+ def __init__(self, *args):
+ _assign_slots(self, args)
+
+ @staticmethod
+ def type():
+ return "longhand"
+
+
+class Shorthand(object):
+ __slots__ = ["name", "method", "id", "flags", "pref"]
+
+ def __init__(self, *args):
+ _assign_slots(self, args)
+
+ @staticmethod
+ def type():
+ return "shorthand"
+
+
+class Alias(object):
+ __slots__ = ["name", "method", "alias_id", "prop_id", "flags", "pref"]
+
+ def __init__(self, *args):
+ _assign_slots(self, args)
+
+ @staticmethod
+ def type():
+ return "alias"
+
<%!
# nsCSSPropertyID of longhands and shorthands is ordered alphabetically
# with vendor prefixes removed. Note that aliases use their alias name
# as order key directly because they may be duplicate without prefix.
def order_key(prop):
if prop.name.startswith("-"):
return prop.name[prop.name.find("-", 1) + 1:]
return prop.name
@@ -22,16 +59,23 @@ def is_internal(prop):
"-moz-context-properties",
"-moz-control-character-visibility",
"-moz-window-opacity",
"-moz-window-transform",
"-moz-window-transform-origin",
]
return prop.name in OTHER_INTERNALS
+def method(prop):
+ if prop.name == "float":
+ return "CssFloat"
+ if prop.name.startswith("-x-"):
+ return prop.camel_case[1:]
+ return prop.camel_case
+
def flags(prop):
result = []
if prop.explicitly_enabled_in_chrome():
result.append("EnabledInUASheetsAndChrome")
elif prop.explicitly_enabled_in_ua_sheets():
result.append("EnabledInUASheets")
if is_internal(prop):
result.append("Internal")
@@ -44,48 +88,21 @@ def flags(prop):
return ", ".join('"CSSPropFlags::{}"'.format(flag) for flag in result)
def pref(prop):
if prop.gecko_pref:
return '"' + prop.gecko_pref + '"'
return '""'
%>
-[
+data = [
% for prop in sorted(data.longhands, key=order_key):
- (
- "${prop.name}",
- % if prop.name == "float":
- "CssFloat",
- % elif prop.name.startswith("-x-"):
- "${prop.camel_case[1:]}",
- % else:
- "${prop.camel_case}",
- % endif
- "${prop.ident}",
- [${flags(prop)}],
- ${pref(prop)},
- "longhand",
- ),
+ Longhand("${prop.name}", "${method(prop)}", "${prop.ident}", [${flags(prop)}], ${pref(prop)}),
% endfor
% for prop in sorted(data.shorthands, key=order_key):
- (
- "${prop.name}",
- "${prop.camel_case}",
- "${prop.ident}",
- [${flags(prop)}],
- ${pref(prop)},
- "shorthand",
- ),
+ Shorthand("${prop.name}", "${prop.camel_case}", "${prop.ident}", [${flags(prop)}], ${pref(prop)}),
% endfor
% for prop in sorted(data.all_aliases(), key=lambda x: x.name):
- (
- "${prop.name}",
- "${prop.camel_case}",
- ("${prop.ident}", "${prop.original.ident}"),
- [],
- ${pref(prop)},
- "alias",
- ),
+ Alias("${prop.name}", "${prop.camel_case}", "${prop.ident}", "${prop.original.ident}", [], ${pref(prop)}),
% endfor
]