Bug 1113369, part 3 - [[DefineOwnProperty]] ObjectOpResult support. r=Waldo, r=bz in dom, r=dvander in js/ipc, r=bholley in js/xpconnect.

Add an ObjectOpResult out-param for DefineProperty functions everywhere. We leave a few js::DefineProperty() convenience functions with no *result out-param. These have strict behavior: that is, they automatically check the result and throw if it is false. In bug 1125624 these strict signatures may end up being called DefinePropertyOrThrow, as that is what the spec calls it.
This commit is contained in:
Jason Orendorff 2015-01-30 11:37:07 -06:00
parent 143ed465ec
commit f43c96af4d
56 changed files with 641 additions and 439 deletions

View File

@ -159,7 +159,8 @@ bool
WindowNamedPropertiesHandler::defineProperty(JSContext* aCx,
JS::Handle<JSObject*> aProxy,
JS::Handle<jsid> aId,
JS::MutableHandle<JSPropertyDescriptor> aDesc) const
JS::MutableHandle<JSPropertyDescriptor> aDesc,
JS::ObjectOpResult &result) const
{
ErrorResult rv;
rv.ThrowTypeError(MSG_DEFINEPROPERTY_ON_GSP);

View File

@ -28,7 +28,8 @@ public:
virtual bool
defineProperty(JSContext* aCx, JS::Handle<JSObject*> aProxy,
JS::Handle<jsid> aId,
JS::MutableHandle<JSPropertyDescriptor> aDesc) const MOZ_OVERRIDE;
JS::MutableHandle<JSPropertyDescriptor> aDesc,
JS::ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool
ownPropNames(JSContext* aCx, JS::Handle<JSObject*> aProxy, unsigned flags,
JS::AutoIdVector& aProps) const MOZ_OVERRIDE;

View File

@ -1174,13 +1174,7 @@ nsDOMClassInfo::PostCreatePrototype(JSContext * cx, JSObject * aProto)
NS_ENSURE_SUCCESS(rv, rv);
if (!contentDefinedProperty && desc.object() && !desc.value().isUndefined() &&
!JS_DefineUCProperty(cx, global, mData->mNameUTF16,
NS_strlen(mData->mNameUTF16),
desc.value(),
// 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()))) {
NS_strlen(mData->mNameUTF16), desc)) {
return NS_ERROR_UNEXPECTED;
}

View File

@ -622,8 +622,8 @@ public:
virtual bool defineProperty(JSContext* cx,
JS::Handle<JSObject*> proxy,
JS::Handle<jsid> id,
JS::MutableHandle<JSPropertyDescriptor> desc)
const MOZ_OVERRIDE;
JS::MutableHandle<JSPropertyDescriptor> desc,
JS::ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool ownPropertyKeys(JSContext *cx,
JS::Handle<JSObject*> proxy,
JS::AutoIdVector &props) const MOZ_OVERRIDE;
@ -783,8 +783,8 @@ bool
nsOuterWindowProxy::defineProperty(JSContext* cx,
JS::Handle<JSObject*> proxy,
JS::Handle<jsid> id,
JS::MutableHandle<JSPropertyDescriptor> desc)
const
JS::MutableHandle<JSPropertyDescriptor> desc,
JS::ObjectOpResult &result) const
{
int32_t index = GetArrayIndexFromId(cx, id);
if (IsArrayIndex(index)) {
@ -792,7 +792,7 @@ nsOuterWindowProxy::defineProperty(JSContext* cx,
// since we have no indexed setter or indexed creator. That means
// throwing in strict mode (FIXME: Bug 828137), doing nothing in
// non-strict mode.
return true;
return result.succeed();
}
// For now, allow chrome code to define non-configurable properties
@ -803,7 +803,7 @@ nsOuterWindowProxy::defineProperty(JSContext* cx,
return ThrowErrorMessage(cx, MSG_DEFINE_NON_CONFIGURABLE_PROP_ON_WINDOW);
}
return js::Wrapper::defineProperty(cx, proxy, id, desc);
return js::Wrapper::defineProperty(cx, proxy, id, desc, result);
}
bool

View File

@ -1423,13 +1423,14 @@ XrayResolveOwnProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
bool
XrayDefineProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
JS::MutableHandle<JSPropertyDescriptor> desc, bool* defined)
JS::MutableHandle<JSPropertyDescriptor> desc,
JS::ObjectOpResult &result, bool *defined)
{
if (!js::IsProxy(obj))
return true;
return true;
const DOMProxyHandler* handler = GetDOMProxyHandler(obj);
return handler->defineProperty(cx, wrapper, id, desc, defined);
return handler->defineProperty(cx, wrapper, id, desc, result, defined);
}
template<typename SpecType>

View File

