Bug 910220 part 2. Use the new API in codegen to only throw when needed. r=peterv
authorBoris Zbarsky <bzbarsky@mit.edu>
Sat, 31 Aug 2013 00:21:28 -0400
changeset 158073 a3a28c1a96a7df12b1523cbb16de66a24dbb9351
parent 158072 f6e727237de21bc57321be9d5ce8114c8ea92774
child 158074 b24700fc8592fc5e88c77df80dbcc9695b1fb1f9
push id2961
push userlsblakk@mozilla.com
push dateMon, 28 Oct 2013 21:59:28 +0000
treeherdermozilla-beta@73ef4f13486f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv
bugs910220
milestone26.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 910220 part 2. Use the new API in codegen to only throw when needed. r=peterv
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
@@ -7374,19 +7374,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 = ("bool hasUnforgeable;\n"
                                    "if (!JS_HasPropertyById(cx, ${holder}, id, &hasUnforgeable)) {\n"
                                    "  return false;\n"
                                    "}\n"
                                    "if (hasUnforgeable) {\n"
                                    "  *defined = true;" +
@@ -7410,18 +7410,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
@@ -71,16 +71,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>