From cdf6ea3b93dc89b22a0d6bfba5b9fcf85b08e8c4 Mon Sep 17 00:00:00 2001 From: Erik Ernst Date: Thu, 5 Feb 2026 15:40:42 +0100 Subject: [PATCH 01/11] Prevent generated imports of dart:_http --- .../lib/src/builder_implementation.dart | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/packages/reflectable_builder/lib/src/builder_implementation.dart b/packages/reflectable_builder/lib/src/builder_implementation.dart index cf20dfca..3b00ce81 100644 --- a/packages/reflectable_builder/lib/src/builder_implementation.dart +++ b/packages/reflectable_builder/lib/src/builder_implementation.dart @@ -4897,6 +4897,27 @@ class BuilderImplementation { } imports.sort(); + // Some "private" platform libraries are exported by public ones. To avoid + // the error caused by importing 'dart:_http', we transform it to 'dart:io'. + // Other cases are ambiguous and not handled. + final length = imports.length; + for (int index = 0; index < length; ++index) { + final import = imports[index]; + if (import.contains('dart:_')) { + if (import.contains('dart:_http')) { + final rest = import.substring(20, import.length); + imports[index] = "import 'dart:io' $rest"; + } else { + // TODO(eernst): Perhaps we can handle some of the remaining cases. + final match = RegExp(r"'dart:_.*'").firstMatch(import); + final String name = match != null + ? import.substring(match.start, match.end) + : import; + await _severe('Reference to an internal platform library: $name'); + } + } + } + var result = ''' // This file has been generated by the reflectable package. From bf1ed82e28b83e8c6ee7acd7e5c42b4b824fc63c Mon Sep 17 00:00:00 2001 From: Erik Ernst Date: Thu, 5 Feb 2026 15:51:05 +0100 Subject: [PATCH 02/11] Update CHANGELOG and pubspec --- packages/reflectable/CHANGELOG.md | 4 ++++ packages/reflectable/pubspec.yaml | 2 +- packages/reflectable_builder/CHANGELOG.md | 4 ++++ packages/reflectable_builder/pubspec.yaml | 2 +- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/reflectable/CHANGELOG.md b/packages/reflectable/CHANGELOG.md index 7b83f0b7..858b2253 100644 --- a/packages/reflectable/CHANGELOG.md +++ b/packages/reflectable/CHANGELOG.md @@ -1,3 +1,7 @@ +## 5.2.1 + +- Fix bugs #354 and #325. + ## 5.2.0 - Upgrade reflectable to use analyzer ^10.0.0 and lints ^6.0.0. diff --git a/packages/reflectable/pubspec.yaml b/packages/reflectable/pubspec.yaml index 321c7360..a80aacdf 100644 --- a/packages/reflectable/pubspec.yaml +++ b/packages/reflectable/pubspec.yaml @@ -1,5 +1,5 @@ name: reflectable -version: 5.2.0 +version: 5.2.1 description: > Reflection support based on code generation, using 'capabilities' to specify which operations to support, on which objects. This is the diff --git a/packages/reflectable_builder/CHANGELOG.md b/packages/reflectable_builder/CHANGELOG.md index d96c7b7c..42378eb9 100644 --- a/packages/reflectable_builder/CHANGELOG.md +++ b/packages/reflectable_builder/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.2.1 + +- Fix bugs #354 and #325. + ## 1.2.0 - Upgrade the code generator to use analyzer ^10.0.0 and lints 6.0.0. diff --git a/packages/reflectable_builder/pubspec.yaml b/packages/reflectable_builder/pubspec.yaml index 4134ed1a..379cac6b 100644 --- a/packages/reflectable_builder/pubspec.yaml +++ b/packages/reflectable_builder/pubspec.yaml @@ -1,5 +1,5 @@ name: reflectable_builder -version: 1.2.0 +version: 1.2.1 description: > Reflection support based on code generation, using 'capabilities' to specify which operations to support, on which objects. This is the From 1dc7a95c95e97956e6d48440fa8a21f0cee25c26 Mon Sep 17 00:00:00 2001 From: Erik Ernst Date: Thu, 5 Feb 2026 15:55:00 +0100 Subject: [PATCH 03/11] Add requested type annotations --- packages/reflectable/example/bin/example.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/reflectable/example/bin/example.dart b/packages/reflectable/example/bin/example.dart index 06dd352d..bd482a81 100644 --- a/packages/reflectable/example/bin/example.dart +++ b/packages/reflectable/example/bin/example.dart @@ -22,7 +22,7 @@ class A { int argNamed(int x, int y, {int z = 42}) => x + y - z; int operator +(int x) => 42 + x; int operator [](int x) => 42 + x; - void operator []=(x, v) { + void operator []=(int x, int v) { f = x + v; } @@ -33,7 +33,8 @@ class A { static int noArguments() => 42; static int oneArgument(x) => x - 42; - static int optionalArguments(x, y, [z = 0, w]) => x + y + z * 42; + static int optionalArguments(int x, int y, [int z = 0, int w]) => + x + y + z * 42; static int namedArguments(int x, int y, {int z = 42}) => x + y - z; } From dfbf2b2b7130c514db391998d97e995024d19c65 Mon Sep 17 00:00:00 2001 From: Erik Ernst Date: Thu, 5 Feb 2026 15:56:33 +0100 Subject: [PATCH 04/11] WIP --- packages/reflectable/example/bin/example.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/reflectable/example/bin/example.dart b/packages/reflectable/example/bin/example.dart index bd482a81..4d5998ea 100644 --- a/packages/reflectable/example/bin/example.dart +++ b/packages/reflectable/example/bin/example.dart @@ -32,8 +32,8 @@ class A { int f = 0; static int noArguments() => 42; - static int oneArgument(x) => x - 42; - static int optionalArguments(int x, int y, [int z = 0, int w]) => + static int oneArgument(int x) => x - 42; + static int optionalArguments(int x, int y, [int z = 0, int? w]) => x + y + z * 42; static int namedArguments(int x, int y, {int z = 42}) => x + y - z; } From 35876a8a026ec0067c691ca524ade4b16435f24b Mon Sep 17 00:00:00 2001 From: Erik Ernst Date: Mon, 9 Feb 2026 14:18:55 +0100 Subject: [PATCH 05/11] Update top-level README.md --- README.md | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index bdd79718..4f0a6057 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,19 @@ +This repository provides the Dart packages `reflectable` and +`reflectable_builder`, along with a set of test cases and +examples in the repository `test_reflectable`. -This repository provides the Dart package `reflectable` along with a set of -test cases, `test_reflectable`. +## [reflectable](https://github.com/google/reflectable.dart/blob/master/packages/reflectable/README.md) -## [reflectable](https://github.com/google/reflectable.dart/blob/master/reflectable/README.md) +Support for implementing a large subset of the features offered by +'dart:mirrors' without relying on 'dart:mirrors' itself. Provides a system +based on capabilities to control the amount of reflection support. -Support for generating code that implements a large subset of the features -offered by 'dart:mirrors' without relying on 'dart:mirrors' itself. -Provides a system based on capabilities to control the amount of reflection -support. +## [reflectable_builder](https://github.com/google/reflectable.dart/blob/master/packages/reflectable_builder/README.md) -## [test_reflectable](https://github.com/google/reflectable.dart/blob/master/test_reflectable/README.md) +Support for generating the code that the package `reflectable` uses to provide +the reflection support described above. + +## [test_reflectable](https://github.com/google/reflectable.dart/blob/master/packages/test_reflectable/README.md) Used to test package `reflectable`. Also serves as a set of examples of how `reflectable` can be used. From 6c1d48a591143f493ebee622b2d8f91083a23d0c Mon Sep 17 00:00:00 2001 From: Erik Ernst Date: Mon, 9 Feb 2026 17:13:06 +0100 Subject: [PATCH 06/11] Add test to test special casing of dart:_http imports --- .../test/substitute_http_test.dart | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 packages/test_reflectable/test/substitute_http_test.dart diff --git a/packages/test_reflectable/test/substitute_http_test.dart b/packages/test_reflectable/test/substitute_http_test.dart new file mode 100644 index 00000000..103d3ec7 --- /dev/null +++ b/packages/test_reflectable/test/substitute_http_test.dart @@ -0,0 +1,37 @@ +// Copyright (c) 2026, 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. + +// Test the special casing of declarations in 'dart:_http'. + +library test_reflectable.test.substitute_http_test; + +import 'dart:io'; + +@GlobalQuantifyCapability(r'\.Cookie$', reflector) +import 'package:reflectable/reflectable.dart'; + +import 'substitute_http_test.reflectable.dart'; + +class Reflector extends Reflectable { + const Reflector() + : super( + instanceInvokeCapability, + declarationsCapability, + superclassQuantifyCapability, + ); +} + +const reflector = Reflector(); + +@reflector +class CookieHolder extends HttpException { + CookieHolder(super._); + final Cookie? cookie = null; +} + +void main() { + initializeReflectable(); + // Just checking that the program compiles, that is, it does not + // attempt to import `dart:_http`. +} From 9b4b8466ebec8e30fa6cf9fc57a2f54da1a4948b Mon Sep 17 00:00:00 2001 From: Erik Ernst Date: Tue, 10 Feb 2026 13:36:51 +0100 Subject: [PATCH 07/11] Update packages/reflectable_builder/lib/src/builder_implementation.dart Co-authored-by: Sigurd Meldgaard --- .../reflectable_builder/lib/src/builder_implementation.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/reflectable_builder/lib/src/builder_implementation.dart b/packages/reflectable_builder/lib/src/builder_implementation.dart index 3b00ce81..469cdd47 100644 --- a/packages/reflectable_builder/lib/src/builder_implementation.dart +++ b/packages/reflectable_builder/lib/src/builder_implementation.dart @@ -4905,7 +4905,7 @@ class BuilderImplementation { final import = imports[index]; if (import.contains('dart:_')) { if (import.contains('dart:_http')) { - final rest = import.substring(20, import.length); + final rest = import.substring("import 'dart:_http' ".length, import.length); imports[index] = "import 'dart:io' $rest"; } else { // TODO(eernst): Perhaps we can handle some of the remaining cases. From 8d3982101bf1a5062b6158a308aa02ac4ad477a4 Mon Sep 17 00:00:00 2001 From: Erik Ernst Date: Tue, 10 Feb 2026 13:43:02 +0100 Subject: [PATCH 08/11] Review response --- packages/reflectable_builder/example/example.dart | 7 ++++--- .../lib/src/builder_implementation.dart | 8 ++++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/reflectable_builder/example/example.dart b/packages/reflectable_builder/example/example.dart index 06dd352d..4d5998ea 100644 --- a/packages/reflectable_builder/example/example.dart +++ b/packages/reflectable_builder/example/example.dart @@ -22,7 +22,7 @@ class A { int argNamed(int x, int y, {int z = 42}) => x + y - z; int operator +(int x) => 42 + x; int operator [](int x) => 42 + x; - void operator []=(x, v) { + void operator []=(int x, int v) { f = x + v; } @@ -32,8 +32,9 @@ class A { int f = 0; static int noArguments() => 42; - static int oneArgument(x) => x - 42; - static int optionalArguments(x, y, [z = 0, w]) => x + y + z * 42; + static int oneArgument(int x) => x - 42; + static int optionalArguments(int x, int y, [int z = 0, int? w]) => + x + y + z * 42; static int namedArguments(int x, int y, {int z = 42}) => x + y - z; } diff --git a/packages/reflectable_builder/lib/src/builder_implementation.dart b/packages/reflectable_builder/lib/src/builder_implementation.dart index 469cdd47..d4ca4482 100644 --- a/packages/reflectable_builder/lib/src/builder_implementation.dart +++ b/packages/reflectable_builder/lib/src/builder_implementation.dart @@ -4904,8 +4904,12 @@ class BuilderImplementation { for (int index = 0; index < length; ++index) { final import = imports[index]; if (import.contains('dart:_')) { - if (import.contains('dart:_http')) { - final rest = import.substring("import 'dart:_http' ".length, import.length); + if (import.contains('"dart:_http"') || + import.contains("'dart:_http'")) { + final rest = import.substring( + "import 'dart:_http' ".length, + import.length, + ); imports[index] = "import 'dart:io' $rest"; } else { // TODO(eernst): Perhaps we can handle some of the remaining cases. From 020ddb46ea1e6a6ff08b4eeac5b2b187f904e415 Mon Sep 17 00:00:00 2001 From: Erik Ernst Date: Tue, 10 Feb 2026 13:45:46 +0100 Subject: [PATCH 09/11] Simplify test (we know how the import was created) --- .../reflectable_builder/lib/src/builder_implementation.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/reflectable_builder/lib/src/builder_implementation.dart b/packages/reflectable_builder/lib/src/builder_implementation.dart index d4ca4482..08313d3d 100644 --- a/packages/reflectable_builder/lib/src/builder_implementation.dart +++ b/packages/reflectable_builder/lib/src/builder_implementation.dart @@ -4904,8 +4904,7 @@ class BuilderImplementation { for (int index = 0; index < length; ++index) { final import = imports[index]; if (import.contains('dart:_')) { - if (import.contains('"dart:_http"') || - import.contains("'dart:_http'")) { + if (import.contains("'dart:_http'")) { final rest = import.substring( "import 'dart:_http' ".length, import.length, From 58ec1be6bdd04c1800fa6f8bc65b124f7ea95cba Mon Sep 17 00:00:00 2001 From: Erik Ernst Date: Tue, 10 Feb 2026 13:48:22 +0100 Subject: [PATCH 10/11] Correct outer test of import string --- .../reflectable_builder/lib/src/builder_implementation.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/reflectable_builder/lib/src/builder_implementation.dart b/packages/reflectable_builder/lib/src/builder_implementation.dart index 08313d3d..2e11a4f3 100644 --- a/packages/reflectable_builder/lib/src/builder_implementation.dart +++ b/packages/reflectable_builder/lib/src/builder_implementation.dart @@ -4903,7 +4903,7 @@ class BuilderImplementation { final length = imports.length; for (int index = 0; index < length; ++index) { final import = imports[index]; - if (import.contains('dart:_')) { + if (import.contains("'dart:_")) { if (import.contains("'dart:_http'")) { final rest = import.substring( "import 'dart:_http' ".length, From 6002a8e6960f632a57c6cbcf9247a7cec9db5241 Mon Sep 17 00:00:00 2001 From: Erik Ernst Date: Tue, 10 Feb 2026 16:00:10 +0100 Subject: [PATCH 11/11] Consistently consider 'dart:_http' as an importable library, then redirect imports to 'dart:io' at the very end --- packages/reflectable_builder/lib/src/builder_implementation.dart | 1 + packages/test_reflectable/test/substitute_http_test.dart | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/reflectable_builder/lib/src/builder_implementation.dart b/packages/reflectable_builder/lib/src/builder_implementation.dart index 2e11a4f3..9753acc1 100644 --- a/packages/reflectable_builder/lib/src/builder_implementation.dart +++ b/packages/reflectable_builder/lib/src/builder_implementation.dart @@ -5599,6 +5599,7 @@ const Set sdkLibraryNames = { 'web_audio', 'web_gl', 'web_sql', + '_http', // Special case, redirected to 'dart:io'. }; // Helper for _extractMetadataCode. diff --git a/packages/test_reflectable/test/substitute_http_test.dart b/packages/test_reflectable/test/substitute_http_test.dart index 103d3ec7..9464822f 100644 --- a/packages/test_reflectable/test/substitute_http_test.dart +++ b/packages/test_reflectable/test/substitute_http_test.dart @@ -19,6 +19,7 @@ class Reflector extends Reflectable { instanceInvokeCapability, declarationsCapability, superclassQuantifyCapability, + typeAnnotationQuantifyCapability, ); }