@ -2456,12 +2456,17 @@ XrayResolveOwnProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
* wrapper is the Xray JS object.
* obj is the target object of the Xray, a binding's instance object or a
* interface or interface prototype object.
* id and desc are the parameters for the property to be defined.
* result is the out-parameter indicating success (read it only if
* this returns true and also sets *defined to true).
* defined will be set to true if a property was set as a result of this call.
*/
bool
XrayDefineProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
JS::MutableHandle<JSPropertyDescriptor> desc, bool* defined);
JS::MutableHandle<JSPropertyDescriptor> desc,
JS::ObjectOpResult &result,
bool *defined);
/**
* Add to props the property keys of all indexed or named properties of obj and

View File

@ -7684,10 +7684,7 @@ class CGResolveHook(CGAbstractBindingMethod):
// has already defined it on the object. Don't try to also
// define it.
if (!desc.value().isUndefined() &&
!JS_DefinePropertyById(cx, obj, id, desc.value(),
desc.attributes() | JSPROP_PROPOP_ACCESSORS,
JS_PROPERTYOP_GETTER(desc.getter()),
JS_PROPERTYOP_SETTER(desc.setter()))) {
!JS_DefinePropertyById(cx, obj, id, desc)) {
return false;
}
*resolvedp = true;
@ -9682,10 +9679,7 @@ class CGResolveOwnPropertyViaResolve(CGAbstractBindingMethod):
// try to also define it.
if (objDesc.object() &&
!objDesc.value().isUndefined() &&
!JS_DefinePropertyById(cx, obj, id, objDesc.value(),
objDesc.attributes() | JSPROP_PROPOP_ACCESSORS,
JS_PROPERTYOP_GETTER(objDesc.getter()),
JS_PROPERTYOP_SETTER(objDesc.setter()))) {
!JS_DefinePropertyById(cx, obj, id, objDesc)) {
return false;
}
}
@ -10221,10 +10215,13 @@ class CGDOMJSProxyHandler_getOwnPropDescriptor(ClassMethod):
class CGDOMJSProxyHandler_defineProperty(ClassMethod):
def __init__(self, descriptor):
# The usual convention is to name the ObjectOpResult out-parameter
# `result`, but that name is a bit overloaded around here.
args = [Argument('JSContext*', 'cx'),
Argument('JS::Handle<JSObject*>', 'proxy'),
Argument('JS::Handle<jsid>', 'id'),
Argument('JS::MutableHandle<JSPropertyDescriptor>', 'desc'),
Argument('JS::ObjectOpResult&', 'opresult'),
Argument('bool*', 'defined')]
ClassMethod.__init__(self, "defineProperty", "bool", args, virtual=True, override=True, const=True)
self.descriptor = descriptor
@ -10242,7 +10239,7 @@ class CGDOMJSProxyHandler_defineProperty(ClassMethod):
if (IsArrayIndex(index)) {
*defined = true;
$*{callSetter}
return true;
return opresult.succeed();
}
""",
callSetter=CGProxyIndexedSetter(self.descriptor).define())
@ -10255,7 +10252,9 @@ class CGDOMJSProxyHandler_defineProperty(ClassMethod):
set += fill(
"""
if (IsArrayIndex(GetArrayIndexFromId(cx, id))) {
return js::IsInNonStrictPropertySet(cx) || ThrowErrorMessage(cx, MSG_NO_INDEXED_SETTER, "${name}");
return js::IsInNonStrictPropertySet(cx)
? opresult.succeed()
: ThrowErrorMessage(cx, MSG_NO_INDEXED_SETTER, "${name}");
}
""",
name=self.descriptor.name)
@ -10275,7 +10274,7 @@ class CGDOMJSProxyHandler_defineProperty(ClassMethod):
*defined = true;
$*{callSetter}
return true;
return opresult.succeed();
""",
callSetter=CGProxyNamedSetter(self.descriptor).define())
else:
@ -10291,7 +10290,9 @@ class CGDOMJSProxyHandler_defineProperty(ClassMethod):
$*{presenceChecker}
if (found) {
return js::IsInNonStrictPropertySet(cx) || ThrowErrorMessage(cx, MSG_NO_NAMED_SETTER, "${name}");
return js::IsInNonStrictPropertySet(cx)
? opresult.succeed()
: ThrowErrorMessage(cx, MSG_NO_NAMED_SETTER, "${name}");
}
""",
presenceChecker=CGProxyNamedPresenceChecker(self.descriptor, foundVar="found").define(),

View File

@ -196,18 +196,15 @@ BaseDOMProxyHandler::getOwnPropertyDescriptor(JSContext* cx,
bool
DOMProxyHandler::defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
MutableHandle<JSPropertyDescriptor> desc, bool* defined) const
MutableHandle<JSPropertyDescriptor> desc,
JS::ObjectOpResult &result, bool *defined) const
{
if (desc.hasGetterObject() && desc.setter() == JS_StrictPropertyStub) {
return JS_ReportErrorFlagsAndNumber(cx,
JSREPORT_WARNING | JSREPORT_STRICT |
JSREPORT_STRICT_MODE_ERROR,
js::GetErrorMessage, nullptr,
JSMSG_GETTER_ONLY);
return result.failGetterOnly();
}
if (xpc::WrapperFactory::IsXrayWrapper(proxy)) {
return true;
return result.succeed();
}
JSObject* expando = EnsureExpandoObject(cx, proxy);
@ -215,8 +212,11 @@ DOMProxyHandler::defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::
return false;
}
bool dummy;
return js::DefineOwnProperty(cx, expando, id, desc, &dummy);
if (!js::DefineOwnProperty(cx, expando, id, desc, result)) {
return false;
}
*defined = true;
return true;
}
bool

View File

@ -105,14 +105,15 @@ public:
{}
bool defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
JS::MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE
JS::MutableHandle<JSPropertyDescriptor> desc,
JS::ObjectOpResult &result) const MOZ_OVERRIDE
{
bool unused;
return defineProperty(cx, proxy, id, desc, &unused);
return defineProperty(cx, proxy, id, desc, result, &unused);
}
virtual bool defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
JS::MutableHandle<JSPropertyDescriptor> desc, bool* defined)
const;
JS::MutableHandle<JSPropertyDescriptor> desc,
JS::ObjectOpResult &result, bool *defined) const;
bool delete_(JSContext* cx, JS::Handle<JSObject*> proxy,
JS::Handle<jsid> id, bool* bp) const MOZ_OVERRIDE;
bool preventExtensions(JSContext *cx, JS::Handle<JSObject*> proxy,

View File

@ -52,8 +52,7 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base
return Answer::RecvGetOwnPropertyDescriptor(ObjectId::deserialize(objId), id, rs, out);
}
bool RecvDefineProperty(const uint64_t &objId, const JSIDVariant &id,
const PPropertyDescriptor &flags,
ReturnStatus *rs) {
const PPropertyDescriptor &flags, ReturnStatus *rs) {
return Answer::RecvDefineProperty(ObjectId::deserialize(objId), id, flags, rs);
}
bool RecvDelete(const uint64_t &objId, const JSIDVariant &id,
@ -145,7 +144,7 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base
}
bool SendDefineProperty(const ObjectId &objId, const JSIDVariant &id,
const PPropertyDescriptor &flags,
ReturnStatus *rs) {
ReturnStatus *rs) {
return Base::SendDefineProperty(objId.serialize(), id, flags, rs);
}
bool SendDelete(const ObjectId &objId, const JSIDVariant &id,

View File

@ -103,11 +103,17 @@ struct ReturnException
JSVariant exn;
};
struct ReturnObjectOpResult
{
uint32_t code;
};
union ReturnStatus
{
ReturnSuccess;
ReturnStopIteration;
ReturnException;
ReturnObjectOpResult;
};
union JSParam

View File

@ -64,6 +64,15 @@ WrapperAnswer::ok(ReturnStatus *rs)
return true;
}
bool
WrapperAnswer::ok(ReturnStatus *rs, const JS::ObjectOpResult &result)
{
*rs = result
? ReturnStatus(ReturnSuccess())
: ReturnStatus(ReturnObjectOpResult(result.failureCode()));
return true;
}
bool
WrapperAnswer::RecvPreventExtensions(const ObjectId &objId, ReturnStatus *rs,
bool *succeeded)
@ -179,11 +188,10 @@ WrapperAnswer::RecvDefineProperty(const ObjectId &objId, const JSIDVariant &idVa
if (!toDescriptor(cx, descriptor, &desc))
return fail(cx, rs);
bool ignored;
if (!js::DefineOwnProperty(cx, obj, id, desc, &ignored))
ObjectOpResult success;
if (!js::DefineOwnProperty(cx, obj, id, desc, success))
return fail(cx, rs);
return ok(rs);
return ok(rs, success);
}
bool

View File

@ -28,8 +28,7 @@ class WrapperAnswer : public virtual JavaScriptShared
ReturnStatus *rs,
PPropertyDescriptor *out);
bool RecvDefineProperty(const ObjectId &objId, const JSIDVariant &id,
const PPropertyDescriptor &flags,
ReturnStatus *rs);
const PPropertyDescriptor &flags, ReturnStatus *rs);
bool RecvDelete(const ObjectId &objId, const JSIDVariant &id,
ReturnStatus *rs, bool *success);
@ -68,6 +67,7 @@ class WrapperAnswer : public virtual JavaScriptShared
private:
bool fail(JSContext *cx, ReturnStatus *rs);
bool ok(ReturnStatus *rs);
bool ok(ReturnStatus *rs, const JS::ObjectOpResult &result);
};
} // mozilla

View File

@ -90,7 +90,8 @@ class CPOWProxyHandler : public BaseProxyHandler
virtual bool getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
virtual bool defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
MutableHandle<JSPropertyDescriptor> desc,
ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool ownPropertyKeys(JSContext *cx, HandleObject proxy,
AutoIdVector &props) const MOZ_OVERRIDE;
virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const MOZ_OVERRIDE;
@ -202,14 +203,16 @@ WrapperOwner::getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, Handle
bool
CPOWProxyHandler::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
MutableHandle<JSPropertyDescriptor> desc) const
MutableHandle<JSPropertyDescriptor> desc,
ObjectOpResult &result) const
{
FORWARD(defineProperty, (cx, proxy, id, desc));
FORWARD(defineProperty, (cx, proxy, id, desc, result));
}
bool
WrapperOwner::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
MutableHandle<JSPropertyDescriptor> desc)
MutableHandle<JSPropertyDescriptor> desc,
ObjectOpResult &result)
{
ObjectId objId = idOf(proxy);
@ -227,7 +230,7 @@ WrapperOwner::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
LOG_STACK();
return ok(cx, status);
return ok(cx, status, result);
}
bool
@ -934,6 +937,16 @@ WrapperOwner::ok(JSContext *cx, const ReturnStatus &status)
return false;
}
bool
WrapperOwner::ok(JSContext *cx, const ReturnStatus &status, ObjectOpResult &result)
{
if (status.type() == ReturnStatus::TReturnObjectOpResult)
return result.fail(status.get_ReturnObjectOpResult().code());
if (!ok(cx, status))
return false;
return result.succeed();
}
static RemoteObject
MakeRemoteObject(JSContext *cx, ObjectId id, HandleObject obj)
{

View File

@ -32,7 +32,8 @@ class WrapperOwner : public virtual JavaScriptShared
bool getOwnPropertyDescriptor(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
JS::MutableHandle<JSPropertyDescriptor> desc);
bool defineProperty(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
JS::MutableHandle<JSPropertyDescriptor> desc);
JS::MutableHandle<JSPropertyDescriptor> desc,
JS::ObjectOpResult &result);
bool ownPropertyKeys(JSContext *cx, JS::HandleObject proxy, JS::AutoIdVector &props);
bool delete_(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp);
bool preventExtensions(JSContext *cx, JS::HandleObject proxy, bool *succeeded);
@ -93,6 +94,10 @@ class WrapperOwner : public virtual JavaScriptShared
bool ipcfail(JSContext *cx);
// Check whether a return status is okay, and if not, propagate its error.
//
// If 'status' might be a ReturnObjectOpResult, which is only possible for
// a subset of the operations below, 'result' must be passed.
bool ok(JSContext *cx, const ReturnStatus &status, JS::ObjectOpResult &result);
bool ok(JSContext *cx, const ReturnStatus &status);
bool inactive_;

View File

@ -118,6 +118,15 @@ class ObjectOpResult
return true;
}
JS_PUBLIC_API(bool) failCantRedefineProp();
JS_PUBLIC_API(bool) failReadOnly();
JS_PUBLIC_API(bool) failGetterOnly();
uint32_t failureCode() const {
MOZ_ASSERT(!ok());
return code_;
}
/*
* Report an error or warning if necessary; return true to proceed and
* false if an error was reported. Call this when failure should cause
@ -280,7 +289,8 @@ typedef bool
JS::MutableHandleObject objp, JS::MutableHandle<Shape*> propp);
typedef bool
(* DefinePropertyOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue value,
JSGetterOp getter, JSSetterOp setter, unsigned attrs);
JSGetterOp getter, JSSetterOp setter, unsigned attrs,
JS::ObjectOpResult &result);
typedef bool
(* HasPropertyOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id, bool *foundp);
typedef bool

View File

@ -26,6 +26,7 @@ using JS::MutableHandle;
using JS::MutableHandleObject;
using JS::MutableHandleValue;
using JS::NativeImpl;
using JS::ObjectOpResult;
using JS::PrivateValue;
using JS::Value;
@ -251,7 +252,8 @@ class JS_FRIEND_API(BaseProxyHandler)
virtual bool getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
MutableHandle<JSPropertyDescriptor> desc) const = 0;
virtual bool defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
MutableHandle<JSPropertyDescriptor> desc) const = 0;
MutableHandle<JSPropertyDescriptor> desc,
ObjectOpResult &result) const = 0;
virtual bool ownPropertyKeys(JSContext *cx, HandleObject proxy,
AutoIdVector &props) const = 0;
virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const = 0;
@ -367,7 +369,8 @@ class JS_FRIEND_API(DirectProxyHandler) : public BaseProxyHandler
virtual bool getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
virtual bool defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
MutableHandle<JSPropertyDescriptor> desc,
ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool ownPropertyKeys(JSContext *cx, HandleObject proxy,
AutoIdVector &props) const MOZ_OVERRIDE;
virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id,

View File

@ -1757,7 +1757,8 @@ ReportPropertyError(JSContext *cx,
bool
TypedObject::obj_defineProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
GetterOp getter, SetterOp setter, unsigned attrs)
GetterOp getter, SetterOp setter, unsigned attrs,
ObjectOpResult &result)
{
Rooted<TypedObject *> typedObj(cx, &obj->as<TypedObject>());
return ReportTypedObjTypeError(cx, JSMSG_OBJECT_NOT_EXTENSIBLE, typedObj);

View File

@ -529,7 +529,8 @@ class TypedObject : public JSObject
MutableHandleObject objp, MutableHandleShape propp);
static bool obj_defineProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
GetterOp getter, SetterOp setter, unsigned attrs);
GetterOp getter, SetterOp setter, unsigned attrs,
ObjectOpResult &result);
static bool obj_hasProperty(JSContext *cx, HandleObject obj, HandleId id, bool *foundp);

View File

@ -168,6 +168,24 @@ JS::ObjectOpResult::reportStrictErrorOrWarning(JSContext *cx, HandleObject obj,
return JS_ReportErrorFlagsAndNumber(cx, flags, GetErrorMessage, nullptr, code_);
}
JS_PUBLIC_API(bool)
JS::ObjectOpResult::failCantRedefineProp()
{
return fail(JSMSG_CANT_REDEFINE_PROP);
}
JS_PUBLIC_API(bool)
JS::ObjectOpResult::failReadOnly()
{
return fail(JSMSG_READ_ONLY);
}
JS_PUBLIC_API(bool)
JS::ObjectOpResult::failGetterOnly()
{
return fail(JSMSG_GETTER_ONLY);
}
JS_PUBLIC_API(int64_t)
JS_Now()
{
@ -2238,6 +2256,33 @@ JS_DefinePropertyById(JSContext *cx, HandleObject obj, HandleId id, double value
NativeOpWrapper(getter), NativeOpWrapper(setter), attrs, 0);
}
static bool
DefinePropertyByDescriptor(JSContext *cx, HandleObject obj, HandleId id,
Handle<JSPropertyDescriptor> desc, ObjectOpResult &result)
{
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, id, desc);
return DefineProperty(cx, obj, id, desc.value(), desc.getter(), desc.setter(),
desc.attributes(), result);
}
JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext *cx, HandleObject obj, HandleId id,
Handle<JSPropertyDescriptor> desc, ObjectOpResult &result)
{
return DefinePropertyByDescriptor(cx, obj, id, desc, result);
}
JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext *cx, HandleObject obj, HandleId id,
Handle<JSPropertyDescriptor> desc)
{
ObjectOpResult result;
return DefinePropertyByDescriptor(cx, obj, id, desc, result) &&
result.checkStrict(cx, obj, id);
}
static bool
DefineElement(JSContext *cx, HandleObject obj, uint32_t index, HandleValue value,
unsigned attrs, Native getter, Native setter)
@ -2494,6 +2539,31 @@ JS_DefineUCProperty(JSContext *cx, HandleObject obj, const char16_t *name, size_
getter, setter, attrs, 0);
}
JS_PUBLIC_API(bool)
JS_DefineUCProperty(JSContext *cx, HandleObject obj, const char16_t *name, size_t namelen,
Handle<JSPropertyDescriptor> desc,
ObjectOpResult &result)
{
JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
if (!atom)
return false;
RootedId id(cx, AtomToId(atom));
return DefinePropertyByDescriptor(cx, obj, id, desc, result);
}
JS_PUBLIC_API(bool)
JS_DefineUCProperty(JSContext *cx, HandleObject obj, const char16_t *name, size_t namelen,
Handle<JSPropertyDescriptor> desc)
{
JSAtom *atom = AtomizeChars(cx, name, AUTO_NAMELEN(name, namelen));
if (!atom)
return false;
RootedId id(cx, AtomToId(atom));
ObjectOpResult result;
return DefinePropertyByDescriptor(cx, obj, id, desc, result) &&
result.checkStrict(cx, obj, id);
}
JS_PUBLIC_API(JSObject *)
JS_DefineObject(JSContext *cx, HandleObject obj, const char *name, const JSClass *jsclasp,
unsigned attrs)

View File

@ -2510,92 +2510,8 @@ JS_PreventExtensions(JSContext *cx, JS::HandleObject obj, bool *succeeded);
extern JS_PUBLIC_API(JSObject *)
JS_New(JSContext *cx, JS::HandleObject ctor, const JS::HandleValueArray& args);
extern JS_PUBLIC_API(JSObject *)
JS_DefineObject(JSContext *cx, JS::HandleObject obj, const char *name,
const JSClass *clasp = nullptr, unsigned attrs = 0);
extern JS_PUBLIC_API(bool)
JS_DefineConstDoubles(JSContext *cx, JS::HandleObject obj, const JSConstDoubleSpec *cds);
extern JS_PUBLIC_API(bool)
JS_DefineConstIntegers(JSContext *cx, JS::HandleObject obj, const JSConstIntegerSpec *cis);
extern JS_PUBLIC_API(bool)
JS_DefineProperties(JSContext *cx, JS::HandleObject obj, const JSPropertySpec *ps);
extern JS_PUBLIC_API(bool)
JS_DefineProperty(JSContext *cx, JS::HandleObject obj, const char *name, JS::HandleValue value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefineProperty(JSContext *cx, JS::HandleObject obj, const char *name, JS::HandleObject value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefineProperty(JSContext *cx, JS::HandleObject obj, const char *name, JS::HandleString value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefineProperty(JSContext *cx, JS::HandleObject obj, const char *name, int32_t value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefineProperty(JSContext *cx, JS::HandleObject obj, const char *name, uint32_t value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefineProperty(JSContext *cx, JS::HandleObject obj, const char *name, double value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleString value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id, int32_t value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id, uint32_t value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id, double value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_AlreadyHasOwnProperty(JSContext *cx, JS::HandleObject obj, const char *name,
bool *foundp);
extern JS_PUBLIC_API(bool)
JS_AlreadyHasOwnPropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
bool *foundp);
extern JS_PUBLIC_API(bool)
JS_HasProperty(JSContext *cx, JS::HandleObject obj, const char *name, bool *foundp);
extern JS_PUBLIC_API(bool)
JS_HasPropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id, bool *foundp);
/*** Property descriptors ************************************************************************/
struct JSPropertyDescriptor {
JSObject *obj;
@ -2784,6 +2700,109 @@ ParsePropertyDescriptorObject(JSContext *cx,
} // namespace JS
/*** [[DefineOwnProperty]] and variations ********************************************************/
extern JS_PUBLIC_API(bool)
JS_DefineProperty(JSContext *cx, JS::HandleObject obj, const char *name, JS::HandleValue value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefineProperty(JSContext *cx, JS::HandleObject obj, const char *name, JS::HandleObject value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefineProperty(JSContext *cx, JS::HandleObject obj, const char *name, JS::HandleString value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefineProperty(JSContext *cx, JS::HandleObject obj, const char *name, int32_t value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefineProperty(JSContext *cx, JS::HandleObject obj, const char *name, uint32_t value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefineProperty(JSContext *cx, JS::HandleObject obj, const char *name, double value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleString value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id, int32_t value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id, uint32_t value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id, double value,
unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
JS::Handle<JSPropertyDescriptor> desc,
JS::ObjectOpResult &result);
extern JS_PUBLIC_API(bool)
JS_DefinePropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
JS::Handle<JSPropertyDescriptor> desc);
extern JS_PUBLIC_API(JSObject *)
JS_DefineObject(JSContext *cx, JS::HandleObject obj, const char *name,
const JSClass *clasp = nullptr, unsigned attrs = 0);
extern JS_PUBLIC_API(bool)
JS_DefineConstDoubles(JSContext *cx, JS::HandleObject obj, const JSConstDoubleSpec *cds);
extern JS_PUBLIC_API(bool)
JS_DefineConstIntegers(JSContext *cx, JS::HandleObject obj, const JSConstIntegerSpec *cis);
extern JS_PUBLIC_API(bool)
JS_DefineProperties(JSContext *cx, JS::HandleObject obj, const JSPropertySpec *ps);
/* * */
extern JS_PUBLIC_API(bool)
JS_AlreadyHasOwnProperty(JSContext *cx, JS::HandleObject obj, const char *name,
bool *foundp);
extern JS_PUBLIC_API(bool)
JS_AlreadyHasOwnPropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
bool *foundp);
extern JS_PUBLIC_API(bool)
JS_HasProperty(JSContext *cx, JS::HandleObject obj, const char *name, bool *foundp);
extern JS_PUBLIC_API(bool)
JS_HasPropertyById(JSContext *cx, JS::HandleObject obj, JS::HandleId id, bool *foundp);
extern JS_PUBLIC_API(bool)
JS_GetOwnPropertyDescriptorById(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
JS::MutableHandle<JSPropertyDescriptor> desc);
@ -2867,6 +2886,15 @@ JS_DefineUCProperty(JSContext *cx, JS::HandleObject obj, const char16_t *name, s
double value, unsigned attrs,
JSNative getter = nullptr, JSNative setter = nullptr);
extern JS_PUBLIC_API(bool)
JS_DefineUCProperty(JSContext *cx, JS::HandleObject obj, const char16_t *name, size_t namelen,
JS::Handle<JSPropertyDescriptor> desc,
JS::ObjectOpResult &result);
extern JS_PUBLIC_API(bool)
JS_DefineUCProperty(JSContext *cx, JS::HandleObject obj, const char16_t *name, size_t namelen,
JS::Handle<JSPropertyDescriptor> desc);
extern JS_PUBLIC_API(bool)
JS_AlreadyHasOwnUCProperty(JSContext *cx, JS::HandleObject obj, const char16_t *name,
size_t namelen, bool *foundp);

View File

@ -746,42 +746,13 @@ js::ArraySetLength(JSContext *cx, Handle<ArrayObject*> arr, HandleId id,
}
bool
js::WouldDefinePastNonwritableLength(ExclusiveContext *cx,
HandleObject obj, uint32_t index, bool strict,
bool *definesPast)
js::WouldDefinePastNonwritableLength(HandleNativeObject obj, uint32_t index)
{
if (!obj->is<ArrayObject>()) {
*definesPast = false;
return true;
}
if (!obj->is<ArrayObject>())
return false;
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
uint32_t length = arr->length();
if (index < length) {
*definesPast = false;
return true;
}
if (arr->lengthIsWritable()) {
*definesPast = false;
return true;
}
*definesPast = true;
// Error in strict mode code or warn with strict option.
unsigned flags = strict ? JSREPORT_ERROR : (JSREPORT_STRICT | JSREPORT_WARNING);
if (!cx->isJSContext())
return true;
JSContext *ncx = cx->asJSContext();
if (!strict && !ncx->compartment()->options().extraWarnings(ncx))
return true;
// XXX include the index and maybe array length in the error message
return JS_ReportErrorFlagsAndNumber(ncx, flags, GetErrorMessage, nullptr,
JSMSG_CANT_DEFINE_PAST_ARRAY_LENGTH);
ArrayObject *arr = &obj->as<ArrayObject>();
return !arr->lengthIsWritable() && index >= arr->length();
}
static bool

View File

@ -101,9 +101,7 @@ NewDenseCopyOnWriteArray(JSContext *cx, HandleArrayObject templateObject, gc::In
* increase the length of the array.
*/
extern bool
WouldDefinePastNonwritableLength(ExclusiveContext *cx,
HandleObject obj, uint32_t index, bool strict,
bool *definesPast);
WouldDefinePastNonwritableLength(HandleNativeObject obj, uint32_t index);
/*
* Canonicalize |vp| to a uint32_t value potentially suitable for use as an

View File

@ -133,6 +133,15 @@ class CompartmentChecker
void check(InterpreterFrame *fp);
void check(AbstractFramePtr frame);
void check(SavedStacks *stacks);
void check(Handle<JSPropertyDescriptor> desc) {
check(desc.object());
if (desc.hasGetterObject())
check(desc.getterObject());
if (desc.hasSetterObject())
check(desc.setterObject());
check(desc.value());
}
};
#endif /* JS_CRASH_DIAGNOSTICS */

View File

@ -1185,7 +1185,7 @@ js::GetObjectMetadata(JSObject *obj)
JS_FRIEND_API(bool)
js::DefineOwnProperty(JSContext *cx, JSObject *objArg, jsid idArg,
JS::Handle<js::PropertyDescriptor> descriptor, bool *bp)
JS::Handle<js::PropertyDescriptor> descriptor, ObjectOpResult &result)
{
RootedObject obj(cx, objArg);
RootedId id(cx, idArg);
@ -1197,11 +1197,7 @@ js::DefineOwnProperty(JSContext *cx, JSObject *objArg, jsid idArg,
if (descriptor.hasSetterObject())
assertSameCompartment(cx, descriptor.setterObject());
ObjectOpResult success;
if (!StandardDefineProperty(cx, obj, id, descriptor, success))
return false;
*bp = bool(success);
return true;
return StandardDefineProperty(cx, obj, id, descriptor, result);
}
JS_FRIEND_API(bool)

View File

@ -361,7 +361,8 @@ proxy_LookupProperty(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::M
JS::MutableHandle<Shape*> propp);
extern JS_FRIEND_API(bool)
proxy_DefineProperty(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue value,
JSGetterOp getter, JSSetterOp setter, unsigned attrs);
JSGetterOp getter, JSSetterOp setter, unsigned attrs,
JS::ObjectOpResult &result);
extern JS_FRIEND_API(bool)
proxy_HasProperty(JSContext *cx, JS::HandleObject obj, JS::HandleId id, bool *foundp);
extern JS_FRIEND_API(bool)
@ -2710,7 +2711,7 @@ ReportIsNotFunction(JSContext *cx, JS::HandleValue v);
extern JS_FRIEND_API(bool)
DefineOwnProperty(JSContext *cx, JSObject *objArg, jsid idArg,
JS::Handle<JSPropertyDescriptor> descriptor, bool *bp);
JS::Handle<JSPropertyDescriptor> descriptor, JS::ObjectOpResult &result);
} /* namespace js */

View File

@ -471,17 +471,14 @@ DefinePropertyOnObject(JSContext *cx, HandleNativeObject obj, HandleId id, const
if (desc.isGenericDescriptor() || desc.isDataDescriptor()) {
MOZ_ASSERT(!obj->getOps()->defineProperty);
RootedValue v(cx, desc.hasValue() ? desc.value() : UndefinedValue());
if (!NativeDefineProperty(cx, obj, id, v, nullptr, nullptr, desc.attributes()))
return false;
} else {
MOZ_ASSERT(desc.isAccessorDescriptor());
if (!NativeDefineProperty(cx, obj, id, UndefinedHandleValue,
desc.getter(), desc.setter(), desc.attributes()))
{
return false;
}
return NativeDefineProperty(cx, obj, id, v, nullptr, nullptr, desc.attributes(),
result);
}
return result.succeed();
MOZ_ASSERT(desc.isAccessorDescriptor());
return NativeDefineProperty(cx, obj, id, UndefinedHandleValue,
desc.getter(), desc.setter(), desc.attributes(), result);
}
/* 8.12.9 steps 5-6 (note 5 is merely a special case of 6). */
@ -746,9 +743,7 @@ DefinePropertyOnObject(JSContext *cx, HandleNativeObject obj, HandleId id, const
return false;
}
if (!NativeDefineProperty(cx, obj, id, v, getter, setter, attrs))
return false;
return result.succeed();
return NativeDefineProperty(cx, obj, id, v, getter, setter, attrs, result);
}
/* ES6 20130308 draft 8.4.2.1 [[DefineOwnProperty]] */
@ -884,9 +879,7 @@ js::StandardDefineProperty(JSContext *cx, HandleObject obj, HandleId id, const P
Rooted<PropertyDescriptor> pd(cx);
desc.populatePropertyDescriptor(obj, &pd);
pd.object().set(obj);
if (!Proxy::defineProperty(cx, obj, id, &pd))
return false;
return result.succeed();
return Proxy::defineProperty(cx, obj, id, &pd, result);
}
return result.fail(JSMSG_OBJECT_NOT_EXTENSIBLE);
}
@ -896,8 +889,7 @@ js::StandardDefineProperty(JSContext *cx, HandleObject obj, HandleId id, const P
bool
js::StandardDefineProperty(JSContext *cx, HandleObject obj, HandleId id,
Handle<PropertyDescriptor> descriptor,
ObjectOpResult &result)
Handle<PropertyDescriptor> descriptor, ObjectOpResult &result)
{
Rooted<PropDesc> desc(cx);
desc.initFromPropertyDescriptor(descriptor);
@ -3253,7 +3245,8 @@ js::GetOwnPropertyDescriptor(JSContext *cx, HandleObject obj, HandleId id,
bool
js::DefineProperty(ExclusiveContext *cx, HandleObject obj, HandleId id, HandleValue value,
JSGetterOp getter, JSSetterOp setter, unsigned attrs)
JSGetterOp getter, JSSetterOp setter, unsigned attrs,
ObjectOpResult &result)
{
MOZ_ASSERT(getter != JS_PropertyStub);
MOZ_ASSERT(setter != JS_StrictPropertyStub);
@ -3263,15 +3256,54 @@ js::DefineProperty(ExclusiveContext *cx, HandleObject obj, HandleId id, HandleVa
if (op) {
if (!cx->shouldBeJSContext())
return false;
return op(cx->asJSContext(), obj, id, value, getter, setter, attrs);
return op(cx->asJSContext(), obj, id, value, getter, setter, attrs, result);
}
return NativeDefineProperty(cx, obj.as<NativeObject>(), id, value, getter, setter, attrs);
return NativeDefineProperty(cx, obj.as<NativeObject>(), id, value, getter, setter, attrs,
result);
}
bool
js::DefineProperty(ExclusiveContext *cx, HandleObject obj,
PropertyName *name, HandleValue value,
JSGetterOp getter, JSSetterOp setter, unsigned attrs)
js::DefineProperty(ExclusiveContext *cx, HandleObject obj, PropertyName *name, HandleValue value,
JSGetterOp getter, JSSetterOp setter, unsigned attrs,
ObjectOpResult &result)
{
RootedId id(cx, NameToId(name));
return DefineProperty(cx, obj, id, value, getter, setter, attrs, result);
}
bool
js::DefineElement(ExclusiveContext *cx, HandleObject obj, uint32_t index, HandleValue value,
JSGetterOp getter, JSSetterOp setter, unsigned attrs,
ObjectOpResult &result)
{
MOZ_ASSERT(getter != JS_PropertyStub);
MOZ_ASSERT(setter != JS_StrictPropertyStub);
RootedId id(cx);
if (!IndexToId(cx, index, &id))
return false;
return DefineProperty(cx, obj, id, value, getter, setter, attrs, result);
}
bool
js::DefineProperty(ExclusiveContext *cx, HandleObject obj, HandleId id, HandleValue value,
JSGetterOp getter, JSSetterOp setter, unsigned attrs)
{
ObjectOpResult result;
if (!DefineProperty(cx, obj, id, value, getter, setter, attrs, result))
return false;
if (!result) {
if (!cx->shouldBeJSContext())
return false;
result.reportError(cx->asJSContext(), obj, id);
return false;
}
return true;
}
bool
js::DefineProperty(ExclusiveContext *cx, HandleObject obj, PropertyName *name, HandleValue value,
JSGetterOp getter, JSSetterOp setter, unsigned attrs)
{
RootedId id(cx, NameToId(name));
return DefineProperty(cx, obj, id, value, getter, setter, attrs);

View File

@ -773,6 +773,22 @@ StandardDefineProperty(JSContext *cx, HandleObject obj, HandleId id,
Handle<PropertyDescriptor> desc);
extern bool
DefineProperty(ExclusiveContext *cx, HandleObject obj, HandleId id, HandleValue value,
JSGetterOp getter, JSSetterOp setter, unsigned attrs, ObjectOpResult &result);
extern bool
DefineProperty(ExclusiveContext *cx, HandleObject obj, PropertyName *name, HandleValue value,
JSGetterOp getter, JSSetterOp setter, unsigned attrs, ObjectOpResult &result);
extern bool
DefineElement(ExclusiveContext *cx, HandleObject obj, uint32_t index, HandleValue value,
JSGetterOp getter, JSSetterOp setter, unsigned attrs, ObjectOpResult &result);
/*
* When the 'result' out-param is omitted, the behavior is the same as above, except
* that any failure results in a TypeError.
*/
extern bool
DefineProperty(ExclusiveContext *cx, HandleObject obj, HandleId id, HandleValue value,
JSGetterOp getter = nullptr,
JSSetterOp setter = nullptr,

View File

@ -117,7 +117,8 @@ class JS_FRIEND_API(CrossCompartmentWrapper) : public Wrapper
virtual bool getOwnPropertyDescriptor(JSContext *cx, HandleObject wrapper, HandleId id,
MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
virtual bool defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
MutableHandle<JSPropertyDescriptor> desc,
ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool ownPropertyKeys(JSContext *cx, HandleObject wrapper,
AutoIdVector &props) const MOZ_OVERRIDE;
virtual bool delete_(JSContext *cx, HandleObject wrapper, HandleId id, bool *bp) const MOZ_OVERRIDE;
@ -182,7 +183,8 @@ class JS_FRIEND_API(SecurityWrapper) : public Base
bool *bp) const MOZ_OVERRIDE;
virtual bool defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
MutableHandle<JSPropertyDescriptor> desc,
ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool isExtensible(JSContext *cx, HandleObject wrapper, bool *extensible) const MOZ_OVERRIDE;
virtual bool preventExtensions(JSContext *cx, HandleObject wrapper, bool *succeeded) const MOZ_OVERRIDE;
virtual bool setPrototypeOf(JSContext *cx, HandleObject proxy, HandleObject proto,

View File

@ -183,7 +183,10 @@ js::SetPropertyIgnoringNamedGetter(JSContext *cx, const BaseProxyHandler *handle
if (descIsOwn) {
MOZ_ASSERT(desc.object() == proxy);
return handler->defineProperty(cx, proxy, id, desc);
ObjectOpResult result;
if (!handler->defineProperty(cx, proxy, id, desc, result))
return false;
return result.checkStrictErrorOrWarning(cx, proxy, id, strict);
}
return DefineProperty(cx, receiver, id, desc.value(),
desc.getter(), desc.setter(), desc.attributes());

View File

@ -49,12 +49,13 @@ CrossCompartmentWrapper::getOwnPropertyDescriptor(JSContext *cx, HandleObject wr
bool
CrossCompartmentWrapper::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
MutableHandle<PropertyDescriptor> desc) const
MutableHandle<PropertyDescriptor> desc,
ObjectOpResult &result) const
{
Rooted<PropertyDescriptor> desc2(cx, desc);
PIERCE(cx, wrapper,
cx->compartment()->wrap(cx, &desc2),
Wrapper::defineProperty(cx, wrapper, id, &desc2),
Wrapper::defineProperty(cx, wrapper, id, &desc2, result),
NOTHING);
}

View File

@ -32,7 +32,8 @@ DeadObjectProxy::getOwnPropertyDescriptor(JSContext *cx, HandleObject wrapper, H
bool
DeadObjectProxy::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
MutableHandle<PropertyDescriptor> desc) const
MutableHandle<PropertyDescriptor> desc,
ObjectOpResult &result) const
{
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_DEAD_OBJECT);
return false;

View File

@ -22,7 +22,8 @@ class DeadObjectProxy : public BaseProxyHandler
virtual bool getOwnPropertyDescriptor(JSContext *cx, HandleObject wrapper, HandleId id,
MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
virtual bool defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
MutableHandle<JSPropertyDescriptor> desc,
ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool ownPropertyKeys(JSContext *cx, HandleObject wrapper,
AutoIdVector &props) const MOZ_OVERRIDE;
virtual bool delete_(JSContext *cx, HandleObject wrapper, HandleId id, bool *bp) const MOZ_OVERRIDE;

View File

@ -34,12 +34,12 @@ DirectProxyHandler::getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy,
bool
DirectProxyHandler::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
MutableHandle<PropertyDescriptor> desc) const
MutableHandle<PropertyDescriptor> desc,
ObjectOpResult &result) const
{
assertEnteredPolicy(cx, proxy, id, SET);
RootedObject target(cx, proxy->as<ProxyObject>().target());
ObjectOpResult ignored;
return StandardDefineProperty(cx, target, id, desc, ignored);
return StandardDefineProperty(cx, target, id, desc, result);
}
bool

View File

@ -134,14 +134,17 @@ Proxy::getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
bool
Proxy::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
MutableHandle<PropertyDescriptor> desc)
MutableHandle<PropertyDescriptor> desc, ObjectOpResult &result)
{
JS_CHECK_RECURSION(cx, return false);
const BaseProxyHandler *handler = proxy->as<ProxyObject>().handler();
AutoEnterPolicy policy(cx, handler, proxy, id, BaseProxyHandler::SET, true);
if (!policy.allowed())
return policy.returnValue();
return proxy->as<ProxyObject>().handler()->defineProperty(cx, proxy, id, desc);
if (!policy.allowed()) {
if (!policy.returnValue())
return false;
return result.succeed();
}
return proxy->as<ProxyObject>().handler()->defineProperty(cx, proxy, id, desc, result);
}
bool
@ -551,7 +554,8 @@ js::proxy_LookupProperty(JSContext *cx, HandleObject obj, HandleId id,
bool
js::proxy_DefineProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue value,
GetterOp getter, SetterOp setter, unsigned attrs)
GetterOp getter, SetterOp setter, unsigned attrs,
ObjectOpResult &result)
{
Rooted<PropertyDescriptor> desc(cx);
desc.object().set(obj);
@ -559,7 +563,7 @@ js::proxy_DefineProperty(JSContext *cx, HandleObject obj, HandleId id, HandleVal
desc.setAttributes(attrs);
desc.setGetter(getter);
desc.setSetter(setter);
return Proxy::defineProperty(cx, obj, id, &desc);
return Proxy::defineProperty(cx, obj, id, &desc, result);
}
bool

View File

@ -29,7 +29,7 @@ class Proxy
static bool getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
MutableHandle<JSPropertyDescriptor> desc);
static bool defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
MutableHandle<JSPropertyDescriptor> desc);
MutableHandle<JSPropertyDescriptor> desc, ObjectOpResult &result);
static bool ownPropertyKeys(JSContext *cx, HandleObject proxy, AutoIdVector &props);
static bool delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp);
static bool enumerate(JSContext *cx, HandleObject proxy, MutableHandleObject objp);

