Bug 792215. Convert quickstubs to using JSNative getters and setters. r=peterv
authorBoris Zbarsky <bzbarsky@mit.edu>
Tue, 25 Sep 2012 14:44:40 -0400
changeset 126877 dc6c1d4bff95458ac95234c8a1b0a599f3332209
parent 126876 36e1ab8c7de08c4d4a2c8384c8413434264d6dee
child 126878 592316b9ce804a7382cebee3ae34382f5ea04242
push id25701
push userbzbarsky@mozilla.com
push dateMon, 01 Apr 2013 21:18:20 +0000
treeherdermozilla-inbound@c3b41432afea [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv
bugs792215
milestone23.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 792215. Convert quickstubs to using JSNative getters and setters. r=peterv
browser/base/content/browser.js
browser/base/content/content.js
browser/base/content/test/browser_bug521216.js
browser/components/tabview/content.js
browser/components/test/browser_bug538331.js
dom/tests/mochitest/bugs/test_bug541530.html
js/xpconnect/src/XPCQuickStubs.cpp
js/xpconnect/src/XPCQuickStubs.h
js/xpconnect/src/qsgen.py
js/xpconnect/tests/mochitest/test_bug428021.html
toolkit/components/search/nsSearchService.js
toolkit/components/viewsource/content/viewSource.js
toolkit/content/globalOverlay.js
toolkit/mozapps/downloads/DownloadUtils.jsm
toolkit/mozapps/extensions/LightweightThemeManager.jsm
toolkit/mozapps/extensions/content/extensions.js
toolkit/mozapps/update/test/chrome/utils.js
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -60,31 +60,31 @@ XPCOMUtils.defineLazyGetter(window, "gFi
   window.gFindBarInitialized = true;
   return findbar;
 });
 
 XPCOMUtils.defineLazyGetter(this, "gPrefService", function() {
   return Services.prefs;
 });
 
