Commit 506999c3 authored by yangguo's avatar yangguo Committed by Commit bot

[debugger] make strict eval-scope visible to debugging.

R=jgruber@chromium.org,kozyatinskiy@chromium.org
BUG=chromium:590256
LOG=N

Review-Url: https://codereview.chromium.org/1961963002
Cr-Commit-Position: refs/heads/master@{#36195}
parent 8f1e31fe
......@@ -183,7 +183,8 @@ DebugEvaluate::ContextBuilder::ContextBuilder(Isolate* isolate,
context_chain_element.wrapped_context = current_context;
}
context_chain_.Add(context_chain_element);
} else if (scope_type == ScopeIterator::ScopeTypeBlock) {
} else if (scope_type == ScopeIterator::ScopeTypeBlock ||
scope_type == ScopeIterator::ScopeTypeEval) {
Handle<JSObject> materialized = factory->NewJSObjectWithNullProto();
frame_inspector.MaterializeStackLocals(materialized,
it.CurrentScopeInfo());
......
This diff is collapsed.
......@@ -25,6 +25,7 @@ class ScopeIterator {
ScopeTypeCatch,
ScopeTypeBlock,
ScopeTypeScript,
ScopeTypeEval,
ScopeTypeModule
};
......@@ -120,13 +121,13 @@ class ScopeIterator {
MUST_USE_RESULT MaybeHandle<JSObject> MaterializeModuleScope();
Handle<JSObject> MaterializeClosure();
Handle<JSObject> MaterializeCatchScope();
Handle<JSObject> MaterializeBlockScope();
Handle<JSObject> MaterializeInnerScope();
Handle<JSObject> WithContextExtension();
bool SetLocalVariableValue(Handle<String> variable_name,
Handle<Object> new_value);
bool SetBlockVariableValue(Handle<String> variable_name,
Handle<Object> new_value);
bool SetInnerScopeVariableValue(Handle<String> variable_name,
Handle<Object> new_value);
bool SetClosureVariableValue(Handle<String> variable_name,
Handle<Object> new_value);
bool SetScriptVariableValue(Handle<String> variable_name,
......@@ -150,7 +151,7 @@ class ScopeIterator {
void CopyContextLocalsToScopeObject(Handle<ScopeInfo> scope_info,
Handle<Context> context,
Handle<JSObject> scope_object);
bool CopyContextExtensionToScopeObject(Handle<JSObject> extension,
void CopyContextExtensionToScopeObject(Handle<Context> context,
Handle<JSObject> scope_object,
KeyCollectionType type);
......
......@@ -256,13 +256,15 @@ PropertyAttribute.DontDelete = DONT_DELETE;
// A copy of the scope types from runtime-debug.cc.
// NOTE: these constants should be backward-compatible, so
// add new ones to the end of this list.
var ScopeType = { Global: 0,
Local: 1,
With: 2,
var ScopeType = { Global: 0,
Local: 1,
With: 2,
Closure: 3,
Catch: 4,
Block: 5,
Script: 6 };
Catch: 4,
Block: 5,
Script: 6,
Eval: 7,
};
/**
* Base class for all mirror objects.
......
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --expose-debug-as debug --no-always-opt
// Test that the (strict) eval scope is visible to the debugger.
var Debug = debug.Debug;
var exception = null;
var delegate = null;
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
delegate(exec_state);
} catch (e) {
exception = e;
}
}
Debug.setListener(listener);
// Current function is the top-level eval.
// We can access stack- and context-allocated values in the eval-scope.
delegate = function(exec_state) {
assertEquals([ debug.ScopeType.Eval,
debug.ScopeType.Script,
debug.ScopeType.Global ],
exec_state.frame(0).allScopes().map(s => s.scopeType()));
var scope = exec_state.frame(0).scope(0);
assertEquals(1, scope.scopeObject().property("a").value().value());
assertEquals(1, exec_state.frame(0).evaluate("a").value());
scope.setVariableValue("a", 2);
assertEquals(2, exec_state.frame(0).evaluate("a++").value());
}
eval("'use strict'; \n" +
"var a = 1; \n" +
"debugger; \n" +
"assertEquals(3, a);\n");
eval("'use strict'; \n" +
"var a = 1; \n" +
"(x=>a); \n" + // Force context-allocation.
"debugger; \n" +
"assertEquals(3, a);\n");
// Current function is an inner function.
// We cannot access stack-allocated values in the eval-scope.
delegate = function(exec_state) {
assertEquals([ debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global ],
exec_state.frame(0).allScopes().map(s => s.scopeType()));
assertEquals([ debug.ScopeType.Eval,
debug.ScopeType.Script,
debug.ScopeType.Global ],
exec_state.frame(1).allScopes().map(s => s.scopeType()));
var scope = exec_state.frame(0).scope(0);
assertThrows(() => exec_state.frame(0).evaluate("a"), ReferenceError);
assertTrue(scope.scopeObject().property("a").isUndefined());
}
eval("'use strict'; \n" +
"var a = 1; \n" +
"(() => {debugger})()\n");
// Current function is an escaped inner function.
delegate = function(exec_state) {
assertEquals([ debug.ScopeType.Local,
debug.ScopeType.Script,
debug.ScopeType.Global ],
exec_state.frame(0).allScopes().map(s => s.scopeType()));
assertEquals([ debug.ScopeType.Script,
debug.ScopeType.Global ],
exec_state.frame(1).allScopes().map(s => s.scopeType()));
var scope = exec_state.frame(0).scope(0);
assertThrows(() => exec_state.frame(0).evaluate("a"), ReferenceError);
assertTrue(scope.scopeObject().property("a").isUndefined());
}
var f = eval("'use strict'; \n" +
"var a = 1; \n" +
"() => {debugger}\n");
f();
// Current function is an inner function.
// We can access context-allocated values in the eval-scope.
delegate = function(exec_state) {
assertEquals([ debug.ScopeType.Local,
debug.ScopeType.Closure,
debug.ScopeType.Script,
debug.ScopeType.Global ],
exec_state.frame(0).allScopes().map(s => s.scopeType()));
assertEquals([ debug.ScopeType.Eval,
debug.ScopeType.Script,
debug.ScopeType.Global ],
exec_state.frame(1).allScopes().map(s => s.scopeType()));
var scope = exec_state.frame(1).scope(0);
assertEquals(1, scope.scopeObject().property("a").value().value());
assertEquals(1, exec_state.frame(1).evaluate("a").value());
assertEquals(1, exec_state.frame(0).evaluate("a").value());
scope.setVariableValue("a", 2);
assertEquals(2, exec_state.frame(0).evaluate("a++").value());
assertEquals(3, exec_state.frame(1).evaluate("a++").value());
}
eval("'use strict'; \n" +
"var a = 1; \n" +
"(() => { a; \n" + // Force context-allocation.
" debugger; \n" +
" assertEquals(4, a);\n" +
" })(); \n"
);
// Current function is an escaped inner function.
// We can access context-allocated values in the eval-scope.
delegate = function(exec_state) {
assertEquals([ debug.ScopeType.Local,
debug.ScopeType.Closure,
debug.ScopeType.Script,
debug.ScopeType.Global ],
exec_state.frame(0).allScopes().map(s => s.scopeType()));
assertEquals([ debug.ScopeType.Script,
debug.ScopeType.Global ],
exec_state.frame(1).allScopes().map(s => s.scopeType()));
var scope = exec_state.frame(0).scope(1);
assertEquals(1, scope.scopeObject().property("a").value().value());
assertEquals(1, exec_state.frame(0).evaluate("a").value());
scope.setVariableValue("a", 2);
assertEquals(2, exec_state.frame(0).evaluate("a++").value());
}
var g = eval("'use strict'; \n" +
"var a = 1; \n" +
"() => { a; \n" +
" debugger; \n" +
" assertEquals(3, a);\n" +
" } \n");
g();
Debug.setListener(null);
assertNull(exception);
......@@ -34,7 +34,7 @@ function listener(event, exec_state, event_data, data) {
exec_state.frame(0).evaluate("debugger;");
} else {
checkScopes(exec_state.frame(0).allScopes(),
[ ScopeType.With, ScopeType.Closure,
[ ScopeType.Eval, ScopeType.With, ScopeType.Closure,
ScopeType.Script, ScopeType.Global ]);
}
} catch (e) {
......
......@@ -42,14 +42,7 @@ function CheckScope(scope_mirror, scope_expectations, expected_scope_type) {
}
}
// A copy of the scope types from debug/mirrors.js.
var ScopeType = { Global: 0,
Local: 1,
With: 2,
Closure: 3,
Catch: 4,
Block: 5,
Script: 6};
var ScopeType = debug.ScopeType;
var f1 = (function F1(x) {
function F2(y) {
......
......@@ -23,17 +23,17 @@ function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
var frame = exec_state.frame(0);
var top_scope = frame.scope(0);
assertTrue(top_scope.scopeObject().propertyNames().includes('y'));
assertEquals(7, top_scope.scopeObject().property('y').value().value());
var block_scope;
if (break_count++ == 0) {
// Inside eval.
assertEquals([ debug.ScopeType.Block,
assertEquals([ debug.ScopeType.Eval,
debug.ScopeType.Block,
debug.ScopeType.Closure,
debug.ScopeType.Script,
debug.ScopeType.Global ],
frame.allScopes().map(s => s.scopeType()));
exec_state.prepareStep(Debug.StepAction.StepOut);
block_scope = frame.scope(1);
} else {
// Outside of eval.
assertEquals([ debug.ScopeType.Block,
......@@ -41,8 +41,12 @@ function listener(event, exec_state, event_data, data) {
debug.ScopeType.Script,
debug.ScopeType.Global ],
frame.allScopes().map(s => s.scopeType()));
block_scope = frame.scope(0);
}
assertTrue(block_scope.scopeObject().propertyNames().includes('y'));
assertEquals(7, block_scope.scopeObject().property('y').value().value());
} catch (e) {
print(e);
exception = e;
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment