blob: d1e9d6e5bf8d9952b730ef9655aef34c28e31d52 [file] [log] [blame]
// 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.
import 'dart:async';
import 'dart:collection';
import 'package:stack_trace/stack_trace.dart';
import 'code.dart';
import 'error.dart';
import 'exceptions.dart';
import 'function.dart';
import 'instance.dart';
import 'scope.dart';
import 'source_location.dart';
import 'utils.dart';
VMFrame newVMFrame(Scope scope, Map json) {
if (json == null) return null;
assert(json["type"] == "Frame");
return new VMFrame._(scope, json);
}
/// An active stack frame.
class VMFrame {
final Scope _scope;
/// The index of the frame in [VMStack.frames].
///
/// The lower the index, the closer the frame to the point of execution. The
/// actual point of execution has index 0.
final int index;
/// The function containing the frame.
final VMFunctionRef function;
/// The frame's code.
final VMCodeRef code;
/// The location of the frame in Dart source.
final VMSourceLocation location;
/// The local variables in the current frame, indexed by name.
final Map<String, VMBoundVariable> variables;
VMFrame._(Scope scope, Map json)
: _scope = scope,
index = json["index"],
function = newVMFunctionRef(scope, json["function"]),
code = newVMCodeRef(scope, json["code"]),
location = newVMSourceLocation(scope, json["location"]),
variables = new UnmodifiableMapView(new Map.fromIterable(json["vars"],
key: (variable) => variable["name"],
value: (variable) => new VMBoundVariable._(scope, variable)));
/// Evaluates [expression] in the context of this frame.
///
/// Throws a [VMErrorException] if evaluating the expression throws an error.
/// Throws a [VMSentinelException] if this frame has expired.
Future<VMInstanceRef> evaluate(String expression) async {
var result = await _scope.sendRequest("evaluateInFrame", {
"frameIndex": index,
"expression": expression
});
switch (result["type"]) {
case "@Error": throw new VMErrorException(newVMErrorRef(_scope, result));
case "@Instance": return newVMInstanceRef(_scope, result);
default:
throw new StateError('Unexpected Object type "${result["type"]}".');
}
}
/// Loads a `stack_trace` [Frame] that corresponds to this frame.
Future<Frame> getFrame() async => frameToFrame(this);
String toString() => "#$index in $function";
}
/// A local variable bound to a particular value in a [VMFrame].
class VMBoundVariable {
/// The name of the variable.
final String name;
/// The value of the variable.
///
/// If this variable is uninitialized, this will be
/// [VMSentinel.notInitialized]. If it's currently being initialized, it will
/// be [VMSentinel.beingInitialized]. If it's been optimized out, it will be
/// [VMSentinel.optimizedOut]. Otherwise, it will be a [VMInstanceRef].
final value;
VMBoundVariable._(Scope scope, Map json)
: name = json["name"],
value = newVMInstanceRefOrSentinel(scope, json["value"]);
String toString() => "var $name = $value";
}