Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dart2js crashes when catching a JS string in strict mode #53105

Closed
nex3 opened this issue Aug 3, 2023 · 1 comment
Closed

dart2js crashes when catching a JS string in strict mode #53105

nex3 opened this issue Aug 3, 2023 · 1 comment
Labels
area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. web-dart2js

Comments

@nex3
Copy link
Member

nex3 commented Aug 3, 2023

If dart2js-compiled code is run in strict mode (such as when it's loaded as an ECMAScript module as in the browser), and it tries to catch an exception from JavaScript that's just a string, it will crash with TypeError: Cannot create property '$cachedTrace' on string. This is because of the helper function getTraceFromException():

getTraceFromException(exception) {
  var trace;
  if (exception instanceof A.ExceptionAndStackTrace)
    return exception.stackTrace;
  if (exception == null)
    return new A._StackTrace(exception);
  trace = exception.$cachedTrace;
  if (trace != null)
    return trace;
  return exception.$cachedTrace = new A._StackTrace(exception);
}

Specifically, exception.$cachedTrace = is not valid in strict mode if exception is a JS value type. Here's a simple reproduction (you can imagine that the exception might come from a JS callback instead of jsThrow()):

// test.dart
import 'package:js/js.dart';

@JS("Function")
class JSFunction {
  external JSFunction(String arg1, [String? arg2, String? arg3]);
  external Object? call([Object? arg1, Object? arg2, Object? arg3]);
}

/// Throws [error] like JS would, without any Dart wrappers.
Never jsThrow(Object error) => _jsThrow.call(error) as Never;

final _jsThrow = JSFunction("error", "throw error;");

void main(List<String> args) {
  try {
    jsThrow('oh no');
  } catch (error, stackTrace) {
    print('error: $error, trace: $stackTrace');
  }
}

Compile this to JS, load it with import in a browser, and you'll see TypeError: Cannot create property '$cachedTrace' on string 'oh no'.

@mraleph mraleph added area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. web-dart2js labels Aug 3, 2023
nex3 added a commit to google/dart_cli_pkg that referenced this issue Aug 3, 2023
nex3 added a commit to google/dart_cli_pkg that referenced this issue Aug 7, 2023
nex3 added a commit to sass/dart-sass that referenced this issue Aug 8, 2023
copybara-service bot pushed a commit that referenced this issue Aug 18, 2023
Avoid trying to add a property to a non-object exception value to
cache the stack trace.

In "use strict" mode this is an error.

Otherwise the property is added to an ephemeral Object and then lost.
The observable behaviour is unchanged - returning a fresh
`_StackTrace` object each time.

Bug: #53105
Change-Id: I406ff14db4ed24b71e0cfe95cd87783621a5b809
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/321622
Reviewed-by: Mayank Patke <fishythefish@google.com>
Commit-Queue: Stephen Adams <sra@google.com>
@rakudrama
Copy link
Member

Fixed via 9d15643

nex3 added a commit to sass/dart-sass that referenced this issue Aug 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. web-dart2js
Projects
None yet
Development

No branches or pull requests

4 participants
@nex3 @mraleph @rakudrama and others