dart-lang / webdev

A CLI for Dart web development.
https://pub.dev/packages/webdev
213 stars 71 forks source link

Breakpoints fail to work in Flutter web when macro experiment is enabled #2396

Closed DanTup closed 3 months ago

DanTup commented 3 months ago

I don't know if this is a DWDS issue or something else, but since DWDS is throwing the exception I thought it makes sense to start here :)

I'm testing out the macros experiment in Flutter. As of the latest master I can get the code to run on Web (but not desktop).

My files look like this: https://gist.github.com/DanTup/83a5e972943a4d9548eeef7144b47504

If I do not use any macros and I add a breakpoint to a line in my main.dart, it works as expected - I hit the breakpoint when I run the app. The VM Service traffic for setting the breakpoint looks like this:

// Add a breakpoint into main.dart
==> [VM] {
    "jsonrpc": "2.0",
    "id": "696",
    "method": "addBreakpointWithScriptUri",
    "params": {
        "isolateId": "1",
        "scriptUri": "file:///C:/Dev/Test%20Projects/flutter_macros/lib/main.dart",
        "line": 13
    }
}
// Success
<== [VM] {
    "jsonrpc": "2.0",
    "result": {
        "type": "Breakpoint",
        "id": "bp/4#13:0",
        "breakpointNumber": 729,
        "enabled": true,
        "resolved": true,
        "location": {
            "type": "SourceLocation",
            "script": {
                "type": "@Script",
                "id": "4",
                "uri": "package:flutter_macros/main.dart"
            },
            "tokenPos": 1339,
            "line": 13,
            "column": 5
        }
    },
    "id": "696"
}

However, if I use a macro in the file, then the same breakpoint (in the main file - not in a macro file) fails to be hit and I see this traffic:

// Add a breakpoint into main.dart (when the file uses macros, but the breakpoint is still in the main library)
==> [VM] {
    "jsonrpc": "2.0",
    "id": "697",
    "method": "addBreakpointWithScriptUri",
    "params": {
        "isolateId": "1",
        "scriptUri": "file:///C:/Dev/Test%20Projects/flutter_macros/lib/main.dart",
        "line": 13
    }
}
// Fails
<== [VM] {
    "jsonrpc": "2.0",
    "error": {
        "code": -32603,
        "message": "Unexpected DWDS error for addBreakpointWithScriptUri: FormatException: Unsupported URI form: C:/Dev/Test%20Projects/flutter_macros/lib/main.dart",
        "data": {
            "request": {
                "jsonrpc": "2.0",
                "id": "697",
                "method": "addBreakpointWithScriptUri",
                "params": {
                    "isolateId": "1",
                    "scriptUri": "file:///C:/Dev/Test%20Projects/flutter_macros/lib/main.dart",
                    "line": 13
                }
            }
        }
    },
    "id": "697"
}

The error appears to originate at https://github.com/dart-lang/webdev/blob/8875ae1b07fefc45c60f5e0562d6a8b26ad0ffce/dwds/lib/src/utilities/dart_uri.dart#L51 but it's not clear to me why it seems to have lost the file:/// prefix (you can see in the original request, and in the data.request field that the script is a full file URI).

I don't know if it's related, but the debugger also pauses a little while after and if I resume it I see the following in the debug console:

Error: TypeError: Instance of 'UniqueRef<JavaScriptObject>': type 'UniqueRef<JavaScriptObject>' is not a subtype of type 'JSObject'
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 296:3       throw_
dart-sdk/lib/_internal/js_shared/lib/rti.dart 1388:3                              _failedAsCheck
dart-sdk/lib/_internal/js_shared/lib/rti.dart 1366:3                              _generalAsCheckImplementation
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 243:33  _argumentErrors
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 422:22  _checkAndCall
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 431:39  dcall

I've made sure my Dart SDK (where I'm using those packages from) matches the version that is in Flutter (I included details in the gist above).

I'm not certain this issue isn't a consequence of how this currently requires a load of dependency_overrides from the Dart SDK. If that seems likely, I can wait until https://dart-review.googlesource.com/c/sdk/+/359040 lands and rolls into Flutter and test again - I aws just trying to get a bit of a head-start.

I'm unable to test this in non-web Flutter right now, however these breakpoints do work correctly in non-Flutter Dart VM.

jakemac53 commented 3 months ago

It looks like we generally build up a cache of library URIs, around here. My guess is we fail to properly build the list of libraries somewhere in this process (in the LibraryHelper), as a result of seeing some macro augmentation URIs.

jacob314 commented 3 months ago

Fyi @elliette @nshahan who were both curious about Flutter web and macros.

jakemac53 commented 3 months ago

I tried looking into this a fair bit today but didn't really make any real progress, I am still very confused why the extra // are being removed from the file URIs.

I did come up with a basic idea for how to handle these URIs:

Also today _recordAbsoluteUri does not get called with any dart-macro+ URIs, and it almost certainly needs to, so we can look up those URIs later. We could manually hack in some of this too, and just assume one of these URIs exists for every library, but that also sounds wasteful as most of them won't ever actually exist. Even with this hack things don't work because of the above issue around file:/ uris only having a single / instead of 3 when they reach this code.

jakemac53 commented 3 months ago

@elliette any idea when that would be published and then rolled into flutter?

elliette commented 2 months ago

I'm hoping to get the latest version of DWDS published and rolled into flutter by end of month. There are still some outstanding issues here that need to be resolved before it can be published: https://github.com/flutter/devtools/issues/7231