Skip to content

Commit 0246c48

Browse files
osa1Commit Queue
authored andcommitted
[dart2wasm] Check types of JS references when boxing JSValues as non-interop types
To make sure Dart values with typed data types like `Uint8List`, `List`, `String` etc. hold the right type of JS values, check types of JS references in boxing functions that return Dart typed data types. To reflect what the functions actually do, and for consistency with other functions, boxing factory names are changed from `fromJSArray` to `fromRef`. New boxing functions `fromRefUnchecked` added for the call sites that already know the reference type to be the right type, for example in `dartifyRaw`. These unchecked functions will also be used in CL 424021 where we replace some `dartifyRaw` calls with more precise "dartify" functions that only converts when the type is right. (`dartifyRaw` always boxes the argument regardless of the type) Issue: #60357 Change-Id: Icdfb49b9b235d35af2af0c4be51b295ee68d99fc Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/429362 Reviewed-by: Martin Kustermann <[email protected]> Commit-Queue: Ömer Ağacan <[email protected]>
1 parent a2312f4 commit 0246c48

17 files changed

+472
-124
lines changed

sdk/lib/_internal/wasm/lib/boxed_double.dart

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ final class BoxedDouble implements double {
353353
return "Infinity";
354354
}
355355

356-
String result = JSStringImpl(
356+
String result = JSStringImpl.fromRefUnchecked(
357357
JS<WasmExternRef?>(
358358
'Function.prototype.call.bind(Number.prototype.toString)',
359359
WasmF64.fromDouble(value),
@@ -400,7 +400,7 @@ final class BoxedDouble implements double {
400400
return result;
401401
}
402402

403-
String _toStringAsFixed(int fractionDigits) => JSStringImpl(
403+
String _toStringAsFixed(int fractionDigits) => JSStringImpl.fromRefUnchecked(
404404
JS<WasmExternRef>(
405405
"(d, digits) => d.toFixed(digits)",
406406
value,
@@ -434,15 +434,16 @@ final class BoxedDouble implements double {
434434
return result;
435435
}
436436

437-
String _toStringAsExponential(int? fractionDigits) => JSStringImpl(
438-
fractionDigits == null
439-
? JS<WasmExternRef>("d => d.toExponential()", value)
440-
: JS<WasmExternRef>(
441-
"(d, f) => d.toExponential(f)",
442-
value,
443-
fractionDigits.toDouble(),
444-
),
445-
);
437+
String _toStringAsExponential(int? fractionDigits) =>
438+
JSStringImpl.fromRefUnchecked(
439+
fractionDigits == null
440+
? JS<WasmExternRef>("d => d.toExponential()", value)
441+
: JS<WasmExternRef>(
442+
"(d, f) => d.toExponential(f)",
443+
value,
444+
fractionDigits.toDouble(),
445+
),
446+
);
446447

447448
String toStringAsPrecision(int precision) {
448449
// See ECMAScript-262, 15.7.4.7 for details.
@@ -463,13 +464,14 @@ final class BoxedDouble implements double {
463464
return result;
464465
}
465466

466-
String _toStringAsPrecision(int fractionDigits) => JSStringImpl(
467-
JS<WasmExternRef>(
468-
"(d, precision) => d.toPrecision(precision)",
469-
value,
470-
fractionDigits.toDouble(),
471-
),
472-
);
467+
String _toStringAsPrecision(int fractionDigits) =>
468+
JSStringImpl.fromRefUnchecked(
469+
JS<WasmExternRef>(
470+
"(d, precision) => d.toPrecision(precision)",
471+
value,
472+
fractionDigits.toDouble(),
473+
),
474+
);
473475

474476
// Order is: NaN > Infinity > ... > 0.0 > -0.0 > ... > -Infinity.
475477
int compareTo(num other) {

sdk/lib/_internal/wasm/lib/boxed_int_to_string.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,5 @@ String _jsBigIntToString(int i, int radix) {
3535
WasmI64.fromInt(i),
3636
WasmI32.fromInt(radix),
3737
);
38-
return JSStringImpl(result);
38+
return JSStringImpl.fromRefUnchecked(result);
3939
}

sdk/lib/_internal/wasm/lib/date_patch_patch.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class DateTime {
1616

1717
@patch
1818
static String _timeZoneNameForClampedSeconds(int secondsSinceEpoch) =>
19-
JSStringImpl(
19+
JSStringImpl.fromRefUnchecked(
2020
JS<WasmExternRef>(r"""secondsSinceEpoch => {
2121
const date = new Date(secondsSinceEpoch * 1000);
2222
const match = /\((.*)\)/.exec(date.toString());

sdk/lib/_internal/wasm/lib/internal_patch.dart

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -155,12 +155,14 @@ void _invokeMain(WasmExternRef jsArrayRef) {
155155
}
156156
}
157157

158-
String jsonEncode(String object) => JSStringImpl(
159-
JS<WasmExternRef>(
160-
"s => JSON.stringify(s)",
161-
jsStringFromDartString(object).toExternRef,
162-
),
163-
);
158+
String jsonEncode(String object) =>
159+
// Use checked boxing as `JSON.stringify` can be patched by users.
160+
JSStringImpl.fromRef(
161+
JS<WasmExternRef>(
162+
"s => JSON.stringify(s)",
163+
jsStringFromDartString(object).toExternRef,
164+
),
165+
);
164166

165167
/// Whether to check bounds in [IndexErrorUtils.checkIndex],
166168
/// which are used in list and typed data implementations.

sdk/lib/_internal/wasm/lib/js_array.dart

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,27 @@ extension JSArrayImplUncheckedOperations<T extends JSAny?> on JSArrayImpl {
1414
class JSArrayImpl<T extends JSAny?> implements List<T> {
1515
final WasmExternRef? _ref;
1616

17-
JSArrayImpl(this._ref);
17+
static bool _checkRefType(WasmExternRef? ref) =>
18+
js.JS<bool>('o => o instanceof Array', ref);
19+
20+
JSArrayImpl.fromRefUnchecked(this._ref) {
21+
assert(_checkRefType(_ref));
22+
}
23+
24+
factory JSArrayImpl.fromRef(WasmExternRef? ref) {
25+
if (!_checkRefType(ref)) {
26+
throw minify
27+
? ArgumentError()
28+
: ArgumentError("JS reference is not an array");
29+
}
30+
return JSArrayImpl<T>.fromRefUnchecked(ref);
31+
}
1832

1933
factory JSArrayImpl.fromLength(int length) =>
20-
JSArrayImpl<T>(js.newArrayFromLengthRaw(length));
34+
JSArrayImpl<T>.fromRefUnchecked(js.newArrayFromLengthRaw(length));
2135

2236
static JSArrayImpl<T>? box<T extends JSAny?>(WasmExternRef? ref) =>
23-
js.isDartNull(ref) ? null : JSArrayImpl<T>(ref);
37+
js.isDartNull(ref) ? null : JSArrayImpl<T>.fromRefUnchecked(ref);
2438

2539
WasmExternRef? get toExternRef => _ref;
2640

@@ -165,7 +179,7 @@ class JSArrayImpl<T extends JSAny?> implements List<T> {
165179
toExternRef,
166180
separator.toExternRef,
167181
);
168-
return JSStringImpl(result);
182+
return JSStringImpl.fromRefUnchecked(result);
169183
}
170184

171185
@override
@@ -257,7 +271,7 @@ class JSArrayImpl<T extends JSAny?> implements List<T> {
257271
@override
258272
List<T> sublist(int start, [int? end]) {
259273
end = RangeErrorUtils.checkValidRange(start, end, length);
260-
return JSArrayImpl<T>(
274+
return JSArrayImpl<T>.fromRefUnchecked(
261275
js.JS<WasmExternRef?>(
262276
'(a, s, e) => a.slice(s, e)',
263277
toExternRef,
@@ -538,7 +552,7 @@ class JSArrayImpl<T extends JSAny?> implements List<T> {
538552
@override
539553
List<T> operator +(List<T> other) {
540554
if (other is JSArrayImpl) {
541-
return JSArrayImpl<T>(
555+
return JSArrayImpl<T>.fromRefUnchecked(
542556
js.JS<WasmExternRef?>(
543557
'(a, t) => a.concat(t)',
544558
toExternRef,

sdk/lib/_internal/wasm/lib/js_helper.dart

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -259,10 +259,10 @@ WasmExternRef? callMethodVarArgsRaw(
259259
) => JS<WasmExternRef?>("(o, m, a) => o[m].apply(o, a)", o, method, args);
260260

261261
String typeof(WasmExternRef? object) =>
262-
JSStringImpl(JS<WasmExternRef?>("o => typeof o", object));
262+
JSStringImpl.fromRefUnchecked(JS<WasmExternRef?>("o => typeof o", object));
263263

264264
String stringify(WasmExternRef? object) =>
265-
JSStringImpl(JS<WasmExternRef?>("o => String(o)", object));
265+
JSStringImpl.fromRefUnchecked(JS<WasmExternRef?>("o => String(o)", object));
266266

267267
void promiseThen(
268268
WasmExternRef? promise,
@@ -491,20 +491,30 @@ Object? dartifyRaw(WasmExternRef? ref, [int? refType]) {
491491
ExternRefType.null_ || ExternRefType.undefined => null,
492492
ExternRefType.boolean => toDartBool(ref),
493493
ExternRefType.number => toDartNumber(ref),
494-
ExternRefType.string => JSStringImpl.box(ref),
494+
ExternRefType.string => JSStringImpl.fromRefUnchecked(ref),
495495
ExternRefType.array => toDartList(ref),
496-
ExternRefType.int8Array => js_types.JSInt8ArrayImpl.fromJSArray(ref),
497-
ExternRefType.uint8Array => js_types.JSUint8ArrayImpl.fromJSArray(ref),
496+
ExternRefType.int8Array => js_types.JSInt8ArrayImpl.fromRefUnchecked(ref),
497+
ExternRefType.uint8Array => js_types.JSUint8ArrayImpl.fromRefUnchecked(ref),
498498
ExternRefType.uint8ClampedArray =>
499-
js_types.JSUint8ClampedArrayImpl.fromJSArray(ref),
500-
ExternRefType.int16Array => js_types.JSInt16ArrayImpl.fromJSArray(ref),
501-
ExternRefType.uint16Array => js_types.JSUint16ArrayImpl.fromJSArray(ref),
502-
ExternRefType.int32Array => js_types.JSInt32ArrayImpl.fromJSArray(ref),
503-
ExternRefType.uint32Array => js_types.JSUint32ArrayImpl.fromJSArray(ref),
504-
ExternRefType.float32Array => js_types.JSFloat32ArrayImpl.fromJSArray(ref),
505-
ExternRefType.float64Array => js_types.JSFloat64ArrayImpl.fromJSArray(ref),
506-
ExternRefType.arrayBuffer => js_types.JSArrayBufferImpl.fromRef(ref),
507-
ExternRefType.dataView => js_types.JSDataViewImpl.fromRef(ref),
499+
js_types.JSUint8ClampedArrayImpl.fromRefUnchecked(ref),
500+
ExternRefType.int16Array => js_types.JSInt16ArrayImpl.fromRefUnchecked(ref),
501+
ExternRefType.uint16Array => js_types.JSUint16ArrayImpl.fromRefUnchecked(
502+
ref,
503+
),
504+
ExternRefType.int32Array => js_types.JSInt32ArrayImpl.fromRefUnchecked(ref),
505+
ExternRefType.uint32Array => js_types.JSUint32ArrayImpl.fromRefUnchecked(
506+
ref,
507+
),
508+
ExternRefType.float32Array => js_types.JSFloat32ArrayImpl.fromRefUnchecked(
509+
ref,
510+
),
511+
ExternRefType.float64Array => js_types.JSFloat64ArrayImpl.fromRefUnchecked(
512+
ref,
513+
),
514+
ExternRefType.arrayBuffer => js_types.JSArrayBufferImpl.fromRefUnchecked(
515+
ref,
516+
),
517+
ExternRefType.dataView => js_types.JSDataViewImpl.fromRefUnchecked(ref),
508518
ExternRefType.unknown =>
509519
isJSWrappedDartFunction(ref)
510520
? unwrapJSWrappedDartFunction(ref)

sdk/lib/_internal/wasm/lib/js_interop_patch.dart

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ extension ByteDataToJSDataView on ByteData {
279279
@patch
280280
extension JSInt8ArrayToInt8List on JSInt8Array {
281281
@patch
282-
Int8List get toDart => js_types.JSInt8ArrayImpl.fromJSArray(toExternRef);
282+
Int8List get toDart => js_types.JSInt8ArrayImpl.fromRef(toExternRef);
283283
}
284284

285285
@patch
@@ -302,7 +302,7 @@ extension Int8ListToJSInt8Array on Int8List {
302302
@patch
303303
extension JSUint8ArrayToUint8List on JSUint8Array {
304304
@patch
305-
Uint8List get toDart => js_types.JSUint8ArrayImpl.fromJSArray(toExternRef);
305+
Uint8List get toDart => js_types.JSUint8ArrayImpl.fromRef(toExternRef);
306306
}
307307

308308
@patch
@@ -326,7 +326,7 @@ extension Uint8ListToJSUint8Array on Uint8List {
326326
extension JSUint8ClampedArrayToUint8ClampedList on JSUint8ClampedArray {
327327
@patch
328328
Uint8ClampedList get toDart =>
329-
js_types.JSUint8ClampedArrayImpl.fromJSArray(toExternRef);
329+
js_types.JSUint8ClampedArrayImpl.fromRef(toExternRef);
330330
}
331331

332332
@patch
@@ -349,7 +349,7 @@ extension Uint8ClampedListToJSUint8ClampedArray on Uint8ClampedList {
349349
@patch
350350
extension JSInt16ArrayToInt16List on JSInt16Array {
351351
@patch
352-
Int16List get toDart => js_types.JSInt16ArrayImpl.fromJSArray(toExternRef);
352+
Int16List get toDart => js_types.JSInt16ArrayImpl.fromRef(toExternRef);
353353
}
354354

355355
@patch
@@ -372,7 +372,7 @@ extension Int16ListToJSInt16Array on Int16List {
372372
@patch
373373
extension JSUint16ArrayToInt16List on JSUint16Array {
374374
@patch
375-
Uint16List get toDart => js_types.JSUint16ArrayImpl.fromJSArray(toExternRef);
375+
Uint16List get toDart => js_types.JSUint16ArrayImpl.fromRef(toExternRef);
376376
}
377377

378378
@patch
@@ -395,7 +395,7 @@ extension Uint16ListToJSInt16Array on Uint16List {
395395
@patch
396396
extension JSInt32ArrayToInt32List on JSInt32Array {
397397
@patch
398-
Int32List get toDart => js_types.JSInt32ArrayImpl.fromJSArray(toExternRef);
398+
Int32List get toDart => js_types.JSInt32ArrayImpl.fromRef(toExternRef);
399399
}
400400

401401
@patch
@@ -418,7 +418,7 @@ extension Int32ListToJSInt32Array on Int32List {
418418
@patch
419419
extension JSUint32ArrayToUint32List on JSUint32Array {
420420
@patch
421-
Uint32List get toDart => js_types.JSUint32ArrayImpl.fromJSArray(toExternRef);
421+
Uint32List get toDart => js_types.JSUint32ArrayImpl.fromRef(toExternRef);
422422
}
423423

424424
@patch
@@ -441,8 +441,7 @@ extension Uint32ListToJSUint32Array on Uint32List {
441441
@patch
442442
extension JSFloat32ArrayToFloat32List on JSFloat32Array {
443443
@patch
444-
Float32List get toDart =>
445-
js_types.JSFloat32ArrayImpl.fromJSArray(toExternRef);
444+
Float32List get toDart => js_types.JSFloat32ArrayImpl.fromRef(toExternRef);
446445
}
447446

448447
@patch
@@ -465,8 +464,7 @@ extension Float32ListToJSFloat32Array on Float32List {
465464
@patch
466465
extension JSFloat64ArrayToFloat64List on JSFloat64Array {
467466
@patch
468-
Float64List get toDart =>
469-
js_types.JSFloat64ArrayImpl.fromJSArray(toExternRef);
467+
Float64List get toDart => js_types.JSFloat64ArrayImpl.fromRef(toExternRef);
470468
}
471469

472470
@patch
@@ -489,7 +487,7 @@ extension Float64ListToJSFloat64Array on Float64List {
489487
@patch
490488
extension JSArrayToList<T extends JSAny?> on JSArray<T> {
491489
@patch
492-
List<T> get toDart => js_types.JSArrayImpl<T>(toExternRef);
490+
List<T> get toDart => js_types.JSArrayImpl<T>.fromRef(toExternRef);
493491
}
494492

495493
@patch
@@ -554,7 +552,7 @@ extension BoolToJSBoolean on bool {
554552
@patch
555553
extension JSStringToString on JSString {
556554
@patch
557-
String get toDart => JSStringImpl(toExternRef);
555+
String get toDart => JSStringImpl.fromRef(toExternRef);
558556
}
559557

560558
@patch

0 commit comments

Comments
 (0)