Backed out changeset d201babc2e84 (bug 1103368)
authorWes Kocher <wkocher@mozilla.com>
Mon, 24 Nov 2014 17:03:52 -0800
changeset 217298 56ebb99d774eef30488e7fcca268308ed15e0660
parent 217297 c80672f72db67fa665c49642f2a73801b27249d8
child 217299 ae31d26695113dbe96aecb29e3055546526ec88b
push idunknown
push userunknown
push dateunknown
bugs1103368
milestone36.0a1
backs outd201babc2e846261e50b2e31893e486a4986dee0
Backed out changeset d201babc2e84 (bug 1103368)
js/ipc/JavaScriptShared.cpp
js/ipc/WrapperAnswer.cpp
js/src/jsobj.cpp
js/src/proxy/DirectProxyHandler.cpp
--- a/js/ipc/JavaScriptShared.cpp
+++ b/js/ipc/JavaScriptShared.cpp
@@ -527,17 +527,18 @@ JavaScriptShared::findObjectById(JSConte
             return nullptr;
     } else {
         if (!JS_WrapObject(cx, &obj))
             return nullptr;
     }
     return obj;
 }
 
-static const uint64_t UnknownPropertyOp = 1;
+static const uint64_t DefaultPropertyOp = 1;
+static const uint64_t UnknownPropertyOp = 2;
 
 bool
 JavaScriptShared::fromDescriptor(JSContext *cx, Handle<JSPropertyDescriptor> desc,
                                  PPropertyDescriptor *out)
 {
     out->attrs() = desc.attributes();
     if (!toVariant(cx, desc.value(), &out->value()))
         return false;
@@ -550,32 +551,32 @@ JavaScriptShared::fromDescriptor(JSConte
     } else if (desc.hasGetterObject()) {
         JSObject *getter = desc.getterObject();
         ObjectVariant objVar;
         if (!toObjectVariant(cx, getter, &objVar))
             return false;
         out->getter() = objVar;
     } else {
         if (desc.getter() == JS_PropertyStub)
-            out->getter() = 0;
+            out->getter() = DefaultPropertyOp;
         else
             out->getter() = UnknownPropertyOp;
     }
 
     if (!desc.setter()) {
         out->setter() = 0;
     } else if (desc.hasSetterObject()) {
         JSObject *setter = desc.setterObject();
         ObjectVariant objVar;
         if (!toObjectVariant(cx, setter, &objVar))
             return false;
         out->setter() = objVar;
     } else {
         if (desc.setter() == JS_StrictPropertyStub)
-            out->setter() = 0;
+            out->setter() = DefaultPropertyOp;
         else
             out->setter() = UnknownPropertyOp;
     }
 
     return true;
 }
 
 bool
