Version 3.6.0-114.0.dev
Merge 2cf3222e4f1c00c36e1b072c1de8db31dad01de7 into dev
diff --git a/pkg/dart2wasm/lib/code_generator.dart b/pkg/dart2wasm/lib/code_generator.dart
index b8c65b6..1488cfe 100644
--- a/pkg/dart2wasm/lib/code_generator.dart
+++ b/pkg/dart2wasm/lib/code_generator.dart
@@ -293,11 +293,11 @@
b.local_set(boxedOperand);
operand = boxedOperand;
}
+ b.local_get(operand);
_generateArgumentTypeCheck(
variable.name!,
- () => b.local_get(operand),
+ operand.type as w.RefType,
variable.type,
- operand,
);
}
}
@@ -2909,32 +2909,23 @@
/// Generate code that checks type of an argument against an expected type
/// and throws a `TypeError` on failure.
///
- /// Does not expect any values on stack and does not leave any values on
- /// stack.
- ///
- /// Locals [argLocal] are used to store values pushed by [pushArg]
- /// and reuse the values.
+ /// Expects a boxed object (whose type is to be checked) on the stack.
///
/// [argName] is used in the type error as the name of the argument that
/// doesn't match the expected type.
void _generateArgumentTypeCheck(
String argName,
- void Function() pushArg,
+ w.RefType argumentType,
DartType testedAgainstType,
- w.Local argLocal,
) {
if (translator.options.minify) {
// We don't need to include the name in the error message, so we can use
// the optimized `as` checks.
- pushArg();
- types.emitAsCheck(
- this,
- testedAgainstType,
- translator.coreTypes.objectNullableRawType,
- argLocal.type as w.RefType);
+ types.emitAsCheck(this, testedAgainstType,
+ translator.coreTypes.objectNullableRawType, argumentType);
b.drop();
} else {
- pushArg();
+ final argLocal = b.addLocal(argumentType);
b.local_tee(argLocal);
types.emitIsTest(
this, testedAgainstType, translator.coreTypes.objectNullableRawType);
@@ -3288,24 +3279,15 @@
final List<VariableDeclaration> memberPositionalParams =
procedure.function.positionalParameters;
- // Local for the current argument being checked. Used to avoid indexing
- // the positional parameters array again when throwing type error.
- final argLocal = addLocal(translator.topInfo.nullableType);
-
for (int positionalParamIdx = 0;
positionalParamIdx < memberPositionalParams.length;
positionalParamIdx += 1) {
final param = memberPositionalParams[positionalParamIdx];
+ b.local_get(positionalArgsLocal);
+ b.i32_const(positionalParamIdx);
+ b.array_get(translator.nullableObjectArrayType);
_generateArgumentTypeCheck(
- param.name!,
- () {
- b.local_get(positionalArgsLocal);
- b.i32_const(positionalParamIdx);
- b.array_get(translator.nullableObjectArrayType);
- },
- param.type,
- argLocal,
- );
+ param.name!, translator.topInfo.nullableType, param.type);
}
// Check named argument types
@@ -3328,16 +3310,11 @@
namedParamIdx < memberNamedParams.length;
namedParamIdx += 1) {
final param = memberNamedParams[namedParamIdx];
+ b.local_get(namedArgsLocal);
+ b.i32_const(mapNamedParameterToArrayIndex(param.name!));
+ b.array_get(translator.nullableObjectArrayType);
_generateArgumentTypeCheck(
- param.name!,
- () {
- b.local_get(namedArgsLocal);
- b.i32_const(mapNamedParameterToArrayIndex(param.name!));
- b.array_get(translator.nullableObjectArrayType);
- },
- param.type,
- argLocal,
- );
+ param.name!, translator.topInfo.nullableType, param.type);
}
}
@@ -3399,9 +3376,6 @@
_initializeThis(member.reference);
- // Local for the argument.
- final argLocal = addLocal(translator.topInfo.nullableType);
-
final member_ = member;
DartType paramType;
if (member_ is Field) {
@@ -3411,11 +3385,11 @@
}
if (!translator.options.omitImplicitTypeChecks) {
+ b.local_get(positionalArgLocal);
_generateArgumentTypeCheck(
member.name.text,
- () => b.local_get(positionalArgLocal),
+ positionalArgLocal.type as w.RefType,
paramType,
- argLocal,
);
}
@@ -3424,9 +3398,9 @@
int fieldIndex = translator.fieldIndex[member_]!;
b.local_get(receiverLocal);
translator.convertType(b, receiverLocal.type, info.nonNullableType);
- b.local_get(argLocal);
- translator.convertType(
- b, argLocal.type, info.struct.fields[fieldIndex].type.unpacked);
+ b.local_get(positionalArgLocal);
+ translator.convertType(b, positionalArgLocal.type,
+ info.struct.fields[fieldIndex].type.unpacked);
b.struct_set(info.struct, fieldIndex);
} else {
final setterProcedure = member_ as Procedure;
@@ -3436,12 +3410,12 @@
assert(setterWasmInputs.length == 2);
b.local_get(receiverLocal);
translator.convertType(b, receiverLocal.type, setterWasmInputs[0]);
- b.local_get(argLocal);
- translator.convertType(b, argLocal.type, setterWasmInputs[1]);
+ b.local_get(positionalArgLocal);
+ translator.convertType(b, positionalArgLocal.type, setterWasmInputs[1]);
call(setterProcedure.reference);
}
- b.local_get(argLocal);
+ b.local_get(positionalArgLocal);
b.end(); // end function
}
}
diff --git a/tests/web/wasm/flutter_regress_152029_test.dart b/tests/web/wasm/flutter_regress_152029_test.dart
new file mode 100644
index 0000000..f218730
--- /dev/null
+++ b/tests/web/wasm/flutter_regress_152029_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2024, 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.
+
+// dart2wasmOptions=--extra-compiler-option=--omit-implicit-checks
+
+import 'package:expect/expect.dart';
+
+class A<T> {
+ T? value = null;
+}
+
+main() {
+ final list = [A<String>(), 1];
+ final dynamic a = list[int.parse('0')];
+ if (int.parse('0') == 0) {
+ a.value = '42';
+ }
+ Expect.equals('42', a.value);
+}
diff --git a/tools/VERSION b/tools/VERSION
index a1b9ef9..2a7cf1f 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 3
MINOR 6
PATCH 0
-PRERELEASE 113
+PRERELEASE 114
PRERELEASE_PATCH 0