Skip to content

Commit

Permalink
Bug 1282257 - Create accessor properties in Debugger.Object.prototype…
Browse files Browse the repository at this point in the history
… to expose the target and the handler of a proxy object. r=jimb

--HG--
extra : rebase_source : e321ee817cee8c2f05103249ce9fad9762aa8643
  • Loading branch information
Loirooriol committed Jul 19, 2016
1 parent c4b04df commit cd54045
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 19 deletions.
31 changes: 12 additions & 19 deletions js/src/doc/Debugger/Debugger.Object.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,26 +188,19 @@ from its prototype:
function, not a debuggee function, or not a function at all, this is
`undefined`.

`isProxy`
: If the referent is a (scripted) proxy, return `true`. If the referent is not
a proxy, return `false`.

`proxyTarget`
: If the referent is a (scripted) proxy, return a `Debugger.Object` instance
referring to the ECMAScript `[[ProxyTarget]]` of the referent. If the referent
is not a proxy, return `undefined`.

`proxyHandler`
: If the referent is a proxy whose handler object was allocated by
debuggee code, this is its handler object—the object whose methods are
invoked to implement accesses of the proxy's properties. If the referent
is not a proxy whose handler object was allocated by debuggee code, this
is `null`.

`proxyCallTrap`
: If the referent is a function proxy whose handler object was allocated
by debuggee code, this is its call trap function—the function called
when the function proxy is called. If the referent is not a function
proxy whose handler object was allocated by debuggee code, this is
`null`.

`proxyConstructTrap`
: If the referent is a function proxy whose handler object was allocated
by debuggee code, its construction trap function—the function called
when the function proxy is called via a `new` expression. If the
referent is not a function proxy whose handler object was allocated by
debuggee code, this is `null`.
: If the referent is a (scripted) proxy, return a `Debugger.Object` instance
referring to the ECMAScript `[[ProxyHandler]]` of the referent. If the referent
is not a proxy, return `undefined`.

`promiseState`
: If the referent is a [`Promise`][promise], this is an object describing
Expand Down
32 changes: 32 additions & 0 deletions js/src/jit-test/tests/debug/Object-proxy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Debugger.Object.prototype.isProxy recognizes (scripted) proxies.
// Debugger.Object.prototype.proxyTarget exposes the [[Proxytarget]] of a proxy.
// Debugger.Object.prototype.proxyHandler exposes the [[ProxyHandler]] of a proxy.

var g = newGlobal();
var dbg = new Debugger;
var gDO = dbg.addDebuggee(g);

g.eval('var target = [1,2,3];');
g.eval('var handler = {has: ()=>false};');
g.eval('var proxy = new Proxy(target, handler);');
g.eval('var proxyProxy = new Proxy(proxy, proxy);');

var target = gDO.getOwnPropertyDescriptor('target').value;
var handler = gDO.getOwnPropertyDescriptor('handler').value;
var proxy = gDO.getOwnPropertyDescriptor('proxy').value;
var proxyProxy = gDO.getOwnPropertyDescriptor('proxyProxy').value;

assertEq(target.isProxy, false);
assertEq(handler.isProxy, false);
assertEq(proxy.isProxy, true);
assertEq(proxyProxy.isProxy, true);

assertEq(target.proxyTarget, undefined);
assertEq(handler.proxyTarget, undefined);
assertEq(proxy.proxyTarget, target);
assertEq(proxyProxy.proxyTarget, proxy);

assertEq(target.proxyHandler, undefined);
assertEq(handler.proxyHandler, undefined);
assertEq(proxy.proxyHandler, handler);
assertEq(proxyProxy.proxyTarget, proxy);
75 changes: 75 additions & 0 deletions js/src/vm/Debugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8288,6 +8288,50 @@ DebuggerObject::errorMessageNameGetter(JSContext *cx, unsigned argc, Value* vp)
return true;
}

/* static */ bool
DebuggerObject::isProxyGetter(JSContext* cx, unsigned argc, Value* vp)
{
THIS_DEBUGOBJECT(cx, argc, vp, "get isProxy", args, object)

args.rval().setBoolean(object->isProxy());
return true;
}

/* static */ bool
DebuggerObject::proxyTargetGetter(JSContext* cx, unsigned argc, Value* vp)
{
THIS_DEBUGOBJECT(cx, argc, vp, "get proxyTarget", args, object)

if (!object->isProxy()) {
args.rval().setUndefined();
return true;
}

Rooted<DebuggerObject*> result(cx);
if (!DebuggerObject::proxyTarget(cx, object, &result))
return false;

args.rval().setObject(*result);
return true;
}

