From 1139ed337319d32006179a83e71c062484cc0579 Mon Sep 17 00:00:00 2001 From: Alexander Markov Date: Thu, 22 Sep 2022 21:49:08 +0000 Subject: [PATCH] [vm] Record toString() TEST=language/records/simple/to_string_test Issue: https://github.com/dart-lang/sdk/issues/49719 Change-Id: I7e55a2486b1d964b24a287ffcf87c40c20f9cfe9 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/260480 Commit-Queue: Alexander Markov Reviewed-by: Ryan Macnak --- sdk/lib/_internal/vm/lib/object_patch.dart | 22 +++++++++++++ .../records/simple/to_string_test.dart | 33 +++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 tests/language/records/simple/to_string_test.dart diff --git a/sdk/lib/_internal/vm/lib/object_patch.dart b/sdk/lib/_internal/vm/lib/object_patch.dart index 5ef4a5a4e2b..5468b68fa49 100644 --- a/sdk/lib/_internal/vm/lib/object_patch.dart +++ b/sdk/lib/_internal/vm/lib/object_patch.dart @@ -132,6 +132,28 @@ class _Record { return SystemHash.finish(hash); } + // Do not inline to avoid mixing _fieldAt with + // record field accesses. + @pragma("vm:never-inline") + String toString() { + StringBuffer buffer = StringBuffer("("); + final int numFields = _numFields; + final _List fieldNames = _fieldNames; + final int numPositionalFields = numFields - fieldNames.length; + for (int i = 0; i < numFields; ++i) { + if (i != 0) { + buffer.write(", "); + } + if (i >= numPositionalFields) { + buffer.write(unsafeCast(fieldNames[i - numPositionalFields])); + buffer.write(": "); + } + buffer.write(_fieldAt(i).toString()); + } + buffer.write(")"); + return buffer.toString(); + } + @pragma("vm:recognized", "other") @pragma("vm:prefer-inline") external int get _numFields; diff --git a/tests/language/records/simple/to_string_test.dart b/tests/language/records/simple/to_string_test.dart new file mode 100644 index 00000000000..ad91b78df33 --- /dev/null +++ b/tests/language/records/simple/to_string_test.dart @@ -0,0 +1,33 @@ +// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code as governed by a +// BSD-style license that can be found in the LICENSE file. + +// SharedOptions=--enable-experiment=records + +import "package:expect/expect.dart"; + +class A { + final String name; + const A(this.name); + + String toString() => name; +} + +main() { + // Although the order of fields in toString() is unspecified, + // this test assumes that positional fields are printed first and + // named fields are sorted lexicographically. + // This test might need more sophisticated checks if there is + // an implementation which doesn't follow that order. + + Expect.equals("(1, 2)", (1, 2).toString()); + Expect.equals("(1, 2)", (const (1, 2)).toString()); + Expect.equals("(3, 2, 1)", (3, 2, 1).toString()); + + Expect.equals("(1, foo: 2)", (1, foo: 2).toString()); + Expect.equals("(1, foo: 2)", (foo: 2, 1).toString()); + + Expect.equals("(1, abc, bar: 3, foo: 2)", (1, foo: 2, "abc", bar: 3).toString()); + + Expect.equals("((A1, A2), (foo: A3), (A7, bar: A5, baz: A6, foo: A4))", ((A("A1"), A("A2")), const (foo: A("A3")), (foo: A("A4"), bar: A("A5"), baz: A("A6"), A("A7"))).toString()); +}