View File

@ -552,38 +552,37 @@ ScriptedDirectProxyHandler::getOwnPropertyDescriptor(JSContext *cx, HandleObject
return true;
}
// ES6 (5 April 2014) 9.5.6 Proxy.[[DefineOwnProperty]](O,P)
// ES6 draft rev 31 (15 Jan 2015) 9.5.6 Proxy.[[DefineOwnProperty]](P, Desc)
bool
ScriptedDirectProxyHandler::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
MutableHandle<PropertyDescriptor> desc) const
MutableHandle<PropertyDescriptor> desc,
ObjectOpResult &result) const
{
// step 2
// steps 2-4
RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
// step 3
if (!handler) {
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_PROXY_REVOKED);
return false;
}
// step 4
// step 5
RootedObject target(cx, proxy->as<ProxyObject>().target());
// step 5-6
// steps 6-7
RootedValue trap(cx);
if (!GetProperty(cx, handler, handler, cx->names().defineProperty, &trap))
return false;
// step 7
// step 8
if (trap.isUndefined())
return DirectProxyHandler::defineProperty(cx, proxy, id, desc);
return DirectProxyHandler::defineProperty(cx, proxy, id, desc, result);
// step 8-9
// step 9
RootedValue descObj(cx);
if (!NewPropertyDescriptorObject(cx, desc, &descObj))
return false;
// step 10, 12
// steps 10-11
RootedValue propKey(cx);
if (!IdToStringOrSymbol(cx, id, &propKey))
return false;
@ -597,48 +596,50 @@ ScriptedDirectProxyHandler::defineProperty(JSContext *cx, HandleObject proxy, Ha
if (!Invoke(cx, ObjectValue(*handler), trap, ArrayLength(argv), argv, &trapResult))
return false;
// step 11, 13
if (ToBoolean(trapResult)) {
// step 14-15
Rooted<PropertyDescriptor> targetDesc(cx);
if (!GetOwnPropertyDescriptor(cx, target, id, &targetDesc))
return false;
// FIXME - bug 1132522: Step 12 is not implemented yet.
// if (!ToBoolean(trapResult))
// return result.fail(JSMSG_PROXY_DEFINE_RETURNED_FALSE);
// step 16-17
bool extensibleTarget;
if (!IsExtensible(cx, target, &extensibleTarget))
return false;
// step 13-14
Rooted<PropertyDescriptor> targetDesc(cx);
if (!GetOwnPropertyDescriptor(cx, target, id, &targetDesc))
return false;
// step 18-19
bool settingConfigFalse = desc.isPermanent();
if (!targetDesc.object()) {
// step 20a
if (!extensibleTarget) {
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CANT_DEFINE_NEW);
return false;
}
// step 20b
if (settingConfigFalse) {
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CANT_DEFINE_NE_AS_NC);
return false;
}
} else {
// step 21
bool valid;
Rooted<PropDesc> pd(cx);
pd.initFromPropertyDescriptor(desc);
if (!ValidatePropertyDescriptor(cx, extensibleTarget, pd, targetDesc, &valid))
return false;
if (!valid || (settingConfigFalse && !targetDesc.isPermanent())) {
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CANT_DEFINE_INVALID);
return false;
}
// step 15-16
bool extensibleTarget;
if (!IsExtensible(cx, target, &extensibleTarget))
return false;
// step 17-18
// FIXME bug 1133081: settingConfigFalse should be false if we have
// JSPROP_IGNORE_PERMANENT.
bool settingConfigFalse = desc.isPermanent();
if (!targetDesc.object()) {
// step 19.a
if (!extensibleTarget) {
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CANT_DEFINE_NEW);
return false;
}
// step 19.b
if (settingConfigFalse) {
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CANT_DEFINE_NE_AS_NC);
return false;
}
} else {
// step 20
bool valid;
Rooted<PropDesc> pd(cx);
pd.initFromPropertyDescriptor(desc);
if (!ValidatePropertyDescriptor(cx, extensibleTarget, pd, targetDesc, &valid))
return false;
if (!valid || (settingConfigFalse && !targetDesc.isPermanent())) {
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CANT_DEFINE_INVALID);
return false;
}
}
// [[DefineProperty]] should return a boolean value, which is used to do things like
// strict-mode throwing. At present, the engine is not prepared to do that. See bug 826587.
return true;
// step 21
return result.succeed();
}
// ES6 (5 April 2014) 9.5.12 Proxy.[[OwnPropertyKeys]]()

