mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 02:14:43 +00:00
Bug 1017109 - Add construct hook for CPOWs (r=mrbkap)
This commit is contained in:
parent
3d9e496beb
commit
026f5d0e68
@ -45,6 +45,7 @@ function make_object()
|
||||
o.s = "hello";
|
||||
o.x = { i: 10 };
|
||||
o.f = function () { return 99; };
|
||||
o.ctor = function() { this.a = 3; }
|
||||
|
||||
// Doing anything with this Proxy will throw.
|
||||
var throwing = new Proxy({}, new Proxy({}, {
|
||||
|
@ -48,6 +48,8 @@
|
||||
ok(data.s === "hello", "string property");
|
||||
ok(data.x.i === 10, "nested property");
|
||||
ok(data.f() === 99, "function call");
|
||||
let obj = new data.ctor();
|
||||
ok(obj.a === 3, "constructor call");
|
||||
ok(document.title === "Hello, Kitty", "document node");
|
||||
|
||||
data.i = 6;
|
||||
|
@ -82,10 +82,10 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base
|
||||
bool *result) {
|
||||
return Answer::AnswerIsExtensible(objId, rs, result);
|
||||
}
|
||||
bool AnswerCall(const ObjectId &objId, const nsTArray<JSParam> &argv,
|
||||
ReturnStatus *rs, JSVariant *result,
|
||||
nsTArray<JSParam> *outparams) {
|
||||
return Answer::AnswerCall(objId, argv, rs, result, outparams);
|
||||
bool AnswerCallOrConstruct(const ObjectId &objId, const nsTArray<JSParam> &argv,
|
||||
const bool &construct, ReturnStatus *rs, JSVariant *result,
|
||||
nsTArray<JSParam> *outparams) {
|
||||
return Answer::AnswerCallOrConstruct(objId, argv, construct, rs, result, outparams);
|
||||
}
|
||||
bool AnswerObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
|
||||
bool *result) {
|
||||
@ -164,10 +164,10 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base
|
||||
bool *result) {
|
||||
return Base::CallIsExtensible(objId, rs, result);
|
||||
}
|
||||
bool CallCall(const ObjectId &objId, const nsTArray<JSParam> &argv,
|
||||
ReturnStatus *rs, JSVariant *result,
|
||||
nsTArray<JSParam> *outparams) {
|
||||
return Base::CallCall(objId, argv, rs, result, outparams);
|
||||
bool CallCallOrConstruct(const ObjectId &objId, const nsTArray<JSParam> &argv,
|
||||
const bool &construct, ReturnStatus *rs, JSVariant *result,
|
||||
nsTArray<JSParam> *outparams) {
|
||||
return Base::CallCallOrConstruct(objId, argv, construct, rs, result, outparams);
|
||||
}
|
||||
bool CallObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
|
||||
bool *result) {
|
||||
|
@ -36,7 +36,7 @@ both:
|
||||
rpc Set(uint64_t objId, ObjectVariant receiver, nsString id, bool strict, JSVariant value) returns (ReturnStatus rs, JSVariant result);
|
||||
|
||||
rpc IsExtensible(uint64_t objId) returns (ReturnStatus rs, bool result);
|
||||
rpc Call(uint64_t objId, JSParam[] argv) returns (ReturnStatus rs, JSVariant result, JSParam[] outparams);
|
||||
rpc CallOrConstruct(uint64_t objId, JSParam[] argv, bool construct) returns (ReturnStatus rs, JSVariant result, JSParam[] outparams);
|
||||
rpc ObjectClassIs(uint64_t objId, uint32_t classValue) returns (bool result);
|
||||
rpc ClassName(uint64_t objId) returns (nsString name);
|
||||
|
||||
|
@ -381,8 +381,12 @@ WrapperAnswer::AnswerIsExtensible(const ObjectId &objId, ReturnStatus *rs, bool
|
||||
}
|
||||
|
||||
bool
|
||||
WrapperAnswer::AnswerCall(const ObjectId &objId, const nsTArray<JSParam> &argv, ReturnStatus *rs,
|
||||
JSVariant *result, nsTArray<JSParam> *outparams)
|
||||
WrapperAnswer::AnswerCallOrConstruct(const ObjectId &objId,
|
||||
const nsTArray<JSParam> &argv,
|
||||
const bool &construct,
|
||||
ReturnStatus *rs,
|
||||
JSVariant *result,
|
||||
nsTArray<JSParam> *outparams)
|
||||
{
|
||||
AutoSafeJSContext cx;
|
||||
JSAutoRequest request(cx);
|
||||
@ -434,7 +438,11 @@ WrapperAnswer::AnswerCall(const ObjectId &objId, const nsTArray<JSParam> &argv,
|
||||
ContextOptionsRef(cx).setDontReportUncaught(true);
|
||||
|
||||
HandleValueArray args = HandleValueArray::subarray(vals, 2, vals.length() - 2);
|
||||
bool success = JS::Call(cx, vals[1], vals[0], args, &rval);
|
||||
bool success;
|
||||
if (construct)
|
||||
success = JS::Construct(cx, vals[0], args, &rval);
|
||||
else
|
||||
success = JS::Call(cx, vals[1], vals[0], args, &rval);
|
||||
if (!success)
|
||||
return fail(cx, rs);
|
||||
}
|
||||
|
@ -45,9 +45,9 @@ class WrapperAnswer : public virtual JavaScriptShared
|
||||
|
||||
bool AnswerIsExtensible(const ObjectId &objId, ReturnStatus *rs,
|
||||
bool *result);
|
||||
bool AnswerCall(const ObjectId &objId, const nsTArray<JSParam> &argv,
|
||||
ReturnStatus *rs, JSVariant *result,
|
||||
nsTArray<JSParam> *outparams);
|
||||
bool AnswerCallOrConstruct(const ObjectId &objId, const nsTArray<JSParam> &argv,
|
||||
const bool &construct, ReturnStatus *rs, JSVariant *result,
|
||||
nsTArray<JSParam> *outparams);
|
||||
bool AnswerObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
|
||||
bool *result);
|
||||
bool AnswerClassName(const ObjectId &objId, nsString *result);
|
||||
|
@ -80,6 +80,7 @@ class CPOWProxyHandler : public BaseProxyHandler
|
||||
|
||||
virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) const MOZ_OVERRIDE;
|
||||
virtual bool call(JSContext *cx, HandleObject proxy, const CallArgs &args) const MOZ_OVERRIDE;
|
||||
virtual bool construct(JSContext *cx, HandleObject proxy, const CallArgs &args) const MOZ_OVERRIDE;
|
||||
virtual bool objectClassIs(HandleObject obj, js::ESClassValue classValue,
|
||||
JSContext *cx) const MOZ_OVERRIDE;
|
||||
virtual const char* className(JSContext *cx, HandleObject proxy) const MOZ_OVERRIDE;
|
||||
@ -336,7 +337,7 @@ WrapperOwner::toString(JSContext *cx, HandleObject cpow, JS::CallArgs &args)
|
||||
// Ask the other side to call its toString method. Update the callee so that
|
||||
// it points to the CPOW and not to the synthesized CPOWToString function.
|
||||
args.setCallee(ObjectValue(*cpow));
|
||||
if (!call(cx, cpow, args))
|
||||
if (!callOrConstruct(cx, cpow, args, false))
|
||||
return false;
|
||||
|
||||
if (!args.rval().isString())
|
||||
@ -482,11 +483,18 @@ WrapperOwner::isExtensible(JSContext *cx, HandleObject proxy, bool *extensible)
|
||||
bool
|
||||
CPOWProxyHandler::call(JSContext *cx, HandleObject proxy, const CallArgs &args) const
|
||||
{
|
||||
FORWARD(call, (cx, proxy, args));
|
||||
FORWARD(callOrConstruct, (cx, proxy, args, false));
|
||||
}
|
||||
|
||||
bool
|
||||
WrapperOwner::call(JSContext *cx, HandleObject proxy, const CallArgs &args)
|
||||
CPOWProxyHandler::construct(JSContext *cx, HandleObject proxy, const CallArgs &args) const
|
||||
{
|
||||
FORWARD(callOrConstruct, (cx, proxy, args, true));
|
||||
}
|
||||
|
||||
bool
|
||||
WrapperOwner::callOrConstruct(JSContext *cx, HandleObject proxy, const CallArgs &args,
|
||||
bool construct)
|
||||
{
|
||||
ObjectId objId = idOf(proxy);
|
||||
|
||||
@ -495,7 +503,12 @@ WrapperOwner::call(JSContext *cx, HandleObject proxy, const CallArgs &args)
|
||||
|
||||
RootedValue v(cx);
|
||||
for (size_t i = 0; i < args.length() + 2; i++) {
|
||||
v = args.base()[i];
|
||||
// The |this| value for constructors is a magic value that we won't be
|
||||
// able to convert, so skip it.
|
||||
if (i == 1 && construct)
|
||||
v = UndefinedValue();
|
||||
else
|
||||
v = args.base()[i];
|
||||
if (v.isObject()) {
|
||||
RootedObject obj(cx, &v.toObject());
|
||||
if (xpc::IsOutObject(cx, obj)) {
|
||||
@ -523,7 +536,7 @@ WrapperOwner::call(JSContext *cx, HandleObject proxy, const CallArgs &args)
|
||||
JSVariant result;
|
||||
ReturnStatus status;
|
||||
InfallibleTArray<JSParam> outparams;
|
||||
if (!CallCall(objId, vals, &status, &result, &outparams))
|
||||
if (!CallCallOrConstruct(objId, vals, construct, &status, &result, &outparams))
|
||||
return ipcfail(cx);
|
||||
|
||||
LOG_STACK();
|
||||
|
@ -55,7 +55,8 @@ class WrapperOwner : public virtual JavaScriptShared
|
||||
|
||||
// SpiderMonkey Extensions.
|
||||
bool isExtensible(JSContext *cx, JS::HandleObject proxy, bool *extensible);
|
||||
bool call(JSContext *cx, JS::HandleObject proxy, const JS::CallArgs &args);
|
||||
bool callOrConstruct(JSContext *cx, JS::HandleObject proxy, const JS::CallArgs &args,
|
||||
bool construct);
|
||||
bool objectClassIs(JSContext *cx, JS::HandleObject obj, js::ESClassValue classValue);
|
||||
const char* className(JSContext *cx, JS::HandleObject proxy);
|
||||
|
||||
@ -125,9 +126,9 @@ class WrapperOwner : public virtual JavaScriptShared
|
||||
|
||||
virtual bool CallIsExtensible(const ObjectId &objId, ReturnStatus *rs,
|
||||
bool *result) = 0;
|
||||
virtual bool CallCall(const ObjectId &objId, const nsTArray<JSParam> &argv,
|
||||
ReturnStatus *rs, JSVariant *result,
|
||||
nsTArray<JSParam> *outparams) = 0;
|
||||
virtual bool CallCallOrConstruct(const ObjectId &objId, const nsTArray<JSParam> &argv,
|
||||
const bool &construct, ReturnStatus *rs, JSVariant *result,
|
||||
nsTArray<JSParam> *outparams) = 0;
|
||||
virtual bool CallObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
|
||||
bool *result) = 0;
|
||||
virtual bool CallClassName(const ObjectId &objId, nsString *result) = 0;
|
||||
|
@ -5126,6 +5126,18 @@ JS::Call(JSContext *cx, HandleValue thisv, HandleValue fval, const JS::HandleVal
|
||||
return Invoke(cx, thisv, fval, args.length(), args.begin(), rval);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::Construct(JSContext *cx, HandleValue fval, const JS::HandleValueArray& args,
|
||||
MutableHandleValue rval)
|
||||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, fval, args);
|
||||
AutoLastFrameCheck lfc(cx);
|
||||
|
||||
return InvokeConstructor(cx, fval, args.length(), args.begin(), rval.address());
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject *)
|
||||
JS_New(JSContext *cx, HandleObject ctor, const JS::HandleValueArray& inputArgs)
|
||||
{
|
||||
|
@ -3996,6 +3996,11 @@ Call(JSContext *cx, JS::HandleValue thisv, JS::HandleObject funObj, const JS::Ha
|
||||
return Call(cx, thisv, fun, args, rval);
|
||||
}
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
Construct(JSContext *cx, JS::HandleValue fun,
|
||||
const JS::HandleValueArray& args,
|
||||
MutableHandleValue rval);
|
||||
|
||||
} /* namespace JS */
|
||||
|
||||
/*
|
||||
|
@ -553,7 +553,7 @@ js::InvokeConstructor(JSContext *cx, CallArgs args)
|
||||
}
|
||||
|
||||
bool
|
||||
js::InvokeConstructor(JSContext *cx, Value fval, unsigned argc, Value *argv, Value *rval)
|
||||
js::InvokeConstructor(JSContext *cx, Value fval, unsigned argc, const Value *argv, Value *rval)
|
||||
{
|
||||
InvokeArgs args(cx);
|
||||
if (!args.init(argc))
|
||||
|
@ -149,7 +149,7 @@ InvokeConstructor(JSContext *cx, CallArgs args);
|
||||
|
||||
/* See the fval overload of Invoke. */
|
||||
extern bool
|
||||
InvokeConstructor(JSContext *cx, Value fval, unsigned argc, Value *argv, Value *rval);
|
||||
InvokeConstructor(JSContext *cx, Value fval, unsigned argc, const Value *argv, Value *rval);
|
||||
|
||||
/*
|
||||
* Executes a script with the given scopeChain/this. The 'type' indicates
|
||||
|
Loading…
Reference in New Issue
Block a user