diff --git a/pkg/dart2wasm/lib/kernel_nodes.dart b/pkg/dart2wasm/lib/kernel_nodes.dart index 2e50bf292114..b31229f4b890 100644 --- a/pkg/dart2wasm/lib/kernel_nodes.dart +++ b/pkg/dart2wasm/lib/kernel_nodes.dart @@ -294,6 +294,8 @@ mixin KernelNodes { index.getTopLevelProcedure("dart:core", "_getMasqueradedRuntimeType"); late final Procedure isSubtype = index.getTopLevelProcedure("dart:core", "_isSubtype"); + late final Procedure asSubtype = + index.getTopLevelProcedure("dart:core", "_asSubtype"); late final Procedure isTypeSubtype = index.getTopLevelProcedure("dart:core", "_isTypeSubtype"); late final Procedure verifyOptimizedTypeCheck = diff --git a/pkg/dart2wasm/lib/types.dart b/pkg/dart2wasm/lib/types.dart index 630377ea48a7..f82979ef12f3 100644 --- a/pkg/dart2wasm/lib/types.dart +++ b/pkg/dart2wasm/lib/types.dart @@ -426,16 +426,12 @@ class Types { w.Local operand = b.addLocal(boxedOperandType, isParameter: false); b.local_tee(operand); - w.Label asCheckBlock = b.block(); - b.local_get(operand); - emitIsTest(codeGen, testedAgainstType, operandType, location); - b.br_if(asCheckBlock); - b.local_get(operand); makeType(codeGen, testedAgainstType); - codeGen.call(translator.stackTraceCurrent.reference); - codeGen.call(translator.throwAsCheckError.reference); - b.unreachable(); - b.end(); + final outputs = codeGen.call(translator.asSubtype.reference); + for (final _ in outputs) { + b.drop(); + } + b.local_get(operand); return operand.type; } @@ -594,8 +590,6 @@ class Types { b.local_get(b.locals[0]); translator.constants.instantiateConstant(function, b, TypeLiteralConstant(testedAgainstType), nonNullableTypeType); - b.call(translator.functions - .getFunction(translator.stackTraceCurrent.reference)); b.call(translator.functions .getFunction(translator.throwAsCheckError.reference)); b.unreachable(); diff --git a/sdk/lib/_internal/wasm/lib/errors_patch.dart b/sdk/lib/_internal/wasm/lib/errors_patch.dart index 7d34fdcee3b3..551047daa5ea 100644 --- a/sdk/lib/_internal/wasm/lib/errors_patch.dart +++ b/sdk/lib/_internal/wasm/lib/errors_patch.dart @@ -65,8 +65,8 @@ class _TypeError extends _Error implements TypeError { } @pragma("wasm:entry-point") - static Never _throwAsCheckError( - Object? operand, Type? type, StackTrace stackTrace) { + static Never _throwAsCheckError(Object? operand, Type? type) { + final stackTrace = StackTrace.current; final typeError = _TypeError.fromMessageAndStackTrace( "Type '${operand.runtimeType}' is not a subtype of type '$type'" " in type cast", diff --git a/sdk/lib/_internal/wasm/lib/type.dart b/sdk/lib/_internal/wasm/lib/type.dart index ed055830355e..c47a31428417 100644 --- a/sdk/lib/_internal/wasm/lib/type.dart +++ b/sdk/lib/_internal/wasm/lib/type.dart @@ -1186,6 +1186,14 @@ bool _isTypeSubtype(_Type s, _Type t) { return _TypeUniverse.isSubtype(s, null, t, null); } +@pragma("wasm:entry-point") +@pragma("wasm:prefer-inline") +void _asSubtype(Object? o, _Type t) { + if (!_isSubtype(o, t)) { + _TypeError._throwAsCheckError(o, t); + } +} + @pragma("wasm:entry-point") bool _verifyOptimizedTypeCheck( bool result, Object? o, _Type t, String? location) {