mirror of
https://github.com/dart-lang/sdk
synced 2024-09-18 21:21:18 +00:00
587e6308bf
When evaluating an expressino at a breakpoint that's inside a closure, the closure may refer to anything it closes over. That includes the `this` from an enclosing method. So depending on whether a closure's parent chain is an instance method or a static method, the expression evaluation function is going to be an instance method or a static method. => We walk up the parent chain to determine the correct enclosing class. => This avoids making a Type object with a cid from a top-level class (see [0]) Handling this correctly will now try to get the `this` when invoking an eval function that has an enclosing instance method. Though we may often have "<optimized out>" the `this` (e.g. due to not capturing it in closure context chain). => We still allow running the expression evaluation function in this case, but only if the expression being evaluated doesn't access `this`. A similar issue occurs when trying to use variables in the eval expression that the closure didn't capture. This results in a confusing CFE compile-time error. This is a separate issue and tracked in [1]. => We update the test to distinuish the cases that this CL makes passing and those that are failing due to [1]. Fixes [0] https://github.com/dart-lang/sdk/issues/53061 See also [1] https://github.com/dart-lang/sdk/issues/53087 TEST=Fixes part of service/evaluate_activation_test failures Change-Id: I3bb24e7338c7b2f12d5340311d944cb59a455641 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/317540 Reviewed-by: Alexander Markov <alexmarkov@google.com> Reviewed-by: Slava Egorov <vegorov@google.com> Commit-Queue: Martin Kustermann <kustermann@google.com>
96 lines
2.8 KiB
Dart
96 lines
2.8 KiB
Dart
// Copyright (c) 2023, 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.
|
|
|
|
// Regression test for https://dartbug.com/52430.
|
|
|
|
import 'dart:developer';
|
|
|
|
import 'package:test/test.dart';
|
|
import 'package:vm_service/vm_service.dart';
|
|
|
|
import 'common/service_test_common.dart';
|
|
import 'common/test_helper.dart';
|
|
|
|
class C {
|
|
static int staticField = 12;
|
|
int instanceField = 34;
|
|
|
|
static void staticMethod() {
|
|
((int x) {
|
|
debugger();
|
|
})(56);
|
|
}
|
|
|
|
void instanceMethod() {
|
|
((int y) {
|
|
debugger();
|
|
use(this);
|
|
})(78);
|
|
}
|
|
}
|
|
|
|
void use(_) {}
|
|
|
|
testMain() {
|
|
C c = C();
|
|
C.staticMethod();
|
|
c.instanceMethod();
|
|
}
|
|
|
|
final tests = <IsolateTest>[
|
|
hasStoppedAtBreakpoint,
|
|
stoppedAtLine(21),
|
|
(VmService service, IsolateRef isolateRef) async {
|
|
final isolateId = isolateRef.id!;
|
|
|
|
final xRef =
|
|
await service.evaluateInFrame(isolateId, 0, 'x') as InstanceRef;
|
|
expect(xRef.valueAsString, '56');
|
|
|
|
InstanceRef staticFieldRef = await service.evaluateInFrame(
|
|
isolateId, 0, 'staticField += 1') as InstanceRef;
|
|
expect(staticFieldRef.valueAsString, '13');
|
|
staticFieldRef = await service.evaluateInFrame(isolateId, 0, 'staticField')
|
|
as InstanceRef;
|
|
expect(staticFieldRef.valueAsString, '13');
|
|
|
|
// Evaluating 'instanceField' should fail since we are paused in the context
|
|
// of a static method.
|
|
try {
|
|
await service.evaluateInFrame(isolateId, 0, 'instanceField');
|
|
fail('Expected RPCError');
|
|
} catch (e) {
|
|
final rpcError = e as RPCError;
|
|
expect(rpcError.code, RPCErrorKind.kExpressionCompilationError.code);
|
|
}
|
|
},
|
|
resumeIsolate,
|
|
stoppedAtLine(27),
|
|
(VmService service, IsolateRef isolateRef) async {
|
|
final isolateId = isolateRef.id!;
|
|
|
|
final yRef =
|
|
await service.evaluateInFrame(isolateId, 0, 'y') as InstanceRef;
|
|
expect(yRef.valueAsString, '78');
|
|
|
|
InstanceRef staticFieldRef = await service.evaluateInFrame(
|
|
isolateId, 0, 'staticField += 1') as InstanceRef;
|
|
expect(staticFieldRef.valueAsString, '14');
|
|
staticFieldRef = await service.evaluateInFrame(isolateId, 0, 'staticField')
|
|
as InstanceRef;
|
|
expect(staticFieldRef.valueAsString, '14');
|
|
|
|
InstanceRef instanceFieldRef = await service.evaluateInFrame(
|
|
isolateId, 0, 'instanceField += 1') as InstanceRef;
|
|
expect(instanceFieldRef.valueAsString, '35');
|
|
instanceFieldRef = await service.evaluateInFrame(
|
|
isolateId, 0, 'instanceField') as InstanceRef;
|
|
expect(instanceFieldRef.valueAsString, '35');
|
|
}
|
|
];
|
|
|
|
main([args = const <String>[]]) async =>
|
|
runIsolateTests(args, tests, 'evaluate_inside_closures_test.dart',
|
|
testeeConcurrent: testMain);
|