Backed out 9 changesets (bug 1142775, bug 1139683, bug 1143810, bug 1142761, bug 1142784, bug 1142794, bug 1144819) for widespread bustage

CLOSED TREE

Backed out changeset 7613fc978d36 (bug 1142794)
Backed out changeset e5f0cb31263d (bug 1142784)
Backed out changeset dcd0af73ac84 (bug 1142784)
Backed out changeset 034f9c8e79ee (bug 1142784)
Backed out changeset ce0ee37e3ca9 (bug 1142775)
Backed out changeset 1519b8f2bbba (bug 1142761)
Backed out changeset 26fd55677841 (bug 1139683)
Backed out changeset 7ebc76a450c3 (bug 1144819)
Backed out changeset 92adb459d519 (bug 1143810)
This commit is contained in:
Phil Ringnalda 2015-03-22 09:34:25 -07:00
parent 735dca6f1b
commit c4745d28b1
70 changed files with 719 additions and 862 deletions

View file

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

View file

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

View file

@ -621,7 +621,7 @@ public:
virtual bool defineProperty(JSContext* cx,
JS::Handle<JSObject*> proxy,
JS::Handle<jsid> id,
JS::Handle<JSPropertyDescriptor> desc,
JS::MutableHandle<JSPropertyDescriptor> desc,
JS::ObjectOpResult &result) const override;
virtual bool ownPropertyKeys(JSContext *cx,
JS::Handle<JSObject*> proxy,
@ -643,8 +643,9 @@ public:
JS::Handle<jsid> id,
JS::MutableHandle<JS::Value> vp) const override;
virtual bool set(JSContext *cx, JS::Handle<JSObject*> proxy,
JS::Handle<jsid> id, JS::Handle<JS::Value> v,
JS::Handle<JS::Value> receiver,
JS::Handle<JSObject*> receiver,
JS::Handle<jsid> id,
JS::MutableHandle<JS::Value> vp,
JS::ObjectOpResult &result) const override;
// SpiderMonkey extensions
@ -781,7 +782,7 @@ bool
nsOuterWindowProxy::defineProperty(JSContext* cx,
JS::Handle<JSObject*> proxy,
JS::Handle<jsid> id,
JS::Handle<JSPropertyDescriptor> desc,
JS::MutableHandle<JSPropertyDescriptor> desc,
JS::ObjectOpResult &result) const
{
int32_t index = GetArrayIndexFromId(cx, id);
@ -908,9 +909,9 @@ nsOuterWindowProxy::get(JSContext *cx, JS::Handle<JSObject*> proxy,
bool
nsOuterWindowProxy::set(JSContext *cx, JS::Handle<JSObject*> proxy,
JS::Handle<JSObject*> receiver,
JS::Handle<jsid> id,
JS::Handle<JS::Value> v,
JS::Handle<JS::Value> receiver,
JS::MutableHandle<JS::Value> vp,
JS::ObjectOpResult &result) const
{
int32_t index = GetArrayIndexFromId(cx, id);
@ -920,7 +921,7 @@ nsOuterWindowProxy::set(JSContext *cx, JS::Handle<JSObject*> proxy,
return result.failReadOnly();
}
return js::Wrapper::set(cx, proxy, id, v, receiver, result);
return js::Wrapper::set(cx, proxy, receiver, id, vp, result);
}
bool

View file

@ -1439,7 +1439,7 @@ XrayResolveOwnProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
bool
XrayDefineProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
JS::Handle<JSPropertyDescriptor> desc,
JS::MutableHandle<JSPropertyDescriptor> desc,
JS::ObjectOpResult &result, bool *defined)
{
if (!js::IsProxy(obj))

View file

@ -2464,7 +2464,7 @@ XrayResolveOwnProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
bool
XrayDefineProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
JS::Handle<JSPropertyDescriptor> desc,
JS::MutableHandle<JSPropertyDescriptor> desc,
JS::ObjectOpResult &result,
bool *defined);

View file

@ -9805,7 +9805,7 @@ class CGProxySpecialOperation(CGPerSignatureCall):
false.
"""
def __init__(self, descriptor, operation, checkFound=True,
argumentHandleValue=None, resultVar=None, foundVar=None):
argumentMutableValue=None, resultVar=None, foundVar=None):
self.checkFound = checkFound
self.foundVar = foundVar or "found"
@ -9830,12 +9830,12 @@ class CGProxySpecialOperation(CGPerSignatureCall):
treatNullAs=argument.treatNullAs,
sourceDescription=("value being assigned to %s setter" %
descriptor.interface.identifier.name))
if argumentHandleValue is None:
argumentHandleValue = "desc.value()"
if argumentMutableValue is None:
argumentMutableValue = "desc.value()"
templateValues = {
"declName": argument.identifier.name,
"holderName": argument.identifier.name + "_holder",
"val": argumentHandleValue,
"val": argumentMutableValue,
"obj": "obj",
"passedToJSImpl": "false"
}
@ -9880,10 +9880,10 @@ class CGProxyIndexedOperation(CGProxySpecialOperation):
foundVar: See the docstring for CGProxySpecialOperation.
"""
def __init__(self, descriptor, name, doUnwrap=True, checkFound=True,
argumentHandleValue=None, resultVar=None, foundVar=None):
argumentMutableValue=None, resultVar=None, foundVar=None):
self.doUnwrap = doUnwrap
CGProxySpecialOperation.__init__(self, descriptor, name, checkFound,
argumentHandleValue=argumentHandleValue,
argumentMutableValue=argumentMutableValue,
resultVar=resultVar,
foundVar=foundVar)
@ -9941,9 +9941,9 @@ class CGProxyIndexedSetter(CGProxyIndexedOperation):
"""
Class to generate a call to an indexed setter.
"""
def __init__(self, descriptor, argumentHandleValue=None):
def __init__(self, descriptor, argumentMutableValue=None):
CGProxyIndexedOperation.__init__(self, descriptor, 'IndexedSetter',
argumentHandleValue=argumentHandleValue)
argumentMutableValue=argumentMutableValue)
class CGProxyIndexedDeleter(CGProxyIndexedOperation):
@ -9971,10 +9971,10 @@ class CGProxyNamedOperation(CGProxySpecialOperation):
foundVar: See the docstring for CGProxySpecialOperation.
"""
def __init__(self, descriptor, name, value=None, argumentHandleValue=None,
def __init__(self, descriptor, name, value=None, argumentMutableValue=None,
resultVar=None, foundVar=None):
CGProxySpecialOperation.__init__(self, descriptor, name,
argumentHandleValue=argumentHandleValue,
argumentMutableValue=argumentMutableValue,
resultVar=resultVar,
foundVar=foundVar)
self.value = value
@ -10072,9 +10072,9 @@ class CGProxyNamedSetter(CGProxyNamedOperation):
"""
Class to generate a call to a named setter.
"""
def __init__(self, descriptor, argumentHandleValue=None):
def __init__(self, descriptor, argumentMutableValue=None):
CGProxyNamedOperation.__init__(self, descriptor, 'NamedSetter',
argumentHandleValue=argumentHandleValue)
argumentMutableValue=argumentMutableValue)
class CGProxyNamedDeleter(CGProxyNamedOperation):
@ -10244,7 +10244,7 @@ class CGDOMJSProxyHandler_defineProperty(ClassMethod):
args = [Argument('JSContext*', 'cx'),
Argument('JS::Handle<JSObject*>', 'proxy'),
Argument('JS::Handle<jsid>', 'id'),
Argument('JS::Handle<JSPropertyDescriptor>', 'desc'),
Argument('JS::MutableHandle<JSPropertyDescriptor>', 'desc'),
Argument('JS::ObjectOpResult&', 'opresult'),
Argument('bool*', 'defined')]
ClassMethod.__init__(self, "defineProperty", "bool", args, virtual=True, override=True, const=True)
@ -10691,7 +10691,7 @@ class CGDOMJSProxyHandler_setCustom(ClassMethod):
args = [Argument('JSContext*', 'cx'),
Argument('JS::Handle<JSObject*>', 'proxy'),
Argument('JS::Handle<jsid>', 'id'),
Argument('JS::Handle<JS::Value>', 'v'),
Argument('JS::MutableHandle<JS::Value>', 'vp'),
Argument('bool*', 'done')]
ClassMethod.__init__(self, "setCustom", "bool", args, virtual=True, override=True, const=True)
self.descriptor = descriptor
@ -10716,7 +10716,7 @@ class CGDOMJSProxyHandler_setCustom(ClassMethod):
raise ValueError("In interface " + self.descriptor.name + ": " +
"Can't cope with [OverrideBuiltins] and unforgeable members")
callSetter = CGProxyNamedSetter(self.descriptor, argumentHandleValue="v")
callSetter = CGProxyNamedSetter(self.descriptor, argumentMutableValue="vp")
return (assertion +
callSetter.define() +
"*done = true;\n"
@ -10741,7 +10741,7 @@ class CGDOMJSProxyHandler_setCustom(ClassMethod):
""",
callSetter=CGProxyIndexedSetter(self.descriptor,
argumentHandleValue="v").define())
argumentMutableValue="vp").define())
else:
setIndexed = ""

View file

@ -195,7 +195,7 @@ BaseDOMProxyHandler::getOwnPropertyDescriptor(JSContext* cx,
bool
DOMProxyHandler::defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
Handle<JSPropertyDescriptor> desc,
MutableHandle<JSPropertyDescriptor> desc,
JS::ObjectOpResult &result, bool *defined) const
{
if (desc.hasGetterObject() && desc.setter() == JS_StrictPropertyStub) {
@ -219,14 +219,13 @@ DOMProxyHandler::defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::
}
bool
DOMProxyHandler::set(JSContext *cx, Handle<JSObject*> proxy, Handle<jsid> id,
Handle<JS::Value> v, Handle<JS::Value> receiver,
ObjectOpResult &result) const
DOMProxyHandler::set(JSContext *cx, Handle<JSObject*> proxy, Handle<JSObject*> receiver,
Handle<jsid> id, MutableHandle<JS::Value> vp, ObjectOpResult &result) const
{
MOZ_ASSERT(!xpc::WrapperFactory::IsXrayWrapper(proxy),
"Should not have a XrayWrapper here");
bool done;
if (!setCustom(cx, proxy, id, v, &done)) {
if (!setCustom(cx, proxy, id, vp, &done)) {
return false;
}
if (done) {
@ -253,7 +252,7 @@ DOMProxyHandler::set(JSContext *cx, Handle<JSObject*> proxy, Handle<jsid> id,
}
}
return js::SetPropertyIgnoringNamedGetter(cx, proxy, id, v, receiver, desc, result);
return js::SetPropertyIgnoringNamedGetter(cx, proxy, id, vp, receiver, &desc, result);
}
bool
@ -351,7 +350,7 @@ IdToInt32(JSContext* cx, JS::Handle<jsid> id)
bool
DOMProxyHandler::setCustom(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
JS::Handle<JS::Value> v, bool *done) const
JS::MutableHandle<JS::Value> vp, bool *done) const
{
*done = false;
return true;

View file

@ -105,14 +105,14 @@ public:
{}
bool defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
JS::Handle<JSPropertyDescriptor> desc,
JS::MutableHandle<JSPropertyDescriptor> desc,
JS::ObjectOpResult &result) const override
{
bool unused;
return defineProperty(cx, proxy, id, desc, result, &unused);
}
virtual bool defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
JS::Handle<JSPropertyDescriptor> desc,
JS::MutableHandle<JSPropertyDescriptor> desc,
JS::ObjectOpResult &result, bool *defined) const;
bool delete_(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
JS::ObjectOpResult &result) const override;
@ -122,8 +122,8 @@ public:
const override;
bool has(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
bool* bp) const override;
bool set(JSContext *cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
JS::Handle<JS::Value> v, JS::Handle<JS::Value> receiver, JS::ObjectOpResult &result)
bool set(JSContext *cx, JS::Handle<JSObject*> proxy, JS::Handle<JSObject*> receiver,
JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp, JS::ObjectOpResult &result)
const override;
/*
@ -132,7 +132,7 @@ public:
* *done to false.
*/
virtual bool setCustom(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
JS::Handle<JS::Value> v, bool *done) const;
JS::MutableHandle<JS::Value> vp, bool *done) const;
static JSObject* GetExpandoObject(JSObject* obj);

View file

@ -71,9 +71,10 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base
ReturnStatus *rs, JSVariant *result) {
return Answer::RecvGet(ObjectId::deserialize(objId), receiverVar, id, rs, result);
}
bool RecvSet(const uint64_t &objId, const JSIDVariant &id, const JSVariant &value,
const JSVariant &receiverVar, ReturnStatus *rs) {
return Answer::RecvSet(ObjectId::deserialize(objId), id, value, receiverVar, rs);
bool RecvSet(const uint64_t &objId, const ObjectVariant &receiverVar,
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,
@ -160,9 +161,10 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base
ReturnStatus *rs, JSVariant *result) {
return Base::SendGet(objId.serialize(), receiverVar, id, rs, result);
}
bool SendSet(const ObjectId &objId, const JSIDVariant &id, const JSVariant &value,
const JSVariant &receiverVar, ReturnStatus *rs) {
return Base::SendSet(objId.serialize(), id, value, receiverVar, rs);
bool SendSet(const ObjectId &objId, const ObjectVariant &receiverVar,
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,

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, JSIDVariant id, JSVariant value, JSVariant receiver) returns (ReturnStatus rs);
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);

View file

@ -308,17 +308,26 @@ WrapperAnswer::RecvGet(const ObjectId &objId, const ObjectVariant &receiverVar,
}
bool
WrapperAnswer::RecvSet(const ObjectId &objId, const JSIDVariant &idVar, const JSVariant &value,
const JSVariant &receiverVar, ReturnStatus *rs)
WrapperAnswer::RecvSet(const ObjectId &objId, const ObjectVariant &receiverVar,
const JSIDVariant &idVar, const JSVariant &value, ReturnStatus *rs,
JSVariant *resultValue)
{
// We may run scripted setters.
AutoEntryScript aes(xpc::NativeGlobal(scopeForTargetObjects()));
JSContext *cx = aes.cx();
// The outparam will be written to the buffer, so it must be set even if
// the parent won't read it.
*resultValue = UndefinedVariant();
RootedObject obj(cx, findObjectById(cx, objId));
if (!obj)
return fail(cx, rs);
RootedObject receiver(cx, fromObjectVariant(cx, receiverVar));
if (!receiver)
return fail(cx, rs);
LOG("set %s[%s] = %s", ReceiverObj(objId), Identifier(idVar), InVariant(value));
RootedId id(cx);
@ -329,12 +338,12 @@ WrapperAnswer::RecvSet(const ObjectId &objId, const JSIDVariant &idVar, const JS
if (!fromVariant(cx, value, &val))
return fail(cx, rs);
RootedValue receiver(cx);
if (!fromVariant(cx, receiverVar, &receiver))
ObjectOpResult result;
RootedValue receiverVal(cx, ObjectValue(*receiver));
if (!JS_ForwardSetPropertyTo(cx, obj, id, val, receiverVal, result))
return fail(cx, rs);
ObjectOpResult result;
if (!JS_ForwardSetPropertyTo(cx, obj, id, val, receiver, result))
if (!toVariant(cx, val, resultValue))
return fail(cx, rs);
return ok(rs, result);

View file

@ -37,8 +37,9 @@ class WrapperAnswer : public virtual JavaScriptShared
bool RecvGet(const ObjectId &objId, const ObjectVariant &receiverVar,
const JSIDVariant &id,
ReturnStatus *rs, JSVariant *result);
bool RecvSet(const ObjectId &objId, const JSIDVariant &id, const JSVariant &value,
const JSVariant &receiverVar, ReturnStatus *rs);
bool RecvSet(const ObjectId &objId, const ObjectVariant &receiverVar,
const JSIDVariant &id, const JSVariant &value, ReturnStatus *rs,
JSVariant *result);
bool RecvIsExtensible(const ObjectId &objId, ReturnStatus *rs,
bool *result);

View file

@ -97,7 +97,7 @@ 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,
Handle<JSPropertyDescriptor> desc,
MutableHandle<JSPropertyDescriptor> desc,
ObjectOpResult &result) const override;
virtual bool ownPropertyKeys(JSContext *cx, HandleObject proxy,
AutoIdVector &props) const override;
@ -110,8 +110,9 @@ class CPOWProxyHandler : public BaseProxyHandler
virtual bool has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const override;
virtual bool get(JSContext *cx, HandleObject proxy, HandleObject receiver,
HandleId id, MutableHandleValue vp) const override;
virtual bool set(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, JS::HandleValue v,
JS::HandleValue receiver, JS::ObjectOpResult &result) const override;
virtual bool set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
JS::HandleId id, JS::MutableHandleValue vp,
JS::ObjectOpResult &result) const 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;
@ -212,7 +213,7 @@ WrapperOwner::getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, Handle
bool
CPOWProxyHandler::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
Handle<JSPropertyDescriptor> desc,
MutableHandle<JSPropertyDescriptor> desc,
ObjectOpResult &result) const
{
FORWARD(defineProperty, (cx, proxy, id, desc, result));
@ -220,7 +221,7 @@ CPOWProxyHandler::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
bool
WrapperOwner::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
Handle<JSPropertyDescriptor> desc,
MutableHandle<JSPropertyDescriptor> desc,
ObjectOpResult &result)
{
ObjectId objId = idOf(proxy);
@ -516,37 +517,41 @@ WrapperOwner::get(JSContext *cx, HandleObject proxy, HandleObject receiver,
}
bool
CPOWProxyHandler::set(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, JS::HandleValue v,
JS::HandleValue receiver, JS::ObjectOpResult &result) const
CPOWProxyHandler::set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
JS::HandleId id, JS::MutableHandleValue vp, JS::ObjectOpResult &result) const
{
FORWARD(set, (cx, proxy, id, v, receiver, result));
FORWARD(set, (cx, proxy, receiver, id, vp, result));
}
bool
WrapperOwner::set(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, JS::HandleValue v,
JS::HandleValue receiver, JS::ObjectOpResult &result)
WrapperOwner::set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
JS::HandleId id, JS::MutableHandleValue vp, JS::ObjectOpResult &result)
{
ObjectId objId = idOf(proxy);
ObjectVariant receiverVar;
if (!toObjectVariant(cx, receiver, &receiverVar))
return false;
JSIDVariant idVar;
if (!toJSIDVariant(cx, id, &idVar))
return false;
JSVariant val;
if (!toVariant(cx, v, &val))
return false;
JSVariant receiverVar;
if (!toVariant(cx, receiver, &receiverVar))
if (!toVariant(cx, vp, &val))
return false;
ReturnStatus status;
if (!SendSet(objId, idVar, val, receiverVar, &status))
JSVariant resultValue;
if (!SendSet(objId, receiverVar, idVar, val, &status, &resultValue))
return ipcfail(cx);
LOG_STACK();
return ok(cx, status, result);
if (!ok(cx, status, result))
return false;
return fromVariant(cx, resultValue, vp);
}
bool

