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

Provide interop between Dart and WASM #37355

Open
bryanrideshark opened this issue Jun 25, 2019 · 45 comments
Open

Provide interop between Dart and WASM #37355

bryanrideshark opened this issue Jun 25, 2019 · 45 comments
Labels
area-dart2wasm Issues for the dart2wasm compiler. area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. P3 A lower priority bug or feature request type-question A question about expected behavior or functionality web-js-interop Issues that impact all js interop

Comments

@bryanrideshark
Copy link

Would it be possible to enable Web Assembly in Dart?

Were this to be possible, I think it would greatly increase investment in the language as existing codebases would have a common compile target which could be used as a bridge.

For example I'd love to use Dart/Flutter but doing so would be incredibly costly without much benefit. Were I able to use WASM in Dart however the story would be very different- Flutter would become just as easy to use as any other web interface were that the case.

Can we get an up/down on whether or not this is A possible, and B something the team would like to support in the future?

@lrhn
Copy link
Member

lrhn commented Jun 25, 2019

As I see it, supporting Web Assembly is not a language feature. It doesn't require any new language features, and since it's only available on the web, we would cautious about adding platform specific syntax. All it needs is a way to communicate with JavaScript, which we already have in JavaScript interop.

I'll move this question to the SDK repository and make it a question for the Dart-for-web team, who are in charge of JavaScript interop: Can they include WASM interop in dart:js or package:js?

@lrhn lrhn transferred this issue from dart-lang/language Jun 25, 2019
@lrhn lrhn added web-js-interop Issues that impact all js interop type-question A question about expected behavior or functionality labels Jun 25, 2019
@lexaknyazev
Copy link
Contributor

A package for accessing raw WASM API from JS exists:
https://pub.dev/packages/wasm_interop

common compile target which could be used as a bridge

Emscripten-compiled modules always require additional JS glue to do initialization and to pass any function parameter or return value that is not a number. So an actual interop would be between dart2js compiled JS and emscripten-supplied JS (which is already possible via existing JS-interop options).

Compiling Dart code to WASM may be interesting for some use cases but the final result would look like what emscripten does: a WASM module with auto-generated JS glue. So again, an actual interop would be between two JS codebases.

@srawlins
Copy link
Member

CC @yjbanov @mraleph @matanlurey

@mraleph
Copy link
Member

mraleph commented Jun 25, 2019

Could you clarify what you mean by "Web Assembly Support" because there are multiple different things this could mean, for example:

  • You want to be able to use WASM on the Web together with Dart
  • You want to be able to use WASM in native environments with Dart (e.g. on command line, Flutter apps, server)
  • You want to be able to compile Dart to WASM

For example I'd love to use Dart/Flutter but doing so would be incredibly costly without much benefit. Were I able to use WASM in Dart however the story would be very different- Flutter would become just as easy to use as any other web interface were that the case.

It is not really clear to me why any form of WASM support makes it easier for you to use Flutter.

You can already use any native language in your Flutter application, you don't really need any WASM support for that. Of course you need to figure out interoperability story because Flutter framework is written in Dart so it works best when actually used from Dart and not from some other language.

Say you want to use Flutter class StatefulWidget from C++ code - how is this supposed to work? What does it even mean? WASM does not magically answer this question.

@vsmenon vsmenon added the area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. label Jul 22, 2019
@vsmenon vsmenon changed the title Web Assembly Support Provide interop between Dart and WASM Jul 22, 2019
@vsmenon
Copy link
Member

vsmenon commented Jul 22, 2019