View File

@ -22,7 +22,8 @@ class ScriptedDirectProxyHandler : public DirectProxyHandler {
virtual bool getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
virtual bool defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
MutableHandle<JSPropertyDescriptor> desc,
ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool ownPropertyKeys(JSContext *cx, HandleObject proxy,
AutoIdVector &props) const MOZ_OVERRIDE;
virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const MOZ_OVERRIDE;

View File

@ -196,13 +196,15 @@ ScriptedIndirectProxyHandler::getOwnPropertyDescriptor(JSContext *cx, HandleObje
bool
ScriptedIndirectProxyHandler::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
MutableHandle<PropertyDescriptor> desc) const
MutableHandle<PropertyDescriptor> desc,
ObjectOpResult &result) const
{
RootedObject handler(cx, GetIndirectProxyHandlerObject(proxy));
RootedValue fval(cx), value(cx);
return GetFundamentalTrap(cx, handler, cx->names().defineProperty, &fval) &&
NewPropertyDescriptorObject(cx, desc, &value) &&
Trap2(cx, handler, fval, id, value, &value);
Trap2(cx, handler, fval, id, value, &value) &&
result.succeed();
}
bool

View File

@ -23,7 +23,8 @@ class ScriptedIndirectProxyHandler : public BaseProxyHandler
virtual bool getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
virtual bool defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
MutableHandle<JSPropertyDescriptor> desc,
ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool ownPropertyKeys(JSContext *cx, HandleObject proxy,
AutoIdVector &props) const MOZ_OVERRIDE;
virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const MOZ_OVERRIDE;

