dart-sdk/pkg/dart2wasm
Ömer Sinan Ağacan 9d1dd89768 [dart2wasm] Handle exceptions and returns in async* functions
New passing tests:

- co19/Language/Expressions/Function_Invocation/async_cleanup_t07
- co19/Language/Expressions/Function_Invocation/async_cleanup_t08
- co19/Language/Expressions/Function_Invocation/async_generator_invokation_t05
- co19/Language/Expressions/Function_Invocation/async_generator_invokation_t09
- co19/Language/Statements/Rethrow/execution_t04
- co19/Language/Statements/Return/syntax_t10
- co19/Language/Statements/Return/syntax_t11
- co19/Language/Statements/Return/syntax_t12
- co19/Language/Statements/Return/syntax_t13
- co19/Language/Statements/Yield_and_Yield_Each/Yield_Each/execution_async_A01_t01
- language/async/return_types_runtime_test
- language/async_star/basic_test
- language/async_star/yield_statement_context_test
- lib/async/stream_from_iterable_test

Change-Id: Id03cc0abe150dadfcd753c4e74a282d46260a1f8
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/304501
Reviewed-by: Joshua Litt <joshualitt@google.com>
Commit-Queue: Ömer Ağacan <omersa@google.com>
2023-05-22 20:31:38 +00:00
..
bin [dart2wasm] New async implementation 2023-05-22 08:32:12 +00:00
lib [dart2wasm] Handle exceptions and returns in async* functions 2023-05-22 20:31:38 +00:00
tool [dart2wasm] New async implementation 2023-05-22 08:32:12 +00:00
analysis_options.yaml
OWNERS
pubspec.yaml
README.md [dart2wasm] New async implementation 2023-05-22 08:32:12 +00:00

Compiling Dart to WebAssembly

WebAssembly (commonly abbreviated to Wasm) is a "binary instruction format for a stack-based virtual machine". Although Wasm was originally designed for running native code on the web, Wasm has since evolved into a general technology for running compiled code across multiple platforms.

The Dart team is currently investigating support for compiling Dart to Wasm, in conjunction with support in Flutter.

Note: This feature is under active development, and is currently considered experimental. The tracking issue is #32894.

Running dart2wasm

You don't need to build the Dart SDK to run dart2wasm, as long as you have a Dart SDK installed and have the Dart SDK repository checked out. NB: the SDK must be checked out using depot tools and not just cloned from this repo.

To compile a Dart file to Wasm, in a checkout of the Dart SDK repository, run:

dart --enable-asserts pkg/dart2wasm/bin/dart2wasm.dart options infile.dart outfile.wasm

where options include:

Option Default Description
--dart-sdk=path relative to script The location of the sdk directory inside the Dart SDK, containing the core library sources.
--platform=path none The location of the platform dill file containing the compiled core libraries.
--depfile=path none Write a Ninja depfile listing the input sources for the compilation.
--[no-]export-all no Export all functions; otherwise, just export main.
--[no-]import-shared-memory no Import a shared memory buffer. If this is on, --shared-memory-max-pages must also be specified.
--[no-]inlining yes Enable function inlining.
--inlining-limit size 0 Always inline functions no larger than this number of AST nodes, if inlining is enabled.
--[no-]name-section yes Emit Name Section with function names.
--[no-]omit-type-checks no Omit runtime type checks, such as covariance checks and downcasts.
--[no-]polymorphic-specialization no Do virtual calls by switching on the class ID instead of using call_indirect.
--[no-]print-kernel no Print IR for each function before compiling it.
--[no-]print-wasm no Print Wasm instructions of each compiled function.
--[no-]enable-asserts no Enable assertions at runtime.
--[no-]constant-branch-pruning yes Avoid emitting code for dead branches of conditionals based on constants.
--shared-memory-max-pages pagecount Max size of the imported memory buffer. If --shared-import-memory is specified, this must also be specified.
--watch offset Print stack trace leading to the byte at offset offset in the .wasm output file. Can be specified multiple times.

Dart2Wasm will output a wasm file, containing Dart compiled to Wasm, as well as an mjs file containing the runtime. The result can be run with:

d8 --experimental-wasm-gc --experimental-wasm-type-reflection pkg/dart2wasm/bin/run_wasm.js -- outfile.wasm /abs/path/to/*outfile*.mjs

Where d8 is the V8 developer shell.

Imports and exports

To import a function, declare it as a global, external function and mark it with a wasm:import pragma indicating the imported name (which must be two identifiers separated by a dot):

@pragma("wasm:import", "foo.bar")
external void fooBar(Object object);

which will call foo.bar on the host side:

var foo = {
    bar: function(object) { /* implementation here */ }
};

To export a function, mark it with a wasm:export pragma:

@pragma("wasm:export")
void foo(double x) { /* implementation here */  }

@pragma("wasm:export", "baz")
void bar(double x) { /* implementation here */  }

With the Wasm module instance in inst, these can be called as:

inst.exports.foo(1);
inst.exports.baz(2);

Types to use for interop

In the signatures of imported and exported functions, use the following types:

  • For numbers, use double.
  • For JS objects, use a JS interop type, e.g. JSAny, which translates to the Wasm externref type. These can be passed around and stored as opaque values on the Dart side.
  • For Dart objects, use the corresponding Dart type. This will be emitted as anyref and automatically converted to and from the Dart type at the boundary.