Skip to content

Commit

Permalink
Provide toStrings for Native objects (flutter#50168)
Browse files Browse the repository at this point in the history
This hides the "Instance of _Native" bit that you get in debug output otherwise.
  • Loading branch information
Hixie authored Feb 6, 2024
1 parent 07cdaab commit ee297c0
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 0 deletions.
6 changes: 6 additions & 0 deletions lib/ui/compositing.dart
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ base class _NativeScene extends NativeFieldWrapperClass1 implements Scene {
@override
@Native<Void Function(Pointer<Void>)>(symbol: 'Scene::dispose')
external void dispose();

@override
String toString() => 'Scene';
}

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

@Native<Void Function(Pointer<Void>, Handle)>(symbol: 'SceneBuilder::build')
external void _build(Scene outScene);

@override
String toString() => 'SceneBuilder';
}
18 changes: 18 additions & 0 deletions lib/ui/painting.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2131,6 +2131,9 @@ base class _NativeCodec extends NativeFieldWrapperClass1 implements Codec {
@override
@Native<Void Function(Pointer<Void>)>(symbol: 'Codec::dispose')
external void dispose();

@override
String toString() => 'Codec(${_cachedFrameCount == null ? "" : "$_cachedFrameCount frames"})';
}

/// Instantiates an image [Codec].
Expand Down Expand Up @@ -3110,6 +3113,9 @@ base class _NativePath extends NativeFieldWrapperClass1 implements Path {
PathMetrics computeMetrics({bool forceClosed = false}) {
return PathMetrics._(this, forceClosed);
}

@override
String toString() => 'Path';
}

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

@Native<Void Function(Pointer<Void>, Pointer<Void>, Uint32, Double, Bool)>(symbol: 'Canvas::drawShadow')
external void _drawShadow(_NativePath path, int color, double elevation, bool transparentOccluder);

@override
String toString() => 'Canvas(recording: ${_recorder != null})';
}

/// Signature for [Picture] lifecycle events.
Expand Down Expand Up @@ -6381,6 +6390,9 @@ base class _NativePicture extends NativeFieldWrapperClass1 implements Picture {
@override
@Native<Uint64 Function(Pointer<Void>)>(symbol: 'Picture::GetAllocationSize', isLeaf: true)
external int get approximateBytesUsed;

@override
String toString() => 'Picture';
}

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

_NativeCanvas? _canvas;

@override
String toString() => 'PictureRecorder(recording: $isRecording)';
}

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

@Native<Void Function(Pointer<Void>, Handle, Int32, Int32)>(symbol: 'ImageDescriptor::instantiateCodec')
external void _instantiateCodec(Codec outCodec, int targetWidth, int targetHeight);

@override
String toString() => 'ImageDescriptor(width: ${_width ?? '?'}, height: ${_height ?? '?'}, bytes per pixel: ${_bytesPerPixel ?? '?'})';
}

/// Generic callback signature, used by [_futurize].
Expand Down
6 changes: 6 additions & 0 deletions lib/ui/semantics.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1027,6 +1027,9 @@ base class _NativeSemanticsUpdateBuilder extends NativeFieldWrapperClass1 implem
}
@Native<Void Function(Pointer<Void>, Handle)>(symbol: 'SemanticsUpdateBuilder::build')
external void _build(_NativeSemanticsUpdate outSemanticsUpdate);

@override
String toString() => 'SemanticsUpdateBuilder';
}

/// An opaque object representing a batch of semantics updates.
Expand Down Expand Up @@ -1056,4 +1059,7 @@ base class _NativeSemanticsUpdate extends NativeFieldWrapperClass1 implements Se
@override
@Native<Void Function(Pointer<Void>)>(symbol: 'SemanticsUpdate::dispose')
external void dispose();

@override
String toString() => 'SemanticsUpdate';
}
24 changes: 24 additions & 0 deletions lib/ui/text.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3334,6 +3334,27 @@ base class _NativeParagraph extends NativeFieldWrapperClass1 implements Paragrap
}());
return disposed ?? (throw StateError('$runtimeType.debugDisposed is only available when asserts are enabled.'));
}

@override
String toString() {
String? result;
assert(() {
if (_disposed && _needsLayout) {
result = 'Paragraph(DISPOSED while dirty)';
}
if (_disposed && !_needsLayout) {
result = 'Paragraph(DISPOSED)';
}
return true;
}());
if (result != null) {
return result!;
}
if (_needsLayout) {
return 'Paragraph(dirty)';
}
return 'Paragraph()';
}
}

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

@Native<Void Function(Pointer<Void>, Handle)>(symbol: 'ParagraphBuilder::build')
external void _build(_NativeParagraph outParagraph);

@override
String toString() => 'ParagraphBuilder';
}

/// Loads a font from a buffer and makes it available for rendering text.
Expand Down
1 change: 1 addition & 0 deletions testing/dart/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ tests = [
"serial_gc_test.dart",
"spawn_helper.dart",
"spawn_test.dart",
"stringification_test.dart",
"task_order_test.dart",
"text_test.dart",
"window_test.dart",
Expand Down
43 changes: 43 additions & 0 deletions testing/dart/stringification_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:typed_data';
import 'dart:ui';

import 'package:litetest/litetest.dart';

final Uint8List imageData = Uint8List.fromList(<int>[ // Small WebP file
0x52, 0x49, 0x46, 0x46, 0x12, 0x00, 0x00, 0x00, 0x57, 0x45, 0x42, 0x50, 0x56, 0x50, 0x38, 0x4c, // |RIFF....WEBPVP8L|
0x06, 0x00, 0x00, 0x00, 0x2f, 0x41, 0x6c, 0x6f, 0x00, 0x6b, // |..../Alo.k|
]);

void main() {
test('Stringification of native objects exposed in Dart', () async {
expect(SemanticsUpdateBuilder().toString(), 'SemanticsUpdateBuilder');
expect(SemanticsUpdateBuilder().build().toString(), 'SemanticsUpdate');
expect(ParagraphBuilder(ParagraphStyle()).toString(), 'ParagraphBuilder');
expect(ParagraphBuilder(ParagraphStyle()).build().toString(), 'Paragraph(dirty)');
expect((await instantiateImageCodec(imageData)).toString(), 'Codec()');
expect(Path().toString(), 'Path');
final PictureRecorder recorder = PictureRecorder();
expect(recorder.toString(), 'PictureRecorder(recording: false)');
final Canvas canvas = Canvas(recorder);
expect(recorder.toString(), 'PictureRecorder(recording: true)');
expect(canvas.toString(), 'Canvas(recording: true)');
final Picture picture = recorder.endRecording();
expect(recorder.toString(), 'PictureRecorder(recording: false)');
expect(canvas.toString(), 'Canvas(recording: false)');
expect(picture.toString(), 'Picture');
expect(
ImageDescriptor.raw(
await ImmutableBuffer.fromUint8List(Uint8List.fromList(<int>[0, 0, 0, 0])),
width: 1,
height: 1,
pixelFormat: PixelFormat.rgba8888,
).toString(), 'ImageDescriptor(width: 1, height: 1, bytes per pixel: 4)',
);
expect(SceneBuilder().toString(), 'SceneBuilder');
expect(SceneBuilder().build().toString(), 'Scene');
});
}

0 comments on commit ee297c0

Please sign in to comment.