Bug 1287912. r=bz
authorPeter Van der Beken <peterv@propagandism.org>
Wed, 23 Nov 2016 16:58:59 -0500
changeset 324129 3a6f55d3d0f40784ba1463ed9250eceb04faeff2
parent 324128 5d426f7715924e0600c4bff3414d09aa5b2e7e9d
child 324130 55405164269f027b2e028d56b10c8aa5261b997f
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewersbz
bugs1287912
milestone53.0a1
Bug 1287912. r=bz
dom/bindings/BindingUtils.h
dom/bindings/test/chrome.ini
dom/bindings/test/test_bug1287912.html
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -2304,16 +2304,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.
@@ -2377,16 +2393,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));
     }
   }
@@ -2443,49 +2462,33 @@ GetCachedSlotStorageObject(JSContext* cx
 }
 
 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
@@ -14,8 +14,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>