Bug 484180 - Don't call the class getter (especially not the scriptable helper!) for functions. r+sr=jst
authorBlake Kaplan <mrbkap@gmail.com>
Fri, 17 Apr 2009 16:52:10 -0700
changeset 25128 e0820d781d663c95aab46f27af464fb7ccfc9ccb
parent 25127 e891045515ec328622f2ee23b3f9f2957babe126
child 25129 83b8bdf6ef4b240405046f641824578cc9f445f1
push id1374
push usermrbkap@mozilla.com
push dateFri, 08 May 2009 21:03:57 +0000
bugs484180
milestone1.9.1b5pre
Bug 484180 - Don't call the class getter (especially not the scriptable helper!) for functions. r+sr=jst
dom/tests/mochitest/localstorage/test_localStorageFromChrome.xhtml
js/src/xpconnect/src/XPCWrapper.cpp
--- a/dom/tests/mochitest/localstorage/test_localStorageFromChrome.xhtml
+++ b/dom/tests/mochitest/localstorage/test_localStorageFromChrome.xhtml
@@ -17,22 +17,22 @@ function startTest()
     .getService(Components.interfaces.nsIScriptSecurityManager);
   var dsm = Components.classes["@mozilla.org/dom/storagemanager;1"]
     .getService(Components.interfaces.nsIDOMStorageManager);
 
   var uri = ios.newURI(url, "", null);
   var principal = ssm.getCodebasePrincipal(uri);
   var storage = dsm.getLocalStorageForPrincipal(principal);
 
-  storage.wrappedJSObject.setItem("chromekey", "chromevalue");
+  storage.setItem("chromekey", "chromevalue");
 
   var aframe = document.getElementById("aframe");
   aframe.onload = function()
   {
-    is(storage.wrappedJSObject.getItem("chromekey"), "chromevalue");
+    is(storage.getItem("chromekey"), "chromevalue");
     is(aframe.contentDocument.getElementById("data").innerHTML, "chromevalue");
     SimpleTest.finish();
   }
   aframe.src = "http://example.com/tests/dom/tests/mochitest/localstorage/frameChromeSlave.html";
 }
 
 SimpleTest.waitForExplicitFinish();
 
--- a/js/src/xpconnect/src/XPCWrapper.cpp
+++ b/js/src/xpconnect/src/XPCWrapper.cpp
@@ -474,16 +474,18 @@ XPCWrapper::ResolveNativeProperty(JSCont
   if (!str) {
     return ThrowException(NS_ERROR_UNEXPECTED, cx);
   }
 
   // Get (and perhaps lazily create) the member's value (commonly a
   // cloneable function).
   jsval v;
   uintN attrs = JSPROP_ENUMERATE;
+  JSPropertyOp getter = nsnull;
+  JSPropertyOp setter = nsnull;
 
   if (member->IsConstant()) {
     if (!member->GetConstantValue(ccx, iface, &v)) {
       return ThrowException(NS_ERROR_XPC_BAD_CONVERT_JS, cx);
     }
   } else if (member->IsAttribute()) {
     // An attribute is being resolved. Define the property, the value
     // will be dealt with in the get/set hooks.  Use JSPROP_SHARED to
@@ -509,33 +511,40 @@ XPCWrapper::ResolveNativeProperty(JSCont
     printf("Wrapping function object for %s\n",
            ::JS_GetStringBytes(JSVAL_TO_STRING(id)));
 #endif
 
     if (!WrapFunction(cx, wrapperObj, JSVAL_TO_OBJECT(funval), &v,
                       isNativeWrapper)) {
       return JS_FALSE;
     }
+
+    // Functions shouldn't have a getter or a setter. Without the wrappers,
+    // they would live on the prototype (and call its getter), since we don't
+    // have a prototype, and we need to avoid calling the scriptable helper's
+    // GetProperty method for this property, stub out the getters and setters
+    // explicitly.
+    getter = setter = JS_PropertyStub;
   }
 
   // Make sure v doesn't go away while we mess with it.
   AUTO_MARK_JSVAL(ccx, v);
 
   // XPCNativeWrapper doesn't need to do this.
   jsval oldFlags;
   if (!isNativeWrapper &&
       (!::JS_GetReservedSlot(cx, wrapperObj, sFlagsSlot, &oldFlags) ||
        !::JS_SetReservedSlot(cx, wrapperObj, sFlagsSlot,
                              INT_TO_JSVAL(JSVAL_TO_INT(oldFlags) |
                                           FLAG_RESOLVING)))) {
     return JS_FALSE;
   }
 
   if (!::JS_DefineUCProperty(cx, wrapperObj, ::JS_GetStringChars(str),
-                            ::JS_GetStringLength(str), v, nsnull, nsnull,
+                            ::JS_GetStringLength(str), v, getter, setter,
                             attrs)) {
     return JS_FALSE;
   }
 
   if (!isNativeWrapper &&
       !::JS_SetReservedSlot(cx, wrapperObj, sFlagsSlot, oldFlags)) {
     return JS_FALSE;
   }