View File

@ -105,7 +105,8 @@ SecurityWrapper<Base>::boxedValue_unbox(JSContext *cx, HandleObject obj, Mutable
template <class Base>
bool
SecurityWrapper<Base>::defineProperty(JSContext *cx, HandleObject wrapper,
HandleId id, MutableHandle<PropertyDescriptor> desc) const
HandleId id, MutableHandle<PropertyDescriptor> desc,
ObjectOpResult &result) const
{
if (desc.getter() || desc.setter()) {
RootedValue idVal(cx, IdToValue(id));
@ -121,7 +122,7 @@ SecurityWrapper<Base>::defineProperty(JSContext *cx, HandleObject wrapper,
return false;
}
return Base::defineProperty(cx, wrapper, id, desc);
return Base::defineProperty(cx, wrapper, id, desc, result);
}
template <class Base>

View File

@ -598,18 +598,6 @@ NativeLookupProperty(ExclusiveContext *cx, HandleNativeObject obj, PropertyName
return NativeLookupProperty<CanGC>(cx, obj, id, objp, propp);
}
inline bool
NativeDefineProperty(ExclusiveContext *cx, HandleNativeObject obj, PropertyName *name,
HandleValue value, GetterOp getter, SetterOp setter,
unsigned attrs)
{
MOZ_ASSERT(getter != JS_PropertyStub);
MOZ_ASSERT(setter != JS_StrictPropertyStub);
RootedId id(cx, NameToId(name));
return NativeDefineProperty(cx, obj, id, value, getter, setter, attrs);
}
inline bool
WarnIfNotConstructing(JSContext *cx, const CallArgs &args, const char *builtinName)
{

View File

@ -1139,7 +1139,7 @@ NativeSet(JSContext *cx, HandleNativeObject obj, HandleObject receiver,
static inline bool
DefinePropertyOrElement(ExclusiveContext *cx, HandleNativeObject obj, HandleId id,
GetterOp getter, SetterOp setter, unsigned attrs, HandleValue value,
bool callSetterAfterwards, bool setterIsStrict)
bool callSetterAfterwards, ObjectOpResult &result)
{
MOZ_ASSERT(getter != JS_PropertyStub);
MOZ_ASSERT(setter != JS_StrictPropertyStub);
@ -1153,20 +1153,17 @@ DefinePropertyOrElement(ExclusiveContext *cx, HandleNativeObject obj, HandleId i
!IsAnyTypedArray(obj))
{
uint32_t index = JSID_TO_INT(id);
bool definesPast;
if (!WouldDefinePastNonwritableLength(cx, obj, index, setterIsStrict, &definesPast))
return false;
if (definesPast)
return true;
if (WouldDefinePastNonwritableLength(obj, index))
return result.fail(JSMSG_CANT_DEFINE_PAST_ARRAY_LENGTH);
NativeObject::EnsureDenseResult result;
result = obj->ensureDenseElements(cx, index, 1);
if (result == NativeObject::ED_FAILED)
NativeObject::EnsureDenseResult edResult = obj->ensureDenseElements(cx, index, 1);
if (edResult == NativeObject::ED_FAILED)
return false;
if (result == NativeObject::ED_OK) {
if (edResult == NativeObject::ED_OK) {
obj->setDenseElementWithType(cx, index, value);
return CallAddPropertyHookDense(cx, obj, index, value);
if (!CallAddPropertyHookDense(cx, obj, index, value))
return false;
return result.succeed();
}
}
@ -1175,24 +1172,13 @@ DefinePropertyOrElement(ExclusiveContext *cx, HandleNativeObject obj, HandleId i
if (id == NameToId(cx->names().length)) {
if (!cx->shouldBeJSContext())
return false;
ObjectOpResult success;
if (!ArraySetLength(cx->asJSContext(), arr, id, attrs, value, success))
return false;
if (setterIsStrict && !success) {
success.reportError(cx->asJSContext(), arr, id);
return false;
}
return true;
return ArraySetLength(cx->asJSContext(), arr, id, attrs, value, result);
}
uint32_t index;
if (IdIsIndex(id, &index)) {
bool definesPast;
if (!WouldDefinePastNonwritableLength(cx, arr, index, setterIsStrict, &definesPast))
return false;
if (definesPast)
return true;
if (WouldDefinePastNonwritableLength(obj, index))
return result.fail(JSMSG_CANT_DEFINE_PAST_ARRAY_LENGTH);
}
}
@ -1200,7 +1186,7 @@ DefinePropertyOrElement(ExclusiveContext *cx, HandleNativeObject obj, HandleId i
if (IsAnyTypedArray(obj)) {
uint64_t index;
if (IsTypedArrayIndex(id, &index))
return true;
return result.succeed();
}
AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
@ -1222,12 +1208,14 @@ DefinePropertyOrElement(ExclusiveContext *cx, HandleNativeObject obj, HandleId i
uint32_t index = JSID_TO_INT(id);
NativeObject::removeDenseElementForSparseIndex(cx, obj, index);
NativeObject::EnsureDenseResult result = NativeObject::maybeDensifySparseElements(cx, obj);
if (result == NativeObject::ED_FAILED)
NativeObject::EnsureDenseResult edResult = NativeObject::maybeDensifySparseElements(cx, obj);
if (edResult == NativeObject::ED_FAILED)
return false;
if (result == NativeObject::ED_OK) {
if (edResult == NativeObject::ED_OK) {
MOZ_ASSERT(!setter);
return CallAddPropertyHookDense(cx, obj, index, value);
if (!CallAddPropertyHookDense(cx, obj, index, value))
return false;
return result.succeed();
}
}
@ -1238,9 +1226,13 @@ DefinePropertyOrElement(ExclusiveContext *cx, HandleNativeObject obj, HandleId i
if (!cx->shouldBeJSContext())
return false;
RootedValue nvalue(cx, value);
return NativeSet(cx->asJSContext(), obj, obj, shape, setterIsStrict, &nvalue);
// FIXME: result should be passed to NativeSet.
if (!NativeSet(cx->asJSContext(), obj, obj, shape, false, &nvalue))
return false;
}
return true;
return result.succeed();
}
static unsigned
@ -1353,7 +1345,8 @@ CheckAccessorRedefinition(ExclusiveContext *cx, HandleObject obj, HandleShape sh
bool
js::NativeDefineProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleId id, HandleValue value,
GetterOp getter, SetterOp setter, unsigned attrs)
GetterOp getter, SetterOp setter, unsigned attrs,
ObjectOpResult &result)
{
MOZ_ASSERT(getter != JS_PropertyStub);
MOZ_ASSERT(setter != JS_StrictPropertyStub);
@ -1381,7 +1374,7 @@ js::NativeDefineProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleId
if (IsImplicitDenseOrTypedArrayElement(shape)) {
if (IsAnyTypedArray(obj)) {
/* Ignore getter/setter properties added to typed arrays. */
return true;
return result.succeed();
}
if (!NativeObject::sparsifyDenseElement(cx, obj, JSID_TO_INT(id)))
return false;
@ -1446,11 +1439,11 @@ js::NativeDefineProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleId
if (IsImplicitDenseOrTypedArrayElement(shape)) {
if (IsAnyTypedArray(obj)) {
/*
* Silently ignore attempts to change individial index attributes.
* Silently ignore attempts to change individual index attributes.
* FIXME: Uses the same broken behavior as for accessors. This should
* probably throw.
* fail.
*/
return true;
return result.succeed();
}
if (!NativeObject::sparsifyDenseElement(cx, obj, JSID_TO_INT(id)))
return false;
@ -1497,14 +1490,16 @@ js::NativeDefineProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleId
// relevant, just clear it.
attrs = ApplyOrDefaultAttributes(attrs) & ~JSPROP_IGNORE_VALUE;
return DefinePropertyOrElement(cx, obj, id, getter, setter,
attrs, updateValue, false, false);
attrs, updateValue, false, result);
}
MOZ_ASSERT(shape);
JS_ALWAYS_TRUE(UpdateShapeTypeAndValue(cx, obj, shape, updateValue));
return CallAddPropertyHook(cx, obj, shape, updateValue);
if (!CallAddPropertyHook(cx, obj, shape, updateValue))
return false;
return result.succeed();
}
template <AllowGC allowGC>
@ -1558,13 +1553,23 @@ js::NativeLookupElement(JSContext *cx, HandleNativeObject obj, uint32_t index,
}
bool
js::NativeDefineElement(ExclusiveContext *cx, HandleNativeObject obj, uint32_t index, HandleValue value,
GetterOp getter, SetterOp setter, unsigned attrs)
js::NativeDefineProperty(ExclusiveContext *cx, HandleNativeObject obj, PropertyName *name,
HandleValue value, GetterOp getter, SetterOp setter,
unsigned attrs, ObjectOpResult &result)
{
RootedId id(cx, NameToId(name));
return NativeDefineProperty(cx, obj, id, value, getter, setter, attrs, result);
}
bool
js::NativeDefineElement(ExclusiveContext *cx, HandleNativeObject obj, uint32_t index,
HandleValue value, GetterOp getter, SetterOp setter,
unsigned attrs, ObjectOpResult &result)
{
RootedId id(cx);
if (index <= JSID_INT_MAX) {
id = INT_TO_JSID(index);
return NativeDefineProperty(cx, obj, id, value, getter, setter, attrs);
return NativeDefineProperty(cx, obj, id, value, getter, setter, attrs, result);
}
AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
@ -1572,6 +1577,35 @@ js::NativeDefineElement(ExclusiveContext *cx, HandleNativeObject obj, uint32_t i
if (!IndexToId(cx, index, &id))
return false;
return NativeDefineProperty(cx, obj, id, value, getter, setter, attrs, result);
}
bool
js::NativeDefineProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleId id,
HandleValue value, JSGetterOp getter, JSSetterOp setter,
unsigned attrs)
{
ObjectOpResult result;
if (!NativeDefineProperty(cx, obj, id, value, getter, setter, attrs, result))
return false;
if (!result) {
// Off-main-thread callers should not get here: they must call this
// function only with known-valid arguments. Populating a new
// PlainObject with configurable properties is fine.
if (!cx->shouldBeJSContext())
return false;
result.reportError(cx->asJSContext(), obj, id);
return false;
}
return true;
}
bool
js::NativeDefineProperty(ExclusiveContext *cx, HandleNativeObject obj, PropertyName *name,
HandleValue value, JSGetterOp getter, JSSetterOp setter,
unsigned attrs)
{
RootedId id(cx, NameToId(name));
return NativeDefineProperty(cx, obj, id, value, getter, setter, attrs);
}
@ -2035,7 +2069,10 @@ js::SetPropertyByDefining(JSContext *cx, HandleObject obj, HandleObject receiver
return DefineProperty(cx, receiver, id, v, getter, setter, attrs);
Rooted<NativeObject*> nativeReceiver(cx, &receiver->as<NativeObject>());
return DefinePropertyOrElement(cx, nativeReceiver, id, getter, setter, attrs, v, true, strict);
ObjectOpResult success;
if (!DefinePropertyOrElement(cx, nativeReceiver, id, getter, setter, attrs, v, true, success))
return false;
return success.checkStrictErrorOrWarning(cx, receiver, id, strict);
}
// When setting |id| for |receiver| and |obj| has no property for id, continue
@ -2115,11 +2152,14 @@ SetDenseOrTypedArrayElement(JSContext *cx, HandleNativeObject obj, uint32_t inde
return true;
}
bool definesPast;
if (!WouldDefinePastNonwritableLength(cx, obj, index, strict, &definesPast))
return false;
if (definesPast)
if (WouldDefinePastNonwritableLength(obj, index)) {
if (strict) {
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr,
JSMSG_CANT_DEFINE_PAST_ARRAY_LENGTH);
return false;
}
return true;
}
if (!obj->maybeCopyElementsForWrite(cx))
return false;

View File

@ -1249,16 +1249,28 @@ IsObjectValueInCompartment(Value v, JSCompartment *comp)
extern bool
NativeDefineProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleId id, HandleValue value,
JSGetterOp getter, JSSetterOp setter, unsigned attrs);
JSGetterOp getter, JSSetterOp setter, unsigned attrs,
ObjectOpResult &result);
inline bool
extern bool
NativeDefineProperty(ExclusiveContext *cx, HandleNativeObject obj, PropertyName *name,
HandleValue value, GetterOp getter, SetterOp setter,
unsigned attrs);
unsigned attrs, ObjectOpResult &result);
extern bool
NativeDefineElement(ExclusiveContext *cx, HandleNativeObject obj, uint32_t index, HandleValue value,
JSGetterOp getter, JSSetterOp setter, unsigned attrs);
JSGetterOp getter, JSSetterOp setter, unsigned attrs,
ObjectOpResult &result);
/* If the result out-param is omitted, throw on failure. */
extern bool
NativeDefineProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleId id, HandleValue value,
JSGetterOp getter, JSSetterOp setter, unsigned attrs);
extern bool
NativeDefineProperty(ExclusiveContext *cx, HandleNativeObject obj, PropertyName *name,
HandleValue value, JSGetterOp getter, JSSetterOp setter,
unsigned attrs);
extern bool
NativeHasProperty(JSContext *cx, HandleNativeObject obj, HandleId id, bool *foundp);

