Bug 910220 - Part 2: Use the new API in codegen to only throw when needed. r=peterv, a=bajaj
authorBoris Zbarsky <bzbarsky@mit.edu>
Sat, 31 Aug 2013 00:21:28 -0400
changeset 153931 314b9508f907f4f26baef0d0cb646e97517424d1
parent 153930 24385c90c9ffd7bf6a540025974c6de664fc05b4
child 153932 9feb51769e20c50392cd6c950901e8deb1489fe4
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv, bajaj
bugs910220
milestone25.0a2
Bug 910220 - Part 2: Use the new API in codegen to only throw when needed. r=peterv, a=bajaj
dom/bindings/Codegen.py
dom/bindings/Errors.msg
dom/bindings/test/Makefile.in
dom/bindings/test/test_defineProperty.html
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -7388,19 +7388,19 @@ class CGDOMJSProxyHandler_defineProperty
                     "  *defined = true;" +
                     CGIndenter(CGProxyIndexedSetter(self.descriptor)).define() +
                     "  return true;\n" +
                     "}\n") % (self.descriptor.nativeType)
         elif self.descriptor.supportsIndexedProperties():
             # XXXbz Once this is fixed to only throw in strict mode, update the
             # code that decides whether to do a
             # CGDOMJSProxyHandler_defineProperty at all.
