Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit ee297c0

Browse files
authored
Provide toStrings for Native objects (#50168)
This hides the "Instance of _Native" bit that you get in debug output otherwise.
1 parent 07cdaab commit ee297c0

File tree

6 files changed

+98
-0
lines changed

6 files changed

+98
-0
lines changed

lib/ui/compositing.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ base class _NativeScene extends NativeFieldWrapperClass1 implements Scene {
8080
@override
8181
@Native<Void Function(Pointer<Void>)>(symbol: 'Scene::dispose')
8282
external void dispose();
83+
84+
@override
85+
String toString() => 'Scene';
8386
}
8487

8588
// Lightweight wrapper of a native layer object.
@@ -951,4 +954,7 @@ base class _NativeSceneBuilder extends NativeFieldWrapperClass1 implements Scene
951954

952955
@Native<Void Function(Pointer<Void>, Handle)>(symbol: 'SceneBuilder::build')
953956
external void _build(Scene outScene);
957+
958+
@override
959+
String toString() => 'SceneBuilder';
954960
}

lib/ui/painting.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2131,6 +2131,9 @@ base class _NativeCodec extends NativeFieldWrapperClass1 implements Codec {
21312131
@override
21322132
@Native<Void Function(Pointer<Void>)>(symbol: 'Codec::dispose')
21332133
external void dispose();
2134+
2135+
@override
2136+
String toString() => 'Codec(${_cachedFrameCount == null ? "" : "$_cachedFrameCount frames"})';
21342137
}
21352138

21362139
/// Instantiates an image [Codec].
@@ -3110,6 +3113,9 @@ base class _NativePath extends NativeFieldWrapperClass1 implements Path {
31103113
PathMetrics computeMetrics({bool forceClosed = false}) {
31113114
return PathMetrics._(this, forceClosed);
31123115
}
3116+
3117+
@override
3118+
String toString() => 'Path';
31133119
}
31143120

31153121
/// The geometric description of a tangent: the angle at a point.
@@ -6238,6 +6244,9 @@ base class _NativeCanvas extends NativeFieldWrapperClass1 implements Canvas {
62386244

62396245
@Native<Void Function(Pointer<Void>, Pointer<Void>, Uint32, Double, Bool)>(symbol: 'Canvas::drawShadow')
62406246
external void _drawShadow(_NativePath path, int color, double elevation, bool transparentOccluder);
6247+
6248+
@override
6249+
String toString() => 'Canvas(recording: ${_recorder != null})';
62416250
}
62426251

62436252
/// Signature for [Picture] lifecycle events.
@@ -6381,6 +6390,9 @@ base class _NativePicture extends NativeFieldWrapperClass1 implements Picture {
63816390
@override
63826391
@Native<Uint64 Function(Pointer<Void>)>(symbol: 'Picture::GetAllocationSize', isLeaf: true)
63836392
external int get approximateBytesUsed;
6393+
6394+
@override
6395+
String toString() => 'Picture';
63846396
}
63856397

63866398
/// Records a [Picture] containing a sequence of graphical operations.
@@ -6438,6 +6450,9 @@ base class _NativePictureRecorder extends NativeFieldWrapperClass1 implements Pi
64386450
external void _endRecording(_NativePicture outPicture);
64396451

64406452
_NativeCanvas? _canvas;
6453+
6454+
@override
6455+
String toString() => 'PictureRecorder(recording: $isRecording)';
64416456
}
64426457

64436458
/// A single shadow.
@@ -6895,6 +6910,9 @@ base class _NativeImageDescriptor extends NativeFieldWrapperClass1 implements Im
68956910

68966911
@Native<Void Function(Pointer<Void>, Handle, Int32, Int32)>(symbol: 'ImageDescriptor::instantiateCodec')
68976912
external void _instantiateCodec(Codec outCodec, int targetWidth, int targetHeight);
6913+
6914+
@override
6915+
String toString() => 'ImageDescriptor(width: ${_width ?? '?'}, height: ${_height ?? '?'}, bytes per pixel: ${_bytesPerPixel ?? '?'})';
68986916
}
68996917

69006918
/// Generic callback signature, used by [_futurize].

lib/ui/semantics.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,6 +1027,9 @@ base class _NativeSemanticsUpdateBuilder extends NativeFieldWrapperClass1 implem
10271027
}
10281028
@Native<Void Function(Pointer<Void>, Handle)>(symbol: 'SemanticsUpdateBuilder::build')
10291029
external void _build(_NativeSemanticsUpdate outSemanticsUpdate);
1030+
1031+
@override
1032+
String toString() => 'SemanticsUpdateBuilder';
10301033
}
10311034

