Skip to content

Commit

Permalink
Version 3.3.0-177.0.dev
Browse files Browse the repository at this point in the history
Merge 3f3e426 into dev
  • Loading branch information
Dart CI committed Dec 1, 2023
2 parents 2816724 + 3f3e426 commit 7a45cad
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 62 deletions.
1 change: 1 addition & 0 deletions pkg/dart2wasm/lib/js/runtime_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ JSMethods _performJSInteropTransformations(
InterfaceType(jsValueClass, staticInteropType.declaredNullability),
additionalCoreLibraries: {
'_js_helper',
'_js_string_convert',
'_js_types',
'convert',
'js_interop',
Expand Down
13 changes: 9 additions & 4 deletions sdk/lib/_internal/wasm/lib/convert_patch.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// BSD-style license that can be found in the LICENSE file.

import "dart:_internal" show patch, POWERS_OF_TEN, unsafeCast;
import "dart:_js_string_convert";
import "dart:_js_types";
import "dart:_string";
import "dart:_typed_data";
import "dart:typed_data" show Uint8List, Uint16List;
Expand Down Expand Up @@ -1671,16 +1673,19 @@ class _Utf8Decoder {
int end = RangeError.checkValidRange(start, maybeEnd, codeUnits.length);
if (start == end) return "";

if (codeUnits is JSUint8ArrayImpl) {
JSStringImpl? decoded =
decodeUtf8JS(codeUnits, start, end, allowMalformed);
if (decoded != null) return decoded;
}

final U8List bytes;
if (codeUnits is U8List) {
bytes = unsafeCast<U8List>(codeUnits);
} else {
// TODO(omersa): Check if `codeUnits` is a JS array and call browser UTF8
// decoder here.
//
// If we're passed a `List<int>` other than `U8List` or a JS typed array,
// it means the performance is not too important. Convert the input to
// `U8List` to avoid shipping another UTF-8 decoder.
// `U8List` to avoid shipping another UTF-8 decoder for `List<int>`.
final length = end - start;
bytes = U8List(length);
final u8listData = bytes.data;
Expand Down
72 changes: 72 additions & 0 deletions sdk/lib/_internal/wasm/lib/js_string_convert.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright (c) 2023, 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.

/// `dart:convert` UTF-8 decoding functions when the input is a JS typed array.
library dart._js_string_convert;

import "dart:_js_types";
import 'dart:_js_helper' as js;
import 'dart:_wasm';

/// Implements `_Utf8Decoder.convertSingle` hook for JS array inputs. Does not
/// do bounds checking.
JSStringImpl? decodeUtf8JS(
JSUint8ArrayImpl codeUnits, int start, int end, bool allowMalformed) {
final length = end - start;
if (length >= _shortInputThreshold) {
final JSAny? decoder = allowMalformed ? _decoderNonFatal : _decoder;
if (decoder != null) {
final arrayRef = codeUnits.toJSArrayExternRef(start, length);
final textDecoderResult =
_useTextDecoder(externRefForJSAny(decoder), arrayRef);
if (textDecoderResult != null) {
return textDecoderResult;
}
}
}
return null;
}

// Always fall back to the Dart implementation for strings shorter than this
// threshold, as there is a large, constant overhead for using `TextDecoder`.
// TODO(omersa): This is copied from dart2js runtime, make sure the value is
// right for dart2wasm.
const int _shortInputThreshold = 15;

JSStringImpl? _useTextDecoder(
WasmExternRef? decoder, WasmExternRef? codeUnits) {
// If the input is malformed, catch the exception and return `null` to fall
// back on unintercepted decoder. The fallback will either succeed in
// decoding, or report the problem better than `TextDecoder`.
try {
return JSStringImpl(js.JS<WasmExternRef?>(
'(decoder, codeUnits) => decoder.decode(codeUnits)',
decoder,
codeUnits));
} catch (e) {}
return null;
}

// TextDecoder is not defined on some browsers and on the stand-alone d8 and
// jsshell engines. Use a lazy initializer to do feature detection once.
//
// Globals need to return boxed Dart values, so these return `JSAny?` instead
// of `WasmExternRef?`.
final JSAny? _decoder = () {
try {
return js
.JS<WasmExternRef>('() => new TextDecoder("utf-8", {fatal: true})')
.toJS;
} catch (e) {}
return null;
}();

final JSAny? _decoderNonFatal = () {
try {
return js
.JS<WasmExternRef>('() => new TextDecoder("utf-8", {fatal: false})')
.toJS;
} catch (e) {}
return null;
}();
62 changes: 5 additions & 57 deletions sdk/lib/_internal/wasm_js_compatibility/lib/convert_patch.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
// BSD-style license that can be found in the LICENSE file.

import "dart:_internal" show ClassID, patch, POWERS_OF_TEN, unsafeCast;
import "dart:_js_string_convert";
import "dart:_js_types";
import 'dart:_wasm';
import 'dart:_js_helper' as js;
import 'dart:_wasm';

import "dart:typed_data" show Uint8List, Uint16List;

Expand Down Expand Up @@ -1480,32 +1481,16 @@ class _Utf8Decoder {
@patch
_Utf8Decoder(this.allowMalformed) : _state = beforeBom;

// Always fall back to the Dart implementation for strings shorter than this
// threshold, as there is a large, constant overhead for using TextDecoder.
// TODO(omersa): This is copied from dart2js runtime, make sure the value is
// right for dart2wasm.
static const int _shortInputThreshold = 15;

@patch
String convertSingle(List<int> codeUnits, int start, int? maybeEnd) {
final codeUnitsLength = codeUnits.length;
final end = RangeError.checkValidRange(start, maybeEnd, codeUnitsLength);
if (start == end) return "";

final length = end - start;

if (codeUnits is JSUint8ArrayImpl) {
if (length >= _shortInputThreshold) {
final JSAny? decoder = allowMalformed ? _decoderNonFatal : _decoder;
if (decoder != null) {
final arrayRef = codeUnits.toJSArrayExternRef(start, length);
final textDecoderResult =
_useTextDecoder(externRefForJSAny(decoder), arrayRef);
if (textDecoderResult != null) {
return textDecoderResult;
}
}
}
JSStringImpl? decoded =
decodeUtf8JS(codeUnits, start, end, allowMalformed);
if (decoded != null) return decoded;
}

return convertGeneral(codeUnits, start, maybeEnd, true);
Expand All @@ -1515,43 +1500,6 @@ class _Utf8Decoder {
String convertChunked(List<int> codeUnits, int start, int? maybeEnd) {
return convertGeneral(codeUnits, start, maybeEnd, false);
}

static String? _useTextDecoder(
WasmExternRef? decoder, WasmExternRef? codeUnits) {
// If the input is malformed, catch the exception and return `null` to fall
// back on unintercepted decoder. The fallback will either succeed in
// decoding, or report the problem better than TextDecoder.
try {
return JSStringImpl(js.JS<WasmExternRef?>(
'(decoder, codeUnits) => decoder.decode(codeUnits)',
decoder,
codeUnits));
} catch (e) {}
return null;
}

// TextDecoder is not defined on some browsers and on the stand-alone d8 and
// jsshell engines. Use a lazy initializer to do feature detection once.
//
// Globls need to return boxed Dart values, so these return `JSAny?` instead
// of `WasmExternRef?`.
static final JSAny? _decoder = () {
try {
return js
.JS<WasmExternRef>('() => new TextDecoder("utf-8", {fatal: true})')
.toJS;
} catch (e) {}
return null;
}();

static final JSAny? _decoderNonFatal = () {
try {
return js
.JS<WasmExternRef>('() => new TextDecoder("utf-8", {fatal: false})')
.toJS;
} catch (e) {}
return null;
}();
}

double _parseDouble(String source, int start, int end) =>
Expand Down
3 changes: 3 additions & 0 deletions sdk/lib/libraries.json
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,9 @@
"_js_helper": {
"uri": "_internal/wasm/lib/js_helper.dart"
},
"_js_string_convert": {
"uri": "_internal/wasm/lib/js_string_convert.dart"
},
"_js_types": {
"uri": "_internal/wasm/lib/js_types.dart"
},
Expand Down
2 changes: 2 additions & 0 deletions sdk/lib/libraries.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ wasm_common:
uri: js/_js_annotations.dart
_js_helper:
uri: _internal/wasm/lib/js_helper.dart
_js_string_convert:
uri: _internal/wasm/lib/js_string_convert.dart
_js_types:
uri: _internal/wasm/lib/js_types.dart
_object_helper:
Expand Down
2 changes: 1 addition & 1 deletion tools/VERSION
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ CHANNEL dev
MAJOR 3
MINOR 3
PATCH 0
PRERELEASE 176
PRERELEASE 177
PRERELEASE_PATCH 0

0 comments on commit 7a45cad

Please sign in to comment.