--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -2313,16 +2313,32 @@ IdEquals(jsid id, const char* string)
inline bool
AddStringToIDVector(JSContext* cx, JS::AutoIdVector& vector, const char* name)
{
return vector.growBy(1) &&
AtomizeAndPinJSString(cx, *(vector[vector.length() - 1]).address(), name);
}
+// We use one constructor JSNative to represent all DOM interface objects (so
+// we can easily detect when we need to wrap them in an Xray wrapper). We store
+// the real JSNative in the mNative member of a JSNativeHolder in the
+// CONSTRUCTOR_NATIVE_HOLDER_RESERVED_SLOT slot of the JSFunction object for a
+// specific interface object. We also store the NativeProperties in the
+// JSNativeHolder.
+// Note that some interface objects are not yet a JSFunction but a normal
+// JSObject with a DOMJSClass, those do not use these slots.
+
+enum {
+ CONSTRUCTOR_NATIVE_HOLDER_RESERVED_SLOT = 0
+};
+
+bool
+Constructor(JSContext* cx, unsigned argc, JS::Value* vp);
+
// Implementation of the bits that XrayWrapper needs
/**
* This resolves operations, attributes and constants of the interfaces for obj.
*
* wrapper is the Xray JS object.
* obj is the target object of the Xray, a binding's instance object or a
* interface or interface prototype object.
@@ -2386,16 +2402,19 @@ XrayGetNativeProto(JSContext* cx, JS::Ha
const DOMJSClass* domClass = GetDOMClass(obj);
if (domClass) {
ProtoHandleGetter protoGetter = domClass->mGetProto;
if (protoGetter) {
protop.set(protoGetter(cx));
} else {
protop.set(JS::GetRealmObjectPrototype(cx));
}
+ } else if (JS_ObjectIsFunction(cx, obj)) {
+ MOZ_ASSERT(JS_IsNativeFunction(obj, Constructor));
+ protop.set(JS::GetRealmFunctionPrototype(cx));
} else {
const js::Class* clasp = js::GetObjectClass(obj);
MOZ_ASSERT(IsDOMIfaceAndProtoClass(clasp));
ProtoGetter protoGetter =
DOMIfaceAndProtoJSClass::FromJSClass(clasp)->mGetParentProto;
protop.set(protoGetter(cx));
}
}
@@ -2404,49 +2423,33 @@ XrayGetNativeProto(JSContext* cx, JS::Ha
}
extern NativePropertyHooks sEmptyNativePropertyHooks;
extern const js::ClassOps sBoringInterfaceObjectClassClassOps;
extern const js::ObjectOps sInterfaceObjectClassObjectOps;
-// We use one constructor JSNative to represent all DOM interface objects (so
-// we can easily detect when we need to wrap them in an Xray wrapper). We store
-// the real JSNative in the mNative member of a JSNativeHolder in the
-// CONSTRUCTOR_NATIVE_HOLDER_RESERVED_SLOT slot of the JSFunction object for a
-// specific interface object. We also store the NativeProperties in the
-// JSNativeHolder.
-// Note that some interface objects are not yet a JSFunction but a normal
-// JSObject with a DOMJSClass, those do not use these slots.
-
-enum {
- CONSTRUCTOR_NATIVE_HOLDER_RESERVED_SLOT = 0
-};
-
-bool
-Constructor(JSContext* cx, unsigned argc, JS::Value* vp);
-
inline bool
UseDOMXray(JSObject* obj)
{
const js::Class* clasp = js::GetObjectClass(obj);
return IsDOMClass(clasp) ||
JS_IsNativeFunction(obj, Constructor) ||
IsDOMIfaceAndProtoClass(clasp);
}
#ifdef DEBUG
inline bool
HasConstructor(JSObject* obj)
{
return JS_IsNativeFunction(obj, Constructor) ||
js::GetObjectClass(obj)->getConstruct();
}
- #endif
+#endif
// Helpers for creating a const version of a type.
template<typename T>
const T& Constify(T& arg)
{
return arg;
}
--- a/dom/bindings/test/chrome.ini
+++ b/dom/bindings/test/chrome.ini
@@ -19,8 +19,9 @@ support-files =
support-files =
file_focuser.html
file_fullScreenPropertyAccessor.html
skip-if = e10s # prerendering doesn't work in e10s yet
[test_kill_longrunning_prerendered_content.xul]
skip-if = e10s # prerendering doesn't work in e10s yet
[test_bug1123516_maplikesetlikechrome.xul]
skip-if = debug == false
+[test_bug1287912.html]
new file mode 100644
--- /dev/null
+++ b/dom/bindings/test/test_bug1287912.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1287912
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1287912</title>
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1287912">Mozilla Bug 1287912</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<iframe id="t" src="http://example.org/tests/dom/bindings/test/"></iframe>
+</div>
+<pre id="test">
+<script type="application/javascript">
+function test()
+{
+ var win = document.getElementById("t").contentWindow;
+ is(Object.getPrototypeOf(win.Image), win.Function.prototype, "The __proto__ of a named constructor is Function.prototype");
+ is(win.Image.prototype, win.HTMLImageElement.prototype, "The prototype property of a named constructor is the interface prototype object");
+ is(win.HTMLImageElement['foo'], undefined, "Should not have a property named foo on the HTMLImageElement interface object");
+ is(win.Image['foo'], undefined, "Should not have a property named foo on the Image named constructor");
+
+ SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(test);
+
+</script>
+</pre>
+</body>
+</html>