View File

@ -471,10 +471,11 @@ with_LookupProperty(JSContext *cx, HandleObject obj, HandleId id,
static bool
with_DefineProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue value,
JSGetterOp getter, JSSetterOp setter, unsigned attrs)
JSGetterOp getter, JSSetterOp setter, unsigned attrs,
ObjectOpResult &result)
{
RootedObject actual(cx, &obj->as<DynamicWithObject>().object());
return DefineProperty(cx, actual, id, value, getter, setter, attrs);
return DefineProperty(cx, actual, id, value, getter, setter, attrs, result);
}
static bool
@ -1626,7 +1627,8 @@ class DebugScopeProxy : public BaseProxyHandler
}
bool defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
MutableHandle<PropertyDescriptor> desc) const MOZ_OVERRIDE
MutableHandle<PropertyDescriptor> desc,
ObjectOpResult &result) const MOZ_OVERRIDE
{
Rooted<ScopeObject*> scope(cx, &proxy->as<DebugScopeObject>().scope());
@ -1636,13 +1638,7 @@ class DebugScopeProxy : public BaseProxyHandler
if (found)
return Throw(cx, id, JSMSG_CANT_REDEFINE_PROP);
return JS_DefinePropertyById(cx, scope, id, desc.value(),
// 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()));
return JS_DefinePropertyById(cx, scope, id, desc, result);
}
bool ownPropertyKeys(JSContext *cx, HandleObject proxy, AutoIdVector &props) const MOZ_OVERRIDE

View File

@ -358,12 +358,13 @@ UnboxedPlainObject::obj_lookupProperty(JSContext *cx, HandleObject obj,
/* static */ bool
UnboxedPlainObject::obj_defineProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
GetterOp getter, SetterOp setter, unsigned attrs)
GetterOp getter, SetterOp setter, unsigned attrs,
ObjectOpResult &result)
{
if (!convertToNative(cx, obj))
return false;
return DefineProperty(cx, obj, id, v, getter, setter, attrs);
return DefineProperty(cx, obj, id, v, getter, setter, attrs, result);
}
/* static */ bool