Since we have an issue ( #32894 ) for compilation, let's use this for interop. We may want to split the native and web cases ( @mraleph 's first two bullets) at some point, but one use case might be deploying / sharing C++ components between Web and native targets.

@vsmenon vsmenon removed the web-js-interop Issues that impact all js interop label Jul 22, 2019
@sffc
Copy link

sffc commented Jul 22, 2019

We are interested in Google i18n about using WASM in native environments with Dart. See #32894 (comment)

@kevmoo
Copy link
Member

kevmoo commented Jul 22, 2019

@nex3 – do you already have an issue open on this?

@nex3
Copy link
Member

nex3 commented Jul 22, 2019

@kevmoo I don't think so.

Using WASM from Dart is something I'm interested in seeing as someone with a vested interest in Dart's success. WASM is extremely portable (any language could add support for it, and it's usable in the browser), it will provide a clearly-defined interop interface for high-level languages, and it's likely to be quite performant for algorithmically-intensive code. This combination positions it very well for becoming the de facto standard platform for self-contained libraries. Library authors are motivated to target WASM because it'll make their libraries easy for downstream users across all manner of languages and platforms to use, and languages will be motivated to support it because so many libraries exist. The normal bootstrapping problem a network effect like this will be smashed by having support from the two most widely-used platforms, Node.js and the browser, from the word go.

If Dart gets ahead of the curve and starts adding support for WASM now, it'll have access to (and input into) this ecosystem as it grows, making it easier and more attractive for new users to move to Dart. But if you wait until WASM support is de rigueur for any serious language, you'll have to exert the same energy playing catch-up that could have instead been a competitive advantage.

@bryanrideshark
Copy link
Author

I was more wanting to use WASM inside Dart, in a mobile Flutter app. I maintain a large enterprise codebase which must be able to work in the browser; Moving to Flutter is simply not feasible, because as it stands, it would require an entire rewrite of important business logic, etc.

If I could use WASM to contain my business logic etc. then I could easily move to a Flutter app as I would need to do, is import the appropriate WASM module.

@sachaarbonel
Copy link

Actually @bryanrideshark as far I can tell Dart will support wasmerio for loading web assembly modules, so you don't have to be worry about that. I think it is behind an experimental flag on master.

@maks
Copy link

maks commented Dec 1, 2019

I'm guessing that @sachaarbonel you mean #37882 so this is very exciting to see support for wasm libraries coming to Dart and I assume eventually to Flutter?

@sachaarbonel
Copy link

Yep exactly @maks

@orangeagain
Copy link

you mean wasmvm on dart?
i need this too

@orangeagain
Copy link

@mraleph
Copy link
Member

mraleph commented Feb 14, 2020

For everybody tracking this issue. We are currently evaluating how to move multiplatform Dart<->WASM interop forward. Similarly to our C FFI work we would like to collect some examples of code that people would like to use in their Dart applications via WASM. So if you have one that is open source please leave a comment here or on #37882 with a link to the source and which platforms you would like to use it on (Flutter on iOS/Android/Desktop/Web, Dart Web), please also include information if you have ever tried running this library in WASM before. Thank you.

@sffc
Copy link

sffc commented Feb 14, 2020

The i18n Engineering team at Google is building a cross-platform standard i18n library, which we intend to make available via WASM (internal link http://go/omnicu, public link http://bit.ly/omnicu-charter). Dart supporting WASM would be a big boost.


Another use case separate from i18n that I'm interested in is to use 2D graphics libraries, such as Cairo. I have not done it personally, but a quick Google search brings up a few different examples of how to use Cairo on the web via WASM.

@syrusakbary
Copy link

That's awesome @sffc. We are working on bringing universality to the WebAssembly modules, integrating Wasm into multiple languages (we already have integrations for Python, PHP, Rust, Ruby, Elixir, C#, Go, C, C++...)

Would be great to chat and see how we can make omnicu usable from all this languages, including Dart as well!

Here's my email, in case is useful for following up [email protected] :)

@maks
Copy link

maks commented Oct 7, 2021

@insinfo if all you want is to do this with Dart in Webbrowsers, then no, I don't think this is possible yet.

But if what you mean by "dart projects" also includes Dart on desktop then the dart:wasm package does allow you to use wasm modules from Dart. I believe support for Flutter is coming soon too. Perhaps you could use this as a starting point to enhance that package to work on Web too.

I also wrote up my experience of using the package to make use of a codebase written in Assemblyscript so it's definitely already usable for codebases originally written to be used within webbrowsers.

@cedvdb
Copy link

cedvdb commented Oct 13, 2021

I'm personally interested in using a C library on mobile and web. One way I'm thinking about going about this is:

  • compile to wasm for the web and access it with js and dart package js
  • use ffi for other platforms

However this would be cumbersome. It would be easier if I could compile to wasm for all platforms.

@sigmundch sigmundch added the web-js-interop Issues that impact all js interop label Nov 8, 2021
@fzyzcjy
Copy link
Contributor

fzyzcjy commented Oct 22, 2022

By the way, https://github.com/fzyzcjy/flutter_rust_bridge already supports Flutter Web to call WASM (compiled from Rust) with safety etc.

@kevmoo
Copy link
Member

kevmoo commented Oct 22, 2022

Sweet @fzyzcjy !!

@fzyzcjy
Copy link
Contributor

fzyzcjy commented Oct 22, 2022

Thanks! @kevmoo

@fzyzcjy
Copy link
Contributor

fzyzcjy commented Oct 22, 2022

Oh forget to say, thanks @Desdaemon for contributing the implementation!

@osa1
Copy link
Member

osa1 commented May 21, 2024

We've shipped the Wasm backend as experimental with Dart 3.3 and as stable with 3.4 (it's still experimental). Closing as completed.

@osa1 osa1 closed this as completed May 21, 2024
@nex3
Copy link
Member

nex3 commented May 21, 2024

Does Dart support loading WASM libraries, or only emitting them? If the latter and not the former, I don't think this should be closed yet.

@osa1
Copy link
Member

osa1 commented May 21, 2024

We can compile Dart to Wasm, and interact with other Wasm modules in Dart compiled to Wasm.

The latter is done via Native. AFAIK this is how Flutter interacts with SkWasm (e.g. in https://github.com/flutter/engine/tree/main/lib/web_ui/lib/src/engine/skwasm/skwasm_impl/raw).

@nex3
Copy link
Member

nex3 commented May 21, 2024

Good to know, thanks. It's also worth noting that in 3.4 dart compile doesn't list wasm as an option, and dart compile wasm explicitly says *NOTE*: Compilation to WasmGC is experimental. Can you clarify whether or not this is in fact considered stable, and if so whether these should be considered UI bugs in the CLI?

@osa1
Copy link
Member

osa1 commented May 21, 2024

Ah, my bad, I read the release notes wrong. It looks like we still advertise it as experimental. I've updated my original comment.

@osa1
Copy link
Member

osa1 commented May 23, 2024

The latter is done via Native. AFAIK this is how Flutter interacts with SkWasm

We discussed this a little bit today, Native works today but we will limit its usage to SDK and Flutter repo. For users that want to interact with any Wasm module we will design and implement a separate mechanism.

@osa1 osa1 reopened this May 23, 2024
@osa1 osa1 added the area-dart2wasm Issues for the dart2wasm compiler. label May 24, 2024
@mkustermann
Copy link
Member

Good to know, thanks. It's also worth noting that in 3.4 dart compile doesn't list wasm as an option, and dart compile wasm explicitly says NOTE: Compilation to WasmGC is experimental. Can you clarify whether or not this is in fact considered stable, and if so whether these should be considered UI bugs in the CLI?

This has been removed in 004d6a3 and the Compile Dart to Wasm bug was closed.

Cross-linking other bugs:

  • Interacting with other wasm modules: Issue 55856
  • Interacting with C code compiled to linear-memory wasm: Issue 46690 (aka make dart:ffi work on web)
  • Running dart2wasm-compiled code in non-JS environments: Issue 53884

We could consider closing this issue in favor of the more concrete ones listed above. wdyt?

@iapicca
Copy link

iapicca commented May 29, 2024

  • Running dart2wasm-compiled code in non-JS environments: Issue 53884

We could consider closing this issue in favor of the more concrete ones listed above. wdyt?

@mkustermann
I feel that the issue above + this one would easily translate in WASI support

@nmfisher
Copy link

nmfisher commented Jun 11, 2024

The latter is done via Native. AFAIK this is how Flutter interacts with SkWasm

We discussed this a little bit today, Native works today but we will limit its usage to SDK and Flutter repo. For users that want to interact with any Wasm module we will design and implement a separate mechanism.

@osa1 seeking a bit of clarification on the direction here:

  1. Does this mean that, at some point in future, it won't be possible for me to create any Dart library that uses @ffi.Native to invoke a method in some external C library on any platform? Or just that we won't be able to do so when compiling to WASM? Or is that something Flutter-specific?

  2. Why is dart:ffi specifically not suitable for WASM? Is it because it's based around the 'native' memory paradigm (e.g. single shared linear memory), which doesn't accommodate WasmGC or multiple linear memory instances? Or is there some other reason?

@osa1
Copy link
Member

osa1 commented Jun 11, 2024

@nmfisher

Does this mean that, at some point in future, it won't be possible for me to create any Dart library that uses @ffi.Native to invoke a method in some external C library on any platform? Or just that we won't be able to do so when compiling to WASM? Or is that something Flutter-specific?

This is when compiling to Wasm. Other platforms/targets will work as before.

Why is dart:ffi specifically not suitable for WASM? Is it because it's based around the 'native' memory paradigm (e.g. single shared linear memory), which doesn't accommodate WasmGC or multiple linear memory instances? Or is there some other reason?

I think most (probably even all) of dart:ffi can be supported with the current Wasm + GC instructions, and I think we will need to support it at some point to allow using emscripten-generated modules with dart2wasm-generated modules. The main problem, as I see it, is that it needs more work, and we may have to do breaking changes to the currently supported (only allowed internally in Flutter) version of dart:ffi. Current version was implemented based on what we need in Flutter. It's easier to disallow it for now and release it when it's properly supported.

I think we can't properly support multiple linear memories (and we certainly don't need to support it) for dart:ffi. The API assumes there's one shared memory with all the FFI code.

(@mkustermann may have more thoughts on this)

@mkustermann
Copy link
Member

@nmfisher As @osa1 alluded to

  • dart:ffi has been designed for native (i.e. Dart VM) and is fully supported there
  • We have very limited sketchy support for dart:ffi in dart2wasm (just enough to support flutter engine use cases). But it's far from being as robust and feature complete as the support the VM has. Because of this we disallow using it for the time being.
  • We will investigate how dart:ffi can be made to work well on the web (tracking bug: dart:ffi for web). It may require a different API, it may have smaller feature set, ... - to be figured out. Please subscribe to dart:ffi for web. This support will most likely be there for all web compilers (not just dart2wasm).
    => It requires some work, stay tuned!

@nmfisher
Copy link

Thanks for the responses @osa1 and @mkustermann. I've been posting about this on Twitter too, but I figure it's better to move it here for a more fruitful discussion :)

By way of background, I was using dart:ffi, package:ffi and package:ffigen so that my Dart library could load symbols from native libraries across all platforms via ffi.Nativesee here for an example.

This works exceptionally well on desktop/mobile. On web/WASM, I can compile the native library via emscripten, generate the native<->Dart bindings with ffigen, compile the Dart library to WASM, pass the emscripten library to the dart2wasm module in JS at instantiation time, and now both Dart and emscripten libraries have access to the same address space (there's a lot of passing pointers around).

This required some hacks to get around missing dart:ffi functionality. I had previously raised the problems here, and the response was that they wouldn't be fixed because dart:ffi wouldn't be used on web going forward. That's fine - I understand that, no complaint.

However, pulling WASM support for dart:ffi before the replacement was in place is a bit frustrating. I know it wasn't 100% complete/stable, but a subset was - after all, that's what Flutter relies on. What was the downside to just keeping it publicly available? There may have been a few GitHub issues filed saying "dart:ffi isn't working on WASM", but couldn't those be adequately addressed with "dart:ffi isn't officially supported on WASM, that won't be fixed until we have a replacement"?

It also feels a bit strange to grant the Flutter engine access to something that other apps can't use (I mean, if Flutter needs dart:ffi to run on web wasm, other apps probably do too, right?). I'm fully behind the decision to create something like dart:wasm (and I know the current "official" approach now is to use JS interop), but for continuity's sake, it didn't really seem like dart:ffi was causing that many problems that it had to be nuked from the WASM target.  

@mkustermann
Copy link
Member

mkustermann commented Jun 11, 2024

However, pulling WASM support for dart:ffi before the replacement was in place is a bit frustrating. I know it wasn't 100% complete/stable, but a subset was - after all, that's what Flutter relies on. What was the downside to just keeping it publicly available? There may have been a few GitHub issues filed saying "dart:ffi isn't working on WASM", but couldn't those be adequately addressed with "dart:ffi isn't officially supported on WASM, that won't be fixed until we have a replacement"?

It also feels a bit strange to grant the Flutter engine access to something that other apps can't use (I mean, if Flutter needs dart:ffi to run on web wasm, other apps probably do too, right?). I'm fully behind the decision to create something like dart:wasm (and I know the current "official" approach now is to use JS interop), but for continuity's sake, it didn't really seem like dart:ffi was causing that many problems that it had to be nuked from the WASM target.

Happy to explain the multitude of reasons that led to this decision:

  • Our development strategy for web apps / flutter web apps: Just like in native where users develop with hot-reload on the Dart VM JIT and deploy with Dart VM AOT, on the web we have DDC as development compiler and Dart2Js/Dart2Wasm as deployment. Since DDC (and Dart2Js) have 0 dart:ffi support - any user using dart:ffi with wasm would be unable to iterate on their app with with DDC - and we have no intention in the short/medium term to make a hot-reload/hot-restart development wasm compiler. So we prefer to offer dart:ffi if it works in both development & deployment modes, not just wasm-specific deployment mode.
  • We are not 100% sure that we can offer the exact same dart:ffi APIs as well as the same feature set we have on native on the web. So we want to first come up with design & implementation on the web. If we put it out now, we'll get a bunch of bug reports - which we may be unable to fix in short term, make some users rely on it only for us to possibly break them a few months later.
  • We declared dart2wasm stable. So we want to ensure things are rock solid and dart:ffi in dart2wasm is just not. To back this up, let me give a concrete example: The following most trivial example crashes the tip-of-tree dart2wasm compiler:
    import 'dart:ffi';
    main() => print(Pointer<Int8>.fromAddress(0));
    with
    Exception in FactoryConstructorInvocation at file:///.../test.dart
    Unhandled exception:
    Bad state: No element
    #0      List.single (dart:core-patch/growable_array.dart:354)
    #1      Intrinsifier.generateStaticIntrinsic (package:dart2wasm/intrinsics.dart:810)
    #2      CodeGenerator.visitStaticInvocation (package:dart2wasm/code_generator.dart:1777)
    #3      StaticInvocation.accept1 (package:kernel/ast.dart:6586)
    #4      CodeGenerator.wrap (package:dart2wasm/code_generator.dart:881)
    #5      CodeGenerator.visitArgumentsLists (package:dart2wasm/code_generator.dart:2817)
    ...
    
  • We have packages on pub database that use conditional imports on dart.library.ffi. Those packages are broken if the ffi-specific imports are used (instead of the web fallback paths). See e.g. flutter/issues/149984. We want those packages to work as well as in dart2js and not fail to compile or run.
  • We want to put our limited resources in the very short term to stability/performance/... work that will benefit all wasm-using flutter web apps today. So we'd have very limited bandwidth on addressing user-reported FFI bugs / missing features etc in the very short term.

It's fantastic to see the community so eager to get this and build on top of it - it's very motivating for us. We'll get there, stay tuned!

@nmfisher
Copy link

Appreciate the response @mkustermann. I understand why dart:ffi isn't stable, and also why the Dart team wouldn't want to open the door to support something known to be unstable (even if personally I'm happy with the "not officially supported, fix it yourself" response to any issue).

Why the exception for Flutter internals though? Rightly or wrongly, many people see Dart as the "Flutter language" rather than a fantastic language/platform in its own right. Giving Flutter "trusted" access to SDK internals doesn't help dispel that view.

@mkustermann
Copy link
Member

Why the exception for Flutter internals though? Rightly or wrongly, many people see Dart as the "Flutter language" rather than a fantastic language/platform in its own right. Giving Flutter "trusted" access to SDK internals doesn't help dispel that view.

From a technical point of view, we allow any dart:* library to import other internal dart:* libraries - it's not specific to flutter in that sense. Flutter happens to have two dart-colon libraries (dart:ui and dart:web_ui) which can access dart:ffi. But the flutter framework for example cannot use dart:ffi. So if a 3rd party would come along and make a flutter-like framework, adds more dart:* libraries, those would be allowed to import it as well.

From a practical standpoint: We e.g. don't have to maintain API stability. We can break the API at any point, update the corresponding flutter engine (i.e. dart:ui / dart:web_ui) code - do so within a day or two without causing widespread breakages throughout our ecosystem. The bar for public APIs is much higher.

(In hindsight we should have started out with dart:_ffi (just like we have dart:_wasm, dart:_internal, dart:_...) and graduate it to dart:ffi (or similar library) once it's ready)

@nmfisher
Copy link

dart:ui is a Flutter SDK package, though. dart:ffi isn't, it is a public Dart API that you can still call on any Dart (VM) platform. It sounds like the WASM implementation fell into a grey area where it was developed specifically for Flutter compatibility, published, but was never intended for public consumption (because it was intentionally incomplete). Understandable, but given it was published, and that Flutter still relies on it for WASM compilation, a graceful deprecation would have made things easier.

I don't want to take up any more of your time, though - you've acknowledged my feedback and there's probably nothing further to add. I'm sure you have many better things to spend your time on! I look forward to the next iteration of WASM interop on Dart.

@jezell
Copy link

jezell commented Jun 11, 2024

  • WASM shipped as "stable" in 3.22 of Flutter without any hot reload support
  • Web doesn't at the moment support hot reload with CanvasKit without leaking the whole CanvasKit heap and will eventually hang your app due to OOM related issues in the CanvasKit heap.

Not to minimize how useful hot reload is, and not to discount other issues which are blocking ffi on web, but while better support for hot reload on web would definitely be useful, in practice it's not really working that well in web, and probably shouldn't block any dart features from shipping if it's not blocking Flutter itself from shipping web support.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-dart2wasm Issues for the dart2wasm compiler. area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. P3 A lower priority bug or feature request type-question A question about expected behavior or functionality web-js-interop Issues that impact all js interop
Projects
None yet
Development

No branches or pull requests