cfug/dio

Is it now possible to use DIO / dio_web_adapter with Web/WASM?

OsvaldoTCF opened this issue ยท 41 comments

Request Statement

$ flutter build web --wasm

I get this error:

.pub-cache/hosted/pub.dev/dio_web_adapter-1.0.1/lib/src/html/adapter.dart:5:8: Error: Dart library 'dart:html' is not available on this platform.
import 'dart:html';
^
Context: The unavailable library 'dart:html' is imported through these packages:

main.dart => package:dio => package:dio_web_adapter => dart:html

Solution Brainstorm

No response

It does. We're pushing it to convert to the package:web and the code base has already been migrated. Once the package:dio_web_adapter releases v2 you'll be able to use Dio on WASM env.

This error started popping up with the latest Dio release and broke our build/tests in getsentry/sentry-dart.

AFAICT, adding the dependency on package web_adapter was a breaking change and should have been a major release (Dio 6.0), not a minor one (Dio 5.5)

This error started popping up with the latest Dio release and broke our build/tests in getsentry/sentry-dart.

Can you elaborate on the details? Please submit an issue at getsentry/sentry-dart and ping me so we can track specific problems. This thread should focus on WASM support.

AFAICT, adding the dependency on package web_adapter was a breaking change and should have been a major release (Dio 6.0), not a minor one (Dio 5.5)

Nope. We intended to make this not a breaking change and the package is still embedded with the package:dio, no implementation has been changed. People who upgrade to Dio v5.5 will automatically use the package:web_adapter.

This is breaking for people who were alerady building for WASM, because package:web_adapter is incompatible with it while Dio at v5.4 worked fine

