зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1271653 - Implement a C++ function for makeDebuggeeValue/unsafeDereference/unwrap;r=jimb
This commit is contained in:
Родитель
77c9eba63e
Коммит
97e08ffec4
|
@ -1080,41 +1080,10 @@ Debugger::wrapDebuggeeValue(JSContext* cx, MutableHandleValue vp)
|
|||
if (vp.isObject()) {
|
||||
RootedObject obj(cx, &vp.toObject());
|
||||
|
||||
if (obj->is<JSFunction>()) {
|
||||
MOZ_ASSERT(!IsInternalFunctionObject(*obj));
|
||||
RootedFunction fun(cx, &obj->as<JSFunction>());
|
||||
if (!EnsureFunctionHasScript(cx, fun))
|
||||
return false;
|
||||
}
|
||||
if (!wrapDebuggeeObject(cx, &obj))
|
||||
return false;
|
||||
|
||||
DependentAddPtr<ObjectWeakMap> p(cx, objects, obj);
|
||||
if (p) {
|
||||
vp.setObject(*p->value());
|
||||
} else {
|
||||
/* Create a new Debugger.Object for obj. */
|
||||
RootedNativeObject debugger(cx, object);
|
||||
RootedObject proto(cx, &object->getReservedSlot(JSSLOT_DEBUG_OBJECT_PROTO).toObject());
|
||||
NativeObject* dobj = DebuggerObject::create(cx, proto, obj, debugger);
|
||||
if (!dobj)
|
||||
return false;
|
||||
|
||||
if (!p.add(cx, objects, obj, dobj)) {
|
||||
NukeDebuggerWrapper(dobj);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (obj->compartment() != object->compartment()) {
|
||||
CrossCompartmentKey key(object, obj, CrossCompartmentKey::DebuggerObject);
|
||||
if (!object->compartment()->putWrapper(cx, key, ObjectValue(*dobj))) {
|
||||
NukeDebuggerWrapper(dobj);
|
||||
objects.remove(obj);
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
vp.setObject(*dobj);
|
||||
}
|
||||
vp.setObject(*obj);
|
||||
} else if (vp.isMagic()) {
|
||||
RootedPlainObject optObj(cx, NewBuiltinClassInstance<PlainObject>(cx));
|
||||
if (!optObj)
|
||||
|
@ -1146,6 +1115,48 @@ Debugger::wrapDebuggeeValue(JSContext* cx, MutableHandleValue vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Debugger::wrapDebuggeeObject(JSContext* cx, MutableHandleObject obj)
|
||||
{
|
||||
if (obj->is<JSFunction>()) {
|
||||
MOZ_ASSERT(!IsInternalFunctionObject(*obj));
|
||||
RootedFunction fun(cx, &obj->as<JSFunction>());
|
||||
if (!EnsureFunctionHasScript(cx, fun))
|
||||
return false;
|
||||
}
|
||||
|
||||
DependentAddPtr<ObjectWeakMap> p(cx, objects, obj);
|
||||
if (p) {
|
||||
obj.set(p->value());
|
||||
} else {
|
||||
/* Create a new Debugger.Object for obj. */
|
||||
RootedNativeObject debugger(cx, object);
|
||||
RootedObject proto(cx, &object->getReservedSlot(JSSLOT_DEBUG_OBJECT_PROTO).toObject());
|
||||
NativeObject* dobj = DebuggerObject::create(cx, proto, obj, debugger);
|
||||
if (!dobj)
|
||||
return false;
|
||||
|
||||
if (!p.add(cx, objects, obj, dobj)) {
|
||||
NukeDebuggerWrapper(dobj);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (obj->compartment() != object->compartment()) {
|
||||
CrossCompartmentKey key(object, obj, CrossCompartmentKey::DebuggerObject);
|
||||
if (!object->compartment()->putWrapper(cx, key, ObjectValue(*dobj))) {
|
||||
NukeDebuggerWrapper(dobj);
|
||||
objects.remove(obj);
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
obj.set(dobj);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static NativeObject*
|
||||
ToNativeDebuggerObject(JSContext* cx, MutableHandleObject obj)
|
||||
{
|
||||
|
@ -8712,69 +8723,36 @@ DebuggerObject_executeInGlobalWithBindings(JSContext* cx, unsigned argc, Value*
|
|||
static bool
|
||||
DebuggerObject_makeDebuggeeValue(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
THIS_DEBUGOBJECT_OWNER_REFERENT(cx, argc, vp, "makeDebuggeeValue", args, dbg, referent);
|
||||
THIS_DEBUGOBJECT(cx, argc, vp, "makeDebuggeeValue", args, object);
|
||||
if (!args.requireAtLeast(cx, "Debugger.Object.prototype.makeDebuggeeValue", 1))
|
||||
return false;
|
||||
|
||||
RootedValue arg0(cx, args[0]);
|
||||
return DebuggerObject::makeDebuggeeValue(cx, object, args[0], args.rval());
|
||||
}
|
||||
|
||||
/* Non-objects are already debuggee values. */
|
||||
if (arg0.isObject()) {
|
||||
// Enter this Debugger.Object's referent's compartment, and wrap the
|
||||
// argument as appropriate for references from there.
|
||||
{
|
||||
AutoCompartment ac(cx, referent);
|
||||
if (!cx->compartment()->wrap(cx, &arg0))
|
||||
return false;
|
||||
}
|
||||
static bool
|
||||
DebuggerObject_unsafeDereference(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
THIS_DEBUGOBJECT(cx, argc, vp, "unsafeDereference", args, object);
|
||||
|
||||
// Back in the debugger's compartment, produce a new Debugger.Object
|
||||
// instance referring to the wrapped argument.
|
||||
if (!dbg->wrapDebuggeeValue(cx, &arg0))
|
||||
return false;
|
||||
}
|
||||
RootedObject result(cx);
|
||||
if (!DebuggerObject::unsafeDereference(cx, object, &result))
|
||||
return false;
|
||||
|
||||
args.rval().set(arg0);
|
||||
args.rval().setObject(*result);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
DebuggerObject_unwrap(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
THIS_DEBUGOBJECT_OWNER_REFERENT(cx, argc, vp, "unwrap", args, dbg, referent);
|
||||
JSObject* unwrapped = UnwrapOneChecked(referent);
|
||||
if (!unwrapped) {
|
||||
args.rval().setNull();
|
||||
return true;
|
||||
}
|
||||
THIS_DEBUGOBJECT(cx, argc, vp, "unwrap", args, object);
|
||||
|
||||
// Don't allow unwrapping to create a D.O whose referent is in an
|
||||
// invisible-to-Debugger global. (If our referent is a *wrapper* to such,
|
||||
// and the wrapper is in a visible compartment, that's fine.)
|
||||
JSCompartment* unwrappedCompartment = unwrapped->compartment();
|
||||
if (unwrappedCompartment->creationOptions().invisibleToDebugger()) {
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr,
|
||||
JSMSG_DEBUG_INVISIBLE_COMPARTMENT);
|
||||
return false;
|
||||
}
|
||||
|
||||
args.rval().setObject(*unwrapped);
|
||||
if (!dbg->wrapDebuggeeValue(cx, args.rval()))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
DebuggerObject_unsafeDereference(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
THIS_DEBUGOBJECT_REFERENT(cx, argc, vp, "unsafeDereference", args, referent);
|
||||
args.rval().setObject(*referent);
|
||||
if (!cx->compartment()->wrap(cx, args.rval()))
|
||||
Rooted<DebuggerObject*> result(cx);
|
||||
if (!DebuggerObject::unwrap(cx, object, &result))
|
||||
return false;
|
||||
|
||||
// Wrapping should return the WindowProxy.
|
||||
MOZ_ASSERT(!IsWindow(&args.rval().toObject()));
|
||||
|
||||
args.rval().setObjectOrNull(result);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -8832,8 +8810,8 @@ const JSFunctionSpec DebuggerObject::methods_[] = {
|
|||
JS_FN("executeInGlobal", DebuggerObject_executeInGlobal, 1, 0),
|
||||
JS_FN("executeInGlobalWithBindings", DebuggerObject_executeInGlobalWithBindings, 2, 0),
|
||||
JS_FN("makeDebuggeeValue", DebuggerObject_makeDebuggeeValue, 1, 0),
|
||||
JS_FN("unwrap", DebuggerObject_unwrap, 0, 0),
|
||||
JS_FN("unsafeDereference", DebuggerObject_unsafeDereference, 0, 0),
|
||||
JS_FN("unwrap", DebuggerObject_unwrap, 0, 0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
|
@ -9216,6 +9194,81 @@ DebuggerObject::executeInGlobal(JSContext* cx, Handle<DebuggerObject*> object,
|
|||
nullptr);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
DebuggerObject::makeDebuggeeValue(JSContext* cx, Handle<DebuggerObject*> object,
|
||||
HandleValue value_, MutableHandleValue result)
|
||||
{
|
||||
RootedObject referent(cx, object->referent());
|
||||
Debugger* dbg = object->owner();
|
||||
|
||||
RootedValue value(cx, value_);
|
||||
|
||||
/* Non-objects are already debuggee values. */
|
||||
if (value.isObject()) {
|
||||
// Enter this Debugger.Object's referent's compartment, and wrap the
|
||||
// argument as appropriate for references from there.
|
||||
{
|
||||
AutoCompartment ac(cx, referent);
|
||||
if (!cx->compartment()->wrap(cx, &value))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Back in the debugger's compartment, produce a new Debugger.Object
|
||||
// instance referring to the wrapped argument.
|
||||
if (!dbg->wrapDebuggeeValue(cx, &value))
|
||||
return false;
|
||||
}
|
||||
|
||||
result.set(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
DebuggerObject::unsafeDereference(JSContext* cx, Handle<DebuggerObject*> object,
|
||||
MutableHandleObject result)
|
||||
{
|
||||
RootedObject referent(cx, object->referent());
|
||||
|
||||
if (!cx->compartment()->wrap(cx, &referent))
|
||||
return false;
|
||||
|
||||
// Wrapping should return the WindowProxy.
|
||||
MOZ_ASSERT(!IsWindow(referent));
|
||||
|
||||
result.set(referent);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
DebuggerObject::unwrap(JSContext* cx, Handle<DebuggerObject*> object,
|
||||
MutableHandle<DebuggerObject*> result)
|
||||
{
|
||||
RootedObject referent(cx, object->referent());
|
||||
Debugger* dbg = object->owner();
|
||||
|
||||
RootedObject unwrapped(cx, UnwrapOneChecked(referent));
|
||||
if (!unwrapped) {
|
||||
result.set(nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Don't allow unwrapping to create a D.O whose referent is in an
|
||||
// invisible-to-Debugger global. (If our referent is a *wrapper* to such,
|
||||
// and the wrapper is in a visible compartment, that's fine.)
|
||||
JSCompartment* unwrappedCompartment = unwrapped->compartment();
|
||||
if (unwrappedCompartment->creationOptions().invisibleToDebugger()) {
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr,
|
||||
JSMSG_DEBUG_INVISIBLE_COMPARTMENT);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!dbg->wrapDebuggeeObject(cx, &unwrapped))
|
||||
return false;
|
||||
|
||||
result.set(&unwrapped->as<DebuggerObject>());
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
DebuggerObject::requireGlobalObject(JSContext* cx, Handle<DebuggerObject*> object)
|
||||
{
|
||||
|
|
|
@ -917,6 +917,7 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
|
|||
* form { uninitialized: true }.
|
||||
*/
|
||||
bool wrapDebuggeeValue(JSContext* cx, MutableHandleValue vp);
|
||||
bool wrapDebuggeeObject(JSContext* cx, MutableHandleObject obj);
|
||||
|
||||
/*
|
||||
* Unwrap a Debug.Object, without rewrapping it for any particular debuggee
|
||||
|
@ -1076,6 +1077,12 @@ class DebuggerObject : public NativeObject
|
|||
static bool executeInGlobal(JSContext* cx, Handle<DebuggerObject*> object,
|
||||
mozilla::Range<const char16_t> chars, HandleObject bindings,
|
||||
const EvalOptions& options, MutableHandleValue result);
|
||||
static bool makeDebuggeeValue(JSContext* cx, Handle<DebuggerObject*> object,
|
||||
HandleValue value, MutableHandleValue result);
|
||||
static bool unsafeDereference(JSContext* cx, Handle<DebuggerObject*> object,
|
||||
MutableHandleObject result);
|
||||
static bool unwrap(JSContext* cx, Handle<DebuggerObject*> object,
|
||||
MutableHandle<DebuggerObject*> result);
|
||||
|
||||
private:
|
||||
enum {
|
||||
|
|
Загрузка…
Ссылка в новой задаче