| Index: pkg/dartino_compiler/lib/vm_context.dart
|
| diff --git a/pkg/dartino_compiler/lib/vm_context.dart b/pkg/dartino_compiler/lib/vm_context.dart
|
| index 4945625c25137d9e9c86ba16be7187124f911d90..42e6f86f91a249e9933ae184b37d260334fa69db 100644
|
| --- a/pkg/dartino_compiler/lib/vm_context.dart
|
| +++ b/pkg/dartino_compiler/lib/vm_context.dart
|
| @@ -63,8 +63,7 @@ import 'program_info.dart' show
|
| ProgramInfoJson;
|
|
|
| import 'package:compiler/src/elements/elements.dart' show
|
| - ClassElement,
|
| - FieldElement;
|
| + ClassElement;
|
|
|
| class SessionCommandTransformerBuilder
|
| extends CommandTransformerBuilder<Pair<int, ByteData>> {
|
| @@ -856,15 +855,7 @@ class DartinoVmContext {
|
| assert(vmState == VmState.terminating);
|
| if (debugState.currentUncaughtException == null) {
|
| await sendCommand(const ProcessUncaughtExceptionRequest());
|
| - VmCommand response = await readNextCommand();
|
| - if (response is DartValue) {
|
| - debugState.currentUncaughtException = new RemoteValue(response);
|
| - } else {
|
| - assert(response is InstanceStructure);
|
| - List<DartValue> fields = await readInstanceStructureFields(response);
|
| - debugState.currentUncaughtException =
|
| - new RemoteInstance(response, fields);
|
| - }
|
| + debugState.currentUncaughtException = await readStructuredObject();
|
| }
|
| return debugState.currentUncaughtException;
|
| }
|
| @@ -951,6 +942,16 @@ class DartinoVmContext {
|
| return '$sb';
|
| }
|
|
|
| + String arrayStructureToString(List<DartValue> items) {
|
| + StringBuffer sb = new StringBuffer();
|
| + sb.writeln("Array with length ${items.length} [");
|
| + for (int i = 0; i < items.length; i++) {
|
| + sb.writeln(" $i = ${dartValueToString(items[i])}");
|
| + }
|
| + sb.write("]");
|
| + return '$sb';
|
| + }
|
| +
|
| String noSuchMethodErrorToString(List<DartValue> nsmFields) {
|
| assert(nsmFields.length == 3);
|
| ClassValue receiverClass = nsmFields[1];
|
| @@ -984,13 +985,25 @@ class DartinoVmContext {
|
| }
|
| }
|
|
|
| - Future<List<DartValue>> readInstanceStructureFields(
|
| - InstanceStructure structure) async {
|
| - List<DartValue> fields = <DartValue>[];
|
| - for (int i = 0; i < structure.fields; i++) {
|
| - fields.add(await readNextCommand());
|
| + Future<RemoteObject> readStructuredObject() async {
|
| + VmCommand response = await readNextCommand();
|
| + if (response is DartValue) {
|
| + return new RemoteValue(response);
|
| + } else if (response is InstanceStructure) {
|
| + List<DartValue> fields = new List<DartValue>();
|
| + for (int i = 0; i < response.fields; i++) {
|
| + fields.add(await readNextCommand());
|
| + }
|
| + return new RemoteInstance(response, fields);
|
| + } else if (response is ArrayStructure) {
|
| + List<DartValue> values = new List<DartValue>();
|
| + for (int i = 0; i < response.length; i++) {
|
| + values.add(await readNextCommand());
|
| + }
|
| + return new RemoteArray(response, values);
|
| + } else {
|
| + return new RemoteErrorObject("Failed reading structured object.");
|
| }
|
| - return fields;
|
| }
|
|
|
| String exceptionToString(RemoteObject exception) {
|
| @@ -1023,6 +1036,7 @@ class DartinoVmContext {
|
| assert(isSpawned);
|
| assert(names.isNotEmpty);
|
| String localName = names.first;
|
| + int frame = debugState.currentFrame;
|
| LocalValue local = await lookupValue(localName);
|
| if (local == null) {
|
| return new RemoteErrorObject("No local '$localName' in scope.");
|
| @@ -1031,8 +1045,10 @@ class DartinoVmContext {
|
| List<int> fieldIndices = new List<int>();
|
| List<String> namesTillHere = <String>[localName];
|
| for (String fieldName in names.skip(1)) {
|
| - RemoteValue remoteValue =
|
| - await processLocal(local, fieldAccesses: fieldIndices);
|
| + RemoteValue remoteValue = await processLocal(
|
| + frame,
|
| + local.slot,
|
| + fieldAccesses: fieldIndices);
|
| DartValue value = remoteValue.value;
|
| if (value is Instance) {
|
| ClassElement classElement =
|
| @@ -1044,6 +1060,14 @@ class DartinoVmContext {
|
| " that does not have a field named '${fieldName}'.");
|
| }
|
| fieldIndices.add(fieldIndex);
|
| + } else if (value is Array) {
|
| + int index = int.parse(fieldName, onError: (_) => -1);
|
| + if (index < 0 || index > value.length) {
|
| + return new RemoteErrorObject(
|
| + "${namesTillHere.join(".")}' is an array with length "
|
| + "${value.length}. It cannot be indexed with ${fieldName}");
|
| + }
|
| + fieldIndices.add(index);
|
| } else {
|
| return new RemoteErrorObject("'${namesTillHere.join(".")}' "
|
| "is a primitive value '${dartValueToString(value)}' "
|
| @@ -1052,9 +1076,10 @@ class DartinoVmContext {
|
| namesTillHere.add(fieldName);
|
| }
|
| if (getStructure) {
|
| - return await processLocalStructure(local, fieldAccesses: fieldIndices);
|
| + return await processLocalStructure(
|
| + frame, local.slot, fieldAccesses: fieldIndices);
|
| } else {
|
| - return await processLocal(local, fieldAccesses: fieldIndices);
|
| + return await processLocal(frame, local.slot, fieldAccesses: fieldIndices);
|
| }
|
| }
|
|
|
| @@ -1074,7 +1099,8 @@ class DartinoVmContext {
|
| for (ScopeInfo current = info;
|
| current != ScopeInfo.sentinel;
|
| current = current.previous) {
|
| - variables.add(await processLocal(current.local, name: current.name));
|
| + variables.add(await processLocal(
|
| + debugState.currentFrame, current.local.slot, name: current.name));
|
| }
|
| return variables;
|
| }
|
| @@ -1086,31 +1112,25 @@ class DartinoVmContext {
|
| }
|
|
|
| Future<RemoteValue> processLocal(
|
| - LocalValue local,
|
| + int frameNumber,
|
| + int localSlot,
|
| {String name,
|
| List<int> fieldAccesses: const <int>[]}) async {
|
| - var actualFrameNumber = debugState.actualCurrentFrameNumber;
|
| VmCommand response = await runCommand(
|
| - new ProcessInstance(actualFrameNumber, local.slot, fieldAccesses));
|
| + new ProcessInstance(frameNumber, localSlot, fieldAccesses));
|
| assert(response is DartValue);
|
| return new RemoteValue(response, name: name);
|
| }
|
|
|
| Future<RemoteObject> processLocalStructure(
|
| - LocalValue local,
|
| + int frameNumber,
|
| + int localSlot,
|
| {String name,
|
| List<int> fieldAccesses: const <int>[]}) async {
|
| - var frameNumber = debugState.actualCurrentFrameNumber;
|
| + frameNumber ??= debugState.actualCurrentFrameNumber;
|
| await sendCommand(
|
| - new ProcessInstanceStructure(frameNumber, local.slot, fieldAccesses));
|
| - VmCommand response = await readNextCommand();
|
| - if (response is DartValue) {
|
| - return new RemoteValue(response);
|
| - } else {
|
| - assert(response is InstanceStructure);
|
| - List<DartValue> fields = await readInstanceStructureFields(response);
|
| - return new RemoteInstance(response, fields);
|
| - }
|
| + new ProcessInstanceStructure(frameNumber, localSlot, fieldAccesses));
|
| + return await readStructuredObject();
|
| }
|
|
|
| String remoteObjectToString(RemoteObject object) {
|
| @@ -1119,6 +1139,8 @@ class DartinoVmContext {
|
| message = dartValueToString(object.value);
|
| } else if (object is RemoteInstance) {
|
| message = instanceStructureToString(object.instance, object.fields);
|
| + } else if (object is RemoteArray) {
|
| + message = arrayStructureToString(object.values);
|
| } else {
|
| throw new UnimplementedError();
|
| }
|
|
|