Backed out 13 changesets (bug 987111) for disagreeing with some patch from b-i or fx-team in tonight's merge to hopefully fix a CLOSED TREE
authorWes Kocher <wkocher@mozilla.com>
Wed, 04 Jun 2014 22:12:50 -0700
changeset 207052 fe14647a422d538acd0959c5cb214d34504b9704
parent 207051 e9859d8b5e516ce16f1343a0174a2f2caba2434f
child 207053 a1199e0dd68bf541f7a0e4f40cb0f777ffd155ed
push id494
push userraliiev@mozilla.com
push dateMon, 25 Aug 2014 18:42:16 +0000
treeherdermozilla-release@a3cc3e46b571 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs987111
milestone32.0a1
backs outd4e390ceac27fe5661e52a42ad9efb48bf148ffc
5f88b5ef94963726e73ee81f9c3b1b6c45a05161
cdfd24ddf448cfda953b1810077158c8c6bcd5c5
7883150e5471699a27121eebf3a69e0f08ef9f7e
407c7ca82ada87a5eea4df3e7530d7ff61cabb90
e7140ccf7e09c75f713fb96af78c655175a4efe4
0a4d18d6306f5bccae307ad6edf1ca47e799b0c9
e7b7548867d998b0e6a9e534860cac5506314a7d
944d128f135aeebe1d91d940f5ad1d81917db58f
33860f30fc4f41fd66cf8a6ce65f78eede465b1a
518a915fb81b2ce455a28a627bd530d642ba0a94
7576a51cf72e705f51ffe5cd6d153cc827662345
1a8dc1af9de67d5af9079643f783d179e243f810
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
Backed out 13 changesets (bug 987111) for disagreeing with some patch from b-i or fx-team in tonight's merge to hopefully fix a CLOSED TREE Backed out changeset d4e390ceac27 (bug 987111) Backed out changeset 5f88b5ef9496 (bug 987111) Backed out changeset cdfd24ddf448 (bug 987111) Backed out changeset 7883150e5471 (bug 987111) Backed out changeset 407c7ca82ada (bug 987111) Backed out changeset e7140ccf7e09 (bug 987111) Backed out changeset 0a4d18d6306f (bug 987111) Backed out changeset e7b7548867d9 (bug 987111) Backed out changeset 944d128f135a (bug 987111) Backed out changeset 33860f30fc4f (bug 987111) Backed out changeset 518a915fb81b (bug 987111) Backed out changeset 7576a51cf72e (bug 987111) Backed out changeset 1a8dc1af9de6 (bug 987111)
dom/identity/nsDOMIdentity.js
js/src/jsapi.h
js/src/jsproxy.cpp
js/xpconnect/tests/chrome/test_xrayToJS.xul
js/xpconnect/wrappers/WrapperFactory.cpp
js/xpconnect/wrappers/XrayWrapper.cpp
--- a/dom/identity/nsDOMIdentity.js
+++ b/dom/identity/nsDOMIdentity.js
@@ -97,17 +97,16 @@ nsDOMIdentity.prototype = {
     });
   },
 
   /**
    * Relying Party (RP) APIs
    */
 
   watch: function nsDOMIdentity_watch(aOptions = {}) {
-    aOptions = Cu.waiveXrays(aOptions);
     if (this._rpWatcher) {
       // For the initial release of Firefox Accounts, we support callers who
       // invoke watch() either for Firefox Accounts, or Persona, but not both.
       // In the future, we may wish to support the dual invocation (say, for
       // packaged apps so they can sign users in who reject the app's request
       // to sign in with their Firefox Accounts identity).
       throw new Error("navigator.id.watch was already called");
     }
@@ -149,17 +148,16 @@ nsDOMIdentity.prototype = {
       // We don't delete the rpWatcher object, because we don't want the
       // broken client to be able to call watch() any more.  It's broken.
       return;
     }
     this._identityInternal._mm.sendAsyncMessage("Identity:RP:Watch", message);
   },
 
   request: function nsDOMIdentity_request(aOptions = {}) {
-    aOptions = Cu.waiveXrays(aOptions);
     this._log("request: " + JSON.stringify(aOptions));
 
     // Has the caller called watch() before this?
     if (!this._rpWatcher) {
       throw new Error("navigator.id.request called before navigator.id.watch");
     }
     if (this._rpCalls > MAX_RP_CALLS) {
       throw new Error("navigator.id.request called too many times");
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -2890,17 +2890,16 @@ class PropertyDescriptorOperations
   public:
     bool isEnumerable() const { return desc()->attrs & JSPROP_ENUMERATE; }
     bool isReadonly() const { return desc()->attrs & JSPROP_READONLY; }
     bool isPermanent() const { return desc()->attrs & JSPROP_PERMANENT; }
     bool hasNativeAccessors() const { return desc()->attrs & JSPROP_NATIVE_ACCESSORS; }
     bool hasGetterObject() const { return desc()->attrs & JSPROP_GETTER; }
     bool hasSetterObject() const { return desc()->attrs & JSPROP_SETTER; }
     bool hasGetterOrSetterObject() const { return desc()->attrs & (JSPROP_GETTER | JSPROP_SETTER); }
-    bool hasGetterOrSetter() const { return desc()->getter || desc()->setter; }
     bool isShared() const { return desc()->attrs & JSPROP_SHARED; }
     bool isIndex() const { return desc()->attrs & JSPROP_INDEX; }
     bool hasAttributes(unsigned attrs) const { return desc()->attrs & attrs; }
 
     JS::HandleObject object() const {
         return JS::HandleObject::fromMarkedLocation(&desc()->obj);
     }
     unsigned attributes() const { return desc()->attrs; }
@@ -2931,24 +2930,16 @@ class MutablePropertyDescriptorOperation
     void clear() {
         object().set(nullptr);
         setAttributes(0);
         setGetter(nullptr);
         setSetter(nullptr);
         value().setUndefined();
     }
 
-    void assign(JSPropertyDescriptor &other) {
-        object().set(other.obj);
-        setAttributes(other.attrs);
-        setGetter(other.getter);
-        setSetter(other.setter);
-        value().set(other.value);
-    }
-
     JS::MutableHandleObject object() {
         return JS::MutableHandleObject::fromMarkedLocation(&desc()->obj);
     }
     unsigned &attributesRef() { return desc()->attrs; }
     JSPropertyOp &getter() { return desc()->getter; }
     JSStrictPropertyOp &setter() { return desc()->setter; }
     JS::MutableHandleValue value() {
         return JS::MutableHandleValue::fromMarkedLocation(&desc()->value);
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -2582,17 +2582,16 @@ Proxy::set(JSContext *cx, HandleObject p
         return false;
     if (desc.object() && desc.setter() && desc.setter() != JS_StrictPropertyStub)
         return CallSetter(cx, receiver, id, desc.setter(), desc.attributes(), strict, vp);
 
     // Ok. Either there was no pre-existing property, or it was a value prop
     // that we're going to shadow. Make a property descriptor and define it.
     Rooted<PropertyDescriptor> newDesc(cx);
     newDesc.value().set(vp);
-    newDesc.setAttributes(JSPROP_ENUMERATE);
     return handler->defineProperty(cx, receiver, id, &newDesc);
 }
 
 bool
 Proxy::keys(JSContext *cx, HandleObject proxy, AutoIdVector &props)
 {
     JS_CHECK_RECURSION(cx, return false);
     BaseProxyHandler *handler = proxy->as<ProxyObject>().handler();
--- a/js/xpconnect/tests/chrome/test_xrayToJS.xul
+++ b/js/xpconnect/tests/chrome/test_xrayToJS.xul
@@ -18,26 +18,16 @@ https://bugzilla.mozilla.org/show_bug.cg
   <script type="application/javascript">
   <![CDATA[
 
   /** Test for ES constructors on Xrayed globals. **/
   SimpleTest.waitForExplicitFinish();
   const Cu = Components.utils;
   let global = Cu.getGlobalForObject.bind(Cu);
 
-  function checkThrows(f, rgxp, msg) {
-    try {
-      f();
-      ok(false, "Should have thrown: " + msg);
-    } catch (e) {
-      ok(true, "Threw as expected: " + msg);
-      ok(rgxp.test(e), "Message correct: " + e);
-    }
-  }
-
   simpleConstructors = ['Object', 'Function', 'Array', 'Boolean', 'Date', 'Number',
                         'String', 'RegExp', 'Error', 'InternalError', 'EvalError',
                         'RangeError', 'ReferenceError', 'SyntaxError', 'TypeError',
                         'URIError', 'ArrayBuffer', 'Int8Array', 'Uint8Array',
                         'Int16Array', 'Uint16Array', 'Int32Array', 'Uint32Array',
                         'Float32Array', 'Float64Array', 'Uint8ClampedArray',
                         'WeakMap', 'Map', 'Set'];
 
@@ -108,70 +98,38 @@ https://bugzilla.mozilla.org/show_bug.cg
     // Test eval.
     var toEval = "({a: 2, b: {foo: 'bar'}, f: function() { return window; }})";
     is(global(iwin.eval(toEval)), iwin, "eval creates objects in the correct global");
     is(iwin.eval(toEval).b.foo, 'bar', "eval-ed object looks right");
     is(Cu.waiveXrays(iwin.eval(toEval)).f(), Cu.waiveXrays(iwin), "evaled function works right");
 
     testDate();
 
-    testObject();
-
     // We could also test DataView and Iterator here for completeness, but it's
     // more trouble than it's worth.
 
 
     SimpleTest.finish();
   }
 
-  // Maintain a static list of the properties that are available on each standard
-  // prototype, so that we make sure to audit any new ones to make sure they're
-  // Xray-safe.
-  //
-  // DO NOT CHANGE WTIHOUT REVIEW FROM AN XPCONNECT PEER.
-  var gPrototypeProperties = {};
-  gPrototypeProperties['Date'] =
-    ["getTime", "getTimezoneOffset", "getYear", "getFullYear", "getUTCFullYear",
-    "getMonth", "getUTCMonth", "getDate", "getUTCDate", "getDay", "getUTCDay",
-    "getHours", "getUTCHours", "getMinutes", "getUTCMinutes", "getSeconds",
-    "getUTCSeconds", "getMilliseconds", "getUTCMilliseconds", "setTime",
-    "setYear", "setFullYear", "setUTCFullYear", "setMonth", "setUTCMonth",
-    "setDate", "setUTCDate", "setHours", "setUTCHours", "setMinutes",
-    "setUTCMinutes", "setSeconds", "setUTCSeconds", "setMilliseconds",
-    "setUTCMilliseconds", "toUTCString", "toLocaleFormat", "toLocaleString",
-    "toLocaleDateString", "toLocaleTimeString", "toDateString", "toTimeString",
-    "toISOString", "toJSON", "toSource", "toString", "valueOf", "constructor",
-    "toGMTString"];
-  gPrototypeProperties['Object'] = /* __proto__ is intentionally excluded here, because
-                                      the JS engine filters it out of getOwnPropertyNames */
-    ["constructor", "toSource", "toString", "toLocaleString", "valueOf", "watch",
-     "unwatch", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable",
-     "__defineGetter__", "__defineSetter__", "__lookupGetter__", "__lookupSetter__"];
-
   function filterOut(array, props) {
     return array.filter(p => props.indexOf(p) == -1);
   }
 
   function testXray(classname, xray, xray2, propsToSkip) {
     propsToSkip = propsToSkip || [];
     let xrayProto = Object.getPrototypeOf(xray);
     let localProto = window[classname].prototype;
-    is(Object.getOwnPropertyNames(localProto).sort().toSource(),
-       gPrototypeProperties[classname].sort().toSource(),
-       "A new property on the " + classname +
-       " prototype has been added! You need a security audit from an XPConnect peer");
-
     let protoProps = filterOut(Object.getOwnPropertyNames(localProto), propsToSkip).sort();
     let protoMethods = protoProps.filter(name => typeof localProto[name] == 'function' &&
                                          name != 'constructor');
     ok(protoMethods.length > 0, "Need something to test");
     is(xrayProto, iwin[classname].prototype, "Xray proto is correct");
     is(xrayProto, xray.__proto__, "Proto accessors agree");
-    var protoProto = classname == "Object" ? null : iwin.Object.prototype;
-    is(Object.getPrototypeOf(xrayProto), protoProto, "proto proto is correct");
+    is(Object.getPrototypeOf(xrayProto), iwin.Object.prototype, "proto proto is correct");
     for (let name of protoMethods) {
       info("Running tests for property: " + name);
       ok(xrayProto.hasOwnProperty(name), "proto should have the property as own");
       ok(!xray.hasOwnProperty(name), "instance should not have the property as own");
       let method = xrayProto[name];
       is(typeof method, 'function', "Methods from Xrays are functions");
       is(global(method), window, "Methods from Xrays are local");
       ok(method instanceof Function, "instanceof works on methods from Xrays");
@@ -206,97 +164,12 @@ https://bugzilla.mozilla.org/show_bug.cg
     // Test the self-hosted toLocaleString.
     var d = new iwin.Date();
     isnot(d.toLocaleString, Cu.unwaiveXrays(d.wrappedJSObject.toLocaleString), "Different function identities");
     is(Cu.getGlobalForObject(d.toLocaleString), window, "Xray global is correct");
     is(Cu.getGlobalForObject(d.wrappedJSObject.toLocaleString), iwin, "Underlying global is correct");
     is(d.toLocaleString('de-DE'), d.wrappedJSObject.toLocaleString('de-DE'), "Results match");
   }
 
-  function testObject() {
-    testXray('Object', iwin.Object.create(new iwin.Object()), new iwin.Object(), []);
-
-    // Construct an object full of tricky things.
-    var trickyObject =
-      iwin.eval('new Object({ \
-                   primitiveProp: 42, objectProp: { foo: 2 }, \
-                   xoProp: top.location, hasOwnProperty: 10, \
-                   get getterProp() { return 2; }, \
-                   set setterProp(x) { }, \
-                   get getterSetterProp() { return 3; }, \
-                   set getterSetterProp(x) { }, \
-                   callableProp: function() { }, \
-                   nonXrayableProp: new WeakMap() })');
-
-    // Make sure it looks right under the hood.
-    is(trickyObject.wrappedJSObject.getterProp, 2, "Underlying object has getter");
-    is(Cu.unwaiveXrays(trickyObject.wrappedJSObject.xoProp), top.location, "Underlying object has xo property");
-
-    // Test getOwnPropertyNames.
-    is(Object.getOwnPropertyNames(trickyObject).sort().toSource(),
-       ['objectProp', 'primitiveProp'].toSource(), "getOwnPropertyNames should be filtered correctly");
-
-    // Test iteration and in-place modification. Beware of 'expando', which is the property
-    // we placed on the xray proto.
-    var propCount = 0;
-    for (let prop in trickyObject) {
-      if (prop == 'primitiveProp')
-        trickyObject[prop] = trickyObject[prop] - 10;
-      if (prop != 'expando')
-        trickyObject[prop] = trickyObject[prop];
-      ++propCount;
-    }
-    is(propCount, 3, "Should iterate the correct number of times");
-
-    // Test Object.keys.
-    is(Object.keys(trickyObject).sort().toSource(),
-       ['objectProp', 'primitiveProp'].toSource(), "Object.keys should be filtered correctly");
-
-    // Test getOwnPropertyDescriptor.
-    is(trickyObject.primitiveProp, 32, "primitive prop works");
-    is(trickyObject.objectProp.foo, 2, "object prop works");
-    is(typeof trickyObject.callableProp, 'undefined', "filtering works correctly");
-    is(Object.getOwnPropertyDescriptor(trickyObject, 'primitiveProp').value, 32, "getOwnPropertyDescriptor works");
-    is(Object.getOwnPropertyDescriptor(trickyObject, 'xoProp'), undefined, "filtering works with getOwnPropertyDescriptor");
-
-    // Test defineProperty.
-
-    trickyObject.primitiveSetByXray = 'fourty two';
-    is(trickyObject.primitiveSetByXray, 'fourty two', "Can set primitive correctly over Xray (ready via Xray)");
-    is(trickyObject.wrappedJSObject.primitiveSetByXray, 'fourty two', "Can set primitive correctly over Xray (ready via Waiver)");
-
-    var newContentObject = iwin.eval('new Object({prop: 99, get getterProp() { return 2; }})');
-    trickyObject.objectSetByXray = newContentObject;
-    is(trickyObject.objectSetByXray.prop, 99, "Can set object correctly over Xray (ready via Xray)");
-    is(trickyObject.wrappedJSObject.objectSetByXray.prop, 99, "Can set object correctly over Xray (ready via Waiver)");
-    checkThrows(function() { trickyObject.rejectedProp = {foo: 33}}, /cross-origin object/,
-                "Should reject privileged object property definition");
-
-    // Test JSON.stringify.
-    var jsonStr = JSON.stringify(newContentObject);
-    ok(/prop/.test(jsonStr), "JSON stringification should work: " + jsonStr);
-
-    // Test deletion.
-    delete newContentObject.prop;
-    ok(!newContentObject.hasOwnProperty('prop'), "Deletion should work");
-    ok(!newContentObject.wrappedJSObject.hasOwnProperty('prop'), "Deletion should forward");
-    delete newContentObject.getterProp;
-    ok(newContentObject.wrappedJSObject.hasOwnProperty('getterProp'), "Deletion be no-op for filtered property");
-
-    // We should be able to overwrite an existing accessor prop and convert it
-    // to a value prop.
-    is(trickyObject.wrappedJSObject.getterSetterProp, 3, "Underlying object has getter");
-    is(trickyObject.getterSetterProp, undefined, "Filtering properly over Xray");
-    trickyObject.getterSetterProp = 'redefined';
-    is(trickyObject.getterSetterProp, 'redefined', "Redefinition works");
-    is(trickyObject.wrappedJSObject.getterSetterProp, 'redefined', "Redefinition forwards");
-
-    checkThrows(function() { trickyObject.hasOwnProperty = 33; }, /shadow/,
-                "Should reject shadowing of pre-existing inherited properties over Xrays");
-
-    checkThrows(function() { Object.defineProperty(trickyObject, 'rejectedProp', { get: function() {}}); },
-                /accessor property/, "Should reject accessor property definition");
-  }
-
   ]]>
   </script>
   <iframe id="ifr" onload="go();" src="http://example.org/tests/js/xpconnect/tests/mochitest/file_empty.html" />
 </window>
--- a/js/xpconnect/wrappers/WrapperFactory.cpp
+++ b/js/xpconnect/wrappers/WrapperFactory.cpp
@@ -115,31 +115,16 @@ WrapperFactory::DoubleWrap(JSContext *cx
 {
     if (flags & WrapperFactory::WAIVE_XRAY_WRAPPER_FLAG) {
         JSAutoCompartment ac(cx, obj);
         return WaiveXray(cx, obj);
     }
     return obj;
 }
 
-// In general, we're trying to deprecate COWs incrementally as we introduce
-// Xrays to the corresponding object types. But switching off COWs for Object
-// instances would be too tumultuous at present, so we punt on that for later.
-static bool
-ForceCOWBehavior(JSObject *obj)
-{
-    if (IdentifyStandardInstanceOrPrototype(obj) == JSProto_Object) {
-        MOZ_ASSERT(GetXrayType(obj) == XrayForJSObject,
-                   "We should use XrayWrappers for standard ES Object instances "
-                   "modulo this hack");
-        return true;
-    }
-    return false;
-}
-
 JSObject *
 WrapperFactory::PrepareForWrapping(JSContext *cx, HandleObject scope,
                                    HandleObject objArg, unsigned flags)
 {
     RootedObject obj(cx, objArg);
     // Outerize any raw inner objects at the entry point here, so that we don't
     // have to worry about them for the rest of the wrapping code.
     if (js::IsInnerObject(obj)) {
@@ -179,17 +164,17 @@ WrapperFactory::PrepareForWrapping(JSCon
     // NB: We now remap all non-subsuming access of standard prototypes.
     //
     // NB: We need to ignore domain here so that the security relationship we
     // compute here can't change over time. See the comment above the other
     // subsumes call below.
     bool subsumes = AccessCheck::subsumes(js::GetContextCompartment(cx),
                                           js::GetObjectCompartment(obj));
     XrayType xrayType = GetXrayType(obj);
-    if (!subsumes && (xrayType == NotXray || ForceCOWBehavior(obj))) {
+    if (!subsumes && xrayType == NotXray) {
         JSProtoKey key = JSProto_Null;
         {
             JSAutoCompartment ac(cx, obj);
             key = IdentifyStandardPrototype(obj);
         }
         if (key != JSProto_Null) {
             RootedObject homeProto(cx);
             if (!JS_GetClassPrototype(cx, key, &homeProto))
@@ -428,22 +413,17 @@ WrapperFactory::Rewrap(JSContext *cx, Ha
     // If UniversalXPConnect is enabled, this is just some dumb mochitest. Use
     // a vanilla CCW.
     if (xpc::IsUniversalXPConnectEnabled(target)) {
         wrapper = &CrossCompartmentWrapper::singleton;
     }
 
     // If this is a chrome object being exposed to content without Xrays, use
     // a COW.
-    //
-    // We make an exception for Object instances, because we still rely on COWs
-    // for those in a lot of places in the tree.
-    else if (originIsChrome && !targetIsChrome &&
-             (xrayType == NotXray || ForceCOWBehavior(obj)))
-    {
+    else if (originIsChrome && !targetIsChrome && xrayType == NotXray) {
         wrapper = &ChromeObjectWrapper::singleton;
     }
 
     // Normally, a non-xrayable non-waived content object that finds itself in
     // a privileged scope is wrapped with a CrossCompartmentWrapper, even though
     // the lack of a waiver _really_ should give it an opaque wrapper. This is
     // a bit too entrenched to change for content-chrome, but we can at least fix
     // it for XBL scopes.
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -13,17 +13,16 @@
 #include "nsContentUtils.h"
 
 #include "XPCWrapper.h"
 #include "xpcprivate.h"
 
 #include "jsapi.h"
 #include "jsprf.h"
 #include "nsJSUtils.h"
-#include "nsPrintfCString.h"
 
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/WindowBinding.h"
 #include "nsGlobalWindow.h"
 
 using namespace mozilla::dom;
 using namespace JS;
 using namespace mozilla;
@@ -39,17 +38,16 @@ namespace xpc {
 using namespace XrayUtils;
 
 // Whitelist for the standard ES classes we can Xray to.
 static bool
 IsJSXraySupported(JSProtoKey key)
 {
     switch (key) {
       case JSProto_Date:
-      case JSProto_Object:
         return true;
       default:
         return false;
     }
 }
 
 XrayType
 GetXrayType(JSObject *obj)
@@ -155,21 +153,16 @@ public:
     // NB: resolveOwnProperty may decide whether or not to cache what it finds
     // on the holder. If the result is not cached, the lookup will happen afresh
     // for each access, which is the right thing for things like dynamic NodeList
     // properties.
     virtual bool resolveOwnProperty(JSContext *cx, Wrapper &jsWrapper,
                                     HandleObject wrapper, HandleObject holder,
                                     HandleId id, MutableHandle<JSPropertyDescriptor> desc);
 
-    bool delete_(JSContext *cx, HandleObject wrapper, HandleId id, bool *bp) {
-        *bp = true;
-        return true;
-    }
-
     virtual void preserveWrapper(JSObject *target) = 0;
 
     static bool set(JSContext *cx, HandleObject wrapper, HandleObject receiver, HandleId id,
                     bool strict, MutableHandleValue vp);
 
     JSObject* getExpandoObject(JSContext *cx, HandleObject target,
                                HandleObject consumer);
     JSObject* ensureExpandoObject(JSContext *cx, HandleObject wrapper,
@@ -210,19 +203,19 @@ public:
     static const XrayType Type = XrayForWrappedNative;
 
     virtual bool resolveNativeProperty(JSContext *cx, HandleObject wrapper,
                                        HandleObject holder, HandleId id,
                                        MutableHandle<JSPropertyDescriptor> desc) MOZ_OVERRIDE;
     virtual bool resolveOwnProperty(JSContext *cx, Wrapper &jsWrapper, HandleObject wrapper,
                                     HandleObject holder, HandleId id,
                                     MutableHandle<JSPropertyDescriptor> desc) MOZ_OVERRIDE;
-    bool defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
-                        MutableHandle<JSPropertyDescriptor> desc,
-                        Handle<JSPropertyDescriptor> existingDesc, bool *defined);
+    static bool defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
+                               MutableHandle<JSPropertyDescriptor> desc,
+                               Handle<JSPropertyDescriptor> existingDesc, bool *defined);
     virtual bool enumerateNames(JSContext *cx, HandleObject wrapper, unsigned flags,
                                 AutoIdVector &props);
     static bool call(JSContext *cx, HandleObject wrapper,
                      const JS::CallArgs &args, js::Wrapper& baseInstance);
     static bool construct(JSContext *cx, HandleObject wrapper,
                           const JS::CallArgs &args, js::Wrapper& baseInstance);
 
     static bool isResolving(JSContext *cx, JSObject *holder, jsid id);
@@ -261,19 +254,19 @@ public:
     static const XrayType Type = XrayForDOMObject;
 
     virtual bool resolveNativeProperty(JSContext *cx, HandleObject wrapper,
                                        HandleObject holder, HandleId id,
                                        MutableHandle<JSPropertyDescriptor> desc) MOZ_OVERRIDE;
     virtual bool resolveOwnProperty(JSContext *cx, Wrapper &jsWrapper, HandleObject wrapper,
                                     HandleObject holder, HandleId id,
                                     MutableHandle<JSPropertyDescriptor> desc) MOZ_OVERRIDE;
-    bool defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
-                        MutableHandle<JSPropertyDescriptor> desc,
-                        Handle<JSPropertyDescriptor> existingDesc, bool *defined);
+    static bool defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
+                               MutableHandle<JSPropertyDescriptor> desc,
+                               Handle<JSPropertyDescriptor> existingDesc, bool *defined);
     static bool set(JSContext *cx, HandleObject wrapper, HandleObject receiver, HandleId id,
                     bool strict, MutableHandleValue vp);
     virtual bool enumerateNames(JSContext *cx, HandleObject wrapper, unsigned flags,
                                 AutoIdVector &props);
     static bool call(JSContext *cx, HandleObject wrapper,
                      const JS::CallArgs &args, js::Wrapper& baseInstance);
     static bool construct(JSContext *cx, HandleObject wrapper,
                           const JS::CallArgs &args, js::Wrapper& baseInstance);
@@ -306,21 +299,24 @@ public:
     {
         MOZ_ASSUME_UNREACHABLE("resolveNativeProperty hook should never be called with HasPrototype = 1");
     }
 
     virtual bool resolveOwnProperty(JSContext *cx, Wrapper &jsWrapper, HandleObject wrapper,
                                     HandleObject holder, HandleId id,
                                     MutableHandle<JSPropertyDescriptor> desc) MOZ_OVERRIDE;
 
-    bool delete_(JSContext *cx, HandleObject wrapper, HandleId id, bool *bp);
-
-    bool defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
-                        MutableHandle<JSPropertyDescriptor> desc,
-                        Handle<JSPropertyDescriptor> existingDesc, bool *defined);
+    static bool defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
+                               MutableHandle<JSPropertyDescriptor> desc,
+                               Handle<JSPropertyDescriptor> existingDesc, bool *defined)
+    {
+        // There's no useful per-trait work to do here. Punt back up to the common code.
+        *defined = false;
+        return true;
+    }
 
     virtual bool enumerateNames(JSContext *cx, HandleObject wrapper, unsigned flags,
                                 AutoIdVector &props);
 
     static bool call(JSContext *cx, HandleObject wrapper,
                      const JS::CallArgs &args, js::Wrapper& baseInstance)
     {
         // We'll handle this when we start supporting Functions.
@@ -345,25 +341,18 @@ public:
 
     typedef ResolvingIdDummy ResolvingIdImpl;
 
     bool getPrototypeOf(JSContext *cx, JS::HandleObject wrapper,
                                JS::HandleObject target,
                                JS::MutableHandleObject protop)
     {
         RootedObject holder(cx, ensureHolder(cx, wrapper));
-        JSProtoKey key = getProtoKey(holder);
-        if (isPrototype(holder)) {
-            if (key == JSProto_Object) {
-                protop.set(nullptr);
-                return true;
-            }
-            key = JSProto_Object;
-        }
-
+        JSProtoKey key = isPrototype(holder) ? JSProto_Object
+                                             : getProtoKey(holder);
         {
             JSAutoCompartment ac(cx, target);
             if (!JS_GetClassPrototype(cx, key, protop))
                 return nullptr;
         }
         return JS_WrapObject(cx, protop);
     }
 
@@ -385,175 +374,57 @@ public:
         int32_t key = js::GetReservedSlot(holder, SLOT_PROTOKEY).toInt32();
         return static_cast<JSProtoKey>(key);
     }
 
     static bool isPrototype(JSObject *holder) {
         return js::GetReservedSlot(holder, SLOT_ISPROTOTYPE).toBoolean();
     }
 
-    static bool getOwnPropertyFromTargetIfSafe(JSContext *cx,
-                                               HandleObject target,
-                                               HandleObject wrapper,
-                                               HandleId id,
-                                               MutableHandle<JSPropertyDescriptor> desc);
-
     static const JSClass HolderClass;
     static JSXrayTraits singleton;
 };
 
 const JSClass JSXrayTraits::HolderClass = {
     "JSXrayHolder", JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT),
     JS_PropertyStub, JS_DeletePropertyStub,
     JS_PropertyStub, JS_StrictPropertyStub,
     JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub
 };
 
-inline bool
-SilentFailure(JSContext *cx, HandleId id, const char *reason)
-{
-#ifdef DEBUG
-    nsDependentJSString name(id);
-    AutoFilename filename;
-    unsigned line = 0;
-    DescribeScriptedCaller(cx, &filename, &line);
-    NS_WARNING(nsPrintfCString("Denied access to property |%s| on Xrayed Object: %s (@%s:%u)",
-                               NS_LossyConvertUTF16toASCII(name).get(), reason,
-                               filename.get(), line).get());
-#endif
-    return true;
-}
-
-bool JSXrayTraits::getOwnPropertyFromTargetIfSafe(JSContext *cx,
-                                                  HandleObject target,
-                                                  HandleObject wrapper,
-                                                  HandleId idArg,
-                                                  MutableHandle<JSPropertyDescriptor> outDesc)
-{
-    // Note - This function operates in the target compartment, because it
-    // avoids a bunch of back-and-forth wrapping in enumerateNames.
-    MOZ_ASSERT(getTargetObject(wrapper) == target);
-    MOZ_ASSERT(js::IsObjectInContextCompartment(target, cx));
-    MOZ_ASSERT(WrapperFactory::IsXrayWrapper(wrapper));
-    MOZ_ASSERT(outDesc.object() == nullptr);
-
-    RootedId id(cx, idArg);
-    if (!JS_WrapId(cx, &id))
-        return false;
-    Rooted<JSPropertyDescriptor> desc(cx);
-    if (!JS_GetOwnPropertyDescriptorById(cx, target, id, &desc))
-        return false;
-
-    // If the property doesn't exist at all, we're done.
-    if (!desc.object())
-        return true;
-
-    // Disallow accessor properties.
-    if (desc.hasGetterOrSetter())
-        return SilentFailure(cx, id, "Property has accessor");
-
-    // Apply extra scrutiny to objects.
-    if (desc.value().isObject()) {
-        RootedObject propObj(cx, js::UncheckedUnwrap(&desc.value().toObject()));
-        JSAutoCompartment ac(cx, propObj);
-
-        // Disallow non-subsumed objects.
-        if (!AccessCheck::subsumes(target, propObj))
-            return SilentFailure(cx, id, "Value not same-origin with target");
-
-        // Disallow non-Xrayable objects.
-        if (GetXrayType(propObj) == NotXray) {
-            // Note - We're going add Xrays for Arrays/TypedArrays soon in
-            // bug 987163, so we don't want to cause unnecessary compat churn
-            // by making xrayedObj.arrayProp stop working temporarily, and then
-            // start working again. At the same time, this is an important check,
-            // and this patch wouldn't be as useful without it. So we just
-            // forcibly override the behavior here for Arrays until bug 987163
-            // lands.
-            JSProtoKey key = IdentifyStandardInstanceOrPrototype(propObj);
-            if (key != JSProto_Array && key != JSProto_Uint8ClampedArray &&
-                key != JSProto_Int8Array && key != JSProto_Uint8Array &&
-                key != JSProto_Int16Array && key != JSProto_Uint16Array &&
-                key != JSProto_Int32Array && key != JSProto_Uint32Array &&
-                key != JSProto_Float32Array && key != JSProto_Float64Array)
-            {
-                return SilentFailure(cx, id, "Value not Xrayable");
-            }
-        }
-
-        // Disallow callables.
-        if (JS_ObjectIsCallable(cx, propObj))
-            return SilentFailure(cx, id, "Value is callable");
-    }
-
-    // Disallow any property that shadows something on its (Xrayed)
-    // prototype chain.
-    JSAutoCompartment ac2(cx, wrapper);
-    RootedObject proto(cx);
-    bool foundOnProto = false;
-    if (!JS_GetPrototype(cx, wrapper, &proto) ||
-        (proto && !JS_HasPropertyById(cx, proto, id, &foundOnProto)))
-    {
-        return false;
-    }
-    if (foundOnProto)
-        return SilentFailure(cx, id, "Value shadows a property on the standard prototype");
-
-    // We made it! Assign over the descriptor, and don't forget to wrap.
-    outDesc.assign(desc.get());
-    return true;
-}
-
 bool
 JSXrayTraits::resolveOwnProperty(JSContext *cx, Wrapper &jsWrapper,
                                  HandleObject wrapper, HandleObject holder,
                                  HandleId id,
                                  MutableHandle<JSPropertyDescriptor> desc)
 {
     // Call the common code.
     bool ok = XrayTraits::resolveOwnProperty(cx, jsWrapper, wrapper, holder,
                                              id, desc);
     if (!ok || desc.object())
         return ok;
 
-    RootedObject target(cx, getTargetObject(wrapper));
-    if (!isPrototype(holder)) {
-        // For object instances, we expose some properties from the underlying
-        // object, but only after filtering them carefully.
-        switch (getProtoKey(holder)) {
-          case JSProto_Object:
-            {
-                JSAutoCompartment ac(cx, target);
-                if (!getOwnPropertyFromTargetIfSafe(cx, target, wrapper, id, desc))
-                    return false;
-            }
-            return JS_WrapPropertyDescriptor(cx, desc);
-
-          default:
-            // Most instance (non-prototypes) Xrays don't have anything on them.
-            break;
-        }
-
-        // The rest of this function applies only to prototypes.
+    // Non-prototypes don't have anything on them yet.
+    if (!isPrototype(holder))
         return true;
-    }
 
     // The non-HasPrototypes semantics implemented by traditional Xrays are kind
     // of broken with respect to |own|-ness and the holder. The common code
     // muddles through by only checking the holder for non-|own| lookups, but
     // that doesn't work for us. So we do an explicit holder check here, and hope
     // that this mess gets fixed up soon.
     if (!JS_GetPropertyDescriptorById(cx, holder, id, desc))
         return false;
     if (desc.object()) {
         desc.object().set(wrapper);
         return true;
     }
 
     // Grab the JSClass. We require all Xrayable classes to have a ClassSpec.
+    RootedObject target(cx, getTargetObject(wrapper));
     const js::Class *clasp = js::GetObjectClass(target);
     JSProtoKey protoKey = JSCLASS_CACHED_PROTO_KEY(clasp);
     MOZ_ASSERT(protoKey == getProtoKey(holder));
     MOZ_ASSERT(clasp->spec.defined());
 
     // Handle the 'constructor' property.
     if (id == GetRTIdByIndex(cx, XPCJSRuntime::IDX_CONSTRUCTOR)) {
         RootedObject constructor(cx);
@@ -654,136 +525,29 @@ JSXrayTraits::resolveOwnProperty(JSConte
                                      desc.getter(), desc.setter()) &&
                JS_GetPropertyDescriptorById(cx, holder, id, desc);
     }
 
     return true;
 }
 
 bool
-JSXrayTraits::delete_(JSContext *cx, HandleObject wrapper, HandleId id, bool *bp)
+JSXrayTraits::enumerateNames(JSContext *cx, HandleObject wrapper, unsigned flags,
+                             AutoIdVector &props)
 {
     RootedObject holder(cx, ensureHolder(cx, wrapper));
-
-    // If we're using Object Xrays, we allow callers to attempt to delete any
-    // property from the underlying object that they are able to resolve. Note
-    // that this deleting may fail if the property is non-configurable.
-    bool isObjectInstance = getProtoKey(holder) == JSProto_Object && !isPrototype(holder);
-    if (isObjectInstance) {
-        RootedObject target(cx, getTargetObject(wrapper));
-        JSAutoCompartment ac(cx, target);
-        Rooted<JSPropertyDescriptor> desc(cx);
-        if (!getOwnPropertyFromTargetIfSafe(cx, target, wrapper, id, &desc))
-            return false;
-        if (desc.object())
-            return JS_DeletePropertyById2(cx, target, id, bp);
-    }
-    *bp = true;
-    return true;
-}
-
-bool
-JSXrayTraits::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
-                               MutableHandle<JSPropertyDescriptor> desc,
-                               Handle<JSPropertyDescriptor> existingDesc,
-                               bool *defined)
-{
-    *defined = false;
-    RootedObject holder(cx, ensureHolder(cx, wrapper));
     if (!holder)
         return false;
 
-
-    // Object instances are special. For that case, we forward property
-    // definitions to the underlying object if the following conditions are met:
-    // * The property being defined is a value-prop.
-    // * The property being defined is either a primitive or subsumed by the target.
-    // * As seen from the Xray, any existing property that we would overwrite is an
-    //   |own| value-prop.
-    //
-    // To avoid confusion, we disallow expandos on Object instances, and
-    // therefore raise an exception here if the above conditions aren't met.
-    bool isObjectInstance = getProtoKey(holder) == JSProto_Object && !isPrototype(holder);
-    if (isObjectInstance) {
-        RootedObject target(cx, getTargetObject(wrapper));
-        if (desc.hasGetterOrSetter()) {
-            JS_ReportError(cx, "Not allowed to define accessor property on [Object] XrayWrapper");
-            return false;
-        }
-        if (desc.value().isObject() &&
-            !AccessCheck::subsumes(target, js::UncheckedUnwrap(&desc.value().toObject())))
-        {
-            JS_ReportError(cx, "Not allowed to define cross-origin object as property on [Object] XrayWrapper");
-            return false;
-        }
-        if (existingDesc.hasGetterOrSetter()) {
-            JS_ReportError(cx, "Not allowed to overwrite accessor property on [Object] XrayWrapper");
-            return false;
-        }
-        if (existingDesc.object() && existingDesc.object() != wrapper) {
-            JS_ReportError(cx, "Not allowed to shadow non-own Xray-resolved property on [Object] XrayWrapper");
-            return false;
-        }
-
-        JSAutoCompartment ac(cx, target);
-        if (!JS_WrapPropertyDescriptor(cx, desc) ||
-            !JS_DefinePropertyById(cx, target, id, desc.value(), desc.attributes(),
-                                   JS_PropertyStub, JS_StrictPropertyStub))
-        {
-            return false;
-        }
-        *defined = true;
+    // Non-prototypes don't have anything on them yet.
+    if (!isPrototype(holder))
         return true;
-    }
-
-    return true;
-}
-
-bool
-JSXrayTraits::enumerateNames(JSContext *cx, HandleObject wrapper, unsigned flags,
-                             AutoIdVector &props)
-{
-    RootedObject target(cx, getTargetObject(wrapper));
-    RootedObject holder(cx, ensureHolder(cx, wrapper));
-    if (!holder)
-        return false;
-
-    if (!isPrototype(holder)) {
-        // For object instances, we expose some properties from the underlying
-        // object, but only after filtering them carefully.
-        switch (getProtoKey(holder)) {
-          case JSProto_Object:
-            MOZ_ASSERT(props.empty());
-            {
-                JSAutoCompartment ac(cx, target);
-                AutoIdVector targetProps(cx);
-                if (!js::GetPropertyNames(cx, target, flags | JSITER_OWNONLY, &targetProps))
-                    return false;
-                // Loop over the properties, and only pass along the ones that
-                // we determine to be safe.
-                for (size_t i = 0; i < targetProps.length(); ++i) {
-                    Rooted<JSPropertyDescriptor> desc(cx);
-                    RootedId id(cx, targetProps[i]);
-                    if (!getOwnPropertyFromTargetIfSafe(cx, target, wrapper, id, &desc))
-                        return false;
-                    if (desc.object())
-                        props.append(id);
-                }
-            }
-            return JS_WrapAutoIdVector(cx, props);
-          default:
-            // Most instance (non-prototypes) Xrays don't have anything on them.
-            break;
-        }
-
-        // The rest of this function applies only to prototypes.
-        return true;
-    }
 
     // Grab the JSClass. We require all Xrayable classes to have a ClassSpec.
+    RootedObject target(cx, getTargetObject(wrapper));
     const js::Class *clasp = js::GetObjectClass(target);
     MOZ_ASSERT(JSCLASS_CACHED_PROTO_KEY(clasp) == getProtoKey(holder));
     MOZ_ASSERT(clasp->spec.defined());
 
     // Intern all the strings, and pass theme to the caller.
     for (const JSFunctionSpec *fs = clasp->spec.prototypeFunctions; fs && fs->name; ++fs) {
         RootedString str(cx, JS_InternString(cx, fs->name));
         if (!str)
@@ -2273,30 +2037,24 @@ RecreateLostWaivers(JSContext *cx, JSPro
 template <typename Base, typename Traits>
 bool
 XrayWrapper<Base, Traits>::defineProperty(JSContext *cx, HandleObject wrapper,
                                           HandleId id, MutableHandle<JSPropertyDescriptor> desc)
 {
     assertEnteredPolicy(cx, wrapper, id, BaseProxyHandler::SET);
 
     Rooted<JSPropertyDescriptor> existing_desc(cx);
-    if (!JS_GetPropertyDescriptorById(cx, wrapper, id, &existing_desc))
+    if (!getOwnPropertyDescriptor(cx, wrapper, id, &existing_desc))
         return false;
 
-    // Note that the check here is intended to differentiate between own and
-    // non-own properties, since the above lookup is not limited to own
-    // properties. At present, this may not always do the right thing because
-    // we often lie (sloppily) about where we found properties and set
-    // desc.object() to |wrapper|. Once we fully fix our Xray prototype semantics,
-    // this should work as intended.
-    if (existing_desc.object() == wrapper && existing_desc.isPermanent())
+    if (existing_desc.object() && existing_desc.isPermanent())
         return true; // silently ignore attempt to overwrite native property
 
     bool defined = false;
-    if (!Traits::singleton.defineProperty(cx, wrapper, id, desc, existing_desc, &defined))
+    if (!Traits::defineProperty(cx, wrapper, id, desc, existing_desc, &defined))
         return false;
     if (defined)
         return true;
 
     // We're placing an expando. The expando objects live in the target
     // compartment, so we need to enter it.
     RootedObject target(cx, Traits::singleton.getTargetObject(wrapper));
     JSAutoCompartment ac(cx, target);
@@ -2339,18 +2097,18 @@ XrayWrapper<Base, Traits>::delete_(JSCon
 
     // Check the expando object.
     RootedObject target(cx, Traits::getTargetObject(wrapper));
     RootedObject expando(cx, Traits::singleton.getExpandoObject(cx, target, wrapper));
     if (expando) {
         JSAutoCompartment ac(cx, expando);
         return JS_DeletePropertyById2(cx, expando, id, bp);
     }
-
-    return Traits::singleton.delete_(cx, wrapper, id, bp);
+    *bp = true;
+    return true;
 }
 
 template <typename Base, typename Traits>
 bool
 XrayWrapper<Base, Traits>::enumerate(JSContext *cx, HandleObject wrapper, unsigned flags,
                                      AutoIdVector &props)
 {
     assertEnteredPolicy(cx, wrapper, JSID_VOID, BaseProxyHandler::ENUMERATE);