From 3b885ad6dad865d4c5bc74b1cc6268d42bf5f61c Mon Sep 17 00:00:00 2001 From: Srujan Gaddam Date: Thu, 25 Sep 2025 09:23:28 -0700 Subject: [PATCH 1/5] Use evaluate instead of periodic timer to test dot shorthands Fixes https://github.com/dart-lang/webdev/issues/2638 Fields are cached after their first execution. When debugging, this means we may not hit the body of the field when using the AMD module format. The DDC library bundle format always has a getter for fields, even with the cached value, however. To make the test consistent, we should avoid any previous executions of the field by using an evaluate call instead of a periodic timer in main. This requires moving the dot shorthands test to its own fixture. --- dwds/test/fixtures/project.dart | 8 +++ .../common/dot_shorthands_common.dart | 54 +++++++++++++------ fixtures/_experiment/web/main.dart | 37 +++---------- fixtures/_test_dot_shorthands/pubspec.yaml | 16 ++++++ fixtures/_test_dot_shorthands/web/index.html | 7 +++ fixtures/_test_dot_shorthands/web/main.dart | 30 +++++++++++ 6 files changed, 105 insertions(+), 47 deletions(-) create mode 100644 fixtures/_test_dot_shorthands/pubspec.yaml create mode 100644 fixtures/_test_dot_shorthands/web/index.html create mode 100644 fixtures/_test_dot_shorthands/web/main.dart diff --git a/dwds/test/fixtures/project.dart b/dwds/test/fixtures/project.dart index 8d83bdfdd..6f15ea89b 100644 --- a/dwds/test/fixtures/project.dart +++ b/dwds/test/fixtures/project.dart @@ -119,6 +119,14 @@ class TestProject { htmlEntryFileName: 'index.html', ); + static final testDotShorthands = TestProject._( + packageName: '_test_dot_shorthands', + packageDirectory: '_test_dot_shorthands', + webAssetsPath: 'web', + dartEntryFileName: 'main.dart', + htmlEntryFileName: 'index.html', + ); + static final testHotRestart1 = TestProject._( packageName: '_test_hot_restart1', packageDirectory: '_test_hot_restart1', diff --git a/dwds/test/instances/common/dot_shorthands_common.dart b/dwds/test/instances/common/dot_shorthands_common.dart index 94c5bd077..b3f754d62 100644 --- a/dwds/test/instances/common/dot_shorthands_common.dart +++ b/dwds/test/instances/common/dot_shorthands_common.dart @@ -2,7 +2,6 @@ // 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 'package:dwds/src/services/expression_compiler.dart' show ModuleFormat; import 'package:path/path.dart' show basename; import 'package:test/test.dart'; import 'package:test_common/logging.dart'; @@ -20,7 +19,7 @@ void runTests({ required bool canaryFeatures, required bool debug, }) { - final context = TestContext(TestProject.testExperiment, provider); + final context = TestContext(TestProject.testDotShorthands, provider); final testInspector = TestInspector(context); late VmService service; @@ -73,8 +72,8 @@ void runTests({ await context.tearDown(); }); - test('expression evaluation and single-stepping', () async { - await onBreakpoint('testDotShorthands', (event) async { + test('expression evaluation', () async { + final bp = onBreakpoint('testDotShorthands', (event) async { final frame = event.topFrame!.index!; var instanceRef = await getInstanceRef(frame, '(c = .two).value'); @@ -86,22 +85,36 @@ void runTests({ instanceRef = await getInstanceRef(frame, '(c = .four()).value'); expect(instanceRef.valueAsString, '4'); + await service.resume(isolateId); + }); + final isolate = await service.getIsolate(isolateId); + await service.evaluate( + isolateId, + isolate.rootLib!.id!, + 'testDotShorthands()', + ); + await bp; + }); + + test('single-stepping', () async { + final bp = onBreakpoint('testDotShorthands', (event) async { final scriptBasename = basename(mainScript.uri!); - const lineA = 116; - const lineB = 118; - const lineC = 119; - const lineD = 120; - const lineE = 127; - const lineF = 129; - const lineG = 131; - const lineH = 132; + const lineA = 11; + const lineB = 13; + const lineC = 14; + const lineD = 15; + const lineE = 22; + const lineF = 24; + const lineG = 26; + const lineH = 27; final expected = [ '$scriptBasename:$lineE:3', // on 'c' - // TODO(2638): Investigate why this conditional exclusion is needed. - if (provider.ddcModuleFormat == ModuleFormat.ddc) - '$scriptBasename:$lineB:20', // on '2' + '$scriptBasename:$lineB:15', // on 'C' + '$scriptBasename:$lineA:10', // on 'v' of 'value' + '$scriptBasename:$lineA:16', // on ';' + '$scriptBasename:$lineB:20', // on '2' '$scriptBasename:$lineF:3', // on 'c' '$scriptBasename:$lineC:25', // on 'C' '$scriptBasename:$lineA:10', // on 'v' of 'value' @@ -119,11 +132,20 @@ void runTests({ await testInspector.runStepIntoThroughProgramRecordingStops( isolateId, stops, - provider.ddcModuleFormat == ModuleFormat.ddc ? 13 : 12, + expected.length, ); expect(stops, expected); + + await service.resume(isolateId); }); + final isolate = await service.getIsolate(isolateId); + await service.evaluate( + isolateId, + isolate.rootLib!.id!, + 'testDotShorthands()', + ); + await bp; }); }); } diff --git a/fixtures/_experiment/web/main.dart b/fixtures/_experiment/web/main.dart index 7618cb6c8..773fd1a74 100644 --- a/fixtures/_experiment/web/main.dart +++ b/fixtures/_experiment/web/main.dart @@ -6,9 +6,10 @@ import 'dart:async'; import 'dart:core'; -// TODO: https://github.com/dart-lang/webdev/issues/2508 -// ignore: deprecated_member_use -import 'dart:html'; +import 'dart:js_interop'; + +@JS('document.body.append') +external void append(String text); void main() { // for evaluation @@ -26,11 +27,9 @@ void main() { testPattern2(); print('Classes'); testClass(); - print('Dot shorthands'); - testDotShorthands(); }); - document.body!.appendText('Program is running!'); + append('Program is running!'); } void printSimpleLocalRecord() { @@ -93,10 +92,7 @@ class GreeterClass { final String greeteeName; final bool useFrench; - GreeterClass({ - this.greeteeName = 'Snoopy', - this.useFrench = false, - }); + GreeterClass({this.greeteeName = 'Snoopy', this.useFrench = false}); void sayHello() { useFrench ? greetInFrench() : greetInEnglish(); @@ -110,24 +106,3 @@ class GreeterClass { print('Bonjour $greeteeName'); } } - -class C { - int value; - C(this.value); // lineA - - static C two = C(2); // lineB - static C get three => C(3); // lineC - static C four() => C(4); // lineD -} - -void testDotShorthands() { - C c = C(1); - print('breakpoint'); // Breakpoint: testDotShorthands - // ignore: experiment_not_enabled - c = .two; // lineE - // ignore: experiment_not_enabled - c = .three; // lineF - // ignore: experiment_not_enabled - c = .four(); // lineG - print(c.value); // lineH -} diff --git a/fixtures/_test_dot_shorthands/pubspec.yaml b/fixtures/_test_dot_shorthands/pubspec.yaml new file mode 100644 index 000000000..a2ea7d4f3 --- /dev/null +++ b/fixtures/_test_dot_shorthands/pubspec.yaml @@ -0,0 +1,16 @@ +name: _test_dot_shorthands +version: 1.0.0 +description: >- + A fake package used for testing dot shorthands. +publish_to: none + +environment: + sdk: ^3.2.0 + +dependencies: + intl: ^0.17.0 + path: ^1.8.2 + +dev_dependencies: + build_runner: ^2.5.0 + build_web_compilers: ^4.0.4 diff --git a/fixtures/_test_dot_shorthands/web/index.html b/fixtures/_test_dot_shorthands/web/index.html new file mode 100644 index 000000000..d93440a94 --- /dev/null +++ b/fixtures/_test_dot_shorthands/web/index.html @@ -0,0 +1,7 @@ + + + + + + + diff --git a/fixtures/_test_dot_shorthands/web/main.dart b/fixtures/_test_dot_shorthands/web/main.dart new file mode 100644 index 000000000..551b6747f --- /dev/null +++ b/fixtures/_test_dot_shorthands/web/main.dart @@ -0,0 +1,30 @@ +// 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. + +// @dart = 3.9 + +import 'dart:core'; + +class C { + int value; + C(this.value); // lineA + + static C two = C(2); // lineB + static C get three => C(3); // lineC + static C four() => C(4); // lineD +} + +void testDotShorthands() { + C c = C(1); + print('breakpoint'); // Breakpoint: testDotShorthands + // ignore: experiment_not_enabled + c = .two; // lineE + // ignore: experiment_not_enabled + c = .three; // lineF + // ignore: experiment_not_enabled + c = .four(); // lineG + print(c.value); // lineH +} + +void main() {} From 777be61b5a343fb4cdde89508d0c569a41760d9f Mon Sep 17 00:00:00 2001 From: Srujan Gaddam Date: Thu, 25 Sep 2025 09:42:26 -0700 Subject: [PATCH 2/5] Change pubspec --- fixtures/_test_dot_shorthands/pubspec.yaml | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/fixtures/_test_dot_shorthands/pubspec.yaml b/fixtures/_test_dot_shorthands/pubspec.yaml index a2ea7d4f3..54e2c65a3 100644 --- a/fixtures/_test_dot_shorthands/pubspec.yaml +++ b/fixtures/_test_dot_shorthands/pubspec.yaml @@ -5,12 +5,4 @@ description: >- publish_to: none environment: - sdk: ^3.2.0 - -dependencies: - intl: ^0.17.0 - path: ^1.8.2 - -dev_dependencies: - build_runner: ^2.5.0 - build_web_compilers: ^4.0.4 + sdk: ^3.9.0 From 46dabe1c719fe9f8825b0d6f7482746205d86162 Mon Sep 17 00:00:00 2001 From: Srujan Gaddam Date: Thu, 25 Sep 2025 09:43:03 -0700 Subject: [PATCH 3/5] Remove dart:core import --- fixtures/_test_dot_shorthands/web/main.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/fixtures/_test_dot_shorthands/web/main.dart b/fixtures/_test_dot_shorthands/web/main.dart index 551b6747f..8860e9f22 100644 --- a/fixtures/_test_dot_shorthands/web/main.dart +++ b/fixtures/_test_dot_shorthands/web/main.dart @@ -4,8 +4,6 @@ // @dart = 3.9 -import 'dart:core'; - class C { int value; C(this.value); // lineA From b9b53d939e3dd862314d4278458117132230d8b0 Mon Sep 17 00:00:00 2001 From: Srujan Gaddam Date: Thu, 25 Sep 2025 09:44:39 -0700 Subject: [PATCH 4/5] Update lines and header --- .../instances/common/dot_shorthands_common.dart | 16 ++++++++-------- fixtures/_test_dot_shorthands/web/main.dart | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/dwds/test/instances/common/dot_shorthands_common.dart b/dwds/test/instances/common/dot_shorthands_common.dart index b3f754d62..9c09be1ee 100644 --- a/dwds/test/instances/common/dot_shorthands_common.dart +++ b/dwds/test/instances/common/dot_shorthands_common.dart @@ -100,14 +100,14 @@ void runTests({ final bp = onBreakpoint('testDotShorthands', (event) async { final scriptBasename = basename(mainScript.uri!); - const lineA = 11; - const lineB = 13; - const lineC = 14; - const lineD = 15; - const lineE = 22; - const lineF = 24; - const lineG = 26; - const lineH = 27; + const lineA = 9; + const lineB = 11; + const lineC = 12; + const lineD = 13; + const lineE = 20; + const lineF = 22; + const lineG = 24; + const lineH = 25; final expected = [ '$scriptBasename:$lineE:3', // on 'c' diff --git a/fixtures/_test_dot_shorthands/web/main.dart b/fixtures/_test_dot_shorthands/web/main.dart index 8860e9f22..41520c7b0 100644 --- a/fixtures/_test_dot_shorthands/web/main.dart +++ b/fixtures/_test_dot_shorthands/web/main.dart @@ -1,4 +1,4 @@ -// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// 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. From c48c3c92e1df7474de3e8d3b2a8de477cc9065f8 Mon Sep 17 00:00:00 2001 From: Srujan Gaddam Date: Thu, 25 Sep 2025 10:39:39 -0700 Subject: [PATCH 5/5] Add build dependencies --- fixtures/_test_dot_shorthands/pubspec.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fixtures/_test_dot_shorthands/pubspec.yaml b/fixtures/_test_dot_shorthands/pubspec.yaml index 54e2c65a3..7bcd88802 100644 --- a/fixtures/_test_dot_shorthands/pubspec.yaml +++ b/fixtures/_test_dot_shorthands/pubspec.yaml @@ -6,3 +6,7 @@ publish_to: none environment: sdk: ^3.9.0 + +dev_dependencies: + build_runner: ^2.5.0 + build_web_compilers: ^4.0.4