Skip to content

Commit 35b93ce

Browse files
committed
Bug 1297480 - Add BindingAlias= for WebIDL attrbutes, use it to slim CSS2Properties down. r=bz
As opposed to Alias attribute, which reuses the JS function object for the property, BindingAlias will only reuse the generated attribute binding implementation, without changing observable behavior. It can be used to reduce amount of generated code, if the attributes are known to behave exactly the same. This cuts the size of generated CSS2PropertiesBinding.cpp by half, and removes ~100kB of dupicated code from libxul. MozReview-Commit-ID: G0q8TbaqFdp --HG-- extra : rebase_source : 87a2a501cc8adb379df1f4563d3696a339abd0fc
1 parent 16cb254 commit 35b93ce

File tree

3 files changed

+61
-26
lines changed

3 files changed

+61
-26
lines changed

dom/bindings/Codegen.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2706,8 +2706,15 @@ def __init__(self, descriptor, name, static, unforgeable=False):
27062706
not isNonExposedNavigatorObjectGetter(m, descriptor)]
27072707
else:
27082708
attributes = []
2709-
self.chrome = [m for m in attributes if isChromeOnly(m)]
2710-
self.regular = [m for m in attributes if not isChromeOnly(m)]
2709+
2710+
attributes = [
2711+
{"name": name, "attr": attr}
2712+
for attr in attributes
2713+
for name in [attr.identifier.name] + attr.bindingAliases
2714+
]
2715+
2716+
self.chrome = [m for m in attributes if isChromeOnly(m["attr"])]
2717+
self.regular = [m for m in attributes if not isChromeOnly(m["attr"])]
27112718
self.static = static
27122719
self.unforgeable = unforgeable
27132720

@@ -2724,6 +2731,9 @@ def generateArray(self, array, name):
27242731
if len(array) == 0:
27252732
return ""
27262733

2734+
def condition(m, d):
2735+
return PropertyDefiner.getControllingCondition(m["attr"], d)
2736+
27272737
def flags(attr):
27282738
unforgeable = " | JSPROP_PERMANENT" if self.unforgeable else ""
27292739
return EnumerabilityFlags(attr) + unforgeable
@@ -2791,16 +2801,16 @@ def setter(attr):
27912801
return "%s, %s" % \
27922802
(accessor, jitinfo)
27932803

2794-
def specData(attr):
2795-
return (attr.identifier.name, flags(attr), getter(attr),
2796-
setter(attr))
2804+
def specData(entry):
2805+
name, attr = entry["name"], entry["attr"]
2806+
return (name, flags(attr), getter(attr), setter(attr))
27972807

27982808
return self.generatePrefableArray(
27992809
array, name,
28002810
lambda fields: ' { "%s", %s, %s, %s }' % fields,
28012811
' { nullptr, 0, nullptr, nullptr, nullptr, nullptr }',
28022812
'JSPropertySpec',
2803-
PropertyDefiner.getControllingCondition, specData)
2813+
condition, specData)
28042814

28052815

28062816
class ConstDefiner(PropertyDefiner):

dom/bindings/GenerateCSS2PropertiesWebIDL.py

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,15 @@ def generate(output, idlFilename, preprocessorHeader):
3333
if pref is not "":
3434
extendedAttrs.append('Pref="%s"' % pref)
3535

36-
# webkit properties get a capitalized "WebkitFoo" accessor (added here)
37-
# as well as a camelcase "webkitFoo" accessor (added next).
36+
# webkit properties get a camelcase "webkitFoo" accessor
37+
# as well as a capitalized "WebkitFoo" alias (added here).
3838
if (prop.startswith("Webkit")):
39-
props += generateLine(prop, extendedAttrs)
39+
extendedAttrs.append('BindingAlias="%s"' % prop)
4040

41-
# Generate a line with camelCase spelling of property-name (or capitalized,
41+
# Generate a name with camelCase spelling of property-name (or capitalized,
4242
# for Moz-prefixed properties):
4343
if not prop.startswith("Moz"):
4444
prop = prop[0].lower() + prop[1:]
45-
props += generateLine(prop, extendedAttrs)
4645

