mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Add Debug.Frame.prototype.evalWithBindings.
This commit is contained in:
parent
0305e45450
commit
20c7510a95
38
js/src/jit-test/tests/debug/Frame-evalWithBindings-01.js
Normal file
38
js/src/jit-test/tests/debug/Frame-evalWithBindings-01.js
Normal file
@ -0,0 +1,38 @@
|
||||
// |jit-test| debug
|
||||
// evalWithBindings basics
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
var dbg = new Debug(g);
|
||||
var hits = 0;
|
||||
dbg.hooks = {
|
||||
debuggerHandler: function (frame) {
|
||||
assertEq(frame.evalWithBindings("x", {x: 2}).return, 2);
|
||||
assertEq(frame.evalWithBindings("x + y", {x: 2}).return, 5);
|
||||
hits++;
|
||||
}
|
||||
};
|
||||
|
||||
// in global code
|
||||
g.y = 3;
|
||||
g.eval("debugger;");
|
||||
|
||||
// in function code
|
||||
g.y = "fail";
|
||||
g.eval("function f(y) { debugger; }");
|
||||
g.f(3);
|
||||
|
||||
// in direct eval code
|
||||
g.eval("function f() { var y = 3; eval('debugger;'); }");
|
||||
g.f();
|
||||
|
||||
// in strict eval code with var
|
||||
g.eval("function f() { 'use strict'; eval('var y = 3; debugger;'); }");
|
||||
g.f();
|
||||
|
||||
// in a with block
|
||||
g.eval("with ({y: 3}) { debugger; }");
|
||||
|
||||
// shadowing
|
||||
g.eval("let (x = 50, y = 3) { debugger; }");
|
||||
|
||||
assertEq(hits, 6);
|
22
js/src/jit-test/tests/debug/Frame-evalWithBindings-02.js
Normal file
22
js/src/jit-test/tests/debug/Frame-evalWithBindings-02.js
Normal file
@ -0,0 +1,22 @@
|
||||
// |jit-test| debug
|
||||
// evalWithBindings to call a method of a debuggee object
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
var dbg = new Debug;
|
||||
var global = dbg.addDebuggee(g);
|
||||
var hits = 0;
|
||||
dbg.hooks = {
|
||||
debuggerHandler: function (frame) {
|
||||
var obj = frame.arguments[0];
|
||||
var expected = frame.arguments[1];
|
||||
assertEq(frame.evalWithBindings("obj.toString()", {obj: obj}).return, expected);
|
||||
hits++;
|
||||
}
|
||||
};
|
||||
|
||||
g.eval("function f(obj, expected) { debugger; }");
|
||||
|
||||
g.eval("f(new Number(-0), '0');");
|
||||
g.eval("f(new String('ok'), 'ok');");
|
||||
g.eval("f({toString: function () { return f; }}, f);");
|
||||
assertEq(hits, 3);
|
20
js/src/jit-test/tests/debug/Frame-evalWithBindings-03.js
Normal file
20
js/src/jit-test/tests/debug/Frame-evalWithBindings-03.js
Normal file
@ -0,0 +1,20 @@
|
||||
// |jit-test| debug
|
||||
// arguments works in evalWithBindings (it does not interpose a function scope)
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
var dbg = new Debug;
|
||||
var global = dbg.addDebuggee(g);
|
||||
var hits = 0;
|
||||
dbg.hooks = {
|
||||
debuggerHandler: function (frame) {
|
||||
var argc = frame.arguments.length;
|
||||
assertEq(argc, 7);
|
||||
assertEq(frame.evalWithBindings("arguments[prop]", {prop: "length"}).return, argc);
|
||||
for (var i = 0; i < argc; i++)
|
||||
assertEq(frame.evalWithBindings("arguments[i]", {i: i}).return, frame.arguments[i]);
|
||||
hits++;
|
||||
}
|
||||
};
|
||||
g.eval("function f() { debugger; }");
|
||||
g.eval("f(undefined, -0, NaN, '\uffff', Array.prototype, Math, f);");
|
||||
assertEq(hits, 1);
|
21
js/src/jit-test/tests/debug/Frame-evalWithBindings-04.js
Normal file
21
js/src/jit-test/tests/debug/Frame-evalWithBindings-04.js
Normal file
@ -0,0 +1,21 @@
|
||||
// |jit-test| debug
|
||||
// evalWithBindings works on non-top frames.
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
var dbg = new Debug(g);
|
||||
var f1;
|
||||
var hits = 0;
|
||||
dbg.hooks = {
|
||||
debuggerHandler: function (frame) {
|
||||
assertEq(frame.older.evalWithBindings("q + r", {r: 3}).return, 5);
|
||||
|
||||
// frame.older.older is in the same function as frame, but a different activation of it
|
||||
assertEq(frame.older.older.evalWithBindings("q + r", {r: 3}).return, 6);
|
||||
hits++;
|
||||
}
|
||||
};
|
||||
|
||||
g.eval("function f1(q) { if (q == 1) debugger; else f2(2); }");
|
||||
g.eval("function f2(arg) { var q = arg; f1(1); }");
|
||||
g.f1(3);
|
||||
assertEq(hits, 1);
|
15
js/src/jit-test/tests/debug/Frame-evalWithBindings-05.js
Normal file
15
js/src/jit-test/tests/debug/Frame-evalWithBindings-05.js
Normal file
@ -0,0 +1,15 @@
|
||||
// |jit-test| debug
|
||||
// evalWithBindings code can assign to the bindings.
|
||||
var g = newGlobal('new-compartment');
|
||||
var dbg = new Debug(g);
|
||||
var hits = 0;
|
||||
dbg.hooks = {
|
||||
debuggerHandler: function (frame) {
|
||||
assertEq(frame.evalWithBindings("for (i = 0; i < 5; i++) {} i;", {i: 10}).return, 5);
|
||||
hits++;
|
||||
}
|
||||
};
|
||||
|
||||
g.eval("debugger;");
|
||||
assertEq("i" in g, false);
|
||||
assertEq(hits, 1);
|
13
js/src/jit-test/tests/debug/Frame-evalWithBindings-06.js
Normal file
13
js/src/jit-test/tests/debug/Frame-evalWithBindings-06.js
Normal file
@ -0,0 +1,13 @@
|
||||
// |jit-test| debug
|
||||
// In evalWithBindings code, assignment to any name not in the bindings works just as in eval.
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
var dbg = new Debug(g);
|
||||
dbg.hooks = {
|
||||
debuggerHandler: function (frame) {
|
||||
assertEq(frame.evalWithBindings("y = z; x = w;", {z: 2, w: 3}).return, 3);
|
||||
}
|
||||
};
|
||||
g.eval("function f(x) { debugger; assertEq(x, 3); }");
|
||||
g.eval("var y = 0; f(0);");
|
||||
assertEq(g.y, 2);
|
20
js/src/jit-test/tests/debug/Frame-evalWithBindings-07.js
Normal file
20
js/src/jit-test/tests/debug/Frame-evalWithBindings-07.js
Normal file
@ -0,0 +1,20 @@
|
||||
// |jit-test| debug
|
||||
// var statements in strict evalWithBindings code behave like strict eval.
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
var dbg = new Debug(g);
|
||||
var hits = 0;
|
||||
dbg.hooks = {
|
||||
debuggerHandler: function (frame) {
|
||||
assertEq(frame.evalWithBindings("var i = a*a + b*b; i === 25;", {a: 3, b: 4}).return, true);
|
||||
hits++;
|
||||
}
|
||||
};
|
||||
g.eval("'use strict'; debugger;");
|
||||
assertEq(hits, 1);
|
||||
assertEq("i" in g, false);
|
||||
|
||||
g.eval("function die() { throw fit; }");
|
||||
g.eval("Object.defineProperty(this, 'i', {get: die, set: die});");
|
||||
g.eval("'use strict'; debugger;");
|
||||
assertEq(hits, 2);
|
17
js/src/jit-test/tests/debug/Frame-evalWithBindings-08.js
Normal file
17
js/src/jit-test/tests/debug/Frame-evalWithBindings-08.js
Normal file
@ -0,0 +1,17 @@
|
||||
// |jit-test| debug
|
||||
// evalWithBindings ignores non-enumerable and non-own properties.
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
var dbg = new Debug(g);
|
||||
var hits = 0;
|
||||
dbg.hooks = {
|
||||
debuggerHandler: function (frame) {
|
||||
assertEq(frame.evalWithBindings("toString + constructor + length", []).return, 112233);
|
||||
var obj = Object.create({constructor: "FAIL"}, {length: {value: "fail"}});
|
||||
assertEq(frame.evalWithBindings("toString + constructor + length", obj).return, 112233);
|
||||
hits++;
|
||||
}
|
||||
};
|
||||
g.eval("function f() { var toString = 111111, constructor = 1111, length = 11; debugger; }");
|
||||
g.f();
|
||||
assertEq(hits, 1);
|
31
js/src/jit-test/tests/debug/Frame-evalWithBindings-09.js
Normal file
31
js/src/jit-test/tests/debug/Frame-evalWithBindings-09.js
Normal file
@ -0,0 +1,31 @@
|
||||
// |jit-test| debug
|
||||
// evalWithBindings code is debuggee code, so it can trip the debugger. It nests!
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
var dbg = new Debug(g);
|
||||
var f1;
|
||||
var hits = 0;
|
||||
dbg.hooks = {
|
||||
debuggerHandler: function (frame) {
|
||||
f1 = frame;
|
||||
|
||||
// This trips the throw hook.
|
||||
var x = frame.evalWithBindings("wrongSpeling", {rightSpelling: 2}).throw;
|
||||
|
||||
assertEq(frame.evalWithBindings("exc.name", {exc: x}).return, "ReferenceError");
|
||||
hits++;
|
||||
},
|
||||
throw: function (frame, exc) {
|
||||
assertEq(frame !== f1, true);
|
||||
|
||||
// f1's environment does not contain the binding for the first evalWithBindings call.
|
||||
assertEq(f1.eval("rightSpelling").return, "dependent");
|
||||
assertEq(f1.evalWithBindings("n + rightSpelling", {n: "in"}).return, "independent");
|
||||
|
||||
// frame's environment does contain the binding.
|
||||
assertEq(frame.eval("rightSpelling").return, 2);
|
||||
assertEq(frame.evalWithBindings("rightSpelling + three", {three: 3}).return, 5);
|
||||
hits++;
|
||||
}
|
||||
};
|
||||
g.eval("(function () { var rightSpelling = 'dependent'; debugger; })();");
|
19
js/src/jit-test/tests/debug/Frame-evalWithBindings-10.js
Normal file
19
js/src/jit-test/tests/debug/Frame-evalWithBindings-10.js
Normal file
@ -0,0 +1,19 @@
|
||||
// |jit-test| debug
|
||||
// Direct eval code under evalWithbindings sees both the bindings and the enclosing scope.
|
||||
|
||||
var g = newGlobal('new-compartment');
|
||||
var dbg = new Debug(g);
|
||||
var hits = 0;
|
||||
dbg.hooks = {
|
||||
debuggerHandler: function (frame) {
|
||||
var code =
|
||||
"assertEq(a, 1234);\n" +
|
||||
"assertEq(b, null);\n" +
|
||||
"assertEq(c, 'ok');\n";
|
||||
assertEq(frame.evalWithBindings("eval(s)", {s: code, a: 1234}).return, undefined);
|
||||
hits++;
|
||||
}
|
||||
};
|
||||
g.eval("function f(b) { var c = 'ok'; debugger; }");
|
||||
g.f(null);
|
||||
assertEq(hits, 1);
|
113
js/src/jsdbg.cpp
113
js/src/jsdbg.cpp
@ -42,6 +42,7 @@
|
||||
#include "jsdbg.h"
|
||||
#include "jsapi.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsemit.h"
|
||||
#include "jsgcmark.h"
|
||||
#include "jsobj.h"
|
||||
#include "jswrapper.h"
|
||||
@ -95,7 +96,7 @@ ReportMoreArgsNeeded(JSContext *cx, const char *name, uintN required)
|
||||
|
||||
#define REQUIRE_ARGC(name, n) \
|
||||
JS_BEGIN_MACRO \
|
||||
if (argc < n) \
|
||||
if (argc < (n)) \
|
||||
return ReportMoreArgsNeeded(cx, name, n); \
|
||||
JS_END_MACRO
|
||||
|
||||
@ -1095,7 +1096,8 @@ CheckThisFrame(JSContext *cx, Value *vp, const char *fnname, bool checkLive)
|
||||
JSObject *thisobj = CheckThisFrame(cx, vp, fnname, true); \
|
||||
if (!thisobj) \
|
||||
return false; \
|
||||
StackFrame *fp = (StackFrame *) thisobj->getPrivate()
|
||||
StackFrame *fp = (StackFrame *) thisobj->getPrivate(); \
|
||||
JS_ASSERT((cx)->stack.contains(fp))
|
||||
|
||||
static JSBool
|
||||
DebugFrame_getType(JSContext *cx, uintN argc, Value *vp)
|
||||
@ -1268,13 +1270,46 @@ DebugFrame_getLive(JSContext *cx, uintN argc, Value *vp)
|
||||
return true;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
DebugFrame_eval(JSContext *cx, uintN argc, Value *vp)
|
||||
namespace js {
|
||||
|
||||
JSBool
|
||||
EvaluateInScope(JSContext *cx, JSObject *scobj, StackFrame *fp, const jschar *chars,
|
||||
uintN length, const char *filename, uintN lineno, Value *rval)
|
||||
{
|
||||
REQUIRE_ARGC("Debug.Frame.eval", 1);
|
||||
THIS_FRAME(cx, vp, "eval", thisobj, fp);
|
||||
assertSameCompartment(cx, scobj, fp);
|
||||
|
||||
/*
|
||||
* NB: This function breaks the assumption that the compiler can see all
|
||||
* calls and properly compute a static level. In order to get around this,
|
||||
* we use a static level that will cause us not to attempt to optimize
|
||||
* variable references made by this frame.
|
||||
*/
|
||||
JSScript *script = Compiler::compileScript(cx, scobj, fp, fp->scopeChain().principals(cx),
|
||||
TCF_COMPILE_N_GO, chars, length,
|
||||
filename, lineno, cx->findVersion(),
|
||||
NULL, UpvarCookie::UPVAR_LEVEL_LIMIT);
|
||||
|
||||
if (!script)
|
||||
return false;
|
||||
|
||||
bool ok = Execute(cx, *scobj, script, fp, StackFrame::DEBUGGER | StackFrame::EVAL, rval);
|
||||
js_DestroyScript(cx, script);
|
||||
return ok;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
enum EvalBindingsMode { WithoutBindings, WithBindings };
|
||||
|
||||
static JSBool
|
||||
DebugFrameEval(JSContext *cx, uintN argc, Value *vp, EvalBindingsMode mode)
|
||||
{
|
||||
REQUIRE_ARGC(mode == WithBindings ? "Debug.Frame.evalWithBindings" : "Debug.Frame.eval",
|
||||
mode == WithBindings ? 2 : 1);
|
||||
THIS_FRAME(cx, vp, mode == WithBindings ? "evalWithBindings" : "eval", thisobj, fp);
|
||||
Debug *dbg = Debug::fromChildJSObject(&vp[1].toObject());
|
||||
|
||||
// Check the first argument, the eval code string.
|
||||
if (!vp[2].isString()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_EXPECTED_TYPE,
|
||||
"Debug.Frame.eval", "string", InformalValueTypeName(vp[2]));
|
||||
@ -1283,17 +1318,76 @@ DebugFrame_eval(JSContext *cx, uintN argc, Value *vp)
|
||||
JSLinearString *linearStr = vp[2].toString()->ensureLinear(cx);
|
||||
if (!linearStr)
|
||||
return false;
|
||||
JS::Anchor<JSString *> anchor(linearStr);
|
||||
|
||||
// Gather keys and values of bindings, if any. This must be done in the
|
||||
// debugger compartment, since that is where any exceptions must be
|
||||
// thrown.
|
||||
AutoIdVector keys(cx);
|
||||
AutoValueVector values(cx);
|
||||
if (mode == WithBindings) {
|
||||
JSObject *bindingsobj = NonNullObject(cx, vp[3]);
|
||||
if (!bindingsobj ||
|
||||
!GetPropertyNames(cx, bindingsobj, JSITER_OWNONLY, &keys) ||
|
||||
!values.growBy(keys.length()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < keys.length(); i++) {
|
||||
Value *vp = &values[i];
|
||||
if (!bindingsobj->getProperty(cx, bindingsobj, keys[i], vp) ||
|
||||
!dbg->unwrapDebuggeeValue(cx, vp))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AutoCompartment ac(cx, &fp->scopeChain());
|
||||
if (!ac.enter())
|
||||
return false;
|
||||
|
||||
// Get a scope object.
|
||||
if (fp->isNonEvalFunctionFrame() && !fp->hasCallObj() && !CreateFunCallObject(cx, fp))
|
||||
return false;
|
||||
JSObject *scobj = GetScopeChain(cx, fp);
|
||||
if (!scobj)
|
||||
return false;
|
||||
|
||||
// If evalWithBindings, create the inner scope object.
|
||||
if (mode == WithBindings) {
|
||||
// TODO - Should probably create a With object here.
|
||||
scobj = NewNonFunction<WithProto::Given>(cx, &js_ObjectClass, NULL, scobj);
|
||||
if (!scobj)
|
||||
return false;
|
||||
for (size_t i = 0; i < keys.length(); i++) {
|
||||
if (!cx->compartment->wrap(cx, &values[i]) ||
|
||||
!DefineNativeProperty(cx, scobj, keys[i], values[i], NULL, NULL, 0, 0, 0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Run the code and produce the completion value.
|
||||
Value rval;
|
||||
bool ok = JS_EvaluateUCInStackFrame(cx, Jsvalify(fp), linearStr->chars(), linearStr->length(),
|
||||
"debugger eval code", 1, Jsvalify(&rval));
|
||||
JS::Anchor<JSString *> anchor(linearStr);
|
||||
bool ok = EvaluateInScope(cx, scobj, fp, linearStr->chars(), linearStr->length(),
|
||||
"debugger eval code", 1, &rval);
|
||||
return dbg->newCompletionValue(ac, ok, rval, vp);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
DebugFrame_eval(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
return DebugFrameEval(cx, argc, vp, WithoutBindings);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
DebugFrame_evalWithBindings(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
return DebugFrameEval(cx, argc, vp, WithBindings);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
DebugFrame_construct(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
@ -1315,6 +1409,7 @@ static JSPropertySpec DebugFrame_properties[] = {
|
||||
|
||||
static JSFunctionSpec DebugFrame_methods[] = {
|
||||
JS_FN("eval", DebugFrame_eval, 1, 0),
|
||||
JS_FN("evalWithBindings", DebugFrame_evalWithBindings, 1, 0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
|
@ -270,6 +270,10 @@ Debug::onThrow(JSContext *cx, js::Value *vp)
|
||||
DebugHandleMethod(&Debug::handleThrow));
|
||||
}
|
||||
|
||||
extern JSBool
|
||||
EvaluateInScope(JSContext *cx, JSObject *scobj, StackFrame *fp, const jschar *chars,
|
||||
uintN length, const char *filename, uintN lineno, Value *rval);
|
||||
|
||||
}
|
||||
|
||||
#endif /* jsdbg_h__ */
|
||||
|
@ -1683,26 +1683,8 @@ JS_EvaluateUCInStackFrame(JSContext *cx, JSStackFrame *fpArg,
|
||||
if (!ac.enter())
|
||||
return false;
|
||||
|
||||
/*
|
||||
* NB: This function breaks the assumption that the compiler can see all
|
||||
* calls and properly compute a static level. In order to get around this,
|
||||
* we use a static level that will cause us not to attempt to optimize
|
||||
* variable references made by this frame.
|
||||
*/
|
||||
StackFrame *fp = Valueify(fpArg);
|
||||
JSScript *script = Compiler::compileScript(cx, scobj, fp, fp->scopeChain().principals(cx),
|
||||
TCF_COMPILE_N_GO, chars, length,
|
||||
filename, lineno, cx->findVersion(),
|
||||
NULL, UpvarCookie::UPVAR_LEVEL_LIMIT);
|
||||
|
||||
if (!script)
|
||||
return false;
|
||||
|
||||
uintN evalFlags = StackFrame::DEBUGGER | StackFrame::EVAL;
|
||||
bool ok = Execute(cx, *scobj, script, fp, evalFlags, Valueify(rval));
|
||||
|
||||
js_DestroyScript(cx, script);
|
||||
return ok;
|
||||
return EvaluateInScope(cx, scobj, fp, chars, length, filename, lineno, Valueify(rval));
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
|
@ -904,8 +904,7 @@ Execute(JSContext *cx, JSObject &chain, JSScript *script, StackFrame *prev, uint
|
||||
/* Initialize frame and locals. */
|
||||
JSObject *initialVarObj;
|
||||
if (prev) {
|
||||
JS_ASSERT(chain == prev->scopeChain());
|
||||
frame.fp()->initEvalFrame(cx, script, prev, flags);
|
||||
frame.fp()->initEvalFrame(cx, script, prev, &chain, flags);
|
||||
|
||||
/* NB: prev may not be in cx->currentSegment. */
|
||||
initialVarObj = (prev == cx->maybefp())
|
||||
|
@ -401,12 +401,19 @@ StackFrame::initCallFrameLatePrologue()
|
||||
}
|
||||
|
||||
inline void
|
||||
StackFrame::initEvalFrame(JSContext *cx, JSScript *script, StackFrame *prev, uint32 flagsArg)
|
||||
StackFrame::initEvalFrame(JSContext *cx, JSScript *script, StackFrame *prev, JSObject *chain, uint32 flagsArg)
|
||||
{
|
||||
JS_ASSERT(flagsArg & EVAL);
|
||||
JS_ASSERT((flagsArg & ~(EVAL | DEBUGGER)) == 0);
|
||||
JS_ASSERT(prev->isScriptFrame());
|
||||
|
||||
/*
|
||||
* eval code always runs in prev's scope, except when executed via
|
||||
* DebugFrame_evalWithBindings. Strict eval is another special case, dealt
|
||||
* with specially in js::Execute after this method returns.
|
||||
*/
|
||||
JS_ASSERT_IF(!(flagsArg & DEBUGGER), chain == &prev->scopeChain());
|
||||
|
||||
/* Copy (callee, thisv). */
|
||||
Value *dstvp = (Value *)this - 2;
|
||||
Value *srcvp = prev->hasArgs()
|
||||
@ -427,7 +434,7 @@ StackFrame::initEvalFrame(JSContext *cx, JSScript *script, StackFrame *prev, uin
|
||||
exec.script = script;
|
||||
}
|
||||
|
||||
scopeChain_ = &prev->scopeChain();
|
||||
scopeChain_ = chain;
|
||||
prev_ = prev;
|
||||
prevpc_ = prev->pc(cx);
|
||||
JS_ASSERT(!hasImacropc());
|
||||
|
@ -308,7 +308,7 @@ class StackFrame
|
||||
inline void initCallFrameLatePrologue();
|
||||
|
||||
/* Used for eval. */
|
||||
inline void initEvalFrame(JSContext *cx, JSScript *script, StackFrame *prev,
|
||||
inline void initEvalFrame(JSContext *cx, JSScript *script, StackFrame *prev, JSObject *chain,
|
||||
uint32 flags);
|
||||
inline void initGlobalFrame(JSScript *script, JSObject &chain, StackFrame *prev,
|
||||
uint32 flags);
|
||||
|
Loading…
Reference in New Issue
Block a user