mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 15:23:51 +00:00
Bug 1454591 part 1 - Generate more structured data in ServoCSSPropList.py. r=heycam
This patch changes ServoCSSPropList.py to use classes for properties. This allows extending the data in the file without needing to update all users of this file. Sorting in GenerateCSSPropsGenerated.py is removed because the data file has the right order already. MozReview-Commit-ID: D74bItCfpPH --HG-- extra : rebase_source : e0138c255f77515f491496fcb8680686362f4e9e
This commit is contained in:
parent
3b95cfc89e
commit
7db648bdec
@ -10,6 +10,7 @@ This information is used to generate the properties-db.js file.
|
||||
|
||||
import json
|
||||
import os
|
||||
import runpy
|
||||
import sys
|
||||
import string
|
||||
import subprocess
|
||||
@ -53,15 +54,12 @@ class MachCommands(MachCommandBase):
|
||||
# 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
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
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
|
||||
@ -13,18 +14,19 @@ 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).
|
||||
@ -52,8 +54,8 @@ def generate(output, idlFilename, dataFile):
|
||||
# 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)
|
||||
|
||||
|
@ -2,30 +2,30 @@
|
||||
# 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({
|
||||
|
@ -2,75 +2,66 @@
|
||||
# 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)]
|
||||
class PropertyWrapper(object):
|
||||
__slots__ = ["index", "prop", "idlname"]
|
||||
|
||||
# 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.
|
||||
|
||||
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
|
||||
|
||||
return properties
|
||||
def __getattr__(self, name):
|
||||
return getattr(self.prop, name)
|
||||
|
||||
|
||||
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))
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
import buildconfig
|
||||
import mozpack.path as mozpath
|
||||
import os
|
||||
import runpy
|
||||
import subprocess
|
||||
import string
|
||||
import sys
|
||||
@ -32,8 +33,7 @@ def generate_data(output, template):
|
||||
|
||||
|
||||
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 */
|
||||
|
||||
@ -68,28 +68,29 @@ def generate_header(output, data):
|
||||
"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:
|
||||
|
@ -2,6 +2,43 @@
|
||||
# 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
|
||||
@ -27,6 +64,13 @@ def is_internal(prop):
|
||||
]
|
||||
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():
|
||||
@ -49,43 +93,16 @@ def pref(prop):
|
||||
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
|
||||
]
|
||||
|
Loading…
Reference in New Issue
Block a user