mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Very rudimentary support for creating Debug.Frame objects, passing them to hooks, and cleaning them up afterwards.
This commit is contained in:
parent
4fcb55d0aa
commit
27da170dc0
@ -8,7 +8,7 @@ var log;
|
||||
function makeDebug(g, name) {
|
||||
var dbg = new Debug(g);
|
||||
dbg.hooks = {
|
||||
debuggerHandler: function () {
|
||||
debuggerHandler: function (frame) {
|
||||
log += name;
|
||||
throw new Error(name);
|
||||
}
|
||||
|
51
js/src/jit-test/tests/debug/debug-object-22.js
Normal file
51
js/src/jit-test/tests/debug/debug-object-22.js
Normal file
@ -0,0 +1,51 @@
|
||||
// |jit-test| debug
|
||||
// Test .type and .generator fields of topmost stack frame passed to debuggerHandler.
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
g.debuggeeGlobal = this;
|
||||
g.eval("var hits;");
|
||||
g.eval("(" + function () {
|
||||
var dbg = Debug(debuggeeGlobal);
|
||||
dbg.hooks = {
|
||||
debuggerHandler: function (f) {
|
||||
assertEq(Object.getPrototypeOf(f), Debug.Frame.prototype);
|
||||
assertEq(f.type, ftype);
|
||||
assertEq(f.generator, fgen);
|
||||
hits++;
|
||||
}
|
||||
};
|
||||
} + ")()");
|
||||
|
||||
g.ftype = "global";
|
||||
g.fgen = false;
|
||||
g.hits = 0;
|
||||
debugger;
|
||||
assertEq(g.hits, 1);
|
||||
|
||||
g.ftype = "call";
|
||||
g.hits = 0;
|
||||
(function () { debugger; })();
|
||||
assertEq(g.hits, 1);
|
||||
|
||||
g.ftype = "eval";
|
||||
g.hits = 0;
|
||||
eval("debugger;");
|
||||
assertEq(g.hits, 1);
|
||||
|
||||
g.ftype = "eval";
|
||||
g.hits = 0;
|
||||
this.eval("debugger;"); // indirect eval
|
||||
assertEq(g.hits, 1);
|
||||
|
||||
g.ftype = "eval";
|
||||
g.hits = 0;
|
||||
(function () { eval("debugger;"); })();
|
||||
assertEq(g.hits, 1);
|
||||
|
||||
g.ftype = "call";
|
||||
g.fgen = true;
|
||||
g.hits = 0;
|
||||
function gen() { debugger; yield 1; debugger; }
|
||||
for (var x in gen()) {
|
||||
}
|
||||
assertEq(g.hits, 2);
|
35
js/src/jit-test/tests/debug/debug-object-23.js
Normal file
35
js/src/jit-test/tests/debug/debug-object-23.js
Normal file
@ -0,0 +1,35 @@
|
||||
// |jit-test| debug
|
||||
// When the debugger is triggered twice from the same stack frame, the same
|
||||
// Debug.Frame object must be passed to the hook both times.
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
g.debuggeeGlobal = this;
|
||||
g.eval("var hits, frame;");
|
||||
g.eval("(" + function () {
|
||||
var dbg = Debug(debuggeeGlobal);
|
||||
dbg.hooks = {
|
||||
debuggerHandler: function (f) {
|
||||
if (hits++ == 0)
|
||||
frame = f;
|
||||
else
|
||||
assertEq(f, frame);
|
||||
}
|
||||
};
|
||||
} + ")()");
|
||||
|
||||
g.hits = 0;
|
||||
debugger;
|
||||
debugger;
|
||||
assertEq(g.hits, 2);
|
||||
|
||||
g.hits = 0;
|
||||
function f() {
|
||||
debugger;
|
||||
debugger;
|
||||
}
|
||||
f();
|
||||
assertEq(g.hits, 2);
|
||||
|
||||
g.hits = 0;
|
||||
eval("debugger; debugger;");
|
||||
assertEq(g.hits, 2);
|
26
js/src/jit-test/tests/debug/debug-object-24.js
Normal file
26
js/src/jit-test/tests/debug/debug-object-24.js
Normal file
@ -0,0 +1,26 @@
|
||||
// |jit-test| debug
|
||||
// When the debugger is triggered from different stack frames that happen to
|
||||
// occupy the same memory, it must deliver different Debug.Frame objects.
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
g.debuggeeGlobal = this;
|
||||
g.eval("var hits;");
|
||||
g.eval("(" + function () {
|
||||
var a = [];
|
||||
var dbg = Debug(debuggeeGlobal);
|
||||
dbg.hooks = {
|
||||
debuggerHandler: function (frame) {
|
||||
for (var i = 0; i < a.length; i++)
|
||||
assertEq(a[i] === frame, false);
|
||||
a.push(frame);
|
||||
hits++;
|
||||
}
|
||||
};
|
||||
} + ")()");
|
||||
|
||||
function f() { debugger; }
|
||||
function h() { debugger; f(); }
|
||||
g.hits = 0;
|
||||
for (var i = 0; i < 4; i++)
|
||||
h();
|
||||
assertEq(g.hits, 8);
|
179
js/src/jsdbg.cpp
179
js/src/jsdbg.cpp
@ -49,6 +49,17 @@
|
||||
|
||||
using namespace js;
|
||||
|
||||
// === Forward declarations
|
||||
|
||||
extern Class Frame_class;
|
||||
|
||||
enum {
|
||||
JSSLOT_FRAME_OWNER,
|
||||
JSSLOT_FRAME_COUNT
|
||||
};
|
||||
|
||||
// === Utils
|
||||
|
||||
static bool
|
||||
NotImplemented(JSContext *cx)
|
||||
{
|
||||
@ -114,12 +125,59 @@ CheckThisClass(JSContext *cx, Value *vp, Class *clasp, const char *fnname)
|
||||
|
||||
// === Debug hook dispatch
|
||||
|
||||
enum {
|
||||
JSSLOT_DEBUG_FRAME_PROTO,
|
||||
JSSLOT_DEBUG_COUNT
|
||||
};
|
||||
|
||||
Debug::Debug(JSObject *dbg, JSObject *hooks, JSCompartment *compartment)
|
||||
: object(dbg), debuggeeCompartment(compartment), hooksObject(hooks),
|
||||
uncaughtExceptionHook(NULL), enabled(true), hasDebuggerHandler(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
Debug::init()
|
||||
{
|
||||
return frames.init();
|
||||
}
|
||||
|
||||
bool
|
||||
Debug::getScriptFrame(JSContext *cx, JSStackFrame *fp, Value *vp)
|
||||
{
|
||||
FrameMap::AddPtr p = frames.lookupForAdd(fp);
|
||||
if (!p) {
|
||||
JSObject *proto = &object->getReservedSlot(JSSLOT_DEBUG_FRAME_PROTO).toObject();
|
||||
JSObject *frameobj = NewNonFunction<WithProto::Given>(cx, &Frame_class, proto, NULL);
|
||||
if (!frameobj || !frameobj->ensureClassReservedSlots(cx))
|
||||
return false;
|
||||
frameobj->setPrivate(fp);
|
||||
frameobj->setReservedSlot(JSSLOT_FRAME_OWNER, ObjectValue(*object));
|
||||
if (!frames.add(p, fp, frameobj)) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
vp->setObject(*p->value);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Debug::slowPathLeaveStackFrame(JSContext *cx)
|
||||
{
|
||||
JSStackFrame *fp = cx->regs->fp;
|
||||
JSCompartment *compartment = cx->compartment;
|
||||
const JSCompartment::DebugVector &debuggers = compartment->getDebuggers();
|
||||
for (Debug **p = debuggers.begin(); p != debuggers.end(); p++) {
|
||||
Debug *dbg = *p;
|
||||
if (FrameMap::Ptr p = dbg->frames.lookup(fp)) {
|
||||
JSObject *frameobj = p->value;
|
||||
frameobj->setPrivate(NULL);
|
||||
dbg->frames.remove(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JSTrapStatus
|
||||
Debug::handleUncaughtException(AutoCompartment &ac, Value *vp, bool callHook)
|
||||
{
|
||||
@ -133,7 +191,7 @@ Debug::handleUncaughtException(AutoCompartment &ac, Value *vp, bool callHook)
|
||||
if (ExternalInvoke(cx, ObjectValue(*object), fval, 1, &exc, &rv))
|
||||
return parseResumptionValue(ac, true, rv, vp, false);
|
||||
}
|
||||
|
||||
|
||||
if (cx->isExceptionPending()) {
|
||||
JS_ReportPendingException(cx);
|
||||
cx->clearPendingException();
|
||||
@ -209,14 +267,20 @@ CallMethodIfPresent(JSContext *cx, JSObject *obj, const char *name, int argc, Va
|
||||
JSTrapStatus
|
||||
Debug::handleDebuggerStatement(JSContext *cx, Value *vp)
|
||||
{
|
||||
// Grab cx->regs->fp before pushing a dummy frame.
|
||||
JSStackFrame *fp = cx->regs->fp;
|
||||
|
||||
JS_ASSERT(hasDebuggerHandler);
|
||||
AutoCompartment ac(cx, hooksObject);
|
||||
if (!ac.enter())
|
||||
return JSTRAP_ERROR;
|
||||
|
||||
// XXX debuggerHandler should receive a Frame.
|
||||
Value argv[1];
|
||||
if (!getScriptFrame(cx, fp, argv))
|
||||
return JSTRAP_ERROR;
|
||||
|
||||
Value rv;
|
||||
bool ok = CallMethodIfPresent(cx, hooksObject, "debuggerHandler", 0, NULL, &rv);
|
||||
bool ok = CallMethodIfPresent(cx, hooksObject, "debuggerHandler", 1, argv, &rv);
|
||||
return parseResumptionValue(ac, ok, rv, vp);
|
||||
}
|
||||
|
||||
@ -252,7 +316,6 @@ Debug::dispatchDebuggerStatement(JSContext *cx, js::Value *vp)
|
||||
return JSTRAP_CONTINUE;
|
||||
}
|
||||
|
||||
|
||||
// === Debug JSObjects
|
||||
|
||||
bool
|
||||
@ -299,6 +362,34 @@ Debug::trace(JSTracer *trc, JSObject *obj)
|
||||
MarkObject(trc, *dbg->hooksObject, "hooks");
|
||||
if (dbg->uncaughtExceptionHook)
|
||||
MarkObject(trc, *dbg->uncaughtExceptionHook, "hooks");
|
||||
|
||||
// Mark Debug.Frame objects that are reachable from JS if we look them up
|
||||
// again (because the corresponding JSStackFrame is still on the stack).
|
||||
for (FrameMap::Enum e(dbg->frames); !e.empty(); e.popFront()) {
|
||||
if (e.front().value->getPrivate())
|
||||
MarkObject(trc, *obj, "live Debug.Frame");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Debug::sweepAll(JSRuntime *rt)
|
||||
{
|
||||
for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); c++)
|
||||
sweepCompartment(*c);
|
||||
}
|
||||
|
||||
void
|
||||
Debug::sweepCompartment(JSCompartment *compartment)
|
||||
{
|
||||
// Sweep FrameMap entries for objects being collected.
|
||||
const JSCompartment::DebugVector &debuggers = compartment->getDebuggers();
|
||||
for (Debug **p = debuggers.begin(); p != debuggers.end(); p++) {
|
||||
Debug *dbg = *p;
|
||||
for (FrameMap::Enum e(dbg->frames); !e.empty(); e.popFront()) {
|
||||
if (!e.front().value->isMarked())
|
||||
e.removeFront();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -319,7 +410,7 @@ Debug::detachFrom(JSCompartment *c)
|
||||
}
|
||||
|
||||
Class Debug::jsclass = {
|
||||
"Debug", JSCLASS_HAS_PRIVATE,
|
||||
"Debug", JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(JSSLOT_DEBUG_COUNT),
|
||||
PropertyStub, PropertyStub, PropertyStub, StrictPropertyStub,
|
||||
EnumerateStub, ResolveStub, ConvertStub, Debug::finalize,
|
||||
NULL, /* reserved0 */
|
||||
@ -432,17 +523,20 @@ Debug::construct(JSContext *cx, uintN argc, Value *vp)
|
||||
JSObject *proto = &v.toObject();
|
||||
JS_ASSERT(proto->getClass() == &Debug::jsclass);
|
||||
|
||||
// Make the new Debug object.
|
||||
// Make the new Debug object. Each one has a reference to
|
||||
// Debug.Frame.prototype in a reserved slot.
|
||||
JSObject *obj = NewNonFunction<WithProto::Given>(cx, &Debug::jsclass, proto, NULL);
|
||||
if (!obj)
|
||||
if (!obj || !obj->ensureClassReservedSlots(cx))
|
||||
return false;
|
||||
obj->setReservedSlot(JSSLOT_DEBUG_FRAME_PROTO,
|
||||
proto->getReservedSlot(JSSLOT_DEBUG_FRAME_PROTO));
|
||||
JSObject *hooks = NewBuiltinClassInstance(cx, &js_ObjectClass);
|
||||
if (!hooks)
|
||||
return false;
|
||||
Debug *dbg = cx->new_<Debug>(obj, hooks, debuggeeCompartment);
|
||||
if (!dbg)
|
||||
return false;
|
||||
if (!debuggeeCompartment->addDebug(dbg)) {
|
||||
if (!dbg->init() || !debuggeeCompartment->addDebug(dbg)) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
@ -460,14 +554,77 @@ JSPropertySpec Debug::properties[] = {
|
||||
JS_PS_END
|
||||
};
|
||||
|
||||
// === Debug.Frame
|
||||
|
||||
Class Frame_class = {
|
||||
"Frame", JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(JSSLOT_FRAME_COUNT),
|
||||
PropertyStub, PropertyStub, PropertyStub, StrictPropertyStub,
|
||||
EnumerateStub, ResolveStub, ConvertStub, FinalizeStub,
|
||||
};
|
||||
|
||||
#define THIS_FRAME(cx, vp, fnname, thisobj, fp) \
|
||||
JSObject *thisobj = CheckThisClass(cx, vp, &Frame_class, fnname); \
|
||||
if (!thisobj) \
|
||||
return false; \
|
||||
JSStackFrame *fp = (JSStackFrame *) thisobj->getPrivate()
|
||||
|
||||
JSBool
|
||||
Frame_getType(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
THIS_FRAME(cx, vp, "get type", thisobj, fp);
|
||||
|
||||
// Indirect eval frames are both isGlobalFrame() and isEvalFrame(), so the
|
||||
// order of checks here is significant.
|
||||
vp->setString(fp->isEvalFrame()
|
||||
? cx->runtime->atomState.evalAtom
|
||||
: fp->isGlobalFrame()
|
||||
? cx->runtime->atomState.globalAtom
|
||||
: cx->runtime->atomState.callAtom);
|
||||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
Frame_getGenerator(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
THIS_FRAME(cx, vp, "get generator", thisobj, fp);
|
||||
vp->setBoolean(fp->isGeneratorFrame());
|
||||
return true;
|
||||
}
|
||||
|
||||
JSBool
|
||||
Frame_construct(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_CONSTRUCTOR, "Debug.Frame");
|
||||
return false;
|
||||
}
|
||||
|
||||
JSPropertySpec Frame_properties[] = {
|
||||
JS_PSG("type", Frame_getType, 0),
|
||||
JS_PSG("generator", Frame_getGenerator, 0),
|
||||
JS_PS_END
|
||||
};
|
||||
|
||||
// === Glue
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_DefineDebugObject(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
JSObject *objProto;
|
||||
if (!js_GetClassPrototype(cx, obj, JSProto_Object, &objProto))
|
||||
return NULL;
|
||||
return false;
|
||||
|
||||
return !!js_InitClass(cx, obj, objProto, &Debug::jsclass, Debug::construct, 1,
|
||||
Debug::properties, NULL, NULL, NULL);
|
||||
JSObject *debugCtor;
|
||||
JSObject *debugProto = js_InitClass(cx, obj, objProto, &Debug::jsclass, Debug::construct, 1,
|
||||
Debug::properties, NULL, NULL, NULL, &debugCtor);
|
||||
if (!debugProto || !debugProto->ensureClassReservedSlots(cx))
|
||||
return false;
|
||||
|
||||
JSObject *frameCtor;
|
||||
JSObject *frameProto = js_InitClass(cx, debugCtor, objProto, &Frame_class, Frame_construct, 0,
|
||||
Frame_properties, NULL, NULL, NULL, &frameCtor);
|
||||
if (!frameProto)
|
||||
return false;
|
||||
debugProto->setReservedSlot(JSSLOT_DEBUG_FRAME_PROTO, ObjectValue(*frameProto));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "jsapi.h"
|
||||
#include "jscompartment.h"
|
||||
#include "jsgc.h"
|
||||
#include "jshashtable.h"
|
||||
#include "jswrapper.h"
|
||||
#include "jsvalue.h"
|
||||
|
||||
@ -64,6 +65,10 @@ class Debug {
|
||||
// property was set.
|
||||
bool hasDebuggerHandler;
|
||||
|
||||
typedef HashMap<JSStackFrame *, JSObject *, DefaultHasher<JSStackFrame *>, SystemAllocPolicy>
|
||||
FrameMap;
|
||||
FrameMap frames;
|
||||
|
||||
JSTrapStatus handleUncaughtException(AutoCompartment &ac, Value *vp, bool callHook);
|
||||
JSTrapStatus parseResumptionValue(AutoCompartment &ac, bool ok, const Value &rv, Value *vp,
|
||||
bool callHook = true);
|
||||
@ -83,14 +88,22 @@ class Debug {
|
||||
|
||||
inline bool hasAnyLiveHooks() const;
|
||||
|
||||
bool getScriptFrame(JSContext *cx, JSStackFrame *fp, Value *vp);
|
||||
static void slowPathLeaveStackFrame(JSContext *cx);
|
||||
|
||||
inline bool observesDebuggerStatement() const;
|
||||
static JSTrapStatus dispatchDebuggerStatement(JSContext *cx, Value *vp);
|
||||
JSTrapStatus handleDebuggerStatement(JSContext *cx, Value *vp);
|
||||
|
||||
public:
|
||||
Debug(JSObject *dbg, JSObject *hooks, JSCompartment *compartment);
|
||||
bool init();
|
||||
inline JSObject *toJSObject() const;
|
||||
static inline Debug *fromJSObject(JSObject *obj);
|
||||
|
||||
// Mark some Debug objects. A Debug object is live if:
|
||||
// Methods for interaction with the GC.
|
||||
//
|
||||
// A Debug object is live if:
|
||||
// * the Debug JSObject is live (Debug::trace handles this case); OR
|
||||
// * it is in the middle of dispatching an event (the event dispatching
|
||||
// code roots it in this case); OR
|
||||
@ -100,18 +113,18 @@ class Debug {
|
||||
// - it has a breakpoint set on a live script
|
||||
// - it has a watchpoint set on a live object.
|
||||
//
|
||||
// The last case is handled by this method. If it finds any Debug objects
|
||||
// that are definitely live but not yet marked, it marks them and returns
|
||||
// true. If not, it returns false.
|
||||
// The last case is handled by the mark() method. If it finds any Debug
|
||||
// objects that are definitely live but not yet marked, it marks them and
|
||||
// returns true. If not, it returns false.
|
||||
//
|
||||
static bool mark(GCMarker *trc, JSCompartment *compartment, JSGCInvocationKind gckind);
|
||||
|
||||
inline JSObject *toJSObject() const;
|
||||
static inline Debug *fromJSObject(JSObject *obj);
|
||||
static void sweepAll(JSRuntime *rt);
|
||||
static void sweepCompartment(JSCompartment *compartment);
|
||||
|
||||
inline bool observesCompartment(JSCompartment *c) const;
|
||||
void detachFrom(JSCompartment *c);
|
||||
|
||||
static inline void leaveStackFrame(JSContext *cx);
|
||||
static inline JSTrapStatus onDebuggerStatement(JSContext *cx, js::Value *vp);
|
||||
};
|
||||
|
||||
@ -142,6 +155,13 @@ Debug::fromJSObject(JSObject *obj)
|
||||
return (Debug *) obj->getPrivate();
|
||||
}
|
||||
|
||||
void
|
||||
Debug::leaveStackFrame(JSContext *cx)
|
||||
{
|
||||
if (!cx->compartment->getDebuggers().empty())
|
||||
slowPathLeaveStackFrame(cx);
|
||||
}
|
||||
|
||||
bool
|
||||
Debug::observesDebuggerStatement() const
|
||||
{
|
||||
|
@ -133,6 +133,7 @@ ScriptDebugPrologue(JSContext *cx, JSStackFrame *fp)
|
||||
bool
|
||||
ScriptDebugEpilogue(JSContext *cx, JSStackFrame *fp, bool okArg)
|
||||
{
|
||||
JS_ASSERT(fp == cx->fp());
|
||||
JSBool ok = okArg;
|
||||
|
||||
Probes::exitJSFun(cx, fp->maybeFun(), fp->script());
|
||||
@ -146,6 +147,7 @@ ScriptDebugEpilogue(JSContext *cx, JSStackFrame *fp, bool okArg)
|
||||
hook(cx, fp, false, &ok, hookData);
|
||||
}
|
||||
}
|
||||
Debug::leaveStackFrame(cx);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
@ -2527,6 +2527,11 @@ MarkAndSweep(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind GCTIM
|
||||
/* Finalize watch points associated with unreachable objects. */
|
||||
js_SweepWatchPoints(cx);
|
||||
|
||||
if (comp)
|
||||
Debug::sweepCompartment(comp);
|
||||
else
|
||||
Debug::sweepAll(rt);
|
||||
|
||||
/*
|
||||
* We finalize objects before other GC things to ensure that object's finalizer
|
||||
* can access them even if they will be freed. Sweep the runtime's property trees
|
||||
|
@ -3827,7 +3827,8 @@ DefineConstructorAndPrototype(JSContext *cx, JSObject *obj, JSProtoKey key, JSAt
|
||||
JSObject *protoProto, Class *clasp,
|
||||
Native constructor, uintN nargs,
|
||||
JSPropertySpec *ps, JSFunctionSpec *fs,
|
||||
JSPropertySpec *static_ps, JSFunctionSpec *static_fs)
|
||||
JSPropertySpec *static_ps, JSFunctionSpec *static_fs,
|
||||
JSObject **ctorp)
|
||||
{
|
||||
/*
|
||||
* Create a prototype object for this class.
|
||||
@ -3966,6 +3967,8 @@ DefineConstructorAndPrototype(JSContext *cx, JSObject *obj, JSProtoKey key, JSAt
|
||||
if (key != JSProto_Null && !js_SetClassObject(cx, obj, key, ctor, proto))
|
||||
goto bad;
|
||||
|
||||
if (ctorp)
|
||||
*ctorp = ctor;
|
||||
return proto;
|
||||
|
||||
bad:
|
||||
@ -3982,7 +3985,8 @@ JSObject *
|
||||
js_InitClass(JSContext *cx, JSObject *obj, JSObject *protoProto,
|
||||
Class *clasp, Native constructor, uintN nargs,
|
||||
JSPropertySpec *ps, JSFunctionSpec *fs,
|
||||
JSPropertySpec *static_ps, JSFunctionSpec *static_fs)
|
||||
JSPropertySpec *static_ps, JSFunctionSpec *static_fs,
|
||||
JSObject **ctorp)
|
||||
{
|
||||
JSAtom *atom = js_Atomize(cx, clasp->name, strlen(clasp->name), 0);
|
||||
if (!atom)
|
||||
@ -4008,7 +4012,7 @@ js_InitClass(JSContext *cx, JSObject *obj, JSObject *protoProto,
|
||||
}
|
||||
|
||||
return DefineConstructorAndPrototype(cx, obj, key, atom, protoProto, clasp, constructor, nargs,
|
||||
ps, fs, static_ps, static_fs);
|
||||
ps, fs, static_ps, static_fs, ctorp);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -663,6 +663,9 @@ struct JSObject : js::gc::Cell {
|
||||
|
||||
inline js::Value getReservedSlot(uintN index) const;
|
||||
|
||||
/* Call this only after the appropriate ensure{Class,Instance}ReservedSlots call. */
|
||||
inline void setReservedSlot(uintN index, const js::Value &v);
|
||||
|
||||
/* Defined in jsscopeinlines.h to avoid including implementation dependencies here. */
|
||||
inline void updateShape(JSContext *cx);
|
||||
inline void updateFlags(const js::Shape *shape, bool isDefinitelyAtom = false);
|
||||
@ -1548,14 +1551,16 @@ DefineConstructorAndPrototype(JSContext *cx, JSObject *obj, JSProtoKey key, JSAt
|
||||
JSObject *protoProto, Class *clasp,
|
||||
Native constructor, uintN nargs,
|
||||
JSPropertySpec *ps, JSFunctionSpec *fs,
|
||||
JSPropertySpec *static_ps, JSFunctionSpec *static_fs);
|
||||
JSPropertySpec *static_ps, JSFunctionSpec *static_fs,
|
||||
JSObject **ctorp = NULL);
|
||||
}
|
||||
|
||||
extern JSObject *
|
||||
js_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto,
|
||||
js::Class *clasp, js::Native constructor, uintN nargs,
|
||||
JSPropertySpec *ps, JSFunctionSpec *fs,
|
||||
JSPropertySpec *static_ps, JSFunctionSpec *static_fs);
|
||||
JSPropertySpec *static_ps, JSFunctionSpec *static_fs,
|
||||
JSObject **ctorp = NULL);
|
||||
|
||||
/*
|
||||
* Select Object.prototype method names shared between jsapi.cpp and jsobj.cpp.
|
||||
|
@ -298,6 +298,12 @@ JSObject::getReservedSlot(uintN index) const
|
||||
return (index < numSlots()) ? getSlot(index) : js::UndefinedValue();
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::setReservedSlot(uintN index, const js::Value &v)
|
||||
{
|
||||
setSlot(index, v);
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSObject::canHaveMethodBarrier() const
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user