import changes from rmottola/Arctic-Fox:

- Bug 1113369, part 1 - Introduce JS::ObjectOpResult and use it in js::StandardDefineProperty. (15663c476)
- Bug 1113369, part 1½ - Avoid regressing error messages by adding obj to the ObjectOpResult methods that could throw a TypeError. (e063faf08)
- Bug 1113369, part 2 - js::SetArrayLength ObjectOpResult support. (cf8326017)
- Bug 1113369, part 3 - [[DefineOwnProperty]] ObjectOpResult support. (e16605a90)
- Bug 1113369, part 4 - [[Set]] ObjectOpResult support. (6f94604d4)
This commit is contained in:
2019-02-07 18:42:28 +08:00
parent 26882c6ce0
commit fbd797d49d
86 changed files with 1464 additions and 925 deletions
+2 -1
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);
+2 -1
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 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 override;
+1 -7
View File
@@ -1170,13 +1170,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;
}
+13 -15
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 override;
JS::MutableHandle<JSPropertyDescriptor> desc,
JS::ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool ownPropertyKeys(JSContext *cx,
JS::Handle<JSObject*> proxy,
JS::AutoIdVector &props) const override;
@@ -646,8 +646,8 @@ public:
virtual bool set(JSContext *cx, JS::Handle<JSObject*> proxy,
JS::Handle<JSObject*> receiver,
JS::Handle<jsid> id,
bool strict,
JS::MutableHandle<JS::Value> vp) const override;
JS::MutableHandle<JS::Value> vp,
JS::ObjectOpResult &result) const MOZ_OVERRIDE;
// SpiderMonkey extensions
virtual bool getPropertyDescriptor(JSContext* cx,
@@ -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
@@ -917,19 +917,17 @@ bool
nsOuterWindowProxy::set(JSContext *cx, JS::Handle<JSObject*> proxy,
JS::Handle<JSObject*> receiver,
JS::Handle<jsid> id,
bool strict,
JS::MutableHandle<JS::Value> vp) const
JS::MutableHandle<JS::Value> vp,
JS::ObjectOpResult &result) const
{
int32_t index = GetArrayIndexFromId(cx, id);
if (IsArrayIndex(index)) {
// Reject (which means throw if and only if strict) the set.
if (strict) {
// XXXbz This needs to throw, but see bug 828137.
}
return true;
// XXX See bug 828137.
return result.succeed();
}
return js::Wrapper::set(cx, proxy, receiver, id, strict, vp);
return js::Wrapper::set(cx, proxy, receiver, id, vp, result);
}
bool
+4 -3
View File
@@ -1469,13 +1469,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>
+6 -1
View File
@@ -2450,12 +2450,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
+14 -14
View File
@@ -7623,10 +7623,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;
@@ -9621,10 +9618,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;
}
}
@@ -10187,10 +10181,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
@@ -10208,7 +10205,7 @@ class CGDOMJSProxyHandler_defineProperty(ClassMethod):
if (IsArrayIndex(index)) {
*defined = true;
$*{callSetter}
return true;
return opresult.succeed();
}
""",
callSetter=CGProxyIndexedSetter(self.descriptor).define())
@@ -10221,7 +10218,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)
@@ -10236,8 +10235,7 @@ class CGDOMJSProxyHandler_defineProperty(ClassMethod):
"}\n"
"if (hasUnforgeable) {\n"
" *defined = true;\n"
" bool unused;\n"
" return js::DefineOwnProperty(cx, ${holder}, id, desc, &unused);\n"
" return js::DefineOwnProperty(cx, ${holder}, id, desc, opresult);\n"
"}\n")
set += CallOnUnforgeableHolder(self.descriptor,
defineOnUnforgeable,
@@ -10254,7 +10252,7 @@ class CGDOMJSProxyHandler_defineProperty(ClassMethod):
*defined = true;
$*{callSetter}
return true;
return opresult.succeed();
""",
callSetter=CGProxyNamedSetter(self.descriptor).define())
else:
@@ -10270,7 +10268,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(),
+12 -12
View File
@@ -195,18 +195,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);
@@ -214,13 +211,16 @@ 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
DOMProxyHandler::set(JSContext *cx, Handle<JSObject*> proxy, Handle<JSObject*> receiver,
Handle<jsid> id, bool strict, MutableHandle<JS::Value> vp) const
Handle<jsid> id, MutableHandle<JS::Value> vp, ObjectOpResult &result) const
{
MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy),
"Should not have a XrayWrapper here");
@@ -229,7 +229,7 @@ DOMProxyHandler::set(JSContext *cx, Handle<JSObject*> proxy, Handle<JSObject*> r
return false;
}
if (done) {
return true;
return result.succeed();
}
// Make sure to ignore our named properties when checking for own
@@ -254,7 +254,7 @@ DOMProxyHandler::set(JSContext *cx, Handle<JSObject*> proxy, Handle<JSObject*> r
}
return js::SetPropertyIgnoringNamedGetter(cx, this, proxy, receiver, id,
&desc, descIsOwn, strict, vp);
&desc, descIsOwn, vp, result);
}
bool
+10 -9
View File
@@ -105,25 +105,26 @@ public:
{}
bool defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
JS::MutableHandle<JSPropertyDescriptor> desc) const 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 override;
JS::Handle<jsid> id, bool* bp) const MOZ_OVERRIDE;
bool preventExtensions(JSContext *cx, JS::Handle<JSObject*> proxy,
bool *succeeded) const override;
bool *succeeded) const MOZ_OVERRIDE;
bool isExtensible(JSContext *cx, JS::Handle<JSObject*> proxy, bool *extensible)
const override;
bool has(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
bool* bp) const override;
bool* bp) const MOZ_OVERRIDE;
bool set(JSContext *cx, JS::Handle<JSObject*> proxy, JS::Handle<JSObject*> receiver,
JS::Handle<jsid> id, bool strict, JS::MutableHandle<JS::Value> vp)
const override;
JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp, JS::ObjectOpResult &result)
const MOZ_OVERRIDE;
/*
* If assigning to proxy[id] hits a named setter with OverrideBuiltins or
+5 -5
View File
@@ -169,8 +169,8 @@ static bool
NPObjWrapper_DelProperty(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, bool *succeeded);
static bool
NPObjWrapper_SetProperty(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, bool strict,
JS::MutableHandle<JS::Value> vp);
NPObjWrapper_SetProperty(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
JS::MutableHandle<JS::Value> vp, JS::ObjectOpResult &result);
static bool
NPObjWrapper_GetProperty(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp);
@@ -1326,8 +1326,8 @@ NPObjWrapper_DelProperty(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<js
}
static bool
NPObjWrapper_SetProperty(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, bool strict,
JS::MutableHandle<JS::Value> vp)
NPObjWrapper_SetProperty(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
JS::MutableHandle<JS::Value> vp, JS::ObjectOpResult &result)
{
NPObject *npobj = GetNPObject(cx, obj);
@@ -1382,7 +1382,7 @@ NPObjWrapper_SetProperty(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<js
return false;
}
return true;
return result.succeed();
}
static bool
+8 -9
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,
@@ -75,9 +74,9 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base
return Answer::RecvGet(ObjectId::deserialize(objId), receiverVar, id, rs, result);
}
bool RecvSet(const uint64_t& objId, const ObjectVariant& receiverVar,
const JSIDVariant& id, const bool& strict,
const JSVariant& value, ReturnStatus* rs, JSVariant* result) {
return Answer::RecvSet(ObjectId::deserialize(objId), receiverVar, id, strict, value, rs, result);
const JSIDVariant &id, const JSVariant &value, ReturnStatus *rs,
JSVariant *result) {
return Answer::RecvSet(ObjectId::deserialize(objId), receiverVar, id, value, rs, result);
}
bool RecvIsExtensible(const uint64_t& objId, ReturnStatus* rs,
@@ -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,
@@ -167,9 +166,9 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base
return Base::SendGet(objId.serialize(), receiverVar, id, rs, result);
}
bool SendSet(const ObjectId& objId, const ObjectVariant& receiverVar,
const JSIDVariant& id, const bool& strict,
const JSVariant& value, ReturnStatus* rs, JSVariant* result) {
return Base::SendSet(objId.serialize(), receiverVar, id, strict, value, rs, result);
const JSIDVariant &id, const JSVariant &value, ReturnStatus *rs,
JSVariant *result) {
return Base::SendSet(objId.serialize(), receiverVar, id, value, rs, result);
}
bool SendIsExtensible(const ObjectId& objId, ReturnStatus* rs,
+2 -1
View File
@@ -605,7 +605,8 @@ UnknownPropertyStub(JSContext* cx, HandleObject obj, HandleId id, MutableHandleV
}
bool
UnknownStrictPropertyStub(JSContext* cx, HandleObject obj, HandleId id, bool strict, MutableHandleValue vp)
UnknownStrictPropertyStub(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp,
ObjectOpResult &result)
{
JS_ReportError(cx, "setter could not be wrapped via CPOWs");
return false;
+6
View File
@@ -103,11 +103,17 @@ struct ReturnException
JSVariant exn;
};
struct ReturnObjectOpResult
{
uint32_t code;
};
union ReturnStatus
{
ReturnSuccess;
ReturnStopIteration;
ReturnException;
ReturnObjectOpResult;
};
union JSParam
+1 -1
View File
@@ -33,7 +33,7 @@ both:
prio(high) sync Has(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, bool has);
prio(high) sync HasOwn(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, bool has);
prio(high) sync Get(uint64_t objId, ObjectVariant receiver, JSIDVariant id) returns (ReturnStatus rs, JSVariant result);
prio(high) sync Set(uint64_t objId, ObjectVariant receiver, JSIDVariant id, bool strict, JSVariant value) returns (ReturnStatus rs, JSVariant result);
prio(high) sync Set(uint64_t objId, ObjectVariant receiver, JSIDVariant id, JSVariant value) returns (ReturnStatus rs, JSVariant result);
prio(high) sync IsExtensible(uint64_t objId) returns (ReturnStatus rs, bool result);
prio(high) sync CallOrConstruct(uint64_t objId, JSParam[] argv, bool construct) returns (ReturnStatus rs, JSVariant result, JSParam[] outparams);
+20 -12
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
@@ -305,8 +313,8 @@ WrapperAnswer::RecvGet(const ObjectId& objId, const ObjectVariant& receiverVar,
bool
WrapperAnswer::RecvSet(const ObjectId& objId, const ObjectVariant& receiverVar,
const JSIDVariant& idVar, const bool& strict, const JSVariant& value,
ReturnStatus* rs, JSVariant* result)
const JSIDVariant &idVar, const JSVariant &value, ReturnStatus *rs,
JSVariant *resultValue)
{
// We may run scripted setters.
AutoEntryScript aes(xpc::NativeGlobal(scopeForTargetObjects()));
@@ -314,7 +322,7 @@ WrapperAnswer::RecvSet(const ObjectId& objId, const ObjectVariant& receiverVar,
// The outparam will be written to the buffer, so it must be set even if
// the parent won't read it.
*result = UndefinedVariant();
*resultValue = UndefinedVariant();
RootedObject obj(cx, findObjectById(cx, objId));
if (!obj)
@@ -330,19 +338,19 @@ WrapperAnswer::RecvSet(const ObjectId& objId, const ObjectVariant& receiverVar,
if (!fromJSIDVariant(cx, idVar, &id))
return fail(cx, rs);
MOZ_ASSERT(obj == receiver);
RootedValue val(cx);
if (!fromVariant(cx, value, &val))
return fail(cx, rs);
if (!JS_SetPropertyById(cx, obj, id, val))
ObjectOpResult result;
RootedValue receiverVal(cx, ObjectValue(*receiver));
if (!JS_ForwardSetPropertyTo(cx, obj, id, val, receiverVal, result))
return fail(cx, rs);
if (!toVariant(cx, val, result))
if (!toVariant(cx, val, resultValue))
return fail(cx, rs);
return ok(rs);
return ok(rs, result);
}
bool
+5 -5
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);
@@ -41,8 +40,8 @@ class WrapperAnswer : public virtual JavaScriptShared
const JSIDVariant& id,
ReturnStatus* rs, JSVariant* result);
bool RecvSet(const ObjectId& objId, const ObjectVariant& receiverVar,
const JSIDVariant& id, const bool& strict,
const JSVariant& value, ReturnStatus* rs, JSVariant* result);
const JSIDVariant &id, const JSVariant &value, ReturnStatus *rs,
JSVariant *result);
bool RecvIsExtensible(const ObjectId& objId, ReturnStatus* rs,
bool* result);
@@ -67,7 +66,8 @@ class WrapperAnswer : public virtual JavaScriptShared
private:
bool fail(JSContext* cx, ReturnStatus* rs);
bool ok(ReturnStatus* rs);
bool ok(ReturnStatus *rs);
bool ok(ReturnStatus *rs, const JS::ObjectOpResult &result);
};
} // mozilla
+27 -13
View File
@@ -90,7 +90,8 @@ class CPOWProxyHandler : public BaseProxyHandler
virtual bool getOwnPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
MutableHandle<JSPropertyDescriptor> desc) const override;
virtual bool defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
MutableHandle<JSPropertyDescriptor> desc) const override;
MutableHandle<JSPropertyDescriptor> desc,
ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool ownPropertyKeys(JSContext* cx, HandleObject proxy,
AutoIdVector& props) const override;
virtual bool delete_(JSContext* cx, HandleObject proxy, HandleId id, bool* bp) const override;
@@ -101,7 +102,8 @@ class CPOWProxyHandler : public BaseProxyHandler
virtual bool get(JSContext* cx, HandleObject proxy, HandleObject receiver,
HandleId id, MutableHandleValue vp) const override;
virtual bool set(JSContext* cx, JS::HandleObject proxy, JS::HandleObject receiver,
JS::HandleId id, bool strict, JS::MutableHandleValue vp) const override;
JS::HandleId id, JS::MutableHandleValue vp,
JS::ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool call(JSContext* cx, HandleObject proxy, const CallArgs& args) const override;
virtual bool construct(JSContext* cx, HandleObject proxy, const CallArgs& args) const override;
@@ -202,14 +204,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 +231,7 @@ WrapperOwner::defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
LOG_STACK();
return ok(cx, status);
return ok(cx, status, result);
}
bool
@@ -431,14 +435,14 @@ WrapperOwner::get(JSContext* cx, HandleObject proxy, HandleObject receiver,
bool
CPOWProxyHandler::set(JSContext* cx, JS::HandleObject proxy, JS::HandleObject receiver,
JS::HandleId id, bool strict, JS::MutableHandleValue vp) const
JS::HandleId id, JS::MutableHandleValue vp, JS::ObjectOpResult &result) const
{
FORWARD(set, (cx, proxy, receiver, id, strict, vp));
FORWARD(set, (cx, proxy, receiver, id, vp, result));
}
bool
WrapperOwner::set(JSContext* cx, JS::HandleObject proxy, JS::HandleObject receiver,
JS::HandleId id, bool strict, JS::MutableHandleValue vp)
JS::HandleId id, JS::MutableHandleValue vp, JS::ObjectOpResult &result)
{
ObjectId objId = idOf(proxy);
@@ -455,16 +459,16 @@ WrapperOwner::set(JSContext* cx, JS::HandleObject proxy, JS::HandleObject receiv
return false;
ReturnStatus status;
JSVariant result;
if (!SendSet(objId, receiverVar, idVar, strict, val, &status, &result))
JSVariant resultValue;
if (!SendSet(objId, receiverVar, idVar, val, &status, &resultValue))
return ipcfail(cx);
LOG_STACK();
if (!ok(cx, status))
if (!ok(cx, status, result))
return false;
return fromVariant(cx, result, vp);
return fromVariant(cx, resultValue, vp);
}
bool
@@ -934,6 +938,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)
{
+9 -4
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);
@@ -41,7 +42,7 @@ class WrapperOwner : public virtual JavaScriptShared
bool get(JSContext* cx, JS::HandleObject proxy, JS::HandleObject receiver,
JS::HandleId id, JS::MutableHandleValue vp);
bool set(JSContext* cx, JS::HandleObject proxy, JS::HandleObject receiver,
JS::HandleId id, bool strict, JS::MutableHandleValue vp);
JS::HandleId id, JS::MutableHandleValue vp, JS::ObjectOpResult &result);
bool callOrConstruct(JSContext* cx, JS::HandleObject proxy, const JS::CallArgs& args,
bool construct);
@@ -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_;
@@ -123,8 +128,8 @@ class WrapperOwner : public virtual JavaScriptShared
const JSIDVariant& id,
ReturnStatus* rs, JSVariant* result) = 0;
virtual bool SendSet(const ObjectId& objId, const ObjectVariant& receiverVar,
const JSIDVariant& id, const bool& strict,
const JSVariant& value, ReturnStatus* rs, JSVariant* result) = 0;
const JSIDVariant &id, const JSVariant &value,
ReturnStatus *rs, JSVariant *result) = 0;
virtual bool SendIsExtensible(const ObjectId& objId, ReturnStatus* rs,
bool* result) = 0;
+125 -3
View File
@@ -44,6 +44,127 @@ namespace JS {
class AutoIdVector;
/*
* Per ES6, the [[DefineOwnProperty]] internal method has three different
* possible outcomes:
*
* - It can throw an exception (which we indicate by returning false).
*
* - It can return true, indicating unvarnished success.
*
* - It can return false, indicating "strict failure". The property could
* not be defined. It's an error, but no exception was thrown.
*
* It's not just [[DefineOwnProperty]]: all the mutating internal methods have
* the same three outcomes. (The other affected internal methods are [[Set]],
* [[Delete]], [[SetPrototypeOf]], and [[PreventExtensions]].)
*
* If you think this design is awful, you're not alone. But as it's the
* standard, we must represent these boolean "success" values somehow.
* ObjectOpSuccess is the class for this. It's like a bool, but when it's false
* it also stores an error code.
*
* Typical usage:
*
* ObjectOpResult result;
* if (!DefineProperty(cx, obj, id, ..., result))
* return false;
* if (!result)
* return result.reportError(cx, obj, id);
*
* Users don't have to call `result.report()`; another possible ending is:
*
* argv.rval().setBoolean(bool(result));
* return true;
*/
class ObjectOpResult
{
private:
uint32_t code_;
public:
enum { OkCode = 0, Uninitialized = 0xffffffff };
ObjectOpResult() : code_(Uninitialized) {}
/* Return true if fail() was not called. */
bool ok() const {
MOZ_ASSERT(code_ != Uninitialized);
return code_ == OkCode;
}
explicit operator bool() const { return ok(); }
/* Set this ObjectOpResult to true and return true. */
bool succeed() {
code_ = OkCode;
return true;
}
/*
* Set this ObjectOpResult to false with an error code.
*
* Always returns true, as a convenience. Typical usage will be:
*
* if (funny condition)
* return result.fail(JSMSG_CANT_DO_THE_THINGS);
*
* The true return value indicates that no exception is pending, and it
* would be OK to ignore the failure and continue.
*/
bool fail(uint32_t msg) {
MOZ_ASSERT(msg != OkCode);
code_ = msg;
return true;
}
JS_PUBLIC_API(bool) failCantRedefineProp();
JS_PUBLIC_API(bool) failReadOnly();
JS_PUBLIC_API(bool) failGetterOnly();
JS_PUBLIC_API(bool) failCantSetInterposed();
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
* a warning if extraWarnings are enabled.
*
* The precise rules are like this:
*
* - If ok(), then we succeeded. Do nothing and return true.
* - Otherwise, if |strict| is true, or if cx has both extraWarnings and
* werrorOption enabled, throw a TypeError and return false.
* - Otherwise, if cx has extraWarnings enabled, emit a warning and
* return true.
* - Otherwise, do nothing and return true.
*/
bool checkStrictErrorOrWarning(JSContext *cx, HandleObject obj, HandleId id, bool strict) {
if (ok())
return true;
return reportStrictErrorOrWarning(cx, obj, id, strict);
}
/*
* Convenience method. Return true if ok() or if strict is false; otherwise
* throw a TypeError and return false.
*/
bool checkStrict(JSContext *cx, HandleObject obj, HandleId id) {
return checkStrictErrorOrWarning(cx, obj, id, true);
}
/* Throw a TypeError. Call this only if !ok(). */
bool reportError(JSContext *cx, HandleObject obj, HandleId id) {
return reportStrictErrorOrWarning(cx, obj, id, true);
}
/* Helper function for checkStrictErrorOrWarning's slow path. */
JS_PUBLIC_API(bool) reportStrictErrorOrWarning(JSContext *cx, HandleObject obj, HandleId id, bool strict);
};
}
// JSClass operation signatures.
@@ -62,7 +183,7 @@ typedef bool
// set.
typedef bool
(* JSStrictPropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
bool strict, JS::MutableHandleValue vp);
JS::MutableHandleValue vp, JS::ObjectOpResult &result);
// Delete a property named by id in obj.
//
@@ -166,7 +287,8 @@ typedef bool
JS::MutableHandleObject objp, JS::MutableHandle<Shape*> propp);
typedef bool
(* DefinePropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue value,
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs,
JS::ObjectOpResult &result);
typedef bool
(* HasPropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* foundp);
typedef bool
@@ -174,7 +296,7 @@ typedef bool
JS::MutableHandleValue vp);
typedef bool
(* SetPropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleObject receiver, JS::HandleId id,
JS::MutableHandleValue vp, bool strict);
JS::MutableHandleValue vp, JS::ObjectOpResult &result);
typedef bool
(* GetOwnPropertyOp)(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
JS::MutableHandle<JSPropertyDescriptor> desc);
+8 -4
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;
@@ -289,7 +291,7 @@ class JS_FRIEND_API(BaseProxyHandler)
virtual bool get(JSContext* cx, HandleObject proxy, HandleObject receiver,
HandleId id, MutableHandleValue vp) const;
virtual bool set(JSContext* cx, HandleObject proxy, HandleObject receiver,
HandleId id, bool strict, MutableHandleValue vp) const;
HandleId id, MutableHandleValue vp, ObjectOpResult &result) const;
/*
* [[Call]] and [[Construct]] are standard internal methods but according
@@ -368,7 +370,8 @@ class JS_PUBLIC_API(DirectProxyHandler) : public BaseProxyHandler
virtual bool getOwnPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
MutableHandle<JSPropertyDescriptor> desc) const override;
virtual bool defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
MutableHandle<JSPropertyDescriptor> desc) const override;
MutableHandle<JSPropertyDescriptor> desc,
ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool ownPropertyKeys(JSContext* cx, HandleObject proxy,
AutoIdVector& props) const override;
virtual bool delete_(JSContext* cx, HandleObject proxy, HandleId id,
@@ -388,7 +391,8 @@ class JS_PUBLIC_API(DirectProxyHandler) : public BaseProxyHandler
virtual bool get(JSContext* cx, HandleObject proxy, HandleObject receiver,
HandleId id, MutableHandleValue vp) const override;
virtual bool set(JSContext* cx, HandleObject proxy, HandleObject receiver,
HandleId id, bool strict, MutableHandleValue vp) const override;
HandleId id, MutableHandleValue vp,
ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool call(JSContext* cx, HandleObject proxy, const CallArgs& args) const override;
virtual bool construct(JSContext* cx, HandleObject proxy, const CallArgs& args) const override;
+3
View File
@@ -45,6 +45,7 @@ class MOZ_STACK_CLASS SourceBufferHolder;
class HandleValueArray;
class ObjectOpResult;
}
// Do the importing.
@@ -143,6 +144,8 @@ using JS::FalseHandleValue;
using JS::HandleValueArray;
using JS::ObjectOpResult;
using JS::Zone;
} /* namespace js */
+1 -2
View File
@@ -833,8 +833,7 @@ js::obj_defineProperty(JSContext* cx, unsigned argc, Value* vp)
if (!desc.initialize(cx, args.get(2)))
return false;
bool ignored;
if (!StandardDefineProperty(cx, obj, id, desc, true, &ignored))
if (!StandardDefineProperty(cx, obj, id, desc))
return false;
args.rval().setObject(*obj);
+13 -8
View File
@@ -1755,7 +1755,8 @@ ReportPropertyError(JSContext* cx,
bool
TypedObject::obj_defineProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
ObjectOpResult &result)
{
Rooted<TypedObject*> typedObj(cx, &obj->as<TypedObject>());
return ReportTypedObjTypeError(cx, JSMSG_OBJECT_NOT_EXTENSIBLE, typedObj);
@@ -1907,7 +1908,7 @@ TypedObject::obj_getArrayElement(JSContext* cx,
bool
TypedObject::obj_setProperty(JSContext* cx, HandleObject obj, HandleObject receiver, HandleId id,
MutableHandleValue vp, bool strict)
MutableHandleValue vp, ObjectOpResult &result)
{
Rooted<TypedObject*> typedObj(cx, &obj->as<TypedObject>());
@@ -1926,13 +1927,13 @@ TypedObject::obj_setProperty(JSContext* cx, HandleObject obj, HandleObject recei
nullptr, JSMSG_CANT_REDEFINE_ARRAY_LENGTH);
return false;
}
return SetNonWritableProperty(cx, id, strict);
return result.failReadOnly();
}
uint32_t index;
if (IdIsIndex(id, &index)) {
if (obj != receiver)
return SetPropertyByDefining(cx, obj, receiver, id, vp, strict, false);
return SetPropertyByDefining(cx, obj, receiver, id, vp, false, result);
if (index >= uint32_t(typedObj->length())) {
JS_ReportErrorNumber(cx, GetErrorMessage,
@@ -1943,7 +1944,9 @@ TypedObject::obj_setProperty(JSContext* cx, HandleObject obj, HandleObject recei
Rooted<TypeDescr*> elementType(cx);
elementType = &typedObj->typeDescr().as<ArrayTypeDescr>().elementType();
size_t offset = elementType->size() * index;
return ConvertAndCopyTo(cx, elementType, typedObj, offset, NullPtr(), vp);
if (!ConvertAndCopyTo(cx, elementType, typedObj, offset, NullPtr(), vp))
return false;
return result.succeed();
}
break;
}
@@ -1956,16 +1959,18 @@ TypedObject::obj_setProperty(JSContext* cx, HandleObject obj, HandleObject recei
break;
if (obj != receiver)
return SetPropertyByDefining(cx, obj, receiver, id, vp, strict, false);
return SetPropertyByDefining(cx, obj, receiver, id, vp, false, result);
size_t offset = descr->fieldOffset(fieldIndex);
Rooted<TypeDescr*> fieldType(cx, &descr->fieldDescr(fieldIndex));
RootedAtom fieldName(cx, &descr->fieldName(fieldIndex));
return ConvertAndCopyTo(cx, fieldType, typedObj, offset, fieldName, vp);
if (!ConvertAndCopyTo(cx, fieldType, typedObj, offset, fieldName, vp))
return false;
return result.succeed();
}
}
return SetPropertyOnProto(cx, obj, receiver, id, vp, strict);
return SetPropertyOnProto(cx, obj, receiver, id, vp, result);
}
bool
+3 -2
View File
@@ -528,7 +528,8 @@ class TypedObject : public JSObject
MutableHandleObject objp, MutableHandleShape propp);
static bool obj_defineProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
ObjectOpResult &result);
static bool obj_hasProperty(JSContext* cx, HandleObject obj, HandleId id, bool* foundp);
@@ -539,7 +540,7 @@ class TypedObject : public JSObject
uint32_t index, MutableHandleValue vp);
static bool obj_setProperty(JSContext* cx, HandleObject obj, HandleObject receiver,
HandleId id, MutableHandleValue vp, bool strict);
HandleId id, MutableHandleValue vp, ObjectOpResult &result);
static bool obj_getOwnPropertyDescriptor(JSContext* cx, HandleObject obj, HandleId id,
MutableHandle<JSPropertyDescriptor> desc);
+17 -10
View File
@@ -287,7 +287,8 @@ namespace ArrayType {
bool LengthGetter(JSContext* cx, const JS::CallArgs& args);
static bool Getter(JSContext* cx, HandleObject obj, HandleId idval, MutableHandleValue vp);
static bool Setter(JSContext* cx, HandleObject obj, HandleId idval, bool strict, MutableHandleValue vp);
static bool Setter(JSContext* cx, HandleObject obj, HandleId idval, MutableHandleValue vp,
ObjectOpResult &result);
static bool AddressOfElement(JSContext* cx, unsigned argc, jsval* vp);
}
@@ -300,9 +301,9 @@ namespace StructType {
bool FieldsArrayGetter(JSContext* cx, const JS::CallArgs& args);
static bool FieldGetter(JSContext* cx, HandleObject obj, HandleId idval,
MutableHandleValue vp);
static bool FieldSetter(JSContext* cx, HandleObject obj, HandleId idval, bool strict,
MutableHandleValue vp);
MutableHandleValue vp);
static bool FieldSetter(JSContext* cx, HandleObject obj, HandleId idval,
MutableHandleValue vp, ObjectOpResult &result);
static bool AddressOfField(JSContext* cx, unsigned argc, jsval* vp);
static bool Define(JSContext* cx, unsigned argc, jsval* vp);
}
@@ -4628,7 +4629,8 @@ ArrayType::Getter(JSContext* cx, HandleObject obj, HandleId idval, MutableHandle
}
bool
ArrayType::Setter(JSContext* cx, HandleObject obj, HandleId idval, bool strict, MutableHandleValue vp)
ArrayType::Setter(JSContext* cx, HandleObject obj, HandleId idval, MutableHandleValue vp,
ObjectOpResult &result)
{
// This should never happen, but we'll check to be safe.
if (!CData::IsCData(obj)) {
@@ -4640,7 +4642,7 @@ ArrayType::Setter(JSContext* cx, HandleObject obj, HandleId idval, bool strict,
// CData, regardless of CType.)
JSObject* typeObj = CData::GetCType(obj);
if (CType::GetTypeCode(typeObj) != TYPE_array)
return true;
return result.succeed();
// Convert the index to a size_t and bounds-check it.
size_t index;
@@ -4650,7 +4652,7 @@ ArrayType::Setter(JSContext* cx, HandleObject obj, HandleId idval, bool strict,
if (!ok && JSID_IS_STRING(idval) && !StringToInteger(cx, JSID_TO_STRING(idval), &dummy)) {
// String either isn't a number, or doesn't fit in size_t.
// Chances are it's a regular property lookup, so return.
return true;
return result.succeed();
}
if (!ok || index >= length) {
JS_ReportError(cx, "invalid index");
@@ -4660,7 +4662,9 @@ ArrayType::Setter(JSContext* cx, HandleObject obj, HandleId idval, bool strict,
JSObject* baseType = GetBaseType(typeObj);
size_t elementSize = CType::GetSize(baseType);
char* data = static_cast<char*>(CData::GetData(obj)) + elementSize * index;
return ImplicitConvert(cx, vp, baseType, data, false, nullptr);
if (!ImplicitConvert(cx, vp, baseType, data, false, nullptr))
return false;
return result.succeed();
}
bool
@@ -5293,7 +5297,8 @@ StructType::FieldGetter(JSContext* cx, HandleObject obj, HandleId idval, Mutable
}
bool
StructType::FieldSetter(JSContext* cx, HandleObject obj, HandleId idval, bool strict, MutableHandleValue vp)
StructType::FieldSetter(JSContext* cx, HandleObject obj, HandleId idval, MutableHandleValue vp,
ObjectOpResult &result)
{
if (!CData::IsCData(obj)) {
JS_ReportError(cx, "not a CData");
@@ -5311,7 +5316,9 @@ StructType::FieldSetter(JSContext* cx, HandleObject obj, HandleId idval, bool st
return false;
char* data = static_cast<char*>(CData::GetData(obj)) + field->mOffset;
return ImplicitConvert(cx, vp, field->mType, data, false, nullptr);
if (!ImplicitConvert(cx, vp, field->mType, data, false, nullptr))
return false;
return result.succeed();
}
bool
@@ -99,7 +99,7 @@ check("o[- (o)]");
// A few one off tests
check_one("6", (function () { 6() }), " is not a function");
check_one("Array.prototype.reverse.call(...)", (function () { Array.prototype.reverse.call('123'); }), " is read-only");
check_one("0", (function () { Array.prototype.reverse.call('123'); }), " is read-only");
check_one(`(intermediate value)[Symbol.iterator](...).next(...).value`,
function () { var [{ x }] = [null, {}]; }, " is null");
check_one(`(intermediate value)[Symbol.iterator](...).next(...).value`,
+1 -1
View File
@@ -8382,7 +8382,7 @@ DoSetPropFallback(JSContext* cx, BaselineFrame* frame, ICSetProp_Fallback* stub_
MOZ_ASSERT(op == JSOP_SETPROP || op == JSOP_STRICTSETPROP);
RootedValue v(cx, rhs);
if (!SetProperty(cx, obj, obj, id, &v, op == JSOP_STRICTSETPROP))
if (!PutProperty(cx, obj, id, &v, op == JSOP_STRICTSETPROP))
return false;
}
+99 -18
View File
@@ -1460,6 +1460,13 @@ GetPropertyIC::tryAttachTypedArrayLength(JSContext* cx, HandleScript outerScript
return linkAndAttachStub(cx, masm, attacher, ion, "typed array length");
}
static void
PushObjectOpResult(MacroAssembler &masm, uint32_t value = ObjectOpResult::Uninitialized)
{
static_assert(sizeof(ObjectOpResult) == sizeof(int32_t),
"ObjectOpResult size must match size reserved by masm.Push() here");
masm.Push(Imm32(value));
}
static bool
EmitCallProxyGet(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& attacher,
@@ -1504,6 +1511,9 @@ EmitCallProxyGet(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& at
masm.Push(object);
masm.movePtr(StackPointer, argProxyReg);
// Unused space, to keep the same stack layout as Proxy::set frames.
PushObjectOpResult(masm, 0);
masm.loadJSContext(argJSContextReg);
if (!masm.icBuildOOLFakeExitFrame(returnAddr, aic))
@@ -2118,6 +2128,54 @@ IsCacheableSetPropCallPropertyOp(HandleObject obj, HandleObject holder, HandleSh
return true;
}
static bool
ReportStrictErrorOrWarning(JSContext *cx, JS::HandleObject obj, JS::HandleId id, bool strict,
JS::ObjectOpResult &result)
{
return result.reportStrictErrorOrWarning(cx, obj, id, strict);
}
template <class FrameLayout>
void
EmitObjectOpResultCheck(MacroAssembler &masm, Label *failure, bool strict,
Register scratchReg,
Register argJSContextReg,
Register argObjReg,
Register argIdReg,
Register argStrictReg,
Register argResultReg)
{
// if (!result) {
Label noStrictError;
masm.branch32(Assembler::Equal,
Address(StackPointer,
FrameLayout::offsetOfObjectOpResult()),
Imm32(ObjectOpResult::OkCode),
&noStrictError);
// if (!ReportStrictErrorOrWarning(cx, obj, id, strict, &result))
// goto failure;
masm.loadJSContext(argJSContextReg);
masm.computeEffectiveAddress(
Address(StackPointer, FrameLayout::offsetOfId()),
argIdReg);
masm.move32(Imm32(strict), argStrictReg);
masm.computeEffectiveAddress(
Address(StackPointer, FrameLayout::offsetOfObjectOpResult()),
argResultReg);
masm.setupUnalignedABICall(5, scratchReg);
masm.passABIArg(argJSContextReg);
masm.passABIArg(argObjReg);
masm.passABIArg(argIdReg);
masm.passABIArg(argStrictReg);
masm.passABIArg(argResultReg);
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, ReportStrictErrorOrWarning));
masm.branchIfFalseBool(ReturnReg, failure);
// }
masm.bind(&noStrictError);
}
static bool
EmitCallProxySet(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& attacher,
HandleId propId, RegisterSet liveRegs, Register object,
@@ -2125,18 +2183,23 @@ EmitCallProxySet(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& at
{
MacroAssembler::AfterICSaveLive aic = masm.icSaveLive(liveRegs);
// Remaining registers should be free, but we need to use |object| still
// so leave it alone.
// Remaining registers should be free, but we still need to use |object| so
// leave it alone.
//
// WARNING: We do not take() the register used by |value|, if any, so
// regSet is going to re-allocate it. Hence the emitted code must not touch
// any of the registers allocated from regSet until after the last use of
// |value|. (We can't afford to take it, either, because x86.)
RegisterSet regSet(RegisterSet::All());
regSet.take(AnyRegister(object));
// Proxy::set(JSContext* cx, HandleObject proxy, HandleObject receiver, HandleId id,
// bool strict, MutableHandleValue vp)
// MutableHandleValue vp, ObjectOpResult &result)
Register argJSContextReg = regSet.takeGeneral();
Register argProxyReg = regSet.takeGeneral();
Register argIdReg = regSet.takeGeneral();
Register argVpReg = regSet.takeGeneral();
Register argStrictReg = regSet.takeGeneral();
Register argResultReg = regSet.takeGeneral();
Register scratch = regSet.takeGeneral();
@@ -2156,8 +2219,11 @@ EmitCallProxySet(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& at
masm.Push(object);
masm.movePtr(StackPointer, argProxyReg);
// Allocate result out-param.
PushObjectOpResult(masm);
masm.movePtr(StackPointer, argResultReg);
masm.loadJSContext(argJSContextReg);
masm.move32(Imm32(strict? 1 : 0), argStrictReg);
if (!masm.icBuildOOLFakeExitFrame(returnAddr, aic))
return false;
@@ -2169,13 +2235,19 @@ EmitCallProxySet(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& at
masm.passABIArg(argProxyReg);
masm.passABIArg(argProxyReg);
masm.passABIArg(argIdReg);
masm.passABIArg(argStrictReg);
masm.passABIArg(argVpReg);
masm.passABIArg(argResultReg);
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, Proxy::set));
// Test for failure.
// Test for error.
masm.branchIfFalseBool(ReturnReg, masm.exceptionLabel());
// Test for strict failure. We emit the check even in non-strict mode in
// order to pick up the warning if extraWarnings is enabled.
EmitObjectOpResultCheck<IonOOLProxyExitFrameLayout>(masm, masm.exceptionLabel(), strict,
scratch, argJSContextReg, argProxyReg,
argIdReg, argVpReg, argResultReg);
// masm.leaveExitFrame & pop locals
masm.adjustStack(IonOOLProxyExitFrameLayout::Size());
@@ -2386,24 +2458,28 @@ GenerateCallSetter(JSContext* cx, IonScript* ion, MacroAssembler& masm,
Register argVpReg = regSet.takeGeneral();
Register argObjReg = regSet.takeGeneral();
Register argIdReg = regSet.takeGeneral();
Register argStrictReg = regSet.takeGeneral();
attacher.pushStubCodePointer(masm);
Register argResultReg = regSet.takeGeneral();
StrictPropertyOp target = shape->setterOp();
MOZ_ASSERT(target);
// JSStrictPropertyOp: bool fn(JSContext* cx, HandleObject obj,
// HandleId id, bool strict, MutableHandleValue vp);
// HandleId id, MutableHandleValue vp, ObjectOpResult &result);
// Push args on stack first so we can take pointers to make handles.
// First, allocate an ObjectOpResult on the stack. We push this before
// the stubCode pointer in order to match the layout of
// IonOOLSetterOpExitFrameLayout.
PushObjectOpResult(masm);
masm.movePtr(StackPointer, argResultReg);
attacher.pushStubCodePointer(masm);
// Push args on stack so we can take pointers to make handles.
if (value.constant())
masm.Push(value.value());
else
masm.Push(value.reg());
masm.movePtr(StackPointer, argVpReg);
masm.move32(Imm32(strict ? 1 : 0), argStrictReg);
// push canonical jsid from shape instead of propertyname.
masm.Push(shape->propid(), argIdReg);
masm.movePtr(StackPointer, argIdReg);
@@ -2415,22 +2491,27 @@ GenerateCallSetter(JSContext* cx, IonScript* ion, MacroAssembler& masm,
if (!masm.icBuildOOLFakeExitFrame(returnAddr, aic))
return false;
masm.enterFakeExitFrame(IonOOLPropertyOpExitFrameLayout::Token());
masm.enterFakeExitFrame(IonOOLSetterOpExitFrameLayout::Token());
// Make the call.
masm.setupUnalignedABICall(5, scratchReg);
masm.passABIArg(argJSContextReg);
masm.passABIArg(argObjReg);
masm.passABIArg(argIdReg);
masm.passABIArg(argStrictReg);
masm.passABIArg(argVpReg);
masm.passABIArg(argResultReg);
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, target));
// Test for failure.
// Test for error.
masm.branchIfFalseBool(ReturnReg, masm.exceptionLabel());
// Test for failure.
EmitObjectOpResultCheck<IonOOLSetterOpExitFrameLayout>(masm, failure, strict, scratchReg,
argJSContextReg, argObjReg,
argIdReg, argVpReg, argResultReg);
// masm.leaveExitFrame & pop locals.
masm.adjustStack(IonOOLPropertyOpExitFrameLayout::Size());
masm.adjustStack(IonOOLSetterOpExitFrameLayout::Size());
} else {
MOZ_ASSERT(IsCacheableSetPropCallScripted(obj, holder, shape));
+12 -4
View File
@@ -1316,7 +1316,7 @@ MarkJitExitFrame(JSTracer* trc, const JitFrameIterator& frame)
}
if (frame.isExitFrameLayout<IonOOLNativeExitFrameLayout>()) {
IonOOLNativeExitFrameLayout* oolnative =
IonOOLNativeExitFrameLayout *oolnative =
frame.exitFrame()->as<IonOOLNativeExitFrameLayout>();
gc::MarkJitCodeRoot(trc, oolnative->stubCode(), "ion-ool-native-code");
gc::MarkValueRoot(trc, oolnative->vp(), "iol-ool-native-vp");
@@ -1325,9 +1325,16 @@ MarkJitExitFrame(JSTracer* trc, const JitFrameIterator& frame)
return;
}
if (frame.isExitFrameLayout<IonOOLPropertyOpExitFrameLayout>()) {
IonOOLPropertyOpExitFrameLayout* oolgetter =
frame.exitFrame()->as<IonOOLPropertyOpExitFrameLayout>();
if (frame.isExitFrameLayout<IonOOLPropertyOpExitFrameLayout>() ||
frame.isExitFrameLayout<IonOOLSetterOpExitFrameLayout>())
{
// A SetterOp frame is a different size, but that's the only relevant
// difference between the two. The fields that need marking are all in
// the common base class.
IonOOLPropertyOpExitFrameLayout *oolgetter =
frame.isExitFrameLayout<IonOOLPropertyOpExitFrameLayout>()
? frame.exitFrame()->as<IonOOLPropertyOpExitFrameLayout>()
: frame.exitFrame()->as<IonOOLSetterOpExitFrameLayout>();
gc::MarkJitCodeRoot(trc, oolgetter->stubCode(), "ion-ool-property-op-code");
gc::MarkValueRoot(trc, oolgetter->vp(), "ion-ool-property-op-vp");
gc::MarkIdRoot(trc, oolgetter->id(), "ion-ool-property-op-id");
@@ -1335,6 +1342,7 @@ MarkJitExitFrame(JSTracer* trc, const JitFrameIterator& frame)
return;
}
if (frame.isExitFrameLayout<IonOOLProxyExitFrameLayout>()) {
IonOOLProxyExitFrameLayout* oolproxy = frame.exitFrame()->as<IonOOLProxyExitFrameLayout>();
gc::MarkJitCodeRoot(trc, oolproxy->stubCode(), "ion-ool-proxy-code");
+36 -3
View File
@@ -494,7 +494,8 @@ enum ExitFrameTokenValues
IonDOMMethodExitFrameLayoutToken = 0x3,
IonOOLNativeExitFrameLayoutToken = 0x4,
IonOOLPropertyOpExitFrameLayoutToken = 0x5,
IonOOLProxyExitFrameLayoutToken = 0x6,
IonOOLSetterOpExitFrameLayoutToken = 0x6,
IonOOLProxyExitFrameLayoutToken = 0x7,
LazyLinkExitFrameLayoutToken = 0xFE,
ExitFrameLayoutBareToken = 0xFF
};
@@ -628,7 +629,7 @@ class IonOOLNativeExitFrameLayout
class IonOOLPropertyOpExitFrameLayout
{
protected: // only to silence a clang warning about unused private fields
protected:
ExitFooterFrame footer_;
ExitFrameLayout exit_;
@@ -653,6 +654,10 @@ class IonOOLPropertyOpExitFrameLayout
return sizeof(IonOOLPropertyOpExitFrameLayout);
}
static size_t offsetOfId() {
return offsetof(IonOOLPropertyOpExitFrameLayout, id_);
}
static size_t offsetOfResult() {
return offsetof(IonOOLPropertyOpExitFrameLayout, vp0_);
}
@@ -671,16 +676,36 @@ class IonOOLPropertyOpExitFrameLayout
}
};
class IonOOLSetterOpExitFrameLayout : public IonOOLPropertyOpExitFrameLayout
{
protected: // only to silence a clang warning about unused private fields
JS::ObjectOpResult result_;
public:
static JitCode *Token() { return (JitCode *)IonOOLSetterOpExitFrameLayoutToken; }
static size_t offsetOfObjectOpResult() {
return offsetof(IonOOLSetterOpExitFrameLayout, result_);
}
static size_t Size() {
return sizeof(IonOOLSetterOpExitFrameLayout);
}
};
// Proxy::get(JSContext* cx, HandleObject proxy, HandleObject receiver, HandleId id,
// MutableHandleValue vp)
// Proxy::set(JSContext* cx, HandleObject proxy, HandleObject receiver, HandleId id,
// bool strict, MutableHandleValue vp)
// MutableHandleValue vp, ObjectOpResult &result)
class IonOOLProxyExitFrameLayout
{
protected: // only to silence a clang warning about unused private fields
ExitFooterFrame footer_;
ExitFrameLayout exit_;
// result out-parameter (unused for Proxy::get)
JS::ObjectOpResult result_;
// The proxy object.
JSObject* proxy_;
@@ -709,6 +734,14 @@ class IonOOLProxyExitFrameLayout
return offsetof(IonOOLProxyExitFrameLayout, vp0_);
}
static size_t offsetOfId() {
return offsetof(IonOOLProxyExitFrameLayout, id_);
}
static size_t offsetOfObjectOpResult() {
return offsetof(IonOOLProxyExitFrameLayout, result_);
}
inline JitCode** stubCode() {
return &stubCode_;
}
+16 -10
View File
@@ -448,18 +448,24 @@ SetProperty(JSContext* cx, HandleObject obj, HandlePropertyName name, HandleValu
return true;
}
ObjectOpResult result;
if (MOZ_LIKELY(!obj->getOps()->setProperty)) {
return NativeSetProperty(
cx, obj.as<NativeObject>(), obj.as<NativeObject>(), id,
(op == JSOP_SETNAME || op == JSOP_STRICTSETNAME ||
op == JSOP_SETGNAME || op == JSOP_STRICTSETGNAME)
? Unqualified
: Qualified,
&v,
strict);
if (!NativeSetProperty(
cx, obj.as<NativeObject>(), obj.as<NativeObject>(), id,
(op == JSOP_SETNAME || op == JSOP_STRICTSETNAME ||
op == JSOP_SETGNAME || op == JSOP_STRICTSETGNAME)
? Unqualified
: Qualified,
&v,
result))
{
return false;
}
} else {
if (!SetProperty(cx, obj, obj, id, &v, result))
return false;
}
return SetProperty(cx, obj, obj, id, &v, strict);
return result.checkStrictErrorOrWarning(cx, obj, id, strict);
}
bool
+5 -1
View File
@@ -50,6 +50,7 @@ MSG_DEF(JSMSG_BAD_SORT_ARG, 0, JSEXN_TYPEERR, "invalid Array.prototyp
MSG_DEF(JSMSG_CANT_WATCH, 1, JSEXN_TYPEERR, "can't watch non-native objects of class {0}")
MSG_DEF(JSMSG_READ_ONLY, 1, JSEXN_TYPEERR, "{0} is read-only")
MSG_DEF(JSMSG_CANT_DELETE, 1, JSEXN_TYPEERR, "property {0} is non-configurable and can't be deleted")
MSG_DEF(JSMSG_CANT_TRUNCATE_ARRAY, 0, JSEXN_TYPEERR, "can't delete non-configurable array element")
MSG_DEF(JSMSG_NOT_FUNCTION, 1, JSEXN_TYPEERR, "{0} is not a function")
MSG_DEF(JSMSG_NOT_CONSTRUCTOR, 1, JSEXN_TYPEERR, "{0} is not a constructor")
MSG_DEF(JSMSG_CANT_CONVERT, 1, JSEXN_ERR, "can't convert {0} to an integer")
@@ -83,7 +84,7 @@ MSG_DEF(JSMSG_MISSING_FUN_ARG, 2, JSEXN_TYPEERR, "missing argument {0} w
MSG_DEF(JSMSG_NOT_NONNULL_OBJECT, 1, JSEXN_TYPEERR, "{0} is not a non-null object")
MSG_DEF(JSMSG_INVALID_DESCRIPTOR, 0, JSEXN_TYPEERR, "property descriptors must not specify a value or be writable when a getter or setter has been specified")
MSG_DEF(JSMSG_OBJECT_NOT_EXTENSIBLE, 1, JSEXN_TYPEERR, "{0} is not extensible")
MSG_DEF(JSMSG_CANT_REDEFINE_PROP, 1, JSEXN_TYPEERR, "can't redefine non-configurable property '{0}'")
MSG_DEF(JSMSG_CANT_REDEFINE_PROP, 1, JSEXN_TYPEERR, "can't redefine non-configurable property {0}")
MSG_DEF(JSMSG_CANT_APPEND_TO_ARRAY, 0, JSEXN_TYPEERR, "can't add elements past the end of an array if its length property is unwritable")
MSG_DEF(JSMSG_CANT_REDEFINE_ARRAY_LENGTH, 0, JSEXN_TYPEERR, "can't redefine array length")
MSG_DEF(JSMSG_CANT_DEFINE_PAST_ARRAY_LENGTH, 0, JSEXN_TYPEERR, "can't define array index property past the end of an array with non-writable length")
@@ -464,3 +465,6 @@ MSG_DEF(JSMSG_SYMBOL_TO_NUMBER, 0, JSEXN_TYPEERR, "can't convert symbol t
MSG_DEF(JSMSG_ATOMICS_BAD_ARRAY, 0, JSEXN_TYPEERR, "invalid array type for the operation")
MSG_DEF(JSMSG_ATOMICS_TOO_LONG, 0, JSEXN_RANGEERR, "timeout value too large")
MSG_DEF(JSMSG_ATOMICS_WAIT_NOT_ALLOWED, 0, JSEXN_ERR, "waiting is not allowed on this thread")
// XPConnect wrappers
MSG_DEF(JSMSG_CANT_SET_INTERPOSED, 1, JSEXN_TYPEERR, "unable to set interposed data property '{0}'")
@@ -45,11 +45,14 @@ BEGIN_TEST(testForwardSetProperty)
// Non-strict setter
CHECK(JS_ForwardSetPropertyTo(cx, obj2, prop, v3, true, setval));
ObjectOpResult result;
CHECK(JS_ForwardSetPropertyTo(cx, obj2, prop, setval, v3, result));
CHECK(result);
EXEC("assertEq(foundValue, obj3, 'wrong receiver passed to setter');");
CHECK(JS_ForwardSetPropertyTo(cx, obj2, prop, setval, true, setval));
CHECK(JS_ForwardSetPropertyTo(cx, obj2, prop, setval, setval, result));
CHECK(result);
EXEC("assertEq(typeof foundValue === 'object', true, \n"
" 'passing 42 as receiver to non-strict setter ' + \n"
@@ -69,12 +72,13 @@ BEGIN_TEST(testForwardSetProperty)
"obj1;",
&v1);
CHECK(JS_ForwardSetPropertyTo(cx, obj2, prop, v3, true, setval));
CHECK(JS_ForwardSetPropertyTo(cx, obj2, prop, setval, v3, result));
CHECK(result);
EXEC("assertEq(foundValue, obj3, 'wrong receiver passed to strict setter');");
CHECK(JS_ForwardSetPropertyTo(cx, obj2, prop, setval, true, setval));
CHECK(JS_ForwardSetPropertyTo(cx, obj2, prop, setval, setval, result));
CHECK(result);
JS::RootedValue strictSetSupported(cx);
EVAL("var strictSetSupported = false; \n"
@@ -28,13 +28,13 @@ class CustomProxyHandler : public DirectProxyHandler {
}
bool set(JSContext* cx, HandleObject proxy, HandleObject receiver,
HandleId id, bool strict, MutableHandleValue vp) const override
HandleId id, MutableHandleValue vp, ObjectOpResult &result) const MOZ_OVERRIDE
{
Rooted<JSPropertyDescriptor> desc(cx);
if (!DirectProxyHandler::getPropertyDescriptor(cx, proxy, id, &desc))
return false;
return SetPropertyIgnoringNamedGetter(cx, this, proxy, receiver, id, &desc,
desc.object() == proxy, strict, vp);
desc.object() == proxy, vp, result);
}
private:
+129 -11
View File
@@ -129,6 +129,70 @@ JS::CallArgs::requireAtLeast(JSContext* cx, const char* fnname, unsigned require
return true;
}
static bool
ErrorTakesIdArgument(unsigned msg)
{
MOZ_ASSERT(msg < JSErr_Limit);
unsigned argCount = js_ErrorFormatString[msg].argCount;
MOZ_ASSERT(argCount <= 1);
return argCount == 1;
}
JS_PUBLIC_API(bool)
JS::ObjectOpResult::reportStrictErrorOrWarning(JSContext *cx, HandleObject obj, HandleId id,
bool strict)
{
static_assert(unsigned(OkCode) == unsigned(JSMSG_NOT_AN_ERROR),
"unsigned value of OkCode must not be an error code");
MOZ_ASSERT(code_ != Uninitialized);
MOZ_ASSERT(!ok());
unsigned flags = strict ? JSREPORT_ERROR : (JSREPORT_WARNING | JSREPORT_STRICT);
if (code_ == JSMSG_OBJECT_NOT_EXTENSIBLE) {
RootedValue val(cx, ObjectValue(*obj));
return ReportValueErrorFlags(cx, flags, code_, JSDVG_IGNORE_STACK, val,
NullPtr(), nullptr, nullptr);
}
if (ErrorTakesIdArgument(code_)) {
RootedValue idv(cx, IdToValue(id));
RootedString str(cx, ValueToSource(cx, idv));
if (!str)
return false;
JSAutoByteString propName(cx, str);
if (!propName)
return false;
return JS_ReportErrorFlagsAndNumber(cx, flags, GetErrorMessage, nullptr, code_,
propName.ptr());
}
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(bool)
JS::ObjectOpResult::failCantSetInterposed()
{
return fail(JSMSG_CANT_SET_INTERPOSED);
}
JS_PUBLIC_API(int64_t)
JS_Now()
{
@@ -1787,9 +1851,10 @@ JS_PropertyStub(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue
}
JS_PUBLIC_API(bool)
JS_StrictPropertyStub(JSContext* cx, HandleObject obj, HandleId id, bool strict, MutableHandleValue vp)
JS_StrictPropertyStub(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp,
ObjectOpResult &result)
{
return true;
return result.succeed();
}
JS_PUBLIC_API(JSObject*)
@@ -2386,6 +2451,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)
@@ -2642,6 +2734,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)
@@ -2884,25 +3001,25 @@ JS_SetPropertyById(JSContext* cx, HandleObject obj, HandleId id, HandleValue v)
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, id);
return SetProperty(cx, obj, obj, id, &value, false);
ObjectOpResult ignored;
return SetProperty(cx, obj, obj, id, &value, ignored);
}
JS_PUBLIC_API(bool)
JS_ForwardSetPropertyTo(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue onBehalfOf,
bool strict, JS::HandleValue v)
JS_ForwardSetPropertyTo(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult &result)
{
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, id);
assertSameCompartment(cx, onBehalfOf);
assertSameCompartment(cx, obj, id, receiver);
// XXX Bug 603201 will eliminate this ToObject.
RootedObject receiver(cx, ToObject(cx, onBehalfOf));
if (!receiver)
RootedObject receiverObj(cx, ToObject(cx, receiver));
if (!receiverObj)
return false;
RootedValue value(cx, v);
return SetProperty(cx, obj, receiver, id, &value, strict);
return SetProperty(cx, obj, receiverObj, id, &value, result);
}
static bool
@@ -2912,7 +3029,8 @@ SetElement(JSContext* cx, HandleObject obj, uint32_t index, MutableHandleValue v
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, vp);
return SetElement(cx, obj, obj, index, vp, false);
ObjectOpResult ignored;
return SetElement(cx, obj, obj, index, vp, ignored);
}
JS_PUBLIC_API(bool)
+116 -90
View File
@@ -2036,8 +2036,8 @@ JS_PropertyStub(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
JS::MutableHandleValue vp);
extern JS_PUBLIC_API(bool)
JS_StrictPropertyStub(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool strict,
JS::MutableHandleValue vp);
JS_StrictPropertyStub(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
JS::MutableHandleValue vp, JS::ObjectOpResult &result);
template<typename T>
struct JSConstScalarSpec {
@@ -2555,92 +2555,7 @@ 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;
@@ -2829,6 +2744,108 @@ 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,8 +2884,8 @@ extern JS_PUBLIC_API(bool)
JS_SetPropertyById(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue v);
extern JS_PUBLIC_API(bool)
JS_ForwardSetPropertyTo(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue onBehalfOf,
bool strict, JS::HandleValue vp);
JS_ForwardSetPropertyTo(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue v,
JS::HandleValue receiver, JS::ObjectOpResult &result);
extern JS_PUBLIC_API(bool)
JS_DeleteProperty(JSContext* cx, JS::HandleObject obj, const char* name);
@@ -2912,6 +2929,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);
+22 -62
View File
@@ -363,7 +363,7 @@ SetArrayElement(JSContext* cx, HandleObject obj, double index, HandleValue v)
return false;
RootedValue tmp(cx, v);
return SetProperty(cx, obj, obj, id, &tmp, true);
return SetProperty(cx, obj, obj, id, &tmp);
}
/*
@@ -433,7 +433,7 @@ bool
js::SetLengthProperty(JSContext* cx, HandleObject obj, double length)
{
RootedValue v(cx, NumberValue(length));
return SetProperty(cx, obj, obj, cx->names().length, &v, true);
return SetProperty(cx, obj, obj, cx->names().length, &v);
}
/*
@@ -459,7 +459,8 @@ array_length_getter(JSContext* cx, HandleObject obj_, HandleId id, MutableHandle
}
static bool
array_length_setter(JSContext* cx, HandleObject obj, HandleId id, bool strict, MutableHandleValue vp)
array_length_setter(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp,
ObjectOpResult &result)
{
if (!obj->is<ArrayObject>()) {
// This array .length property was found on the prototype
@@ -467,13 +468,14 @@ array_length_setter(JSContext* cx, HandleObject obj, HandleId id, bool strict, M
// we're here, do an impression of SetPropertyByDefining.
const Class* clasp = obj->getClass();
return DefineProperty(cx, obj, cx->names().length, vp,
clasp->getProperty, clasp->setProperty, JSPROP_ENUMERATE);
clasp->getProperty, clasp->setProperty, JSPROP_ENUMERATE, result);
}
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
MOZ_ASSERT(arr->lengthIsWritable(),
"setter shouldn't be called if property is non-writable");
return ArraySetLength(cx, arr, id, JSPROP_PERMANENT, vp, strict);
return ArraySetLength(cx, arr, id, JSPROP_PERMANENT, vp, result);
}
struct ReverseIndexComparator
@@ -506,7 +508,7 @@ js::CanonicalizeArrayLengthValue(JSContext* cx, HandleValue v, uint32_t* newLen)
/* ES6 20130308 draft 8.4.2.4 ArraySetLength */
bool
js::ArraySetLength(JSContext* cx, Handle<ArrayObject*> arr, HandleId id,
unsigned attrs, HandleValue value, bool setterIsStrict)
unsigned attrs, HandleValue value, ObjectOpResult &result)
{
MOZ_ASSERT(id == NameToId(cx->names().length));
@@ -529,11 +531,8 @@ js::ArraySetLength(JSContext* cx, Handle<ArrayObject*> arr, HandleId id,
// OrdinaryDefineOwnProperty in ES6, the default [[DefineOwnProperty]] in
// ES5 -- but we reimplement all the conflict-detection bits ourselves here
// so that we can use a customized length representation.)
if (!(attrs & JSPROP_PERMANENT) || (attrs & JSPROP_ENUMERATE)) {
if (!setterIsStrict)
return true;
return Throw(cx, id, JSMSG_CANT_REDEFINE_PROP);
}
if (!(attrs & JSPROP_PERMANENT) || (attrs & JSPROP_ENUMERATE))
return result.fail(JSMSG_CANT_REDEFINE_PROP);
/* Steps 6-7. */
bool lengthIsWritable = arr->lengthIsWritable();
@@ -550,14 +549,9 @@ js::ArraySetLength(JSContext* cx, Handle<ArrayObject*> arr, HandleId id,
/* Steps 8-9 for arrays with non-writable length. */
if (!lengthIsWritable) {
if (newLen == oldLen)
return true;
return result.succeed();
if (setterIsStrict) {
return JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, GetErrorMessage, nullptr,
JSMSG_CANT_REDEFINE_ARRAY_LENGTH);
}
return JSObject::reportReadOnly(cx, id, JSREPORT_STRICT | JSREPORT_WARNING);
return result.fail(JSMSG_CANT_REDEFINE_ARRAY_LENGTH);
}
/* Step 8. */
@@ -738,53 +732,20 @@ js::ArraySetLength(JSContext* cx, Handle<ArrayObject*> arr, HandleId id,
}
}
if (setterIsStrict && !succeeded) {
RootedId elementId(cx);
if (!IndexToId(cx, newLen - 1, &elementId))
return false;
return arr->reportNotConfigurable(cx, elementId);
}
if (!succeeded)
return result.fail(JSMSG_CANT_TRUNCATE_ARRAY);
return true;
return result.succeed();
}
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
@@ -1308,7 +1269,7 @@ InitArrayElements(JSContext* cx, HandleObject obj, uint32_t start, uint32_t coun
value = *vector++;
indexv = DoubleValue(index);
if (!ValueToId<CanGC>(cx, indexv, &id) ||
!SetProperty(cx, obj, obj, id, &value, true))
!SetProperty(cx, obj, obj, id, &value))
{
return false;
}
@@ -3112,8 +3073,7 @@ array_of(JSContext* cx, unsigned argc, Value* vp)
}
// Steps 9-10.
RootedValue v(cx, NumberValue(args.length()));
if (!SetProperty(cx, obj, obj, cx->names().length, &v, true))
if (!SetLengthProperty(cx, obj, args.length()))
return false;
// Step 11.
+1 -3
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
+18 -7
View File
@@ -132,6 +132,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());
}
};
/*
@@ -307,12 +316,12 @@ CallJSPropertyOp(JSContext* cx, PropertyOp op, HandleObject receiver, HandleId i
MOZ_ALWAYS_INLINE bool
CallJSPropertyOpSetter(JSContext* cx, StrictPropertyOp op, HandleObject obj, HandleId id,
bool strict, MutableHandleValue vp)
MutableHandleValue vp, ObjectOpResult &result)
{
JS_CHECK_RECURSION(cx, return false);
assertSameCompartment(cx, obj, id, vp);
return op(cx, obj, id, strict, vp);
return op(cx, obj, id, vp, result);
}
static inline bool
@@ -330,20 +339,22 @@ CallJSDeletePropertyOp(JSContext* cx, JSDeletePropertyOp op, HandleObject receiv
inline bool
CallSetter(JSContext* cx, HandleObject obj, HandleId id, StrictPropertyOp op, unsigned attrs,
bool strict, MutableHandleValue vp)
MutableHandleValue vp, ObjectOpResult &result)
{
if (attrs & JSPROP_SETTER) {
RootedValue opv(cx, CastAsObjectJsval(op));
return InvokeGetterOrSetter(cx, obj, opv, 1, vp.address(), vp);
if (!InvokeGetterOrSetter(cx, obj, opv, 1, vp.address(), vp))
return false;
return result.succeed();
}
if (attrs & JSPROP_GETTER)
return ReportGetterOnlyAssignment(cx, strict);
return result.fail(JSMSG_GETTER_ONLY);
if (!op)
return true;
return result.succeed();
return CallJSPropertyOpSetter(cx, op, obj, id, strict, vp);
return CallJSPropertyOpSetter(cx, op, obj, id, vp, result);
}
inline uintptr_t
+2 -2
View File
@@ -1169,7 +1169,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);
@@ -1181,7 +1181,7 @@ js::DefineOwnProperty(JSContext* cx, JSObject* objArg, jsid idArg,
if (descriptor.hasSetterObject())
assertSameCompartment(cx, descriptor.setterObject());
return StandardDefineProperty(cx, obj, id, descriptor, bp);
return StandardDefineProperty(cx, obj, id, descriptor, result);
}
JS_FRIEND_API(bool)
+6 -4
View File
@@ -311,7 +311,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,
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
JSPropertyOp getter, JSStrictPropertyOp 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)
@@ -319,7 +320,7 @@ proxy_GetProperty(JSContext* cx, JS::HandleObject obj, JS::HandleObject receiver
JS::MutableHandleValue vp);
extern JS_FRIEND_API(bool)
proxy_SetProperty(JSContext* cx, JS::HandleObject obj, JS::HandleObject receiver, JS::HandleId id,
JS::MutableHandleValue bp, bool strict);
JS::MutableHandleValue bp, JS::ObjectOpResult &result);
extern JS_FRIEND_API(bool)
proxy_GetOwnPropertyDescriptor(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
JS::MutableHandle<JSPropertyDescriptor> desc);
@@ -2550,7 +2551,8 @@ JS_FRIEND_API(bool)
SetPropertyIgnoringNamedGetter(JSContext* cx, const BaseProxyHandler* handler,
JS::HandleObject proxy, JS::HandleObject receiver,
JS::HandleId id, JS::MutableHandle<JSPropertyDescriptor> desc,
bool descIsOwn, bool strict, JS::MutableHandleValue vp);
bool descIsOwn, JS::MutableHandleValue vp,
JS::ObjectOpResult &result);
JS_FRIEND_API(void)
ReportErrorWithId(JSContext* cx, const char* msg, JS::HandleId id);
@@ -2621,7 +2623,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 */
+132 -99
View File
@@ -445,41 +445,12 @@ js::Throw(JSContext* cx, JSObject* obj, unsigned errorNumber)
return false;
}
static bool
Reject(JSContext* cx, unsigned errorNumber, bool throwError, jsid id, bool* rval)
{
if (throwError)
return Throw(cx, id, errorNumber);
*rval = false;
return true;
}
static bool
Reject(JSContext* cx, JSObject* obj, unsigned errorNumber, bool throwError, bool* rval)
{
if (throwError)
return Throw(cx, obj, errorNumber);
*rval = false;
return true;
}
static bool
Reject(JSContext* cx, HandleId id, unsigned errorNumber, bool throwError, bool* rval)
{
if (throwError)
return Throw(cx, id, errorNumber);
*rval = false;
return true;
}
/*** Standard-compliant property definition (used by Object.defineProperty) **********************/
static bool
DefinePropertyOnObject(JSContext* cx, HandleNativeObject obj, HandleId id, const PropDesc& desc,
bool throwError, bool* rval)
ObjectOpResult &result)
{
/* 8.12.9 step 1. */
RootedShape shape(cx);
@@ -495,20 +466,19 @@ DefinePropertyOnObject(JSContext* cx, HandleNativeObject obj, HandleId id, const
if (!IsExtensible(cx, obj, &extensible))
return false;
if (!extensible)
return Reject(cx, obj, JSMSG_OBJECT_NOT_EXTENSIBLE, throwError, rval);
*rval = true;
return result.fail(JSMSG_OBJECT_NOT_EXTENSIBLE);
if (desc.isGenericDescriptor() || desc.isDataDescriptor()) {
MOZ_ASSERT(!obj->getOps()->defineProperty);
RootedValue v(cx, desc.hasValue() ? desc.value() : UndefinedValue());
return NativeDefineProperty(cx, obj, id, v, nullptr, nullptr, desc.attributes());
return NativeDefineProperty(cx, obj, id, v, nullptr, nullptr, desc.attributes(),
result);
}
MOZ_ASSERT(desc.isAccessorDescriptor());
return NativeDefineProperty(cx, obj, id, UndefinedHandleValue,
desc.getter(), desc.setter(), desc.attributes());
desc.getter(), desc.setter(), desc.attributes(), result);
}
/* 8.12.9 steps 5-6 (note 5 is merely a special case of 6). */
@@ -585,7 +555,7 @@ DefinePropertyOnObject(JSContext* cx, HandleNativeObject obj, HandleId id, const
desc.isDataDescriptor() &&
(desc.hasWritable() ? desc.writable() : shape->writable()))
{
return Reject(cx, JSMSG_CANT_REDEFINE_PROP, throwError, id, rval);
return result.fail(JSMSG_CANT_REDEFINE_PROP);
}
if (!NativeGetExistingProperty(cx, obj, obj, shape, &v))
@@ -611,16 +581,16 @@ DefinePropertyOnObject(JSContext* cx, HandleNativeObject obj, HandleId id, const
* flag we veto from true to false for non-configurable
* PropertyOp-based data properties and test before the
* SameValue check later on in order to re-use that "if
* (!SameValue) Reject" logic.
* (!SameValue) return false" logic.
*
* This function is large and complex enough that it
* seems best to repeat a small bit of code and return
* Reject(...) ASAP, instead of being clever.
* result.fail() ASAP, instead of being clever.
*/
if (!shapeConfigurable &&
(!shape->hasDefaultGetter() || !shape->hasDefaultSetter()))
{
return Reject(cx, JSMSG_CANT_REDEFINE_PROP, throwError, id, rval);
return result.fail(JSMSG_CANT_REDEFINE_PROP);
}
break;
}
@@ -639,15 +609,14 @@ DefinePropertyOnObject(JSContext* cx, HandleNativeObject obj, HandleId id, const
break;
/* The conditions imposed by step 5 or step 6 apply. */
*rval = true;
return true;
return result.succeed();
} while (0);
/* 8.12.9 step 7. */
if (!shapeConfigurable) {
if ((desc.hasConfigurable() && desc.configurable()) ||
(desc.hasEnumerable() && desc.enumerable() != shape->enumerable())) {
return Reject(cx, JSMSG_CANT_REDEFINE_PROP, throwError, id, rval);
return result.fail(JSMSG_CANT_REDEFINE_PROP);
}
}
@@ -658,19 +627,19 @@ DefinePropertyOnObject(JSContext* cx, HandleNativeObject obj, HandleId id, const
} else if (desc.isDataDescriptor() != shapeDataDescriptor) {
/* 8.12.9 step 9. */
if (!shapeConfigurable)
return Reject(cx, JSMSG_CANT_REDEFINE_PROP, throwError, id, rval);
return result.fail(JSMSG_CANT_REDEFINE_PROP);
} else if (desc.isDataDescriptor()) {
/* 8.12.9 step 10. */
MOZ_ASSERT(shapeDataDescriptor);
if (!shapeConfigurable && !shape->writable()) {
if (desc.hasWritable() && desc.writable())
return Reject(cx, JSMSG_CANT_REDEFINE_PROP, throwError, id, rval);
return result.fail(JSMSG_CANT_REDEFINE_PROP);
if (desc.hasValue()) {
bool same;
if (!SameValue(cx, desc.value(), v, &same))
return false;
if (!same)
return Reject(cx, JSMSG_CANT_REDEFINE_PROP, throwError, id, rval);
return result.fail(JSMSG_CANT_REDEFINE_PROP);
}
}
@@ -685,7 +654,7 @@ DefinePropertyOnObject(JSContext* cx, HandleNativeObject obj, HandleId id, const
if (!SameValue(cx, desc.setterValue(), setter, &same))
return false;
if (!same)
return Reject(cx, JSMSG_CANT_REDEFINE_PROP, throwError, id, rval);
return result.fail(JSMSG_CANT_REDEFINE_PROP);
}
if (desc.hasGet()) {
@@ -694,7 +663,7 @@ DefinePropertyOnObject(JSContext* cx, HandleNativeObject obj, HandleId id, const
if (!SameValue(cx, desc.getterValue(), getter, &same))
return false;
if (!same)
return Reject(cx, JSMSG_CANT_REDEFINE_PROP, throwError, id, rval);
return result.fail(JSMSG_CANT_REDEFINE_PROP);
}
}
}
@@ -759,8 +728,6 @@ DefinePropertyOnObject(JSContext* cx, HandleNativeObject obj, HandleId id, const
}
}
*rval = true;
/*
* Since "data" properties implemented using native C functions may rely on
* side effects during setting, we must make them aware that they have been
@@ -771,18 +738,18 @@ DefinePropertyOnObject(JSContext* cx, HandleNativeObject obj, HandleId id, const
* redefining it or we had invoked its setter to change its value).
*/
if (callDelProperty) {
bool succeeded;
if (!CallJSDeletePropertyOp(cx, obj->getClass()->delProperty, obj, id, &succeeded))
bool ignored;
if (!CallJSDeletePropertyOp(cx, obj->getClass()->delProperty, obj, id, &ignored))
return false;
}
return NativeDefineProperty(cx, obj, id, v, getter, setter, attrs);
return NativeDefineProperty(cx, obj, id, v, getter, setter, attrs, result);
}
/* ES6 20130308 draft 8.4.2.1 [[DefineOwnProperty]] */
static bool
DefinePropertyOnArray(JSContext* cx, Handle<ArrayObject*> arr, HandleId id, const PropDesc& desc,
bool throwError, bool* rval)
ObjectOpResult &result)
{
/* Step 2. */
if (id == NameToId(cx->names().length)) {
@@ -804,23 +771,23 @@ DefinePropertyOnArray(JSContext* cx, Handle<ArrayObject*> arr, HandleId id, cons
}
if (desc.hasConfigurable() && desc.configurable())
return Reject(cx, id, JSMSG_CANT_REDEFINE_PROP, throwError, rval);
return result.fail(JSMSG_CANT_REDEFINE_PROP);
if (desc.hasEnumerable() && desc.enumerable())
return Reject(cx, id, JSMSG_CANT_REDEFINE_PROP, throwError, rval);
return result.fail(JSMSG_CANT_REDEFINE_PROP);
if (desc.isAccessorDescriptor())
return Reject(cx, id, JSMSG_CANT_REDEFINE_PROP, throwError, rval);
return result.fail(JSMSG_CANT_REDEFINE_PROP);
unsigned attrs = arr->lookup(cx, id)->attributes();
if (!arr->lengthIsWritable()) {
if (desc.hasWritable() && desc.writable())
return Reject(cx, id, JSMSG_CANT_REDEFINE_PROP, throwError, rval);
return result.fail(JSMSG_CANT_REDEFINE_PROP);
} else {
if (desc.hasWritable() && !desc.writable())
attrs = attrs | JSPROP_READONLY;
}
return ArraySetLength(cx, arr, id, attrs, v, throwError);
return ArraySetLength(cx, arr, id, attrs, v, result);
}
/* Step 3. */
@@ -831,22 +798,21 @@ DefinePropertyOnArray(JSContext* cx, Handle<ArrayObject*> arr, HandleId id, cons
/* Steps 3a, 3e. */
if (index >= oldLen && !arr->lengthIsWritable())
return Reject(cx, arr, JSMSG_CANT_APPEND_TO_ARRAY, throwError, rval);
return result.fail(JSMSG_CANT_APPEND_TO_ARRAY);
/* Steps 3f-j. */
return DefinePropertyOnObject(cx, arr, id, desc, throwError, rval);
return DefinePropertyOnObject(cx, arr, id, desc, result);
}
/* Step 4. */
return DefinePropertyOnObject(cx, arr, id, desc, throwError, rval);
return DefinePropertyOnObject(cx, arr, id, desc, result);
}
// ES6 draft rev31 9.4.5.3 [[DefineOwnProperty]]
static bool
DefinePropertyOnTypedArray(JSContext* cx, HandleObject obj, HandleId id, const PropDesc& desc,
bool throwError, bool* rval)
ObjectOpResult &result)
{
MOZ_ASSERT(IsAnyTypedArray(obj));
// Steps 3.a-c.
uint64_t index;
@@ -854,26 +820,24 @@ DefinePropertyOnTypedArray(JSContext* cx, HandleObject obj, HandleId id, const P
// These are all substeps of 3.c.
// Steps i-vi.
// We (wrongly) ignore out of range defines with a value.
if (index >= AnyTypedArrayLength(obj)) {
*rval = true;
return true;
}
if (index >= AnyTypedArrayLength(obj))
return result.succeed();
// Step vii.
if (desc.isAccessorDescriptor())
return Reject(cx, id, JSMSG_CANT_REDEFINE_PROP, throwError, rval);
return result.fail(JSMSG_CANT_REDEFINE_PROP);
// Step viii.
if (desc.hasConfigurable() && desc.configurable())
return Reject(cx, id, JSMSG_CANT_REDEFINE_PROP, throwError, rval);
return result.fail(JSMSG_CANT_REDEFINE_PROP);
// Step ix.
if (desc.hasEnumerable() && !desc.enumerable())
return Reject(cx, id, JSMSG_CANT_REDEFINE_PROP, throwError, rval);
return result.fail(JSMSG_CANT_REDEFINE_PROP);
// Step x.
if (desc.hasWritable() && !desc.writable())
return Reject(cx, id, JSMSG_CANT_REDEFINE_PROP, throwError, rval);
return result.fail(JSMSG_CANT_REDEFINE_PROP);
// Step xi.
if (desc.hasValue()) {
@@ -888,25 +852,24 @@ DefinePropertyOnTypedArray(JSContext* cx, HandleObject obj, HandleId id, const P
}
// Step xii.
*rval = true;
return true;
return result.succeed();
}
// Step 4.
return DefinePropertyOnObject(cx, obj.as<NativeObject>(), id, desc, throwError, rval);
return DefinePropertyOnObject(cx, obj.as<NativeObject>(), id, desc, result);
}
bool
js::StandardDefineProperty(JSContext* cx, HandleObject obj, HandleId id, const PropDesc& desc,
bool throwError, bool* rval)
ObjectOpResult &result)
{
if (obj->is<ArrayObject>()) {
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
return DefinePropertyOnArray(cx, arr, id, desc, throwError, rval);
return DefinePropertyOnArray(cx, arr, id, desc, result);
}
if (IsAnyTypedArray(obj))
return DefinePropertyOnTypedArray(cx, obj, id, desc, throwError, rval);
return DefinePropertyOnTypedArray(cx, obj, id, desc, result);
if (obj->is<UnboxedPlainObject>() && !UnboxedPlainObject::convertToNative(cx, obj))
return false;
@@ -916,21 +879,38 @@ js::StandardDefineProperty(JSContext* cx, HandleObject obj, HandleId id, const P
Rooted<PropertyDescriptor> pd(cx);
desc.populatePropertyDescriptor(obj, &pd);
pd.object().set(obj);
return Proxy::defineProperty(cx, obj, id, &pd);
return Proxy::defineProperty(cx, obj, id, &pd, result);
}
return Reject(cx, obj, JSMSG_OBJECT_NOT_EXTENSIBLE, throwError, rval);
return result.fail(JSMSG_OBJECT_NOT_EXTENSIBLE);
}
return DefinePropertyOnObject(cx, obj.as<NativeObject>(), id, desc, throwError, rval);
return DefinePropertyOnObject(cx, obj.as<NativeObject>(), id, desc, result);
}
bool
js::StandardDefineProperty(JSContext* cx, HandleObject obj, HandleId id,
Handle<PropertyDescriptor> descriptor, bool* bp)
Handle<PropertyDescriptor> descriptor, ObjectOpResult &result)
{
Rooted<PropDesc> desc(cx);
desc.initFromPropertyDescriptor(descriptor);
return StandardDefineProperty(cx, obj, id, desc, true, bp);
return StandardDefineProperty(cx, obj, id, desc, result);
}
bool
js::StandardDefineProperty(JSContext *cx, HandleObject obj, HandleId id, const PropDesc &desc)
{
ObjectOpResult success;
return StandardDefineProperty(cx, obj, id, desc, success) &&
success.checkStrict(cx, obj, id);
}
bool
js::StandardDefineProperty(JSContext *cx, HandleObject obj, HandleId id,
Handle<PropertyDescriptor> desc)
{
ObjectOpResult success;
return StandardDefineProperty(cx, obj, id, desc, success) &&
success.checkStrict(cx, obj, id);
}
bool
@@ -963,9 +943,8 @@ js::DefineProperties(JSContext* cx, HandleObject obj, HandleObject props)
if (!ReadPropertyDescriptors(cx, props, true, &ids, &descs))
return false;
bool dummy;
for (size_t i = 0, len = ids.length(); i < len; i++) {
if (!StandardDefineProperty(cx, obj, ids[i], descs[i], true, &dummy))
if (!StandardDefineProperty(cx, obj, ids[i], descs[i]))
return false;
}
@@ -1083,8 +1062,7 @@ js::SetIntegrityLevel(JSContext* cx, HandleObject obj, IntegrityLevel level)
desc.object().set(obj);
// 8.a.i-ii. / 9.a.iii.3-4
bool result;
if (!StandardDefineProperty(cx, obj, id, desc, &result))
if (!StandardDefineProperty(cx, obj, id, desc))
return false;
}
}
@@ -1676,24 +1654,24 @@ js::CreateThisForFunction(JSContext* cx, HandleObject callee, NewObjectKind newK
/* static */ bool
JSObject::nonNativeSetProperty(JSContext* cx, HandleObject obj, HandleObject receiver,
HandleId id, MutableHandleValue vp, bool strict)
HandleId id, MutableHandleValue vp, ObjectOpResult &result)
{
if (MOZ_UNLIKELY(obj->watched())) {
WatchpointMap* wpmap = cx->compartment()->watchpointMap;
if (wpmap && !wpmap->triggerWatchpoint(cx, obj, id, vp))
return false;
}
return obj->getOps()->setProperty(cx, obj, receiver, id, vp, strict);
return obj->getOps()->setProperty(cx, obj, receiver, id, vp, result);
}
/* static */ bool
JSObject::nonNativeSetElement(JSContext* cx, HandleObject obj, HandleObject receiver,
uint32_t index, MutableHandleValue vp, bool strict)
uint32_t index, MutableHandleValue vp, ObjectOpResult &result)
{
RootedId id(cx);
if (!IndexToId(cx, index, &id))
return false;
return nonNativeSetProperty(cx, obj, receiver, id, vp, strict);
return nonNativeSetProperty(cx, obj, receiver, id, vp, result);
}
JS_FRIEND_API(bool)
@@ -1724,8 +1702,7 @@ JS_CopyPropertyFrom(JSContext* cx, HandleId id, HandleObject target,
if (!cx->compartment()->wrap(cx, &desc))
return false;
bool ignored;
return StandardDefineProperty(cx, target, wrappedId, desc, &ignored);
return StandardDefineProperty(cx, target, wrappedId, desc);
}
JS_FRIEND_API(bool)
@@ -3206,7 +3183,8 @@ js::GetOwnPropertyDescriptor(JSContext* cx, HandleObject obj, HandleId id,
bool
js::DefineProperty(ExclusiveContext* cx, HandleObject obj, HandleId id, HandleValue value,
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs,
ObjectOpResult &result)
{
MOZ_ASSERT(getter != JS_PropertyStub);
MOZ_ASSERT(setter != JS_StrictPropertyStub);
@@ -3216,15 +3194,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,
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
js::DefineProperty(ExclusiveContext *cx, HandleObject obj, PropertyName *name, HandleValue value,
JSPropertyOp getter, JSStrictPropertyOp 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,
JSPropertyOp getter, JSStrictPropertyOp 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,
JSPropertyOp getter, JSStrictPropertyOp 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,
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
{
RootedId id(cx, NameToId(name));
return DefineProperty(cx, obj, id, value, getter, setter, attrs);
@@ -3232,7 +3249,7 @@ js::DefineProperty(ExclusiveContext* cx, HandleObject obj,
bool
js::DefineElement(ExclusiveContext* cx, HandleObject obj, uint32_t index, HandleValue value,
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
{
MOZ_ASSERT(getter != JS_PropertyStub);
MOZ_ASSERT(setter != JS_StrictPropertyStub);
@@ -3243,6 +3260,22 @@ js::DefineElement(ExclusiveContext* cx, HandleObject obj, uint32_t index, Handle
return DefineProperty(cx, obj, id, value, getter, setter, attrs);
}
bool
js::SetProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandlePropertyName name,
MutableHandleValue vp)
{
RootedId id(cx, NameToId(name));
return SetProperty(cx, obj, receiver, id, vp);
}
bool
js::PutProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, MutableHandleValue value,
bool strict)
{
RootedId id(cx, NameToId(name));
return PutProperty(cx, obj, id, value, strict);
}
/*** SpiderMonkey nonstandard internal methods ***************************************************/
+66 -9
View File
@@ -519,10 +519,10 @@ class JSObject : public js::gc::Cell
static bool nonNativeSetProperty(JSContext* cx, js::HandleObject obj,
js::HandleObject receiver, js::HandleId id,
js::MutableHandleValue vp, bool strict);
js::MutableHandleValue vp, JS::ObjectOpResult &result);
static bool nonNativeSetElement(JSContext* cx, js::HandleObject obj,
js::HandleObject receiver, uint32_t index,
js::MutableHandleValue vp, bool strict);
js::MutableHandleValue vp, JS::ObjectOpResult &result);
static bool swap(JSContext* cx, JS::HandleObject a, JS::HandleObject b);
@@ -787,13 +787,40 @@ GetOwnPropertyDescriptor(JSContext* cx, HandleObject obj, HandleId id,
* the DefineProperty functions do not enforce some invariants mandated by ES6.
*/
extern bool
StandardDefineProperty(JSContext* cx, HandleObject obj, HandleId id,
const PropDesc& desc, bool throwError, bool* rval);
StandardDefineProperty(JSContext *cx, HandleObject obj, HandleId id, const PropDesc &desc,
ObjectOpResult &result);
extern bool
StandardDefineProperty(JSContext* cx, HandleObject obj, HandleId id,
Handle<PropertyDescriptor> descriptor, bool* bp);
Handle<PropertyDescriptor> descriptor, ObjectOpResult &result);
/*
* For convenience, signatures identical to the above except without the
* ObjectOpResult out-parameter. They throw a TypeError on failure.
*/
extern bool
StandardDefineProperty(JSContext *cx, HandleObject obj, HandleId id, const PropDesc &desc);
extern bool
StandardDefineProperty(JSContext* cx, HandleObject obj, HandleId id,
Handle<PropertyDescriptor> desc);
extern bool
DefineProperty(ExclusiveContext *cx, HandleObject obj, HandleId id, HandleValue value,
JSPropertyOp getter, JSStrictPropertyOp, unsigned attrs, ObjectOpResult &result);
extern bool
DefineProperty(ExclusiveContext *cx, HandleObject obj, PropertyName *name, HandleValue value,
JSPropertyOp getter, JSStrictPropertyOp, unsigned attrs, ObjectOpResult &result);
extern bool
DefineElement(ExclusiveContext *cx, HandleObject obj, uint32_t index, HandleValue value,
JSPropertyOp getter, JSStrictPropertyOp, 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,
JSPropertyOp getter = nullptr,
@@ -876,19 +903,49 @@ GetElementNoGC(JSContext* cx, JSObject* obj, JSObject* receiver, uint32_t index,
*/
inline bool
SetProperty(JSContext* cx, HandleObject obj, HandleObject receiver, HandleId id,
MutableHandleValue vp, bool strict);
MutableHandleValue vp, ObjectOpResult &result);
inline bool
SetProperty(JSContext* cx, HandleObject obj, HandleObject receiver, PropertyName* name,
MutableHandleValue vp, bool strict)
MutableHandleValue vp, ObjectOpResult &result)
{
RootedId id(cx, NameToId(name));
return SetProperty(cx, obj, receiver, id, vp, strict);
return SetProperty(cx, obj, receiver, id, vp, result);
}
inline bool
SetElement(JSContext* cx, HandleObject obj, HandleObject receiver, uint32_t index,
MutableHandleValue vp, bool strict);
MutableHandleValue vp, ObjectOpResult &result);
inline bool
SetProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id,
MutableHandleValue vp)
{
ObjectOpResult result;
return SetProperty(cx, obj, receiver, id, vp, result) &&
result.checkStrict(cx, receiver, id);
}
extern bool
SetProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandlePropertyName name,
MutableHandleValue vp);
/*
* ES6 draft rev 31 (15 Jan 2015) 7.3.3 Put (O, P, V, Throw), except that on
* success, the spec says this is supposed to return a boolean value, which we
* don't bother doing.
*/
inline bool
PutProperty(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue value, bool strict)
{
ObjectOpResult result;
return SetProperty(cx, obj, obj, id, value, result) &&
result.checkStrictErrorOrWarning(cx, obj, id, strict);
}
extern bool
PutProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, MutableHandleValue value,
bool strict);
/*
* ES6 [[Delete]]. Equivalent to the JS code `delete obj[id]`.
+1 -1
View File
@@ -742,7 +742,7 @@ NodeBuilder::newArray(NodeVector& elts, MutableHandleValue dst)
if (val.isMagic(JS_SERIALIZE_NO_NODE))
continue;
if (!SetElement(cx, array, array, i, &val, false))
if (!DefineElement(cx, array, i, val))
return false;
}
+1 -1
View File
@@ -2175,7 +2175,7 @@ class MOZ_STACK_CLASS StringRegExpGuard
// Handle everything else generically (including throwing if .lastIndex is non-writable).
RootedValue zero(cx, Int32Value(0));
return SetProperty(cx, obj_, obj_, cx->names().lastIndex, &zero, true);
return SetProperty(cx, obj_, obj_, cx->names().lastIndex, &zero);
}
RegExpShared& regExp() { return *re_; }
+6 -4
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 override;
virtual bool defineProperty(JSContext* cx, HandleObject wrapper, HandleId id,
MutableHandle<JSPropertyDescriptor> desc) const override;
MutableHandle<JSPropertyDescriptor> desc,
ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool ownPropertyKeys(JSContext* cx, HandleObject wrapper,
AutoIdVector& props) const override;
virtual bool delete_(JSContext* cx, HandleObject wrapper, HandleId id, bool* bp) const override;
@@ -134,8 +135,8 @@ class JS_FRIEND_API(CrossCompartmentWrapper) : public Wrapper
virtual bool has(JSContext* cx, HandleObject wrapper, HandleId id, bool* bp) const override;
virtual bool get(JSContext* cx, HandleObject wrapper, HandleObject receiver,
HandleId id, MutableHandleValue vp) const override;
virtual bool set(JSContext* cx, HandleObject wrapper, HandleObject receiver,
HandleId id, bool strict, MutableHandleValue vp) const override;
virtual bool set(JSContext *cx, HandleObject wrapper, HandleObject receiver, HandleId id,
MutableHandleValue vp, ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool call(JSContext* cx, HandleObject wrapper, const CallArgs& args) const override;
virtual bool construct(JSContext* cx, HandleObject wrapper, const CallArgs& args) const override;
@@ -182,7 +183,8 @@ class JS_FRIEND_API(SecurityWrapper) : public Base
bool* bp) const override;
virtual bool defineProperty(JSContext* cx, HandleObject wrapper, HandleId id,
MutableHandle<JSPropertyDescriptor> desc) const override;
MutableHandle<JSPropertyDescriptor> desc,
ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool isExtensible(JSContext* cx, HandleObject wrapper, bool* extensible) const override;
virtual bool preventExtensions(JSContext* cx, HandleObject wrapper, bool* succeeded) const override;
virtual bool setPrototypeOf(JSContext* cx, HandleObject proxy, HandleObject proto,
+27 -28
View File
@@ -73,7 +73,7 @@ BaseProxyHandler::get(JSContext* cx, HandleObject proxy, HandleObject receiver,
bool
BaseProxyHandler::set(JSContext* cx, HandleObject proxy, HandleObject receiver,
HandleId id, bool strict, MutableHandleValue vp) const
HandleId id, MutableHandleValue vp, ObjectOpResult &result) const
{
assertEnteredPolicy(cx, proxy, id, SET);
@@ -94,7 +94,7 @@ BaseProxyHandler::set(JSContext* cx, HandleObject proxy, HandleObject receiver,
if (!GetPrototype(cx, proxy, &proto))
return false;
if (proto)
return SetProperty(cx, proto, receiver, id, vp, strict);
return SetProperty(cx, proto, receiver, id, vp, result);
// Change ownDesc to be a complete descriptor for a configurable,
// writable, enumerable data property. Then fall through to step 5.
@@ -106,19 +106,14 @@ BaseProxyHandler::set(JSContext* cx, HandleObject proxy, HandleObject receiver,
if (ownDesc.isDataDescriptor()) {
// Steps 5.a-b, adapted to our nonstandard implementation of ES6
// [[Set]] return values.
if (!ownDesc.isWritable()) {
if (strict)
return JSObject::reportReadOnly(cx, id, JSREPORT_ERROR);
if (cx->compartment()->options().extraWarnings(cx))
return JSObject::reportReadOnly(cx, id, JSREPORT_STRICT | JSREPORT_WARNING);
return true;
}
if (!ownDesc.isWritable())
return result.fail(JSMSG_READ_ONLY);
// Nonstandard SpiderMonkey special case: setter ops.
StrictPropertyOp setter = ownDesc.setter();
MOZ_ASSERT(setter != JS_StrictPropertyStub);
if (setter && setter != JS_StrictPropertyStub)
return CallSetter(cx, receiver, id, setter, ownDesc.attributes(), strict, vp);
return CallSetter(cx, receiver, id, setter, ownDesc.attributes(), vp, result);
// Steps 5.c-d. Adapt for SpiderMonkey by using HasOwnProperty instead
// of the standard [[GetOwnProperty]].
@@ -137,8 +132,8 @@ BaseProxyHandler::set(JSContext* cx, HandleObject proxy, HandleObject receiver,
const Class* clasp = receiver->getClass();
MOZ_ASSERT(clasp->getProperty != JS_PropertyStub);
MOZ_ASSERT(clasp->setProperty != JS_StrictPropertyStub);
return DefineProperty(cx, receiver, id, vp,
clasp->getProperty, clasp->setProperty, attrs);
return DefineProperty(cx, receiver, id, vp, clasp->getProperty, clasp->setProperty,
attrs, result);
}
// Step 6.
@@ -147,16 +142,18 @@ BaseProxyHandler::set(JSContext* cx, HandleObject proxy, HandleObject receiver,
if (ownDesc.hasSetterObject())
setter = ownDesc.setterObject();
if (!setter)
return ReportGetterOnlyAssignment(cx, strict);
return result.fail(JSMSG_GETTER_ONLY);
RootedValue setterValue(cx, ObjectValue(*setter));
return InvokeGetterOrSetter(cx, receiver, setterValue, 1, vp.address(), vp);
if (!InvokeGetterOrSetter(cx, receiver, setterValue, 1, vp.address(), vp))
return false;
return result.succeed();
}
bool
js::SetPropertyIgnoringNamedGetter(JSContext* cx, const BaseProxyHandler* handler,
HandleObject proxy, HandleObject receiver,
HandleId id, MutableHandle<PropertyDescriptor> desc,
bool descIsOwn, bool strict, MutableHandleValue vp)
bool descIsOwn, MutableHandleValue vp, ObjectOpResult &result)
{
/* The control-flow here differs from ::get() because of the fall-through case below. */
MOZ_ASSERT_IF(descIsOwn, desc.object());
@@ -165,35 +162,37 @@ js::SetPropertyIgnoringNamedGetter(JSContext* cx, const BaseProxyHandler* handle
MOZ_ASSERT(desc.setter() != JS_StrictPropertyStub);
// Check for read-only properties.
if (desc.isReadonly()) {
if (strict)
return Throw(cx, id, descIsOwn ? JSMSG_READ_ONLY : JSMSG_CANT_REDEFINE_PROP);
return true;
}
if (desc.isReadonly())
return result.fail(descIsOwn ? JSMSG_READ_ONLY : JSMSG_CANT_REDEFINE_PROP);
if (desc.hasSetterObject() || desc.setter()) {
if (!CallSetter(cx, receiver, id, desc.setter(), desc.attributes(), strict, vp))
if (!CallSetter(cx, receiver, id, desc.setter(), desc.attributes(), vp, result))
return false;
if (!proxy->is<ProxyObject>() || proxy->as<ProxyObject>().handler() != handler)
return true;
if (desc.isShared())
if (!result)
return true;
if (!proxy->is<ProxyObject>() ||
proxy->as<ProxyObject>().handler() != handler ||
desc.isShared())
{
return result.succeed();
}
}
desc.value().set(vp.get());
if (descIsOwn) {
MOZ_ASSERT(desc.object() == proxy);
return handler->defineProperty(cx, proxy, id, desc);
return handler->defineProperty(cx, proxy, id, desc, result);
}
return DefineProperty(cx, receiver, id, desc.value(),
desc.getter(), desc.setter(), desc.attributes());
return DefineProperty(cx, receiver, id, desc.value(), desc.getter(), desc.setter(),
desc.attributes(), result);
}
desc.object().set(receiver);
desc.value().set(vp.get());
desc.setAttributes(JSPROP_ENUMERATE);
desc.setGetter(nullptr);
desc.setSetter(nullptr); // Pick up the class getter/setter.
return DefineProperty(cx, receiver, id, desc.value(), nullptr, nullptr, JSPROP_ENUMERATE);
return DefineProperty(cx, receiver, id, desc.value(), nullptr, nullptr, JSPROP_ENUMERATE,
result);
}
bool
+5 -4
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);
}
@@ -168,13 +169,13 @@ CrossCompartmentWrapper::get(JSContext* cx, HandleObject wrapper, HandleObject r
bool
CrossCompartmentWrapper::set(JSContext* cx, HandleObject wrapper, HandleObject receiver,
HandleId id, bool strict, MutableHandleValue vp) const
HandleId id, MutableHandleValue vp, ObjectOpResult &result) const
{
RootedObject receiverCopy(cx, receiver);
PIERCE(cx, wrapper,
cx->compartment()->wrap(cx, &receiverCopy) &&
cx->compartment()->wrap(cx, vp),
Wrapper::set(cx, wrapper, receiverCopy, id, strict, vp),
Wrapper::set(cx, wrapper, receiverCopy, id, vp, result),
NOTHING);
}
+2 -1
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;
+2 -1
View File
@@ -22,7 +22,8 @@ class DeadObjectProxy : public BaseProxyHandler
virtual bool getOwnPropertyDescriptor(JSContext* cx, HandleObject wrapper, HandleId id,
MutableHandle<JSPropertyDescriptor> desc) const override;
virtual bool defineProperty(JSContext* cx, HandleObject wrapper, HandleId id,
MutableHandle<JSPropertyDescriptor> desc) const override;
MutableHandle<JSPropertyDescriptor> desc,
ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool ownPropertyKeys(JSContext* cx, HandleObject wrapper,
AutoIdVector& props) const override;
virtual bool delete_(JSContext* cx, HandleObject wrapper, HandleId id, bool* bp) const override;
+5 -5
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());
bool ignored;
return StandardDefineProperty(cx, target, id, desc, &ignored);
return StandardDefineProperty(cx, target, id, desc, result);
}
bool
@@ -223,11 +223,11 @@ DirectProxyHandler::get(JSContext* cx, HandleObject proxy, HandleObject receiver
bool
DirectProxyHandler::set(JSContext* cx, HandleObject proxy, HandleObject receiver,
HandleId id, bool strict, MutableHandleValue vp) const
HandleId id, MutableHandleValue vp, ObjectOpResult &result) const
{
assertEnteredPolicy(cx, proxy, id, SET);
RootedObject target(cx, proxy->as<ProxyObject>().target());
return SetProperty(cx, target, receiver, id, vp, strict);
return SetProperty(cx, target, receiver, id, vp, result);
}
bool
+21 -14
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
@@ -301,20 +304,23 @@ Proxy::callProp(JSContext* cx, HandleObject proxy, HandleObject receiver, Handle
}
bool
Proxy::set(JSContext* cx, HandleObject proxy, HandleObject receiver, HandleId id, bool strict,
MutableHandleValue vp)
Proxy::set(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id,
MutableHandleValue vp, 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();
if (!policy.allowed()) {
if (!policy.returnValue())
return false;
return result.succeed();
}
// Special case. See the comment on BaseProxyHandler::mHasPrototype.
if (handler->hasPrototype())
return handler->BaseProxyHandler::set(cx, proxy, receiver, id, strict, vp);
return handler->BaseProxyHandler::set(cx, proxy, receiver, id, vp, result);
return handler->set(cx, proxy, receiver, id, strict, vp);
return handler->set(cx, proxy, receiver, id, vp, result);
}
bool
@@ -551,7 +557,8 @@ js::proxy_LookupProperty(JSContext* cx, HandleObject obj, HandleId id,
bool
js::proxy_DefineProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
ObjectOpResult &result)
{
Rooted<PropertyDescriptor> desc(cx);
desc.object().set(obj);
@@ -559,7 +566,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
@@ -577,9 +584,9 @@ js::proxy_GetProperty(JSContext* cx, HandleObject obj, HandleObject receiver, Ha
bool
js::proxy_SetProperty(JSContext* cx, HandleObject obj, HandleObject receiver, HandleId id,
MutableHandleValue vp, bool strict)
MutableHandleValue vp, ObjectOpResult &result)
{
return Proxy::set(cx, obj, receiver, id, strict, vp);
return Proxy::set(cx, obj, receiver, id, vp, result);
}
bool
+2 -2
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);
@@ -42,7 +42,7 @@ class Proxy
static bool get(JSContext* cx, HandleObject proxy, HandleObject receiver, HandleId id,
MutableHandleValue vp);
static bool set(JSContext* cx, HandleObject proxy, HandleObject receiver, HandleId id,
bool strict, MutableHandleValue vp);
MutableHandleValue vp, ObjectOpResult &result);
static bool call(JSContext* cx, HandleObject proxy, const CallArgs& args);
static bool construct(JSContext* cx, HandleObject proxy, const CallArgs& args);
+56 -52
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
// step 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]]()
@@ -934,7 +935,7 @@ ScriptedDirectProxyHandler::get(JSContext* cx, HandleObject proxy, HandleObject
// ES6 (22 May, 2014) 9.5.9 Proxy.[[SetP]](P, V, Receiver)
bool
ScriptedDirectProxyHandler::set(JSContext* cx, HandleObject proxy, HandleObject receiver,
HandleId id, bool strict, MutableHandleValue vp) const
HandleId id, MutableHandleValue vp, ObjectOpResult &result) const
{
// step 2
RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
@@ -955,7 +956,7 @@ ScriptedDirectProxyHandler::set(JSContext* cx, HandleObject proxy, HandleObject
// step 7
if (trap.isUndefined())
return DirectProxyHandler::set(cx, proxy, receiver, id, strict, vp);
return DirectProxyHandler::set(cx, proxy, receiver, id, vp, result);
// step 8,10
RootedValue value(cx);
@@ -971,7 +972,9 @@ ScriptedDirectProxyHandler::set(JSContext* cx, HandleObject proxy, HandleObject
if (!Invoke(cx, ObjectValue(*handler), trap, ArrayLength(argv), argv, &trapResult))
return false;
// step 9
// FIXME - bug 1132522: Step 9 is not implemented yet.
// if (!ToBoolean(trapResult))
// return result.fail(JSMSG_PROXY_SET_RETURNED_FALSE);
bool success = ToBoolean(trapResult);
if (success) {
@@ -1000,8 +1003,9 @@ ScriptedDirectProxyHandler::set(JSContext* cx, HandleObject proxy, HandleObject
}
// step 11, 15
// XXX FIXME - This use of vp is wrong. Bug 1132522 can clean it up.
vp.setBoolean(success);
return true;
return result.succeed();
}
+3 -2
View File
@@ -22,7 +22,8 @@ class ScriptedDirectProxyHandler : public DirectProxyHandler {
virtual bool getOwnPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
MutableHandle<JSPropertyDescriptor> desc) const override;
virtual bool defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
MutableHandle<JSPropertyDescriptor> desc) const override;
MutableHandle<JSPropertyDescriptor> desc,
ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool ownPropertyKeys(JSContext* cx, HandleObject proxy,
AutoIdVector& props) const override;
virtual bool delete_(JSContext* cx, HandleObject proxy, HandleId id, bool* bp) const override;
@@ -44,7 +45,7 @@ class ScriptedDirectProxyHandler : public DirectProxyHandler {
virtual bool get(JSContext* cx, HandleObject proxy, HandleObject receiver, HandleId id,
MutableHandleValue vp) const override;
virtual bool set(JSContext* cx, HandleObject proxy, HandleObject receiver, HandleId id,
bool strict, MutableHandleValue vp) const override;
MutableHandleValue vp, ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool call(JSContext* cx, HandleObject proxy, const CallArgs& args) const override;
virtual bool construct(JSContext* cx, HandleObject proxy, const CallArgs& args) const override;
+13 -8
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
@@ -294,7 +296,7 @@ ScriptedIndirectProxyHandler::get(JSContext* cx, HandleObject proxy, HandleObjec
bool
ScriptedIndirectProxyHandler::set(JSContext* cx, HandleObject proxy, HandleObject receiver,
HandleId id, bool strict, MutableHandleValue vp) const
HandleId id, MutableHandleValue vp, ObjectOpResult &result) const
{
RootedObject handler(cx, GetIndirectProxyHandlerObject(proxy));
RootedValue idv(cx);
@@ -308,13 +310,16 @@ ScriptedIndirectProxyHandler::set(JSContext* cx, HandleObject proxy, HandleObjec
if (!GetDerivedTrap(cx, handler, cx->names().set, &fval))
return false;
if (!IsCallable(fval))
return derivedSet(cx, proxy, receiver, id, strict, vp);
return Trap(cx, handler, fval, 3, argv.begin(), &idv);
return derivedSet(cx, proxy, receiver, id, vp, result);
if (!Trap(cx, handler, fval, 3, argv.begin(), &idv))
return false;
return result.succeed();
}
bool
ScriptedIndirectProxyHandler::derivedSet(JSContext* cx, HandleObject proxy, HandleObject receiver,
HandleId id, bool strict, MutableHandleValue vp) const
HandleId id, MutableHandleValue vp,
ObjectOpResult &result) const
{
// Find an own or inherited property. The code here is strange for maximum
// backward compatibility with earlier code written before ES6 and before
@@ -328,8 +333,8 @@ ScriptedIndirectProxyHandler::derivedSet(JSContext* cx, HandleObject proxy, Hand
return false;
}
return SetPropertyIgnoringNamedGetter(cx, this, proxy, receiver, id, &desc, descIsOwn, strict,
vp);
return SetPropertyIgnoringNamedGetter(cx, this, proxy, receiver, id, &desc, descIsOwn, vp,
result);
}
bool
+4 -3
View File
@@ -23,7 +23,8 @@ class ScriptedIndirectProxyHandler : public BaseProxyHandler
virtual bool getOwnPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
MutableHandle<JSPropertyDescriptor> desc) const override;
virtual bool defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
MutableHandle<JSPropertyDescriptor> desc) const override;
MutableHandle<JSPropertyDescriptor> desc,
ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool ownPropertyKeys(JSContext* cx, HandleObject proxy,
AutoIdVector& props) const override;
virtual bool delete_(JSContext* cx, HandleObject proxy, HandleId id, bool* bp) const override;
@@ -35,7 +36,7 @@ class ScriptedIndirectProxyHandler : public BaseProxyHandler
virtual bool get(JSContext* cx, HandleObject proxy, HandleObject receiver, HandleId id,
MutableHandleValue vp) const override;
virtual bool set(JSContext* cx, HandleObject proxy, HandleObject receiver, HandleId id,
bool strict, MutableHandleValue vp) const override;
MutableHandleValue vp, ObjectOpResult &result) const MOZ_OVERRIDE;
/* SpiderMonkey extensions. */
virtual bool getPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
@@ -53,7 +54,7 @@ class ScriptedIndirectProxyHandler : public BaseProxyHandler
private:
bool derivedSet(JSContext* cx, HandleObject proxy, HandleObject receiver, HandleId id,
bool strict, MutableHandleValue vp) const;
MutableHandleValue vp, ObjectOpResult &result) const;
};
/* Derived class to handle Proxy.createFunction() */
+3 -2
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>
@@ -33,7 +33,7 @@ function test()
try
{
expect = "TypeError: can't redefine non-configurable property '5'";
expect = "TypeError: can't redefine non-configurable property 5";
"012345".__defineSetter__(5, function(){});
}
catch(ex)
+5 -5
View File
@@ -29,7 +29,7 @@ reportCompare(expect, actual, summary + ': join');
// reverse
value = '123';
expect = 'TypeError: Array.prototype.reverse.call(...) is read-only';
expect = 'TypeError: 0 is read-only';
try
{
actual = Array.prototype.reverse.call(value) + '';
@@ -42,7 +42,7 @@ reportCompare(expect, actual, summary + ': reverse');
// sort
value = 'cba';
expect = 'TypeError: Array.prototype.sort.call(...) is read-only';
expect = 'TypeError: 0 is read-only';
try
{
actual = Array.prototype.sort.call(value) + '';
@@ -100,7 +100,7 @@ reportCompare('abc', value, summary + ': pop');
// unshift
value = 'def';
expect = 'TypeError: Array.prototype.unshift.call(...) is read-only';
expect = 'TypeError: 0 is read-only';
try
{
actual = Array.prototype.unshift.call(value, 'a', 'b', 'c');
@@ -114,7 +114,7 @@ reportCompare('def', value, summary + ': unshift');
// shift
value = 'abc';
expect = 'TypeError: Array.prototype.shift.call(...) is read-only';
expect = 'TypeError: 0 is read-only';
try
{
actual = Array.prototype.shift.call(value);
@@ -128,7 +128,7 @@ reportCompare('abc', value, summary + ': shift');
// splice
value = 'abc';
expect = 'TypeError: Array.prototype.splice.call(...) is read-only';
expect = 'TypeError: 1 is read-only';
try
{
actual = Array.prototype.splice.call(value, 1, 1) + '';
+10 -8
View File
@@ -317,10 +317,11 @@ ArgGetter(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue vp)
}
static bool
ArgSetter(JSContext* cx, HandleObject obj, HandleId id, bool strict, MutableHandleValue vp)
ArgSetter(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp,
ObjectOpResult &result)
{
if (!obj->is<NormalArgumentsObject>())
return true;
return result.succeed();
Handle<NormalArgumentsObject*> argsobj = obj.as<NormalArgumentsObject>();
Rooted<PropertyDescriptor> desc(cx);
@@ -339,7 +340,7 @@ ArgSetter(JSContext* cx, HandleObject obj, HandleId id, bool strict, MutableHand
argsobj->setElement(cx, arg, vp);
if (arg < script->functionNonDelazifying()->nargs())
TypeScript::SetArgument(cx, script, arg, vp);
return true;
return result.succeed();
}
} else {
MOZ_ASSERT(JSID_IS_ATOM(id, cx->names().length) || JSID_IS_ATOM(id, cx->names().callee));
@@ -354,7 +355,7 @@ ArgSetter(JSContext* cx, HandleObject obj, HandleId id, bool strict, MutableHand
*/
bool succeeded;
return NativeDeleteProperty(cx, argsobj, id, &succeeded) &&
NativeDefineProperty(cx, argsobj, id, vp, nullptr, nullptr, attrs);
NativeDefineProperty(cx, argsobj, id, vp, nullptr, nullptr, attrs, result);
}
static bool
@@ -438,10 +439,11 @@ StrictArgGetter(JSContext* cx, HandleObject obj, HandleId id, MutableHandleValue
}
static bool
StrictArgSetter(JSContext* cx, HandleObject obj, HandleId id, bool strict, MutableHandleValue vp)
StrictArgSetter(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp,
ObjectOpResult &result)
{
if (!obj->is<StrictArgumentsObject>())
return true;
return result.succeed();
Handle<StrictArgumentsObject*> argsobj = obj.as<StrictArgumentsObject>();
Rooted<PropertyDescriptor> desc(cx);
@@ -456,7 +458,7 @@ StrictArgSetter(JSContext* cx, HandleObject obj, HandleId id, bool strict, Mutab
unsigned arg = unsigned(JSID_TO_INT(id));
if (arg < argsobj->initialLength()) {
argsobj->setElement(cx, arg, vp);
return true;
return result.succeed();
}
} else {
MOZ_ASSERT(JSID_IS_ATOM(id, cx->names().length));
@@ -469,7 +471,7 @@ StrictArgSetter(JSContext* cx, HandleObject obj, HandleId id, bool strict, Mutab
*/
bool succeeded;
return NativeDeleteProperty(cx, argsobj, id, &succeeded) &&
NativeDefineProperty(cx, argsobj, id, vp, nullptr, nullptr, attrs);
NativeDefineProperty(cx, argsobj, id, vp, nullptr, nullptr, attrs, result);
}
static bool
+3 -5
View File
@@ -6720,8 +6720,7 @@ DebuggerObject_defineProperty(JSContext* cx, unsigned argc, Value* vp)
return false;
ErrorCopier ec(ac);
bool dummy;
if (!StandardDefineProperty(cx, obj, id, desc, true, &dummy))
if (!StandardDefineProperty(cx, obj, id, desc))
return false;
}
@@ -6764,8 +6763,7 @@ DebuggerObject_defineProperties(JSContext* cx, unsigned argc, Value* vp)
ErrorCopier ec(ac);
for (size_t i = 0; i < n; i++) {
bool dummy;
if (!StandardDefineProperty(cx, obj, ids[i], descs[i], true, &dummy))
if (!StandardDefineProperty(cx, obj, ids[i], descs[i]))
return false;
}
}
@@ -7512,7 +7510,7 @@ DebuggerEnv_setVariable(JSContext* cx, unsigned argc, Value* vp)
}
/* Just set the property. */
if (!SetProperty(cx, env, env, id, &v, true))
if (!SetProperty(cx, env, env, id, &v))
return false;
}
+4 -1
View File
@@ -607,7 +607,10 @@ class GlobalObject : public NativeObject
#endif
RootedObject holder(cx, intrinsicsHolder());
RootedValue valCopy(cx, value);
return SetProperty(cx, holder, holder, name, &valCopy, false);
ObjectOpResult result;
bool ok = SetProperty(cx, holder, holder, name, &valCopy, result);
MOZ_ASSERT_IF(ok, result);
return ok;
}
bool getSelfHostedFunction(JSContext* cx, HandleAtom selfHostedName, HandleAtom name,
+12 -11
View File
@@ -313,19 +313,20 @@ SetNameOperation(JSContext* cx, JSScript* script, jsbytecode* pc, HandleObject s
RootedPropertyName name(cx, script->getName(pc));
RootedValue valCopy(cx, val);
/*
* In strict-mode, we need to trigger an error when trying to assign to an
* undeclared global variable. To do this, we call NativeSetProperty
* directly and pass Unqualified.
*/
// In strict mode, assigning to an undeclared global variable is an
// error. To detect this, we call NativeSetProperty directly and pass
// Unqualified. It stores the error, if any, in |result|.
bool ok;
ObjectOpResult result;
RootedId id(cx, NameToId(name));
if (scope->isUnqualifiedVarObj()) {
MOZ_ASSERT(!scope->getOps()->setProperty);
RootedId id(cx, NameToId(name));
return NativeSetProperty(cx, scope.as<NativeObject>(), scope.as<NativeObject>(), id,
Unqualified, &valCopy, strict);
ok = NativeSetProperty(cx, scope.as<NativeObject>(), scope.as<NativeObject>(), id,
Unqualified, &valCopy, result);
} else {
ok = SetProperty(cx, scope, scope, id, &valCopy, result);
}
return SetProperty(cx, scope, scope, name, &valCopy, strict);
return ok && result.checkStrictErrorOrWarning(cx, scope, id, strict);
}
inline bool
@@ -339,7 +340,7 @@ InitPropertyOperation(JSContext *cx, JSOp op, HandleObject obj, HandleId id, Han
MOZ_ASSERT(obj->as<UnboxedPlainObject>().layout().lookup(id));
RootedValue v(cx, rhs);
return SetProperty(cx, obj, obj, id, &v, false);
return PutProperty(cx, obj, id, &v, false);
}
inline bool
+6 -6
View File
@@ -310,19 +310,19 @@ SetObjectProperty(JSContext* cx, JSOp op, HandleValue lval, HandleId id, Mutable
RootedObject obj(cx, &lval.toObject());
bool strict = op == JSOP_STRICTSETPROP;
ObjectOpResult result;
if (MOZ_LIKELY(!obj->getOps()->setProperty)) {
if (!NativeSetProperty(cx, obj.as<NativeObject>(), obj.as<NativeObject>(), id,
Qualified, rref, strict))
Qualified, rref, result))
{
return false;
}
} else {
if (!SetProperty(cx, obj, obj, id, rref, strict))
if (!SetProperty(cx, obj, obj, id, rref, result))
return false;
}
return true;
return result.checkStrictErrorOrWarning(cx, obj, id, op == JSOP_STRICTSETPROP);
}
static bool
@@ -1425,7 +1425,7 @@ SetObjectElementOperation(JSContext* cx, Handle<JSObject*> obj, HandleId id, con
return false;
RootedValue tmp(cx, value);
return SetProperty(cx, obj, obj, id, &tmp, strict);
return PutProperty(cx, obj, id, &tmp, strict);
}
static MOZ_NEVER_INLINE bool
@@ -3859,7 +3859,7 @@ js::DefFunOperation(JSContext* cx, HandleScript script, HandleObject scopeChain,
*/
/* Step 5f. */
return SetProperty(cx, parent, parent, name, &rval, script->strict());
return PutProperty(cx, parent, name, &rval, script->strict());
}
bool
-12
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, PropertyOp getter, StrictPropertyOp 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)
{
+112 -95
View File
@@ -1129,13 +1129,13 @@ UpdateShapeTypeAndValue(ExclusiveContext* cx, NativeObject* obj, Shape* shape, c
static bool
NativeSet(JSContext* cx, HandleNativeObject obj, HandleObject receiver,
HandleShape shape, bool strict, MutableHandleValue vp);
HandleShape shape, MutableHandleValue vp, ObjectOpResult &result);
static inline bool
DefinePropertyOrElement(ExclusiveContext* cx, HandleNativeObject obj, HandleId id,
PropertyOp getter, StrictPropertyOp setter,
unsigned attrs, HandleValue value,
bool callSetterAfterwards, bool setterIsStrict)
bool callSetterAfterwards, ObjectOpResult &result)
{
MOZ_ASSERT(getter != JS_PropertyStub);
MOZ_ASSERT(setter != JS_StrictPropertyStub);
@@ -1149,20 +1149,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();
}
}
@@ -1171,16 +1168,13 @@ DefinePropertyOrElement(ExclusiveContext* cx, HandleNativeObject obj, HandleId i
if (id == NameToId(cx->names().length)) {
if (!cx->shouldBeJSContext())
return false;
return ArraySetLength(cx->asJSContext(), arr, id, attrs, value, setterIsStrict);
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);
}
}
@@ -1188,7 +1182,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);
@@ -1210,12 +1204,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();
}
}
@@ -1226,9 +1222,10 @@ 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);
return NativeSet(cx->asJSContext(), obj, obj, shape, &nvalue, result);
}
return true;
return result.succeed();
}
static unsigned
@@ -1341,7 +1338,8 @@ CheckAccessorRedefinition(ExclusiveContext* cx, HandleObject obj, HandleShape sh
bool
js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId id, HandleValue value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
ObjectOpResult &result)
{
MOZ_ASSERT(getter != JS_PropertyStub);
MOZ_ASSERT(setter != JS_StrictPropertyStub);
@@ -1369,7 +1367,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;
@@ -1434,11 +1432,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;
@@ -1485,14 +1483,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>
@@ -1546,13 +1546,23 @@ js::NativeLookupElement(JSContext* cx, HandleNativeObject obj, uint32_t index,
}
bool
js::NativeDefineElement(ExclusiveContext* cx, HandleNativeObject obj, uint32_t index, HandleValue value,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
js::NativeDefineProperty(ExclusiveContext *cx, HandleNativeObject obj, PropertyName *name,
HandleValue value, PropertyOp getter, StrictPropertyOp 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, PropertyOp getter, StrictPropertyOp 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);
@@ -1560,6 +1570,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, PropertyOp getter, StrictPropertyOp 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, PropertyOp getter, StrictPropertyOp setter,
unsigned attrs)
{
RootedId id(cx, NameToId(name));
return NativeDefineProperty(cx, obj, id, value, getter, setter, attrs);
}
@@ -1961,7 +2000,7 @@ MaybeReportUndeclaredVarAssignment(JSContext* cx, JSString* propname)
*/
bool
js::SetPropertyByDefining(JSContext* cx, HandleObject obj, HandleObject receiver,
HandleId id, HandleValue v, bool strict, bool objHasOwn)
HandleId id, HandleValue v, bool objHasOwn, ObjectOpResult &result)
{
// Step 5.c-d: Test whether receiver has an existing own property
// receiver[id]. The spec calls [[GetOwnProperty]]; js::HasOwnProperty is
@@ -1992,15 +2031,8 @@ js::SetPropertyByDefining(JSContext* cx, HandleObject obj, HandleObject receiver
bool extensible;
if (!IsExtensible(cx, receiver, &extensible))
return false;
if (!extensible) {
// Error in strict mode code, warn with extra warnings option,
// otherwise do nothing.
if (strict)
return receiver->reportNotExtensible(cx);
if (cx->compartment()->options().extraWarnings(cx))
return receiver->reportNotExtensible(cx, JSREPORT_STRICT | JSREPORT_WARNING);
return true;
}
if (!extensible)
return result.fail(JSMSG_OBJECT_NOT_EXTENSIBLE);
}
// Invalidate SpiderMonkey-specific caches or bail.
@@ -2020,37 +2052,24 @@ js::SetPropertyByDefining(JSContext* cx, HandleObject obj, HandleObject receiver
MOZ_ASSERT(getter != JS_PropertyStub);
MOZ_ASSERT(setter != JS_StrictPropertyStub);
if (!receiver->is<NativeObject>())
return DefineProperty(cx, receiver, id, v, getter, setter, attrs);
return DefineProperty(cx, receiver, id, v, getter, setter, attrs, result);
Rooted<NativeObject*> nativeReceiver(cx, &receiver->as<NativeObject>());
return DefinePropertyOrElement(cx, nativeReceiver, id, getter, setter, attrs, v, true, strict);
return DefinePropertyOrElement(cx, nativeReceiver, id, getter, setter, attrs, v, true, result);
}
// When setting |id| for |receiver| and |obj| has no property for id, continue
// the search up the prototype chain.
bool
js::SetPropertyOnProto(JSContext* cx, HandleObject obj, HandleObject receiver,
HandleId id, MutableHandleValue vp, bool strict)
HandleId id, MutableHandleValue vp, ObjectOpResult &result)
{
MOZ_ASSERT(!obj->is<ProxyObject>());
RootedObject proto(cx, obj->getProto());
if (proto)
return SetProperty(cx, proto, receiver, id, vp, strict);
return SetPropertyByDefining(cx, obj, receiver, id, vp, strict, false);
}
bool
js::SetNonWritableProperty(JSContext* cx, HandleId id, bool strict)
{
// Setting a non-writable property is an error in strict mode code, a
// warning with the extra warnings option, and otherwise does nothing.
if (strict)
return JSObject::reportReadOnly(cx, id, JSREPORT_ERROR);
if (cx->compartment()->options().extraWarnings(cx))
return JSObject::reportReadOnly(cx, id, JSREPORT_STRICT | JSREPORT_WARNING);
return true;
return SetProperty(cx, proto, receiver, id, vp, result);
return SetPropertyByDefining(cx, obj, receiver, id, vp, false, result);
}
/*
@@ -2064,7 +2083,7 @@ js::SetNonWritableProperty(JSContext* cx, HandleId id, bool strict)
*/
static bool
SetNonexistentProperty(JSContext* cx, HandleNativeObject obj, HandleObject receiver, HandleId id,
QualifiedBool qualified, HandleValue v, bool strict)
QualifiedBool qualified, HandleValue v, ObjectOpResult &result)
{
// We should never add properties to lexical blocks.
MOZ_ASSERT(!receiver->is<BlockObject>());
@@ -2074,7 +2093,7 @@ SetNonexistentProperty(JSContext* cx, HandleNativeObject obj, HandleObject recei
return false;
}
return SetPropertyByDefining(cx, obj, receiver, id, v, strict, false);
return SetPropertyByDefining(cx, obj, receiver, id, v, false, result);
}
/*
@@ -2083,7 +2102,7 @@ SetNonexistentProperty(JSContext* cx, HandleNativeObject obj, HandleObject recei
*/
static bool
SetDenseOrTypedArrayElement(JSContext* cx, HandleNativeObject obj, uint32_t index,
MutableHandleValue vp, bool strict)
MutableHandleValue vp, ObjectOpResult &result)
{
if (IsAnyTypedArray(obj)) {
double d;
@@ -2100,20 +2119,17 @@ SetDenseOrTypedArrayElement(JSContext* cx, HandleNativeObject obj, uint32_t inde
else
SharedTypedArrayObject::setElement(obj->as<SharedTypedArrayObject>(), index, d);
}
return true;
return result.succeed();
}
bool definesPast;
if (!WouldDefinePastNonwritableLength(cx, obj, index, strict, &definesPast))
return false;
if (definesPast)
return true;
if (WouldDefinePastNonwritableLength(obj, index))
return result.fail(JSMSG_CANT_DEFINE_PAST_ARRAY_LENGTH);
if (!obj->maybeCopyElementsForWrite(cx))
return false;
obj->setDenseElementWithType(cx, index, vp);
return true;
return result.succeed();
}
/*
@@ -2122,7 +2138,7 @@ SetDenseOrTypedArrayElement(JSContext* cx, HandleNativeObject obj, uint32_t inde
*/
static bool
NativeSet(JSContext* cx, HandleNativeObject obj, HandleObject receiver,
HandleShape shape, bool strict, MutableHandleValue vp)
HandleShape shape, MutableHandleValue vp, ObjectOpResult &result)
{
MOZ_ASSERT(obj->isNative());
@@ -2134,7 +2150,7 @@ NativeSet(JSContext* cx, HandleNativeObject obj, HandleObject receiver,
// assignments to such properties as overwrites.
bool overwriting = !obj->is<GlobalObject>() || !obj->getSlot(shape->slot()).isUndefined();
obj->setSlotWithType(cx, shape, vp, overwriting);
return true;
return result.succeed();
}
}
@@ -2146,13 +2162,13 @@ NativeSet(JSContext* cx, HandleNativeObject obj, HandleObject receiver,
* or throw if we're in strict mode.
*/
if (!shape->hasGetterValue() && shape->hasDefaultSetter())
return ReportGetterOnlyAssignment(cx, strict);
return result.fail(JSMSG_GETTER_ONLY);
}
RootedValue ovp(cx, vp);
uint32_t sample = cx->runtime()->propertyRemovals;
if (!shape->set(cx, obj, receiver, strict, vp))
if (!shape->set(cx, obj, receiver, vp, result))
return false;
/*
@@ -2166,7 +2182,7 @@ NativeSet(JSContext* cx, HandleNativeObject obj, HandleObject receiver,
obj->setSlot(shape->slot(), vp);
}
return true;
return true; // result is populated by shape->set() above.
}
/*
@@ -2178,30 +2194,31 @@ NativeSet(JSContext* cx, HandleNativeObject obj, HandleObject receiver,
*/
static bool
SetExistingProperty(JSContext* cx, HandleNativeObject obj, HandleObject receiver, HandleId id,
HandleNativeObject pobj, HandleShape shape, MutableHandleValue vp, bool strict)
HandleNativeObject pobj, HandleShape shape, MutableHandleValue vp,
ObjectOpResult &result)
{
if (IsImplicitDenseOrTypedArrayElement(shape)) {
/* ES5 8.12.4 [[Put]] step 2, for a dense data property on pobj. */
if (pobj == receiver)
return SetDenseOrTypedArrayElement(cx, pobj, JSID_TO_INT(id), vp, strict);
return SetDenseOrTypedArrayElement(cx, pobj, JSID_TO_INT(id), vp, result);
} else {
/* ES5 8.12.4 [[Put]] step 2. */
if (shape->isAccessorDescriptor()) {
if (shape->hasDefaultSetter())
return ReportGetterOnlyAssignment(cx, strict);
return result.fail(JSMSG_GETTER_ONLY);
} else {
MOZ_ASSERT(shape->isDataDescriptor());
if (!shape->writable())
return SetNonWritableProperty(cx, id, strict);
return result.fail(JSMSG_READ_ONLY);
}
if (pobj == receiver) {
if (pobj->is<ArrayObject>() && id == NameToId(cx->names().length)) {
Rooted<ArrayObject*> arr(cx, &pobj->as<ArrayObject>());
return ArraySetLength(cx, arr, id, shape->attributes(), vp, strict);
return ArraySetLength(cx, arr, id, shape->attributes(), vp, result);
}
return NativeSet(cx, obj, receiver, shape, strict, vp);
return NativeSet(cx, obj, receiver, shape, vp, result);
}
// pobj[id] is not an own property of receiver. Call the setter or shadow it.
@@ -2210,19 +2227,19 @@ SetExistingProperty(JSContext* cx, HandleNativeObject obj, HandleObject receiver
{
// Weird special case: slotless property with default setter.
if (shape->hasDefaultSetter() && !shape->hasGetterValue())
return true;
return result.succeed();
return shape->set(cx, obj, receiver, strict, vp);
return shape->set(cx, obj, receiver, vp, result);
}
}
// Shadow pobj[id] by defining a new data property receiver[id].
return SetPropertyByDefining(cx, obj, receiver, id, vp, strict, obj == pobj);
return SetPropertyByDefining(cx, obj, receiver, id, vp, obj == pobj, result);
}
bool
js::NativeSetProperty(JSContext* cx, HandleNativeObject obj, HandleObject receiver, HandleId id,
QualifiedBool qualified, MutableHandleValue vp, bool strict)
QualifiedBool qualified, MutableHandleValue vp, ObjectOpResult &result)
{
// Fire watchpoints, if any.
if (MOZ_UNLIKELY(obj->watched())) {
@@ -2248,7 +2265,7 @@ js::NativeSetProperty(JSContext* cx, HandleNativeObject obj, HandleObject receiv
if (shape) {
// Steps 5-6.
return SetExistingProperty(cx, obj, receiver, id, pobj, shape, vp, strict);
return SetExistingProperty(cx, obj, receiver, id, pobj, shape, vp, result);
}
// Steps 4.a-b. The check for 'done' on this next line is tricky.
@@ -2262,7 +2279,7 @@ js::NativeSetProperty(JSContext* cx, HandleNativeObject obj, HandleObject receiv
RootedObject proto(cx, done ? nullptr : pobj->getProto());
if (!proto) {
// Step 4.d.i (and step 5).
return SetNonexistentProperty(cx, obj, receiver, id, qualified, vp, strict);
return SetNonexistentProperty(cx, obj, receiver, id, qualified, vp, result);
}
// Step 4.c.i. If the prototype is also native, this step is a
@@ -2279,10 +2296,10 @@ js::NativeSetProperty(JSContext* cx, HandleNativeObject obj, HandleObject receiv
if (!HasProperty(cx, proto, id, &found))
return false;
if (!found)
return SetNonexistentProperty(cx, obj, receiver, id, qualified, vp, strict);
return SetNonexistentProperty(cx, obj, receiver, id, qualified, vp, result);
}
return SetProperty(cx, proto, receiver, id, vp, strict);
return SetProperty(cx, proto, receiver, id, vp, result);
}
pobj = &proto->as<NativeObject>();
}
@@ -2290,12 +2307,12 @@ js::NativeSetProperty(JSContext* cx, HandleNativeObject obj, HandleObject receiv
bool
js::NativeSetElement(JSContext* cx, HandleNativeObject obj, HandleObject receiver, uint32_t index,
MutableHandleValue vp, bool strict)
MutableHandleValue vp, ObjectOpResult &result)
{
RootedId id(cx);
if (!IndexToId(cx, index, &id))
return false;
return NativeSetProperty(cx, obj, receiver, id, Qualified, vp, strict);
return NativeSetProperty(cx, obj, receiver, id, Qualified, vp, result);
}
/*** [[Delete]] **********************************************************************************/
+31 -28
View File
@@ -83,12 +83,11 @@ class ArrayObject;
*
* |id| must be "length", |attrs| are the attributes to be used for the newly-
* changed length property, |value| is the value for the new length, and
* |setterIsStrict| indicates whether invalid changes will cause a TypeError
* to be thrown.
* |result| receives an error code if the change is invalid.
*/
extern bool
ArraySetLength(JSContext* cx, Handle<ArrayObject*> obj, HandleId id,
unsigned attrs, HandleValue value, bool setterIsStrict);
unsigned attrs, HandleValue value, ObjectOpResult &result);
/*
* Elements header used for native objects. The elements component of such objects
@@ -189,7 +188,7 @@ class ObjectElements
friend bool
ArraySetLength(JSContext* cx, Handle<ArrayObject*> obj, HandleId id,
unsigned attrs, HandleValue value, bool setterIsStrict);
unsigned attrs, HandleValue value, ObjectOpResult &result);
/* See Flags enum above. */
uint32_t flags;
@@ -347,10 +346,6 @@ class NativeObject : public JSObject
/* Slots for object dense elements. */
js::HeapSlot* elements_;
friend bool
ArraySetLength(JSContext* cx, Handle<ArrayObject*> obj, HandleId id, unsigned attrs,
HandleValue value, bool setterIsStrict);
friend class ::JSObject;
private:
@@ -1238,16 +1233,28 @@ IsObjectValueInCompartment(Value v, JSCompartment* comp)
extern bool
NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId id, HandleValue value,
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
PropertyOp getter, StrictPropertyOp, unsigned attrs,
ObjectOpResult &result);
inline bool
extern bool
NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, PropertyName* name,
HandleValue value, PropertyOp getter, StrictPropertyOp setter,
unsigned attrs);
unsigned attrs, ObjectOpResult &result);
extern bool
NativeDefineElement(ExclusiveContext* cx, HandleNativeObject obj, uint32_t index, HandleValue value,
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
PropertyOp getter, StrictPropertyOp 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,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
extern bool
NativeDefineProperty(ExclusiveContext *cx, HandleNativeObject obj, PropertyName *name,
HandleValue value, PropertyOp getter, StrictPropertyOp setter,
unsigned attrs);
extern bool
NativeHasProperty(JSContext* cx, HandleNativeObject obj, HandleId id, bool* foundp);
@@ -1276,16 +1283,12 @@ NativeGetElement(JSContext* cx, HandleNativeObject obj, uint32_t index, MutableH
}
bool
SetPropertyByDefining(JSContext* cx, HandleObject obj, HandleObject receiver,
HandleId id, HandleValue v, bool strict, bool objHasOwn);
SetPropertyByDefining(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id,
HandleValue v, bool objHasOwn, ObjectOpResult &result);
bool
SetPropertyOnProto(JSContext* cx, HandleObject obj, HandleObject receiver,
HandleId id, MutableHandleValue vp, bool strict);
// Report any error or warning when writing to a non-writable property.
bool
SetNonWritableProperty(JSContext* cx, HandleId id, bool strict);
SetPropertyOnProto(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id,
MutableHandleValue vp, ObjectOpResult &result);
/*
* Indicates whether an assignment operation is qualified (`x.y = 0`) or
@@ -1301,11 +1304,11 @@ enum QualifiedBool {
extern bool
NativeSetProperty(JSContext* cx, HandleNativeObject obj, HandleObject receiver, HandleId id,
QualifiedBool qualified, MutableHandleValue vp, bool strict);
QualifiedBool qualified, MutableHandleValue vp, ObjectOpResult &result);
extern bool
NativeSetElement(JSContext* cx, HandleNativeObject obj, HandleObject receiver, uint32_t index,
MutableHandleValue vp, bool strict);
MutableHandleValue vp, ObjectOpResult &result);
extern bool
NativeDeleteProperty(JSContext* cx, HandleNativeObject obj, HandleId id, bool* succeeded);
@@ -1417,20 +1420,20 @@ js::GetPropertyNoGC(JSContext* cx, JSObject* obj, JSObject* receiver, jsid id, V
inline bool
js::SetProperty(JSContext* cx, HandleObject obj, HandleObject receiver,
HandleId id, MutableHandleValue vp, bool strict)
HandleId id, MutableHandleValue vp, ObjectOpResult &result)
{
if (obj->getOps()->setProperty)
return JSObject::nonNativeSetProperty(cx, obj, receiver, id, vp, strict);
return NativeSetProperty(cx, obj.as<NativeObject>(), receiver, id, Qualified, vp, strict);
return JSObject::nonNativeSetProperty(cx, obj, receiver, id, vp, result);
return NativeSetProperty(cx, obj.as<NativeObject>(), receiver, id, Qualified, vp, result);
}
inline bool
js::SetElement(JSContext* cx, HandleObject obj, HandleObject receiver, uint32_t index,
MutableHandleValue vp, bool strict)
MutableHandleValue vp, ObjectOpResult &result)
{
if (obj->getOps()->setProperty)
return JSObject::nonNativeSetElement(cx, obj, receiver, index, vp, strict);
return NativeSetElement(cx, obj.as<NativeObject>(), receiver, index, vp, strict);
return JSObject::nonNativeSetElement(cx, obj, receiver, index, vp, result);
return NativeSetElement(cx, obj.as<NativeObject>(), receiver, index, vp, result);
}
#endif /* vm_NativeObject_h */
+14 -18
View File
@@ -298,7 +298,7 @@ CallObject::createHollowForDebug(JSContext* cx, HandleFunction callee)
RootedScript script(cx, callee->nonLazyScript());
for (BindingIter bi(script); !bi.done(); bi++) {
id = NameToId(bi->name());
if (!SetProperty(cx, callobj, callobj, id, &optimizedOut, true))
if (!SetProperty(cx, callobj, callobj, id, &optimizedOut))
return nullptr;
}
@@ -503,10 +503,11 @@ with_LookupProperty(JSContext* cx, HandleObject obj, HandleId id,
static bool
with_DefineProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue value,
JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs)
JSPropertyOp getter, JSStrictPropertyOp 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
@@ -534,13 +535,13 @@ with_GetProperty(JSContext* cx, HandleObject obj, HandleObject receiver, HandleI
static bool
with_SetProperty(JSContext* cx, HandleObject obj, HandleObject receiver, HandleId id,
MutableHandleValue vp, bool strict)
MutableHandleValue vp, ObjectOpResult &result)
{
RootedObject actual(cx, &obj->as<DynamicWithObject>().object());
RootedObject actualReceiver(cx, receiver);
if (receiver == obj)
actualReceiver = actual;
return SetProperty(cx, actual, actualReceiver, id, vp, strict);
return SetProperty(cx, actual, actualReceiver, id, vp, result);
}
static bool
@@ -1009,7 +1010,7 @@ uninitialized_GetProperty(JSContext* cx, HandleObject obj, HandleObject receiver
static bool
uninitialized_SetProperty(JSContext* cx, HandleObject obj, HandleObject receiver, HandleId id,
MutableHandleValue vp, bool strict)
MutableHandleValue vp, ObjectOpResult &result)
{
ReportUninitializedLexicalId(cx, id);
return false;
@@ -1671,8 +1672,8 @@ class DebugScopeProxy : public BaseProxyHandler
}
}
bool set(JSContext* cx, HandleObject proxy, HandleObject receiver, HandleId id, bool strict,
MutableHandleValue vp) const override
bool set(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id,
MutableHandleValue vp, ObjectOpResult &result) const MOZ_OVERRIDE
{
Rooted<DebugScopeObject*> debugScope(cx, &proxy->as<DebugScopeObject>());
Rooted<ScopeObject*> scope(cx, &proxy->as<DebugScopeObject>().scope());
@@ -1686,16 +1687,17 @@ class DebugScopeProxy : public BaseProxyHandler
switch (access) {
case ACCESS_UNALIASED:
return true;
return result.succeed();
case ACCESS_GENERIC:
return SetProperty(cx, scope, scope, id, vp, strict);
return SetProperty(cx, scope, scope, id, vp, result);
default:
MOZ_CRASH("bad AccessResult");
}
}
bool defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
MutableHandle<PropertyDescriptor> desc) const override
MutableHandle<PropertyDescriptor> desc,
ObjectOpResult &result) const MOZ_OVERRIDE
{
Rooted<ScopeObject*> scope(cx, &proxy->as<DebugScopeObject>().scope());
@@ -1705,13 +1707,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 override
+3 -3
View File
@@ -373,7 +373,8 @@ js::intrinsic_UnsafePutElements(JSContext* cx, unsigned argc, Value* vp)
MOZ_ASSERT_IF(arrobj->is<TypedObject>(), idx < uint32_t(arrobj->as<TypedObject>().length()));
RootedValue tmp(cx, args[elemi]);
// XXX: Always non-strict.
if (!SetElement(cx, arrobj, arrobj, idx, &tmp, false))
ObjectOpResult ignored;
if (!SetElement(cx, arrobj, arrobj, idx, &tmp, ignored))
return false;
} else {
MOZ_ASSERT(idx < arrobj->as<ArrayObject>().getDenseInitializedLength());
@@ -421,8 +422,7 @@ js::intrinsic_DefineDataProperty(JSContext* cx, unsigned argc, Value* vp)
desc = PropDesc(value, writable, enumerable, configurable);
bool result;
return StandardDefineProperty(cx, obj, id, desc, true, &result);
return StandardDefineProperty(cx, obj, id, desc);
}
bool
+8 -6
View File
@@ -41,25 +41,27 @@ Shape::search(ExclusiveContext* cx, jsid id)
}
inline bool
Shape::set(JSContext* cx, HandleNativeObject obj, HandleObject receiver, bool strict,
MutableHandleValue vp)
Shape::set(JSContext* cx, HandleNativeObject obj, HandleObject receiver, MutableHandleValue vp,
ObjectOpResult &result)
{
MOZ_ASSERT_IF(hasDefaultSetter(), hasGetterValue());
MOZ_ASSERT(!obj->is<DynamicWithObject>()); // See bug 1128681.
if (attrs & JSPROP_SETTER) {
Value fval = setterValue();
return InvokeGetterOrSetter(cx, receiver, fval, 1, vp.address(), vp);
if (!InvokeGetterOrSetter(cx, receiver, fval, 1, vp.address(), vp))
return false;
return result.succeed();
}
if (attrs & JSPROP_GETTER)
return ReportGetterOnlyAssignment(cx, strict);
return result.fail(JSMSG_GETTER_ONLY);
if (!setterOp())
return true;
return result.succeed();
RootedId id(cx, propid());
return CallJSPropertyOpSetter(cx, setterOp(), obj, id, strict, vp);
return CallJSPropertyOpSetter(cx, setterOp(), obj, id, vp, result);
}
/* static */ inline Shape*
+2 -2
View File
@@ -959,8 +959,8 @@ class Shape : public gc::TenuredCell
setter() == rawSetter;
}
bool set(JSContext* cx, HandleNativeObject obj, HandleObject receiver, bool strict,
MutableHandleValue vp);
bool set(JSContext* cx, HandleNativeObject obj, HandleObject receiver, MutableHandleValue vp,
ObjectOpResult &result);
BaseShape* base() const { return base_.get(); }
+8 -7
View File
@@ -362,12 +362,13 @@ UnboxedPlainObject::obj_lookupProperty(JSContext* cx, HandleObject obj,
/* static */ bool
UnboxedPlainObject::obj_defineProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
PropertyOp getter, StrictPropertyOp 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
@@ -409,24 +410,24 @@ UnboxedPlainObject::obj_getProperty(JSContext* cx, HandleObject obj, HandleObjec
/* static */ bool
UnboxedPlainObject::obj_setProperty(JSContext* cx, HandleObject obj, HandleObject receiver,
HandleId id, MutableHandleValue vp, bool strict)
HandleId id, MutableHandleValue vp, ObjectOpResult &result)
{
const UnboxedLayout& layout = obj->as<UnboxedPlainObject>().layout();
if (const UnboxedLayout::Property* property = layout.lookup(id)) {
if (obj == receiver) {
if (obj->as<UnboxedPlainObject>().setValue(cx, *property, vp))
return true;
return result.succeed();
if (!convertToNative(cx, obj))
return false;
return SetProperty(cx, obj, receiver, id, vp, strict);
return SetProperty(cx, obj, receiver, id, vp, result);
}
return SetPropertyByDefining(cx, obj, receiver, id, vp, strict, false);
return SetPropertyByDefining(cx, obj, receiver, id, vp, false, result);
}
return SetPropertyOnProto(cx, obj, receiver, id, vp, strict);
return SetPropertyOnProto(cx, obj, receiver, id, vp, result);
}
/* static */ bool
+3 -2
View File
@@ -162,7 +162,8 @@ class UnboxedPlainObject : public JSObject
MutableHandleShape propp);
static bool obj_defineProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
ObjectOpResult &result);
static bool obj_hasProperty(JSContext* cx, HandleObject obj, HandleId id, bool* foundp);
@@ -170,7 +171,7 @@ class UnboxedPlainObject : public JSObject
HandleId id, MutableHandleValue vp);
static bool obj_setProperty(JSContext* cx, HandleObject obj, HandleObject receiver,
HandleId id, MutableHandleValue vp, bool strict);
HandleId id, MutableHandleValue vp, ObjectOpResult &result);
static bool obj_getOwnPropertyDescriptor(JSContext* cx, HandleObject obj, HandleId id,
MutableHandle<JSPropertyDescriptor> desc);
+2 -2
View File
@@ -29,11 +29,11 @@ namespace js {
*
* https://developer.mozilla.org/en-US/docs/SpiderMonkey/Internals/Bytecode
*/
static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 239;
static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 241;
static const uint32_t XDR_BYTECODE_VERSION =
uint32_t(0xb973c0de - XDR_BYTECODE_VERSION_SUBTRAHEND);
static_assert(JSErr_Limit == 371,
static_assert(JSErr_Limit == 373,
"GREETINGS, POTENTIAL SUBTRAHEND INCREMENTER! If you added or "
"removed MSG_DEFs from js.msg, you should increment "
"XDR_BYTECODE_VERSION_SUBTRAHEND and update this assertion's "
+6 -5
View File
@@ -357,13 +357,14 @@ sandbox_convert(JSContext* cx, HandleObject obj, JSType type, MutableHandleValue
static bool
writeToProto_setProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id,
bool strict, JS::MutableHandleValue vp)
JS::MutableHandleValue vp, JS::ObjectOpResult &result)
{
RootedObject proto(cx);
if (!JS_GetPrototype(cx, obj, &proto))
return false;
return JS_SetPropertyById(cx, proto, id, vp);
RootedValue receiver(cx, ObjectValue(*proto));
return JS_ForwardSetPropertyTo(cx, proto, id, vp, receiver, result);
}
static bool
@@ -738,10 +739,10 @@ bool
xpc::SandboxProxyHandler::set(JSContext* cx, JS::Handle<JSObject*> proxy,
JS::Handle<JSObject*> receiver,
JS::Handle<jsid> id,
bool strict,
JS::MutableHandle<Value> vp) const
JS::MutableHandle<Value> vp,
JS::ObjectOpResult &result) const
{
return BaseProxyHandler::set(cx, proxy, receiver, id, strict, vp);
return BaseProxyHandler::set(cx, proxy, receiver, id, vp, result);
}
bool
+3 -2
View File
@@ -659,7 +659,8 @@ static const JSFunctionSpec glob_functions[] = {
};
static bool
env_setProperty(JSContext* cx, HandleObject obj, HandleId id, bool strict, MutableHandleValue vp)
env_setProperty(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp,
ObjectOpResult &result)
{
/* XXX porting may be easy, but these don't seem to supply setenv by default */
#if !defined SOLARIS
@@ -709,7 +710,7 @@ env_setProperty(JSContext* cx, HandleObject obj, HandleId id, bool strict, Mutab
}
vp.set(STRING_TO_JSVAL(valstr));
#endif /* !defined SOLARIS */
return true;
return result.succeed();
}
static bool
+23 -21
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);
}
}
@@ -433,9 +427,10 @@ XPC_WN_OnlyIWrite_AddPropertyStub(JSContext* cx, HandleObject obj, HandleId id,
}
static bool
XPC_WN_OnlyIWrite_SetPropertyStub(JSContext* cx, HandleObject obj, HandleId id, bool strict,
MutableHandleValue vp)
XPC_WN_OnlyIWrite_SetPropertyStub(JSContext *cx, HandleObject obj, HandleId id,
MutableHandleValue vp, ObjectOpResult &result)
{
result.succeed();
return XPC_WN_OnlyIWrite_AddPropertyStub(cx, obj, id, vp);
}
@@ -454,10 +449,10 @@ XPC_WN_CantDeletePropertyStub(JSContext* cx, HandleObject obj, HandleId id,
}
static bool
XPC_WN_CannotModifyStrictPropertyStub(JSContext* cx, HandleObject obj, HandleId id, bool strict,
MutableHandleValue vp)
XPC_WN_CannotModifySetPropertyStub(JSContext *cx, HandleObject obj, HandleId id,
MutableHandleValue vp, ObjectOpResult &result)
{
return XPC_WN_CannotModifyPropertyStub(cx, obj, id, vp);
return Throw(NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN, cx);
}
static bool
@@ -713,9 +708,10 @@ XPC_WN_MaybeResolvingPropertyStub(JSContext* cx, HandleObject obj, HandleId id,
}
static bool
XPC_WN_MaybeResolvingStrictPropertyStub(JSContext* cx, HandleObject obj, HandleId id, bool strict,
MutableHandleValue vp)
XPC_WN_MaybeResolvingSetPropertyStub(JSContext *cx, HandleObject obj, HandleId id,
MutableHandleValue vp, ObjectOpResult &result)
{
result.succeed();
return XPC_WN_MaybeResolvingPropertyStub(cx, obj, id, vp);
}
@@ -753,6 +749,11 @@ XPC_WN_MaybeResolvingDeletePropertyStub(JSContext* cx, HandleObject obj, HandleI
return Throw(rv, cx); \
return retval;
#define POST_HELPER_STUB_WITH_OBJECTOPRESULT(failMethod) \
if (NS_FAILED(rv)) \
return Throw(rv, cx); \
return retval ? result.succeed() : result.failMethod();
static bool
XPC_WN_Helper_AddProperty(JSContext* cx, HandleObject obj, HandleId id,
MutableHandleValue vp)
@@ -772,12 +773,12 @@ XPC_WN_Helper_GetProperty(JSContext* cx, HandleObject obj, HandleId id,
}
bool
XPC_WN_Helper_SetProperty(JSContext* cx, HandleObject obj, HandleId id, bool strict,
MutableHandleValue vp)
XPC_WN_Helper_SetProperty(JSContext *cx, HandleObject obj, HandleId id,
MutableHandleValue vp, ObjectOpResult &result)
{
PRE_HELPER_STUB
SetProperty(wrapper, cx, obj, id, vp.address(), &retval);
POST_HELPER_STUB
POST_HELPER_STUB_WITH_OBJECTOPRESULT(failReadOnly)
}
static bool
@@ -1029,9 +1030,9 @@ XPCNativeScriptableShared::PopulateJSClass()
else if (mFlags.UseJSStubForSetProperty())
setProperty = nullptr;
else if (mFlags.AllowPropModsDuringResolve())
setProperty = XPC_WN_MaybeResolvingStrictPropertyStub;
setProperty = XPC_WN_MaybeResolvingSetPropertyStub;
else
setProperty = XPC_WN_CannotModifyStrictPropertyStub;
setProperty = XPC_WN_CannotModifySetPropertyStub;
mJSClass.base.setProperty = setProperty;
MOZ_ASSERT_IF(mFlags.WantEnumerate(), !mFlags.WantNewEnumerate());
@@ -1358,9 +1359,10 @@ XPC_WN_OnlyIWrite_Proto_AddPropertyStub(JSContext* cx, HandleObject obj, HandleI
}
static bool
XPC_WN_OnlyIWrite_Proto_SetPropertyStub(JSContext* cx, HandleObject obj, HandleId id, bool strict,
MutableHandleValue vp)
XPC_WN_OnlyIWrite_Proto_SetPropertyStub(JSContext *cx, HandleObject obj, HandleId id,
MutableHandleValue vp, ObjectOpResult &result)
{
result.succeed();
return XPC_WN_OnlyIWrite_Proto_AddPropertyStub(cx, obj, id, vp);
}
+11 -11
View File
@@ -120,14 +120,15 @@ AddonWrapper<Base>::get(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle
template<typename Base>
bool
AddonWrapper<Base>::set(JSContext* cx, JS::HandleObject wrapper, JS::HandleObject receiver,
JS::HandleId id, bool strict, JS::MutableHandleValue vp) const
JS::HandleId id, JS::MutableHandleValue vp,
JS::ObjectOpResult &result) const
{
Rooted<JSPropertyDescriptor> desc(cx);
if (!Interpose(cx, wrapper, nullptr, id, &desc))
return false;
if (!desc.object())
return Base::set(cx, wrapper, receiver, id, strict, vp);
return Base::set(cx, wrapper, receiver, id, vp, result);
if (desc.setter()) {
MOZ_ASSERT(desc.hasSetterObject());
@@ -135,27 +136,26 @@ AddonWrapper<Base>::set(JSContext* cx, JS::HandleObject wrapper, JS::HandleObjec
JS::AutoValueVector args(cx);
args.append(vp);
RootedValue fval(cx, ObjectValue(*desc.setterObject()));
return JS_CallFunctionValue(cx, receiver, fval, args, vp);
} else {
if (!strict)
return true;
js::ReportErrorWithId(cx, "unable to set interposed data property %s", id);
return false;
if (!JS_CallFunctionValue(cx, receiver, fval, args, vp))
return false;
return result.succeed();
}
return result.failCantSetInterposed();
}
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;
+4 -2
View File
@@ -28,12 +28,14 @@ class AddonWrapper : public Base {
JS::Handle<jsid> id,
JS::MutableHandle<JSPropertyDescriptor> desc) const override;
virtual bool defineProperty(JSContext* cx, JS::HandleObject proxy, JS::HandleId id,
JS::MutableHandle<JSPropertyDescriptor> desc) const 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 override;
virtual bool get(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<JSObject*> receiver,
JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp) const override;
virtual bool set(JSContext* cx, JS::HandleObject wrapper, JS::HandleObject receiver,
JS::HandleId id, bool strict, JS::MutableHandleValue vp) const override;
JS::HandleId id, JS::MutableHandleValue vp,
JS::ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool getPropertyDescriptor(JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::Handle<jsid> id,
@@ -21,21 +21,22 @@ 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
ChromeObjectWrapper::set(JSContext* cx, HandleObject wrapper,
HandleObject receiver, HandleId id,
bool strict, MutableHandleValue vp) const
MutableHandleValue vp, ObjectOpResult &result) const
{
if (!AccessCheck::checkPassToPrivilegedCode(cx, wrapper, vp))
return false;
return ChromeObjectWrapperBase::set(cx, wrapper, receiver, id, strict, vp);
return ChromeObjectWrapperBase::set(cx, wrapper, receiver, id, vp, result);
}
}
+4 -2
View File
@@ -29,10 +29,12 @@ class ChromeObjectWrapper : public ChromeObjectWrapperBase
virtual bool defineProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::Handle<jsid> id,
JS::MutableHandle<JSPropertyDescriptor> desc) const 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 override;
JS::MutableHandle<JS::Value> vp,
JS::ObjectOpResult &result) const MOZ_OVERRIDE;
static const ChromeObjectWrapper singleton;
};
+2 -1
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;
+2 -1
View File
@@ -73,7 +73,8 @@ class CrossOriginXrayWrapper : public SecurityXrayDOM {
JS::MutableHandle<JSPropertyDescriptor> desc) const override;
virtual bool defineProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::Handle<jsid> id,
JS::MutableHandle<JSPropertyDescriptor> desc) const override;
JS::MutableHandle<JSPropertyDescriptor> desc,
JS::ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool ownPropertyKeys(JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::AutoIdVector& props) const override;
virtual bool delete_(JSContext* cx, JS::Handle<JSObject*> wrapper,
+25 -55
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;
}
@@ -1190,13 +1189,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);
}
@@ -1251,14 +1244,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
@@ -1397,7 +1383,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));
@@ -1407,7 +1394,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;
@@ -1550,20 +1537,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.
@@ -1571,12 +1553,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
@@ -1874,13 +1856,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;
@@ -1967,8 +1943,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);
@@ -1990,17 +1966,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;
@@ -2025,13 +2001,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>
@@ -2080,13 +2050,13 @@ template <typename Base, typename Traits>
bool
XrayWrapper<Base, Traits>::set(JSContext* cx, HandleObject wrapper,
HandleObject receiver, HandleId id,
bool strict, MutableHandleValue vp) const
MutableHandleValue vp, ObjectOpResult &result) const
{
MOZ_ASSERT(!Traits::HasPrototype);
// Skip our Base if it isn't already BaseProxyHandler.
// NB: None of the functions we call are prepared for the receiver not
// being the wrapper, so ignore the receiver here.
return js::BaseProxyHandler::set(cx, wrapper, wrapper, id, strict, vp);
return js::BaseProxyHandler::set(cx, wrapper, wrapper, id, vp, result);
}
template <typename Base, typename Traits>
+14 -7
View File
@@ -126,7 +126,8 @@ public:
JS::MutableHandle<JSPropertyDescriptor> desc) 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) 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 override;
virtual bool defineProperty(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<jsid> id,
JS::MutableHandle<JSPropertyDescriptor> desc) const override;
JS::MutableHandle<JSPropertyDescriptor> desc,
JS::ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool ownPropertyKeys(JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::AutoIdVector& props) const override;
virtual bool delete_(JSContext* cx, JS::Handle<JSObject*> wrapper,
@@ -428,7 +433,8 @@ class XrayWrapper : public Base {
virtual bool get(JSContext* cx, JS::Handle<JSObject*> wrapper, JS::Handle<JSObject*> receiver,
JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp) const 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 override;
JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp,
JS::ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool call(JSContext* cx, JS::Handle<JSObject*> wrapper,
const JS::CallArgs& args) const override;
virtual bool construct(JSContext* cx, JS::Handle<JSObject*> wrapper,
@@ -501,7 +507,8 @@ public:
virtual bool get(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<JSObject*> receiver,
JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp) const override;
virtual bool set(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<JSObject*> receiver,
JS::Handle<jsid> id, bool strict, JS::MutableHandle<JS::Value> vp) const override;
JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp,
JS::ObjectOpResult &result) const MOZ_OVERRIDE;
virtual bool getPropertyDescriptor(JSContext* cx, JS::Handle<JSObject*> proxy,
JS::Handle<jsid> id,