--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -71,35 +71,35 @@ static void DebuggerSource_trace(JSTrace
enum {
JSSLOT_DEBUGFRAME_OWNER,
JSSLOT_DEBUGFRAME_ARGUMENTS,
JSSLOT_DEBUGFRAME_ONSTEP_HANDLER,
JSSLOT_DEBUGFRAME_ONPOP_HANDLER,
JSSLOT_DEBUGFRAME_COUNT
};
-static const ClassOps DebuggerFrame_classOps = {
+const ClassOps DebuggerFrame::classOps_ = {
nullptr, /* addProperty */
nullptr, /* delProperty */
nullptr, /* getProperty */
nullptr, /* setProperty */
nullptr, /* enumerate */
nullptr, /* resolve */
nullptr, /* mayResolve */
DebuggerFrame_finalize,
nullptr, /* call */
nullptr, /* hasInstance */
nullptr, /* construct */
nullptr, /* trace */
};
-static const Class DebuggerFrame_class = {
+const Class DebuggerFrame::class_ = {
"Frame",
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(JSSLOT_DEBUGFRAME_COUNT),
- &DebuggerFrame_classOps
+ &DebuggerFrame::classOps_
};
enum {
JSSLOT_DEBUGARGUMENTS_FRAME,
JSSLOT_DEBUGARGUMENTS_COUNT
};
static const Class DebuggerArguments_class = {
@@ -687,17 +687,17 @@ Debugger::init(JSContext* cx)
JS_STATIC_ASSERT(unsigned(JSSLOT_DEBUGFRAME_OWNER) == unsigned(JSSLOT_DEBUGSCRIPT_OWNER));
JS_STATIC_ASSERT(unsigned(JSSLOT_DEBUGFRAME_OWNER) == unsigned(JSSLOT_DEBUGSOURCE_OWNER));
JS_STATIC_ASSERT(unsigned(JSSLOT_DEBUGFRAME_OWNER) == unsigned(JSSLOT_DEBUGOBJECT_OWNER));
JS_STATIC_ASSERT(unsigned(JSSLOT_DEBUGFRAME_OWNER) == unsigned(DebuggerEnvironment::OWNER_SLOT));
/* static */ Debugger*
Debugger::fromChildJSObject(JSObject* obj)
{
- MOZ_ASSERT(obj->getClass() == &DebuggerFrame_class ||
+ MOZ_ASSERT(obj->getClass() == &DebuggerFrame::class_ ||
obj->getClass() == &DebuggerScript_class ||
obj->getClass() == &DebuggerSource_class ||
obj->getClass() == &DebuggerObject::class_ ||
obj->getClass() == &DebuggerEnvironment::class_);
JSObject* dbgobj = &obj->as<NativeObject>().getReservedSlot(JSSLOT_DEBUGOBJECT_OWNER).toObject();
return fromJSObject(dbgobj);
}
@@ -710,55 +710,45 @@ Debugger::hasMemory() const
DebuggerMemory&
Debugger::memory() const
{
MOZ_ASSERT(hasMemory());
return object->getReservedSlot(JSSLOT_DEBUG_MEMORY_INSTANCE).toObject().as<DebuggerMemory>();
}
bool
-Debugger::getScriptFrameWithIter(JSContext* cx, AbstractFramePtr frame,
+Debugger::getScriptFrameWithIter(JSContext* cx, AbstractFramePtr referent,
const ScriptFrameIter* maybeIter, MutableHandleValue vp)
{
- MOZ_ASSERT_IF(maybeIter, maybeIter->abstractFramePtr() == frame);
- MOZ_ASSERT(!frame.script()->selfHosted());
-
- if (!frame.script()->ensureHasAnalyzedArgsUsage(cx))
- return false;
-
- FrameMap::AddPtr p = frames.lookupForAdd(frame);
+ MOZ_ASSERT_IF(maybeIter, maybeIter->abstractFramePtr() == referent);
+ MOZ_ASSERT(!referent.script()->selfHosted());
+
+ if (!referent.script()->ensureHasAnalyzedArgsUsage(cx))
+ return false;
+
+ FrameMap::AddPtr p = frames.lookupForAdd(referent);
if (!p) {
/* Create and populate the Debugger.Frame object. */
RootedObject proto(cx, &object->getReservedSlot(JSSLOT_DEBUG_FRAME_PROTO).toObject());
- RootedNativeObject frameobj(cx, NewNativeObjectWithGivenProto(cx, &DebuggerFrame_class,
- proto));
- if (!frameobj)
- return false;
-
- // Eagerly copy ScriptFrameIter data if we've already walked the
- // stack.
- if (maybeIter) {
- AbstractFramePtr data = maybeIter->copyDataAsAbstractFramePtr();
- if (!data)
- return false;
- frameobj->setPrivate(data.raw());
- } else {
- frameobj->setPrivate(frame.raw());
- }
-
- frameobj->setReservedSlot(JSSLOT_DEBUGFRAME_OWNER, ObjectValue(*object));
-
- if (!ensureExecutionObservabilityOfFrame(cx, frame))
- return false;
-
- if (!frames.add(p, frame, frameobj)) {
+ RootedNativeObject debugger(cx, object);
+
+ RootedNativeObject frame(cx, DebuggerFrame::create(cx, proto, referent, maybeIter,
+ debugger));
+ if (!frame)
+ return false;
+
+ if (!ensureExecutionObservabilityOfFrame(cx, referent))
+ return false;
+
+ if (!frames.add(p, referent, frame)) {
ReportOutOfMemory(cx);
return false;
}
}
+
vp.setObject(*p->value());
return true;
}
/* static */ bool
Debugger::hasLiveHook(GlobalObject* global, Hook which)
{
if (GlobalObject::DebuggerVector* debuggers = global->getDebuggers()) {
@@ -7009,16 +6999,48 @@ static const JSPropertySpec DebuggerSour
static const JSFunctionSpec DebuggerSource_methods[] = {
JS_FS_END
};
/*** Debugger.Frame ******************************************************************************/
+/* static */ NativeObject*
+DebuggerFrame::initClass(JSContext* cx, HandleObject dbgCtor, HandleObject objProto)
+{
+ return InitClass(cx, dbgCtor, objProto, &class_, construct, 0, properties_,
+ methods_, nullptr, nullptr);
+}
+
+/* static */ DebuggerFrame*
+DebuggerFrame::create(JSContext* cx, HandleObject proto, AbstractFramePtr referent,
+ const ScriptFrameIter* maybeIter, HandleNativeObject debugger)
+{
+ JSObject* obj = NewObjectWithGivenProto(cx, &DebuggerFrame::class_, proto, TenuredObject);
+ if (!obj)
+ return nullptr;
+
+ DebuggerFrame& frame = obj->as<DebuggerFrame>();
+
+ // Eagerly copy ScriptFrameIter data if we've already walked the stack.
+ if (maybeIter) {
+ AbstractFramePtr data = maybeIter->copyDataAsAbstractFramePtr();
+ if (!data)
+ return false;
+ frame.setPrivate(data.raw());
+ } else {
+ frame.setPrivate(referent.raw());
+ }
+
+ frame.setReservedSlot(JSSLOT_DEBUGFRAME_OWNER, ObjectValue(*debugger));
+
+ return &frame;
+}
+
static void
UpdateFrameIterPc(FrameIter& iter)
{
if (iter.abstractFramePtr().isRematerializedFrame()) {
#ifdef DEBUG
// Rematerialized frames don't need their pc updated. The reason we
// need to update pc is because we might get the same Debugger.Frame
// object for multiple re-entries into debugger code from debuggee
@@ -7070,32 +7092,32 @@ DebuggerFrame_maybeDecrementFrameScriptS
}
static void
DebuggerFrame_finalize(FreeOp* fop, JSObject* obj)
{
DebuggerFrame_freeScriptFrameIterData(fop, obj);
}
-static NativeObject*
-CheckThisFrame(JSContext* cx, const CallArgs& args, const char* fnname, bool checkLive)
+/* static */ DebuggerFrame*
+DebuggerFrame::checkThis(JSContext* cx, const CallArgs& args, const char* fnname, bool checkLive)
{
JSObject* thisobj = NonNullObject(cx, args.thisv());
if (!thisobj)
return nullptr;
- if (thisobj->getClass() != &DebuggerFrame_class) {
+ if (thisobj->getClass() != &DebuggerFrame::class_) {
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_INCOMPATIBLE_PROTO,
"Debugger.Frame", fnname, thisobj->getClass()->name);
return nullptr;
}
- NativeObject* nthisobj = &thisobj->as<NativeObject>();
+ DebuggerFrame* nthisobj = &thisobj->as<DebuggerFrame>();
/*
- * Forbid Debugger.Frame.prototype, which is of class DebuggerFrame_class
+ * Forbid Debugger.Frame.prototype, which is of class DebuggerFrame::class_
* but isn't really a working Debugger.Frame object. The prototype object
* is distinguished by having a nullptr private value. Also, forbid popped
* frames.
*/
if (!nthisobj->getPrivate()) {
if (nthisobj->getReservedSlot(JSSLOT_DEBUGFRAME_OWNER).isUndefined()) {
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_INCOMPATIBLE_PROTO,
"Debugger.Frame", fnname, "prototype object");
@@ -7122,20 +7144,20 @@ CheckThisFrame(JSContext* cx, const Call
* by the AbstractFramePtr and cache its internal Data in the Debugger.Frame
* object's private slot. Subsequent uses of the Debugger.Frame object will
* always create a ScriptFrameIter from the cached Data.
*
* Methods that only need the AbstractFramePtr should use THIS_FRAME.
* Methods that need a ScriptFrameIterator should use THIS_FRAME_ITER.
*/
-#define THIS_FRAME_THISOBJ(cx, argc, vp, fnname, args, thisobj) \
- CallArgs args = CallArgsFromVp(argc, vp); \
- RootedNativeObject thisobj(cx, CheckThisFrame(cx, args, fnname, true)); \
- if (!thisobj) \
+#define THIS_FRAME_THISOBJ(cx, argc, vp, fnname, args, thisobj) \
+ CallArgs args = CallArgsFromVp(argc, vp); \
+ RootedNativeObject thisobj(cx, DebuggerFrame::checkThis(cx, args, fnname, true)); \
+ if (!thisobj) \
return false
#define THIS_FRAME(cx, argc, vp, fnname, args, thisobj, frame) \
THIS_FRAME_THISOBJ(cx, argc, vp, fnname, args, thisobj); \
AbstractFramePtr frame = AbstractFramePtr::FromRaw(thisobj->getPrivate()); \
if (frame.isScriptFrameIterData()) { \
ScriptFrameIter iter(*(ScriptFrameIter::Data*)(frame.raw())); \
frame = iter.abstractFramePtr(); \
@@ -7453,17 +7475,17 @@ DebuggerFrame_getOffset(JSContext* cx, u
args.rval().setNumber(double(offset));
return true;
}
static bool
DebuggerFrame_getLive(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
- NativeObject* thisobj = CheckThisFrame(cx, args, "get live", false);
+ NativeObject* thisobj = DebuggerFrame::checkThis(cx, args, "get live", false);
if (!thisobj)
return false;
bool hasFrame = !!thisobj->getPrivate();
args.rval().setBoolean(hasFrame);
return true;
}
static bool
@@ -7753,25 +7775,25 @@ DebuggerFrame_evalWithBindings(JSContext
EvalOptions options;
if (!ParseEvalOptions(cx, args.get(2), options))
return false;
return DebuggerGenericEval(cx, chars, bindings, options, args.rval(), dbg, nullptr, &iter);
}
-static bool
-DebuggerFrame_construct(JSContext* cx, unsigned argc, Value* vp)
+/* static */ bool
+DebuggerFrame::construct(JSContext* cx, unsigned argc, Value* vp)
{
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_NO_CONSTRUCTOR,
"Debugger.Frame");
return false;
}
-static const JSPropertySpec DebuggerFrame_properties[] = {
+const JSPropertySpec DebuggerFrame::properties_[] = {
JS_PSG("arguments", DebuggerFrame_getArguments, 0),
JS_PSG("callee", DebuggerFrame_getCallee, 0),
JS_PSG("constructing", DebuggerFrame_getConstructing, 0),
JS_PSG("environment", DebuggerFrame_getEnvironment, 0),
JS_PSG("generator", DebuggerFrame_getGenerator, 0),
JS_PSG("live", DebuggerFrame_getLive, 0),
JS_PSG("offset", DebuggerFrame_getOffset, 0),
JS_PSG("older", DebuggerFrame_getOlder, 0),
@@ -7779,17 +7801,17 @@ static const JSPropertySpec DebuggerFram
JS_PSG("this", DebuggerFrame_getThis, 0),
JS_PSG("type", DebuggerFrame_getType, 0),
JS_PSG("implementation", DebuggerFrame_getImplementation, 0),
JS_PSGS("onStep", DebuggerFrame_getOnStep, DebuggerFrame_setOnStep, 0),
JS_PSGS("onPop", DebuggerFrame_getOnPop, DebuggerFrame_setOnPop, 0),
JS_PS_END
};
-static const JSFunctionSpec DebuggerFrame_methods[] = {
+const JSFunctionSpec DebuggerFrame::methods_[] = {
JS_FN("eval", DebuggerFrame_eval, 1, 0),
JS_FN("evalWithBindings", DebuggerFrame_evalWithBindings, 1, 0),
JS_FS_END
};
/*** Debugger.Object *****************************************************************************/
@@ -10190,20 +10212,17 @@ JS_DefineDebuggerObject(JSContext* cx, H
return false;
debugProto = InitClass(cx, obj,
objProto, &Debugger::class_, Debugger::construct,
1, Debugger::properties, Debugger::methods, nullptr,
Debugger::static_methods, debugCtor.address());
if (!debugProto)
return false;
- frameProto = InitClass(cx, debugCtor, objProto, &DebuggerFrame_class,
- DebuggerFrame_construct, 0,
- DebuggerFrame_properties, DebuggerFrame_methods,
- nullptr, nullptr);
+ frameProto = DebuggerFrame::initClass(cx, debugCtor, obj);
if (!frameProto)
return false;
scriptProto = InitClass(cx, debugCtor, objProto, &DebuggerScript_class,
DebuggerScript_construct, 0,
DebuggerScript_properties, DebuggerScript_methods,
nullptr, nullptr);
if (!scriptProto)