mirror of
https://github.com/dart-lang/sdk
synced 2024-11-05 18:22:09 +00:00
VM: Fix issue with local variable values reported by the debugger.
I added a function to test if a variable is visible or not to the debugger tests. BUG=dartbug.com/22353 TEST=standalone/debugger/local_variables_test R=hausner@google.com Review URL: https://codereview.chromium.org//933253003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@43850 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
parent
6666c2502b
commit
aefdc04fa8
5 changed files with 110 additions and 13 deletions
|
@ -22,7 +22,7 @@ void DynamicAssertionHelper::Fail(const char* format, ...) {
|
|||
|
||||
va_list arguments;
|
||||
va_start(arguments, format);
|
||||
char buffer[2 * KB];
|
||||
char buffer[4 * KB];
|
||||
vsnprintf(buffer, sizeof(buffer), format, arguments);
|
||||
va_end(arguments);
|
||||
stream << buffer << std::endl;
|
||||
|
|
|
@ -6677,16 +6677,18 @@ AstNode* Parser::ParseVariableDeclaration(const AbstractType& type,
|
|||
ASSERT(IsIdentifier());
|
||||
const intptr_t ident_pos = TokenPos();
|
||||
const String& ident = *CurrentLiteral();
|
||||
LocalVariable* variable = new(Z) LocalVariable(
|
||||
ident_pos, ident, type);
|
||||
ConsumeToken(); // Variable identifier.
|
||||
AstNode* initialization = NULL;
|
||||
LocalVariable* variable = NULL;
|
||||
if (CurrentToken() == Token::kASSIGN) {
|
||||
// Variable initialization.
|
||||
const intptr_t assign_pos = TokenPos();
|
||||
ConsumeToken();
|
||||
AstNode* expr = ParseAwaitableExpr(
|
||||
is_const, kConsumeCascades, await_preamble);
|
||||
const intptr_t expr_end_pos = TokenPos();
|
||||
variable = new(Z) LocalVariable(
|
||||
expr_end_pos, ident, type);
|
||||
initialization = new(Z) StoreLocalNode(
|
||||
assign_pos, variable, expr);
|
||||
if (is_const) {
|
||||
|
@ -6698,6 +6700,8 @@ AstNode* Parser::ParseVariableDeclaration(const AbstractType& type,
|
|||
"missing initialization of 'final' or 'const' variable");
|
||||
} else {
|
||||
// Initialize variable with null.
|
||||
variable = new(Z) LocalVariable(
|
||||
ident_pos, ident, type);
|
||||
AstNode* null_expr = new(Z) LiteralNode(ident_pos, Instance::ZoneHandle(Z));
|
||||
initialization = new(Z) StoreLocalNode(
|
||||
ident_pos, variable, null_expr);
|
||||
|
@ -6705,7 +6709,7 @@ AstNode* Parser::ParseVariableDeclaration(const AbstractType& type,
|
|||
|
||||
ASSERT(current_block_ != NULL);
|
||||
const intptr_t previous_pos =
|
||||
current_block_->scope->PreviousReferencePos(ident);
|
||||
current_block_->scope->PreviousReferencePos(ident);
|
||||
if (previous_pos >= 0) {
|
||||
ASSERT(!script_.IsNull());
|
||||
if (previous_pos > ident_pos) {
|
||||
|
|
|
@ -280,7 +280,7 @@ TEST_CASE(Parser_AllocateVariables_CapturedVar) {
|
|||
" 0 ContextLevel level=1 scope=1 begin=2 end=37\n"
|
||||
" 1 CurrentCtx scope=0 begin=0 end=0"
|
||||
" name=:current_context_var\n"
|
||||
" 2 ContextVar level=1 begin=7 end=37 name=value\n"
|
||||
" 2 ContextVar level=1 begin=10 end=37 name=value\n"
|
||||
" 3 StackVar scope=2 begin=12 end=37 name=f\n",
|
||||
CaptureVarsAtLine(lib, "main", 4));
|
||||
}
|
||||
|
@ -321,7 +321,7 @@ TEST_CASE(Parser_AllocateVariables_NestedCapturedVar) {
|
|||
" 0 ContextLevel level=1 scope=1 begin=8 end=38\n"
|
||||
" 1 CurrentCtx scope=0 begin=0 end=0"
|
||||
" name=:current_context_var\n"
|
||||
" 2 ContextVar level=1 begin=13 end=38 name=value\n"
|
||||
" 2 ContextVar level=1 begin=16 end=38 name=value\n"
|
||||
" 3 StackVar scope=2 begin=18 end=38 name=c\n"
|
||||
|
||||
// Closure call saves current context.
|
||||
|
@ -380,7 +380,7 @@ TEST_CASE(Parser_AllocateVariables_TwoChains) {
|
|||
" 0 ContextLevel level=1 scope=1 begin=20 end=50\n"
|
||||
" 1 CurrentCtx scope=0 begin=0 end=0"
|
||||
" name=:current_context_var\n"
|
||||
" 2 ContextVar level=1 begin=25 end=50 name=value2\n"
|
||||
" 2 ContextVar level=1 begin=28 end=50 name=value2\n"
|
||||
" 3 StackVar scope=2 begin=30 end=50 name=bb\n"
|
||||
|
||||
// Closure call saves current context.
|
||||
|
@ -407,7 +407,7 @@ TEST_CASE(Parser_AllocateVariables_TwoChains) {
|
|||
" 0 ContextLevel level=1 scope=1 begin=2 end=68\n"
|
||||
" 1 CurrentCtx scope=0 begin=0 end=0"
|
||||
" name=:current_context_var\n"
|
||||
" 2 ContextVar level=1 begin=7 end=68 name=value1\n"
|
||||
" 2 ContextVar level=1 begin=10 end=68 name=value1\n"
|
||||
" 3 StackVar scope=2 begin=12 end=68 name=b\n",
|
||||
CaptureVarsAtLine(lib, "a", 7));
|
||||
}
|
||||
|
@ -464,7 +464,7 @@ TEST_CASE(Parser_AllocateVariables_Issue7681) {
|
|||
"doIt\n"
|
||||
" 0 CurrentCtx scope=0 begin=0 end=0"
|
||||
" name=:current_context_var\n"
|
||||
" 1 StackVar scope=2 begin=29 end=77 name=x\n",
|
||||
" 1 StackVar scope=2 begin=35 end=77 name=x\n",
|
||||
CaptureVarsAtLine(lib, "doIt", 12));
|
||||
}
|
||||
|
||||
|
@ -505,9 +505,9 @@ TEST_CASE(Parser_AllocateVariables_CaptureLoopVar) {
|
|||
"outer\n"
|
||||
" 0 CurrentCtx scope=0 begin=0 end=0"
|
||||
" name=:current_context_var\n"
|
||||
" 1 StackVar scope=3 begin=9 end=50 name=i\n"
|
||||
" 1 StackVar scope=3 begin=12 end=50 name=i\n"
|
||||
" 2 ContextLevel level=1 scope=4 begin=20 end=50\n"
|
||||
" 3 ContextVar level=1 begin=23 end=50 name=value\n"
|
||||
" 3 ContextVar level=1 begin=28 end=50 name=value\n"
|
||||
" 4 StackVar scope=4 begin=30 end=50 name=inner\n",
|
||||
CaptureVarsAtLine(lib, "outer", 5));
|
||||
}
|
||||
|
@ -548,7 +548,7 @@ TEST_CASE(Parser_AllocateVariables_MiddleChain) {
|
|||
" name=:current_context_var\n"
|
||||
" 2 StackVar scope=2 begin=46 end=68 name=c\n"
|
||||
" 3 ContextLevel level=1 scope=3 begin=18 end=46\n"
|
||||
" 4 ContextVar level=1 begin=19 end=46 name=i\n"
|
||||
" 4 ContextVar level=1 begin=22 end=46 name=i\n"
|
||||
" 5 StackVar scope=4 begin=32 end=46 name=d\n"
|
||||
|
||||
"_FunctionImpl.call\n"
|
||||
|
@ -560,7 +560,7 @@ TEST_CASE(Parser_AllocateVariables_MiddleChain) {
|
|||
" 0 ContextLevel level=1 scope=1 begin=1 end=76\n"
|
||||
" 1 CurrentCtx scope=0 begin=0 end=0"
|
||||
" name=:current_context_var\n"
|
||||
" 2 ContextVar level=1 begin=6 end=76 name=x\n"
|
||||
" 2 ContextVar level=1 begin=9 end=76 name=x\n"
|
||||
" 3 StackVar scope=2 begin=11 end=76 name=b\n",
|
||||
CaptureVarsAtLine(lib, "a", 10));
|
||||
}
|
||||
|
|
|
@ -338,6 +338,43 @@ MatchLocals(Map localValues) {
|
|||
}
|
||||
|
||||
|
||||
// Used to check if local variables are visible.
|
||||
class AssertLocalsNotVisibleMatcher extends Command {
|
||||
List<String> locals;
|
||||
int frame_index;
|
||||
|
||||
AssertLocalsNotVisibleMatcher(this.locals, this.frame_index) {
|
||||
template = {"id": 0, "command": "getStackTrace", "params": {"isolateId": 0}};
|
||||
}
|
||||
|
||||
void matchResponse(Debugger debugger) {
|
||||
super.matchResponse(debugger);
|
||||
|
||||
List frames = getJsonValue(debugger.currentMessage, "result:callFrames");
|
||||
assert(frames != null);
|
||||
|
||||
String functionName = frames[frame_index]['functionName'];
|
||||
List localsList = frames[frame_index]['locals'];
|
||||
Map reportedLocals = {};
|
||||
localsList.forEach((local) => reportedLocals[local['name']] = local['value']);
|
||||
for (String key in locals) {
|
||||
if (reportedLocals[key] != null) {
|
||||
debugger.error("Error in $functionName(): local variable $key not "
|
||||
"expected in scope (reported value "
|
||||
"${reportedLocals[key]['text']})");
|
||||
return;
|
||||
}
|
||||
}
|
||||
print("Matched locals $locals");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AssertLocalsNotVisible(List<String> locals, [int frame_index = 0]) {
|
||||
return new AssertLocalsNotVisibleMatcher(locals, frame_index);
|
||||
}
|
||||
|
||||
|
||||
class EventMatcher {
|
||||
String eventName;
|
||||
Map params;
|
||||
|
|
56
tests/standalone/debugger/local_variables_test.dart
Normal file
56
tests/standalone/debugger/local_variables_test.dart
Normal file
|
@ -0,0 +1,56 @@
|
|||
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
// This test forks a second vm process that runs this dart script as
|
||||
// a debug target.
|
||||
// Run this test with option --wire to see the json messages sent
|
||||
// between the processes.
|
||||
// Run this test with option --verbose to see the stdout and stderr output
|
||||
// of the debug target process.
|
||||
|
||||
import "debug_lib.dart";
|
||||
|
||||
foo() {
|
||||
var y; // Breakpoint
|
||||
return 123;
|
||||
}
|
||||
|
||||
test() {
|
||||
if (true) {
|
||||
var temp = 777;
|
||||
}
|
||||
if (true) {
|
||||
var a = foo(); // Breakpoint
|
||||
if (true) {
|
||||
var s = 456;
|
||||
print(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
main(List<String> arguments) {
|
||||
if (RunScript(testScript, arguments)) return;
|
||||
print("Hello from debuggee");
|
||||
test();
|
||||
print("Hello again");
|
||||
}
|
||||
|
||||
|
||||
// Expected debugger events and commands.
|
||||
var testScript = [
|
||||
MatchFrame(0, "main"), // Top frame in trace is function "main".
|
||||
Step(),
|
||||
MatchFrame(0, "main"), // Should still be in "main".
|
||||
SetBreakpoint(15), // Set breakpoint in function foo.
|
||||
SetBreakpoint(24), // Set breakpoint in function test.
|
||||
Resume(),
|
||||
MatchFrames(["test", "main"]),
|
||||
AssertLocalsNotVisible(["a"]), // Here, a is not in scope yet.
|
||||
Resume(),
|
||||
MatchFrames(["foo", "test", "main"]),
|
||||
AssertLocalsNotVisible(["a"], 1), // In the caller, a is not in scope.
|
||||
Step(),
|
||||
MatchLocals({"y": "null"}), // Expect y initialized to null.
|
||||
Resume(),
|
||||
];
|
Loading…
Reference in a new issue