Bug 860841. Hook up the proto chain of a WebIDL interface object to the interface object of its nearest ancestor interface that has one, as if these were ES6 classes. r=peterv

This commit is contained in:
Boris Zbarsky 2013-05-02 14:38:19 -04:00
parent a40cbfe148
commit fb71a87689
9 changed files with 89 additions and 34 deletions

View File

@ -39,28 +39,28 @@ is(HTMLMediaElement.MEDIA_ERR_ABORTED, undefined);
is(HTMLMediaElement.MEDIA_ERR_NETWORK, undefined);
is(HTMLMediaElement.MEDIA_ERR_DECODE, undefined);
is(HTMLMediaElement.MEDIA_ERR_SRC_NOT_SUPPORTED, undefined);
is(HTMLVideoElement.NETWORK_EMPTY, undefined);
is(HTMLVideoElement.NETWORK_IDLE, undefined);
is(HTMLVideoElement.NETWORK_LOADING, undefined);
is(HTMLVideoElement.NETWORK_NO_SOURCE, undefined);
is(HTMLVideoElement.HAVE_NOTHING, undefined);
is(HTMLVideoElement.HAVE_METADATA, undefined);
is(HTMLVideoElement.HAVE_CURRENT_DATA, undefined);
is(HTMLVideoElement.HAVE_FUTURE_DATA, undefined);
is(HTMLVideoElement.HAVE_ENOUGH_DATA, undefined);
is(HTMLVideoElement.NETWORK_EMPTY, 0);
is(HTMLVideoElement.NETWORK_IDLE, 1);
is(HTMLVideoElement.NETWORK_LOADING, 2);
is(HTMLVideoElement.NETWORK_NO_SOURCE, 3);
is(HTMLVideoElement.HAVE_NOTHING, 0);
is(HTMLVideoElement.HAVE_METADATA, 1);
is(HTMLVideoElement.HAVE_CURRENT_DATA, 2);
is(HTMLVideoElement.HAVE_FUTURE_DATA, 3);
is(HTMLVideoElement.HAVE_ENOUGH_DATA, 4);
is(HTMLVideoElement.MEDIA_ERR_ABORTED, undefined);
is(HTMLVideoElement.MEDIA_ERR_NETWORK, undefined);
is(HTMLVideoElement.MEDIA_ERR_DECODE, undefined);
is(HTMLVideoElement.MEDIA_ERR_SRC_NOT_SUPPORTED, undefined);
is(HTMLAudioElement.NETWORK_EMPTY, undefined);
is(HTMLAudioElement.NETWORK_IDLE, undefined);
is(HTMLAudioElement.NETWORK_LOADING, undefined);
is(HTMLAudioElement.NETWORK_NO_SOURCE, undefined);
is(HTMLAudioElement.HAVE_NOTHING, undefined);
is(HTMLAudioElement.HAVE_METADATA, undefined);
is(HTMLAudioElement.HAVE_CURRENT_DATA, undefined);
is(HTMLAudioElement.HAVE_FUTURE_DATA, undefined);
is(HTMLAudioElement.HAVE_ENOUGH_DATA, undefined);
is(HTMLAudioElement.NETWORK_EMPTY, 0);
is(HTMLAudioElement.NETWORK_IDLE, 1);
is(HTMLAudioElement.NETWORK_LOADING, 2);
is(HTMLAudioElement.NETWORK_NO_SOURCE, 3);
is(HTMLAudioElement.HAVE_NOTHING, 0);
is(HTMLAudioElement.HAVE_METADATA, 1);
is(HTMLAudioElement.HAVE_CURRENT_DATA, 2);
is(HTMLAudioElement.HAVE_FUTURE_DATA, 3);
is(HTMLAudioElement.HAVE_ENOUGH_DATA, 4);
is(HTMLAudioElement.MEDIA_ERR_ABORTED, undefined);
is(HTMLAudioElement.MEDIA_ERR_NETWORK, undefined);
is(HTMLAudioElement.MEDIA_ERR_DECODE, undefined);

View File

@ -309,6 +309,7 @@ DefineConstructor(JSContext* cx, JS::Handle<JSObject*> global, const char* name,
static JSObject*
CreateInterfaceObject(JSContext* cx, JS::Handle<JSObject*> global,
JS::Handle<JSObject*> constructorProto,
JSClass* constructorClass,
const JSNativeHolder* constructorNative,
unsigned ctorNargs, const NamedConstructor* namedConstructors,
@ -318,20 +319,12 @@ CreateInterfaceObject(JSContext* cx, JS::Handle<JSObject*> global,
const char* name)
{
JS::Rooted<JSObject*> constructor(cx);
bool isCallbackInterface = constructorClass == js::Jsvalify(&js::ObjectClass);
if (constructorClass) {
JSObject* constructorProto;
if (isCallbackInterface) {
constructorProto = JS_GetObjectPrototype(cx, global);
} else {
constructorProto = JS_GetFunctionPrototype(cx, global);
}
if (!constructorProto) {
return NULL;
}
MOZ_ASSERT(constructorProto);
constructor = JS_NewObject(cx, constructorClass, constructorProto, global);
} else {
MOZ_ASSERT(constructorNative);
MOZ_ASSERT(constructorProto == JS_GetFunctionPrototype(cx, global));
constructor = CreateConstructor(cx, global, name, constructorNative,
ctorNargs);
}
@ -339,7 +332,7 @@ CreateInterfaceObject(JSContext* cx, JS::Handle<JSObject*> global,
return NULL;
}
if (constructorClass && !isCallbackInterface) {
if (constructorClass) {
// Have to shadow Function.prototype.toString, since that throws
// on things that are not js::FunctionClass.
JS::Rooted<JSFunction*> toString(cx,
@ -506,6 +499,7 @@ void
CreateInterfaceObjects(JSContext* cx, JS::Handle<JSObject*> global,
JS::Handle<JSObject*> protoProto,
JSClass* protoClass, JSObject** protoCache,
JS::Handle<JSObject*> constructorProto,
JSClass* constructorClass, const JSNativeHolder* constructor,
unsigned ctorNargs, const NamedConstructor* namedConstructors,
JSObject** constructorCache, const DOMClass* domClass,
@ -558,7 +552,8 @@ CreateInterfaceObjects(JSContext* cx, JS::Handle<JSObject*> global,
JSObject* interface;
if (constructorClass || constructor) {
interface = CreateInterfaceObject(cx, global, constructorClass, constructor,
interface = CreateInterfaceObject(cx, global, constructorProto,
constructorClass, constructor,
ctorNargs, namedConstructors, proto,
properties, chromeOnlyProperties, name);
if (!interface) {

View File

@ -299,6 +299,7 @@ struct NamedConstructor
* global is used as the parent of the interface object and the interface
* prototype object
* protoProto is the prototype to use for the interface prototype object.
* interfaceProto is the prototype to use for the interface object.
* protoClass is the JSClass to use for the interface prototype object.
* This is null if we should not create an interface prototype
* object.
@ -334,6 +335,7 @@ void
CreateInterfaceObjects(JSContext* cx, JS::Handle<JSObject*> global,
JS::Handle<JSObject*> protoProto,
JSClass* protoClass, JSObject** protoCache,
JS::Handle<JSObject*> interfaceProto,
JSClass* constructorClass, const JSNativeHolder* constructor,
unsigned ctorNargs, const NamedConstructor* namedConstructors,
JSObject** constructorCache, const DOMClass* domClass,

View File

@ -1688,6 +1688,21 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
toBindingNamespace(parentProtoName))
parentProtoType = "Handle"
parentWithInterfaceObject = self.descriptor.interface.parent
while (parentWithInterfaceObject and
not parentWithInterfaceObject.hasInterfaceObject()):
parentWithInterfaceObject = parentWithInterfaceObject.parent
if parentWithInterfaceObject:
parentIfaceName = parentWithInterfaceObject.identifier.name
if self.descriptor.workers:
parentIfaceName += "_workers"
getConstructorProto = ("%s::GetConstructorObject(aCx, aGlobal)" %
toBindingNamespace(parentIfaceName))
constructorProtoType = "Handle"
else:
getConstructorProto = "aCx, JS_GetFunctionPrototype(aCx, aGlobal)"
constructorProtoType = "Rooted"
needInterfaceObject = self.descriptor.interface.hasInterfaceObject()
needInterfacePrototypeObject = self.descriptor.interface.hasInterfacePrototypeObject()
@ -1757,7 +1772,12 @@ if (!unforgeableHolder) {
getParentProto = ("JS::%s<JSObject*> parentProto(%s);\n" +
"if (!parentProto) {\n" +
" return;\n" +
"}\n") % (parentProtoType, getParentProto)
"}") % (parentProtoType, getParentProto)
getConstructorProto = ("JS::%s<JSObject*> constructorProto(%s);\n"
"if (!constructorProto) {\n"
" return;\n"
"}" % (constructorProtoType, getConstructorProto))
if (needInterfaceObject and
self.descriptor.needsConstructHookHolder()):
@ -1807,7 +1827,7 @@ if (!unforgeableHolder) {
chromeProperties = "nullptr"
call = ("dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,\n"
" %s, %s,\n"
" %s, %s, %d, %s,\n"
" constructorProto, %s, %s, %d, %s,\n"
" %s,\n"
" %s,\n"
" %s,\n"
@ -1832,8 +1852,8 @@ if (!unforgeableHolder) {
else:
setUnforgeableHolder = None
functionBody = CGList(
[CGGeneric(getParentProto), initIds, prefCache,
createUnforgeableHolder, CGGeneric(call), setUnforgeableHolder],
[CGGeneric(getParentProto), CGGeneric(getConstructorProto), initIds,
prefCache, createUnforgeableHolder, CGGeneric(call), setUnforgeableHolder],
"\n\n")
return CGIndenter(functionBody).define()

View File

@ -139,6 +139,18 @@
"CharacterData interface: calling after(union) on document.createComment(\"abc\") with too few arguments must throw TypeError": true,
"CharacterData interface: document.createComment(\"abc\") must inherit property \"replace\" with the proper type (11)": true,
"CharacterData interface: calling replace(union) on document.createComment(\"abc\") with too few arguments must throw TypeError": true,
"Node interface: existence and properties of interface object": true,
"Document interface: existence and properties of interface object": true,
"XMLDocument interface: existence and properties of interface object": true,
"DocumentFragment interface: existence and properties of interface object": true,
"DocumentType interface: existence and properties of interface object": true,
"Element interface: existence and properties of interface object": true,
"Attr interface: existence and properties of interface object": true,
"CharacterData interface: existence and properties of interface object": true,
"Text interface: existence and properties of interface object": true,
"ProcessingInstruction interface: existence and properties of interface object": true,
"Comment interface: existence and properties of interface object": true,
"DOMSettableTokenList interface: existence and properties of interface object": true,
"NodeFilter interface: existence and properties of interface object": true,
"NodeList interface: existence and properties of interface prototype object": true
}

View File

@ -0,0 +1,16 @@
# THIS FILE IS AUTOGENERATED BY parseFailures.py - DO NOT EDIT
DEPTH := @DEPTH@
topsrcdir := @top_srcdir@
srcdir := @srcdir@
VPATH := @srcdir@
relativesrcdir := @relativesrcdir@
include $(DEPTH)/config/autoconf.mk
MOCHITEST_FILES := \
test_interfaces.html.json \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,5 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# THIS FILE IS AUTOGENERATED BY parseFailures.py - DO NOT EDIT
DIRS += [
]

View File

@ -0,0 +1,4 @@
{
"XMLHttpRequestUpload interface: existence and properties of interface object": true,
"XMLHttpRequest interface: existence and properties of interface object": true
}

View File

@ -26,6 +26,7 @@ DIRS += [
'failures/webapps/DOMCore/tests/submissions/Opera',
'failures/webapps/WebStorage/tests/submissions/Infraware',
'failures/webapps/WebStorage/tests/submissions/Ms2ger',
'failures/webapps/XMLHttpRequest/tests/submissions/Ms2ger'
]
include('editing.mozbuild')