View File

@ -165,7 +165,8 @@ class UnboxedPlainObject : public JSObject
MutableHandleShape propp);
static bool obj_defineProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
GetterOp getter, SetterOp setter, unsigned attrs);
GetterOp getter, SetterOp setter, unsigned attrs,
ObjectOpResult &result);
static bool obj_hasProperty(JSContext *cx, HandleObject obj, HandleId id, bool *foundp);

View File

@ -364,13 +364,7 @@ DefinePropertyIfFound(XPCCallContext& ccx,
AutoResolveName arn(ccx, id);
if (resolved)
*resolved = true;
return JS_DefinePropertyById(ccx, obj, id, desc.value(),
// Descriptors never store JSNatives
// for accessors: they have either
// JSFunctions or JSPropertyOps.
desc.attributes(),
JS_PROPERTYOP_GETTER(desc.getter()),
JS_PROPERTYOP_SETTER(desc.setter()));
return JS_DefinePropertyById(ccx, obj, id, desc);
}
}

View File

@ -148,14 +148,15 @@ AddonWrapper<Base>::set(JSContext *cx, JS::HandleObject wrapper, JS::HandleObjec
template<typename Base>
bool
AddonWrapper<Base>::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
MutableHandle<JSPropertyDescriptor> desc) const
MutableHandle<JSPropertyDescriptor> desc,
JS::ObjectOpResult &result) const
{
Rooted<JSPropertyDescriptor> interpDesc(cx);
if (!Interpose(cx, wrapper, nullptr, id, &interpDesc))
return false;
if (!interpDesc.object())
return Base::defineProperty(cx, wrapper, id, desc);
return Base::defineProperty(cx, wrapper, id, desc, result);
js::ReportErrorWithId(cx, "unable to modify interposed property %s", id);
return false;

View File

@ -28,7 +28,8 @@ class AddonWrapper : public Base {
JS::Handle<jsid> id,
JS::MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
virtual bool defineProperty(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
JS::MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
JS::MutableHandle<JSPropertyDescriptor> desc,
JS::ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool delete_(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp) const MOZ_OVERRIDE;
virtual bool get(JSContext *cx, JS::Handle<JSObject*> wrapper, JS::Handle<JSObject*> receiver,
JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp) const MOZ_OVERRIDE;

View File

@ -21,11 +21,12 @@ const ChromeObjectWrapper ChromeObjectWrapper::singleton;
bool
ChromeObjectWrapper::defineProperty(JSContext *cx, HandleObject wrapper,
HandleId id,
MutableHandle<JSPropertyDescriptor> desc) const
MutableHandle<JSPropertyDescriptor> desc,
JS::ObjectOpResult &result) const
{
if (!AccessCheck::checkPassToPrivilegedCode(cx, wrapper, desc.value()))
return false;
return ChromeObjectWrapperBase::defineProperty(cx, wrapper, id, desc);
return ChromeObjectWrapperBase::defineProperty(cx, wrapper, id, desc, result);
}
bool

View File

@ -29,7 +29,8 @@ class ChromeObjectWrapper : public ChromeObjectWrapperBase
virtual bool defineProperty(JSContext *cx, JS::Handle<JSObject*> wrapper,
JS::Handle<jsid> id,
JS::MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
JS::MutableHandle<JSPropertyDescriptor> desc,
JS::ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool set(JSContext *cx, JS::Handle<JSObject*> wrapper,
JS::Handle<JSObject*> receiver, JS::Handle<jsid> id,
bool strict, JS::MutableHandle<JS::Value> vp) const MOZ_OVERRIDE;

View File

@ -234,7 +234,8 @@ CrossOriginXrayWrapper::ownPropertyKeys(JSContext *cx, JS::Handle<JSObject*> wra
bool
CrossOriginXrayWrapper::defineProperty(JSContext *cx, JS::Handle<JSObject*> wrapper,
JS::Handle<jsid> id,
JS::MutableHandle<JSPropertyDescriptor> desc) const
JS::MutableHandle<JSPropertyDescriptor> desc,
JS::ObjectOpResult &result) const
{
JS_ReportError(cx, "Permission denied to define property on cross-origin object");
return false;

View File

@ -73,7 +73,8 @@ class CrossOriginXrayWrapper : public SecurityXrayDOM {
JS::MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
virtual bool defineProperty(JSContext *cx, JS::Handle<JSObject*> wrapper,
JS::Handle<jsid> id,
JS::MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
JS::MutableHandle<JSPropertyDescriptor> desc,
JS::ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool ownPropertyKeys(JSContext *cx, JS::Handle<JSObject*> wrapper,
JS::AutoIdVector &props) const MOZ_OVERRIDE;
virtual bool delete_(JSContext *cx, JS::Handle<JSObject*> wrapper,

View File

@ -568,9 +568,10 @@ JSXrayTraits::delete_(JSContext *cx, HandleObject wrapper, HandleId id, bool *bp
bool
JSXrayTraits::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
MutableHandle<JSPropertyDescriptor> desc,
Handle<JSPropertyDescriptor> existingDesc,
bool *defined)
MutableHandle<JSPropertyDescriptor> desc,
Handle<JSPropertyDescriptor> existingDesc,
ObjectOpResult &result,
bool *defined)
{
*defined = false;
RootedObject holder(cx, ensureHolder(cx, wrapper));
@ -613,9 +614,7 @@ JSXrayTraits::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
JSAutoCompartment ac(cx, target);
if (!JS_WrapPropertyDescriptor(cx, desc) ||
!JS_DefinePropertyById(cx, target, id, desc.value(),
desc.attributes(),
JS_STUBGETTER, JS_STUBSETTER))
!JS_DefinePropertyById(cx, target, id, desc, result))
{
return false;
}
@ -1199,13 +1198,7 @@ XPCWrappedNativeXrayTraits::resolveNativeProperty(JSContext *cx, HandleObject wr
FillPropertyDescriptor(desc, wrapper, 0,
ObjectValue(*JS_GetFunctionObject(toString)));
return JS_DefinePropertyById(cx, holder, id, desc.value(),
// 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())) &&
return JS_DefinePropertyById(cx, holder, id, desc) &&
JS_GetPropertyDescriptorById(cx, holder, id, desc);
}
@ -1260,14 +1253,7 @@ XPCWrappedNativeXrayTraits::resolveNativeProperty(JSContext *cx, HandleObject wr
if (desc.hasSetterObject())
desc.setSetterObject(&fval.toObject());
// Define the property.
return JS_DefinePropertyById(cx, holder, id, desc.value(),
// 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()));
return JS_DefinePropertyById(cx, holder, id, desc);
}
static bool
@ -1406,7 +1392,8 @@ XPCWrappedNativeXrayTraits::resolveOwnProperty(JSContext *cx, const Wrapper &jsW
bool
XPCWrappedNativeXrayTraits::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
MutableHandle<JSPropertyDescriptor> desc,
Handle<JSPropertyDescriptor> existingDesc, bool *defined)
Handle<JSPropertyDescriptor> existingDesc,
JS::ObjectOpResult &result, bool *defined)
{
*defined = false;
RootedObject holder(cx, singleton.ensureHolder(cx, wrapper));
@ -1416,7 +1403,7 @@ XPCWrappedNativeXrayTraits::defineProperty(JSContext *cx, HandleObject wrapper,
int32_t index = GetArrayIndexFromId(cx, id);
if (IsArrayIndex(index) && IsWindow(cx, wrapper)) {
*defined = true;
return true;
return result.succeed();
}
return true;
@ -1559,20 +1546,15 @@ DOMXrayTraits::resolveOwnProperty(JSContext *cx, const Wrapper &jsWrapper, Handl
if (!desc.object() || !cacheOnHolder)
return true;
return JS_DefinePropertyById(cx, holder, id, desc.value(),
// 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())) &&
return JS_DefinePropertyById(cx, holder, id, desc) &&
JS_GetPropertyDescriptorById(cx, holder, id, desc);
}
bool
DOMXrayTraits::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
MutableHandle<JSPropertyDescriptor> desc,
Handle<JSPropertyDescriptor> existingDesc, bool *defined)
Handle<JSPropertyDescriptor> existingDesc,
JS::ObjectOpResult &result, bool *defined)
{
// Check for an indexed property on a Window. If that's happening, do
// nothing but claim we defined it so it won't get added as an expando.
@ -1580,12 +1562,12 @@ DOMXrayTraits::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
int32_t index = GetArrayIndexFromId(cx, id);
if (IsArrayIndex(index)) {
*defined = true;
return true;
return result.succeed();
}
}
JS::Rooted<JSObject*> obj(cx, getTargetObject(wrapper));
return XrayDefineProperty(cx, wrapper, obj, id, desc, defined);
return XrayDefineProperty(cx, wrapper, obj, id, desc, result, defined);
}
bool
@ -1883,13 +1865,7 @@ XrayWrapper<Base, Traits>::getPropertyDescriptor(JSContext *cx, HandleObject wra
if (!desc.object())
return true;
if (!JS_DefinePropertyById(cx, holder, id, desc.value(),
// 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())) ||
if (!JS_DefinePropertyById(cx, holder, id, desc) ||
!JS_GetPropertyDescriptorById(cx, holder, id, desc))
{
return false;
@ -1976,8 +1952,8 @@ RecreateLostWaivers(JSContext *cx, JSPropertyDescriptor *orig,
template <typename Base, typename Traits>
bool
XrayWrapper<Base, Traits>::defineProperty(JSContext *cx, HandleObject wrapper,
HandleId id, MutableHandle<JSPropertyDescriptor> desc)
const
HandleId id, MutableHandle<JSPropertyDescriptor> desc,
ObjectOpResult &result) const
{
assertEnteredPolicy(cx, wrapper, id, BaseProxyHandler::SET);
@ -1999,17 +1975,17 @@ XrayWrapper<Base, Traits>::defineProperty(JSContext *cx, HandleObject wrapper,
(existing_desc.isReadonly() && !desc.isReadonly()))
{
// We should technically report non-configurability in strict mode, but
// doing that via JSAPI is a lot of trouble.
return true;
// doing that via JSAPI used to be a lot of trouble. See bug 1135997.
return result.succeed();
}
if (existing_desc.isReadonly()) {
// Same as the above for non-writability.
return true;
return result.succeed();
}
}
bool defined = false;
if (!Traits::singleton.defineProperty(cx, wrapper, id, desc, existing_desc, &defined))
if (!Traits::singleton.defineProperty(cx, wrapper, id, desc, existing_desc, result, &defined))
return false;
if (defined)
return true;
@ -2034,13 +2010,7 @@ XrayWrapper<Base, Traits>::defineProperty(JSContext *cx, HandleObject wrapper,
if (!RecreateLostWaivers(cx, desc.address(), &wrappedDesc))
return false;
return JS_DefinePropertyById(cx, expandoObject, id, wrappedDesc.value(),
// Descriptors never store JSNatives for
// accessors: they have either JSFunctions
// or JSPropertyOps.
wrappedDesc.get().attrs | JSPROP_PROPOP_ACCESSORS,
JS_PROPERTYOP_GETTER(wrappedDesc.getter()),
JS_PROPERTYOP_SETTER(wrappedDesc.setter()));
return JS_DefinePropertyById(cx, expandoObject, id, wrappedDesc, result);
}
template <typename Base, typename Traits>

View File

@ -126,7 +126,8 @@ public:
JS::MutableHandle<JSPropertyDescriptor> desc) MOZ_OVERRIDE;
bool defineProperty(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id,
JS::MutableHandle<JSPropertyDescriptor> desc,
JS::Handle<JSPropertyDescriptor> existingDesc, bool *defined);
JS::Handle<JSPropertyDescriptor> existingDesc,
JS::ObjectOpResult &result, bool *defined);
virtual bool enumerateNames(JSContext *cx, JS::HandleObject wrapper, unsigned flags,
JS::AutoIdVector &props);
static bool call(JSContext *cx, JS::HandleObject wrapper,
@ -177,7 +178,8 @@ public:
JS::MutableHandle<JSPropertyDescriptor> desc) MOZ_OVERRIDE;
bool defineProperty(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id,
JS::MutableHandle<JSPropertyDescriptor> desc,
JS::Handle<JSPropertyDescriptor> existingDesc, bool *defined);
JS::Handle<JSPropertyDescriptor> existingDesc,
JS::ObjectOpResult &result, bool *defined);
virtual bool enumerateNames(JSContext *cx, JS::HandleObject wrapper, unsigned flags,
JS::AutoIdVector &props);
static bool call(JSContext *cx, JS::HandleObject wrapper,
@ -219,7 +221,8 @@ public:
bool defineProperty(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id,
JS::MutableHandle<JSPropertyDescriptor> desc,
JS::Handle<JSPropertyDescriptor> existingDesc, bool *defined);
JS::Handle<JSPropertyDescriptor> existingDesc,
JS::ObjectOpResult &result, bool *defined);
virtual bool enumerateNames(JSContext *cx, JS::HandleObject wrapper, unsigned flags,
JS::AutoIdVector &props);
@ -336,7 +339,8 @@ public:
bool defineProperty(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id,
JS::MutableHandle<JSPropertyDescriptor> desc,
JS::Handle<JSPropertyDescriptor> existingDesc, bool *defined)
JS::Handle<JSPropertyDescriptor> existingDesc,
JS::ObjectOpResult &result, bool *defined)
{
*defined = false;
return true;
@ -408,7 +412,8 @@ class XrayWrapper : public Base {
virtual bool getOwnPropertyDescriptor(JSContext *cx, JS::Handle<JSObject*> wrapper, JS::Handle<jsid> id,
JS::MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
virtual bool defineProperty(JSContext *cx, JS::Handle<JSObject*> wrapper, JS::Handle<jsid> id,
JS::MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
JS::MutableHandle<JSPropertyDescriptor> desc,
JS::ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool ownPropertyKeys(JSContext *cx, JS::Handle<JSObject*> wrapper,
JS::AutoIdVector &props) const MOZ_OVERRIDE;
virtual bool delete_(JSContext *cx, JS::Handle<JSObject*> wrapper,