-__defineGetter__("AddonManager", function() {
+this.__defineGetter__("AddonManager", function() {
   let tmp = {};
   Cu.import("resource://gre/modules/AddonManager.jsm", tmp);
   return this.AddonManager = tmp.AddonManager;
 });
-__defineSetter__("AddonManager", function (val) {
+this.__defineSetter__("AddonManager", function (val) {
   delete this.AddonManager;
   return this.AddonManager = val;
 });
 
-__defineGetter__("PluralForm", function() {
+this.__defineGetter__("PluralForm", function() {
   Cu.import("resource://gre/modules/PluralForm.jsm");
   return this.PluralForm;
 });
-__defineSetter__("PluralForm", function (val) {
+this.__defineSetter__("PluralForm", function (val) {
   delete this.PluralForm;
   return this.PluralForm = val;
 });
 
 XPCOMUtils.defineLazyModuleGetter(this, "TelemetryStopwatch",
   "resource://gre/modules/TelemetryStopwatch.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "AboutHomeUtils",
@@ -3745,17 +3745,17 @@ function BrowserToolboxCustomizeDone(aTo
 
 #ifndef XP_MACOSX
     updateEditUIVisibility();
 #endif
 
     // Hacky: update the PopupNotifications' object's reference to the iconBox,
     // if it already exists, since it may have changed if the URL bar was
     // added/removed.
-    if (!__lookupGetter__("PopupNotifications"))
+    if (!window.__lookupGetter__("PopupNotifications"))
       PopupNotifications.iconBox = document.getElementById("notification-popup-box");
   }
 
   PlacesToolbarHelper.customizeDone();
   BookmarksMenuButton.customizeDone();
   DownloadsButton.customizeDone();
 
   // The url bar splitter state is dependent on whether stop/reload
--- a/browser/base/content/content.js
+++ b/browser/base/content/content.js
@@ -4,17 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 let Cc = Components.classes;
 let Ci = Components.interfaces;
 let Cu = Components.utils;
 
 // Bug 671101 - directly using webNavigation in this context
 // causes docshells to leak
-__defineGetter__("webNavigation", function () {
+this.__defineGetter__("webNavigation", function () {
   return docShell.QueryInterface(Ci.nsIWebNavigation);
 });
 
 addMessageListener("WebNavigation:LoadURI", function (message) {
   let flags = message.json.flags || webNavigation.LOAD_FLAGS_NONE;
 
   webNavigation.loadURI(message.json.uri, flags, null, null, null);
 });
--- a/browser/base/content/test/browser_bug521216.js
+++ b/browser/base/content/test/browser_bug521216.js
@@ -1,12 +1,12 @@
 var expected = ["TabOpen", "onStateChange", "onLocationChange", "onLinkIconAvailable"];
 var actual = [];
 var tabIndex = -1;
-__defineGetter__("tab", function () gBrowser.tabs[tabIndex]);
+this.__defineGetter__("tab", function () gBrowser.tabs[tabIndex]);
 
 function test() {
   waitForExplicitFinish();
   tabIndex = gBrowser.tabs.length;
   gBrowser.addTabsProgressListener(progressListener);
   gBrowser.tabContainer.addEventListener("TabOpen", TabOpen, false);
   gBrowser.addTab("data:text/html,<html><head><link href='about:logo' rel='shortcut icon'>");
 }
--- a/browser/components/tabview/content.js
+++ b/browser/components/tabview/content.js
@@ -5,17 +5,17 @@
 "use strict";
 
 let Cu = Components.utils;
 
 Cu.import("resource:///modules/tabview/utils.jsm");
 
 // Bug 671101 - directly using webProgress in this context
 // causes docShells to leak
-__defineGetter__("webProgress", function () {
+this.__defineGetter__("webProgress", function () {
   let ifaceReq = docShell.QueryInterface(Ci.nsIInterfaceRequestor);
   return ifaceReq.getInterface(Ci.nsIWebProgress);
 });
 
 // ----------
 // WindowEventHandler
 //
 // Handles events dispatched by the content window.
--- a/browser/components/test/browser_bug538331.js
+++ b/browser/components/test/browser_bug538331.js
@@ -102,17 +102,17 @@ const BCH_TESTS = [
                  "for actions and openURL",
     actions: "silent showURL showAlert showNotification"
   }
 ];
 
 var gOriginalMStone;
 var gOriginalOverrideURL;
 
-__defineGetter__("gBG", function() {
+this.__defineGetter__("gBG", function() {
   delete this.gBG;
   return this.gBG = Cc["@mozilla.org/browser/browserglue;1"].
                     getService(Ci.nsIBrowserGlue).
                     QueryInterface(Ci.nsIObserver);
 });
 
 function test()
 {
--- a/dom/tests/mochitest/bugs/test_bug541530.html
+++ b/dom/tests/mochitest/bugs/test_bug541530.html
@@ -23,64 +23,64 @@ var origLocation = location;
 
 ok(window === orig, "can't override window");
 ok(window.location === location, "properties are properly aliased");
 ok(document.location === location, "properties are properly aliased");
 
 var canDefine = false;
 try {
     var foo;
-    __defineGetter__.call(foo, 'bar', function() {});
-    __defineSetter__.call(foo, 'bar', function() {});
+    this.__defineGetter__.call(foo, 'bar', function() {});
+    this.__defineSetter__.call(foo, 'bar', function() {});
     canDefine = true;
 } catch (e) {}
 ok(canDefine, "Should have access to __defineGetter__ and __defineSetter__");
 
 try {
-    __defineGetter__('window', function() {});
+    this.__defineGetter__('window', function() {});
     ok(false, "should not be able to defineGetter(window)");
 } catch (e) {
 }
 
 try {
-    __defineGetter__.call(window, 'location', function(){});
+    this.__defineGetter__.call(window, 'location', function(){});
     ok(false, "should not be able to defineGetter(window.location)");
 } catch (e) {
 }
 
 try {
-    __defineGetter__.call(window.location, 'href', function(){});
+    this.__defineGetter__.call(window.location, 'href', function(){});
     ok(false, "shouldn't be able to override location.href");
 } catch (e) {
     ok(/shadow/.exec(e.message), "Should be caught by the anti-shadow mechanism.");
 }
 
 // Try deleting the property.
 delete window.location.href;
 ok(typeof window.location.href !== 'undefined',
    "shouldn't be able to delete the inherited property");
 delete Object.getPrototypeOf(window.location).href;
 ok(typeof window.location.href !== 'undefined',
    "shouldn't be able to delete the property off of the prototype");
 
 try {
-    __defineGetter__.call(Object.getPrototypeOf(window.location), 'href', function(){});
+    this.__defineGetter__.call(Object.getPrototypeOf(window.location), 'href', function(){});
     ok(false, "shouldn't be able to use the prototype");
 } catch (e) {
 }
 
 try {
-    __defineSetter__.call(window.location, 'href', function(){});
+    this.__defineSetter__.call(window.location, 'href', function(){});
     ok(false, "overrode a setter for location.href?");
 } catch (e) {
     ok(/shadow/.exec(e.message), "Should be caught by the anti-shadow mechanism.");
 }
 
 try {
-    __defineGetter__.call(document, 'location', function(){});
+    this.__defineGetter__.call(document, 'location', function(){});
     ok(false, "shouldn't be able to override document.location");
 } catch (e) {
 }
 
 ok(window === orig, "can't override window");
 ok(window.location === origLocation, "properties are properly aliased");
 ok(document.location === origLocation, "properties are properly aliased");
 
--- a/js/xpconnect/src/XPCQuickStubs.cpp
+++ b/js/xpconnect/src/XPCQuickStubs.cpp
@@ -11,16 +11,18 @@
 #include "xpcprivate.h"
 #include "XPCInlines.h"
 #include "XPCQuickStubs.h"
 #include "XPCWrapper.h"
 #include "mozilla/dom/BindingUtils.h"
 
 using namespace mozilla;
 
+extern const char* xpc_qsStringTable;
+
 static inline QITableEntry *
 GetOffsets(nsISupports *identity, XPCWrappedNativeProto* proto)
 {
     QITableEntry* offsets = proto ? proto->GetOffsets() : nullptr;
     if (!offsets) {
         static NS_DEFINE_IID(kThisPtrOffsetsSID, NS_THISPTROFFSETS_SID);
         identity->QueryInterface(kThisPtrOffsetsSID, (void**)&offsets);
     }
@@ -92,191 +94,16 @@ PointerFinalize(JSFreeOp *fop, JSObject 
 
 JSClass
 PointerHolderClass = {
     "Pointer", JSCLASS_HAS_PRIVATE,
     JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
     JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, PointerFinalize
 };
 
-static JSBool
-ReifyPropertyOps(JSContext *cx, JSObject *obj, jsid id, unsigned orig_attrs,
-                 JSPropertyOp getter, JSStrictPropertyOp setter,
-                 JSObject **getterobjp, JSObject **setterobjp)
-{
-    // Generate both getter and setter and stash them in the prototype.
-    jsval roots[2] = { JSVAL_NULL, JSVAL_NULL };
-    JS::AutoArrayRooter tvr(cx, ArrayLength(roots), roots);
-
-    unsigned attrs = JSPROP_SHARED | (orig_attrs & JSPROP_ENUMERATE);
-    JSObject *getterobj;
-    if (getter) {
-        getterobj = GeneratePropertyOp(cx, obj, id, 0, getter);
-        if (!getterobj)
-            return false;
-        roots[0] = OBJECT_TO_JSVAL(getterobj);
-        attrs |= JSPROP_GETTER;
-    } else
-        getterobj = nullptr;
-
-    JSObject *setterobj;
-    if (setter) {
-        setterobj = GeneratePropertyOp(cx, obj, id, 1, setter);
-        if (!setterobj)
-            return false;
-        roots[1] = OBJECT_TO_JSVAL(setterobj);
-        attrs |= JSPROP_SETTER;
-    } else
-        setterobj = nullptr;
-
-    if (getterobjp)
-        *getterobjp = getterobj;
-    if (setterobjp)
-        *setterobjp = setterobj;
-    return JS_DefinePropertyById(cx, obj, id, JSVAL_VOID,
-                                 JS_DATA_TO_FUNC_PTR(JSPropertyOp, getterobj),
-                                 JS_DATA_TO_FUNC_PTR(JSStrictPropertyOp, setterobj),
-                                 attrs);
-}
-
-static JSBool
-LookupGetterOrSetter(JSContext *cx, JSBool wantGetter, unsigned argc, jsval *vp)
-{
-    XPC_QS_ASSERT_CONTEXT_OK(cx);
-
-    if (argc == 0) {
-        JS_SET_RVAL(cx, vp, JSVAL_VOID);
-        return true;
-    }
-
-    JSObject *obj = JS_THIS_OBJECT(cx, vp);
-    if (!obj)
-        return false;
-
-    jsval idval = JS_ARGV(cx, vp)[0];
-    jsid id;
-    JSPropertyDescriptor desc;
-    if (!JS_ValueToId(cx, idval, &id) ||
-        !JS_GetPropertyDescriptorById(cx, obj, id, 0, &desc))
-        return false;
-
-    // No property at all means no getters or setters possible.
-    if (!desc.obj) {
-        JS_SET_RVAL(cx, vp, JSVAL_VOID);
-        return true;
-    }
-
-    // Inline obj_lookup[GS]etter here.
-    if (wantGetter) {
-        if (desc.attrs & JSPROP_GETTER) {
-            JS_SET_RVAL(cx, vp,
-                        OBJECT_TO_JSVAL(JS_FUNC_TO_DATA_PTR(JSObject *, desc.getter)));
-            return true;
-        }
-    } else {
-        if (desc.attrs & JSPROP_SETTER) {
-            JS_SET_RVAL(cx, vp,
-                        OBJECT_TO_JSVAL(JS_FUNC_TO_DATA_PTR(JSObject *, desc.setter)));
-            return true;
-        }
-    }
-
-    // Since XPConnect doesn't use JSPropertyOps in any other contexts,
-    // ensuring that we have an XPConnect prototype object ensures that
-    // we are only going to expose quickstubbed properties to script.
-    // Also be careful not to overwrite existing properties!
-
-    if (!JSID_IS_STRING(id) ||
-        !IS_PROTO_CLASS(js::GetObjectClass(desc.obj)) ||
-        (desc.attrs & (JSPROP_GETTER | JSPROP_SETTER)) ||
-        !(desc.getter || desc.setter) ||
-        desc.setter == js::GetObjectJSClass(desc.obj)->setProperty) {
-        JS_SET_RVAL(cx, vp, JSVAL_VOID);
-        return true;
-    }
-
-    JSObject *getterobj, *setterobj;
-    if (!ReifyPropertyOps(cx, desc.obj, id, desc.attrs, desc.getter, desc.setter,
-                          &getterobj, &setterobj)) {
-        return false;
-    }
-
-    JSObject *wantedobj = wantGetter ? getterobj : setterobj;
-    jsval v = wantedobj ? OBJECT_TO_JSVAL(wantedobj) : JSVAL_VOID;
-    JS_SET_RVAL(cx, vp, v);
-    return true;
-}
-
-static JSBool
-SharedLookupGetter(JSContext *cx, unsigned argc, jsval *vp)
-{
-    return LookupGetterOrSetter(cx, true, argc, vp);
-}
-
-static JSBool
-SharedLookupSetter(JSContext *cx, unsigned argc, jsval *vp)
-{
-    return LookupGetterOrSetter(cx, false, argc, vp);
-}
-
-static JSBool
-DefineGetterOrSetter(JSContext *cx, unsigned argc, JSBool wantGetter, jsval *vp)
-{
-    unsigned attrs;
-    JSBool found;
-    JSPropertyOp getter;
-    JSStrictPropertyOp setter;
-    JSObject *obj2;
-    jsval v;
-    jsid id;
-
-    XPC_QS_ASSERT_CONTEXT_OK(cx);
-    JSObject *obj = JS_THIS_OBJECT(cx, vp);
-    if (!obj)
-        return false;
-    JSNative forward = wantGetter ? js::obj_defineGetter : js::obj_defineSetter;
-    jsval idval = (argc >= 1) ? JS_ARGV(cx, vp)[0] : JSVAL_VOID;
-    if (!JSVAL_IS_STRING(idval))
-        return forward(cx, argc, vp);
-
-    if (!JS_ValueToId(cx, idval, &id) ||
-        !JS_LookupPropertyWithFlagsById(cx, obj, id, 0, &obj2, &v) ||
-        (obj2 &&
-         !JS_GetPropertyAttrsGetterAndSetterById(cx, obj2, id, &attrs,
-                                                 &found, &getter, &setter)))
-        return false;
-
-    // The property didn't exist, already has a getter or setter, or is not
-    // our property, then just forward now.
-    if (!obj2 ||
-        (attrs & (JSPROP_GETTER | JSPROP_SETTER)) ||
-        !(getter || setter) ||
-        !IS_PROTO_CLASS(js::GetObjectClass(obj2)))
-        return forward(cx, argc, vp);
-
-    // Reify the getter and setter...
-    if (!ReifyPropertyOps(cx, obj2, id, attrs, getter, setter, nullptr, nullptr))
-        return false;
-
-    return forward(cx, argc, vp);
-}
-
-static JSBool
-SharedDefineGetter(JSContext *cx, unsigned argc, jsval *vp)
-{
-    return DefineGetterOrSetter(cx, argc, true, vp);
-}
-
-static JSBool
-SharedDefineSetter(JSContext *cx, unsigned argc, jsval *vp)
-{
-    return DefineGetterOrSetter(cx, argc, false, vp);
-}
-
-
 JSBool
 xpc_qsDefineQuickStubs(JSContext *cx, JSObject *proto, unsigned flags,
                        uint32_t ifacec, const nsIID **interfaces,
                        uint32_t tableSize, const xpc_qsHashEntry *table,
                        const xpc_qsPropertySpec *propspecs,
                        const xpc_qsFunctionSpec *funcspecs,
                        const char *stringTable)
 {
@@ -298,18 +125,20 @@ xpc_qsDefineQuickStubs(JSContext *cx, JS
             for (;;) {
                 // Define quick stubs for attributes.
                 const xpc_qsPropertySpec *ps = propspecs + entry->prop_index;
                 const xpc_qsPropertySpec *ps_end = ps + entry->n_props;
                 for ( ; ps < ps_end; ++ps) {
                     definedProperty = true;
                     if (!JS_DefineProperty(cx, proto,
                                            stringTable + ps->name_index,
-                                           JSVAL_VOID, ps->getter, ps->setter,
-                                           flags | JSPROP_SHARED)) 
+                                           JSVAL_VOID,
+                                           (JSPropertyOp)ps->getter,
+                                           (JSStrictPropertyOp)ps->setter,
+                                           flags | JSPROP_SHARED | JSPROP_NATIVE_ACCESSORS))
                         return false;
                 }
 
                 // Define quick stubs for methods.
                 const xpc_qsFunctionSpec *fs = funcspecs + entry->func_index;
                 const xpc_qsFunctionSpec *fs_end = fs + entry->n_funcs;
                 for ( ; fs < fs_end; ++fs) {
                     if (!JS_DefineFunction(cx, proto,
@@ -326,27 +155,16 @@ xpc_qsDefineQuickStubs(JSContext *cx, JS
                 size_t j = entry->parentInterface;
                 if (j == XPC_QS_NULL_INDEX)
                     break;
                 entry = table + j;
             }
         }
     }
 
-    static JSFunctionSpec getterfns[] = {
-        JS_FN("__lookupGetter__", SharedLookupGetter, 1, 0),
-        JS_FN("__lookupSetter__", SharedLookupSetter, 1, 0),
-        JS_FN("__defineGetter__", SharedDefineGetter, 2, 0),
-        JS_FN("__defineSetter__", SharedDefineSetter, 2, 0),
-        JS_FS_END
-    };
-
-    if (definedProperty && !JS_DefineFunctions(cx, proto, getterfns))
-        return false;
-
     return true;
 }
 
 JSBool
 xpc_qsThrow(JSContext *cx, nsresult rv)
 {
     XPCThrower::Throw(rv, cx);
     return false;
@@ -461,16 +279,36 @@ xpc_qsThrowGetterSetterFailed(JSContext 
                               jsid memberId)
 {
     const char *ifaceName;
     GetMemberInfo(obj, memberId, &ifaceName);
     return ThrowCallFailed(cx, rv, ifaceName, memberId, NULL);
 }
 
 JSBool
+xpc_qsThrowGetterSetterFailed(JSContext *cx, nsresult rv, JSObject *obj,
+                              const char* memberName)
+{
+    JSString *str = JS_InternString(cx, memberName);
+    if (!str) {
+        return false;
+    }
+    return xpc_qsThrowGetterSetterFailed(cx, rv, obj,
+                                         INTERNED_STRING_TO_JSID(cx, str));
+}
+
+JSBool
+xpc_qsThrowGetterSetterFailed(JSContext *cx, nsresult rv, JSObject *obj,
+                              uint16_t memberIndex)
+{
+    return xpc_qsThrowGetterSetterFailed(cx, rv, obj,
+                                         xpc_qsStringTable + memberIndex);
+}
+
+JSBool
 xpc_qsThrowMethodFailed(JSContext *cx, nsresult rv, jsval *vp)
 {
     const char *ifaceName;
     jsid memberId;
     GetMethodInfo(cx, vp, &ifaceName, &memberId);
     return ThrowCallFailed(cx, rv, ifaceName, memberId, NULL);
 }
 
@@ -544,27 +382,55 @@ void
 xpc_qsThrowBadSetterValue(JSContext *cx, nsresult rv,
                           JSObject *obj, jsid propId)
 {
     const char *ifaceName;
     GetMemberInfo(obj, propId, &ifaceName);
     ThrowBadArg(cx, rv, ifaceName, propId, NULL, 0);
 }
 
+void
+xpc_qsThrowBadSetterValue(JSContext *cx, nsresult rv,
+                          JSObject *obj, const char* propName)
+{
+    JSString *str = JS_InternString(cx, propName);
+    if (!str) {
+        return;
+    }
+    xpc_qsThrowBadSetterValue(cx, rv, obj, INTERNED_STRING_TO_JSID(cx, str));
+}
+
+void
+xpc_qsThrowBadSetterValue(JSContext *cx, nsresult rv, JSObject *obj,
+                          uint16_t name_index)
+{
+    xpc_qsThrowBadSetterValue(cx, rv, obj, xpc_qsStringTable + name_index);
+}
+
 JSBool
 xpc_qsGetterOnlyPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict,
                              JSMutableHandleValue vp)
 {
     return JS_ReportErrorFlagsAndNumber(cx,
                                         JSREPORT_WARNING | JSREPORT_STRICT |
                                         JSREPORT_STRICT_MODE_ERROR,
                                         js_GetErrorMessage, NULL,
                                         JSMSG_GETTER_ONLY);
 }
 
+JSBool
+xpc_qsGetterOnlyNativeStub(JSContext *cx, unsigned argc, jsval *vp)
+{
+    return JS_ReportErrorFlagsAndNumber(cx,
+                                        JSREPORT_WARNING | JSREPORT_STRICT |
+                                        JSREPORT_STRICT_MODE_ERROR,
+                                        js_GetErrorMessage, NULL,
+                                        JSMSG_GETTER_ONLY);
+}
+
 xpc_qsDOMString::xpc_qsDOMString(JSContext *cx, jsval v, jsval *pval,
                                  StringificationBehavior nullBehavior,
                                  StringificationBehavior undefinedBehavior)
 {
     typedef implementation_type::char_traits traits;
     // From the T_DOMSTRING case in XPCConvert::JSData2Native.
     JSString *s = InitOrStringify<traits>(cx, v, pval, nullBehavior,
                                           undefinedBehavior);
--- a/js/xpconnect/src/XPCQuickStubs.h
+++ b/js/xpconnect/src/XPCQuickStubs.h
@@ -15,18 +15,18 @@
 /* XPCQuickStubs.h - Support functions used only by quick stubs. */
 
 class XPCCallContext;
 
 #define XPC_QS_NULL_INDEX  ((uint16_t) -1)
 
 struct xpc_qsPropertySpec {
     uint16_t name_index;
-    JSPropertyOp getter;
-    JSStrictPropertyOp setter;
+    JSNative getter;
+    JSNative setter;
 };
 
 struct xpc_qsFunctionSpec {
     uint16_t name_index;
     uint16_t arity;
     JSNative native;
 };
 
@@ -67,16 +67,23 @@ xpc_qsThrow(JSContext *cx, nsresult rv);
  *
  * This is one reason the UnwrapThis functions below have an out parameter that
  * receives the wrapper JSObject.  (The other reason is to help the caller keep
  * that JSObject GC-reachable.)
  */
 JSBool
 xpc_qsThrowGetterSetterFailed(JSContext *cx, nsresult rv,
                               JSObject *obj, jsid memberId);
+// And variants using strings and string tables
+JSBool
+xpc_qsThrowGetterSetterFailed(JSContext *cx, nsresult rv,
+                              JSObject *obj, const char* memberName);
+JSBool
+xpc_qsThrowGetterSetterFailed(JSContext *cx, nsresult rv,
+                              JSObject *obj, uint16_t memberIndex);
 
 /**
  * Fail after an XPCOM method returned rv.
  *
  * See NOTE at xpc_qsThrowGetterSetterFailed.
  */
 JSBool
 xpc_qsThrowMethodFailed(JSContext *cx, nsresult rv, jsval *vp);
@@ -107,21 +114,31 @@ xpc_qsThrowBadArgWithDetails(JSContext *
 /**
  * Fail after converting a setter argument fails.
  *
  * See NOTE at xpc_qsThrowGetterSetterFailed.
  */
 void
 xpc_qsThrowBadSetterValue(JSContext *cx, nsresult rv, JSObject *obj,
                           jsid propId);
+// And variants using strings and string tables
+void
+xpc_qsThrowBadSetterValue(JSContext *cx, nsresult rv, JSObject *obj,
+                          const char* propName);
+void
+xpc_qsThrowBadSetterValue(JSContext *cx, nsresult rv, JSObject *obj,
+                          uint16_t name_index);
 
 
 JSBool
 xpc_qsGetterOnlyPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict, JSMutableHandleValue vp);
 
+JSBool
+xpc_qsGetterOnlyNativeStub(JSContext *cx, unsigned argc, jsval *vp);
+
 /* Functions for converting values between COM and JS. */
 
 inline JSBool
 xpc_qsInt64ToJsval(JSContext *cx, int64_t i, jsval *rv)
 {
     *rv = JS_NumberValue(static_cast<double>(i));
     return true;
 }
--- a/js/xpconnect/src/qsgen.py
+++ b/js/xpconnect/src/qsgen.py
@@ -373,16 +373,17 @@ class StringTable:
         def explodeToCharArray(string):
             return ", ".join(map(lambda x:"'%s'" % x, string))
         f.write("static const char %s[] = {\n" % name)
         for (string, offset) in entries[:-1]:
             f.write("  /* %5d */ %s, '\\0',\n"
                     % (offset, explodeToCharArray(string)))
         f.write("  /* %5d */ %s, '\\0' };\n\n"
                 % (entries[-1][1], explodeToCharArray(entries[-1][0])))
+        f.write("const char* xpc_qsStringTable = %s;\n\n" % name);
 
 def substitute(template, vals):
     """ Simple replacement for string.Template, which isn't in Python 2.3. """
     def replacement(match):
         return vals[match.group(1)]
     return re.sub(r'\${(\w+)}', replacement, template)
 
 # From JSData2Native.
@@ -479,34 +480,35 @@ argumentUnboxingTemplates = {
 
 # From JSData2Native.
 #
 # Omitted optional arguments are treated as though the caller had passed JS
 # `null`; this behavior is from XPCWrappedNative::CallMethod. The 'jsval' type,
 # however, defaults to 'undefined'.
 #
 def writeArgumentUnboxing(f, i, name, type, optional, rvdeclared,
-                          nullBehavior, undefinedBehavior):
+                          nullBehavior, undefinedBehavior,
+                          propIndex=None):
     # f - file to write to
     # i - int or None - Indicates the source jsval.  If i is an int, the source
-    #     jsval is argv[i]; otherwise it is *vp.  But if Python i >= C++ argc,
+    #     jsval is argv[i]; otherwise it is argv[0].  But if Python i >= C++ argc,
     #     which can only happen if optional is True, the argument is missing;
     #     use JSVAL_NULL as the source jsval instead.
     # name - str - name of the native C++ variable to create.
     # type - xpidl.{Interface,Native,Builtin} - IDL type of argument
     # optional - bool - True if the parameter is optional.
     # rvdeclared - bool - False if no |nsresult rv| has been declared earlier.
 
     typeName = getBuiltinOrNativeTypeName(type)
 
     isSetter = (i is None)
 
     if isSetter:
-        argPtr = "vp"
-        argVal = "*vp"
+        argPtr = "argv"
+        argVal = "argv[0]"
     elif optional:
         if typeName == "[jsval]":
             val = "JSVAL_VOID"
         else:
             val = "JSVAL_NULL"
         argVal = "(%d < argc ? argv[%d] : %s)" % (i, i, val)
         argPtr = "(%d < argc ? &argv[%d] : NULL)" % (i, i)
     else:
@@ -547,27 +549,28 @@ def writeArgumentUnboxing(f, i, name, ty
                 f.write("    nsresult rv;\n");
             f.write("    %s *%s;\n" % (type.name, name))
             f.write("    xpc_qsSelfRef %sref;\n" % name)
             f.write("    rv = xpc_qsUnwrapArg<%s>("
                     "cx, %s, &%s, &%sref.ptr, %s);\n"
                     % (type.name, argVal, name, name, argPtr))
             f.write("    if (NS_FAILED(rv)) {\n")
             if isSetter:
-                f.write("        xpc_qsThrowBadSetterValue("
-                        "cx, rv, JSVAL_TO_OBJECT(*tvr.jsval_addr()), id);\n")
+                assert(propIndex is not None)
+                f.write("        xpc_qsThrowBadSetterValue(cx, rv, JSVAL_TO_OBJECT(vp[1]), (uint16_t)%s);\n" %
+                        propIndex)
             else:
                 f.write("        xpc_qsThrowBadArg(cx, rv, vp, %d);\n" % i)
             f.write("        return JS_FALSE;\n"
                     "    }\n")
             return True
 
     warn("Unable to unbox argument of type %s (native type %s)" % (type.name, typeName))
     if i is None:
-        src = '*vp'
+        src = 'argv[0]'
     else:
         src = 'argv[%d]' % i
     f.write("    !; // TODO - Unbox argument %s = %s\n" % (name, src))
     return rvdeclared
 
 def writeResultDecl(f, type, varname):
     if isVoidType(type):
         return  # nothing to declare
@@ -737,39 +740,32 @@ def setOptimizationForMSVC(f, b):
     if b:
         pragmaParam = "on"
     else:
         pragmaParam = "off"
     f.write("#ifdef _MSC_VER\n")
     f.write('# pragma optimize("", %s)\n'%pragmaParam)
     f.write("#endif\n")
 
-def writeQuickStub(f, customMethodCalls, member, stubName, isSetter=False):
+def writeQuickStub(f, customMethodCalls, stringtable, member, stubName,
+                   isSetter=False):
     """ Write a single quick stub (a custom SpiderMonkey getter/setter/method)
     for the specified XPCOM interface-member. 
     """
     # Workaround for suspected compiler bug.
     # See https://bugzilla.mozilla.org/show_bug.cgi?id=750019
     disableOptimizationForMSVC = (stubName == 'nsIDOMHTMLDocument_Write')
 
     isAttr = (member.kind == 'attribute')
     isMethod = (member.kind == 'method')
     assert isAttr or isMethod
     isGetter = isAttr and not isSetter
 
-    signature = "static JSBool\n"
-    if isAttr:
-        # JSPropertyOp signature.
-        if isSetter:
-            signature += "%s(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool strict,%s JSMutableHandleValue vp_)\n"
-        else:
-            signature += "%s(JSContext *cx, JSHandleObject obj, JSHandleId id,%s JSMutableHandleValue vp_)\n"
-    else:
-        # JSFastNative.
-        signature += "%s(JSContext *cx, unsigned argc,%s jsval *vp)\n"
+    signature = ("static JSBool\n" +
+                 "%s(JSContext *cx, unsigned argc,%s jsval *vp)\n")
 
     customMethodCall = customMethodCalls.get(stubName, None)
 
     if customMethodCall is None:
         customMethodCall = customMethodCalls.get(member.iface.name + '_', None)
         if customMethodCall is not None:
             if isMethod:
                 code = customMethodCall.get('code', None)
@@ -792,22 +788,18 @@ def writeQuickStub(f, customMethodCalls,
             # arguments, only the template function can.
             callTemplate = signature % (stubName, '')
             callTemplate += "{\n"
 
             nativeName = (member.binaryname is not None and member.binaryname
                           or header.firstCap(member.name))
             argumentValues = (customMethodCall['additionalArgumentValues']
                               % nativeName)
-            if isAttr:
-                callTemplate += ("    return %s(cx, obj, id%s, %s, vp_);\n"
-                                 % (templateName, ", strict" if isSetter else "", argumentValues))
-            else:
-                callTemplate += ("    return %s(cx, argc, %s, vp);\n"
-                                 % (templateName, argumentValues))
+            callTemplate += ("    return %s(cx, argc, %s, vp);\n"
+                             % (templateName, argumentValues))
             callTemplate += "}\n\n"
 
             # Fall through and create the template function stub called from the
             # real stubs, but only generate the stub once. Otherwise, just write
             # out the call to the template function and return.
             templateGenerated = templateName + '_generated'
             if templateGenerated in customMethodCall:
                 f.write(callTemplate)
@@ -835,39 +827,28 @@ def writeQuickStub(f, customMethodCalls,
     else:
         additionalArguments = " %s," % customMethodCall['additionalArguments']
     if disableOptimizationForMSVC:
         setOptimizationForMSVC(f, False)
     f.write(signature % (stubName, additionalArguments))
     f.write("{\n")
     f.write("    XPC_QS_ASSERT_CONTEXT_OK(cx);\n")
 
-    # Convert JSMutableHandleValue to jsval*
-    if isAttr:
-        f.write("    jsval *vp = vp_.address();\n")
-
-    # For methods, compute "this".
-    if isMethod:
-        f.write("    JSObject *obj = JS_THIS_OBJECT(cx, vp);\n"
-                "    if (!obj)\n"
-                "        return JS_FALSE;\n")
+    # Compute "this".
+    f.write("    JSObject *obj = JS_THIS_OBJECT(cx, vp);\n"
+            "    if (!obj)\n"
+            "        return JS_FALSE;\n")
 
     # Get the 'self' pointer.
     if customMethodCall is None or not 'thisType' in customMethodCall:
         f.write("    %s *self;\n" % member.iface.name)
     else:
         f.write("    %s *self;\n" % customMethodCall['thisType'])
     f.write("    xpc_qsSelfRef selfref;\n")
-    if isGetter:
-        pthisval = 'vp'
-    elif isSetter:
-        f.write("    JS::AutoValueRooter tvr(cx);\n")
-        pthisval = 'tvr.jsval_addr()'
-    else:
-        pthisval = '&vp[1]' # as above, ok to overwrite vp[1]
+    pthisval = '&vp[1]' # as above, ok to overwrite vp[1]
 
     if unwrapThisFailureFatal:
         unwrapFatalArg = "true"
     else:
         unwrapFatalArg = "false"
 
     if not isSetter and isInterfaceType(member.realtype):
         f.write("    XPCLazyCallContext lccx(JS_CALLER, cx, obj);\n")
@@ -885,20 +866,24 @@ def writeQuickStub(f, customMethodCalls,
         f.write("        return JS_TRUE;\n")
         f.write("    }\n");
 
     if isMethod:
         # If there are any required arguments, check argc.
         requiredArgs = len(member.params)
         while requiredArgs and member.params[requiredArgs-1].optional:
             requiredArgs -= 1
-        if requiredArgs:
-            f.write("    if (argc < %d)\n" % requiredArgs)
-            f.write("        return xpc_qsThrow(cx, "
-                    "NS_ERROR_XPC_NOT_ENOUGH_ARGS);\n")
+    elif isSetter:
+        requiredArgs = 1
+    else:
+        requiredArgs = 0
+    if requiredArgs:
+        f.write("    if (argc < %d)\n" % requiredArgs)
+        f.write("        return xpc_qsThrow(cx, "
+                "NS_ERROR_XPC_NOT_ENOUGH_ARGS);\n")
 
     # Convert in-parameters.
     rvdeclared = False
     if isMethod:
         if len(member.params) > 0:
             f.write("    jsval *argv = JS_ARGV(cx, vp);\n")
         for i, param in enumerate(member.params):
             argName = 'arg%d' % i
@@ -912,21 +897,23 @@ def writeQuickStub(f, customMethodCalls,
             # Emit code to convert this argument from jsval.
             rvdeclared = writeArgumentUnboxing(
                 f, i, argName, realtype,
                 optional=param.optional,
                 rvdeclared=rvdeclared,
                 nullBehavior=param.null,
                 undefinedBehavior=param.undefined)
     elif isSetter:
+        f.write("    jsval *argv = JS_ARGV(cx, vp);\n")
         rvdeclared = writeArgumentUnboxing(f, None, 'arg0', member.realtype,
                                            optional=False,
                                            rvdeclared=rvdeclared,
                                            nullBehavior=member.null,
-                                           undefinedBehavior=member.undefined)
+                                           undefinedBehavior=member.undefined,
+                                           propIndex=stringtable.stringIndex(member.name))
 
     canFail = customMethodCall is None or customMethodCall.get('canFail', True)
     if canFail and not rvdeclared:
         f.write("    nsresult rv;\n")
         rvdeclared = True
 
     if code is not None:
         f.write("%s\n" % code)
@@ -989,22 +976,19 @@ def writeQuickStub(f, customMethodCalls,
 
     if canFail:
         # Check for errors.
         f.write("    if (NS_FAILED(rv))\n")
         if isMethod:
             f.write("        return xpc_qsThrowMethodFailed("
                     "cx, rv, vp);\n")
         else:
-            if isGetter:
-                thisval = '*vp'
-            else:
-                thisval = '*tvr.jsval_addr()'
             f.write("        return xpc_qsThrowGetterSetterFailed(cx, rv, " +
-                    "JSVAL_TO_OBJECT(%s), id);\n" % thisval)
+                    "JSVAL_TO_OBJECT(vp[1]), (uint16_t)%d);\n" %
+                    stringtable.stringIndex(member.name))
 
     # Convert the return value.
     if isMethod or isGetter:
         writeResultConv(f, member.realtype, 'vp', '*vp')
     else:
         f.write("    return JS_TRUE;\n")
 
     # Epilog.
@@ -1015,33 +999,34 @@ def writeQuickStub(f, customMethodCalls,
 
     # Now write out the call to the template function.
     if customMethodCall is not None:
         f.write(callTemplate)
 
 def writeAttrStubs(f, customMethodCalls, stringtable, attr):
     getterName = (attr.iface.name + '_'
                   + header.attributeNativeName(attr, True))
-    writeQuickStub(f, customMethodCalls, attr, getterName)
+    writeQuickStub(f, customMethodCalls, stringtable, attr, getterName)
     if attr.readonly:
-        setterName = 'xpc_qsGetterOnlyPropertyStub'
+        setterName = 'xpc_qsGetterOnlyNativeStub'
     else:
         setterName = (attr.iface.name + '_'
                       + header.attributeNativeName(attr, False))
-        writeQuickStub(f, customMethodCalls, attr, setterName, isSetter=True)
+        writeQuickStub(f, customMethodCalls, stringtable, attr, setterName,
+                       isSetter=True)
 
     ps = ('{%d, %s, %s}'
           % (stringtable.stringIndex(attr.name), getterName, setterName))
     return ps
 
 def writeMethodStub(f, customMethodCalls, stringtable, method):
     """ Write a method stub to `f`. Return an xpc_qsFunctionSpec initializer. """
 
     stubName = method.iface.name + '_' + header.methodNativeName(method)
-    writeQuickStub(f, customMethodCalls, method, stubName)
+    writeQuickStub(f, customMethodCalls, stringtable, method, stubName)
     fs = '{%d, %d, %s}' % (stringtable.stringIndex(method.name),
                            len(method.params), stubName)
     return fs
 
 def writeStubsForInterface(f, customMethodCalls, stringtable, iface):
     f.write("// === interface %s\n\n" % iface.name)
     propspecs = []
     funcspecs = []
--- a/js/xpconnect/tests/mochitest/test_bug428021.html
+++ b/js/xpconnect/tests/mochitest/test_bug428021.html
@@ -14,18 +14,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
       /** Test for Bug 428021 **/
       var rangetter, ransetter;
-      __defineGetter__('x', function() { rangetter = true; });
-      __defineSetter__('x', function(val) { ransetter = true; });
+      this.__defineGetter__('x', function() { rangetter = true; });
+      this.__defineSetter__('x', function(val) { ransetter = true; });
 
       var exn;
       try {
           e = x;
           x = false;
       } catch (e) {
           exn = e;
       }
--- a/toolkit/components/search/nsSearchService.js
+++ b/toolkit/components/search/nsSearchService.js
@@ -202,29 +202,29 @@ var OS_UNSUPPORTED_PARAMS = [
 const SEARCH_DEFAULT_UPDATE_INTERVAL = 7;
 
 // Returns false for whitespace-only or commented out lines in a
 // Sherlock file, true otherwise.
 function isUsefulLine(aLine) {
   return !(/^\s*($|#)/i.test(aLine));
 }
 
-__defineGetter__("FileUtils", function() {
+this.__defineGetter__("FileUtils", function() {
   delete this.FileUtils;
   Components.utils.import("resource://gre/modules/FileUtils.jsm");
   return FileUtils;
 });
 
-__defineGetter__("NetUtil", function() {
+this.__defineGetter__("NetUtil", function() {
   delete this.NetUtil;
   Components.utils.import("resource://gre/modules/NetUtil.jsm");
   return NetUtil;
 });
 
-__defineGetter__("gChromeReg", function() {
+this.__defineGetter__("gChromeReg", function() {
   delete this.gChromeReg;
   return this.gChromeReg = Cc["@mozilla.org/chrome/chrome-registry;1"].
                            getService(Ci.nsIChromeRegistry);
 });
 
 /**
  * Prefixed to all search debug output.
  */
--- a/toolkit/components/viewsource/content/viewSource.js
+++ b/toolkit/components/viewsource/content/viewSource.js
@@ -26,17 +26,17 @@ var gGoToLine = 0;
   });
 });
 
 // viewZoomOverlay.js uses this
 function getBrowser() {
   return gBrowser;
 }
 
-__defineGetter__("gPageLoader", function () {
+this.__defineGetter__("gPageLoader", function () {
   var webnav = getWebNavigation();
   if (!webnav)
     return null;
   delete this.gPageLoader;
   return this.gPageLoader = webnav.QueryInterface(Ci.nsIWebPageDescriptor);
 });
 
 var gSelectionListener = {
--- a/toolkit/content/globalOverlay.js
+++ b/toolkit/content/globalOverlay.js
@@ -175,14 +175,14 @@ function visitLink(aEvent) {
 
 function setTooltipText(aID, aTooltipText)
 {
   var element = document.getElementById(aID);
   if (element)
     element.setAttribute("tooltiptext", aTooltipText);
 }
 
-__defineGetter__("NS_ASSERT", function() {
+this.__defineGetter__("NS_ASSERT", function() {
   delete this.NS_ASSERT;
   var tmpScope = {};
   Components.utils.import("resource://gre/modules/debug.js", tmpScope);
   return this.NS_ASSERT = tmpScope.NS_ASSERT;
 });
--- a/toolkit/mozapps/downloads/DownloadUtils.jsm
+++ b/toolkit/mozapps/downloads/DownloadUtils.jsm
@@ -34,23 +34,23 @@ this.EXPORTED_SYMBOLS = [ "DownloadUtils
  * [int time, string units, int subTime, string subUnits]
  * convertTimeUnits(double aSecs)
  */
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
-__defineGetter__("PluralForm", function() {
+this.__defineGetter__("PluralForm", function() {
   delete this.PluralForm;
   Cu.import("resource://gre/modules/PluralForm.jsm");
   return PluralForm;
 });
 
-__defineGetter__("gDecimalSymbol", function() {
+this.__defineGetter__("gDecimalSymbol", function() {
   delete this.gDecimalSymbol;
   return this.gDecimalSymbol = Number(5.4).toLocaleString().match(/\D/);
 });
 
 const kDownloadProperties =
   "chrome://mozapps/locale/downloads/downloads.properties";
 
 let gStr = {
@@ -69,17 +69,17 @@ let gStr = {
   doneScheme: "doneScheme2",
   doneFileScheme: "doneFileScheme",
   units: ["bytes", "kilobyte", "megabyte", "gigabyte"],
   // Update timeSize in convertTimeUnits if changing the length of this array
   timeUnits: ["seconds", "minutes", "hours", "days"],
 };
 
 // This lazily initializes the string bundle upon first use.
-__defineGetter__("gBundle", function() {
+this.__defineGetter__("gBundle", function() {
   delete gBundle;
   return this.gBundle = Cc["@mozilla.org/intl/stringbundle;1"].
                         getService(Ci.nsIStringBundleService).
                         createBundle(kDownloadProperties);
 });
 
 // Keep track of at most this many second/lastSec pairs so that multiple calls
 // to getTimeLeft produce the same time left
--- a/toolkit/mozapps/extensions/LightweightThemeManager.jsm
+++ b/toolkit/mozapps/extensions/LightweightThemeManager.jsm
@@ -37,33 +37,33 @@ const PERSIST_BYPASS_CACHE = false;
 const PERSIST_FILES = {
   headerURL: "lightweighttheme-header",
   footerURL: "lightweighttheme-footer"
 };
 
 XPCOMUtils.defineLazyModuleGetter(this, "LightweightThemeImageOptimizer",
   "resource://gre/modules/LightweightThemeImageOptimizer.jsm");
 
-__defineGetter__("_prefs", function prefsGetter() {
+this.__defineGetter__("_prefs", function prefsGetter() {
   delete this._prefs;
   return this._prefs = Services.prefs.getBranch("lightweightThemes.");
 });
 
-__defineGetter__("_maxUsedThemes", function maxUsedThemesGetter() {
+this.__defineGetter__("_maxUsedThemes", function maxUsedThemesGetter() {
   delete this._maxUsedThemes;
   try {
     this._maxUsedThemes = _prefs.getIntPref("maxUsedThemes");
   }
   catch (e) {
     this._maxUsedThemes = DEFAULT_MAX_USED_THEMES_COUNT;
   }
   return this._maxUsedThemes;
 });
 
-__defineSetter__("_maxUsedThemes", function maxUsedThemesSetter(aVal) {
+this.__defineSetter__("_maxUsedThemes", function maxUsedThemesSetter(aVal) {
   delete this._maxUsedThemes;
   return this._maxUsedThemes = aVal;
 });
 
 // Holds the ID of the theme being enabled or disabled while sending out the
 // events so cached AddonWrapper instances can return correct values for
 // permissions and pendingOperations
 var _themeIDBeingEnabled = null;
--- a/toolkit/mozapps/extensions/content/extensions.js
+++ b/toolkit/mozapps/extensions/content/extensions.js
@@ -63,17 +63,17 @@ XPCOMUtils.defineLazyGetter(gStrings, "b
 XPCOMUtils.defineLazyGetter(gStrings, "appVersion", function appVersionLazyGetter() {
   return Services.appinfo.version;
 });
 
 document.addEventListener("load", initialize, true);
 window.addEventListener("unload", shutdown, false);
 
 var gPendingInitializations = 1;
-__defineGetter__("gIsInitializing", function gIsInitializingGetter() gPendingInitializations > 0);
+this.__defineGetter__("gIsInitializing", function gIsInitializingGetter() gPendingInitializations > 0);
 
 function initialize(event) {
   // XXXbz this listener gets _all_ load events for all nodes in the
   // document... but relies on not being called "too early".
   if (event.target instanceof XMLStylesheetProcessingInstruction) {
     return;
   }
   document.removeEventListener("load", initialize, true);
--- a/toolkit/mozapps/update/test/chrome/utils.js
+++ b/toolkit/mozapps/update/test/chrome/utils.js
@@ -183,66 +183,66 @@ var gDisableNoUpdateAddon = false;
 // onload function.
 var DEBUG_AUS_TEST = false;
 
 #include ../shared.js
 
 /**
  * The current test in TESTS array.
  */
-__defineGetter__("gTest", function() {
+this.__defineGetter__("gTest", function() {
   return TESTS[gTestCounter];
 });
 
 /**
  * The current test's callback. This will either return the callback defined in
  * the test's overrideCallback property or defaultCallback if the
  * overrideCallback property is undefined.
  */
-__defineGetter__("gCallback", function() {
+this.__defineGetter__("gCallback", function() {
   return gTest.overrideCallback ? gTest.overrideCallback
                                 : defaultCallback;
 });
 
 /**
  * The remotecontent element for the current page if one exists or null if a
  * remotecontent element doesn't exist.
  */
-__defineGetter__("gRemoteContent", function() {
+this.__defineGetter__("gRemoteContent", function() {
   switch (gTest.pageid) {
     case PAGEID_FOUND_BILLBOARD:
       return gWin.document.getElementById("updateMoreInfoContent");
     case PAGEID_LICENSE:
       return gWin.document.getElementById("licenseContent");
   }
   return null;
 });
 
 /**
  * The state for the remotecontent element if one exists or null if a
  * remotecontent element doesn't exist.
  */
-__defineGetter__("gRemoteContentState", function() {
+this.__defineGetter__("gRemoteContentState", function() {
   if (gRemoteContent) {
     return gRemoteContent.getAttribute("state");
   }
   return null;
 });
 
 /**
  * The radiogroup for the license page.
  */
-__defineGetter__("gAcceptDeclineLicense", function() {
+this.__defineGetter__("gAcceptDeclineLicense", function() {
   return gWin.document.getElementById("acceptDeclineLicense");
 });
 
 /**
  * The listbox for the incompatibleList page.
  */
-__defineGetter__("gIncompatibleListbox", function() {
+this.__defineGetter__("gIncompatibleListbox", function() {
   return gWin.document.getElementById("incompatibleListbox");
 });
 
 /**
  * Default test run function that can be used by most tests. This function uses
  * protective measures to prevent the test from failing provided by
  * |runTestDefaultWaitForWindowClosed| helper functions to prevent failure due
  * to a previous test failure.