diff --git a/pkg/dart2wasm/bin/run_wasm.js b/pkg/dart2wasm/bin/run_wasm.js index 56d5248a3db..3a842fb3bfb 100644 --- a/pkg/dart2wasm/bin/run_wasm.js +++ b/pkg/dart2wasm/bin/run_wasm.js @@ -176,6 +176,9 @@ var dart2wasm = { getTimeZoneOffsetInSeconds: function(secondsSinceEpoch) { return new Date(secondsSinceEpoch * 1000).getTimezoneOffset() * 60; }, + jsonEncode: function(s) { + return stringToDartString(JSON.stringify(stringFromDartString(s))); + }, }; function instantiate(filename, imports) { diff --git a/sdk/lib/_internal/wasm/lib/core_patch.dart b/sdk/lib/_internal/wasm/lib/core_patch.dart index 29fe06c61aa..e8756c9b4ea 100644 --- a/sdk/lib/_internal/wasm/lib/core_patch.dart +++ b/sdk/lib/_internal/wasm/lib/core_patch.dart @@ -15,6 +15,7 @@ import "dart:_internal" EfficientLengthIterable, FixedLengthListMixin, IterableElementError, + jsonEncode, ListIterator, Lists, mix64, @@ -29,6 +30,8 @@ import "dart:_internal" writeIntoOneByteString, writeIntoTwoByteString; +import "dart:_internal" as _internal show Symbol; + import "dart:collection" show HashMap, @@ -50,3 +53,6 @@ import "dart:typed_data" import 'dart:wasm'; typedef _Smi = int; // For compatibility with VM patch files + +String _symbolToString(Symbol s) => + _internal.Symbol.getName(s as _internal.Symbol); diff --git a/sdk/lib/_internal/wasm/lib/errors_patch.dart b/sdk/lib/_internal/wasm/lib/errors_patch.dart index 991d4821572..f1542bd3ec1 100644 --- a/sdk/lib/_internal/wasm/lib/errors_patch.dart +++ b/sdk/lib/_internal/wasm/lib/errors_patch.dart @@ -8,13 +8,12 @@ external Never _throwObjectWithStackTrace(Object error, StackTrace stacktrace); class Error { @patch static String _objectToString(Object object) { - return object.toString(); + return 'Instance of ${object._runtimeType}'; } @patch static String _stringToSafeString(String string) { - // TODO(joshualitt): JSON encode string. - return string; + return jsonEncode(string); } @patch @@ -82,6 +81,71 @@ class _TypeError extends _Error implements TypeError { } } +@patch +class NoSuchMethodError { + final Object? _receiver; + final Symbol _memberName; + final List? _arguments; + final Map? _namedArguments; + final List? _existingArgumentNames; + + @patch + factory NoSuchMethodError.withInvocation( + Object? receiver, Invocation invocation) => + NoSuchMethodError(receiver, invocation.memberName, + invocation.positionalArguments, invocation.namedArguments); + + @patch + NoSuchMethodError(Object? receiver, Symbol memberName, + List? positionalArguments, Map? namedArguments, + [List? existingArgumentNames = null]) + : _receiver = receiver, + _memberName = memberName, + _arguments = positionalArguments, + _namedArguments = namedArguments, + _existingArgumentNames = existingArgumentNames; + + @patch + String toString() { + StringBuffer sb = StringBuffer(''); + String comma = ''; + List? arguments = _arguments; + if (arguments != null) { + for (var argument in arguments) { + sb.write(comma); + sb.write(Error.safeToString(argument)); + comma = ', '; + } + } + Map? namedArguments = _namedArguments; + if (namedArguments != null) { + namedArguments.forEach((Symbol key, var value) { + sb.write(comma); + sb.write(_symbolToString(key)); + sb.write(": "); + sb.write(Error.safeToString(value)); + comma = ', '; + }); + } + String memberName = _symbolToString(_memberName); + String receiverText = Error.safeToString(_receiver); + String actualParameters = '$sb'; + List? existingArgumentNames = _existingArgumentNames; + if (existingArgumentNames == null) { + return "NoSuchMethodError: method not found: '$memberName'\n" + "Receiver: ${receiverText}\n" + "Arguments: [$actualParameters]"; + } else { + String formalParameters = existingArgumentNames.join(', '); + return "NoSuchMethodError: incorrect number of arguments passed to " + "method named '$memberName'\n" + "Receiver: ${receiverText}\n" + "Tried calling: $memberName($actualParameters)\n" + "Found: $memberName($formalParameters)"; + } + } +} + /// Used by Fasta to report a runtime error when a final field with an /// initializer is also initialized in a generative constructor. /// diff --git a/sdk/lib/_internal/wasm/lib/internal_patch.dart b/sdk/lib/_internal/wasm/lib/internal_patch.dart index b6e9a148cc5..a2fd23917ae 100644 --- a/sdk/lib/_internal/wasm/lib/internal_patch.dart +++ b/sdk/lib/_internal/wasm/lib/internal_patch.dart @@ -140,3 +140,6 @@ dynamic _callClosure2(dynamic closure, dynamic arg1, dynamic arg2) { // Schedule a callback from JS via setTimeout. @pragma("wasm:import", "dart2wasm.scheduleCallback") external void scheduleCallback(double millis, dynamic Function() callback); + +@pragma("wasm:import", "dart2wasm.jsonEncode") +external String jsonEncode(String object);