Bug 1618011 part 9. Make error reporting for unions nicer. r=peterv

Instead of something like
"ByteStringSequenceSequenceOrByteStringByteStringRecord" we should have
"(sequence<sequence<ByteString>> or record<ByteString, Bytestring>)" in error
messages.

Please take a careful look at the resulting error messages (see attachment
in the bug) to see whether this makes sense.

Differential Revision: https://phabricator.services.mozilla.com/D64890

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Boris Zbarsky 2020-03-06 20:39:43 +00:00
Родитель 2564974432
Коммит 7eef692e9d
2 изменённых файлов: 79 добавлений и 13 удалений

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

@ -5357,7 +5357,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
unionArgumentObj += ".SetValue()" if isOwningUnion else ".ref()"
memberTypes = type.flatMemberTypes
names = []
prettyNames = []
interfaceMemberTypes = filter(lambda t: t.isNonCallbackInterface(), memberTypes)
if len(interfaceMemberTypes) > 0:
@ -5367,7 +5367,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
interfaceObject.append(
CGGeneric("(failed = !%s.TrySetTo%s(cx, ${val}, tryNext, ${passedToJSImpl})) || !tryNext" %
(unionArgumentObj, name)))
names.append(name)
prettyNames.append(memberType.prettyName())
interfaceObject = CGWrapper(CGList(interfaceObject, " ||\n"),
pre="done = ", post=";\n\n", reindent=True)
else:
@ -5376,11 +5376,12 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
sequenceObjectMemberTypes = filter(lambda t: t.isSequence(), memberTypes)
if len(sequenceObjectMemberTypes) > 0:
assert len(sequenceObjectMemberTypes) == 1
name = getUnionMemberName(sequenceObjectMemberTypes[0])
memberType = sequenceObjectMemberTypes[0]
name = getUnionMemberName(memberType)
sequenceObject = CGGeneric(
"done = (failed = !%s.TrySetTo%s(cx, ${val}, tryNext, ${passedToJSImpl})) || !tryNext;\n" %
(unionArgumentObj, name))
names.append(name)
prettyNames.append(memberType.prettyName())
else:
sequenceObject = None
@ -5392,29 +5393,31 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
callbackObject = CGGeneric(
"done = (failed = !%s.TrySetTo%s(cx, ${val}, tryNext, ${passedToJSImpl})) || !tryNext;\n" %
(unionArgumentObj, name))
names.append(name)
prettyNames.append(memberType.prettyName())
else:
callbackObject = None
dictionaryMemberTypes = filter(lambda t: t.isDictionary(), memberTypes)
if len(dictionaryMemberTypes) > 0:
assert len(dictionaryMemberTypes) == 1
name = getUnionMemberName(dictionaryMemberTypes[0])
memberType = dictionaryMemberTypes[0]
name = getUnionMemberName(memberType)
setDictionary = CGGeneric(
"done = (failed = !%s.TrySetTo%s(cx, ${val}, tryNext, ${passedToJSImpl})) || !tryNext;\n" %
(unionArgumentObj, name))
names.append(name)
prettyNames.append(memberType.prettyName())
else:
setDictionary = None
recordMemberTypes = filter(lambda t: t.isRecord(), memberTypes)
if len(recordMemberTypes) > 0:
assert len(recordMemberTypes) == 1
name = getUnionMemberName(recordMemberTypes[0])
memberType = recordMemberTypes[0]
name = getUnionMemberName(memberType)
recordObject = CGGeneric(
"done = (failed = !%s.TrySetTo%s(cx, ${val}, tryNext, ${passedToJSImpl})) || !tryNext;\n" %
(unionArgumentObj, name))
names.append(name)
prettyNames.append(memberType.prettyName())
else:
recordObject = None
@ -5428,7 +5431,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
"%s"
"}\n"
"done = true;\n" % (unionArgumentObj, indent(exceptionCode)))
names.append(objectMemberTypes[0].name)
prettyNames.append(objectMemberTypes[0].prettyName())
else:
object = None
@ -5527,7 +5530,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
""",
exceptionCode=exceptionCode,
desc=firstCap(sourceDescription),
names=", ".join(names)))
names=", ".join(prettyNames)))
templateBody = CGWrapper(CGIndenter(CGList([templateBody, throw])), pre="{\n", post="}\n")
@ -5652,7 +5655,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
CGGeneric("return false;\n"),
('!%s.RawSetAs%s(%s).Init(cx, JS::NullHandleValue, "Member of %s")'
% (declLoc, getUnionMemberName(defaultValue.type),
ctorArgs, type)))
ctorArgs, type.prettyName())))
templateBody = CGIfElseWrapper("!(${haveValue})",
initDictionaryWithNull,
templateBody)
@ -10566,7 +10569,8 @@ def getUnionTypeTemplateVars(unionType, type, descriptorProvider,
"tryNext = true;\n"
"return true;\n" % (prefix, name))
sourceDescription = "member of %s" % unionType
sourceDescription = ("%s branch of %s" %
(type.prettyName(), unionType.prettyName()))
conversionInfo = getJSToNativeConversionInfo(
type, descriptorProvider, failureCode=tryNextCode,

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

@ -2122,6 +2122,14 @@ class IDLType(IDLObject):
def __str__(self):
return str(self.name)
def prettyName(self):
"""
A name that looks like what this type is named in the IDL spec. By default
this is just our .name, but types that have more interesting spec
representations should override this.
"""
return str(self.name)
def isType(self):
return True
@ -2353,6 +2361,9 @@ class IDLNullableType(IDLParametrizedType):
def __str__(self):
return self.inner.__str__() + "OrNull"
def prettyName(self):
return self.inner.prettyName() + "?"
def nullable(self):
return True
@ -2512,6 +2523,9 @@ class IDLSequenceType(IDLParametrizedType):
def __str__(self):
return self.inner.__str__() + "Sequence"
def prettyName(self):
return "sequence<%s>" % self.inner.prettyName()
def nullable(self):
return False
@ -2593,6 +2607,9 @@ class IDLRecordType(IDLParametrizedType):
def __str__(self):
return self.keyType.__str__() + self.inner.__str__() + "Record"
def prettyName(self):
return "record<%s, %s>" % (self.keyType.prettyName(), self.inner.prettyName())
def isRecord(self):
return True
@ -2642,6 +2659,9 @@ class IDLUnionType(IDLType):
assert self.isComplete()
return self.name.__hash__()
def prettyName(self):
return "(" + " or ".join(m.prettyName() for m in self.memberTypes) + ")"
def isVoid(self):
return False
@ -3078,6 +3098,9 @@ class IDLPromiseType(IDLParametrizedType):
def __str__(self):
return self.inner.__str__() + "Promise"
def prettyName(self):
return "Promise<%s>" % self.inner.prettyName()
def isPromise(self):
return True
@ -3185,6 +3208,42 @@ class IDLBuiltinType(IDLType):
Types.ReadableStream: IDLType.Tags.interface,
}
PrettyNames = {
Types.byte: "byte",
Types.octet: "octet",
Types.short: "short",
Types.unsigned_short: "unsigned short",
Types.long: "long",
Types.unsigned_long: "unsigned long",
Types.long_long: "long long",
Types.unsigned_long_long: "unsigned long long",
Types.boolean: "boolean",
Types.unrestricted_float: "unrestricted float",
Types.float: "float",
Types.unrestricted_double: "unrestricted double",
Types.double: "double",
Types.any: "any",
Types.domstring: "DOMString",
Types.bytestring: "ByteString",
Types.usvstring: "USVString",
Types.utf8string: "USVString", # That's what it is in spec terms
Types.jsstring: "USVString", # Again, that's what it is in spec terms
Types.object: "object",
Types.void: "void",
Types.ArrayBuffer: "ArrayBuffer",
Types.ArrayBufferView: "ArrayBufferView",
Types.Int8Array: "Int8Array",
Types.Uint8Array: "Uint8Array",
Types.Uint8ClampedArray: "Uint8ClampedArray",
Types.Int16Array: "Int16Array",
Types.Uint16Array: "Uint16Array",
Types.Int32Array: "Int32Array",
Types.Uint32Array: "Uint32Array",
Types.Float32Array: "Float32Array",
Types.Float64Array: "Float64Array",
Types.ReadableStream: "ReadableStream",
}
def __init__(self, location, name, type, clamp=False, enforceRange=False, treatNullAsEmpty=False,
allowShared=False, attrLocation=[]):
"""
@ -3232,6 +3291,9 @@ class IDLBuiltinType(IDLType):
return "MaybeShared" + str(self.name)
return str(self.name)
def prettyName(self):
return IDLBuiltinType.PrettyNames[self._typeTag]
def clamped(self, attrLocation):
if not self._clamped:
self._clamped = IDLBuiltinType(self.location, self.name,