10321035
/// An opaque object representing a batch of semantics updates.
@@ -1056,4 +1059,7 @@ base class _NativeSemanticsUpdate extends NativeFieldWrapperClass1 implements Se
10561059
@override
10571060
@Native<Void Function(Pointer<Void>)>(symbol: 'SemanticsUpdate::dispose')
10581061
external void dispose();
1062+
1063+
@override
1064+
String toString() => 'SemanticsUpdate';
10591065
}

lib/ui/text.dart

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3334,6 +3334,27 @@ base class _NativeParagraph extends NativeFieldWrapperClass1 implements Paragrap
33343334
}());
33353335
return disposed ?? (throw StateError('$runtimeType.debugDisposed is only available when asserts are enabled.'));
33363336
}
3337+
3338+
@override
3339+
String toString() {
3340+
String? result;
3341+
assert(() {
3342+
if (_disposed && _needsLayout) {
3343+
result = 'Paragraph(DISPOSED while dirty)';
3344+
}
3345+
if (_disposed && !_needsLayout) {
3346+
result = 'Paragraph(DISPOSED)';
3347+
}
3348+
return true;
3349+
}());
3350+
if (result != null) {
3351+
return result!;
3352+
}
3353+
if (_needsLayout) {
3354+
return 'Paragraph(dirty)';
3355+
}
3356+
return 'Paragraph()';
3357+
}
33373358
}
33383359

33393360
/// Builds a [Paragraph] containing text with the given styling information.
@@ -3657,6 +3678,9 @@ base class _NativeParagraphBuilder extends NativeFieldWrapperClass1 implements P
36573678

36583679
@Native<Void Function(Pointer<Void>, Handle)>(symbol: 'ParagraphBuilder::build')
36593680
external void _build(_NativeParagraph outParagraph);
3681+
3682+
@override
3683+
String toString() => 'ParagraphBuilder';
36603684
}
36613685

36623686
/// Loads a font from a buffer and makes it available for rendering text.

testing/dart/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ tests = [
4545
"serial_gc_test.dart",
4646
"spawn_helper.dart",
4747
"spawn_test.dart",
48+
"stringification_test.dart",
4849
"task_order_test.dart",
4950
"text_test.dart",
5051
"window_test.dart",
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'dart:typed_data';
6+
import 'dart:ui';
7+
8+
import 'package:litetest/litetest.dart';
9+
10+
final Uint8List imageData = Uint8List.fromList(<int>[ // Small WebP file
11+
0x52, 0x49, 0x46, 0x46, 0x12, 0x00, 0x00, 0x00, 0x57, 0x45, 0x42, 0x50, 0x56, 0x50, 0x38, 0x4c, // |RIFF....WEBPVP8L|
12+
0x06, 0x00, 0x00, 0x00, 0x2f, 0x41, 0x6c, 0x6f, 0x00, 0x6b, // |..../Alo.k|
13+
]);
14+
15+
void main() {
16+
test('Stringification of native objects exposed in Dart', () async {
17+
expect(SemanticsUpdateBuilder().toString(), 'SemanticsUpdateBuilder');
18+
expect(SemanticsUpdateBuilder().build().toString(), 'SemanticsUpdate');
19+
expect(ParagraphBuilder(ParagraphStyle()).toString(), 'ParagraphBuilder');
20+
expect(ParagraphBuilder(ParagraphStyle()).build().toString(), 'Paragraph(dirty)');
21+
expect((await instantiateImageCodec(imageData)).toString(), 'Codec()');
22+
expect(Path().toString(), 'Path');
23+
final PictureRecorder recorder = PictureRecorder();
24+
expect(recorder.toString(), 'PictureRecorder(recording: false)');
25+
final Canvas canvas = Canvas(recorder);
26+
expect(recorder.toString(), 'PictureRecorder(recording: true)');
27+
expect(canvas.toString(), 'Canvas(recording: true)');
28+
final Picture picture = recorder.endRecording();
29+
expect(recorder.toString(), 'PictureRecorder(recording: false)');
30+
expect(canvas.toString(), 'Canvas(recording: false)');
31+
expect(picture.toString(), 'Picture');
32+
expect(
33+
ImageDescriptor.raw(
34+
await ImmutableBuffer.fromUint8List(Uint8List.fromList(<int>[0, 0, 0, 0])),
35+
width: 1,
36+
height: 1,
37+
pixelFormat: PixelFormat.rgba8888,
38+
).toString(), 'ImageDescriptor(width: 1, height: 1, bytes per pixel: 4)',
39+
);
40+
expect(SceneBuilder().toString(), 'SceneBuilder');
41+
expect(SceneBuilder().build().toString(), 'Scene');
42+
});
43+
}

0 commit comments

Comments
 (0)