-            set += ("if (IsArrayIndex(GetArrayIndexFromId(cx, id))) {\n" +
-                    "  return ThrowErrorMessage(cx, MSG_NO_PROPERTY_SETTER, \"%s\");\n" +
-                    "}\n") % self.descriptor.name
+            set += ("if (IsArrayIndex(GetArrayIndexFromId(cx, id))) {\n"
+                    "  return js::IsInNonStrictPropertySet(cx) || ThrowErrorMessage(cx, MSG_NO_INDEXED_SETTER, \"%s\");\n"
+                    "}\n" % self.descriptor.name)
 
         if UseHolderForUnforgeable(self.descriptor):
             defineOnUnforgeable = ("JSBool hasUnforgeable;\n"
                                    "if (!JS_HasPropertyById(cx, ${holder}, id, &hasUnforgeable)) {\n"
                                    "  return false;\n"
                                    "}\n"
                                    "if (hasUnforgeable) {\n"
                                    "  *defined = true;" +
@@ -7424,18 +7424,18 @@ class CGDOMJSProxyHandler_defineProperty
             if self.descriptor.supportsNamedProperties():
                 # XXXbz Once this is fixed to only throw in strict mode, update
                 # the code that decides whether to do a
                 # CGDOMJSProxyHandler_defineProperty at all.  If we support
                 # indexed properties, we won't get down here for indices, so we
                 # can just do our setter unconditionally here.
                 set += (CGProxyNamedPresenceChecker(self.descriptor).define() + "\n" +
                         "if (found) {\n"
-                        "  return ThrowErrorMessage(cx, MSG_NO_PROPERTY_SETTER, \"%s\");\n"
-                        "}" % self.descriptor.name)
+                        "  return js::IsInNonStrictPropertySet(cx) || ThrowErrorMessage(cx, MSG_NO_NAMED_SETTER, \"%s\");\n"
+                        "}\n" % self.descriptor.name)
             set += ("return mozilla::dom::DOMProxyHandler::defineProperty(%s);" %
                     ", ".join(a.name for a in self.args))
         return set
 
 class CGDOMJSProxyHandler_delete(ClassMethod):
     def __init__(self, descriptor):
         args = [Argument('JSContext*', 'cx'), Argument('JS::Handle<JSObject*>', 'proxy'),
                 Argument('JS::Handle<jsid>', 'id'),
--- a/dom/bindings/Errors.msg
+++ b/dom/bindings/Errors.msg
@@ -25,17 +25,18 @@ MSG_DEF(MSG_NOT_OBJECT, 1, "{0} is not a
 MSG_DEF(MSG_NOT_CALLABLE, 1, "{0} is not callable.")
 MSG_DEF(MSG_DOES_NOT_IMPLEMENT_INTERFACE, 2, "{0} does not implement interface {1}.")
 MSG_DEF(MSG_METHOD_THIS_DOES_NOT_IMPLEMENT_INTERFACE, 2, "'{0}' called on an object that does not implement interface {1}.")
 MSG_DEF(MSG_GETTER_THIS_DOES_NOT_IMPLEMENT_INTERFACE, 2, "'{0}' getter called on an object that does not implement interface {1}.")
 MSG_DEF(MSG_SETTER_THIS_DOES_NOT_IMPLEMENT_INTERFACE, 2, "'{0}' setter called on an object that does not implement interface {1}.")
 MSG_DEF(MSG_THIS_DOES_NOT_IMPLEMENT_INTERFACE, 1, "\"this\" object does not implement interface {0}.")
 MSG_DEF(MSG_NOT_IN_UNION, 2, "{0} could not be converted to any of: {1}.")
 MSG_DEF(MSG_ILLEGAL_CONSTRUCTOR, 0, "Illegal constructor.")
-MSG_DEF(MSG_NO_PROPERTY_SETTER, 1, "{0} doesn't have an indexed property setter.")
+MSG_DEF(MSG_NO_INDEXED_SETTER, 1, "{0} doesn't have an indexed property setter.")
+MSG_DEF(MSG_NO_NAMED_SETTER, 1, "{0} doesn't have a named property setter.")
 MSG_DEF(MSG_ENFORCE_RANGE_NON_FINITE, 1, "Non-finite value is out of range for {0}.")
 MSG_DEF(MSG_ENFORCE_RANGE_OUT_OF_RANGE, 1, "Value is out of range for {0}.")
 MSG_DEF(MSG_NOT_SEQUENCE, 1, "{0} can't be converted to a sequence.")
 MSG_DEF(MSG_NOT_DICTIONARY, 1, "{0} can't be converted to a dictionary.")
 MSG_DEF(MSG_OVERLOAD_RESOLUTION_FAILED, 3, "Argument {0} is not valid for any of the {1}-argument overloads of {2}.")
 MSG_DEF(MSG_GLOBAL_NOT_NATIVE, 0, "Global is not a native object.")
 MSG_DEF(MSG_ENCODING_NOT_SUPPORTED, 1, "The given encoding '{0}' is not supported.")
 MSG_DEF(MSG_DOM_ENCODING_NOT_UTF, 0, "The encoding must be utf-8, utf-16, or utf-16be.")
--- a/dom/bindings/test/Makefile.in
+++ b/dom/bindings/test/Makefile.in
@@ -73,16 +73,17 @@ MOCHITEST_FILES := \
   test_bug852846.html \
   test_bug862092.html \
   test_bug560072.html \
   test_lenientThis.html \
   test_ByteString.html \
   test_exception_messages.html \
   test_bug707564.html \
   test_bug907548.html \
+  test_defineProperty.html \
   $(NULL)
 
 MOCHITEST_CHROME_FILES = \
   test_bug775543.html \
   test_bug707564-chrome.html \
   $(NULL)
 
 ifdef GNU_CC
new file mode 100644
--- /dev/null
+++ b/dom/bindings/test/test_defineProperty.html
@@ -0,0 +1,93 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=910220
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 910220</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=910220">Mozilla Bug 910220</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<form name="x"></form>
+</div>
+<pre id="test">
+</pre>
+<script type="application/javascript">
+
+/** Test for Bug 910220 **/
+
+function getX() {
+  return "x";
+}
+
+function namedSetStrict(obj) {
+  "use strict";
+  var threw;
+  try {
+    obj.x = 5;
+    threw = false;
+  } catch (e) {
+    threw = true;
+  }
+  ok(threw,
+     "Should throw in strict mode when setting named property on " + obj);
+
+  try {
+    obj[getX()] = 5;
+    threw = false;
+  } catch (e) {
+    threw = true;
+  }
+  ok(threw,
+     "Should throw in strict mode when setting named property via SETELEM on " + obj);
+
+  try {
+    Object.defineProperty(obj, "x", { value: 17 });
+    threw = false;
+  } catch (e) {
+    threw = true;
+  }
+  ok(threw,
+     "Should throw in strict mode when defining named property on " + obj);
+}
+function namedSetNonStrict(obj) {
+  var threw;
+  try {
+    obj.x = 5;
+    threw = false;
+  } catch (e) {
+    threw = true;
+  }
+  ok(!threw,
+     "Should not throw in non-strict mode when setting named property on " + obj);
+
+  try {
+    obj[getX()] = 5;
+    threw = false;
+  } catch (e) {
+    threw = true;
+  }
+  ok(!threw,
+     "Should not throw in non-strict mode when setting named property via SETELEM on" + obj);
+
+  try {
+    Object.defineProperty(obj, "x", { value: 17 });
+    threw = false;
+  } catch (e) {
+    threw = true;
+  }
+  ok(threw,
+     "Should throw in non-strict mode when defining named property on " + obj);
+}
+for (var obj of [ document ]) {
+  namedSetStrict(obj);
+  namedSetNonStrict(obj);
+}
+</script>
+</body>
+</html>