View file

@ -32,7 +32,7 @@ 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::Handle<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,
@ -42,8 +42,8 @@ class WrapperOwner : public virtual JavaScriptShared
bool has(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp);
bool get(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
JS::HandleId id, JS::MutableHandleValue vp);
bool set(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, JS::HandleValue v,
JS::HandleValue receiver, JS::ObjectOpResult &result);
bool set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
JS::HandleId id, JS::MutableHandleValue vp, JS::ObjectOpResult &result);
bool callOrConstruct(JSContext *cx, JS::HandleObject proxy, const JS::CallArgs &args,
bool construct);
@ -128,8 +128,9 @@ class WrapperOwner : public virtual JavaScriptShared
virtual bool SendGet(const ObjectId &objId, const ObjectVariant &receiverVar,
const JSIDVariant &id,
ReturnStatus *rs, JSVariant *result) = 0;
virtual bool SendSet(const ObjectId &objId, const JSIDVariant &id, const JSVariant &value,
const JSVariant &receiverVar, ReturnStatus *rs) = 0;
virtual bool SendSet(const ObjectId &objId, const ObjectVariant &receiverVar,
const JSIDVariant &id, const JSVariant &value,
ReturnStatus *rs, JSVariant *result) = 0;
virtual bool SendIsExtensible(const ObjectId &objId, ReturnStatus *rs,
bool *result) = 0;

View file