4746
# Per spec, what's actually supposed to happen here is that we're supposed
4847
# to have properties for:
@@ -56,15 +55,14 @@ def generate(output, idlFilename, preprocessorHeader):
5655
# in that list.
5756
#
5857
# In practice, cssFloat is the only case in which "name" doesn't contain
59-
# "-" but also doesn't match "prop". So the above generatePropLine() call
60-
# covered (3) and all of (1) except "float". If we now output attributes
58+
# "-" but also doesn't match "prop". So the generateLine() call will
59+
# cover (3) and all of (1) except "float". If we now add an alias
6160
# for all the cases where "name" doesn't match "prop", that will cover
6261
# "float" and (2).
6362
if prop != name:
64-
extendedAttrs.append('BinaryName="%s"' % prop)
65-
# Throw in a '_' before the attribute name, because some of these
66-
# property names collide with IDL reserved words.
67-
props += generateLine("_" + name, extendedAttrs)
63+
extendedAttrs.append('BindingAlias="%s"' % name)
64+
65+
props += generateLine(prop, extendedAttrs)
6866

6967

7068
idlFile = open(idlFilename, "r")

dom/bindings/parser/WebIDL.py

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,6 +1181,22 @@ def finish(self, scope):
11811181
parent = parent.parent
11821182

11831183
def validate(self):
1184+
1185+
def checkDuplicateNames(member, name, attributeName):
1186+
for m in self.members:
1187+
if m.identifier.name == name:
1188+
raise WebIDLError("[%s=%s] has same name as interface member" %
1189+
(attributeName, name),
1190+
[member.location, m.location])
1191+
if m.isMethod() and m != member and name in m.aliases:
1192+
raise WebIDLError("conflicting [%s=%s] definitions" %
1193+
(attributeName, name),
1194+
[member.location, m.location])
1195+
if m.isAttr() and m != member and name in m.bindingAliases:
1196+
raise WebIDLError("conflicting [%s=%s] definitions" %
1197+
(attributeName, name),
1198+
[member.location, m.location])
1199+
11841200
# We don't support consequential unforgeable interfaces. Need to check
11851201
# this here, because in finish() an interface might not know yet that
11861202
# it's consequential.
@@ -1293,15 +1309,15 @@ def validate(self):
12931309
raise WebIDLError("[Alias] must not be used on an "
12941310
"[Unforgeable] operation",
12951311
[member.location])
1296-
for m in self.members:
1297-
if m.identifier.name == alias:
1298-
raise WebIDLError("[Alias=%s] has same name as "
1299-
"interface member" % alias,
1300-
[member.location, m.location])
1301-
if m.isMethod() and m != member and alias in m.aliases:
1302-
raise WebIDLError("duplicate [Alias=%s] definitions" %
1303-
alias,
1304-
[member.location, m.location])
1312+
1313+
checkDuplicateNames(member, alias, "Alias")
1314+
1315+
# Check that the name of a [BindingAlias] doesn't conflict with an
1316+
# interface member.
1317+
if member.isAttr():
1318+
for bindingAlias in member.bindingAliases:
1319+
checkDuplicateNames(member, bindingAlias, "BindingAlias")
1320+
13051321

13061322
if (self.getExtendedAttribute("Pref") and
13071323
self._exposureGlobalNames != set([self.parentScope.primaryGlobalName])):
@@ -3581,6 +3597,11 @@ def _addAlias(self, alias):
35813597
[self.location])
35823598
self.aliases.append(alias)
35833599

3600+
def _addBindingAlias(self, bindingAlias):
3601+
if bindingAlias in self.bindingAliases:
3602+
raise WebIDLError("Duplicate [BindingAlias=%s] on attribute" % bindingAlias,
3603+
[self.location])
3604+
self.bindingAliases.append(bindingAlias)
35843605

35853606
class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
35863607

@@ -4011,6 +4032,7 @@ def __init__(self, location, identifier, type, readonly, inherit=False,
40114032
self.dependsOn = "Everything"
40124033
self.affects = "Everything"
40134034
self.navigatorObjectGetter = navigatorObjectGetter
4035+
self.bindingAliases = []
40144036

40154037
if static and identifier.name == "prototype":
40164038
raise WebIDLError("The identifier of a static attribute must not be 'prototype'",
@@ -4155,6 +4177,11 @@ def handleExtendedAttribute(self, attr):
41554177
raise WebIDLError("Readonly attributes must not be flagged as "
41564178
"[%s]" % identifier,
41574179
[self.location])
4180+
elif identifier == "BindingAlias":
4181+
if not attr.hasValue():
4182+
raise WebIDLError("[BindingAlias] takes an identifier or string",
4183+
[attr.location])
4184+
self._addBindingAlias(attr.value())
41584185
elif (((identifier == "Throws" or identifier == "GetterThrows" or
41594186
identifier == "CanOOM" or identifier == "GetterCanOOM") and
41604187
self.getExtendedAttribute("StoreInSlot")) or

0 commit comments

Comments
 (0)