From af17e1544dae1e352409e4b80ae917358b15d8d2 Mon Sep 17 00:00:00 2001 From: "Sergey G. Grekhov" Date: Tue, 21 Oct 2025 17:35:30 +0300 Subject: [PATCH 1/3] #3203. Add VM - CFE interaction tests for primary initializer scope --- VM/declaring_constructors_t02.dart | 104 +++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 VM/declaring_constructors_t02.dart diff --git a/VM/declaring_constructors_t02.dart b/VM/declaring_constructors_t02.dart new file mode 100644 index 0000000000..a71e9021d5 --- /dev/null +++ b/VM/declaring_constructors_t02.dart @@ -0,0 +1,104 @@ +// Copyright (c) 2025, 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. + +/// @assertion A declaring constructor declaration is a declaration that +/// contains a `` with a +/// ``, or a declaration that contains a +/// ``, or it is a +/// `` in the header of a class, enum, or extension +/// type declaration, together with a declaration in the body that contains a +/// ``. +/// +/// @description Check that members initialized in primary initializer scope can +/// be debugged. +/// @author sgrekhov22@gmail.com + +// SharedOptions=--enable-experiment=declaring-constructors + +import 'dart:developer'; +import 'package:vm_service/vm_service.dart'; + +import '../../../../pkg/vm_service/test/common/service_test_common.dart'; +import '../../../../pkg/vm_service/test/common/test_helper.dart'; +import '../Utils/expect.dart'; + +const String shortFile = 'declaring_constructors_t02.dart'; + +// AUTOGENERATED START +// +// Update these constants by running: +// +// dart pkg/vm_service/test/update_line_numbers.dart tests/co19/src/VM/declaring_constructors_t02.dart +// +const LINE_A = 45; +const LINE_B = 46; +const LINE_C = 47; +const LINE_D = 48; +const LINE_E = 50; +const LINE_F = 51; +const LINE_G = 57; +const LINE_H = 58; +const LINE_I = 59; +// AUTOGENERATED END + +class C(var String x) { // LINE_A + String Function() captureAtDeclaration = () => x; // LINE_B + String Function() captureInInitializer; // LINE_C + String Function()? captureInBody; // LINE_D + + this : captureInInitializer = (() => x) { // LINE_E + captureInBody = () => x; // LINE_F + } +} + +void testeeMain() { + debugger(); + var c = C("test"); // LINE_G + c.captureInInitializer(); // LINE_H + c.captureAtDeclaration(); // LINE_I +} + +List stops = []; + +const List expected = [ + '$shortFile:$LINE_G:9', // on '=' + '$shortFile:$LINE_G:11', // on 'C' + '$shortFile:$LINE_A:20', // on 'x' + '$shortFile:$LINE_F:5', // on 'captureInBody' + '$shortFile:$LINE_H:5', // on 'captureInInitializer' + '$shortFile:$LINE_H:25', // on '()' + '$shortFile:$LINE_E:34', // on '() =>' + '$shortFile:$LINE_E:40', // on 'x' + '$shortFile:$LINE_I:5', // on 'captureAtDeclaration' + '$shortFile:$LINE_I:25', // on '()' + '$shortFile:$LINE_B:44', // on '() =>' + '$shortFile:$LINE_B:50', // on 'x' +]; + +final tests = [ + + // Test interaction of breakpoints with declaring constructors. + (VmService service, IsolateRef isolateRef) async { + final isolateId = isolateRef.id!; + final isolate = await service.getIsolate(isolateId); + final lib = + (await service.getObject(isolateId, isolate.rootLib!.id!)) as Library; + final scriptId = lib.scripts!.first.id!; + + var breakpoint = await service.addBreakpoint(isolateId, scriptId, LINE_G); + var (_, (line, column)) = await breakpoint.getLocation(service, isolateRef); + }, + + // Test interaction of single-stepping with declaring constructors. + runStepIntoThroughProgramRecordingStops(stops), + checkRecordedStops(stops, expected), +]; + +void main([args = const []]) => runIsolateTests( + args, + tests, + 'declaring_constructors_t02.dart', + pauseOnExit: true, + testeeConcurrent: testeeMain, +); From dc8f5bf401a8d6ac0e1ea95607a3ffcc42c1de2b Mon Sep 17 00:00:00 2001 From: "Sergey G. Grekhov" Date: Thu, 30 Oct 2025 16:17:00 +0200 Subject: [PATCH 2/3] Rewrite the test to debug declaring constructors --- VM/declaring_constructors_t02.dart | 106 +++++++++++++++-------------- 1 file changed, 56 insertions(+), 50 deletions(-) diff --git a/VM/declaring_constructors_t02.dart b/VM/declaring_constructors_t02.dart index a71e9021d5..9fd0135809 100644 --- a/VM/declaring_constructors_t02.dart +++ b/VM/declaring_constructors_t02.dart @@ -23,7 +23,7 @@ import '../../../../pkg/vm_service/test/common/service_test_common.dart'; import '../../../../pkg/vm_service/test/common/test_helper.dart'; import '../Utils/expect.dart'; -const String shortFile = 'declaring_constructors_t02.dart'; +const String shortFile = 'declaring_constructors_t03.dart'; // AUTOGENERATED START // @@ -31,68 +31,74 @@ const String shortFile = 'declaring_constructors_t02.dart'; // // dart pkg/vm_service/test/update_line_numbers.dart tests/co19/src/VM/declaring_constructors_t02.dart // -const LINE_A = 45; -const LINE_B = 46; -const LINE_C = 47; -const LINE_D = 48; +const LINE_A = 41; +const LINE_B = 44; +const LINE_C = 48; +const LINE_D = 49; const LINE_E = 50; -const LINE_F = 51; -const LINE_G = 57; -const LINE_H = 58; -const LINE_I = 59; // AUTOGENERATED END -class C(var String x) { // LINE_A - String Function() captureAtDeclaration = () => x; // LINE_B - String Function() captureInInitializer; // LINE_C - String Function()? captureInBody; // LINE_D +class C1(var String x); // LINE_A - this : captureInInitializer = (() => x) { // LINE_E - captureInBody = () => x; // LINE_F - } +class C2 { + this(final String x); // LINE_B } void testeeMain() { - debugger(); - var c = C("test"); // LINE_G - c.captureInInitializer(); // LINE_H - c.captureAtDeclaration(); // LINE_I + debugger(); // LINE_C + C1("xxx"); // LINE_D + C2("yyy"); // LINE_E } -List stops = []; - -const List expected = [ - '$shortFile:$LINE_G:9', // on '=' - '$shortFile:$LINE_G:11', // on 'C' - '$shortFile:$LINE_A:20', // on 'x' - '$shortFile:$LINE_F:5', // on 'captureInBody' - '$shortFile:$LINE_H:5', // on 'captureInInitializer' - '$shortFile:$LINE_H:25', // on '()' - '$shortFile:$LINE_E:34', // on '() =>' - '$shortFile:$LINE_E:40', // on 'x' - '$shortFile:$LINE_I:5', // on 'captureAtDeclaration' - '$shortFile:$LINE_I:25', // on '()' - '$shortFile:$LINE_B:44', // on '() =>' - '$shortFile:$LINE_B:50', // on 'x' -]; - final tests = [ - - // Test interaction of breakpoints with declaring constructors. + hasStoppedAtBreakpoint, + stoppedAtLine(LINE_C), + stepInto, + stoppedAtLine(LINE_D), + stepInto, + stoppedAtLine(LINE_A), (VmService service, IsolateRef isolateRef) async { final isolateId = isolateRef.id!; - final isolate = await service.getIsolate(isolateId); - final lib = - (await service.getObject(isolateId, isolate.rootLib!.id!)) as Library; - final scriptId = lib.scripts!.first.id!; - - var breakpoint = await service.addBreakpoint(isolateId, scriptId, LINE_G); - var (_, (line, column)) = await breakpoint.getLocation(service, isolateRef); + final xRef1 = + await service.evaluateInFrame(isolateId, 0, 'x') as InstanceRef; + Expect.equals("null", xRef1.valueAsString); + final xRef2 = + await service.evaluateInFrame(isolateId, 0, 'this.x') as InstanceRef; + Expect.equals("null", xRef2.valueAsString); + }, + stepInto, + (VmService service, IsolateRef isolateRef) async { + final isolateId = isolateRef.id!; + final xRef1 = + await service.evaluateInFrame(isolateId, 0, 'x') as InstanceRef; + Expect.equals('xxx', xRef1.valueAsString); + final xRef2 = + await service.evaluateInFrame(isolateId, 0, 'this.x') as InstanceRef; + Expect.equals('xxx', xRef2.valueAsString); + }, + stepInto, + stoppedAtLine(LINE_E), + stepInto, + stoppedAtLine(LINE_B), + (VmService service, IsolateRef isolateRef) async { + final isolateId = isolateRef.id!; + final xRef1 = + await service.evaluateInFrame(isolateId, 0, 'x') as InstanceRef; + Expect.equals("null", xRef1.valueAsString); + final xRef2 = + await service.evaluateInFrame(isolateId, 0, 'this.x') as InstanceRef; + Expect.equals("null", xRef2.valueAsString); + }, + stepInto, + (VmService service, IsolateRef isolateRef) async { + final isolateId = isolateRef.id!; + final xRef1 = + await service.evaluateInFrame(isolateId, 0, 'x') as InstanceRef; + Expect.equals('yyy', xRef1.valueAsString); + final xRef2 = + await service.evaluateInFrame(isolateId, 0, 'this.x') as InstanceRef; + Expect.equals('yyy', xRef2.valueAsString); }, - - // Test interaction of single-stepping with declaring constructors. - runStepIntoThroughProgramRecordingStops(stops), - checkRecordedStops(stops, expected), ]; void main([args = const []]) => runIsolateTests( From 3fb21d54ef7bedd5fdf631aa966611d79aa351ef Mon Sep 17 00:00:00 2001 From: sgrekhov Date: Fri, 31 Oct 2025 09:08:39 +0200 Subject: [PATCH 3/3] Format code --- VM/declaring_constructors_t02.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/VM/declaring_constructors_t02.dart b/VM/declaring_constructors_t02.dart index 9fd0135809..1f66d663b4 100644 --- a/VM/declaring_constructors_t02.dart +++ b/VM/declaring_constructors_t02.dart @@ -60,20 +60,20 @@ final tests = [ (VmService service, IsolateRef isolateRef) async { final isolateId = isolateRef.id!; final xRef1 = - await service.evaluateInFrame(isolateId, 0, 'x') as InstanceRef; + await service.evaluateInFrame(isolateId, 0, 'x') as InstanceRef; Expect.equals("null", xRef1.valueAsString); final xRef2 = - await service.evaluateInFrame(isolateId, 0, 'this.x') as InstanceRef; + await service.evaluateInFrame(isolateId, 0, 'this.x') as InstanceRef; Expect.equals("null", xRef2.valueAsString); }, stepInto, (VmService service, IsolateRef isolateRef) async { final isolateId = isolateRef.id!; final xRef1 = - await service.evaluateInFrame(isolateId, 0, 'x') as InstanceRef; + await service.evaluateInFrame(isolateId, 0, 'x') as InstanceRef; Expect.equals('xxx', xRef1.valueAsString); final xRef2 = - await service.evaluateInFrame(isolateId, 0, 'this.x') as InstanceRef; + await service.evaluateInFrame(isolateId, 0, 'this.x') as InstanceRef; Expect.equals('xxx', xRef2.valueAsString); }, stepInto,