Bug 1375829 part 5. Switch from using "jsonifier" syntax to the spec's "[Default] toJSON" syntax. r=qdot

This commit is contained in:
Boris Zbarsky 2018-05-17 23:43:59 -04:00
Родитель 5d1de86578
Коммит bbb35f3bbb
20 изменённых файлов: 80 добавлений и 137 удалений

Просмотреть файл

@ -1075,15 +1075,15 @@ class CGHeaders(CGWrapper):
ancestors.append(parent)
interfaceDeps.extend(ancestors)
# Include parent interface headers needed for jsonifier code.
# Include parent interface headers needed for default toJSON code.
jsonInterfaceParents = []
for desc in descriptors:
if not desc.operations['Jsonifier']:
if not desc.hasDefaultToJSON:
continue
parent = desc.interface.parent
while parent:
parentDesc = desc.getDescriptor(parent.identifier.name)
if parentDesc.operations['Jsonifier']:
if parentDesc.hasDefaultToJSON:
jsonInterfaceParents.append(parentDesc.interface)
parent = parent.parent
interfaceDeps.extend(jsonInterfaceParents)
@ -2411,20 +2411,6 @@ class MethodDefiner(PropertyDefiner):
self.chrome.append(toStringDesc)
else:
self.regular.append(toStringDesc)
jsonifier = descriptor.operations['Jsonifier']
if (jsonifier and
unforgeable == MemberIsUnforgeable(jsonifier, descriptor)):
toJSONDesc = {
"name": "toJSON",
"nativeName": jsonifier.identifier.name,
"length": 0,
"flags": "JSPROP_ENUMERATE",
"condition": PropertyDefiner.getControllingCondition(jsonifier, descriptor)
}
if isChromeOnly(jsonifier):
self.chrome.append(toJSONDesc)
else:
self.regular.append(toJSONDesc)
if (unforgeable and
descriptor.interface.getExtendedAttribute("Unforgeable")):
# Synthesize our valueOf method
@ -2878,23 +2864,23 @@ class CGNativeProperties(CGList):
return CGList.define(self)
class CGJsonifyAttributesMethod(CGAbstractMethod):
class CGCollectJSONAttributesMethod(CGAbstractMethod):
"""
Generate the JsonifyAttributes method for an interface descriptor
Generate the CollectJSONAttributes method for an interface descriptor
"""
def __init__(self, descriptor, jsonifierMethod):
def __init__(self, descriptor, toJSONMethod):
args = [Argument('JSContext*', 'aCx'),
Argument('JS::Handle<JSObject*>', 'obj'),
Argument('%s*' % descriptor.nativeType, 'self'),
Argument('JS::Rooted<JSObject*>&', 'aResult')]
CGAbstractMethod.__init__(self, descriptor, 'JsonifyAttributes',
CGAbstractMethod.__init__(self, descriptor, 'CollectJSONAttributes',
'bool', args, canRunScript=True)
self.jsonifierMethod = jsonifierMethod
self.toJSONMethod = toJSONMethod
def definition_body(self):
ret = ''
interface = self.descriptor.interface
jsonifierCondition = PropertyDefiner.getControllingCondition(self.jsonifierMethod,
toJSONCondition = PropertyDefiner.getControllingCondition(self.toJSONMethod,
self.descriptor)
for m in interface.members:
if m.isAttr() and not m.isStatic() and m.type.isJSONType():
@ -2911,10 +2897,10 @@ class CGJsonifyAttributesMethod(CGAbstractMethod):
name=IDLToCIdentifier(m.identifier.name))
# Make sure we don't include things which are supposed to be
# disabled. Things that either don't have disablers or whose
# disablers match the disablers for our jsonifier method can't
# disablers match the disablers for our toJSON method can't
# possibly be disabled, but other things might be.
condition = PropertyDefiner.getControllingCondition(m, self.descriptor)
if condition.hasDisablers() and condition != jsonifierCondition:
if condition.hasDisablers() and condition != toJSONCondition:
ret += fill(
"""
// This is unfortunately a linear scan through sAttributes, but we
@ -8641,9 +8627,9 @@ class CGMethodPromiseWrapper(CGAbstractStaticMethod):
return methodName + "_promiseWrapper"
class CGJsonifierMethod(CGSpecializedMethod):
class CGDefaultToJSONMethod(CGSpecializedMethod):
def __init__(self, descriptor, method):
assert method.isJsonifier()
assert method.isDefaultToJSON()
CGSpecializedMethod.__init__(self, descriptor, method)
def definition_body(self):
@ -8658,7 +8644,7 @@ class CGJsonifierMethod(CGSpecializedMethod):
interface = self.descriptor.interface.parent
while interface:
descriptor = self.descriptor.getDescriptor(interface.identifier.name)
if descriptor.operations['Jsonifier']:
if descriptor.hasDefaultToJSON:
jsonDescriptors.append(descriptor)
interface = interface.parent
@ -8666,7 +8652,7 @@ class CGJsonifierMethod(CGSpecializedMethod):
for descriptor in jsonDescriptors[::-1]:
ret += fill(
"""
if (!${parentclass}::JsonifyAttributes(cx, obj, self, result)) {
if (!${parentclass}::CollectJSONAttributes(cx, obj, self, result)) {
return false;
}
""",
@ -12264,15 +12250,12 @@ class MemberProperties:
self.isCrossOriginMethod = False
self.isCrossOriginGetter = False
self.isCrossOriginSetter = False
self.isJsonifier = False
def memberProperties(m, descriptor):
props = MemberProperties()
if m.isMethod():
if m == descriptor.operations['Jsonifier']:
props.isJsonifier = True
elif (not m.isIdentifierLess() or m == descriptor.operations['Stringifier']):
if (not m.isIdentifierLess() or m == descriptor.operations['Stringifier']):
if not m.isStatic() and descriptor.interface.hasInterfacePrototypeObject():
if m.getExtendedAttribute("CrossOriginCallable"):
props.isCrossOriginMethod = True
@ -12312,7 +12295,7 @@ class CGDescriptor(CGThing):
" \"Can't inherit from an interface with a different ownership model.\");\n" %
toBindingNamespace(descriptor.parentPrototypeName)))
jsonifierMethod = None
defaultToJSONMethod = None
crossOriginMethods, crossOriginGetters, crossOriginSetters = set(), set(), set()
unscopableNames = list()
for n in descriptor.interface.namedConstructors:
@ -12328,8 +12311,8 @@ class CGDescriptor(CGThing):
if m.getExtendedAttribute("Unscopable"):
assert not m.isStatic()
unscopableNames.append(m.identifier.name)
if props.isJsonifier:
jsonifierMethod = m
if m.isDefaultToJSON():
defaultToJSONMethod = m
elif not m.isIdentifierLess() or m == descriptor.operations['Stringifier']:
if m.isStatic():
assert descriptor.interface.hasInterfaceObject()
@ -12390,9 +12373,9 @@ class CGDescriptor(CGThing):
if m.isConst() and m.type.isPrimitive():
cgThings.append(CGConstDefinition(m))
if jsonifierMethod:
cgThings.append(CGJsonifierMethod(descriptor, jsonifierMethod))
cgThings.append(CGMemberJITInfo(descriptor, jsonifierMethod))
if defaultToJSONMethod:
cgThings.append(CGDefaultToJSONMethod(descriptor, defaultToJSONMethod))
cgThings.append(CGMemberJITInfo(descriptor, defaultToJSONMethod))
if descriptor.interface.isNavigatorProperty():
cgThings.append(CGConstructNavigatorObject(descriptor))
@ -12416,10 +12399,10 @@ class CGDescriptor(CGThing):
cgThings.append(CGGeneric(define=str(properties)))
cgThings.append(CGNativeProperties(descriptor, properties))
if jsonifierMethod:
if defaultToJSONMethod:
# Now that we know about our property arrays, we can
# output our "jsonify attributes" method, which uses those.
cgThings.append(CGJsonifyAttributesMethod(descriptor, jsonifierMethod))
# output our "collect attribute values" method, which uses those.
cgThings.append(CGCollectJSONAttributesMethod(descriptor, defaultToJSONMethod))
if descriptor.interface.hasInterfaceObject():
cgThings.append(CGClassConstructor(descriptor,
@ -14722,9 +14705,6 @@ class CGBindingImplClass(CGClass):
else:
# We already added this method
return
if name == "Jsonifier":
# We already added this method
return
self.methodDecls.append(
CGNativeMember(descriptor, op,
name,

Просмотреть файл

@ -417,10 +417,11 @@ class Descriptor(DescriptorProvider):
'NamedDeleter': None,
'Stringifier': None,
'LegacyCaller': None,
'Jsonifier': None
}
# Stringifiers and jsonifiers need to be set up whether an interface is
self.hasDefaultToJSON = False
# Stringifiers need to be set up whether an interface is
# concrete or not, because they're actually prototype methods and hence
# can apply to instances of descendant interfaces. Legacy callers and
# named/indexed operations only need to be set up on concrete
@ -436,8 +437,8 @@ class Descriptor(DescriptorProvider):
for m in self.interface.members:
if m.isMethod() and m.isStringifier():
addOperation('Stringifier', m)
if m.isMethod() and m.isJsonifier():
addOperation('Jsonifier', m)
if m.isMethod() and m.isDefaultToJSON():
self.hasDefaultToJSON = True
if self.concrete:
self.proxy = False

Просмотреть файл

@ -1017,10 +1017,9 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
[self.location])
for m in self.members:
if ((m.isMethod() and m.isJsonifier()) or
m.identifier.name == "toJSON"):
if m.identifier.name == "toJSON":
raise WebIDLError("Unforgeable interface %s has a "
"jsonifier so we won't be able to add "
"toJSON so we won't be able to add "
"one ourselves" % self.identifier.name,
[self.location, m.location])
@ -1115,15 +1114,12 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
memberType = "deleters"
elif member.isStringifier():
memberType = "stringifiers"
elif member.isJsonifier():
memberType = "jsonifiers"
elif member.isLegacycaller():
memberType = "legacycallers"
else:
continue
if (memberType != "stringifiers" and memberType != "legacycallers" and
memberType != "jsonifiers"):
if (memberType != "stringifiers" and memberType != "legacycallers"):
if member.isNamed():
memberType = "named " + memberType
else:
@ -2818,7 +2814,7 @@ class IDLWrapperType(IDLType):
return False
iface = self.inner
while iface:
if any(m.isMethod() and m.isJsonifier() for m in self.inner.members):
if any(m.isMethod() and m.isToJSON() for m in self.inner.members):
return True
iface = iface.parent
return False
@ -4671,7 +4667,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
def __init__(self, location, identifier, returnType, arguments,
static=False, getter=False, setter=False,
deleter=False, specialType=NamedOrIndexed.Neither,
legacycaller=False, stringifier=False, jsonifier=False,
legacycaller=False, stringifier=False,
maplikeOrSetlikeOrIterable=None, htmlConstructor=False):
# REVIEW: specialType is NamedOrIndexed -- wow, this is messed up.
IDLInterfaceMember.__init__(self, location, identifier,
@ -4696,8 +4692,6 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
self._legacycaller = legacycaller
assert isinstance(stringifier, bool)
self._stringifier = stringifier
assert isinstance(jsonifier, bool)
self._jsonifier = jsonifier
assert maplikeOrSetlikeOrIterable is None or isinstance(maplikeOrSetlikeOrIterable, IDLMaplikeOrSetlikeOrIterableBase)
self.maplikeOrSetlikeOrIterable = maplikeOrSetlikeOrIterable
assert isinstance(htmlConstructor, bool)
@ -4745,12 +4739,6 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
assert len(overload.arguments) == 0
assert overload.returnType == BuiltinTypes[IDLBuiltinType.Types.domstring]
if self._jsonifier:
assert len(self._overloads) == 1
overload = self._overloads[0]
assert len(overload.arguments) == 0
assert overload.returnType == BuiltinTypes[IDLBuiltinType.Types.object]
def isStatic(self):
return self._static
@ -4782,8 +4770,11 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
def isStringifier(self):
return self._stringifier
def isJsonifier(self):
return self._jsonifier
def isToJSON(self):
return self.identifier.name == "toJSON"
def isDefaultToJSON(self):
return self.isToJSON() and self.getExtendedAttribute("Default")
def isMaplikeOrSetlikeOrIterableMethod(self):
"""
@ -4797,8 +4788,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
self.isSetter() or
self.isDeleter() or
self.isLegacycaller() or
self.isStringifier() or
self.isJsonifier())
self.isStringifier())
def isHTMLConstructor(self):
return self._htmlConstructor
@ -4854,8 +4844,6 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
assert not method.isDeleter()
assert not self.isStringifier()
assert not method.isStringifier()
assert not self.isJsonifier()
assert not method.isJsonifier()
assert not self.isHTMLConstructor()
assert not method.isHTMLConstructor()
@ -5124,6 +5112,14 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
raise WebIDLError("[CEReactions] is only allowed on operation, "
"attribute, setter, and deleter",
[attr.location, self.location])
elif identifier == "Default":
if not attr.noArguments():
raise WebIDLError("[Default] must take no arguments",
[attr.location])
if not self.isToJSON():
raise WebIDLError("[Default] is only allowed on toJSON operations",
[attr.location, self.location])
elif (identifier == "Throws" or
identifier == "CanOOM" or
identifier == "NewObject" or
@ -5311,7 +5307,6 @@ class Tokenizer(object):
"false": "FALSE",
"serializer": "SERIALIZER",
"stringifier": "STRINGIFIER",
"jsonifier": "JSONIFIER",
"unrestricted": "UNRESTRICTED",
"attribute": "ATTRIBUTE",
"readonly": "READONLY",
@ -6142,19 +6137,6 @@ class Parser(Tokenizer):
stringifier=True)
p[0] = method
def p_Jsonifier(self, p):
"""
Operation : JSONIFIER SEMICOLON
"""
identifier = IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
"__jsonifier", allowDoubleUnderscore=True)
method = IDLMethod(self.getLocation(p, 1),
identifier,
returnType=BuiltinTypes[IDLBuiltinType.Types.object],
arguments=[],
jsonifier=True)
p[0] = method
def p_QualifierStatic(self, p):
"""
Qualifier : STATIC
@ -6308,7 +6290,6 @@ class Parser(Tokenizer):
| SETTER
| STATIC
| STRINGIFIER
| JSONIFIER
| TYPEDEF
| UNRESTRICTED
| NAMESPACE
@ -6460,7 +6441,6 @@ class Parser(Tokenizer):
| SHORT
| STATIC
| STRINGIFIER
| JSONIFIER
| TRUE
| TYPEDEF
| UNSIGNED

Просмотреть файл

@ -131,17 +131,3 @@ def WebIDLTest(parser, harness):
harness.ok(threw,
"Should have thrown for [CEReactions] used on a stringifier")
parser = parser.reset()
threw = False
try:
parser.parse("""
interface Foo {
[CEReactions] jsonifier;
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Should have thrown for [CEReactions] used on a jsonifier")

Просмотреть файл

@ -945,12 +945,12 @@ public:
TestInterface* PutForwardsAttr();
TestInterface* PutForwardsAttr2();
TestInterface* PutForwardsAttr3();
void GetJsonifierShouldSkipThis(JSContext*, JS::MutableHandle<JS::Value>);
void SetJsonifierShouldSkipThis(JSContext*, JS::Rooted<JS::Value>&);
TestParentInterface* JsonifierShouldSkipThis2();
void SetJsonifierShouldSkipThis2(TestParentInterface&);
TestCallbackInterface* JsonifierShouldSkipThis3();
void SetJsonifierShouldSkipThis3(TestCallbackInterface&);
void GetToJSONShouldSkipThis(JSContext*, JS::MutableHandle<JS::Value>);
void SetToJSONShouldSkipThis(JSContext*, JS::Rooted<JS::Value>&);
TestParentInterface* ToJSONShouldSkipThis2();
void SetToJSONShouldSkipThis2(TestParentInterface&);
TestCallbackInterface* ToJSONShouldSkipThis3();
void SetToJSONShouldSkipThis3(TestCallbackInterface&);
void ThrowingMethod(ErrorResult& aRv);
bool GetThrowingAttr(ErrorResult& aRv) const;
void SetThrowingAttr(bool arg, ErrorResult& aRv);

Просмотреть файл

@ -963,10 +963,10 @@ interface TestInterface {
optional Dict arg3, optional double arg4 = 5.0,
optional float arg5);
attribute any jsonifierShouldSkipThis;
attribute TestParentInterface jsonifierShouldSkipThis2;
attribute TestCallbackInterface jsonifierShouldSkipThis3;
jsonifier;
attribute any toJSONShouldSkipThis;
attribute TestParentInterface toJSONShouldSkipThis2;
attribute TestCallbackInterface toJSONShouldSkipThis3;
[Default] object toJSON();
attribute byte dashed-attribute;
void dashed-method();

Просмотреть файл

@ -796,10 +796,10 @@ interface TestExampleInterface {
optional TestInterface? arg2 = null,
optional Dict arg3, optional double arg4 = 5.0,
optional float arg5);
attribute any jsonifierShouldSkipThis;
attribute TestParentInterface jsonifierShouldSkipThis2;
attribute TestCallbackInterface jsonifierShouldSkipThis3;
jsonifier;
attribute any toJSONShouldSkipThis;
attribute TestParentInterface toJSONShouldSkipThis2;
attribute TestCallbackInterface toJSONShouldSkipThis3;
[Default] object toJSON();
attribute byte dashed-attribute;
void dashed-method();

Просмотреть файл

@ -814,10 +814,10 @@ interface TestJSImplInterface {
optional TestInterface? arg2 = null,
optional Dict arg3, optional double arg4 = 5.0,
optional float arg5);
attribute any jsonifierShouldSkipThis;
attribute TestParentInterface jsonifierShouldSkipThis2;
attribute TestCallbackInterface jsonifierShouldSkipThis3;
jsonifier;
attribute any toJSONShouldSkipThis;
attribute TestParentInterface toJSONShouldSkipThis2;
attribute TestCallbackInterface toJSONShouldSkipThis3;
[Default] object toJSON();
attribute byte dashed-attribute;
void dashed-method();

Просмотреть файл

@ -20,5 +20,5 @@ interface MediaDeviceInfo {
readonly attribute DOMString label;
readonly attribute DOMString groupId;
jsonifier;
[Default] object toJSON();
};

Просмотреть файл

@ -10,9 +10,7 @@
[SecureContext,
Func="mozilla::dom::PaymentRequest::PrefEnabled"]
interface PaymentAddress {
// TODO: Use serializer once available. (Bug 863402)
// serializer = {attribute};
jsonifier;
[Default] object toJSON();
readonly attribute DOMString country;
// TODO: Use FrozenArray once available. (Bug 1236777)

Просмотреть файл

@ -16,9 +16,7 @@ enum PaymentComplete {
[SecureContext,
Func="mozilla::dom::PaymentRequest::PrefEnabled"]
interface PaymentResponse {
// TODO: Use serializer once available. (Bug 863402)
// serializer = {attribute};
jsonifier;
[Default] object toJSON();
readonly attribute DOMString requestId;
readonly attribute DOMString methodName;

Просмотреть файл

@ -29,7 +29,7 @@ partial interface Performance {
[Constant]
readonly attribute PerformanceNavigation navigation;
jsonifier;
[Default] object toJSON();
};
// http://www.w3.org/TR/performance-timeline/#sec-window.performance-attribute

Просмотреть файл

@ -18,5 +18,5 @@ interface PerformanceEntry
readonly attribute DOMHighResTimeStamp startTime;
readonly attribute DOMHighResTimeStamp duration;
jsonifier;
[Default] object toJSON();
};

Просмотреть файл

@ -19,5 +19,5 @@ interface PerformanceNavigation {
readonly attribute unsigned short type;
readonly attribute unsigned short redirectCount;
jsonifier;
[Default] object toJSON();
};

Просмотреть файл

@ -29,5 +29,5 @@ interface PerformanceNavigationTiming : PerformanceResourceTiming {
readonly attribute NavigationType type;
readonly attribute unsigned short redirectCount;
jsonifier;
[Default] object toJSON();
};

Просмотреть файл

@ -54,5 +54,5 @@ interface PerformanceResourceTiming : PerformanceEntry
[SecureContext, Frozen, Cached, Pure, NeedsSubjectPrincipal]
readonly attribute sequence<PerformanceServerTiming> serverTiming;
jsonifier;
[Default] object toJSON();
};

Просмотреть файл

@ -16,5 +16,5 @@ interface PerformanceServerTiming {
readonly attribute DOMHighResTimeStamp duration;
readonly attribute DOMString description;
jsonifier;
[Default] object toJSON();
};

Просмотреть файл

@ -45,5 +45,5 @@ interface PerformanceTiming {
[Pref="dom.performance.time_to_dom_content_flushed.enabled"]
readonly attribute unsigned long long timeToDOMContentFlushed;
jsonifier;
[Default] object toJSON();
};

Просмотреть файл

@ -21,5 +21,5 @@ interface RTCIceCandidate {
attribute DOMString? sdpMid;
attribute unsigned short? sdpMLineIndex;
jsonifier;
[Default] object toJSON();
};

Просмотреть файл

@ -27,5 +27,5 @@ interface RTCSessionDescription {
attribute RTCSdpType type;
attribute DOMString sdp;
jsonifier;
[Default] object toJSON();
};