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 "jsdbg.h"
|
||||||
#include "jsapi.h"
|
#include "jsapi.h"
|
||||||
#include "jscntxt.h"
|
#include "jscntxt.h"
|
||||||
|
#include "jsemit.h"
|
||||||
#include "jsgcmark.h"
|
#include "jsgcmark.h"
|
||||||
#include "jsobj.h"
|
#include "jsobj.h"
|
||||||
#include "jswrapper.h"
|
#include "jswrapper.h"
|
||||||
@ -95,7 +96,7 @@ ReportMoreArgsNeeded(JSContext *cx, const char *name, uintN required)
|
|||||||
|
|
||||||
#define REQUIRE_ARGC(name, n) \
|
#define REQUIRE_ARGC(name, n) \
|
||||||
JS_BEGIN_MACRO \
|
JS_BEGIN_MACRO \
|
||||||
if (argc < n) \
|
if (argc < (n)) \
|
||||||
return ReportMoreArgsNeeded(cx, name, n); \
|
return ReportMoreArgsNeeded(cx, name, n); \
|
||||||
JS_END_MACRO
|
JS_END_MACRO
|
||||||
|
|
||||||
@ -1095,7 +1096,8 @@ CheckThisFrame(JSContext *cx, Value *vp, const char *fnname, bool checkLive)
|
|||||||
JSObject *thisobj = CheckThisFrame(cx, vp, fnname, true); \
|
JSObject *thisobj = CheckThisFrame(cx, vp, fnname, true); \
|
||||||
if (!thisobj) \
|
if (!thisobj) \
|
||||||
return false; \
|
return false; \
|
||||||
StackFrame *fp = (StackFrame *) thisobj->getPrivate()
|
StackFrame *fp = (StackFrame *) thisobj->getPrivate(); \
|
||||||
|
JS_ASSERT((cx)->stack.contains(fp))
|
||||||
|
|
||||||
static JSBool
|
static JSBool
|
||||||
DebugFrame_getType(JSContext *cx, uintN argc, Value *vp)
|
DebugFrame_getType(JSContext *cx, uintN argc, Value *vp)
|
||||||
@ -1268,13 +1270,46 @@ DebugFrame_getLive(JSContext *cx, uintN argc, Value *vp)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSBool
|
namespace js {
|
||||||
DebugFrame_eval(JSContext *cx, uintN argc, Value *vp)
|
|
||||||
|
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);
|
assertSameCompartment(cx, scobj, fp);
|
||||||
THIS_FRAME(cx, vp, "eval", thisobj, 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());
|
Debug *dbg = Debug::fromChildJSObject(&vp[1].toObject());
|
||||||
|
|
||||||
|
// Check the first argument, the eval code string.
|
||||||
if (!vp[2].isString()) {
|
if (!vp[2].isString()) {
|
||||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_EXPECTED_TYPE,
|
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NOT_EXPECTED_TYPE,
|
||||||
"Debug.Frame.eval", "string", InformalValueTypeName(vp[2]));
|
"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);
|
JSLinearString *linearStr = vp[2].toString()->ensureLinear(cx);
|
||||||
if (!linearStr)
|
if (!linearStr)
|
||||||
return false;
|
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());
|
AutoCompartment ac(cx, &fp->scopeChain());
|
||||||
if (!ac.enter())
|
if (!ac.enter())
|
||||||
return false;
|
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;
|
Value rval;
|
||||||
bool ok = JS_EvaluateUCInStackFrame(cx, Jsvalify(fp), linearStr->chars(), linearStr->length(),
|
JS::Anchor<JSString *> anchor(linearStr);
|
||||||
"debugger eval code", 1, Jsvalify(&rval));
|
bool ok = EvaluateInScope(cx, scobj, fp, linearStr->chars(), linearStr->length(),
|
||||||
|
"debugger eval code", 1, &rval);
|
||||||
return dbg->newCompletionValue(ac, ok, rval, vp);
|
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
|
static JSBool
|
||||||
DebugFrame_construct(JSContext *cx, uintN argc, Value *vp)
|
DebugFrame_construct(JSContext *cx, uintN argc, Value *vp)
|
||||||
{
|
{
|
||||||
@ -1315,6 +1409,7 @@ static JSPropertySpec DebugFrame_properties[] = {
|
|||||||
|
|
||||||
static JSFunctionSpec DebugFrame_methods[] = {
|
static JSFunctionSpec DebugFrame_methods[] = {
|
||||||
JS_FN("eval", DebugFrame_eval, 1, 0),
|
JS_FN("eval", DebugFrame_eval, 1, 0),
|
||||||
|
JS_FN("evalWithBindings", DebugFrame_evalWithBindings, 1, 0),
|
||||||
JS_FS_END
|
JS_FS_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -270,6 +270,10 @@ Debug::onThrow(JSContext *cx, js::Value *vp)
|
|||||||
DebugHandleMethod(&Debug::handleThrow));
|
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__ */
|
#endif /* jsdbg_h__ */
|
||||||
|
@ -1683,26 +1683,8 @@ JS_EvaluateUCInStackFrame(JSContext *cx, JSStackFrame *fpArg,
|
|||||||
if (!ac.enter())
|
if (!ac.enter())
|
||||||
return false;
|
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);
|
StackFrame *fp = Valueify(fpArg);
|
||||||
JSScript *script = Compiler::compileScript(cx, scobj, fp, fp->scopeChain().principals(cx),
|
return EvaluateInScope(cx, scobj, fp, chars, length, filename, lineno, Valueify(rval));
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(JSBool)
|
JS_PUBLIC_API(JSBool)
|
||||||
|
@ -904,8 +904,7 @@ Execute(JSContext *cx, JSObject &chain, JSScript *script, StackFrame *prev, uint
|
|||||||
/* Initialize frame and locals. */
|
/* Initialize frame and locals. */
|
||||||
JSObject *initialVarObj;
|
JSObject *initialVarObj;
|
||||||
if (prev) {
|
if (prev) {
|
||||||
JS_ASSERT(chain == prev->scopeChain());
|
frame.fp()->initEvalFrame(cx, script, prev, &chain, flags);
|
||||||
frame.fp()->initEvalFrame(cx, script, prev, flags);
|
|
||||||
|
|
||||||
/* NB: prev may not be in cx->currentSegment. */
|
/* NB: prev may not be in cx->currentSegment. */
|
||||||
initialVarObj = (prev == cx->maybefp())
|
initialVarObj = (prev == cx->maybefp())
|
||||||
|
@ -401,12 +401,19 @@ StackFrame::initCallFrameLatePrologue()
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
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);
|
||||||
JS_ASSERT((flagsArg & ~(EVAL | DEBUGGER)) == 0);
|
JS_ASSERT((flagsArg & ~(EVAL | DEBUGGER)) == 0);
|
||||||
JS_ASSERT(prev->isScriptFrame());
|
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). */
|
/* Copy (callee, thisv). */
|
||||||
Value *dstvp = (Value *)this - 2;
|
Value *dstvp = (Value *)this - 2;
|
||||||
Value *srcvp = prev->hasArgs()
|
Value *srcvp = prev->hasArgs()
|
||||||
@ -427,7 +434,7 @@ StackFrame::initEvalFrame(JSContext *cx, JSScript *script, StackFrame *prev, uin
|
|||||||
exec.script = script;
|
exec.script = script;
|
||||||
}
|
}
|
||||||
|
|
||||||
scopeChain_ = &prev->scopeChain();
|
scopeChain_ = chain;
|
||||||
prev_ = prev;
|
prev_ = prev;
|
||||||
prevpc_ = prev->pc(cx);
|
prevpc_ = prev->pc(cx);
|
||||||
JS_ASSERT(!hasImacropc());
|
JS_ASSERT(!hasImacropc());
|
||||||
|
@ -308,7 +308,7 @@ class StackFrame
|
|||||||
inline void initCallFrameLatePrologue();
|
inline void initCallFrameLatePrologue();
|
||||||
|
|
||||||
/* Used for eval. */
|
/* 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);
|
uint32 flags);
|
||||||
inline void initGlobalFrame(JSScript *script, JSObject &chain, StackFrame *prev,
|
inline void initGlobalFrame(JSScript *script, JSObject &chain, StackFrame *prev,
|
||||||
uint32 flags);
|
uint32 flags);
|
||||||
|
Loading…
Reference in New Issue
Block a user