Skip to content

Commit 9eea7a3

Browse files
osa1Commit Queue
authored andcommitted
[dart2wasm] Fix ByteData.elementSizeInBytes, ByteData to JS convs
Bug: #61515 Change-Id: I54821b61f310e084affbc4dfbe00c97573ebebfa Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/449901 Commit-Queue: Ömer Ağacan <[email protected]> Reviewed-by: Martin Kustermann <[email protected]>
1 parent ef73551 commit 9eea7a3

File tree

5 files changed

+188
-43
lines changed

5 files changed

+188
-43
lines changed

sdk/lib/_internal/wasm/lib/js_helper_patch.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ WasmExternRef jsDataViewFromDartByteData(ByteData l, int length) {
440440
length,
441441
);
442442
} else {
443-
jsArray.toDart.setRange(0, length, Uint8List.sublistView(l, length));
443+
jsArray.toDart.setRange(0, length, Uint8List.sublistView(l, 0, length));
444444
}
445445

446446
return (JSDataView(jsArrayBuffer, 0, length) as JSValue).toExternRef!;

sdk/lib/_internal/wasm/lib/typed_data.dart

Lines changed: 37 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ abstract class ByteDataBase extends WasmTypedDataBase implements ByteData {
110110
);
111111
}
112112

113+
@override
114+
int get elementSizeInBytes => 1;
115+
113116
@override
114117
int getInt8(int byteOffset) {
115118
_offsetRangeCheck(byteOffset, 1);
@@ -509,9 +512,6 @@ class I8ByteData extends ByteDataBase {
509512
@pragma('wasm:prefer-inline')
510513
_I8ByteBuffer get buffer => _I8ByteBuffer(_data);
511514

512-
@override
513-
int get elementSizeInBytes => Int8List.bytesPerElement;
514-
515515
@override
516516
int _getUint8Unchecked(int byteOffset) {
517517
return _data.readUnsigned(offsetInBytes + byteOffset);
@@ -529,6 +529,8 @@ extension WasmI8ByteDataExt on I8ByteData {
529529
}
530530

531531
class _I16ByteData extends ByteDataBase {
532+
static const int bytesPerElement = 2;
533+
532534
final WasmArray<WasmI16> _data;
533535

534536
_I16ByteData._(this._data, int offsetInBytes, int lengthInBytes)
@@ -551,20 +553,17 @@ class _I16ByteData extends ByteDataBase {
551553
@pragma('wasm:prefer-inline')
552554
_I16ByteBuffer get buffer => _I16ByteBuffer(_data);
553555

554-
@override
555-
int get elementSizeInBytes => Int16List.bytesPerElement;
556-
557556
@override
558557
int _getUint8Unchecked(int byteOffset) {
559558
byteOffset += offsetInBytes;
560-
final byteIndex = byteOffset ~/ elementSizeInBytes;
559+
final byteIndex = byteOffset ~/ bytesPerElement;
561560
return (_data.readUnsigned(byteIndex) >> (8 * (byteOffset & 1))) & 0xFF;
562561
}
563562

564563
@override
565564
void _setUint8Unchecked(int byteOffset, int value) {
566565
byteOffset += offsetInBytes;
567-
final byteIndex = byteOffset ~/ elementSizeInBytes;
566+
final byteIndex = byteOffset ~/ bytesPerElement;
568567
final element = _data.readUnsigned(byteIndex);
569568
final byteElementIndex = byteOffset & 1;
570569
final b1 = byteElementIndex == 0 ? value : (element & 0xFF);
@@ -577,7 +576,7 @@ class _I16ByteData extends ByteDataBase {
577576
int _getUint16Unchecked(int byteOffset, [Endian endian = Endian.big]) {
578577
final totalOffset = offsetInBytes + byteOffset;
579578
if (totalOffset & 1 == 0 && endian == Endian.little) {
580-
return _data.readUnsigned(totalOffset ~/ elementSizeInBytes);
579+
return _data.readUnsigned(totalOffset ~/ bytesPerElement);
581580
} else {
582581
return super._getUint16Unchecked(byteOffset, endian);
583582
}
@@ -591,14 +590,16 @@ class _I16ByteData extends ByteDataBase {
591590
]) {
592591
final totalOffset = offsetInBytes + byteOffset;
593592
if (totalOffset & 1 == 0 && endian == Endian.little) {
594-
_data.write(totalOffset ~/ elementSizeInBytes, value);
593+
_data.write(totalOffset ~/ bytesPerElement, value);
595594
} else {
596595
super._setUint16Unchecked(byteOffset, value, endian);
597596
}
598597
}
599598
}
600599

601600
class _I32ByteData extends ByteDataBase {
601+
static const int bytesPerElement = 4;
602+
602603
final WasmArray<WasmI32> _data;
603604

604605
_I32ByteData._(this._data, int offsetInBytes, int lengthInBytes)
@@ -621,20 +622,17 @@ class _I32ByteData extends ByteDataBase {
621622
@pragma('wasm:prefer-inline')
622623
_I32ByteBuffer get buffer => _I32ByteBuffer(_data);
623624

624-
@override
625-
int get elementSizeInBytes => Int32List.bytesPerElement;
626-
627625
@override
628626
int _getUint8Unchecked(int byteOffset) {
629627
byteOffset += offsetInBytes;
630-
final byteIndex = byteOffset ~/ elementSizeInBytes;
628+
final byteIndex = byteOffset ~/ bytesPerElement;
631629
return (_data.readUnsigned(byteIndex) >> (8 * (byteOffset & 3))) & 0xFF;
632630
}
633631

634632
@override
635633
void _setUint8Unchecked(int byteOffset, int value) {
636634
byteOffset += offsetInBytes;
637-
final byteIndex = byteOffset ~/ elementSizeInBytes;
635+
final byteIndex = byteOffset ~/ bytesPerElement;
638636
final element = _data.readUnsigned(byteIndex);
639637
final byteElementIndex = byteOffset & 3;
640638
final b1 = byteElementIndex == 0 ? value : (element & 0xFF);
@@ -649,7 +647,7 @@ class _I32ByteData extends ByteDataBase {
649647
int _getInt32Unchecked(int byteOffset, [Endian endian = Endian.big]) {
650648
final totalOffset = offsetInBytes + byteOffset;
651649
if (totalOffset & 3 == 0 && endian == Endian.little) {
652-
return _data.readSigned(totalOffset ~/ elementSizeInBytes);
650+
return _data.readSigned(totalOffset ~/ bytesPerElement);
653651
} else {
654652
return super._getInt32Unchecked(byteOffset, endian);
655653
}
@@ -659,7 +657,7 @@ class _I32ByteData extends ByteDataBase {
659657
int _getUint32Unchecked(int byteOffset, [Endian endian = Endian.big]) {
660658
final totalOffset = offsetInBytes + byteOffset;
661659
if (totalOffset & 3 == 0 && endian == Endian.little) {
662-
return _data.readUnsigned(totalOffset ~/ elementSizeInBytes);
660+
return _data.readUnsigned(totalOffset ~/ bytesPerElement);
663661
} else {
664662
return super._getUint32Unchecked(byteOffset, endian);
665663
}
@@ -673,7 +671,7 @@ class _I32ByteData extends ByteDataBase {
673671
]) {
674672
final totalOffset = offsetInBytes + byteOffset;
675673
if (totalOffset & 3 == 0 && endian == Endian.little) {
676-
_data.write(totalOffset ~/ elementSizeInBytes, value.toUnsigned(32));
674+
_data.write(totalOffset ~/ bytesPerElement, value.toUnsigned(32));
677675
} else {
678676
super._setInt32Unchecked(byteOffset, value, endian);
679677
}
@@ -687,14 +685,16 @@ class _I32ByteData extends ByteDataBase {
687685
]) {
688686
final totalOffset = offsetInBytes + byteOffset;
689687
if (totalOffset & 3 == 0 && endian == Endian.little) {
690-
_data.write(totalOffset ~/ elementSizeInBytes, value);
688+
_data.write(totalOffset ~/ bytesPerElement, value);
691689
} else {
692690
super._setUint32Unchecked(byteOffset, value, endian);
693691
}
694692
}
695693
}
696694

697695
class _I64ByteData extends ByteDataBase {
696+
static const int bytesPerElement = 8;
697+
698698
final WasmArray<WasmI64> _data;
699699

700700
_I64ByteData._(this._data, int offsetInBytes, int lengthInBytes)
@@ -717,20 +717,17 @@ class _I64ByteData extends ByteDataBase {
717717
@pragma('wasm:prefer-inline')
718718
_I64ByteBuffer get buffer => _I64ByteBuffer(_data);
719719

720-
@override
721-
int get elementSizeInBytes => Int64List.bytesPerElement;
722-
723720
@override
724721
int _getUint8Unchecked(int byteOffset) {
725722
byteOffset += offsetInBytes;
726-
final byteIndex = byteOffset ~/ elementSizeInBytes;
723+
final byteIndex = byteOffset ~/ bytesPerElement;
727724
return (_data.read(byteIndex) >> (8 * (byteOffset & 7))) & 0xFF;
728725
}
729726

730727
@override
731728
void _setUint8Unchecked(int byteOffset, int value) {
732729
byteOffset += offsetInBytes;
733-
final byteIndex = byteOffset ~/ elementSizeInBytes;
730+
final byteIndex = byteOffset ~/ bytesPerElement;
734731
final element = _data.read(byteIndex);
735732
final byteElementIndex = byteOffset & 7;
736733
final b1 = byteElementIndex == 0 ? value : (element & 0xFF);
@@ -757,7 +754,7 @@ class _I64ByteData extends ByteDataBase {
757754
int _getInt64Unchecked(int byteOffset, [Endian endian = Endian.big]) {
758755
final totalOffset = offsetInBytes + byteOffset;
759756
if (totalOffset & 7 == 0 && endian == Endian.little) {
760-
return _data.read(totalOffset ~/ elementSizeInBytes);
757+
return _data.read(totalOffset ~/ bytesPerElement);
761758
} else {
762759
return super._getInt64Unchecked(byteOffset, endian);
763760
}
@@ -767,7 +764,7 @@ class _I64ByteData extends ByteDataBase {
767764
int _getUint64Unchecked(int byteOffset, [Endian endian = Endian.big]) {
768765
final totalOffset = offsetInBytes + byteOffset;
769766
if (totalOffset & 7 == 0 && endian == Endian.little) {
770-
return _data.read(totalOffset ~/ elementSizeInBytes);
767+
return _data.read(totalOffset ~/ bytesPerElement);
771768
} else {
772769
return super._getUint64Unchecked(byteOffset, endian);
773770
}
@@ -781,7 +778,7 @@ class _I64ByteData extends ByteDataBase {
781778
]) {
782779
final totalOffset = offsetInBytes + byteOffset;
783780
if (totalOffset & 7 == 0 && endian == Endian.little) {
784-
_data.write(totalOffset ~/ elementSizeInBytes, value);
781+
_data.write(totalOffset ~/ bytesPerElement, value);
785782
} else {
786783
super._setInt64Unchecked(byteOffset, value, endian);
787784
}
@@ -795,14 +792,16 @@ class _I64ByteData extends ByteDataBase {
795792
]) {
796793
final totalOffset = offsetInBytes + byteOffset;
797794
if (totalOffset & 7 == 0 && endian == Endian.little) {
798-
_data.write(totalOffset ~/ elementSizeInBytes, value);
795+
_data.write(totalOffset ~/ bytesPerElement, value);
799796
} else {
800797
super._setUint64Unchecked(byteOffset, value, endian);
801798
}
802799
}
803800
}
804801

805802
class _F32ByteData extends ByteDataBase {
803+
static const int bytesPerElement = 4;
804+
806805
final WasmArray<WasmF32> _data;
807806

808807
_F32ByteData._(this._data, int offsetInBytes, int lengthInBytes)
@@ -825,21 +824,18 @@ class _F32ByteData extends ByteDataBase {
825824
@pragma('wasm:prefer-inline')
826825
_F32ByteBuffer get buffer => _F32ByteBuffer(_data);
827826

828-
@override
829-
int get elementSizeInBytes => Float32List.bytesPerElement;
830-
831827
@override
832828
int _getUint8Unchecked(int byteOffset) {
833829
byteOffset += offsetInBytes;
834-
final byteIndex = byteOffset ~/ elementSizeInBytes;
830+
final byteIndex = byteOffset ~/ bytesPerElement;
835831
final word = floatToIntBits(_data.read(byteIndex));
836832
return (word >> (8 * (byteOffset & 3))) & 0xFF;
837833
}
838834

839835
@override
840836
void _setUint8Unchecked(int byteOffset, int value) {
841837
byteOffset += offsetInBytes;
842-
final byteIndex = byteOffset ~/ elementSizeInBytes;
838+
final byteIndex = byteOffset ~/ bytesPerElement;
843839
final element = floatToIntBits(_data.read(byteIndex));
844840
final byteElementIndex = byteOffset & 3;
845841
final b1 = byteElementIndex == 0 ? value : (element & 0xFF);
@@ -854,7 +850,7 @@ class _F32ByteData extends ByteDataBase {
854850
double _getFloat32Unchecked(int byteOffset, [Endian endian = Endian.big]) {
855851
final totalOffset = offsetInBytes + byteOffset;
856852
if (totalOffset & 3 == 0 && endian == Endian.little) {
857-
return _data.read(totalOffset ~/ elementSizeInBytes);
853+
return _data.read(totalOffset ~/ bytesPerElement);
858854
} else {
859855
return super._getFloat32Unchecked(byteOffset, endian);
860856
}
@@ -868,14 +864,16 @@ class _F32ByteData extends ByteDataBase {
868864
]) {
869865
final totalOffset = offsetInBytes + byteOffset;
870866
if (totalOffset & 3 == 0 && endian == Endian.little) {
871-
_data.write(totalOffset ~/ elementSizeInBytes, value);
867+
_data.write(totalOffset ~/ bytesPerElement, value);
872868
} else {
873869
super._setFloat32Unchecked(byteOffset, value, endian);
874870
}
875871
}
876872
}
877873

878874
class _F64ByteData extends ByteDataBase {
875+
static const int bytesPerElement = 8;
876+
879877
final WasmArray<WasmF64> _data;
880878

881879
_F64ByteData._(this._data, int offsetInBytes, int lengthInBytes)
@@ -898,21 +896,18 @@ class _F64ByteData extends ByteDataBase {
898896
@pragma('wasm:prefer-inline')
899897
_F64ByteBuffer get buffer => _F64ByteBuffer(_data);
900898

901-
@override
902-
int get elementSizeInBytes => Float64List.bytesPerElement;
903-
904899
@override
905900
int _getUint8Unchecked(int byteOffset) {
906901
byteOffset += offsetInBytes;
907-
final byteIndex = byteOffset ~/ elementSizeInBytes;
902+
final byteIndex = byteOffset ~/ bytesPerElement;
908903
final word = doubleToIntBits(_data.read(byteIndex));
909904
return (word >> (8 * (byteOffset & 7))) & 0xFF;
910905
}
911906

912907
@override
913908
void _setUint8Unchecked(int byteOffset, int value) {
914909
byteOffset += offsetInBytes;
915-
final byteIndex = byteOffset ~/ elementSizeInBytes;
910+
final byteIndex = byteOffset ~/ bytesPerElement;
916911
final element = doubleToIntBits(_data.read(byteIndex));
917912
final byteElementIndex = byteOffset & 7;
918913
final b1 = byteElementIndex == 0 ? value : (element & 0xFF);
@@ -939,7 +934,7 @@ class _F64ByteData extends ByteDataBase {
939934
double _getFloat64Unchecked(int byteOffset, [Endian endian = Endian.big]) {
940935
final totalOffset = offsetInBytes + byteOffset;
941936
if (totalOffset & 7 == 0 && endian == Endian.little) {
942-
return _data.read(totalOffset ~/ elementSizeInBytes);
937+
return _data.read(totalOffset ~/ bytesPerElement);
943938
} else {
944939
return super._getFloat64Unchecked(byteOffset, endian);
945940
}
@@ -953,7 +948,7 @@ class _F64ByteData extends ByteDataBase {
953948
]) {
954949
final totalOffset = offsetInBytes + byteOffset;
955950
if (totalOffset & 7 == 0 && endian == Endian.little) {
956-
_data.write(totalOffset ~/ elementSizeInBytes, value);
951+
_data.write(totalOffset ~/ bytesPerElement, value);
957952
} else {
958953
super._setFloat64Unchecked(byteOffset, value, endian);
959954
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'dart:js_interop';
6+
import 'dart:typed_data';
7+
8+
import 'package:expect/expect.dart';
9+
10+
const bool isJS = identical(1, 1.0);
11+
12+
main() {
13+
checkBytes(Int8List.fromList, [42]);
14+
checkBytes(Uint8List.fromList, [42]);
15+
checkBytes(Uint8ClampedList.fromList, [42]);
16+
checkBytes(Int16List.fromList, [42, 0]);
17+
checkBytes(Uint16List.fromList, [42, 0]);
18+
checkBytes(Int32List.fromList, [42, 0, 0, 0]);
19+
checkBytes(Uint32List.fromList, [42, 0, 0, 0]);
20+
if (!isJS) {
21+
checkBytes(Int64List.fromList, [42, 0, 0, 0, 0, 0, 0, 0]);
22+
checkBytes(Uint64List.fromList, [42, 0, 0, 0, 0, 0, 0, 0]);
23+
}
24+
}
25+
26+
void checkBytes(dynamic Function(List<int>) makeList, List<int> expected) {
27+
ByteBuffer buffer = makeList([42]).buffer;
28+
Expect.listEquals(expected, buffer.toJS.toDart.asUint8List());
29+
}

0 commit comments

Comments
 (0)