This is the test failure in CI after automatic update to Dio 5.5 (because we don't pin a lower version). Before the release of Dio 5.5, the CI worked fine and there were no relevant code changes

Run dart test -p chrome --compiler dart2wasm --test-randomize-ordering-seed=random --chain-stack-traces
Shuffling test order with --test-randomize-ordering-seed=2877333308

โŒ [Chrome, Dart2Wasm] loading test/dio_stacktrace_extractor_test.dart (failed)
  *NOTE*: Compilation to WasmGC is experimental.
  The support may change, or be removed, with no advance notice.
  
  ../../../../.pub-cache/hosted/pub.dev/dio_web_adapter-1.0.1/lib/src/html/adapter.dart:5:8: Error: Dart library 'dart:html' is not available on this platform.
  import 'dart:html';
         ^
  Context: The unavailable library 'dart:html' is imported through these packages:
  
      /home/runner/work/sentry-dart/sentry-dart/dio/test/dio_stacktrace_extractor_test.dart => package:dio => package:dio_web_adapter => dart:html
      /home/runner/work/sentry-dart/sentry-dart/dio/test/dio_stacktrace_extractor_test.dart => package:sentry_dio => package:dio => package:dio_web_adapter => dart:html
  
  Detailed import paths for (some of) the these imports:
  
      main.dart => /home/runner/work/sentry-dart/sentry-dart/dio/test/dio_stacktrace_extractor_test.dart => package:dio/dio.dart => package:dio/src/adapter.dart => package:dio/src/adapters/browser_adapter.dart => package:dio_web_adapter/dio_web_adapter.dart => package:dio_web_adapter/src/html/adapter.dart => dart:html
      main.dart => /home/runner/work/sentry-dart/sentry-dart/dio/test/dio_stacktrace_extractor_test.dart => package:dio/dio.dart => package:dio/src/adapter.dart => package:dio/src/adapters/browser_adapter.dart => package:dio_web_adapter/dio_web_adapter.dart => package:dio_web_adapter/src/html/dio_impl.dart => package:dio_web_adapter/src/html/adapter.dart => dart:html
      main.dart => /home/runner/work/sentry-dart/sentry-dart/dio/test/dio_stacktrace_extractor_test.dart => package:dio/dio.dart => package:dio/src/dio.dart => package:dio/src/adapter.dart => package:dio/src/adapters/browser_adapter.dart => package:dio_web_adapter/dio_web_adapter.dart => package:dio_web_adapter/src/html/adapter.dart => dart:html
      main.dart => /home/runner/work/sentry-dart/sentry-dart/dio/test/dio_stacktrace_extractor_test.dart => package:dio/dio.dart => package:dio/src/dio.dart => package:dio/src/adapter.dart => package:dio/src/adapters/browser_adapter.dart => package:dio_web_adapter/dio_web_adapter.dart => package:dio_web_adapter/src/html/dio_impl.dart => package:dio_web_adapter/src/html/adapter.dart => dart:html
      main.dart => /home/runner/work/sentry-dart/sentry-dart/dio/test/dio_stacktrace_extractor_test.dart => package:dio/dio.dart => package:dio/src/dio.dart => package:dio/src/dio/dio_for_browser.dart => package:dio_web_adapter/dio_web_adapter.dart => package:dio_web_adapter/src/html/adapter.dart => dart:html
      main.dart => /home/runner/work/sentry-dart/sentry-dart/dio/test/dio_stacktrace_extractor_test.dart => package:dio/dio.dart => package:dio/src/dio.dart => package:dio/src/dio/dio_for_browser.dart => package:dio_web_adapter/dio_web_adapter.dart => package:dio_web_adapter/src/html/dio_impl.dart => package:dio_web_adapter/src/html/adapter.dart => dart:html
      main.dart => /home/runner/work/sentry-dart/sentry-dart/dio/test/dio_stacktrace_extractor_test.dart => package:dio/dio.dart => package:dio/src/dio.dart => package:dio/src/dio_mixin.dart => package:dio/src/adapter.dart => package:dio/src/adapters/browser_adapter.dart => package:dio_web_adapter/dio_web_adapter.dart => package:dio_web_adapter/src/html/adapter.dart => dart:html
      main.dart => /home/runner/work/sentry-dart/sentry-dart/dio/test/dio_stacktrace_extractor_test.dart => package:dio/dio.dart => package:dio/src/dio.dart => package:dio/src/dio_mixin.dart => package:dio/src/adapter.dart => package:dio/src/adapters/browser_adapter.dart => package:dio_web_adapter/dio_web_adapter.dart => package:dio_web_adapter/src/html/dio_impl.dart => package:dio_web_adapter/src/html/adapter.dart => dart:html
      main.dart => /home/runner/work/sentry-dart/sentry-dart/dio/test/dio_stacktrace_extractor_test.dart => package:dio/dio.dart => package:dio/src/dio.dart => package:dio/src/dio_mixin.dart => package:dio/src/form_data.dart => package:dio/src/multipart_file.dart => package:dio/src/multipart_file/browser_multipart_file.dart => package:dio_web_adapter/dio_web_adapter.dart => package:dio_web_adapter/src/html/adapter.dart => dart:html
      main.dart => /home/runner/work/sentry-dart/sentry-dart/dio/test/dio_stacktrace_extractor_test.dart => package:dio/dio.dart => package:dio/src/dio.dart => package:dio/src/dio_mixin.dart => package:dio/src/form_data.dart => package:dio/src/multipart_file.dart => package:dio/src/multipart_file/browser_multipart_file.dart => package:dio_web_adapter/dio_web_adapter.dart => package:dio_web_adapter/src/html/dio_impl.dart => package:dio_web_adapter/src/html/adapter.dart => dart:html
      main.dart => /home/runner/work/sentry-dart/sentry-dart/dio/test/dio_stacktrace_extractor_test.dart => package:dio/dio.dart => package:dio/src/dio.dart => package:dio/src/dio_mixin.dart => package:dio/src/interceptors/imply_content_type.dart => package:dio/src/form_data.dart => package:dio/src/multipart_file.dart => package:dio/src/multipart_file/browser_multipart_file.dart => package:dio_web_adapter/dio_web_adapter.dart => package:dio_web_adapter/src/html/adapter.dart => dart:html
      main.dart => /home/runner/work/sentry-dart/sentry-dart/dio/test/dio_stacktrace_extractor_test.dart => package:dio/dio.dart => package:dio/src/dio.dart => package:dio/src/dio_mixin.dart => package:dio/src/interceptors/imply_content_type.dart => package:dio/src/form_data.dart => package:dio/src/multipart_file.dart => package:dio/src/multipart_file/browser_multipart_file.dart => package:dio_web_adapter/dio_web_adapter.dart => package:dio_web_adapter/src/html/dio_impl.dart => package:dio_web_adapter/src/html/adapter.dart => dart:html
      main.dart => /home/runner/work/sentry-dart/sentry-dart/dio/test/dio_stacktrace_extractor_test.dart => package:dio/dio.dart => package:dio/src/dio.dart => package:dio/src/dio_mixin.dart => package:dio/src/progress_stream/browser_progress_stream.dart => package:dio_web_adapter/dio_web_adapter.dart => package:dio_web_adapter/src/html/adapter.dart => dart:html
      main.dart => /home/runner/work/sentry-dart/sentry-dart/dio/test/dio_stacktrace_extractor_test.dart => package:dio/dio.dart => package:dio/src/dio.dart => package:dio/src/dio_mixin.dart => package:dio/src/progress_stream/browser_progress_stream.dart => package:dio_web_adapter/dio_web_adapter.dart => package:dio_web_adapter/src/html/dio_impl.dart => package:dio_web_adapter/src/html/adapter.dart => dart:html
      main.dart => /home/runner/work/sentry-dart/sentry-dart/dio/test/dio_stacktrace_extractor_test.dart => package:dio/dio.dart => package:dio/src/dio.dart => package:dio/src/dio_mixin.dart => package:dio/src/response/response_stream_handler.dart => package:dio/src/adapter.dart => package:dio/src/adapters/browser_adapter.dart => package:dio_web_adapter/dio_web_adapter.dart => package:dio_web_adapter/src/html/adapter.dart => dart:html
      main.dart => /home/runner/work/sentry-dart/sentry-dart/dio/test/dio_stacktrace_extractor_test.dart => package:dio/dio.dart => package:dio/src/dio.dart => package:dio/src/dio_mixin.dart => package:dio/src/response/response_stream_handler.dart => package:dio/src/adapter.dart => package:dio/src/adapters/browser_adapter.dart => package:dio_web_adapter/dio_web_adapter.dart => package:dio_web_adapter/src/html/dio_impl.dart => package:dio_web_adapter/src/html/adapter.dart => dart:html
      main.dart => /home/runner/work/sentry-dart/sentry-dart/dio/test/dio_stacktrace_extractor_test.dart => package:dio/dio.dart => package:dio/src/dio_mixin.dart => package:dio/src/adapter.dart => package:dio/src/adapters/browser_adapter.dart => package:dio_web_adapter/dio_web_adapter.dart => package:dio_web_adapter/src/html/adapter.dart => dart:html
      main.dart => /home/runner/work/sentry-dart/sentry-dart/dio/test/dio_stacktrace_extractor_test.dart => package:dio/dio.dart => package:dio/src/dio_mixin.dart => package:dio/src/adapter.dart => package:dio/src/adapters/browser_adapter.dart => package:dio_web_adapter/dio_web_adapter.dart => package:dio_web_adapter/src/html/dio_impl.dart => package:dio_web_adapter/src/html/adapter.dart => dart:html
      main.dart => /home/runner/work/sentry-dart/sentry-dart/dio/test/dio_stacktrace_extractor_test.dart => package:dio/dio.dart => package:dio/src/dio_mixin.dart => package:dio/src/form_data.dart => package:dio/src/multipart_file.dart => package:dio/src/multipart_file/browser_multipart_file.dart => package:dio_web_adapter/dio_web_adapter.dart => package:dio_web_adapter/src/html/adapter.dart => dart:html
      main.dart => /home/runner/work/sentry-dart/sentry-dart/dio/test/dio_stacktrace_extractor_test.dart => package:dio/dio.dart => package:dio/src/dio_mixin.dart => package:dio/src/form_data.dart => package:dio/src/multipart_file.dart => package:dio/src/multipart_file/browser_multipart_file.dart => package:dio_web_adapter/dio_web_adapter.dart => package:dio_web_adapter/src/html/dio_impl.dart => package:dio_web_adapter/src/html/adapter.dart => dart:html
      main.dart => /home/runner/work/sentry-dart/sentry-dart/dio/test/dio_stacktrace_extractor_test.dart => package:dio/dio.dart => package:dio/src/dio_mixin.dart => package:dio/src/interceptors/imply_content_type.dart => package:dio/src/form_data.dart => package:dio/src/multipart_file.dart => package:dio/src/multipart_file/browser_multipart_file.dart => package:dio_web_adapter/dio_web_adapter.dart => package:dio_web_adapter/src/html/adapter.dart => dart:html
      ...
  
  ../../../../.pub-cache/hosted/pub.dev/dio_web_adapter-1.0.1/lib/src/html/adapter.dart:20:17: Error: 'HttpRequest' isn't a type.
    final xhrs = <HttpRequest>{};
                  ^^^^^^^^^^^
  ../../../../.pub-cache/hosted/pub.dev/dio_web_adapter-1.0.1/lib/src/html/adapter.dart:183:8: Error: 'ProgressEvent' isn't a type.
        (ProgressEvent event) {
         ^^^^^^^^^^^^^
  ../../../../.pub-cache/hosted/pub.dev/dio_web_adapter-1.0.1/lib/src/html/adapter.dart:37:17: Error: The method 'HttpRequest' isn't defined for the class 'BrowserHttpClientAdapter'.
   - 'BrowserHttpClientAdapter' is from 'package:dio_web_adapter/src/html/adapter.dart' ('../../../../.pub-cache/hosted/pub.dev/dio_web_adapter-1.0.1/lib/src/html/adapter.dart').
  Try correcting the name to the name of an existing method, or defining a method named 'HttpRequest'.
      final xhr = HttpRequest();
                  ^^^^^^^^^^^
  ../../../../.pub-cache/hosted/pub.dev/dio_web_adapter-1.0.1/lib/src/html/adapter.dart:239:28: Error: The getter 'HttpRequest' isn't defined for the class 'BrowserHttpClientAdapter'.
   - 'BrowserHttpClientAdapter' is from 'package:dio_web_adapter/src/html/adapter.dart' ('../../../../.pub-cache/hosted/pub.dev/dio_web_adapter-1.0.1/lib/src/html/adapter.dart').
  Try correcting the name to the name of an existing getter, or defining a getter or field named 'HttpRequest'.
        if (xhr.readyState < HttpRequest.DONE &&
                             ^^^^^^^^^^^
  ../../../../.pub-cache/hosted/pub.dev/dio_web_adapter-1.0.1/lib/src/html/adapter.dart:240:28: Error: The getter 'HttpRequest' isn't defined for the class 'BrowserHttpClientAdapter'.
   - 'BrowserHttpClientAdapter' is from 'package:dio_web_adapter/src/html/adapter.dart' ('../../../../.pub-cache/hosted/pub.dev/dio_web_adapter-1.0.1/lib/src/html/adapter.dart').
  Try correcting the name to the name of an existing getter, or defining a getter or field named 'HttpRequest'.
            xhr.readyState > HttpRequest.UNSENT) {
                             ^^^^^^^^^^^
  
  Failed to load "test/dio_stacktrace_extractor_test.dart": Bad state: dart2wasm failed.
  package:test_core/src/runner/wasm_compiler_pool.dart 74:26      WasmCompilerPool.compileInternal.<fn>
  ===== asynchronous gap ===========================
  package:test_core/src/util/io.dart 120:23                       withTempDir.<fn>.<fn>
  ===== asynchronous gap ===========================
  package:pool/pool.dart 127:14                                   Pool.withResource
  ===== asynchronous gap ===========================
  package:test/src/runner/browser/compilers/dart2wasm.dart 136:7  Dart2WasmSupport.compileSuite.<fn>
  ===== asynchronous gap ===========================
  package:test/src/runner/browser/platform.dart 178:5             BrowserPlatform.load
  ===== asynchronous gap ===========================
  package:test_core/src/runner/loader.dart 219:27                 Loader.loadFile.<fn>
  ===== asynchronous gap ===========================
  package:test_core/src/runner/load_suite.dart 97:19              new LoadSuite.<fn>.<fn>

Please submit an issue at getsentry/sentry-dart and ping me so we can track specific problems. This thread should focus on WASM support.

@vaind

This is not an issue in sentry-dart. Your package added a dependency on a noncompatible package. I'll create a new issue.

@vaind What are you talking about? They created dio_web_adapter because dio currently does not support WASM.

../../.pub-cache/hosted/pub.dev/dio-5.4.3+1/lib/src/adapters/browser_adapter.dart:3:8: Error: Dart library 'dart:html' is not available on this platform.
import 'dart:html';

@AlexV525 while we're here, how do you plan on dealing with the possibility of needing to update dio_web_adapter v1 after releasing v2? I'm pretty sure pub won't let you release versions below 2.0.0 after you release it.

I'm pretty sure pub won't let you release versions below 2.0.0 after you release it.

AFAICT it does allow. But maybe it's been changed.

Holy crap it totally does. I did not expect that.

why wouldn't it? it's another major version - it's pretty normal to have releases on multiple major versions

@vaind What are you talking about? They created dio_web_adapter because dio currently does not support WASM.

../../.pub-cache/hosted/pub.dev/dio-5.4.3+1/lib/src/adapters/browser_adapter.dart:3:8: Error: Dart library 'dart:html' is not available on this platform.
import 'dart:html';

Depends on what you're using from Dio. See #2266

Judging by your sample, with no specific adapter configuration, it seems that the default IO adapter is used for the WASM compile. Which does not really make sense to me, why would that work? I mean I can see that it compiles but....

Judging by your sample, with no specific adapter configuration, it seems that the default IO adapter is used for the WASM compile. Which does not really make sense to me, why would that work? I mean I can see that it compiles but....

I guess that the WASM env is compatible with the compilation of dart:io but no actual business can be involved.

That might be a bug in the WASM compiler

That might be a bug in the WASM compiler

The compiled code works fine: the request is executed successfully.

So from what I read, dart:io seems to be a supported package for WASM. Just can not target any browser API then.
Not sure how a file download etc. will behave at runtime in a browser.

What is the status of dio_web_adapter: 2.0.0? Is there anything I can do to help with the migration?

I am interested in some feedback on the usage of the IOHttpClientAdapter in WASM mode. It seems to compile and work. Do we actually need a web adapter for WASM?

Apps can build but you can't actually make any calls

main.dart.mjs:19 DioException [unknown]: null
Error: Unsupported operation: Platform._version
main.dart.mjs:19     at _DioForNative&Object&DioMixin.fetch inner (http://localhost:49762/main.dart.wasm:wasm-function[1369]:0x4a870)
    at _awaitHelper closure at org-dartlang-sdk:///dart-sdk/lib/_internal/wasm/lib/async_patch.dart:85:15 (http://localhost:49762/main.dart.wasm:wasm-function[2508]:0x6113a)
    at closure wrapper at org-dartlang-sdk:///dart-sdk/lib/_internal/wasm/lib/async_patch.dart:85:15 trampoline (http://localhost:49762/main.dart.wasm:wasm-function[2514]:0x611a6)
    at _RootZone.runBinary (http://localhost:49762/main.dart.wasm:wasm-function[949]:0x42673)
    at _FutureListener.handleError (http://localhost:49762/main.dart.wasm:wasm-function[948]:0x425c2)
    at _Future._propagateToListeners closure handleError at org-dartlang-sdk:///dart-sdk/lib/async/future_impl.dart:868:25 (http://localhost:49762/main.dart.wasm:wasm-function[914]:0x41ee1)
    at _Future._propagateToListeners (http://localhost:49762/main.dart.wasm:wasm-function[910]:0x41ad0)
    at _Future._completeError (http://localhost:49762/main.dart.wasm:wasm-function[1004]:0x43015)
localhost/:1 Uncaught Exception

Apps can build but you can't actually make any calls

main.dart.mjs:19 DioException [unknown]: null
Error: Unsupported operation: Platform._version
main.dart.mjs:19     at _DioForNative&Object&DioMixin.fetch inner (http://localhost:49762/main.dart.wasm:wasm-function[1369]:0x4a870)
    at _awaitHelper closure at org-dartlang-sdk:///dart-sdk/lib/_internal/wasm/lib/async_patch.dart:85:15 (http://localhost:49762/main.dart.wasm:wasm-function[2508]:0x6113a)
    at closure wrapper at org-dartlang-sdk:///dart-sdk/lib/_internal/wasm/lib/async_patch.dart:85:15 trampoline (http://localhost:49762/main.dart.wasm:wasm-function[2514]:0x611a6)
    at _RootZone.runBinary (http://localhost:49762/main.dart.wasm:wasm-function[949]:0x42673)
    at _FutureListener.handleError (http://localhost:49762/main.dart.wasm:wasm-function[948]:0x425c2)
    at _Future._propagateToListeners closure handleError at org-dartlang-sdk:///dart-sdk/lib/async/future_impl.dart:868:25 (http://localhost:49762/main.dart.wasm:wasm-function[914]:0x41ee1)
    at _Future._propagateToListeners (http://localhost:49762/main.dart.wasm:wasm-function[910]:0x41ad0)
    at _Future._completeError (http://localhost:49762/main.dart.wasm:wasm-function[1004]:0x43015)
localhost/:1 Uncaught Exception

We have same issue in our project. Apps can build in wasm mode but there are no actually performing any calls.

Any updates about status of dio_web_adapter: 2.0.0 ?

@vaind How did you test your requests?

by checking the response

Idk what call you're making but dio.get doesn't work

@vaind are you 100% sure your app is running with the WASM renderer? There are very specific header and browser requirements.

see my repro here where I've tested it with dio 5.4 #2266 - you can give it a try and print out the the response, to see if it actually works. I remember it worked, although I have no need for dio/wasm personally so that repro was just to get the plugin fixed to unbreak my builds elsewhere

Can you check the value of bool.fromEnvironment('FLUTTER_WEB_USE_SKWASM')?

Can you check the value of bool.fromEnvironment('FLUTTER_WEB_USE_SKWASM')?

Sorry, I don't have the environment to do that anymore but you can try it yourself with the given example. Or just wait until official wasm support lands in Dio

you can try it yourself with the given example

Your example is pretty much what I created myself

Or just wait until official wasm support lands in Dio

Your claims that requests work when compiled to WASM seem to be what is blocking work on that support

The compiled code works fine: the request is executed successfully.

In the future please check the value of bool.fromEnvironment('FLUTTER_WEB_USE_SKWASM') before making any claims about what does and doesn't work when compiled to WASM. I looked at the sentry-dio tests and there are only mocked requests which is why they aren't failing. See the Flutter WASM docs for information about running the WASM renderer.

In the future please check the value of bool.fromEnvironment('FLUTTER_WEB_USE_SKWASM')

I'll do that. Maybe it just falled back on .js or something. As I've said, I have no need for wasm+dio so I didn't looked too much into it and I must have gotten fooled by it showing stuff when I launched the built app.

@kuhnroyal Is there existing work on dio_web_adapter: 2.0.0? If not and no one is assigned to it I can take a look.

I think some initial work was done in #2218 but we had to split the adapter first. Feel free to create a PR ๐Ÿ‘

@kuhnroyal Is there existing work on dio_web_adapter: 2.0.0? If not and no one is assigned to it I can take a look.

The implementation has already been setup with src/js_interop, the remaining things are:

  1. We need to update our CI to work with WASM.
  2. We have a Web-related pull request but not making good progress #2230
  3. Other misc checks.

Self-assigned since I've already done most of the work. This could be pushed in the next few days, I've been through a busy month recently :).

@AlexV525 Thank you! I need this soon for an upcoming project, so if you need any help with the migration or testing please let me know!

@AlexV525 Thank you! I need this soon for an upcoming project, so if you need any help with the migration or testing please let me know!

For personal usages I'd recommend to easily fork and update the code like this: https://github.com/cfug/dio/pull/2274/files
The official support could be generally served for downstream package usages and provide a solid solution.

Yes that would work as a last resort, but I'd rather not start a new project with a bunch of self-hosted dependencies if I can avoid it

Yes that would work as a last resort, but I'd rather not start a new project with a bunch of self-hosted dependencies if I can avoid it

or rely on this ref-based dependency: e247bd0

Will the 'dio_web_adapter' v2 support SSE (Streaming) ?

Any update about release of this version of dio?

We've published dio v5.6.0 and dio_web_adapter v2.0.0 to support the WASM environment. Please submit separate issues regarding specific implementations if any.