mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 00:29:48 +00:00
[dart2wasm] Implement toString
methods on double using JS interop.
Change-Id: I5843e9cae59b8f152b922a01796eaf05494808a0 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/250681 Reviewed-by: Aske Simon Christensen <askesc@google.com> Commit-Queue: Joshua Litt <joshualitt@google.com>
This commit is contained in:
parent
4fcbbb107a
commit
2c4ee2895f
|
@ -270,6 +270,34 @@ var dart2wasm = {
|
|||
}
|
||||
return null;
|
||||
},
|
||||
stringify: function(o) {
|
||||
return stringToDartString(String(o));
|
||||
},
|
||||
doubleToString: function(v) {
|
||||
return stringToDartString(v.toString());
|
||||
},
|
||||
toFixed: function(double, digits) {
|
||||
return stringToDartString(double.toFixed(digits));
|
||||
},
|
||||
toExponential: function(double, fractionDigits) {
|
||||
return stringToDartString(double.toExponential(fractionDigits));
|
||||
},
|
||||
toPrecision: function(double, precision) {
|
||||
return stringToDartString(double.toPrecision(precision));
|
||||
},
|
||||
parseDouble: function(source) {
|
||||
// Notice that JS parseFloat accepts garbage at the end of the string.
|
||||
// Accept only:
|
||||
// - [+/-]NaN
|
||||
// - [+/-]Infinity
|
||||
// - a Dart double literal
|
||||
// We do allow leading or trailing whitespace.
|
||||
var jsSource = stringFromDartString(source);
|
||||
if (!/^\s*[+-]?(?:Infinity|NaN|(?:\.\d+|\d+(?:\.\d*)?)(?:[eE][+-]?\d+)?)\s*$/.test(jsSource)) {
|
||||
return NaN;
|
||||
}
|
||||
return parseFloat(jsSource);
|
||||
},
|
||||
};
|
||||
|
||||
function instantiate(filename, imports) {
|
||||
|
|
|
@ -4,6 +4,49 @@
|
|||
|
||||
// part of "core_patch.dart";
|
||||
|
||||
@pragma("wasm:import", "dart2wasm.doubleToString")
|
||||
external String _doubleToString(double v);
|
||||
|
||||
@pragma("wasm:import", "dart2wasm.toFixed")
|
||||
external String _toFixed(double d, double digits);
|
||||
|
||||
@pragma("wasm:import", "dart2wasm.toExponential")
|
||||
external String _toExponential1(double d);
|
||||
|
||||
@pragma("wasm:import", "dart2wasm.toExponential")
|
||||
external String _toExponential2(double d, double fractionDigits);
|
||||
|
||||
@pragma("wasm:import", "dart2wasm.toPrecision")
|
||||
external String _toPrecision(double d, double precision);
|
||||
|
||||
@pragma("wasm:import", "dart2wasm.parseDouble")
|
||||
external double _parseDouble(String doubleString);
|
||||
|
||||
@patch
|
||||
class double {
|
||||
@patch
|
||||
static double parse(String source,
|
||||
[@deprecated double onError(String source)?]) {
|
||||
double? result = tryParse(source);
|
||||
if (result == null) {
|
||||
throw FormatException('Invalid double $source');
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@patch
|
||||
static double? tryParse(String source) {
|
||||
double result = _parseDouble(source);
|
||||
if (result.isNaN) {
|
||||
String trimmed = source.trim();
|
||||
if (!(trimmed == 'NaN' || trimmed == '+NaN' || trimmed == '-NaN')) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@pragma("wasm:entry-point")
|
||||
class _BoxedDouble implements double {
|
||||
// A boxed double contains an unboxed double.
|
||||
|
@ -142,8 +185,6 @@ class _BoxedDouble implements double {
|
|||
static final List _cache = new List.filled(CACHE_LENGTH, null);
|
||||
static int _cacheEvictIndex = 0;
|
||||
|
||||
external String _toString();
|
||||
|
||||
String toString() {
|
||||
// TODO(koda): Consider starting at most recently inserted.
|
||||
for (int i = 0; i < CACHE_LENGTH; i += 2) {
|
||||
|
@ -156,7 +197,7 @@ class _BoxedDouble implements double {
|
|||
if (identical(0.0, this)) {
|
||||
return "0.0";
|
||||
}
|
||||
String result = _toString();
|
||||
String result = _doubleToString(value);
|
||||
// Replace the least recently inserted entry.
|
||||
_cache[_cacheEvictIndex] = this;
|
||||
_cache[_cacheEvictIndex + 1] = result;
|
||||
|
@ -188,7 +229,8 @@ class _BoxedDouble implements double {
|
|||
return _toStringAsFixed(fractionDigits);
|
||||
}
|
||||
|
||||
external String _toStringAsFixed(int fractionDigits);
|
||||
String _toStringAsFixed(int fractionDigits) =>
|
||||
_toFixed(value, fractionDigits.toDouble());
|
||||
|
||||
String toStringAsExponential([int? fractionDigits]) {
|
||||
// See ECMAScript-262, 15.7.4.6 for details.
|
||||
|
@ -208,14 +250,16 @@ class _BoxedDouble implements double {
|
|||
if (this == double.infinity) return "Infinity";
|
||||
if (this == -double.infinity) return "-Infinity";
|
||||
|
||||
// The dart function prints the shortest representation when fractionDigits
|
||||
// equals null. The native function wants -1 instead.
|
||||
fractionDigits = (fractionDigits == null) ? -1 : fractionDigits;
|
||||
|
||||
return _toStringAsExponential(fractionDigits);
|
||||
}
|
||||
|
||||
external String _toStringAsExponential(int fractionDigits);
|
||||
String _toStringAsExponential(int? fractionDigits) {
|
||||
if (fractionDigits == null) {
|
||||
return _toExponential1(value);
|
||||
} else {
|
||||
return _toExponential2(value, fractionDigits.toDouble());
|
||||
}
|
||||
}
|
||||
|
||||
String toStringAsPrecision(int precision) {
|
||||
// See ECMAScript-262, 15.7.4.7 for details.
|
||||
|
@ -236,7 +280,8 @@ class _BoxedDouble implements double {
|
|||
return _toStringAsPrecision(precision);
|
||||
}
|
||||
|
||||
external String _toStringAsPrecision(int fractionDigits);
|
||||
String _toStringAsPrecision(int fractionDigits) =>
|
||||
_toPrecision(value, fractionDigits.toDouble());
|
||||
|
||||
// Order is: NaN > Infinity > ... > 0.0 > -0.0 > ... > -Infinity.
|
||||
int compareTo(num other) {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
// Helpers for working with JS.
|
||||
library dart.js_helper;
|
||||
library dart._js_helper;
|
||||
|
||||
import 'dart:_internal';
|
||||
import 'dart:typed_data';
|
||||
|
@ -23,6 +23,11 @@ class JSValue {
|
|||
Object toObject() => jsObjectToDartObject(_ref);
|
||||
}
|
||||
|
||||
extension DoubleToJS on double {
|
||||
WasmAnyRef toAnyRef() => toJSNumber(this);
|
||||
JSValue toJS() => JSValue(toAnyRef());
|
||||
}
|
||||
|
||||
extension StringToJS on String {
|
||||
WasmAnyRef toAnyRef() => jsStringFromDartString(this);
|
||||
JSValue toJS() => JSValue(toAnyRef());
|
||||
|
@ -108,6 +113,9 @@ external bool isJSWrappedDartFunction(WasmAnyRef? o);
|
|||
@pragma("wasm:import", "dart2wasm.isJSObject")
|
||||
external bool isJSObject(WasmAnyRef? o);
|
||||
|
||||
// The JS runtime will run helpful conversion routines between refs and bool /
|
||||
// double. In the longer term hopefully we can find a way to avoid the round
|
||||
// trip.
|
||||
@pragma("wasm:import", "dart2wasm.roundtrip")
|
||||
external double toDartNumber(WasmAnyRef ref);
|
||||
|
||||
|
@ -193,6 +201,9 @@ external WasmAnyRef? setPropertyRaw(
|
|||
external WasmAnyRef? callMethodVarArgsRaw(
|
||||
WasmAnyRef o, WasmAnyRef method, WasmAnyRef? args);
|
||||
|
||||
@pragma("wasm:import", "dart2wasm.stringify")
|
||||
external String stringifyRaw(WasmAnyRef? object);
|
||||
|
||||
// Currently, `allowInterop` returns a Function type. This is unfortunate for
|
||||
// Dart2wasm because it means arbitrary Dart functions can flow to JS util
|
||||
// calls. Our only solutions is to cache every function called with
|
||||
|
|
Loading…
Reference in a new issue