@ -333,8 +333,8 @@ typedef bool
(* LookupPropertyOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
JS::MutableHandleObject objp, JS::MutableHandle<Shape*> propp);
typedef bool
(* DefinePropertyOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
JS::Handle<JSPropertyDescriptor> desc,
(* DefinePropertyOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue value,
JSGetterOp getter, JSSetterOp setter, unsigned attrs,
JS::ObjectOpResult &result);
typedef bool
(* HasPropertyOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id, bool *foundp);
@ -342,8 +342,8 @@ typedef bool
(* GetPropertyOp)(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver, JS::HandleId id,
JS::MutableHandleValue vp);
typedef bool
(* SetPropertyOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue v,
JS::HandleValue receiver, JS::ObjectOpResult &result);
(* SetPropertyOp)(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver, JS::HandleId id,
JS::MutableHandleValue vp, JS::ObjectOpResult &result);
typedef bool
(* GetOwnPropertyOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
JS::MutableHandle<JSPropertyDescriptor> desc);

View file

@ -18,7 +18,6 @@ namespace js {
using JS::AutoIdVector;
using JS::CallArgs;
using JS::Handle;
using JS::HandleId;
using JS::HandleObject;
using JS::HandleValue;
@ -253,7 +252,7 @@ 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,
Handle<JSPropertyDescriptor> desc,
MutableHandle<JSPropertyDescriptor> desc,
ObjectOpResult &result) const = 0;
virtual bool ownPropertyKeys(JSContext *cx, HandleObject proxy,
AutoIdVector &props) const = 0;
@ -295,8 +294,8 @@ class JS_FRIEND_API(BaseProxyHandler)
virtual bool has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const;
virtual bool get(JSContext *cx, HandleObject proxy, HandleObject receiver,
HandleId id, MutableHandleValue vp) const;
virtual bool set(JSContext *cx, HandleObject proxy, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult &result) const;
virtual bool set(JSContext *cx, HandleObject proxy, HandleObject receiver,
HandleId id, MutableHandleValue vp, ObjectOpResult &result) const;
/*
* [[Call]] and [[Construct]] are standard internal methods but according
@ -374,7 +373,7 @@ class JS_FRIEND_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,
Handle<JSPropertyDescriptor> desc,
MutableHandle<JSPropertyDescriptor> desc,
ObjectOpResult &result) const override;
virtual bool ownPropertyKeys(JSContext *cx, HandleObject proxy,
AutoIdVector &props) const override;
@ -395,8 +394,9 @@ class JS_FRIEND_API(DirectProxyHandler) : public BaseProxyHandler
bool *bp) const override;
virtual bool get(JSContext *cx, HandleObject proxy, HandleObject receiver,
HandleId id, MutableHandleValue vp) const override;
virtual bool set(JSContext *cx, HandleObject proxy, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult &result) const override;
virtual bool set(JSContext *cx, HandleObject proxy, HandleObject receiver,
HandleId id, MutableHandleValue vp,
ObjectOpResult &result) const 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;

View file

@ -1751,8 +1751,8 @@ ReportPropertyError(JSContext *cx,
}
bool
TypedObject::obj_defineProperty(JSContext *cx, HandleObject obj, HandleId id,
Handle<JSPropertyDescriptor> desc,
TypedObject::obj_defineProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
GetterOp getter, SetterOp setter, unsigned attrs,
ObjectOpResult &result)
{
Rooted<TypedObject *> typedObj(cx, &obj->as<TypedObject>());
@ -1904,8 +1904,8 @@ TypedObject::obj_getArrayElement(JSContext *cx,
}
bool
TypedObject::obj_setProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult &result)
TypedObject::obj_setProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id,
MutableHandleValue vp, ObjectOpResult &result)
{
Rooted<TypedObject *> typedObj(cx, &obj->as<TypedObject>());
@ -1919,7 +1919,7 @@ TypedObject::obj_setProperty(JSContext *cx, HandleObject obj, HandleId id, Handl
case type::Array: {
if (JSID_IS_ATOM(id, cx->names().length)) {
if (receiver.isObject() && obj == &receiver.toObject()) {
if (obj == receiver) {
JS_ReportErrorNumber(cx, GetErrorMessage,
nullptr, JSMSG_CANT_REDEFINE_ARRAY_LENGTH);
return false;
@ -1929,8 +1929,8 @@ TypedObject::obj_setProperty(JSContext *cx, HandleObject obj, HandleId id, Handl
uint32_t index;
if (IdIsIndex(id, &index)) {
if (!receiver.isObject() || obj != &receiver.toObject())
return SetPropertyByDefining(cx, obj, id, v, receiver, false, result);
if (obj != receiver)
return SetPropertyByDefining(cx, obj, receiver, id, vp, false, result);
if (index >= uint32_t(typedObj->length())) {
JS_ReportErrorNumber(cx, GetErrorMessage,
@ -1941,7 +1941,7 @@ TypedObject::obj_setProperty(JSContext *cx, HandleObject obj, HandleId id, Handl
Rooted<TypeDescr*> elementType(cx);
elementType = &typedObj->typeDescr().as<ArrayTypeDescr>().elementType();
size_t offset = elementType->size() * index;
if (!ConvertAndCopyTo(cx, elementType, typedObj, offset, NullPtr(), v))
if (!ConvertAndCopyTo(cx, elementType, typedObj, offset, NullPtr(), vp))
return false;
return result.succeed();
}
@ -1955,19 +1955,19 @@ TypedObject::obj_setProperty(JSContext *cx, HandleObject obj, HandleId id, Handl
if (!descr->fieldIndex(id, &fieldIndex))
break;
if (!receiver.isObject() || obj != &receiver.toObject())
return SetPropertyByDefining(cx, obj, id, v, receiver, false, result);
if (obj != receiver)
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));
if (!ConvertAndCopyTo(cx, fieldType, typedObj, offset, fieldName, v))
if (!ConvertAndCopyTo(cx, fieldType, typedObj, offset, fieldName, vp))
return false;
return result.succeed();
}
}
return SetPropertyOnProto(cx, obj, id, v, receiver, result);
return SetPropertyOnProto(cx, obj, receiver, id, vp, result);
}
bool

View file

@ -528,8 +528,8 @@ class TypedObject : public JSObject
static bool obj_lookupElement(JSContext *cx, HandleObject obj, uint32_t index,
MutableHandleObject objp, MutableHandleShape propp);
static bool obj_defineProperty(JSContext *cx, HandleObject obj, HandleId id,
Handle<JSPropertyDescriptor> desc,
static bool obj_defineProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
GetterOp getter, SetterOp setter, unsigned attrs,
ObjectOpResult &result);
static bool obj_hasProperty(JSContext *cx, HandleObject obj, HandleId id, bool *foundp);
@ -540,8 +540,8 @@ class TypedObject : public JSObject
static bool obj_getElement(JSContext *cx, HandleObject obj, HandleObject receiver,
uint32_t index, MutableHandleValue vp);
static bool obj_setProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult &result);
static bool obj_setProperty(JSContext *cx, HandleObject obj, HandleObject receiver,
HandleId id, MutableHandleValue vp, ObjectOpResult &result);
static bool obj_getOwnPropertyDescriptor(JSContext *cx, HandleObject obj, HandleId id,
MutableHandle<JSPropertyDescriptor> desc);

View file

@ -8364,7 +8364,7 @@ DoSetPropFallback(JSContext *cx, BaselineFrame *frame, ICSetProp_Fallback *stub_
MOZ_ASSERT(op == JSOP_SETPROP || op == JSOP_STRICTSETPROP);
RootedValue v(cx, rhs);
if (!PutProperty(cx, obj, id, v, op == JSOP_STRICTSETPROP))
if (!PutProperty(cx, obj, id, &v, op == JSOP_STRICTSETPROP))
return false;
}

View file

@ -429,6 +429,7 @@ bool
SetProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value,
bool strict, jsbytecode *pc)
{
RootedValue v(cx, value);
RootedId id(cx, NameToId(name));
JSOp op = JSOp(*pc);
@ -442,21 +443,21 @@ SetProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValu
return true;
}
RootedValue receiver(cx, ObjectValue(*obj));
ObjectOpResult result;
if (MOZ_LIKELY(!obj->getOps()->setProperty)) {
if (!NativeSetProperty(
cx, obj.as<NativeObject>(), id, value, receiver,
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, id, value, receiver, result))
if (!SetProperty(cx, obj, obj, id, &v, result))
return false;
}
return result.checkStrictErrorOrWarning(cx, obj, id, strict);

View file

@ -82,7 +82,6 @@ MSG_DEF(JSMSG_EMPTY_ARRAY_REDUCE, 0, JSEXN_TYPEERR, "reduce of empty array
MSG_DEF(JSMSG_UNEXPECTED_TYPE, 2, JSEXN_TYPEERR, "{0} is {1}")
MSG_DEF(JSMSG_MISSING_FUN_ARG, 2, JSEXN_TYPEERR, "missing argument {0} when calling function {1}")
MSG_DEF(JSMSG_NOT_NONNULL_OBJECT, 1, JSEXN_TYPEERR, "{0} is not a non-null object")
MSG_DEF(JSMSG_SET_NON_OBJECT_RECEIVER, 1, JSEXN_TYPEERR, "can't assign to properties of {0}: not an 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}")

View file

@ -27,13 +27,13 @@ class CustomProxyHandler : public DirectProxyHandler {
return impl(cx, proxy, id, desc, true);
}
bool set(JSContext *cx, HandleObject proxy, HandleId id, HandleValue v, HandleValue receiver,
ObjectOpResult &result) const override
bool set(JSContext *cx, HandleObject proxy, HandleObject receiver,
HandleId id, MutableHandleValue vp, ObjectOpResult &result) const override
{
Rooted<JSPropertyDescriptor> desc(cx);
if (!DirectProxyHandler::getPropertyDescriptor(cx, proxy, id, &desc))
return false;
return SetPropertyIgnoringNamedGetter(cx, proxy, id, v, receiver, desc, result);
return SetPropertyIgnoringNamedGetter(cx, proxy, id, vp, receiver, &desc, result);
}
private:

View file

@ -147,7 +147,7 @@ JS::ObjectOpResult::reportStrictErrorOrWarning(JSContext *cx, HandleObject obj,
MOZ_ASSERT(!ok());
unsigned flags = strict ? JSREPORT_ERROR : (JSREPORT_WARNING | JSREPORT_STRICT);
if (code_ == JSMSG_OBJECT_NOT_EXTENSIBLE || code_ == JSMSG_SET_NON_OBJECT_RECEIVER) {
if (code_ == JSMSG_OBJECT_NOT_EXTENSIBLE) {
RootedValue val(cx, ObjectValue(*obj));
return ReportValueErrorFlags(cx, flags, code_, JSDVG_IGNORE_STACK, val,
NullPtr(), nullptr, nullptr);
@ -2205,12 +2205,10 @@ DefinePropertyById(JSContext *cx, HandleObject obj, HandleId id, HandleValue val
// it's just a plain old data property. However the JS_Define* APIs use
// null getter and setter to mean "default to the Class getProperty and
// setProperty ops".
if (!(attrs & (JSPROP_GETTER | JSPROP_SETTER))) {
if (!getter)
getter = obj->getClass()->getProperty;
if (!setter)
setter = obj->getClass()->setProperty;
}
if (!getter)
getter = obj->getClass()->getProperty;
if (!setter)
setter = obj->getClass()->setProperty;
if (getter == JS_PropertyStub)
getter = nullptr;
if (setter == JS_StrictPropertyStub)
@ -2830,13 +2828,13 @@ JS_GetUCProperty(JSContext *cx, HandleObject obj, const char16_t *name, size_t n
JS_PUBLIC_API(bool)
JS_SetPropertyById(JSContext *cx, HandleObject obj, HandleId id, HandleValue v)
{
RootedValue value(cx, v);
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, id);
RootedValue receiver(cx, ObjectValue(*obj));
ObjectOpResult ignored;
return SetProperty(cx, obj, id, v, receiver, ignored);
return SetProperty(cx, obj, obj, id, &value, ignored);
}
JS_PUBLIC_API(bool)
@ -2847,60 +2845,66 @@ JS_ForwardSetPropertyTo(JSContext *cx, HandleObject obj, HandleId id, HandleValu
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, id, receiver);
return SetProperty(cx, obj, id, v, receiver, result);
// XXX Bug 603201 will eliminate this ToObject.
RootedObject receiverObj(cx, ToObject(cx, receiver));
if (!receiverObj)
return false;
RootedValue value(cx, v);
return SetProperty(cx, obj, receiverObj, id, &value, result);
}
static bool
SetElement(JSContext *cx, HandleObject obj, uint32_t index, HandleValue v)
SetElement(JSContext *cx, HandleObject obj, uint32_t index, MutableHandleValue vp)
{
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, v);
assertSameCompartment(cx, obj, vp);
RootedValue receiver(cx, ObjectValue(*obj));
ObjectOpResult ignored;
return SetElement(cx, obj, index, v, receiver, ignored);
return SetElement(cx, obj, obj, index, vp, ignored);
}
JS_PUBLIC_API(bool)
JS_SetElement(JSContext *cx, HandleObject obj, uint32_t index, HandleValue v)
{
return SetElement(cx, obj, index, v);
RootedValue value(cx, v);
return SetElement(cx, obj, index, &value);
}
JS_PUBLIC_API(bool)
JS_SetElement(JSContext *cx, HandleObject obj, uint32_t index, HandleObject v)
{
RootedValue value(cx, ObjectOrNullValue(v));
return SetElement(cx, obj, index, value);
return SetElement(cx, obj, index, &value);
}
JS_PUBLIC_API(bool)
JS_SetElement(JSContext *cx, HandleObject obj, uint32_t index, HandleString v)
{
RootedValue value(cx, StringValue(v));
return SetElement(cx, obj, index, value);
return SetElement(cx, obj, index, &value);
}
JS_PUBLIC_API(bool)
JS_SetElement(JSContext *cx, HandleObject obj, uint32_t index, int32_t v)
{
RootedValue value(cx, NumberValue(v));
return SetElement(cx, obj, index, value);
return SetElement(cx, obj, index, &value);
}
JS_PUBLIC_API(bool)
JS_SetElement(JSContext *cx, HandleObject obj, uint32_t index, uint32_t v)
{
RootedValue value(cx, NumberValue(v));
return SetElement(cx, obj, index, value);
return SetElement(cx, obj, index, &value);
}
JS_PUBLIC_API(bool)
JS_SetElement(JSContext *cx, HandleObject obj, uint32_t index, double v)
{
RootedValue value(cx, NumberValue(v));
return SetElement(cx, obj, index, value);
return SetElement(cx, obj, index, &value);
}
JS_PUBLIC_API(bool)

View file

@ -2600,18 +2600,6 @@ class MutablePropertyDescriptorOperations : public PropertyDescriptorOperations<
value().setUndefined();
}
void initFields(HandleObject obj, HandleValue v, unsigned attrs,
JSGetterOp getterOp, JSSetterOp setterOp) {
MOZ_ASSERT(getterOp != JS_PropertyStub);
MOZ_ASSERT(setterOp != JS_StrictPropertyStub);
object().set(obj);
value().set(v);
setAttributes(attrs);
setGetter(getterOp);
setSetter(setterOp);
}
void assign(JSPropertyDescriptor &other) {
object().set(other.obj);
setAttributes(other.attrs);

View file

@ -364,7 +364,8 @@ SetArrayElement(JSContext *cx, HandleObject obj, double index, HandleValue v)
if (!ToId(cx, index, &id))
return false;
return SetProperty(cx, obj, id, v);
RootedValue tmp(cx, v);
return SetProperty(cx, obj, obj, id, &tmp);
}
/*
@ -433,7 +434,7 @@ bool
js::SetLengthProperty(JSContext *cx, HandleObject obj, double length)
{
RootedValue v(cx, NumberValue(length));
return SetProperty(cx, obj, cx->names().length, v);
return SetProperty(cx, obj, obj, cx->names().length, &v);
}
/*
@ -1269,10 +1270,11 @@ InitArrayElements(JSContext *cx, HandleObject obj, uint32_t start, uint32_t coun
do {
value = *vector++;
indexv = DoubleValue(index);
if (!ValueToId<CanGC>(cx, indexv, &id))
return false;
if (!SetProperty(cx, obj, id, value))
if (!ValueToId<CanGC>(cx, indexv, &id) ||
!SetProperty(cx, obj, obj, id, &value))
{
return false;
}
index += 1;
} while (vector != end);

View file

@ -332,6 +332,26 @@ CallJSDeletePropertyOp(JSContext *cx, JSDeletePropertyOp op, HandleObject receiv
return result.succeed();
}
inline bool
CallSetter(JSContext *cx, HandleObject obj, HandleId id, SetterOp op, unsigned attrs,
MutableHandleValue vp, ObjectOpResult &result)
{
if (attrs & JSPROP_SETTER) {
RootedValue opv(cx, CastAsObjectJsval(op));
if (!InvokeGetterOrSetter(cx, obj, opv, 1, vp.address(), vp))
return false;
return result.succeed();
}
if (attrs & JSPROP_GETTER)
return result.fail(JSMSG_GETTER_ONLY);
if (!op)
return result.succeed();
return CallJSSetterOp(cx, op, obj, id, vp, result);
}
inline uintptr_t
GetNativeStackLimit(ExclusiveContext *cx)
{

View file

@ -359,8 +359,8 @@ extern JS_FRIEND_API(bool)
proxy_LookupProperty(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleObject objp,
JS::MutableHandle<Shape*> propp);
extern JS_FRIEND_API(bool)
proxy_DefineProperty(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
JS::Handle<JSPropertyDescriptor> desc,
proxy_DefineProperty(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue value,
JSGetterOp getter, JSSetterOp setter, unsigned attrs,
JS::ObjectOpResult &result);
extern JS_FRIEND_API(bool)
proxy_HasProperty(JSContext *cx, JS::HandleObject obj, JS::HandleId id, bool *foundp);
@ -368,8 +368,8 @@ extern JS_FRIEND_API(bool)
proxy_GetProperty(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver, JS::HandleId id,
JS::MutableHandleValue vp);
extern JS_FRIEND_API(bool)
proxy_SetProperty(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleValue bp,
JS::HandleValue receiver, JS::ObjectOpResult &result);
proxy_SetProperty(JSContext *cx, JS::HandleObject obj, JS::HandleObject receiver, JS::HandleId id,
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);
@ -2632,8 +2632,8 @@ ForwardToNative(JSContext *cx, JSNative native, const JS::CallArgs &args);
*/
JS_FRIEND_API(bool)
SetPropertyIgnoringNamedGetter(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
JS::HandleValue v, JS::HandleValue receiver,
JS::Handle<JSPropertyDescriptor> ownDesc,
JS::MutableHandleValue vp, JS::HandleObject receiver,
JS::MutableHandle<JSPropertyDescriptor> ownDesc,
JS::ObjectOpResult &result);
JS_FRIEND_API(void)

View file

@ -689,7 +689,7 @@ js::StandardDefineProperty(JSContext *cx, HandleObject obj, HandleId id,
if (obj->is<ProxyObject>()) {
Rooted<PropertyDescriptor> pd(cx, desc);
pd.object().set(obj);
return Proxy::defineProperty(cx, obj, id, pd, result);
return Proxy::defineProperty(cx, obj, id, &pd, result);
}
return result.fail(JSMSG_OBJECT_NOT_EXTENSIBLE);
}
@ -1584,26 +1584,25 @@ js::CreateThisForFunction(JSContext *cx, HandleObject callee, NewObjectKind newK
}
/* static */ bool
JSObject::nonNativeSetProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult &result)
JSObject::nonNativeSetProperty(JSContext *cx, HandleObject obj, HandleObject receiver,
HandleId id, MutableHandleValue vp, ObjectOpResult &result)
{
RootedValue value(cx, v);
if (MOZ_UNLIKELY(obj->watched())) {
WatchpointMap *wpmap = cx->compartment()->watchpointMap;
if (wpmap && !wpmap->triggerWatchpoint(cx, obj, id, &value))
if (wpmap && !wpmap->triggerWatchpoint(cx, obj, id, vp))
return false;
}
return obj->getOps()->setProperty(cx, obj, id, value, receiver, result);
return obj->getOps()->setProperty(cx, obj, receiver, id, vp, result);
}
/* static */ bool
JSObject::nonNativeSetElement(JSContext *cx, HandleObject obj, uint32_t index, HandleValue v,
HandleValue receiver, ObjectOpResult &result)
JSObject::nonNativeSetElement(JSContext *cx, HandleObject obj, HandleObject receiver,
uint32_t index, MutableHandleValue vp, ObjectOpResult &result)
{
RootedId id(cx);
if (!IndexToId(cx, index, &id))
return false;
return nonNativeSetProperty(cx, obj, id, v, receiver, result);
return nonNativeSetProperty(cx, obj, receiver, id, vp, result);
}
JS_FRIEND_API(bool)
@ -3193,30 +3192,23 @@ js::GetOwnPropertyDescriptor(JSContext *cx, HandleObject obj, HandleId id,
return true;
}
bool
js::DefineProperty(JSContext *cx, HandleObject obj, HandleId id, Handle<PropertyDescriptor> desc,
ObjectOpResult &result)
{
if (DefinePropertyOp op = obj->getOps()->defineProperty)
return op(cx, obj, id, desc, result);
return NativeDefineProperty(cx, obj.as<NativeObject>(), id, desc, result);
}
bool
js::DefineProperty(ExclusiveContext *cx, HandleObject obj, HandleId id, HandleValue value,
JSGetterOp getter, JSSetterOp setter, unsigned attrs,
ObjectOpResult &result)
{
MOZ_ASSERT(getter != JS_PropertyStub);
MOZ_ASSERT(setter != JS_StrictPropertyStub);
MOZ_ASSERT(!(attrs & JSPROP_PROPOP_ACCESSORS));
Rooted<PropertyDescriptor> desc(cx);
desc.initFields(obj, value, attrs, getter, setter);
if (DefinePropertyOp op = obj->getOps()->defineProperty) {
DefinePropertyOp op = obj->getOps()->defineProperty;
if (op) {
if (!cx->shouldBeJSContext())
return false;
return op(cx->asJSContext(), obj, id, desc, result);
return op(cx->asJSContext(), obj, id, value, getter, setter, attrs, result);
}
return NativeDefineProperty(cx, obj.as<NativeObject>(), id, desc, result);
return NativeDefineProperty(cx, obj.as<NativeObject>(), id, value, getter, setter, attrs,
result);
}
bool
@ -3279,6 +3271,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 ***************************************************/

View file

@ -478,12 +478,12 @@ class JSObject : public js::gc::Cell
bool callMethod(JSContext *cx, js::HandleId id, unsigned argc, js::Value *argv,
js::MutableHandleValue vp);
static bool nonNativeSetProperty(JSContext *cx, js::HandleObject obj, js::HandleId id,
js::HandleValue v, js::HandleValue receiver,
JS::ObjectOpResult &result);
static bool nonNativeSetElement(JSContext *cx, js::HandleObject obj, uint32_t index,
js::HandleValue v, js::HandleValue receiver,
JS::ObjectOpResult &result);
static bool nonNativeSetProperty(JSContext *cx, js::HandleObject obj,
js::HandleObject receiver, js::HandleId id,
js::MutableHandleValue vp, JS::ObjectOpResult &result);
static bool nonNativeSetElement(JSContext *cx, js::HandleObject obj,
js::HandleObject receiver, uint32_t index,
js::MutableHandleValue vp, JS::ObjectOpResult &result);
static bool swap(JSContext *cx, JS::HandleObject a, JS::HandleObject b);
@ -768,10 +768,6 @@ extern bool
StandardDefineProperty(JSContext *cx, HandleObject obj, HandleId id,
Handle<PropertyDescriptor> desc);
extern bool
DefineProperty(JSContext *cx, HandleObject obj, HandleId id,
Handle<PropertyDescriptor> desc, ObjectOpResult &result);
extern bool
DefineProperty(ExclusiveContext *cx, HandleObject obj, HandleId id, HandleValue value,
JSGetterOp getter, JSSetterOp setter, unsigned attrs, ObjectOpResult &result);
@ -853,52 +849,49 @@ inline bool
GetElementNoGC(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t index, Value *vp);
/*
* ES6 [[Set]]. Carry out the assignment `obj[id] = v`.
* ES6 [[Set]]. Carry out the assignment `obj[id] = vp`.
*
* The `receiver` argument has to do with how [[Set]] interacts with the
* prototype chain and proxies. It's hard to explain and ES6 doesn't really
* try. Long story short, if you just want bog-standard assignment, pass
* `ObjectValue(*obj)` as receiver. Or better, use one of the signatures that
* doesn't have a receiver parameter.
* try. Long story short, if you just want bog-standard assignment, pass the
* same object as both obj and receiver.
*
* Callers pass obj != receiver e.g. when a proxy is involved, obj is the
* proxy's target, and the proxy is using SetProperty to finish an assignment
* that started out as `receiver[id] = v`, by delegating it to obj.
* When obj != receiver, it's a reasonable guess that a proxy is involved, obj
* is the proxy's target, and the proxy is using SetProperty to finish an
* assignment that started out as `receiver[id] = vp`, by delegating it to obj.
*
* Strict errors: ES6 specifies that this method returns a boolean value
* indicating whether assignment "succeeded". We currently take a `strict`
* argument instead, but this has to change. See bug 1113369.
*/
inline bool
SetProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult &result);
SetProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id,
MutableHandleValue vp, ObjectOpResult &result);
inline bool
SetProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue v)
{
RootedValue receiver(cx, ObjectValue(*obj));
ObjectOpResult result;
return SetProperty(cx, obj, id, v, receiver, result) &&
result.checkStrict(cx, obj, id);
}
inline bool
SetProperty(JSContext *cx, HandleObject obj, PropertyName *name, HandleValue v,
HandleValue receiver, ObjectOpResult &result)
SetProperty(JSContext *cx, HandleObject obj, HandleObject receiver, PropertyName *name,
MutableHandleValue vp, ObjectOpResult &result)
{
RootedId id(cx, NameToId(name));
return SetProperty(cx, obj, id, v, receiver, result);
return SetProperty(cx, obj, receiver, id, vp, result);
}
inline bool
SetProperty(JSContext *cx, HandleObject obj, PropertyName *name, HandleValue v)
SetElement(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index,
MutableHandleValue vp, ObjectOpResult &result);
inline bool
SetProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id,
MutableHandleValue vp)
{
RootedId id(cx, NameToId(name));
RootedValue receiver(cx, ObjectValue(*obj));
ObjectOpResult result;
return SetProperty(cx, obj, id, v, receiver, result) &&
result.checkStrict(cx, obj, id);
return SetProperty(cx, obj, receiver, id, vp, result) &&
result.checkStrict(cx, receiver, id);
}
inline bool
SetElement(JSContext *cx, HandleObject obj, uint32_t index, HandleValue v,
HandleValue receiver, ObjectOpResult &result);
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
@ -906,14 +899,17 @@ SetElement(JSContext *cx, HandleObject obj, uint32_t index, HandleValue v,
* don't bother doing.
*/
inline bool
PutProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue v, bool strict)
PutProperty(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue value, bool strict)
{
RootedValue receiver(cx, ObjectValue(*obj));
ObjectOpResult result;
return SetProperty(cx, obj, id, v, receiver, 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]`.
*/

View file

@ -2168,7 +2168,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_, cx->names().lastIndex, zero);
return SetProperty(cx, obj_, obj_, cx->names().lastIndex, &zero);
}
RegExpShared &regExp() { return *re_; }

View file

@ -117,7 +117,7 @@ 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,
Handle<JSPropertyDescriptor> desc,
MutableHandle<JSPropertyDescriptor> desc,
ObjectOpResult &result) const override;
virtual bool ownPropertyKeys(JSContext *cx, HandleObject wrapper,
AutoIdVector &props) const override;
@ -137,8 +137,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, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult &result) const override;
virtual bool set(JSContext *cx, HandleObject wrapper, HandleObject receiver, HandleId id,
MutableHandleValue vp, ObjectOpResult &result) const 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;
@ -185,7 +185,7 @@ class JS_FRIEND_API(SecurityWrapper) : public Base
bool *bp) const override;
virtual bool defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
Handle<JSPropertyDescriptor> desc,
MutableHandle<JSPropertyDescriptor> desc,
ObjectOpResult &result) const override;
virtual bool isExtensible(JSContext *cx, HandleObject wrapper, bool *extensible) const override;
virtual bool preventExtensions(JSContext *cx, HandleObject wrapper,

View file

@ -61,7 +61,8 @@ BaseProxyHandler::get(JSContext *cx, HandleObject proxy, HandleObject receiver,
return true;
}
if (desc.hasGetterObject())
return InvokeGetter(cx, receiver, ObjectValue(*desc.getterObject()), vp);
return InvokeGetterOrSetter(cx, receiver, ObjectValue(*desc.getterObject()),
0, nullptr, vp);
if (!desc.isShared())
vp.set(desc.value());
else
@ -71,8 +72,8 @@ BaseProxyHandler::get(JSContext *cx, HandleObject proxy, HandleObject receiver,
}
bool
BaseProxyHandler::set(JSContext *cx, HandleObject proxy, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult &result) const
BaseProxyHandler::set(JSContext *cx, HandleObject proxy, HandleObject receiver,
HandleId id, MutableHandleValue vp, ObjectOpResult &result) const
{
assertEnteredPolicy(cx, proxy, id, SET);
@ -87,16 +88,15 @@ BaseProxyHandler::set(JSContext *cx, HandleObject proxy, HandleId id, HandleValu
// The rest is factored out into a separate function with a weird name.
// This algorithm continues just below.
return SetPropertyIgnoringNamedGetter(cx, proxy, id, v, receiver, ownDesc, result);
return SetPropertyIgnoringNamedGetter(cx, proxy, id, vp, receiver, &ownDesc, result);
}
bool
js::SetPropertyIgnoringNamedGetter(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
HandleValue receiver, Handle<PropertyDescriptor> ownDesc_,
js::SetPropertyIgnoringNamedGetter(JSContext *cx, HandleObject obj, HandleId id,
MutableHandleValue vp, HandleObject receiver,
MutableHandle<PropertyDescriptor> ownDesc,
ObjectOpResult &result)
{
Rooted<PropertyDescriptor> ownDesc(cx, ownDesc_);
// Step 4.
if (!ownDesc.object()) {
// The spec calls this variable "parent", but that word has weird
@ -105,33 +105,31 @@ js::SetPropertyIgnoringNamedGetter(JSContext *cx, HandleObject obj, HandleId id,
if (!GetPrototype(cx, obj, &proto))
return false;
if (proto)
return SetProperty(cx, proto, id, v, receiver, result);
return SetProperty(cx, proto, receiver, id, vp, result);
// Step 4.d.
ownDesc.setDataDescriptor(UndefinedHandleValue, JSPROP_ENUMERATE);
// Change ownDesc to be a complete descriptor for a configurable,
// writable, enumerable data property. Then fall through to step 5.
ownDesc.clear();
ownDesc.setAttributes(JSPROP_ENUMERATE);
}
// Step 5.
if (ownDesc.isDataDescriptor()) {
// Steps 5.a-b.
// Steps 5.a-b, adapted to our nonstandard implementation of ES6
// [[Set]] return values.
if (!ownDesc.writable())
return result.fail(JSMSG_READ_ONLY);
if (!receiver.isObject())
return result.fail(JSMSG_SET_NON_OBJECT_RECEIVER);
RootedObject receiverObj(cx, &receiver.toObject());
// Nonstandard SpiderMonkey special case: setter ops.
SetterOp setter = ownDesc.setter();
MOZ_ASSERT(setter != JS_StrictPropertyStub);
if (setter && setter != JS_StrictPropertyStub) {
RootedValue valCopy(cx, v);
return CallJSSetterOp(cx, setter, receiverObj, id, &valCopy, result);
}
if (setter && setter != JS_StrictPropertyStub)
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]].
bool existingDescriptor;
if (!HasOwnProperty(cx, receiverObj, id, &existingDescriptor))
if (!HasOwnProperty(cx, receiver, id, &existingDescriptor))
return false;
// Steps 5.e-f.
@ -142,10 +140,10 @@ js::SetPropertyIgnoringNamedGetter(JSContext *cx, HandleObject obj, HandleId id,
// A very old nonstandard SpiderMonkey extension: default to the Class
// getter and setter ops.
const Class *clasp = receiverObj->getClass();
const Class *clasp = receiver->getClass();
MOZ_ASSERT(clasp->getProperty != JS_PropertyStub);
MOZ_ASSERT(clasp->setProperty != JS_StrictPropertyStub);
return DefineProperty(cx, receiverObj, id, v, clasp->getProperty, clasp->setProperty,
return DefineProperty(cx, receiver, id, vp, clasp->getProperty, clasp->setProperty,
attrs, result);
}
@ -157,7 +155,7 @@ js::SetPropertyIgnoringNamedGetter(JSContext *cx, HandleObject obj, HandleId id,
if (!setter)
return result.fail(JSMSG_GETTER_ONLY);
RootedValue setterValue(cx, ObjectValue(*setter));
if (!InvokeSetter(cx, receiver, setterValue, v))
if (!InvokeGetterOrSetter(cx, receiver, setterValue, 1, vp.address(), vp))
return false;
return result.succeed();
}

View file

@ -49,13 +49,13 @@ CrossCompartmentWrapper::getOwnPropertyDescriptor(JSContext *cx, HandleObject wr
bool
CrossCompartmentWrapper::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
Handle<PropertyDescriptor> desc,
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, result),
Wrapper::defineProperty(cx, wrapper, id, &desc2, result),
NOTHING);
}
@ -169,15 +169,14 @@ CrossCompartmentWrapper::get(JSContext *cx, HandleObject wrapper, HandleObject r
}
bool
CrossCompartmentWrapper::set(JSContext *cx, HandleObject wrapper, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult &result) const
CrossCompartmentWrapper::set(JSContext *cx, HandleObject wrapper, HandleObject receiver,
HandleId id, MutableHandleValue vp, ObjectOpResult &result) const
{
RootedValue valCopy(cx, v);
RootedValue receiverCopy(cx, receiver);
RootedObject receiverCopy(cx, receiver);
PIERCE(cx, wrapper,
cx->compartment()->wrap(cx, &valCopy) &&
cx->compartment()->wrap(cx, &receiverCopy),
Wrapper::set(cx, wrapper, id, valCopy, receiverCopy, result),
cx->compartment()->wrap(cx, &receiverCopy) &&
cx->compartment()->wrap(cx, vp),
Wrapper::set(cx, wrapper, receiverCopy, id, vp, result),
NOTHING);
}

View file

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

View file

@ -22,7 +22,7 @@ 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,
Handle<JSPropertyDescriptor> desc,
MutableHandle<JSPropertyDescriptor> desc,
ObjectOpResult &result) const override;
virtual bool ownPropertyKeys(JSContext *cx, HandleObject wrapper,
AutoIdVector &props) const override;

View file

@ -34,7 +34,7 @@ DirectProxyHandler::getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy,
bool
DirectProxyHandler::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
Handle<PropertyDescriptor> desc,
MutableHandle<PropertyDescriptor> desc,
ObjectOpResult &result) const
{
assertEnteredPolicy(cx, proxy, id, SET);
@ -216,12 +216,12 @@ DirectProxyHandler::get(JSContext *cx, HandleObject proxy, HandleObject receiver
}
bool
DirectProxyHandler::set(JSContext *cx, HandleObject proxy, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult &result) const
DirectProxyHandler::set(JSContext *cx, HandleObject proxy, HandleObject receiver,
HandleId id, MutableHandleValue vp, ObjectOpResult &result) const
{
assertEnteredPolicy(cx, proxy, id, SET);
RootedObject target(cx, proxy->as<ProxyObject>().target());
return SetProperty(cx, target, id, v, receiver, result);
return SetProperty(cx, target, receiver, id, vp, result);
}
bool

View file

@ -134,7 +134,7 @@ Proxy::getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
bool
Proxy::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
Handle<PropertyDescriptor> desc, ObjectOpResult &result)
MutableHandle<PropertyDescriptor> desc, ObjectOpResult &result)
{
JS_CHECK_RECURSION(cx, return false);
const BaseProxyHandler *handler = proxy->as<ProxyObject>().handler();
@ -307,8 +307,8 @@ Proxy::callProp(JSContext *cx, HandleObject proxy, HandleObject receiver, Handle
}
bool
Proxy::set(JSContext *cx, HandleObject proxy, HandleId id, HandleValue v, HandleValue receiver,
ObjectOpResult &result)
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();
@ -321,9 +321,9 @@ Proxy::set(JSContext *cx, HandleObject proxy, HandleId id, HandleValue v, Handle
// Special case. See the comment on BaseProxyHandler::mHasPrototype.
if (handler->hasPrototype())
return handler->BaseProxyHandler::set(cx, proxy, id, v, receiver, result);
return handler->BaseProxyHandler::set(cx, proxy, receiver, id, vp, result);
return handler->set(cx, proxy, id, v, receiver, result);
return handler->set(cx, proxy, receiver, id, vp, result);
}
bool
@ -559,11 +559,17 @@ js::proxy_LookupProperty(JSContext *cx, HandleObject obj, HandleId id,
}
bool
js::proxy_DefineProperty(JSContext *cx, HandleObject obj, HandleId id,
Handle<JSPropertyDescriptor> desc,
js::proxy_DefineProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue value,
GetterOp getter, SetterOp setter, unsigned attrs,
ObjectOpResult &result)
{
return Proxy::defineProperty(cx, obj, id, desc, result);
Rooted<PropertyDescriptor> desc(cx);
desc.object().set(obj);
desc.value().set(value);
desc.setAttributes(attrs);
desc.setGetter(getter);
desc.setSetter(setter);
return Proxy::defineProperty(cx, obj, id, &desc, result);
}
bool
@ -580,10 +586,10 @@ js::proxy_GetProperty(JSContext *cx, HandleObject obj, HandleObject receiver, Ha
}
bool
js::proxy_SetProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult &result)
js::proxy_SetProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id,
MutableHandleValue vp, ObjectOpResult &result)
{
return Proxy::set(cx, obj, id, v, receiver, result);
return Proxy::set(cx, obj, receiver, id, vp, result);
}
bool

View file

@ -29,7 +29,7 @@ class Proxy
static bool getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
MutableHandle<JSPropertyDescriptor> desc);
static bool defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
Handle<JSPropertyDescriptor> desc, ObjectOpResult &result);
MutableHandle<JSPropertyDescriptor> desc, ObjectOpResult &result);
static bool ownPropertyKeys(JSContext *cx, HandleObject proxy, AutoIdVector &props);
static bool delete_(JSContext *cx, HandleObject proxy, HandleId id, ObjectOpResult &result);
static bool enumerate(JSContext *cx, HandleObject proxy, MutableHandleObject objp);
@ -42,8 +42,8 @@ class Proxy
static bool has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp);
static bool get(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id,
MutableHandleValue vp);
static bool set(JSContext *cx, HandleObject proxy, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult &result);
static bool set(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id,
MutableHandleValue vp, ObjectOpResult &result);
static bool call(JSContext *cx, HandleObject proxy, const CallArgs &args);
static bool construct(JSContext *cx, HandleObject proxy, const CallArgs &args);

View file

@ -550,7 +550,7 @@ ScriptedDirectProxyHandler::getOwnPropertyDescriptor(JSContext *cx, HandleObject
// ES6 draft rev 31 (15 Jan 2015) 9.5.6 Proxy.[[DefineOwnProperty]](P, Desc)
bool
ScriptedDirectProxyHandler::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
Handle<PropertyDescriptor> desc,
MutableHandle<PropertyDescriptor> desc,
ObjectOpResult &result) const
{
// steps 2-4
@ -922,8 +922,8 @@ ScriptedDirectProxyHandler::get(JSContext *cx, HandleObject proxy, HandleObject
// ES6 draft rev 32 (2015 Feb 2) 9.5.9 Proxy.[[Set]](P, V, Receiver)
bool
ScriptedDirectProxyHandler::set(JSContext *cx, HandleObject proxy, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult &result) const
ScriptedDirectProxyHandler::set(JSContext *cx, HandleObject proxy, HandleObject receiver,
HandleId id, MutableHandleValue vp, ObjectOpResult &result) const
{
// step 2-3 (Steps 1 and 4 are irrelevant assertions.)
RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
@ -940,7 +940,7 @@ ScriptedDirectProxyHandler::set(JSContext *cx, HandleObject proxy, HandleId id,
// step 8
if (trap.isUndefined())
return SetProperty(cx, target, id, v, receiver, result);
return SetProperty(cx, target, receiver, id, vp, result);
// step 9-10
RootedValue value(cx);
@ -949,8 +949,8 @@ ScriptedDirectProxyHandler::set(JSContext *cx, HandleObject proxy, HandleId id,
Value argv[] = {
ObjectOrNullValue(target),
value,
v.get(),
receiver.get()
vp.get(),
ObjectValue(*receiver)
};
RootedValue trapResult(cx);
if (!Invoke(cx, ObjectValue(*handler), trap, ArrayLength(argv), argv, &trapResult))
@ -969,7 +969,7 @@ ScriptedDirectProxyHandler::set(JSContext *cx, HandleObject proxy, HandleId id,
if (desc.object()) {
if (desc.isDataDescriptor() && !desc.configurable() && !desc.writable()) {
bool same;
if (!SameValue(cx, v, desc.value(), &same))
if (!SameValue(cx, vp, desc.value(), &same))
return false;
if (!same) {
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CANT_SET_NW_NC);

View file

@ -22,7 +22,7 @@ class ScriptedDirectProxyHandler : 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,
Handle<JSPropertyDescriptor> desc,
MutableHandle<JSPropertyDescriptor> desc,
ObjectOpResult &result) const override;
virtual bool ownPropertyKeys(JSContext *cx, HandleObject proxy,
AutoIdVector &props) const override;
@ -46,8 +46,8 @@ class ScriptedDirectProxyHandler : public BaseProxyHandler {
virtual bool has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const override;
virtual bool get(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id,
MutableHandleValue vp) const override;
virtual bool set(JSContext *cx, HandleObject proxy, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult &result) const override;
virtual bool set(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id,
MutableHandleValue vp, ObjectOpResult &result) const 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;

View file

@ -10,7 +10,6 @@
#include "jsapi.h"
#include "jscntxt.h"
#include "jscntxtinlines.h"
#include "jsobjinlines.h"
using namespace js;
@ -197,7 +196,7 @@ ScriptedIndirectProxyHandler::getOwnPropertyDescriptor(JSContext *cx, HandleObje
bool
ScriptedIndirectProxyHandler::defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
Handle<PropertyDescriptor> desc,
MutableHandle<PropertyDescriptor> desc,
ObjectOpResult &result) const
{
RootedObject handler(cx, GetIndirectProxyHandlerObject(proxy));
@ -304,55 +303,30 @@ ScriptedIndirectProxyHandler::get(JSContext *cx, HandleObject proxy, HandleObjec
}
bool
ScriptedIndirectProxyHandler::set(JSContext *cx, HandleObject proxy, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult &result) const
ScriptedIndirectProxyHandler::set(JSContext *cx, HandleObject proxy, HandleObject receiver,
HandleId id, MutableHandleValue vp, ObjectOpResult &result) const
{
RootedObject handler(cx, GetIndirectProxyHandlerObject(proxy));
RootedValue idv(cx);
if (!IdToStringOrSymbol(cx, id, &idv))
return false;
JS::AutoValueArray<3> argv(cx);
argv[0].set(receiver);
argv[0].setObjectOrNull(receiver);
argv[1].set(idv);
argv[2].set(v);
argv[2].set(vp);
RootedValue fval(cx);
if (!GetDerivedTrap(cx, handler, cx->names().set, &fval))
return false;
if (!IsCallable(fval))
return derivedSet(cx, proxy, id, v, receiver, result);
return derivedSet(cx, proxy, receiver, id, vp, result);
if (!Trap(cx, handler, fval, 3, argv.begin(), &idv))
return false;
return result.succeed();
}
static bool
CallSetter(JSContext *cx, HandleValue receiver, HandleId id, SetterOp op, unsigned attrs,
HandleValue v, ObjectOpResult &result)
{
if (attrs & JSPROP_SETTER) {
RootedValue fval(cx, CastAsObjectJsval(op));
if (!InvokeSetter(cx, receiver, fval, v))
return false;
return result.succeed();
}
if (attrs & JSPROP_GETTER)
return result.fail(JSMSG_GETTER_ONLY);
if (!receiver.isObject())
return result.fail(JSMSG_SET_NON_OBJECT_RECEIVER);
RootedObject receiverObj(cx, &receiver.toObject());
if (!op)
return result.succeed();
RootedValue valCopy(cx, v);
return CallJSSetterOp(cx, op, receiverObj, id, &valCopy, result);
}
bool
ScriptedIndirectProxyHandler::derivedSet(JSContext *cx, HandleObject proxy, HandleId id,
HandleValue v, HandleValue receiver,
ScriptedIndirectProxyHandler::derivedSet(JSContext *cx, HandleObject proxy, HandleObject receiver,
HandleId id, MutableHandleValue vp,
ObjectOpResult &result) const
{
// Find an own or inherited property. The code here is strange for maximum
@ -383,7 +357,7 @@ ScriptedIndirectProxyHandler::derivedSet(JSContext *cx, HandleObject proxy, Hand
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(), v, result))
if (!CallSetter(cx, receiver, id, desc.setter(), desc.attributes(), vp, result))
return false;
if (!result)
return true;
@ -394,21 +368,22 @@ ScriptedIndirectProxyHandler::derivedSet(JSContext *cx, HandleObject proxy, Hand
return result.succeed();
}
}
desc.value().set(v);
desc.value().set(vp.get());
if (descIsOwn) {
MOZ_ASSERT(desc.object() == proxy);
return this->defineProperty(cx, proxy, id, desc, result);
return this->defineProperty(cx, proxy, id, &desc, result);
}
} else {
desc.setDataDescriptor(v, JSPROP_ENUMERATE);
return DefineProperty(cx, receiver, id, desc.value(), desc.getter(), desc.setter(),
desc.attributes(), result);
}
if (!receiver.isObject())
return result.fail(JSMSG_SET_NON_OBJECT_RECEIVER);
RootedObject receiverObj(cx, &receiver.toObject());
desc.object().set(receiverObj);
return DefineProperty(cx, receiverObj, id, desc, 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,
result);
}
bool

View file

@ -23,7 +23,7 @@ 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,
Handle<JSPropertyDescriptor> desc,
MutableHandle<JSPropertyDescriptor> desc,
ObjectOpResult &result) const override;
virtual bool ownPropertyKeys(JSContext *cx, HandleObject proxy,
AutoIdVector &props) const override;
@ -37,8 +37,8 @@ class ScriptedIndirectProxyHandler : public BaseProxyHandler
virtual bool has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const override;
virtual bool get(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id,
MutableHandleValue vp) const override;
virtual bool set(JSContext *cx, HandleObject proxy, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult &result) const override;
virtual bool set(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id,
MutableHandleValue vp, ObjectOpResult &result) const override;
/* SpiderMonkey extensions. */
virtual bool getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
@ -55,8 +55,8 @@ class ScriptedIndirectProxyHandler : public BaseProxyHandler
static const ScriptedIndirectProxyHandler singleton;
private:
bool derivedSet(JSContext *cx, HandleObject proxy, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult &result) const;
bool derivedSet(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id,
MutableHandleValue vp, ObjectOpResult &result) const;
};
/* Derived class to handle Proxy.createFunction() */

View file

@ -103,8 +103,8 @@ SecurityWrapper<Base>::boxedValue_unbox(JSContext *cx, HandleObject obj, Mutable
template <class Base>
bool
SecurityWrapper<Base>::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
Handle<PropertyDescriptor> desc,
SecurityWrapper<Base>::defineProperty(JSContext *cx, HandleObject wrapper,
HandleId id, MutableHandle<PropertyDescriptor> desc,
ObjectOpResult &result) const
{
if (desc.getter() || desc.setter()) {

View file

@ -7637,7 +7637,7 @@ DebuggerEnv_setVariable(JSContext *cx, unsigned argc, Value *vp)
}
/* Just set the property. */
if (!SetProperty(cx, env, id, v))
if (!SetProperty(cx, env, env, id, &v))
return false;
}

View file

@ -612,7 +612,11 @@ class GlobalObject : public NativeObject
MOZ_ASSERT(cx->runtime()->isSelfHostingGlobal(self));
#endif
RootedObject holder(cx, intrinsicsHolder());
return SetProperty(cx, holder, name, value);
RootedValue valCopy(cx, value);
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,

View file

@ -308,6 +308,7 @@ SetNameOperation(JSContext *cx, JSScript *script, jsbytecode *pc, HandleObject s
bool strict = *pc == JSOP_STRICTSETNAME || *pc == JSOP_STRICTSETGNAME;
RootedPropertyName name(cx, script->getName(pc));
RootedValue valCopy(cx, val);
// In strict mode, assigning to an undeclared global variable is an
// error. To detect this, we call NativeSetProperty directly and pass
@ -315,13 +316,12 @@ SetNameOperation(JSContext *cx, JSScript *script, jsbytecode *pc, HandleObject s
bool ok;
ObjectOpResult result;
RootedId id(cx, NameToId(name));
RootedValue receiver(cx, ObjectValue(*scope));
if (scope->isUnqualifiedVarObj()) {
MOZ_ASSERT(!scope->getOps()->setProperty);
ok = NativeSetProperty(cx, scope.as<NativeObject>(), id, val, receiver, Unqualified,
result);
ok = NativeSetProperty(cx, scope.as<NativeObject>(), scope.as<NativeObject>(), id,
Unqualified, &valCopy, result);
} else {
ok = SetProperty(cx, scope, id, val, receiver, result);
ok = SetProperty(cx, scope, scope, id, &valCopy, result);
}
return ok && result.checkStrictErrorOrWarning(cx, scope, id, strict);
}
@ -336,7 +336,8 @@ InitPropertyOperation(JSContext *cx, JSOp op, HandleObject obj, HandleId id, Han
}
MOZ_ASSERT(obj->as<UnboxedPlainObject>().layout().lookup(id));
return PutProperty(cx, obj, id, rhs, false);
RootedValue v(cx, rhs);
return PutProperty(cx, obj, id, &v, false);
}
inline bool

View file

@ -313,20 +313,52 @@ GetNameOperation(JSContext *cx, InterpreterFrame *fp, jsbytecode *pc, MutableHan
}
static bool
SetPropertyOperation(JSContext *cx, JSOp op, HandleValue lval, HandleId id, HandleValue rval)
SetObjectProperty(JSContext *cx, JSOp op, HandleValue lval, HandleId id, MutableHandleValue rref)
{
MOZ_ASSERT(op == JSOP_SETPROP || op == JSOP_STRICTSETPROP);
MOZ_ASSERT(lval.isObject());
RootedObject obj(cx, &lval.toObject());
ObjectOpResult result;
if (MOZ_LIKELY(!obj->getOps()->setProperty)) {
if (!NativeSetProperty(cx, obj.as<NativeObject>(), obj.as<NativeObject>(), id,
Qualified, rref, result))
{
return false;
}
} else {
if (!SetProperty(cx, obj, obj, id, rref, result))
return false;
}
return result.checkStrictErrorOrWarning(cx, obj, id, op == JSOP_STRICTSETPROP);
}
static bool
SetPrimitiveProperty(JSContext *cx, JSOp op, HandleValue lval, HandleId id,
MutableHandleValue rref)
{
MOZ_ASSERT(lval.isPrimitive());
RootedObject obj(cx, ToObjectFromStack(cx, lval));
if (!obj)
return false;
// Note: ES6 specifies that the value lval, not obj, is passed as receiver
// to obj's [[Set]] internal method. See bug 603201.
RootedValue receiver(cx, ObjectValue(*obj));
ObjectOpResult result;
return SetProperty(cx, obj, id, rval, receiver, result) &&
result.checkStrictErrorOrWarning(cx, obj, id, op == JSOP_STRICTSETPROP);
return SetObjectProperty(cx, op, receiver, id, rref);
}
static bool
SetPropertyOperation(JSContext *cx, JSOp op, HandleValue lval, HandleId id, HandleValue rval)
{
MOZ_ASSERT(op == JSOP_SETPROP || op == JSOP_STRICTSETPROP);
RootedValue rref(cx, rval);
if (lval.isPrimitive())
return SetPrimitiveProperty(cx, op, lval, id, &rref);
return SetObjectProperty(cx, op, lval, id, &rref);
}
bool
@ -584,7 +616,8 @@ js::InvokeConstructor(JSContext *cx, Value fval, unsigned argc, const Value *arg
}
bool
js::InvokeGetter(JSContext *cx, JSObject *obj, Value fval, MutableHandleValue rval)
js::InvokeGetterOrSetter(JSContext *cx, JSObject *obj, Value fval, unsigned argc,
Value *argv, MutableHandleValue rval)
{
/*
* Invoke could result in another try to get or set the same id again, see
@ -592,16 +625,7 @@ js::InvokeGetter(JSContext *cx, JSObject *obj, Value fval, MutableHandleValue rv
*/
JS_CHECK_RECURSION(cx, return false);
return Invoke(cx, ObjectValue(*obj), fval, 0, nullptr, rval);
}
bool
js::InvokeSetter(JSContext *cx, const Value &thisv, Value fval, HandleValue v)
{
JS_CHECK_RECURSION(cx, return false);
RootedValue ignored(cx);
return Invoke(cx, thisv, fval, 1, v.address(), &ignored);
return Invoke(cx, ObjectValue(*obj), fval, argc, argv, rval);
}
bool
@ -1379,7 +1403,7 @@ SetObjectElementOperation(JSContext *cx, Handle<JSObject*> obj, HandleId id, con
return false;
RootedValue tmp(cx, value);
return PutProperty(cx, obj, id, tmp, strict);
return PutProperty(cx, obj, id, &tmp, strict);
}
static MOZ_NEVER_INLINE bool
@ -3861,8 +3885,7 @@ js::DefFunOperation(JSContext *cx, HandleScript script, HandleObject scopeChain,
*/
/* Step 5f. */
RootedId id(cx, NameToId(name));
return PutProperty(cx, parent, id, rval, script->strict());
return PutProperty(cx, parent, name, &rval, script->strict());
}
bool

View file

@ -76,14 +76,12 @@ Invoke(JSContext *cx, const Value &thisv, const Value &fval, unsigned argc, cons
MutableHandleValue rval);
/*
* These helpers take care of the infinite-recursion check necessary for
* This helper takes care of the infinite-recursion check necessary for
* getter/setter calls.
*/
extern bool
InvokeGetter(JSContext *cx, JSObject *obj, Value fval, MutableHandleValue rval);
extern bool
InvokeSetter(JSContext *cx, const Value &thisv, Value fval, HandleValue v);
InvokeGetterOrSetter(JSContext *cx, JSObject *obj, Value fval, unsigned argc, Value *argv,
MutableHandleValue rval);
/*
* InvokeConstructor implement a function call from a constructor context

View file

@ -73,7 +73,8 @@ NativeObject::clearShouldConvertDoubleElements()
}
inline void
NativeObject::setDenseElementWithType(ExclusiveContext *cx, uint32_t index, const Value &val)
NativeObject::setDenseElementWithType(ExclusiveContext *cx, uint32_t index,
const Value &val)
{
// Avoid a slow AddTypePropertyId call if the type is the same as the type
// of the previous element.
@ -84,7 +85,8 @@ NativeObject::setDenseElementWithType(ExclusiveContext *cx, uint32_t index, cons
}
inline void
NativeObject::initDenseElementWithType(ExclusiveContext *cx, uint32_t index, const Value &val)
NativeObject::initDenseElementWithType(ExclusiveContext *cx, uint32_t index,
const Value &val)
{
MOZ_ASSERT(!shouldConvertDoubleElements());
AddTypePropertyId(cx, this, JSID_VOID, val);

View file

@ -981,59 +981,6 @@ NativeObject::addDataProperty(ExclusiveContext *cx, HandlePropertyName name,
return addProperty(cx, self, id, nullptr, nullptr, slot, attrs, 0);
}
template <AllowGC allowGC>
bool
js::NativeLookupOwnProperty(ExclusiveContext *cx,
typename MaybeRooted<NativeObject*, allowGC>::HandleType obj,
typename MaybeRooted<jsid, allowGC>::HandleType id,
typename MaybeRooted<Shape*, allowGC>::MutableHandleType propp)
{
bool done;
return LookupOwnPropertyInline<allowGC>(cx, obj, id, propp, &done);
}
template bool
js::NativeLookupOwnProperty<CanGC>(ExclusiveContext *cx, HandleNativeObject obj, HandleId id,
MutableHandleShape propp);
template bool
js::NativeLookupOwnProperty<NoGC>(ExclusiveContext *cx, NativeObject *obj, jsid id,
FakeMutableHandle<Shape*> propp);
template <AllowGC allowGC>
bool
js::NativeLookupProperty(ExclusiveContext *cx,
typename MaybeRooted<NativeObject*, allowGC>::HandleType obj,
typename MaybeRooted<jsid, allowGC>::HandleType id,
typename MaybeRooted<JSObject*, allowGC>::MutableHandleType objp,
typename MaybeRooted<Shape*, allowGC>::MutableHandleType propp)
{
return LookupPropertyInline<allowGC>(cx, obj, id, objp, propp);
}
template bool
js::NativeLookupProperty<CanGC>(ExclusiveContext *cx, HandleNativeObject obj, HandleId id,
MutableHandleObject objp, MutableHandleShape propp);
template bool
js::NativeLookupProperty<NoGC>(ExclusiveContext *cx, NativeObject *obj, jsid id,
FakeMutableHandle<JSObject*> objp,
FakeMutableHandle<Shape*> propp);
bool
js::NativeLookupElement(JSContext *cx, HandleNativeObject obj, uint32_t index,
MutableHandleObject objp, MutableHandleShape propp)
{
RootedId id(cx);
if (!IndexToId(cx, index, &id))
return false;
return LookupPropertyInline<CanGC>(cx, obj, id, objp, propp);
}
/*** [[DefineOwnProperty]] ***********************************************************************/
/*
* Backward compatibility requires allowing addProperty hooks to mutate the
* nominal initial value of a slotful property, while GC safety wants that
@ -1130,8 +1077,8 @@ UpdateShapeTypeAndValue(ExclusiveContext *cx, NativeObject *obj, Shape *shape, c
}
static bool
NativeSetExistingDataProperty(JSContext *cx, HandleNativeObject obj, HandleShape shape,
HandleValue v, HandleValue receiver, ObjectOpResult &result);
NativeSet(JSContext *cx, HandleNativeObject obj, HandleObject receiver,
HandleShape shape, MutableHandleValue vp, ObjectOpResult &result);
static inline bool
DefinePropertyOrElement(ExclusiveContext *cx, HandleNativeObject obj, HandleId id,
@ -1220,13 +1167,10 @@ DefinePropertyOrElement(ExclusiveContext *cx, HandleNativeObject obj, HandleId i
return false;
if (callSetterAfterwards && setter) {
MOZ_ASSERT(!(attrs & JSPROP_GETTER));
MOZ_ASSERT(!(attrs & JSPROP_SETTER));
if (!cx->shouldBeJSContext())
return false;
RootedValue receiver(cx, ObjectValue(*obj));
return NativeSetExistingDataProperty(cx->asJSContext(), obj, shape, value, receiver,
result);
RootedValue nvalue(cx, value);
return NativeSet(cx->asJSContext(), obj, obj, shape, &nvalue, result);
}
return result.succeed();
@ -1341,19 +1285,18 @@ CheckAccessorRedefinition(ExclusiveContext *cx, HandleObject obj, HandleShape sh
}
bool
js::NativeDefineProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleId id,
Handle<JSPropertyDescriptor> desc,
js::NativeDefineProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleId id, HandleValue value,
GetterOp getter, SetterOp setter, unsigned attrs,
ObjectOpResult &result)
{
GetterOp getter = desc.getter();
SetterOp setter = desc.setter();
unsigned attrs = desc.attributes();
MOZ_ASSERT(getter != JS_PropertyStub);
MOZ_ASSERT(setter != JS_StrictPropertyStub);
MOZ_ASSERT(!(attrs & JSPROP_PROPOP_ACCESSORS));
AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
RootedShape shape(cx);
RootedValue updateValue(cx, desc.value());
RootedValue updateValue(cx, value);
bool shouldDefine = true;
/*
@ -1361,7 +1304,7 @@ js::NativeDefineProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleId
* update the attributes and property ops. A getter or setter is really
* only half of a property.
*/
if (desc.isAccessorDescriptor()) {
if (attrs & (JSPROP_GETTER | JSPROP_SETTER)) {
if (!NativeLookupOwnProperty<CanGC>(cx, obj, id, &shape))
return false;
if (shape) {
@ -1395,7 +1338,7 @@ js::NativeDefineProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleId
shouldDefine = false;
}
}
} else if (desc.hasValue()) {
} else if (!(attrs & JSPROP_IGNORE_VALUE)) {
// If we did a normal lookup here, it would cause resolve hook recursion in
// the following case. Suppose the first script we run in a lazy global is
// |parseInt()|.
@ -1457,8 +1400,8 @@ js::NativeDefineProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleId
attrs = ApplyOrDefaultAttributes(attrs, shape);
if (shape->isAccessorDescriptor() && !(attrs & JSPROP_IGNORE_READONLY)) {
// ES6 draft 2014-10-14 9.1.6.3 step 7.c: Since [[Writable]]
// is present, change the existing accessor property to a data
// ES6 draft 2014-10-14 9.1.6.3 step 7.c: Since [[Writable]]
// is present, change the existing accessor property to a data
// property.
updateValue = UndefinedValue();
} else {
@ -1500,20 +1443,60 @@ js::NativeDefineProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleId
return result.succeed();
}
template <AllowGC allowGC>
bool
js::NativeDefineProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleId id,
HandleValue value, GetterOp getter, SetterOp setter, unsigned attrs,
ObjectOpResult &result)
js::NativeLookupOwnProperty(ExclusiveContext *cx,
typename MaybeRooted<NativeObject*, allowGC>::HandleType obj,
typename MaybeRooted<jsid, allowGC>::HandleType id,
typename MaybeRooted<Shape*, allowGC>::MutableHandleType propp)
{
Rooted<PropertyDescriptor> desc(cx);
desc.initFields(obj, value, attrs, getter, setter);
return NativeDefineProperty(cx, obj, id, desc, result);
bool done;
return LookupOwnPropertyInline<allowGC>(cx, obj, id, propp, &done);
}
template bool
js::NativeLookupOwnProperty<CanGC>(ExclusiveContext *cx, HandleNativeObject obj, HandleId id,
MutableHandleShape propp);
template bool
js::NativeLookupOwnProperty<NoGC>(ExclusiveContext *cx, NativeObject *obj, jsid id,
FakeMutableHandle<Shape*> propp);
template <AllowGC allowGC>
bool
js::NativeLookupProperty(ExclusiveContext *cx,
typename MaybeRooted<NativeObject*, allowGC>::HandleType obj,
typename MaybeRooted<jsid, allowGC>::HandleType id,
typename MaybeRooted<JSObject*, allowGC>::MutableHandleType objp,
typename MaybeRooted<Shape*, allowGC>::MutableHandleType propp)
{
return LookupPropertyInline<allowGC>(cx, obj, id, objp, propp);
}
template bool
js::NativeLookupProperty<CanGC>(ExclusiveContext *cx, HandleNativeObject obj, HandleId id,
MutableHandleObject objp, MutableHandleShape propp);
template bool
js::NativeLookupProperty<NoGC>(ExclusiveContext *cx, NativeObject *obj, jsid id,
FakeMutableHandle<JSObject*> objp,
FakeMutableHandle<Shape*> propp);
bool
js::NativeLookupElement(JSContext *cx, HandleNativeObject obj, uint32_t index,
MutableHandleObject objp, MutableHandleShape propp)
{
RootedId id(cx);
if (!IndexToId(cx, index, &id))
return false;
return LookupPropertyInline<CanGC>(cx, obj, id, objp, propp);
}
bool
js::NativeDefineProperty(ExclusiveContext *cx, HandleNativeObject obj, PropertyName *name,
HandleValue value, GetterOp getter, SetterOp setter, unsigned attrs,
ObjectOpResult &result)
HandleValue value, GetterOp getter, SetterOp setter,
unsigned attrs, ObjectOpResult &result)
{
RootedId id(cx, NameToId(name));
return NativeDefineProperty(cx, obj, id, value, getter, setter, attrs, result);
@ -1521,8 +1504,8 @@ js::NativeDefineProperty(ExclusiveContext *cx, HandleNativeObject obj, PropertyN
bool
js::NativeDefineElement(ExclusiveContext *cx, HandleNativeObject obj, uint32_t index,
HandleValue value, GetterOp getter, SetterOp setter, unsigned attrs,
ObjectOpResult &result)
HandleValue value, GetterOp getter, SetterOp setter,
unsigned attrs, ObjectOpResult &result)
{
RootedId id(cx);
if (index <= JSID_INT_MAX) {
@ -1567,7 +1550,6 @@ js::NativeDefineProperty(ExclusiveContext *cx, HandleNativeObject obj, PropertyN
return NativeDefineProperty(cx, obj, id, value, getter, setter, attrs);
}
/*** [[HasProperty]] *****************************************************************************/
// ES6 draft rev31 9.1.7.1 OrdinaryHasProperty
@ -1620,7 +1602,6 @@ js::NativeHasProperty(JSContext *cx, HandleNativeObject obj, HandleId id, bool *
}
}
/*** [[Get]] *************************************************************************************/
static inline bool
@ -1630,7 +1611,7 @@ CallGetter(JSContext* cx, HandleObject receiver, HandleShape shape, MutableHandl
if (shape->hasGetterValue()) {
Value fval = shape->getterValue();
return InvokeGetter(cx, receiver, fval, vp);
return InvokeGetterOrSetter(cx, receiver, fval, 0, 0, vp);
}
RootedId id(cx, shape->propid());
@ -1946,7 +1927,6 @@ js::GetPropertyForNameLookup(JSContext *cx, HandleObject obj, HandleId id, Mutab
return NativeGetPropertyInline<CanGC>(cx, obj.as<NativeObject>(), obj, id, NameLookup, vp);
}
/*** [[Set]] *************************************************************************************/
static bool
@ -1978,18 +1958,13 @@ MaybeReportUndeclaredVarAssignment(JSContext *cx, JSString *propname)
* or finds a writable data property on the prototype chain, we end up here.
* Finish the [[Set]] by defining a new property on receiver.
*
* This implements ES6 draft rev 28, 9.1.9 [[Set]] steps 5.b-f, but it
* This implements ES6 draft rev 28, 9.1.9 [[Set]] steps 5.c-f, but it
* is really old code and there are a few barnacles.
*/
bool
js::SetPropertyByDefining(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
HandleValue receiverValue, bool objHasOwn, ObjectOpResult &result)
js::SetPropertyByDefining(JSContext *cx, HandleObject obj, HandleObject receiver,
HandleId id, HandleValue v, bool objHasOwn, ObjectOpResult &result)
{
// Step 5.b.
if (!receiverValue.isObject())
return result.fail(JSMSG_SET_NON_OBJECT_RECEIVER);
RootedObject receiver(cx, &receiverValue.toObject());
// Step 5.c-d: Test whether receiver has an existing own property
// receiver[id]. The spec calls [[GetOwnProperty]]; js::HasOwnProperty is
// the same thing except faster in the non-proxy case. Sometimes we can
@ -2042,8 +2017,6 @@ js::SetPropertyByDefining(JSContext *cx, HandleObject obj, HandleId id, HandleVa
if (!receiver->is<NativeObject>())
return DefineProperty(cx, receiver, id, v, getter, setter, attrs, result);
// If the receiver is native, there is one more legacy wrinkle: the class
// JSSetterOp is called after defining the new property.
Rooted<NativeObject*> nativeReceiver(cx, &receiver->as<NativeObject>());
return DefinePropertyOrElement(cx, nativeReceiver, id, getter, setter, attrs, v, true, result);
}
@ -2051,15 +2024,15 @@ js::SetPropertyByDefining(JSContext *cx, HandleObject obj, HandleId id, HandleVa
// 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, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult &result)
js::SetPropertyOnProto(JSContext *cx, HandleObject obj, HandleObject receiver,
HandleId id, MutableHandleValue vp, ObjectOpResult &result)
{
MOZ_ASSERT(!obj->is<ProxyObject>());
RootedObject proto(cx, obj->getProto());
if (proto)
return SetProperty(cx, proto, id, v, receiver, result);
return SetPropertyByDefining(cx, obj, id, v, receiver, false, result);
return SetProperty(cx, proto, receiver, id, vp, result);
return SetPropertyByDefining(cx, obj, receiver, id, vp, false, result);
}
/*
@ -2068,20 +2041,22 @@ js::SetPropertyOnProto(JSContext *cx, HandleObject obj, HandleId id, HandleValue
*
* FIXME: This should be updated to follow ES6 draft rev 28, section 9.1.9,
* steps 4.d.i and 5.
*
* Note that receiver is not necessarily native.
*/
static bool
SetNonexistentProperty(JSContext *cx, HandleNativeObject obj, HandleId id, HandleValue v,
HandleValue receiver, QualifiedBool qualified, ObjectOpResult &result)
SetNonexistentProperty(JSContext *cx, HandleNativeObject obj, HandleObject receiver, HandleId id,
QualifiedBool qualified, HandleValue v, ObjectOpResult &result)
{
// We should never add properties to lexical blocks.
MOZ_ASSERT_IF(receiver.isObject(), !receiver.toObject().is<BlockObject>());
MOZ_ASSERT(!receiver->is<BlockObject>());
if (!qualified && receiver.isObject() && receiver.toObject().isUnqualifiedVarObj()) {
if (receiver->isUnqualifiedVarObj() && !qualified) {
if (!MaybeReportUndeclaredVarAssignment(cx, JSID_TO_STRING(id)))
return false;
}
return SetPropertyByDefining(cx, obj, id, v, receiver, false, result);
return SetPropertyByDefining(cx, obj, receiver, id, v, false, result);
}
/*
@ -2089,12 +2064,12 @@ SetNonexistentProperty(JSContext *cx, HandleNativeObject obj, HandleId id, Handl
* array element.
*/
static bool
SetDenseOrTypedArrayElement(JSContext *cx, HandleNativeObject obj, uint32_t index, HandleValue v,
ObjectOpResult &result)
SetDenseOrTypedArrayElement(JSContext *cx, HandleNativeObject obj, uint32_t index,
MutableHandleValue vp, ObjectOpResult &result)
{
if (IsAnyTypedArray(obj)) {
double d;
if (!ToNumber(cx, v, &d))
if (!ToNumber(cx, vp, &d))
return false;
// Silently do nothing for out-of-bounds sets, for consistency with
@ -2116,152 +2091,128 @@ SetDenseOrTypedArrayElement(JSContext *cx, HandleNativeObject obj, uint32_t inde
if (!obj->maybeCopyElementsForWrite(cx))
return false;
obj->setDenseElementWithType(cx, index, v);
obj->setDenseElementWithType(cx, index, vp);
return result.succeed();
}
/*
* Finish assignment to a shapeful data property of a native object obj. This
* Finish assignment to a shapeful property of a native object obj. This
* conforms to no standard and there is a lot of legacy baggage here.
*/
static bool
NativeSetExistingDataProperty(JSContext *cx, HandleNativeObject obj, HandleShape shape,
HandleValue v, HandleValue receiver, ObjectOpResult &result)
NativeSet(JSContext *cx, HandleNativeObject obj, HandleObject receiver,
HandleShape shape, MutableHandleValue vp, ObjectOpResult &result)
{
MOZ_ASSERT(obj->isNative());
MOZ_ASSERT(shape->isDataDescriptor());
if (shape->hasDefaultSetter()) {
if (shape->hasSlot()) {
// The common path. Standard data property.
if (shape->hasSlot()) {
/* If shape has a stub setter, just store vp. */
if (shape->hasDefaultSetter()) {
// Global properties declared with 'var' will be initially
// defined with an undefined value, so don't treat the initial
// assignments to such properties as overwrites.
bool overwriting = !obj->is<GlobalObject>() || !obj->getSlot(shape->slot()).isUndefined();
obj->setSlotWithType(cx, shape, v, overwriting);
obj->setSlotWithType(cx, shape, vp, overwriting);
return result.succeed();
}
// Bizarre: shared (slotless) property that's writable but has no
// JSSetterOp. JS code can't define such a property, but it can be done
// through the JSAPI. Treat it as non-writable.
return result.fail(JSMSG_GETTER_ONLY);
}
MOZ_ASSERT(!obj->is<DynamicWithObject>()); // See bug 1128681.
if (!shape->hasSlot()) {
/*
* Allow API consumers to create shared properties with stub setters.
* Such properties effectively function as data descriptors which are
* not writable, so attempting to set such a property should do nothing
* or throw if we're in strict mode.
*/
if (!shape->hasGetterValue() && shape->hasDefaultSetter())
return result.fail(JSMSG_GETTER_ONLY);
}
RootedValue ovp(cx, vp);
uint32_t sample = cx->runtime()->propertyRemovals;
RootedId id(cx, shape->propid());
RootedValue value(cx, v);
if (!CallJSSetterOp(cx, shape->setterOp(), obj, id, &value, result))
if (!shape->set(cx, obj, receiver, vp, result))
return false;
// Update any slot for the shape with the value produced by the setter,
// unless the setter deleted the shape.
/*
* Update any slot for the shape with the value produced by the setter,
* unless the setter deleted the shape.
*/
if (shape->hasSlot() &&
(MOZ_LIKELY(cx->runtime()->propertyRemovals == sample) ||
obj->contains(cx, shape)))
{
obj->setSlot(shape->slot(), value);
obj->setSlot(shape->slot(), vp);
}
return true; // result is populated by CallJSSetterOp above.
return true; // result is populated by shape->set() above.
}
/*
* Finish the assignment `receiver[id] = v` when an existing property (shape)
* has been found on a native object (pobj). This implements ES6 draft rev 32
* (2015 Feb 2) 9.1.9 steps 5 and 6.
* Implement "the rest of" assignment to receiver[id] when an existing property
* (shape) has been found on a native object (pobj).
*
* It is necessary to pass both id and shape because shape could be an implicit
* dense or typed array element (i.e. not actually a pointer to a Shape).
*/
static bool
SetExistingProperty(JSContext *cx, HandleNativeObject obj, HandleId id, HandleValue v,
HandleValue receiver, HandleNativeObject pobj, HandleShape shape,
SetExistingProperty(JSContext *cx, HandleNativeObject obj, HandleObject receiver, HandleId id,
HandleNativeObject pobj, HandleShape shape, MutableHandleValue vp,
ObjectOpResult &result)
{
// Step 5 for dense elements.
if (IsImplicitDenseOrTypedArrayElement(shape)) {
// Step 5.a is a no-op: all dense elements are writable.
/* 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, result);
} else {
/* ES5 8.12.4 [[Put]] step 2. */
if (shape->isAccessorDescriptor()) {
if (shape->hasDefaultSetter())
return result.fail(JSMSG_GETTER_ONLY);
} else {
MOZ_ASSERT(shape->isDataDescriptor());
if (!shape->writable())
return result.fail(JSMSG_READ_ONLY);
}
// Pure optimization for the common case:
if (receiver.isObject() && pobj == &receiver.toObject())
return SetDenseOrTypedArrayElement(cx, pobj, JSID_TO_INT(id), v, result);
// Steps 5.b-f.
return SetPropertyByDefining(cx, obj, id, v, receiver, obj == pobj, result);
}
// Step 5 for all other properties.
if (shape->isDataDescriptor()) {
// Step 5.a.
if (!shape->writable())
return result.fail(JSMSG_READ_ONLY);
// steps 5.c-f.
if (receiver.isObject() && pobj == &receiver.toObject()) {
// Pure optimization for the common case. There's no point performing
// the lookup in step 5.c again, as our caller just did it for us. The
// result is |shape|.
// Steps 5.e.i-ii.
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(), v, result);
return ArraySetLength(cx, arr, id, shape->attributes(), vp, result);
}
return NativeSetExistingDataProperty(cx, obj, shape, v, receiver, result);
return NativeSet(cx, obj, receiver, shape, vp, result);
}
// SpiderMonkey special case: assigning to an inherited slotless
// property causes the setter to be called, instead of shadowing,
// unless the existing property is JSPROP_SHADOWABLE (see bug 552432)
// or it's the array length property.
if (!shape->hasSlot() &&
!shape->hasShadowable() &&
// pobj[id] is not an own property of receiver. Call the setter or shadow it.
if (!shape->shadowable() &&
!(pobj->is<ArrayObject>() && id == NameToId(cx->names().length)))
{
// Even weirder sub-special-case: inherited slotless data property
// with default setter. Wut.
if (shape->hasDefaultSetter())
// Weird special case: slotless property with default setter.
if (shape->hasDefaultSetter() && !shape->hasGetterValue())
return result.succeed();
RootedValue valCopy(cx, v);
return CallJSSetterOp(cx, shape->setterOp(), obj, id, &valCopy, result);
return shape->set(cx, obj, receiver, vp, result);
}
// Shadow pobj[id] by defining a new data property receiver[id].
// Delegate everything to SetPropertyByDefining.
return SetPropertyByDefining(cx, obj, id, v, receiver, obj == pobj, result);
}
// Steps 6-11.
MOZ_ASSERT(shape->isAccessorDescriptor());
MOZ_ASSERT_IF(!shape->hasSetterObject(), shape->hasDefaultSetter());
if (shape->hasDefaultSetter())
return result.fail(JSMSG_GETTER_ONLY);
Value setter = ObjectValue(*shape->setterObject());
if (!InvokeSetter(cx, receiver, setter, v))
return false;
return result.succeed();
// Shadow pobj[id] by defining a new data property receiver[id].
return SetPropertyByDefining(cx, obj, receiver, id, vp, obj == pobj, result);
}
bool
js::NativeSetProperty(JSContext *cx, HandleNativeObject obj, HandleId id, HandleValue value,
HandleValue receiver, QualifiedBool qualified, ObjectOpResult &result)
js::NativeSetProperty(JSContext *cx, HandleNativeObject obj, HandleObject receiver, HandleId id,
QualifiedBool qualified, MutableHandleValue vp, ObjectOpResult &result)
{
// Fire watchpoints, if any.
RootedValue v(cx, value);
if (MOZ_UNLIKELY(obj->watched())) {
WatchpointMap *wpmap = cx->compartment()->watchpointMap;
if (wpmap && !wpmap->triggerWatchpoint(cx, obj, id, &v))
if (wpmap && !wpmap->triggerWatchpoint(cx, obj, id, vp))
return false;
}
// Step numbers below reference ES6 rev 27 9.1.9, the [[Set]] internal
// method for ordinary objects. We substitute our own names for these names
// used in the spec: O -> pobj, P -> id, ownDesc -> shape.
// used in the spec: O -> pobj, P -> id, V -> *vp, ownDesc -> shape.
RootedShape shape(cx);
RootedNativeObject pobj(cx, obj);
@ -2276,7 +2227,7 @@ js::NativeSetProperty(JSContext *cx, HandleNativeObject obj, HandleId id, Handle
if (shape) {
// Steps 5-6.
return SetExistingProperty(cx, obj, id, v, receiver, pobj, shape, result);
return SetExistingProperty(cx, obj, receiver, id, pobj, shape, vp, result);
}
// Steps 4.a-b. The check for 'done' on this next line is tricky.
@ -2290,7 +2241,7 @@ js::NativeSetProperty(JSContext *cx, HandleNativeObject obj, HandleId id, Handle
RootedObject proto(cx, done ? nullptr : pobj->getProto());
if (!proto) {
// Step 4.d.i (and step 5).
return SetNonexistentProperty(cx, obj, id, v, receiver, qualified, result);
return SetNonexistentProperty(cx, obj, receiver, id, qualified, vp, result);
}
// Step 4.c.i. If the prototype is also native, this step is a
@ -2307,23 +2258,23 @@ js::NativeSetProperty(JSContext *cx, HandleNativeObject obj, HandleId id, Handle
if (!HasProperty(cx, proto, id, &found))
return false;
if (!found)
return SetNonexistentProperty(cx, obj, id, v, receiver, qualified, result);
return SetNonexistentProperty(cx, obj, receiver, id, qualified, vp, result);
}
return SetProperty(cx, proto, id, v, receiver, result);
return SetProperty(cx, proto, receiver, id, vp, result);
}
pobj = &proto->as<NativeObject>();
}
}
bool
js::NativeSetElement(JSContext *cx, HandleNativeObject obj, uint32_t index, HandleValue v,
HandleValue receiver, ObjectOpResult &result)
js::NativeSetElement(JSContext *cx, HandleNativeObject obj, HandleObject receiver, uint32_t index,
MutableHandleValue vp, ObjectOpResult &result)
{
RootedId id(cx);
if (!IndexToId(cx, index, &id))
return false;
return NativeSetProperty(cx, obj, id, v, receiver, Qualified, result);
return NativeSetProperty(cx, obj, receiver, id, Qualified, vp, result);
}
/*** [[Delete]] **********************************************************************************/

View file

@ -1255,11 +1255,6 @@ IsObjectValueInCompartment(Value v, JSCompartment *comp)
* (9.4.2), Strings (9.4.3), and so on.
*/
extern bool
NativeDefineProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleId id,
Handle<PropertyDescriptor> desc,
ObjectOpResult &result);
extern bool
NativeDefineProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleId id, HandleValue value,
JSGetterOp getter, JSSetterOp setter, unsigned attrs,
@ -1312,12 +1307,12 @@ NativeGetElement(JSContext *cx, HandleNativeObject obj, uint32_t index, MutableH
}
bool
SetPropertyByDefining(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
HandleValue receiver, bool objHasOwn, ObjectOpResult &result);
SetPropertyByDefining(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id,
HandleValue v, bool objHasOwn, ObjectOpResult &result);
bool
SetPropertyOnProto(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult &result);
SetPropertyOnProto(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id,
MutableHandleValue vp, ObjectOpResult &result);
/*
* Indicates whether an assignment operation is qualified (`x.y = 0`) or
@ -1332,12 +1327,12 @@ enum QualifiedBool {
};
extern bool
NativeSetProperty(JSContext *cx, HandleNativeObject obj, HandleId id, HandleValue v,
HandleValue receiver, QualifiedBool qualified, ObjectOpResult &result);
NativeSetProperty(JSContext *cx, HandleNativeObject obj, HandleObject receiver, HandleId id,
QualifiedBool qualified, MutableHandleValue vp, ObjectOpResult &result);
extern bool
NativeSetElement(JSContext *cx, HandleNativeObject obj, uint32_t index, HandleValue v,
HandleValue receiver, ObjectOpResult &result);
NativeSetElement(JSContext *cx, HandleNativeObject obj, HandleObject receiver, uint32_t index,
MutableHandleValue vp, ObjectOpResult &result);
extern bool
NativeDeleteProperty(JSContext *cx, HandleNativeObject obj, HandleId id, ObjectOpResult &result);
@ -1448,21 +1443,21 @@ js::GetPropertyNoGC(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, V
}
inline bool
js::SetProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult &result)
js::SetProperty(JSContext *cx, HandleObject obj, HandleObject receiver,
HandleId id, MutableHandleValue vp, ObjectOpResult &result)
{
if (obj->getOps()->setProperty)
return JSObject::nonNativeSetProperty(cx, obj, id, v, receiver, result);
return NativeSetProperty(cx, obj.as<NativeObject>(), id, v, receiver, Qualified, result);
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, uint32_t index, HandleValue v,
HandleValue receiver, ObjectOpResult &result)
js::SetElement(JSContext *cx, HandleObject obj, HandleObject receiver, uint32_t index,
MutableHandleValue vp, ObjectOpResult &result)
{
if (obj->getOps()->setProperty)
return JSObject::nonNativeSetElement(cx, obj, index, v, receiver, result);
return NativeSetElement(cx, obj.as<NativeObject>(), index, v, receiver, result);
return JSObject::nonNativeSetElement(cx, obj, receiver, index, vp, result);
return NativeSetElement(cx, obj.as<NativeObject>(), receiver, index, vp, result);
}
#endif /* vm_NativeObject_h */

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, id, optimizedOut))
if (!SetProperty(cx, callobj, callobj, id, &optimizedOut))
return nullptr;
}
@ -469,11 +469,12 @@ with_LookupProperty(JSContext *cx, HandleObject obj, HandleId id,
}
static bool
with_DefineProperty(JSContext *cx, HandleObject obj, HandleId id, Handle<PropertyDescriptor> desc,
with_DefineProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue value,
JSGetterOp getter, JSSetterOp setter, unsigned attrs,
ObjectOpResult &result)
{
RootedObject actual(cx, &obj->as<DynamicWithObject>().object());
return DefineProperty(cx, actual, id, desc, result);
return DefineProperty(cx, actual, id, value, getter, setter, attrs, result);
}
static bool
@ -492,14 +493,14 @@ with_GetProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandleI
}
static bool
with_SetProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult &result)
with_SetProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id,
MutableHandleValue vp, ObjectOpResult &result)
{
RootedObject actual(cx, &obj->as<DynamicWithObject>().object());
RootedValue actualReceiver(cx, receiver);
if (receiver.isObject() && &receiver.toObject() == obj)
actualReceiver.setObject(*actual);
return SetProperty(cx, actual, id, v, actualReceiver, result);
RootedObject actualReceiver(cx, receiver);
if (receiver == obj)
actualReceiver = actual;
return SetProperty(cx, actual, actualReceiver, id, vp, result);
}
static bool
@ -930,8 +931,8 @@ uninitialized_GetProperty(JSContext *cx, HandleObject obj, HandleObject receiver
}
static bool
uninitialized_SetProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult &result)
uninitialized_SetProperty(JSContext *cx, HandleObject obj, HandleObject receiver, HandleId id,
MutableHandleValue vp, ObjectOpResult &result)
{
ReportUninitializedLexicalId(cx, id);
return false;
@ -1593,8 +1594,8 @@ class DebugScopeProxy : public BaseProxyHandler
}
}
bool set(JSContext *cx, HandleObject proxy, HandleId id, HandleValue v, HandleValue receiver,
ObjectOpResult &result) const override
bool set(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id,
MutableHandleValue vp, ObjectOpResult &result) const override
{
Rooted<DebugScopeObject*> debugScope(cx, &proxy->as<DebugScopeObject>());
Rooted<ScopeObject*> scope(cx, &proxy->as<DebugScopeObject>().scope());
@ -1603,25 +1604,21 @@ class DebugScopeProxy : public BaseProxyHandler
return Throw(cx, id, JSMSG_DEBUG_CANT_SET_OPT_ENV);
AccessResult access;
RootedValue valCopy(cx, v);
if (!handleUnaliasedAccess(cx, debugScope, scope, id, SET, &valCopy, &access))
if (!handleUnaliasedAccess(cx, debugScope, scope, id, SET, vp, &access))
return false;
switch (access) {
case ACCESS_UNALIASED:
return result.succeed();
case ACCESS_GENERIC:
{
RootedValue scopeVal(cx, ObjectValue(*scope));
return SetProperty(cx, scope, id, v, scopeVal, result);
}
return SetProperty(cx, scope, scope, id, vp, result);
default:
MOZ_CRASH("bad AccessResult");
}
}
bool defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
Handle<PropertyDescriptor> desc,
MutableHandle<PropertyDescriptor> desc,
ObjectOpResult &result) const override
{
Rooted<ScopeObject*> scope(cx, &proxy->as<DebugScopeObject>().scope());

View file

@ -336,10 +336,10 @@ js::intrinsic_UnsafePutElements(JSContext *cx, unsigned argc, Value *vp)
if (IsAnyTypedArray(arrobj.get()) || arrobj->is<TypedObject>()) {
MOZ_ASSERT_IF(IsAnyTypedArray(arrobj.get()), idx < AnyTypedArrayLength(arrobj.get()));
MOZ_ASSERT_IF(arrobj->is<TypedObject>(), idx < uint32_t(arrobj->as<TypedObject>().length()));
RootedValue tmp(cx, args[elemi]);
// XXX: Always non-strict.
ObjectOpResult ignored;
RootedValue receiver(cx, ObjectValue(*arrobj));
if (!SetElement(cx, arrobj, idx, args[elemi], receiver, ignored))
if (!SetElement(cx, arrobj, arrobj, idx, &tmp, ignored))
return false;
} else {
MOZ_ASSERT(idx < arrobj->as<ArrayObject>().getDenseInitializedLength());

View file

@ -39,6 +39,30 @@ Shape::search(ExclusiveContext *cx, jsid id)
return search(cx, this, id, &_);
}
inline bool
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();
if (!InvokeGetterOrSetter(cx, receiver, fval, 1, vp.address(), vp))
return false;
return result.succeed();
}
if (attrs & JSPROP_GETTER)
return result.fail(JSMSG_GETTER_ONLY);
if (!setterOp())
return result.succeed();
RootedId id(cx, propid());
return CallJSSetterOp(cx, setterOp(), obj, id, vp, result);
}
/* static */ inline Shape *
Shape::search(ExclusiveContext *cx, Shape *start, jsid id, ShapeTable::Entry **pentry, bool adding)
{

View file

@ -1019,7 +1019,16 @@ class Shape : public gc::TenuredCell
return (attrs & (JSPROP_SETTER | JSPROP_GETTER)) != 0;
}
bool hasShadowable() const { return attrs & JSPROP_SHADOWABLE; }
/*
* For ES5 compatibility, we allow properties with SetterOp-flavored
* setters to be shadowed when set. The "own" property thereby created in
* the directly referenced object will have the same getter and setter as
* the prototype property. See bug 552432.
*/
bool shadowable() const {
MOZ_ASSERT_IF(isDataDescriptor(), writable());
return hasSlot() || (attrs & JSPROP_SHADOWABLE);
}
uint32_t entryCount() {
if (hasTable())

View file

@ -679,16 +679,16 @@ UnboxedPlainObject::obj_lookupProperty(JSContext *cx, HandleObject obj,
}
/* static */ bool
UnboxedPlainObject::obj_defineProperty(JSContext *cx, HandleObject obj, HandleId id,
Handle<JSPropertyDescriptor> desc,
UnboxedPlainObject::obj_defineProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
GetterOp getter, SetterOp setter, unsigned attrs,
ObjectOpResult &result)
{
const UnboxedLayout &layout = obj->as<UnboxedPlainObject>().layout();
if (const UnboxedLayout::Property *property = layout.lookup(id)) {
if (!desc.getter() && !desc.setter() && desc.attributes() == JSPROP_ENUMERATE) {
if (!getter && !setter && attrs == JSPROP_ENUMERATE) {
// This define is equivalent to setting an existing property.
if (obj->as<UnboxedPlainObject>().setValue(cx, *property, desc.value()))
if (obj->as<UnboxedPlainObject>().setValue(cx, *property, v))
return true;
}
@ -697,8 +697,7 @@ UnboxedPlainObject::obj_defineProperty(JSContext *cx, HandleObject obj, HandleId
if (!convertToNative(cx, obj))
return false;
return DefineProperty(cx, obj, id, desc, result) &&
result.checkStrict(cx, obj, id);
return DefineProperty(cx, obj, id, v, getter, setter, attrs);
}
// Define the property on the expando object.
@ -707,9 +706,9 @@ UnboxedPlainObject::obj_defineProperty(JSContext *cx, HandleObject obj, HandleId
return false;
// Update property types on the unboxed object as well.
AddTypePropertyId(cx, obj, id, desc.value());
AddTypePropertyId(cx, obj, id, v);
return DefineProperty(cx, expando, id, desc, result);
return DefineProperty(cx, expando, id, v, getter, setter, attrs, result);
}
/* static */ bool
@ -758,38 +757,36 @@ UnboxedPlainObject::obj_getProperty(JSContext *cx, HandleObject obj, HandleObjec
}
/* static */ bool
UnboxedPlainObject::obj_setProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult &result)
UnboxedPlainObject::obj_setProperty(JSContext *cx, HandleObject obj, HandleObject receiver,
HandleId id, MutableHandleValue vp, ObjectOpResult &result)
{
const UnboxedLayout &layout = obj->as<UnboxedPlainObject>().layout();
if (const UnboxedLayout::Property *property = layout.lookup(id)) {
if (receiver.isObject() && obj == &receiver.toObject()) {
if (obj->as<UnboxedPlainObject>().setValue(cx, *property, v))
if (obj == receiver) {
if (obj->as<UnboxedPlainObject>().setValue(cx, *property, vp))
return result.succeed();
if (!convertToNative(cx, obj))
return false;
return SetProperty(cx, obj, id, v, receiver, result);
return SetProperty(cx, obj, receiver, id, vp, result);
}
return SetPropertyByDefining(cx, obj, id, v, receiver, false, result);
return SetPropertyByDefining(cx, obj, receiver, id, vp, false, result);
}
if (UnboxedExpandoObject *expando = obj->as<UnboxedPlainObject>().maybeExpando()) {
if (expando->containsShapeOrElement(cx, id)) {
// Update property types on the unboxed object as well.
AddTypePropertyId(cx, obj, id, v);
AddTypePropertyId(cx, obj, id, vp);
RootedObject nexpando(cx, expando);
RootedValue nreceiver(cx, (receiver.isObject() && obj == &receiver.toObject())
? ObjectValue(*expando)
: receiver);
return SetProperty(cx, nexpando, id, v, nreceiver, result);
RootedObject nreceiver(cx, (obj == receiver) ? expando : receiver.get());
return SetProperty(cx, nexpando, nreceiver, id, vp, result);
}
}
return SetPropertyOnProto(cx, obj, id, v, receiver, result);
return SetPropertyOnProto(cx, obj, receiver, id, vp, result);
}
/* static */ bool

View file

@ -192,8 +192,8 @@ class UnboxedPlainObject : public JSObject
HandleId id, MutableHandleObject objp,
MutableHandleShape propp);
static bool obj_defineProperty(JSContext *cx, HandleObject obj, HandleId id,
Handle<JSPropertyDescriptor> desc,
static bool obj_defineProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
GetterOp getter, SetterOp setter, unsigned attrs,
ObjectOpResult &result);
static bool obj_hasProperty(JSContext *cx, HandleObject obj, HandleId id, bool *foundp);
@ -201,8 +201,8 @@ class UnboxedPlainObject : public JSObject
static bool obj_getProperty(JSContext *cx, HandleObject obj, HandleObject receiver,
HandleId id, MutableHandleValue vp);
static bool obj_setProperty(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult &result);
static bool obj_setProperty(JSContext *cx, HandleObject obj, HandleObject receiver,
HandleId id, MutableHandleValue vp, ObjectOpResult &result);
static bool obj_getOwnPropertyDescriptor(JSContext *cx, HandleObject obj, HandleId id,
MutableHandle<JSPropertyDescriptor> desc);

View file

@ -33,7 +33,7 @@ static const uint32_t XDR_BYTECODE_VERSION_SUBTRAHEND = 265;
static const uint32_t XDR_BYTECODE_VERSION =
uint32_t(0xb973c0de - XDR_BYTECODE_VERSION_SUBTRAHEND);
static_assert(JSErr_Limit == 389,
static_assert(JSErr_Limit == 388,
"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 "

View file

@ -733,12 +733,12 @@ xpc::SandboxProxyHandler::get(JSContext *cx, JS::Handle<JSObject*> proxy,
bool
xpc::SandboxProxyHandler::set(JSContext *cx, JS::Handle<JSObject*> proxy,
JS::Handle<JSObject*> receiver,
JS::Handle<jsid> id,
JS::Handle<Value> v,
JS::Handle<Value> receiver,
JS::MutableHandle<Value> vp,
JS::ObjectOpResult &result) const
{
return BaseProxyHandler::set(cx, proxy, id, v, receiver, result);
return BaseProxyHandler::set(cx, proxy, receiver, id, vp, result);
}
bool

View file

@ -426,6 +426,14 @@ XPC_WN_OnlyIWrite_AddPropertyStub(JSContext *cx, HandleObject obj, HandleId id,
return Throw(NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN, cx);
}
static bool
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);
}
static bool
XPC_WN_CannotModifyPropertyStub(JSContext *cx, HandleObject obj, HandleId id,
MutableHandleValue vp)
@ -644,7 +652,7 @@ const XPCWrappedNativeJSClass XPC_WN_NoHelper_JSClass = {
XPC_WN_OnlyIWrite_AddPropertyStub, // addProperty
XPC_WN_CantDeletePropertyStub, // delProperty
nullptr, // getProperty
nullptr, // setProperty
XPC_WN_OnlyIWrite_SetPropertyStub, // setProperty
XPC_WN_Shared_Enumerate, // enumerate
XPC_WN_NoHelper_Resolve, // resolve
@ -1353,6 +1361,14 @@ XPC_WN_OnlyIWrite_Proto_AddPropertyStub(JSContext *cx, HandleObject obj, HandleI
return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);
}
static bool
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);
}
static bool
XPC_WN_NoMods_Proto_Resolve(JSContext *cx, HandleObject obj, HandleId id, bool *resolvedp)
{
@ -1388,7 +1404,7 @@ const js::Class XPC_WN_NoMods_WithCall_Proto_JSClass = {
XPC_WN_OnlyIWrite_Proto_AddPropertyStub, // addProperty;
XPC_WN_CantDeletePropertyStub, // delProperty;
nullptr, // getProperty;
nullptr, // setProperty;
XPC_WN_OnlyIWrite_Proto_SetPropertyStub, // setProperty;
XPC_WN_Shared_Proto_Enumerate, // enumerate;
XPC_WN_NoMods_Proto_Resolve, // resolve;
nullptr, // convert;
@ -1413,7 +1429,7 @@ const js::Class XPC_WN_NoMods_NoCall_Proto_JSClass = {
XPC_WN_OnlyIWrite_Proto_AddPropertyStub, // addProperty;
XPC_WN_CantDeletePropertyStub, // delProperty;
nullptr, // getProperty;
nullptr, // setProperty;
XPC_WN_OnlyIWrite_Proto_SetPropertyStub, // setProperty;
XPC_WN_Shared_Proto_Enumerate, // enumerate;
XPC_WN_NoMods_Proto_Resolve, // resolve;
nullptr, // convert;
@ -1508,7 +1524,7 @@ const js::Class XPC_WN_Tearoff_JSClass = {
XPC_WN_OnlyIWrite_AddPropertyStub, // addProperty;
XPC_WN_CantDeletePropertyStub, // delProperty;
nullptr, // getProperty;
nullptr, // setProperty;
XPC_WN_OnlyIWrite_SetPropertyStub, // setProperty;
XPC_WN_TearOff_Enumerate, // enumerate;
XPC_WN_TearOff_Resolve, // resolve;
XPC_WN_Shared_Convert, // convert;

View file

@ -1,175 +0,0 @@
// Test that it's not possible to create expando properties on XPCWNs.
// See <https://bugzilla.mozilla.org/show_bug.cgi?id=1143810#c5>.
const Cc = Components.classes;
const Ci = Components.interfaces;
function check_throws(f) {
try {
f();
} catch (exc) {
return;
}
throw new TypeError("Expected exception, no exception thrown");
}
/*
* Test that XPCWrappedNative objects do not permit expando properties to be created.
*
* This function is called twice. The first time, realObj is an nsITimer XPCWN
* and accessObj === realObj.
*
* The second time, accessObj is a scripted proxy with realObj as its target.
* So the second time we are testing that scripted proxies don't magically
* bypass whatever mechanism enforces the expando policy on XPCWNs.
*/
function test_tamperproof(realObj, accessObj, {method, constant, attribute}) {
// Assignment can't create an expando property.
check_throws(function () { accessObj.expando = 14; });
do_check_false("expando" in realObj);
// Strict assignment throws.
check_throws(function () { "use strict"; accessObj.expando = 14; });
do_check_false("expando" in realObj);
// Assignment to an inherited method name doesn't work either.
check_throws(function () { accessObj.hasOwnProperty = () => "lies"; });
check_throws(function () { "use strict"; accessObj.hasOwnProperty = () => "lies"; });
do_check_false(realObj.hasOwnProperty("hasOwnProperty"));
// Assignment to a method name doesn't work either.
let originalMethod;
if (method) {
originalMethod = accessObj[method];
accessObj[method] = "nope"; // non-writable data property, no exception in non-strict code
check_throws(function () { "use strict"; accessObj[method] = "nope"; });
do_check_true(realObj[method] === originalMethod);
}
// A constant is the same thing.
let originalConstantValue;
if (constant) {
originalConstantValue = accessObj[constant];
accessObj[constant] = "nope";
do_check_eq(realObj[constant], originalConstantValue);
check_throws(function () { "use strict"; accessObj[constant] = "nope"; });
do_check_eq(realObj[constant], originalConstantValue);
}
// Assignment to a readonly accessor property with no setter doesn't work either.
let originalAttributeDesc;
if (attribute) {
originalAttributeDesc = Object.getOwnPropertyDescriptor(realObj, attribute);
do_check_true("set" in originalAttributeDesc);
do_check_true(originalAttributeDesc.set === undefined);
accessObj[attribute] = "nope"; // accessor property with no setter: no exception in non-strict code
check_throws(function () { "use strict"; accessObj[attribute] = "nope"; });
let desc = Object.getOwnPropertyDescriptor(realObj, attribute);
do_check_true("set" in desc);
do_check_eq(originalAttributeDesc.get, desc.get);
do_check_eq(undefined, desc.set);
}
// Reflect.set doesn't work either.
if (this.Reflect && this.Reflect.set)
throw new Error("Congratulations on implementing Reflect.set! Here are some tests to uncomment.");
/*
if (method) {
do_check_false(Reflect.set({}, method, "bad", accessObj));
do_check_eq(realObj[method], originalMethod);
}
if (attribute) {
do_check_false(Reflect.set({}, attribute, "bad", accessObj));
do_check_eq(originalAttributeDesc.get, Object.getOwnPropertyDescriptor(realObj, attribute).get);
}
*/
// Object.defineProperty can't do anything either.
let names = ["expando"];
if (method) names.push(method);
if (constant) names.push(constant);
if (attribute) names.push(attribute);
for (let name of names) {
let originalDesc = Object.getOwnPropertyDescriptor(realObj, name);
check_throws(function () {
Object.defineProperty(accessObj, name, {configurable: true});
});
check_throws(function () {
Object.defineProperty(accessObj, name, {writable: true});
});
check_throws(function () {
Object.defineProperty(accessObj, name, {get: function () { return "lies"; }});
});
check_throws(function () {
Object.defineProperty(accessObj, name, {value: "bad"});
});
let desc = Object.getOwnPropertyDescriptor(realObj, name);
if (originalDesc === undefined) {
do_check_eq(undefined, desc);
} else {
do_check_eq(originalDesc.configurable, desc.configurable);
do_check_eq(originalDesc.enumerable, desc.enumerable);
do_check_eq(originalDesc.writable, desc.writable);
do_check_eq(originalDesc.value, desc.value);
do_check_eq(originalDesc.get, desc.get);
do_check_eq(originalDesc.set, desc.set);
}
}
// Existing properties can't be deleted.
if (method) {
do_check_false(delete accessObj[method]);
check_throws(function () { "use strict"; delete accessObj[method]; });
do_check_eq(realObj[method], originalMethod);
}
if (constant) {
do_check_false(delete accessObj[constant]);
check_throws(function () { "use strict"; delete accessObj[constant]; });
do_check_eq(realObj[constant], originalConstantValue);
}
if (attribute) {
do_check_false(delete accessObj[attribute]);
check_throws(function () { "use strict"; delete accessObj[attribute]; });
desc = Object.getOwnPropertyDescriptor(realObj, attribute);
do_check_eq(originalAttributeDesc.get, desc.get);
}
}
function test_twice(obj, options) {
test_tamperproof(obj, obj, options);
let handler = {
getPrototypeOf(t) {
return new Proxy(Object.getPrototypeOf(t), handler);
}
};
test_tamperproof(obj, new Proxy(obj, handler), options);
}
function run_test() {
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
test_twice(timer, {
method: "init",
constant: "TYPE_ONE_SHOT",
attribute: "callback"
});
let principal = Cc["@mozilla.org/nullprincipal;1"].createInstance(Ci.nsIPrincipal);
test_twice(principal, {});
test_twice(Object.getPrototypeOf(principal), {
method: "subsumes",
constant: "APP_STATUS_INSTALLED",
attribute: "origin"
});
// Test a tearoff object.
Components.manager.autoRegister(do_get_file('../components/js/xpctest.manifest'));
let b = Cc["@mozilla.org/js/xpc/test/js/TestInterfaceAll;1"].createInstance(Ci.nsIXPCTestInterfaceB);
let tearoff = b.nsIXPCTestInterfaceA;
test_twice(tearoff, {
method: "QueryInterface"
});
}

View file

@ -109,6 +109,5 @@ head = head_watchdog.js
[test_watchdog_hibernate.js]
head = head_watchdog.js
[test_writeToGlobalPrototype.js]
[test_xpcwn_tamperproof.js]
[test_xrayed_iterator.js]
[test_xray_SavedFrame.js]

View file

@ -119,24 +119,24 @@ AddonWrapper<Base>::get(JSContext *cx, JS::Handle<JSObject*> wrapper, JS::Handle
template<typename Base>
bool
AddonWrapper<Base>::set(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id, JS::HandleValue v,
JS::HandleValue receiver, JS::ObjectOpResult &result) const
AddonWrapper<Base>::set(JSContext *cx, JS::HandleObject wrapper, JS::HandleObject receiver,
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, id, v, receiver, result);
return Base::set(cx, wrapper, receiver, id, vp, result);
if (desc.setter()) {
MOZ_ASSERT(desc.hasSetterObject());
JS::AutoValueVector args(cx);
if (!args.append(v))
if (!args.append(vp))
return false;
RootedValue fval(cx, ObjectValue(*desc.setterObject()));
RootedValue ignored(cx);
if (!JS::Call(cx, receiver, fval, args, &ignored))
if (!JS_CallFunctionValue(cx, receiver, fval, args, vp))
return false;
return result.succeed();
}
@ -147,8 +147,8 @@ AddonWrapper<Base>::set(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id
template<typename Base>
bool
AddonWrapper<Base>::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
Handle<JSPropertyDescriptor> desc,
ObjectOpResult &result) const
MutableHandle<JSPropertyDescriptor> desc,
JS::ObjectOpResult &result) const
{
Rooted<JSPropertyDescriptor> interpDesc(cx);
if (!Interpose(cx, wrapper, nullptr, id, &interpDesc))

View file

@ -28,14 +28,15 @@ 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::Handle<JSPropertyDescriptor> desc,
JS::MutableHandle<JSPropertyDescriptor> desc,
JS::ObjectOpResult &result) const override;
virtual bool delete_(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
JS::ObjectOpResult &result) 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::HandleId id, JS::HandleValue v,
JS::HandleValue receiver, JS::ObjectOpResult &result) const override;
virtual bool set(JSContext *cx, JS::HandleObject wrapper, JS::HandleObject receiver,
JS::HandleId id, JS::MutableHandleValue vp,
JS::ObjectOpResult &result) const override;
virtual bool getPropertyDescriptor(JSContext *cx, JS::Handle<JSObject*> wrapper,
JS::Handle<jsid> id,

View file

@ -21,7 +21,7 @@ const ChromeObjectWrapper ChromeObjectWrapper::singleton;
bool
ChromeObjectWrapper::defineProperty(JSContext *cx, HandleObject wrapper,
HandleId id,
Handle<JSPropertyDescriptor> desc,
MutableHandle<JSPropertyDescriptor> desc,
JS::ObjectOpResult &result) const
{
if (!AccessCheck::checkPassToPrivilegedCode(cx, wrapper, desc.value()))
@ -30,12 +30,13 @@ ChromeObjectWrapper::defineProperty(JSContext *cx, HandleObject wrapper,
}
bool
ChromeObjectWrapper::set(JSContext *cx, HandleObject wrapper, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult &result) const
ChromeObjectWrapper::set(JSContext *cx, HandleObject wrapper,
HandleObject receiver, HandleId id,
MutableHandleValue vp, ObjectOpResult &result) const
{
if (!AccessCheck::checkPassToPrivilegedCode(cx, wrapper, v))
if (!AccessCheck::checkPassToPrivilegedCode(cx, wrapper, vp))
return false;
return ChromeObjectWrapperBase::set(cx, wrapper, id, v, receiver, result);
return ChromeObjectWrapperBase::set(cx, wrapper, receiver, id, vp, result);
}
}

View file

@ -29,10 +29,11 @@ class ChromeObjectWrapper : public ChromeObjectWrapperBase
virtual bool defineProperty(JSContext *cx, JS::Handle<JSObject*> wrapper,
JS::Handle<jsid> id,
JS::Handle<JSPropertyDescriptor> desc,
JS::MutableHandle<JSPropertyDescriptor> desc,
JS::ObjectOpResult &result) const override;
virtual bool set(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id,
JS::HandleValue v, JS::HandleValue receiver,
virtual bool set(JSContext *cx, JS::Handle<JSObject*> wrapper,
JS::Handle<JSObject*> receiver, JS::Handle<jsid> id,
JS::MutableHandle<JS::Value> vp,
JS::ObjectOpResult &result) const override;
static const ChromeObjectWrapper singleton;

View file

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

View file

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

View file

@ -593,7 +593,7 @@ JSXrayTraits::delete_(JSContext *cx, HandleObject wrapper, HandleId id, ObjectOp
bool
JSXrayTraits::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
Handle<JSPropertyDescriptor> desc,
MutableHandle<JSPropertyDescriptor> desc,
Handle<JSPropertyDescriptor> existingDesc,
ObjectOpResult &result,
bool *defined)
@ -637,10 +637,9 @@ JSXrayTraits::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
return false;
}
Rooted<JSPropertyDescriptor> wrappedDesc(cx, desc);
JSAutoCompartment ac(cx, target);
if (!JS_WrapPropertyDescriptor(cx, &wrappedDesc) ||
!JS_DefinePropertyById(cx, target, id, wrappedDesc, result))
if (!JS_WrapPropertyDescriptor(cx, desc) ||
!JS_DefinePropertyById(cx, target, id, desc, result))
{
return false;
}
@ -1416,7 +1415,7 @@ XPCWrappedNativeXrayTraits::resolveOwnProperty(JSContext *cx, const Wrapper &jsW
bool
XPCWrappedNativeXrayTraits::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
Handle<JSPropertyDescriptor> desc,
MutableHandle<JSPropertyDescriptor> desc,
Handle<JSPropertyDescriptor> existingDesc,
JS::ObjectOpResult &result, bool *defined)
{
@ -1577,7 +1576,7 @@ DOMXrayTraits::resolveOwnProperty(JSContext *cx, const Wrapper &jsWrapper, Handl
bool
DOMXrayTraits::defineProperty(JSContext *cx, HandleObject wrapper, HandleId id,
Handle<JSPropertyDescriptor> desc,
MutableHandle<JSPropertyDescriptor> desc,
Handle<JSPropertyDescriptor> existingDesc,
JS::ObjectOpResult &result, bool *defined)
{
@ -1931,7 +1930,7 @@ XrayWrapper<Base, Traits>::getOwnPropertyDescriptor(JSContext *cx, HandleObject
// to the content object. This is ok, because the the expando object is only
// ever accessed by code across the compartment boundary.
static bool
RecreateLostWaivers(JSContext *cx, const JSPropertyDescriptor *orig,
RecreateLostWaivers(JSContext *cx, JSPropertyDescriptor *orig,
MutableHandle<JSPropertyDescriptor> wrapped)
{
// Compute whether the original objects were waived, and implicitly, whether
@ -1976,7 +1975,7 @@ RecreateLostWaivers(JSContext *cx, const JSPropertyDescriptor *orig,
template <typename Base, typename Traits>
bool
XrayWrapper<Base, Traits>::defineProperty(JSContext *cx, HandleObject wrapper,
HandleId id, Handle<JSPropertyDescriptor> desc,
HandleId id, MutableHandle<JSPropertyDescriptor> desc,
ObjectOpResult &result) const
{
assertEnteredPolicy(cx, wrapper, id, BaseProxyHandler::SET);
@ -2081,15 +2080,15 @@ XrayWrapper<Base, Traits>::get(JSContext *cx, HandleObject wrapper,
template <typename Base, typename Traits>
bool
XrayWrapper<Base, Traits>::set(JSContext *cx, HandleObject wrapper, HandleId id, HandleValue v,
HandleValue receiver, ObjectOpResult &result) const
XrayWrapper<Base, Traits>::set(JSContext *cx, HandleObject wrapper,
HandleObject receiver, HandleId id,
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.
RootedValue wrapperValue(cx, ObjectValue(*wrapper));
return js::BaseProxyHandler::set(cx, wrapper, id, v, wrapperValue, result);
return js::BaseProxyHandler::set(cx, wrapper, wrapper, id, vp, result);
}
template <typename Base, typename Traits>

View file

@ -133,7 +133,7 @@ public:
JS::HandleObject holder, JS::HandleId id,
JS::MutableHandle<JSPropertyDescriptor> desc) override;
bool defineProperty(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id,
JS::Handle<JSPropertyDescriptor> desc,
JS::MutableHandle<JSPropertyDescriptor> desc,
JS::Handle<JSPropertyDescriptor> existingDesc,
JS::ObjectOpResult &result, bool *defined);
virtual bool enumerateNames(JSContext *cx, JS::HandleObject wrapper, unsigned flags,
@ -185,7 +185,7 @@ public:
JS::HandleObject holder, JS::HandleId id,
JS::MutableHandle<JSPropertyDescriptor> desc) override;
bool defineProperty(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id,
JS::Handle<JSPropertyDescriptor> desc,
JS::MutableHandle<JSPropertyDescriptor> desc,
JS::Handle<JSPropertyDescriptor> existingDesc,
JS::ObjectOpResult &result, bool *defined);
virtual bool enumerateNames(JSContext *cx, JS::HandleObject wrapper, unsigned flags,
@ -228,7 +228,7 @@ public:
bool delete_(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id, JS::ObjectOpResult &result);
bool defineProperty(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id,
JS::Handle<JSPropertyDescriptor> desc,
JS::MutableHandle<JSPropertyDescriptor> desc,
JS::Handle<JSPropertyDescriptor> existingDesc,
JS::ObjectOpResult &result, bool *defined);
@ -346,7 +346,7 @@ public:
JS::MutableHandle<JSPropertyDescriptor> desc) override;
bool defineProperty(JSContext *cx, JS::HandleObject wrapper, JS::HandleId id,
JS::Handle<JSPropertyDescriptor> desc,
JS::MutableHandle<JSPropertyDescriptor> desc,
JS::Handle<JSPropertyDescriptor> existingDesc,
JS::ObjectOpResult &result, bool *defined)
{
@ -420,7 +420,7 @@ 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::Handle<JSPropertyDescriptor> desc,
JS::MutableHandle<JSPropertyDescriptor> desc,
JS::ObjectOpResult &result) const override;
virtual bool ownPropertyKeys(JSContext *cx, JS::Handle<JSObject*> wrapper,
JS::AutoIdVector &props) const override;
@ -441,8 +441,8 @@ class XrayWrapper : public Base {
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::Handle<JSObject*> wrapper, JS::Handle<jsid> id,
JS::Handle<JS::Value> v, JS::Handle<JS::Value> receiver,
virtual bool set(JSContext *cx, JS::Handle<JSObject*> wrapper, JS::Handle<JSObject*> receiver,
JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp,
JS::ObjectOpResult &result) const override;
virtual bool call(JSContext *cx, JS::Handle<JSObject*> wrapper,
const JS::CallArgs &args) const override;
@ -515,8 +515,8 @@ public:
bool *bp) const override;
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<jsid> id,
JS::Handle<JS::Value> v, JS::Handle<JS::Value> receiver,
virtual bool set(JSContext *cx, JS::Handle<JSObject*> proxy, JS::Handle<JSObject*> receiver,
JS::Handle<jsid> id, JS::MutableHandle<JS::Value> vp,
JS::ObjectOpResult &result) const override;
virtual bool getPropertyDescriptor(JSContext *cx, JS::Handle<JSObject*> proxy,