Bug 1081037 - LinkConstructorAndPrototype in RegisterElement. r=wchen
authorGabor Krizsanits <gkrizsanits@mozilla.com>
Mon, 15 Dec 2014 11:28:54 +0100
changeset 219676 f662a378f18d
parent 219675 ca218faa12dd
child 219677 4d9be695d380
push id52905
push usergkrizsanits@mozilla.com
push dateMon, 15 Dec 2014 10:29:45 +0000
treeherdermozilla-inbound@f662a378f18d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerswchen
bugs1081037
milestone37.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1081037 - LinkConstructorAndPrototype in RegisterElement. r=wchen
dom/base/nsDocument.cpp
dom/html/test/mochitest.ini
dom/html/test/test_bug1081037.html
testing/web-platform/meta/custom-elements/creating-and-passing-registries/share-registry-create-document.html.ini
testing/web-platform/meta/custom-elements/custom-element-lifecycle/types-of-callbacks/created-callback-element-prototype-test.html.ini
testing/web-platform/meta/custom-elements/instantiating-custom-elements/changing-is-attribute.html.ini
testing/web-platform/meta/custom-elements/instantiating-custom-elements/custom-element-type-local-name-and-is-attribute.html.ini
testing/web-platform/meta/custom-elements/instantiating-custom-elements/custom-element-type-local-name.html.ini
testing/web-platform/meta/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-interface-type-is-a-local-name.html.ini
testing/web-platform/meta/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-type-is-a-local-name.html.ini
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -6260,17 +6260,23 @@ nsDocument::RegisterElement(JSContext* a
   JSFunction* constructor = JS_NewFunction(aCx, nsDocument::CustomElementConstructor, 0,
                                            JSFUN_CONSTRUCTOR, JS::NullPtr(),
                                            NS_ConvertUTF16toUTF8(lcType).get());
   if (!constructor) {
     rv.Throw(NS_ERROR_OUT_OF_MEMORY);
     return;
   }
 
-  aRetval.set(JS_GetFunctionObject(constructor));
+  JS::Rooted<JSObject*> constructorObj(aCx, JS_GetFunctionObject(constructor));
+  if (!JS_LinkConstructorAndPrototype(aCx, constructorObj, protoObject)) {
+    rv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
+    return;
+  }
+
+  aRetval.set(constructorObj);
 }
 
 void
 nsDocument::UseRegistryFromDocument(nsIDocument* aDocument)
 {
   nsDocument* doc = static_cast<nsDocument*>(aDocument);
   MOZ_ASSERT(!mRegistry, "There should be no existing registry.");
   mRegistry = doc->mRegistry;
--- a/dom/html/test/mochitest.ini
+++ b/dom/html/test/mochitest.ini
@@ -573,9 +573,10 @@ skip-if = toolkit == 'android'
 skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e10s # b2g(needs control of popup window size) b2g-debug(needs control of popup window size) b2g-desktop(needs control of popup window size)
 [test_non-ascii-cookie.html]
 skip-if = buildapp == 'b2g' || e10s
 [test_bug765780.html]
 [test_bug871161.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || e10s #Bug 931116, b2g desktop specific, initial triage
 support-files = file_bug871161-1.html file_bug871161-2.html
 [test_bug1013316.html]
+[test_bug1081037.html]
 
new file mode 100644
--- /dev/null
+++ b/dom/html/test/test_bug1081037.html
@@ -0,0 +1,142 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1081037
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 1081037</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="application/javascript">
+
+  /** Test for Bug 1081037 **/
+
+function shouldThrow(fun, msg, ex, todo) {
+  try {
+    fun();
+    ok(todo, msg);
+  } catch (e) {
+    ok(new RegExp(ex).test(e), msg + " (thrown:" + e + ")")
+  }
+}
+
+var Foo = document.registerElement('x-foo', {
+  prototype: {bar: 5}
+});
+
+Foo.prototype.bar = 6;
+var foo = new Foo();
+is(foo.bar, 6, "prototype of the ctor returned from registerElement works");
+
+var protoDesc = Object.getOwnPropertyDescriptor(Foo, "prototype");
+is(protoDesc.configurable, false, "proto should be non-configurable");
+is(protoDesc.enumerable, false, "proto should be non-enumerable");
+is(protoDesc.writable, false, "proto should be non-writable");
+
+// TODO: FIXME!
+shouldThrow(function() {
+              document.registerElement('x-foo2', {
+                prototype: Foo.prototype
+              });
+            },
+            "if proto is an interface prototype object, registerElement should throw",
+            "not supported",
+            /* todo = */ true);
+
+var nonConfigReadonlyProto = Object.create(HTMLElement.prototype,
+  { constructor: { configurable: false, writable: false, value: 42 } });
+
+shouldThrow(function() {
+              document.registerElement('x-nonconfig-readonly', {
+                prototype: nonConfigReadonlyProto
+              });
+            },
+            "non-configurable and not-writable constructor property",
+            "not supported");
+
+
+// this is not defined in current spec:
+var readonlyProto = Object.create(HTMLElement.prototype,
+  { constructor: { configurable: true, writable: false, value: 42 } });
+
+var Readonly = document.registerElement('x-nonconfig-readonly', {
+  prototype: readonlyProto
+});
+
+is(Readonly.prototype, readonlyProto, "configurable readonly constructor property");
+
+var handler = {
+  getOwnPropertyDescriptor: function(target, name) {
+    return name == "constructor" ? undefined : Object.getOwnPropertyDescriptor(target,name);
+  },
+  defineProperty: function(target, name, propertyDescriptor) {
+     if (name == "constructor") {
+      throw "spec this";
+    }
+
+    return Object.defineProperty(target, name, propertyDescriptor);
+  },
+  has: function(target, name) {
+    if (name == "constructor") {
+      return false;
+    }
+    return name in target;
+  }
+};
+var proxy = new Proxy({}, handler);
+
+shouldThrow(function() {
+              document.registerElement('x-proxymagic', {
+                prototype: proxy
+              });
+            },
+            "proxy magic",
+            "spec this");
+
+var getOwn = 0;
+var defineProp = 0;
+var _has = 0;
+var handler2 = {
+  getOwnPropertyDescriptor: function(target, name) {
+    if (name == "constructor") {
+      getOwn++;
+    }
+    return Object.getOwnPropertyDescriptor(target,name);
+  },
+  defineProperty: function(target, name, propertyDescriptor) {
+    if (name == "constructor") {
+      defineProp++;
+    }
+    return Object.defineProperty(target, name, propertyDescriptor);
+  },
+  has: function(target, name) {
+    if (name == "constructor") {
+      _has++;
+    }
+    return name in target;
+  }
+};
+var proxy2 = new Proxy({}, handler2);
+
+document.registerElement('x-proxymagic2', {
+  prototype: proxy2
+});
+
+is(getOwn, 1, "number of getOwnPropertyDescriptor calls from registerElement: " + getOwn);
+is(defineProp, 1, "number of defineProperty calls from registerElement: " + defineProp);
+is(_has, 1, "number of 'has' calls from registerElement: " + _has);
+
+
+  </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1081037">Mozilla Bug 1081037</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
\ No newline at end of file
--- a/testing/web-platform/meta/custom-elements/creating-and-passing-registries/share-registry-create-document.html.ini
+++ b/testing/web-platform/meta/custom-elements/creating-and-passing-registries/share-registry-create-document.html.ini
@@ -1,8 +1,6 @@
 [share-registry-create-document.html]
   type: testharness
-  [Document created by createHTMLDocument should share an existing registry]
-    expected: FAIL
 
   [Document created by createDocument with HTML namespace should share an existing registry]
     expected: FAIL
 
--- a/testing/web-platform/meta/custom-elements/custom-element-lifecycle/types-of-callbacks/created-callback-element-prototype-test.html.ini
+++ b/testing/web-platform/meta/custom-elements/custom-element-lifecycle/types-of-callbacks/created-callback-element-prototype-test.html.ini
@@ -1,20 +1,5 @@
 [created-callback-element-prototype-test.html]
   type: testharness
-  [Test custom element prototype inside created callback when custom element is created in HTML before registration of a custom element]
-    expected: FAIL
 
-  [Test custom element prototype inside created callback when custom element is created in HTML after registration of a custom element]
-    expected: FAIL
-
-  [Test custom element prototype inside created callback when custom element is created via document.createElement() before registration of a custom element]
+  [Document created by createHTMLDocument should share an existing registry]
     expected: FAIL
-
-  [Test custom element prototype inside created callback when custom element is created via document.createElement() after registration of a custom element]
-    expected: FAIL
-
-  [Test custom element prototype inside created callback when custom element is created via constructor returned by method registerElement]
-    expected: FAIL
-
-  [Test custom element prototype inside created callback when custom element is created by UA parser before registration of a custom element]
-    expected: FAIL
-
--- a/testing/web-platform/meta/custom-elements/instantiating-custom-elements/changing-is-attribute.html.ini
+++ b/testing/web-platform/meta/custom-elements/instantiating-custom-elements/changing-is-attribute.html.ini
@@ -1,29 +1,7 @@
 [changing-is-attribute.html]
   type: testharness
-  [Test custom element type, after assigning IS attribute value. Element is created by constructor]
-    expected: FAIL
-
-  [Test custom element type, after assigning IS attribute value. Element is created via innerHTML property]
-    expected: FAIL
-
-  [Test custom element type, after assigning IS attribute value to unresolved element. Element is created via innerHTML property]
-    expected: FAIL
-
-  [Test custom element type, after assigning IS attribute value. Element is defined in loaded HTML document]
-    expected: FAIL
-
-  [Test custom element type, after assigning IS attribute value to unresolved element. Element is defined in loaded HTML document]
-    expected: FAIL
-
   [Test custom element type after changing IS attribute value. Element is HTML5 element with IS attribute referring to custom element type]
     expected: FAIL
 
   [Test custom element type after changing IS attribute value several times. Element is HTML5 element with IS attribute referring to custom element type]
     expected: FAIL
-
-  [Test custom element type, after removing IS attribute value. Element is created via innerHTML property]
-    expected: FAIL
-
-  [Test custom element type, after removing IS attribute value. Element is HTML5 element with IS attribute referring to custom element type]
-    expected: FAIL
-
--- a/testing/web-platform/meta/custom-elements/instantiating-custom-elements/custom-element-type-local-name-and-is-attribute.html.ini
+++ b/testing/web-platform/meta/custom-elements/instantiating-custom-elements/custom-element-type-local-name-and-is-attribute.html.ini
@@ -1,17 +1,11 @@
 [custom-element-type-local-name-and-is-attribute.html]
   type: testharness
-  [Custom element type must be taken from the local name of the element even if IS attribute provided.]
-    expected: FAIL
-
-  [Custom element type must be taken from the local name of the element even if IS attribute provided. Custom element is unresolved at first]
-    expected: FAIL
-
-  [Custom element type must be taken from the local name of the element even if IS attribute provided. There\'s no definition for the value of IS attribute at first]
-    expected: FAIL
 
   [Custom element type must be taken from the local name of the element even if IS attribute provided. IS attribute refers to another custom element type, which extends HTML5 elements]
     expected: FAIL
 
   [Custom element type must be taken from the local name of the custom element even if IS attribute provided. The element extends HTML5 elements, IS attribute refers to another custom element type.]
     expected: FAIL
 
+  [Test custom element type after changing IS attribute value. Element is HTML5 element with IS attribute referring to custom element type]
+    expected: FAIL
deleted file mode 100644
--- a/testing/web-platform/meta/custom-elements/instantiating-custom-elements/custom-element-type-local-name.html.ini
+++ /dev/null
@@ -1,8 +0,0 @@
-[custom-element-type-local-name.html]
-  type: testharness
-  [Test custom element type, which is given via the local name of the custom element. Custom element created via innerHTML property]
-    expected: FAIL
-
-  [Test custom element type, which is given via the local name of the custom element. Custom element is defined in loaded HTML document]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-interface-type-is-a-local-name.html.ini
+++ /dev/null
@@ -1,8 +0,0 @@
-[create-element-interface-type-is-a-local-name.html]
-  type: testharness
-  [Test Document.createElement() creates custom element of type, specified by localName argument, if an element definition with matching localName, namespace, and type is not registered]
-    expected: FAIL
-
-  [Test Document.createElementNS() creates custom element of type, specified by localName argument, if an element definition with matching localName, namespace, and type is not registered]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-type-is-a-local-name.html.ini
+++ /dev/null
@@ -1,8 +0,0 @@
-[create-element-type-is-a-local-name.html]
-  type: testharness
-  [Test Document.createElement() creates custom element of type, specified by single localName argument]
-    expected: FAIL
-
-  [Test Document.createElementNS() creates custom element of type, specified by localName argument. Argument typeExtension is not passed]
-    expected: FAIL
-