@@ -605,29 +606,35 @@ JavaScriptShared::toDescriptor(JSContext
         out.setGetter(nullptr);
     } else if (in.attrs() & JSPROP_GETTER) {
         Rooted<JSObject*> getter(cx);
         getter = fromObjectVariant(cx, in.getter().get_ObjectVariant());
         if (!getter)
             return false;
         out.setGetter(JS_DATA_TO_FUNC_PTR(JSPropertyOp, getter.get()));
     } else {
-        out.setGetter(UnknownPropertyStub);
+        if (in.getter().get_uint64_t() == DefaultPropertyOp)
+            out.setGetter(JS_PropertyStub);
+        else
+            out.setGetter(UnknownPropertyStub);
     }
 
     if (in.setter().type() == GetterSetter::Tuint64_t && !in.setter().get_uint64_t()) {
         out.setSetter(nullptr);
     } else if (in.attrs() & JSPROP_SETTER) {
         Rooted<JSObject*> setter(cx);
         setter = fromObjectVariant(cx, in.setter().get_ObjectVariant());
         if (!setter)
             return false;
         out.setSetter(JS_DATA_TO_FUNC_PTR(JSStrictPropertyOp, setter.get()));
     } else {
-        out.setSetter(UnknownStrictPropertyStub);
+        if (in.setter().get_uint64_t() == DefaultPropertyOp)
+            out.setSetter(JS_StrictPropertyStub);
+        else
+            out.setSetter(UnknownStrictPropertyStub);
     }
 
     return true;
 }
 
 bool
 JavaScriptShared::toObjectOrNullVariant(JSContext *cx, JSObject *obj, ObjectOrNullVariant *objVarp)
 {
--- a/js/ipc/WrapperAnswer.cpp
+++ b/js/ipc/WrapperAnswer.cpp
@@ -185,22 +185,18 @@ WrapperAnswer::RecvDefineProperty(const 
         return fail(cx, rs);
     }
 
     if (!JS_DefinePropertyById(cx, obj, id, desc.value(),
                                // Descrriptors never store JSNatives for
                                // accessors: they have either JSFunctions or
                                // JSPropertyOps.
                                desc.attributes() | JSPROP_PROPOP_ACCESSORS,
-                               JS_PROPERTYOP_GETTER(desc.getter()
-                                                    ? desc.getter()
-                                                    : JS_PropertyStub),
-                               JS_PROPERTYOP_SETTER(desc.setter()
-                                                    ? desc.setter()
-                                                    : JS_StrictPropertyStub)))
+                               JS_PROPERTYOP_GETTER(desc.getter()),
+                               JS_PROPERTYOP_SETTER(desc.setter())))
     {
         return fail(cx, rs);
     }
 
     return ok(rs);
 }
 
 bool
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -669,19 +669,16 @@ ApplyOrDefaultAttributes(unsigned attrs,
 // See comments on CheckDefineProperty in jsfriendapi.h.
 //
 // DefinePropertyOnObject has its own implementation of these checks.
 //
 JS_FRIEND_API(bool)
 js::CheckDefineProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue value,
                         unsigned attrs, PropertyOp getter, StrictPropertyOp setter)
 {
-    MOZ_ASSERT(getter != JS_PropertyStub);
-    MOZ_ASSERT(setter != JS_StrictPropertyStub);
-
     if (!obj->isNative())
         return true;
 
     // ES5 8.12.9 Step 1. Even though we know obj is native, we use generic
     // APIs for shorter, more readable code.
     Rooted<PropertyDescriptor> desc(cx);
     if (!GetOwnPropertyDescriptor(cx, obj, id, &desc))
         return false;
@@ -693,18 +690,18 @@ js::CheckDefineProperty(JSContext *cx, H
 
     // This does not have to check obj's extensibility when !desc.obj (steps
     // 2-3) because the low-level methods JSObject::{add,put}Property check
     // for that.
     if (desc.object() && desc.isPermanent()) {
         // Steps 6-11, skipping step 10.a.ii. Prohibit redefining a permanent
         // property with different metadata, except to make a writable property
         // non-writable.
-        if (getter != desc.getter() ||
-            setter != desc.setter() ||
+        if ((getter != desc.getter() && !(getter == JS_PropertyStub && !desc.getter())) ||
+            (setter != desc.setter() && !(setter == JS_StrictPropertyStub && !desc.setter())) ||
             (attrs != desc.attributes() && attrs != (desc.attributes() | JSPROP_READONLY)))
         {
             return Throw(cx, id, JSMSG_CANT_REDEFINE_PROP);
         }
 
         // Step 10.a.ii. Prohibit changing the value of a non-configurable,
         // non-writable data property.
         if ((desc.attributes() & (JSPROP_GETTER | JSPROP_SETTER | JSPROP_READONLY)) == JSPROP_READONLY) {
--- a/js/src/proxy/DirectProxyHandler.cpp
+++ b/js/src/proxy/DirectProxyHandler.cpp
@@ -36,18 +36,23 @@ bool
 DirectProxyHandler::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
                                    MutableHandle<PropertyDescriptor> desc) const
 {
     assertEnteredPolicy(cx, proxy, id, SET);
     RootedObject target(cx, proxy->as<ProxyObject>().target());
     RootedValue v(cx, desc.value());
     return CheckDefineProperty(cx, target, id, v, desc.attributes(),
                                desc.getter(), desc.setter()) &&
-           JSObject::defineGeneric(cx, target, id, v, desc.getter(), desc.setter(),
-                                   desc.attributes());
+           JS_DefinePropertyById(cx, target, id, v,
+                                 // Descriptors never store JSNatives for
+                                 // accessors: they have either JSFunctions or
+                                 // JSPropertyOps.
+                                 desc.attributes() | JSPROP_PROPOP_ACCESSORS,
+                                 JS_PROPERTYOP_GETTER(desc.getter()),
+                                 JS_PROPERTYOP_SETTER(desc.setter()));
 }
 
 bool
 DirectProxyHandler::ownPropertyKeys(JSContext *cx, HandleObject proxy,
                                     AutoIdVector &props) const
 {
     assertEnteredPolicy(cx, proxy, JSID_VOID, ENUMERATE);
     RootedObject target(cx, proxy->as<ProxyObject>().target());