Bug 768750 - Make FieldSetter always set a return value. r=bz
authorJeff Walden <jwalden@mit.edu>
Wed, 17 Oct 2012 13:42:58 -0700
changeset 111407 c6b6895b0db60fc294a167d5ea6b17748b57227d
parent 111406 67db046bd148781238131d518f1008620677eb49
child 111408 fae81f4e7a9b4526af487664c92d176d4716e01f
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersbz
bugs768750
milestone19.0a1
Bug 768750 - Make FieldSetter always set a return value. r=bz
content/xbl/crashtests/crashtests.list
content/xbl/crashtests/set-field-bad-this.xhtml
content/xbl/src/nsXBLBinding.cpp
--- a/content/xbl/crashtests/crashtests.list
+++ b/content/xbl/crashtests/crashtests.list
@@ -30,8 +30,9 @@ load 463511-1.xhtml
 load 464863-1.xhtml
 load 472260-1.xhtml
 load 477878-1.html
 load 492978-1.xul
 asserts-if(Android,2) load 493123-1.xhtml
 load 495354-1.xhtml
 load 507628-1.xhtml
 load 507991-1.xhtml
+load set-field-bad-this.xhtml
new file mode 100644
--- /dev/null
+++ b/content/xbl/crashtests/set-field-bad-this.xhtml
@@ -0,0 +1,31 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+<head>
+  <title>Gracefully handle setting a field on a bad |this|</title>
+
+  <bindings xmlns="http://www.mozilla.org/xbl">
+    <binding id="a">
+      <implementation>
+        <field name="f">17</field>
+      </implementation>
+    </binding>
+  </bindings>
+
+  <script type="application/javascript">
+    window.onload = function()
+    {
+      var bound = document.getElementById("bound");
+      try
+      {
+        Object.getPrototypeOf(bound).f = 42;
+      }
+      catch (e) { /* Throwing's fine, crashing isn't. */ }
+    };
+  </script>
+</head>
+
+<body>
+  <div id="bound" style="-moz-binding: url(#a)"></div>
+</body>
+
+</html>
--- a/content/xbl/src/nsXBLBinding.cpp
+++ b/content/xbl/src/nsXBLBinding.cpp
@@ -257,19 +257,25 @@ FieldSetterImpl(JSContext *cx, JS::CallA
 
   bool installed = false;
   js::Rooted<JSObject*> callee(cx, &args.calleev().toObject());
   js::Rooted<jsid> id(cx);
   if (!InstallXBLField(cx, callee, thisObj, id.address(), &installed)) {
     return false;
   }
 
-  js::Rooted<JS::Value> v(cx,
-                          args.length() > 0 ? args[0] : JS::UndefinedValue());
-  return JS_SetPropertyById(cx, thisObj, id, v.address());
+  if (installed) {
+    js::Rooted<JS::Value> v(cx,
+                            args.length() > 0 ? args[0] : JS::UndefinedValue());
+    if (!::JS_SetPropertyById(cx, thisObj, id, v.address())) {
+      return false;
+    }
+  }
+  args.rval().setUndefined();
+  return true;
 }
 
 static JSBool
 FieldSetter(JSContext *cx, unsigned argc, JS::Value *vp)
 {
   JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   return JS::CallNonGenericMethod<ValueHasISupportsPrivate, FieldSetterImpl>
                                  (cx, args);