mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 10:48:25 +00:00
[kernel] Fix vm crash when trying to break on default constructor
Writing "break Foo" in observatory with a file including ``` class Foo { } ``` would crash them VM. This CL introduces a test that reproduces it and fixes the issue. Bug: Change-Id: I24780d9204117ade19a0cb590c45aa31b7c04f7e Reviewed-on: https://dart-review.googlesource.com/30445 Commit-Queue: Jens Johansen <jensj@google.com> Reviewed-by: Vyacheslav Egorov <vegorov@google.com> Reviewed-by: Kevin Millikin <kmillikin@google.com>
This commit is contained in:
parent
ac068b3cb4
commit
4e162c5318
|
@ -0,0 +1,76 @@
|
|||
// Copyright (c) 2017, 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.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:observatory/debugger.dart';
|
||||
import 'package:observatory/service_io.dart';
|
||||
import 'package:unittest/unittest.dart';
|
||||
import 'package:observatory/service.dart' as S;
|
||||
|
||||
import 'service_test_common.dart';
|
||||
import 'test_helper.dart';
|
||||
|
||||
class Foo {}
|
||||
|
||||
code() {
|
||||
new Foo();
|
||||
}
|
||||
|
||||
class TestDebugger extends Debugger {
|
||||
TestDebugger(this.isolate, this.stack);
|
||||
|
||||
VM get vm => isolate.vm;
|
||||
Isolate isolate;
|
||||
ServiceMap stack;
|
||||
int currentFrame = 0;
|
||||
}
|
||||
|
||||
Future<Debugger> initDebugger(Isolate isolate) {
|
||||
return isolate.getStack().then((stack) {
|
||||
return new TestDebugger(isolate, stack);
|
||||
});
|
||||
}
|
||||
|
||||
List<String> stops = [];
|
||||
|
||||
var tests = [
|
||||
hasPausedAtStart,
|
||||
// Load the isolate's libraries
|
||||
(Isolate isolate) async {
|
||||
for (var lib in isolate.libraries) {
|
||||
await lib.load();
|
||||
}
|
||||
},
|
||||
|
||||
(Isolate isolate) async {
|
||||
var debugger = await initDebugger(isolate);
|
||||
var loc = await DebuggerLocation.parse(debugger, 'Foo');
|
||||
|
||||
if (loc.valid) {
|
||||
if (loc.function != null) {
|
||||
try {
|
||||
await debugger.isolate.addBreakpointAtEntry(loc.function);
|
||||
} on S.ServerRpcException catch (e) {
|
||||
if (e.code == S.ServerRpcException.kCannotAddBreakpoint) {
|
||||
// Expected
|
||||
} else {
|
||||
fail("Got unexpected error $e");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fail("Expected to find function");
|
||||
}
|
||||
} else {
|
||||
fail("Expected to find function");
|
||||
}
|
||||
|
||||
isolate.resume();
|
||||
},
|
||||
];
|
||||
|
||||
main(args) {
|
||||
runIsolateTestsSynchronous(args, tests,
|
||||
testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright (c) 2017, 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.
|
||||
|
||||
import 'test_helper.dart';
|
||||
import 'service_test_common.dart';
|
||||
|
||||
const int LINE = 17;
|
||||
const String file = "step_through_constructor_test.dart";
|
||||
|
||||
code() {
|
||||
new Foo();
|
||||
}
|
||||
|
||||
class Foo {
|
||||
Foo() {
|
||||
print("Hello from Foo!");
|
||||
}
|
||||
}
|
||||
|
||||
List<String> stops = [];
|
||||
List<String> expected = [
|
||||
"$file:${LINE+0}:5", // on 'print'
|
||||
"$file:${LINE+1}:3", // on ending '}'
|
||||
];
|
||||
|
||||
var tests = [
|
||||
hasPausedAtStart,
|
||||
setBreakpointAtLine(LINE),
|
||||
runStepIntoThroughProgramRecordingStops(stops),
|
||||
checkRecordedStops(stops, expected,
|
||||
debugPrint: true, debugPrintFile: file, debugPrintLine: LINE)
|
||||
];
|
||||
|
||||
main(args) {
|
||||
runIsolateTestsSynchronous(args, tests,
|
||||
testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
|
||||
}
|
|
@ -322,6 +322,7 @@ class ConstructorHelper {
|
|||
enum Flag {
|
||||
kConst = 1 << 0,
|
||||
kExternal = 1 << 1,
|
||||
kSyntheticDefault = 1 << 2,
|
||||
};
|
||||
|
||||
explicit ConstructorHelper(StreamingFlowGraphBuilder* builder) {
|
||||
|
@ -340,6 +341,7 @@ class ConstructorHelper {
|
|||
|
||||
bool IsExternal() { return (flags_ & kExternal) != 0; }
|
||||
bool IsConst() { return (flags_ & kConst) != 0; }
|
||||
bool IsSyntheticDefault() { return (flags_ & kSyntheticDefault) != 0; }
|
||||
|
||||
NameIndex canonical_name_;
|
||||
TokenPosition position_;
|
||||
|
|
|
@ -2827,6 +2827,10 @@ Breakpoint* Debugger::SetBreakpointAtEntry(const Function& target_function,
|
|||
BreakpointLocation* bpt_location = SetBreakpoint(
|
||||
script, target_function.token_pos(), target_function.end_token_pos(), -1,
|
||||
-1 /* no requested line/col */);
|
||||
if (bpt_location == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (single_shot) {
|
||||
return bpt_location->AddSingleShot(this);
|
||||
} else {
|
||||
|
|
|
@ -986,6 +986,10 @@ void KernelLoader::FinishClassLoading(const Class& klass,
|
|||
true, // is_method
|
||||
false, // is_closure
|
||||
&function_node_helper);
|
||||
if (constructor_helper.IsSyntheticDefault()) {
|
||||
function.set_is_debuggable(false);
|
||||
}
|
||||
|
||||
function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kEnd);
|
||||
constructor_helper.SetJustRead(ConstructorHelper::kFunction);
|
||||
constructor_helper.ReadUntilExcluding(ConstructorHelper::kEnd);
|
||||
|
|
Loading…
Reference in a new issue