/* static */ bool
DebuggerObject::proxyHandlerGetter(JSContext* cx, unsigned argc, Value* vp)
{
THIS_DEBUGOBJECT(cx, argc, vp, "get proxyHandler", args, object)

if (!object->isProxy()) {
args.rval().setUndefined();
return true;
}
Rooted<DebuggerObject*> result(cx);
if (!DebuggerObject::proxyHandler(cx, object, &result))
return false;

args.rval().setObject(*result);
return true;
}

#ifdef SPIDERMONKEY_PROMISE
/* static */ bool
DebuggerObject::isPromiseGetter(JSContext* cx, unsigned argc, Value* vp)
Expand Down Expand Up @@ -8854,6 +8898,9 @@ const JSPropertySpec DebuggerObject::properties_[] = {
JS_PSG("global", DebuggerObject::globalGetter, 0),
JS_PSG("allocationSite", DebuggerObject::allocationSiteGetter, 0),
JS_PSG("errorMessageName", DebuggerObject::errorMessageNameGetter, 0),
JS_PSG("isProxy", DebuggerObject::isProxyGetter, 0),
JS_PSG("proxyTarget", DebuggerObject::proxyTargetGetter, 0),
JS_PSG("proxyHandler", DebuggerObject::proxyHandlerGetter, 0),
JS_PS_END
};

Expand Down Expand Up @@ -8983,6 +9030,12 @@ DebuggerObject::isPromise() const
return obj->is<PromiseObject>();
}

bool
DebuggerObject::isProxy() const
{
return js::IsScriptedProxy(referent());
}

/* static */ bool
DebuggerObject::getClassName(JSContext* cx, Handle<DebuggerObject*> object,
MutableHandleString result)
Expand Down Expand Up @@ -9640,6 +9693,28 @@ DebuggerObject::requireGlobal(JSContext* cx, Handle<DebuggerObject*> object)
return true;
}

/* static */ bool
DebuggerObject::proxyTarget(JSContext* cx, Handle<DebuggerObject*> object,
MutableHandle<DebuggerObject*> result)
{
MOZ_ASSERT(isProxy());
RootedObject referent(cx, object->referent());
Debugger* dbg = object->owner();
RootedObject unwrapped(cx, js::GetProxyTargetObject(referent));
return dbg->wrapDebuggeeObject(cx, unwrapped, result);
}

/* static */ bool
DebuggerObject::proxyHandler(JSContext* cx, Handle<DebuggerObject*> object,
MutableHandle<DebuggerObject*> result)
{
MOZ_ASSERT(isProxy());
RootedObject referent(cx, object->referent());
Debugger* dbg = object->owner();
RootedObject unwrapped(cx, js::GetProxyExtra(referent, 0).toObjectOrNull());
return dbg->wrapDebuggeeObject(cx, unwrapped, result);
}


/*** Debugger.Environment ************************************************************************/

Expand Down
8 changes: 8 additions & 0 deletions js/src/vm/Debugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -1202,6 +1202,10 @@ class DebuggerObject : public NativeObject
MutableHandleObject result);
static MOZ_MUST_USE bool getErrorMessageName(JSContext* cx, Handle<DebuggerObject*> object,
MutableHandleString result);
static MOZ_MUST_USE bool proxyTarget(JSContext* cx, Handle<DebuggerObject*> object,
MutableHandle<DebuggerObject*> result);
static MOZ_MUST_USE bool proxyHandler(JSContext* cx, Handle<DebuggerObject*> object,
MutableHandle<DebuggerObject*> result);

// Methods
static MOZ_MUST_USE bool isExtensible(JSContext* cx, Handle<DebuggerObject*> object,
Expand Down Expand Up @@ -1251,6 +1255,7 @@ class DebuggerObject : public NativeObject
bool isArrowFunction() const;
bool isGlobal() const;
bool isPromise() const;
bool isProxy() const;
JSAtom* name() const;
JSAtom* displayName() const;

Expand Down Expand Up @@ -1299,6 +1304,9 @@ class DebuggerObject : public NativeObject
static MOZ_MUST_USE bool globalGetter(JSContext* cx, unsigned argc, Value* vp);
static MOZ_MUST_USE bool allocationSiteGetter(JSContext* cx, unsigned argc, Value* vp);
static MOZ_MUST_USE bool errorMessageNameGetter(JSContext* cx, unsigned argc, Value* vp);
static MOZ_MUST_USE bool isProxyGetter(JSContext* cx, unsigned argc, Value* vp);
static MOZ_MUST_USE bool proxyTargetGetter(JSContext* cx, unsigned argc, Value* vp);
static MOZ_MUST_USE bool proxyHandlerGetter(JSContext* cx, unsigned argc, Value* vp);
#ifdef SPIDERMONKEY_PROMISE
static MOZ_MUST_USE bool isPromiseGetter(JSContext* cx, unsigned argc, Value* vp);
static MOZ_MUST_USE bool promiseStateGetter(JSContext* cx, unsigned argc, Value* vp);
Expand Down

0 comments on commit cd54045

Please sign in to comment.