[dart2wasm] Fix int.parse(<str>) for when <str> is a JSString

The `int.parse()` function would - if radix is provided and not 10 - use
functions that `unsafeCast<StringBase>()`.

=> The string can be a JSString.

Issue https://github.com/dart-lang/sdk/issues/54800

CoreLibraryReviewExempt: Adding test that should pass on all backends.
Change-Id: Ie6efa5bc545cadce5ea946e2c1d732b2cf94e306
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/350303
Reviewed-by: Slava Egorov <vegorov@google.com>
Commit-Queue: Martin Kustermann <kustermann@google.com>
This commit is contained in:
Martin Kustermann 2024-02-05 22:38:18 +00:00 committed by Commit Queue
parent 7e8ba2a708
commit 1c5e12c212
3 changed files with 30 additions and 4 deletions

View file

@ -4,6 +4,7 @@
import "dart:_internal" show has63BitSmis, patch, unsafeCast;
import "dart:_string" show StringBase;
import "dart:_js_types" show JSStringImpl;
import "dart:typed_data" show Int64List;
@ -51,11 +52,11 @@ class int {
throw RangeError("Radix $radix not in range 2..36");
}
// Split here so improve odds of parse being inlined and the checks omitted.
return _parse(unsafeCast<StringBase>(source), radix, onError) as int;
return _parse(source, radix, onError) as int;
}
static int? _parse(
StringBase source, int? radix, int? Function(String)? onError) {
String source, int? radix, int? Function(String)? onError) {
int end = source.lastNonWhitespace() + 1;
if (end == 0) {
return _handleFormatError(onError, source, source.length, radix, null);
@ -94,7 +95,6 @@ class int {
@patch
static int? tryParse(String source, {int? radix}) {
if (source == null) throw ArgumentError("The source must not be null");
if (source.isEmpty) return null;
if (radix == null || radix == 10) {
// Try parsing immediately, without trimming whitespace.
@ -103,7 +103,7 @@ class int {
} else if (radix < 2 || radix > 36) {
throw RangeError("Radix $radix not in range 2..36");
}
return _parse(unsafeCast<StringBase>(source), radix, _kNull);
return _parse(source, radix, _kNull);
}
static Null _kNull(_) => null;

View file

@ -4,6 +4,7 @@
import "dart:_internal" show patch;
import "dart:_string";
import "dart:_js_types" show JSStringImpl;
@patch
class String {
@ -50,3 +51,17 @@ class String {
external const factory String.fromEnvironment(String name,
{String defaultValue = ""});
}
extension _StringExt on String {
int firstNonWhitespace() {
final value = this;
if (value is StringBase) return value.firstNonWhitespace();
return (value as JSStringImpl).firstNonWhitespace();
}
int lastNonWhitespace() {
final value = this;
if (value is StringBase) return value.lastNonWhitespace();
return (value as JSStringImpl).lastNonWhitespace();
}
}

View file

@ -0,0 +1,11 @@
// Copyright (c) 2024, 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.
import 'package:expect/expect.dart';
void main() {
final match = RegExp(r' ([0-9]+) ').allMatches(' 1234 ').single;
print(match[1]!.runtimeType);
Expect.equals(0x1234, int.parse(match[1]!, radix: 16));
}