diff --git a/pkg/dart2wasm/lib/code_generator.dart b/pkg/dart2wasm/lib/code_generator.dart index bb43d23d3b4..509ff61137e 100644 --- a/pkg/dart2wasm/lib/code_generator.dart +++ b/pkg/dart2wasm/lib/code_generator.dart @@ -2883,8 +2883,7 @@ class CodeGenerator extends ExpressionVisitor1 // assume non-nullable here. assert(!dartTypeOf(node.expression).isPotentiallyNullable); wrap(node.expression, translator.topInfo.nonNullableType); - call(translator.stackTraceCurrent.reference); - call(translator.errorThrow.reference); + call(translator.errorThrowWithCurrentStackTrace.reference); b.unreachable(); return expectedType; } diff --git a/pkg/dart2wasm/lib/kernel_nodes.dart b/pkg/dart2wasm/lib/kernel_nodes.dart index 062ea0402cf..4688c3975a0 100644 --- a/pkg/dart2wasm/lib/kernel_nodes.dart +++ b/pkg/dart2wasm/lib/kernel_nodes.dart @@ -251,8 +251,8 @@ mixin KernelNodes { late final Class errorClass = index.getClass("dart:core", "Error"); late final Field errorClassStackTraceField = index.getField("dart:core", "Error", "_stackTrace"); - late final Procedure errorThrow = - index.getProcedure("dart:core", "Error", "_throw"); + late final Procedure errorThrowWithCurrentStackTrace = + index.getProcedure("dart:core", "Error", "_throwWithCurrentStackTrace"); // dart:core type procedures late final Procedure getClosureRuntimeType = diff --git a/sdk/lib/_internal/wasm/lib/errors_patch.dart b/sdk/lib/_internal/wasm/lib/errors_patch.dart index 37decf4a31c..2b04b0eb1c0 100644 --- a/sdk/lib/_internal/wasm/lib/errors_patch.dart +++ b/sdk/lib/_internal/wasm/lib/errors_patch.dart @@ -14,6 +14,10 @@ class Error { return jsonEncode(string); } + @pragma('wasm:entry-point') + static Never _throwWithCurrentStackTrace(Object object) => + Error._throw(object, StackTrace.current); + @patch StackTrace? get stackTrace => _stackTrace; diff --git a/tests/language/stack_trace/full2_test.dart b/tests/language/stack_trace/full2_test.dart index ece2252271d..ae1e936d0a2 100644 --- a/tests/language/stack_trace/full2_test.dart +++ b/tests/language/stack_trace/full2_test.dart @@ -12,6 +12,8 @@ import "package:expect/expect.dart"; +import 'non_web_helper.dart' if (dart.library.js_interop) 'web_helper.dart'; + @pragma("vm:entry-point") // Prevent obfuscation. void func1() { throw new Exception("Test full stacktrace"); @@ -78,6 +80,7 @@ int func7() { } main() { + configureStackFrameLimit(); var i = func7(); Expect.equals(1, i); } diff --git a/tests/language/stack_trace/full3_test.dart b/tests/language/stack_trace/full3_test.dart index 92eac16e49b..5dc16aee0a1 100644 --- a/tests/language/stack_trace/full3_test.dart +++ b/tests/language/stack_trace/full3_test.dart @@ -12,6 +12,8 @@ import "package:expect/expect.dart"; +import 'non_web_helper.dart' if (dart.library.js_interop) 'web_helper.dart'; + @pragma("vm:entry-point") // Prevent obfuscation void func1() { throw new Exception("Test full stacktrace"); @@ -77,6 +79,7 @@ int func7() { } main() { + configureStackFrameLimit(); var i = func7(); Expect.equals(1, i); } diff --git a/tests/language/stack_trace/non_web_helper.dart b/tests/language/stack_trace/non_web_helper.dart new file mode 100644 index 00000000000..c4d11d21e44 --- /dev/null +++ b/tests/language/stack_trace/non_web_helper.dart @@ -0,0 +1,5 @@ +// (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. + +void configureStackFrameLimit() {} diff --git a/tests/language/stack_trace/web_helper.dart b/tests/language/stack_trace/web_helper.dart new file mode 100644 index 00000000000..ecdf245266e --- /dev/null +++ b/tests/language/stack_trace/web_helper.dart @@ -0,0 +1,25 @@ +// (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. + +import 'dart:js_interop'; + +void configureStackFrameLimit() { + // Different browsers have different limits on how many top frames + // are captured in stack traces (e.g. Chrome's limit is 10). + // We can configure that here manually, to ensure the tests pass + // on all compiler+browser combinations. + eval(''' + var globalState = (typeof window != "undefined") ? window + : (typeof global != "undefined") ? global + : (typeof self != "undefined") ? self : null; + + // By default, stack traces cutoff at 10 in Chrome. + if (globalState.Error) { + globalState.Error.stackTraceLimit = Infinity; + } +'''); +} + +@JS() +external void eval(String code);