Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions component-model/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
- [Building a simple component](./building-a-simple-component.md)
- [C/C++](./language-support/building-a-simple-component/c.md)
- [C#](./language-support/building-a-simple-component/csharp.md)
- [Dart](./language-support/building-a-simple-component/dart.md)
- [Go](./language-support/building-a-simple-component/go.md)
- [JavaScript](./language-support/building-a-simple-component/javascript.md)
- [Python](./language-support/building-a-simple-component/python.md)
Expand All @@ -31,16 +32,19 @@
- [WebAssembly Text Format (WAT)](./language-support/building-a-simple-component/wat.md)
- [Other Languages](./language-support/building-a-simple-component/other-languages.md)
- [Importing and reusing components](./importing-and-reusing-components.md)
- [Dart](./language-support/importing-and-reusing-components/dart.md)
- [Rust](./language-support/importing-and-reusing-components/rust.md)
- [Javascript](./language-support/importing-and-reusing-components/javascript.md)
- [Other Languages](./language-support/importing-and-reusing-components/other-languages.md)
- [Creating runnable components](./creating-runnable-components.md)
- [Dart](./language-support/creating-runnable-components/dart.md)
- [Rust](./language-support/creating-runnable-components/rust.md)
- [Javascript](./language-support/creating-runnable-components/javascript.md)
- [Other languages](./language-support/creating-runnable-components/other-languages.md)
- [Using WIT resources](./using-wit-resources.md)
- [Rust](./language-support/using-wit-resources/rust.md)
- [Using HTTP in components](./using-http-in-components.md)
- [Dart](./language-support/using-http-in-components/dart.md)
- [Rust](./language-support/using-http-in-components/rust.md)
- [Running Components](./running-components.md)
- [Wasmtime](./running-components/wasmtime.md)
Expand Down
1 change: 1 addition & 0 deletions component-model/src/building-a-simple-component.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ This guide is implemented for various languages:
|----------------------------------------------------------------------------------------|
| [C/C++](./language-support/building-a-simple-component/c.md) |
| [C#](./language-support/building-a-simple-component/csharp.md) |
| [Dart](./language-support/building-a-simple-component/dart.md) |
| [Go](./language-support/building-a-simple-component/go.md) |
| [JavaScript](./language-support/building-a-simple-component/javascript.md) |
| [Python](./language-support/building-a-simple-component/python.md) |
Expand Down
1 change: 1 addition & 0 deletions component-model/src/creating-runnable-components.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ This guide is implemented for various languages:

| Language |
|---------------------------------------------------------------------------------------|
| [Dart](./language-support/creating-runnable-components/dart.md) |
| [Rust](./language-support/creating-runnable-components/rust.md) |
| [Javascript](./language-support/creating-runnable-components/javascript.md) |
| [Other Languages](./language-support/creating-runnable-components/other-languages.md) |
Expand Down
1 change: 1 addition & 0 deletions component-model/src/importing-and-reusing-components.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ This guide is implemented for various languages:

| Language |
|-------------------------------------------------------------------------------------------|
| [Dart](./language-support/importing-and-reusing-components/dart.md) |
| [Rust](./language-support/importing-and-reusing-components/rust.md) |
| [Javascript](./language-support/importing-and-reusing-components/javascript.md) |
| [Other languages](./language-support/importing-and-reusing-components/other-languages.md) |
Expand Down
8 changes: 5 additions & 3 deletions component-model/src/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ This documentation is aimed at _users_ of the component model: developers of lib
|--------------------------|----------------------|-------------------|
| [Why Components?] | [C/C++] | [Composing] |
| [Components] | [C#] | [Running] |
| [Interfaces] | [Go] | [Distributing] |
| [Worlds] | [JavaScript] | |
| [Interfaces] | [Dart] | [Distributing] |
| [Worlds] | [Go] | [Distributing] |
| | [JavaScript] | |
| | [Python] | |
| | [Rust] | |
| | [MoonBit] | |
| | [MoonBit] | |

[Why Components?]: ./design/why-component-model.md
[Components]: ./design/components.md
Expand All @@ -28,6 +29,7 @@ This documentation is aimed at _users_ of the component model: developers of lib

[C/C++]: ./language-support/building-a-simple-component/c.md
[C#]: ./language-support/building-a-simple-component/csharp.md
[Dart]: ./language-support/building-a-simple-component/dart.md
[Go]: ./language-support/building-a-simple-component/go.md
[JavaScript]: ./language-support/building-a-simple-component/javascript.md
[Python]: ./language-support/building-a-simple-component/python.md
Expand Down
1 change: 1 addition & 0 deletions component-model/src/language-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ without using a higher-level language front-end.
- [Building a Component with `wit-bindgen` and `wasm-tools`](./language-support/building-a-simple-component/c.md#building-a-component-with-wit-bindgen-and-wasm-tools)
- [Running a Component from C/C++ Applications](./language-support/building-a-simple-component/c.md#running-a-component-from-cc-applications)
- [C# Tooling](./language-support/building-a-simple-component/csharp.md)
- [Dart Tooling](./language-support/building-a-simple-component/dart.md)
- [Go Tooling](./language-support/building-a-simple-component/go.md)
- [JavaScript Tooling](./language-support/building-a-simple-component/javascript.md)
- [Building a Component with `jco`](./language-support/building-a-simple-component/javascript.md#building-a-component-with-jco)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# Dart Tooling

> [!WARNING]
> Compiling Dart to non-web WebAssembly targets is experimental.
> This guide requires Dart version `3.14.0-251.0.dev` or later.

WebAssembly components in Dart can be built with the [wasm_tools package](https://github.com/simolus3/wasm.dart/) on pub.dev.

This guide walks through building a Dart component that implements
the `adder` world defined in the [`adder/world.wit` package][docs-adder].
The component will implement the `adder` world, which contains an `add` interface with an `add` function.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: I think just pasting the WIT here (we can use a reference so the file stays in sync) would be easier than reading through this prose.


Keep in mind that this is a basic intro. For more examples, please see the [dart-samples][examples]
from the `wasm_tools` package or TODO: running a component.

If you still have questions, feel free to open an issue on [the repository][wasm_tools]
or reach out on [Zulip][chat].

## 1. Create your Dart project

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might want to include a section about tooling/setup here, and that would be a good place for the warning to go


Begin by creating a fresh Dart project:

```sh
dart create -t cli dart_wasm_adder
cd dart_wasm_adder
```

## 2. Install the tools

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
## 2. Install the tools
## 2. Install Dart tooling for Wasm

Something like this?


All tools requires to create WebAssembly components from Dart can be installed via pub:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
All tools requires to create WebAssembly components from Dart can be installed via pub:
All tools required to create WebAssembly components from Dart can be installed via `dart pub`:

Maybe it's more normal to refer to it as just "pub", but in that case I think even pub nicely indicates that it's a command/binary of some sort.


```sh
dart pub add wasm_components dev:wasm_tools
```

The `wasm_components` package provides runtime support for component models
(like an allocator or async task management), while `wasm_tools` contains `witgen`
and tools to compile Dart to components.

## 3. Generate bindings for the Wasm component

Since we will be implementing the [`adder` world][docs-adder], we can copy the WIT to our project.
Create a file named `adder.wit` and paste the following code into it:

```wit
{{#include ../../../examples/tutorial/wit/adder/world.wit}}
```

Generate Dart code and required metadata for the compiler with

```sh
dart run wasm_tools witgen -i adder.wit
```

This generates:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be a good place to maybe add a blub about what witgen does as a part of wasm_tools

It might also be nice if where we introduce wasm_tools we add an admonition that notes the difference/contrast to @bytecodealliance/wasm-tools.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tree output might be useful here, to orient the user to what files were created/what the folder looks like at this point in the guide


- `lib/src/components/docs_adder.dart` containing interfaces (only `add` in this example).
- `lib/src/components/docs_adder_adder.dart` containing bindings for the `adder` world.
- `lib/src/components/docs_adder_adder.json` containing metadata used to turn WebAssembly
modules emitted by `dart2wasm` into components.

The JSON file describe which component imports and exports a Dart program needs.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The JSON file describe which component imports and exports a Dart program needs.
The JSON file describes which component imports and exports a Dart program needs.

The toolchain reads it via [link hooks]. All packages defining component imports
or exports need one, including the `dart_wasm_adder` package. Create a
`hook/link.dart` file with these contents:
Comment on lines +63 to +65

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The toolchain reads it via [link hooks]. All packages defining component imports
or exports need one, including the `dart_wasm_adder` package. Create a
`hook/link.dart` file with these contents:
The toolchain reads it via [link hooks].
All packages defining component imports or exports need a link hooks script,
including the `dart_wasm_adder` package. Create a `hook/link.dart` file
with these contents:

Not sure what these are called normally "link hook script" or "link hook", but fine with either.


```dart
import 'dart:convert';
import 'dart:io';

import 'package:hooks/hooks.dart';
import 'package:wasm_tools/hooks.dart';

void main(List<String> args) => link(args, (input, output) async {
if (input.config.buildWasmComponent) {
final abi = input.packageRoot.resolve('lib/src/components/docs_adder_adder.json');

output.dependencies.add(abi);
output.assets.webAssemblyComponents.add(
WasmComponentAsset(
encoded: json.decode(
File(abi.toFilePath()).readAsStringSync(),
) as Map<String, Object?>,
),
);
}
});
```

## 4. Implement the `add` function

The generated `adderComponent` function is used to define this component:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might want to be a little bit more explanatory here -- like "The wasm_tools witgen utility generated a file named <...> which contains an adderComponent function ..."

It receives imported interfaces as parameters (in this case, there aren't any)
and returns the exported interface.

For this example, replace `bin/dart_wasm_adder.dart` with:

```dart
import 'package:dart_wasm_adder/src/components/docs_adder.dart';
import 'package:dart_wasm_adder/src/components/docs_adder_adder.dart';

import 'package:wasm_components/wasm_components.dart';

void main() {
adderComponent((_) => const _Add());

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some comments might be nice here to explain what is happening/the mechanism here and how the generated code fits in with this user-provided code.

For example, this section could be diff formatted and that would help, but then would make it hard to leave explanatory comments.

A section after the code block would also be fine.

}

final class const _Add() implements Add {
@override
int add({required int x, required int y}) {
return x + y;
}
}
```

## 5. Testing the `add` component

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
## 5. Testing the `add` component
## 5. Running the `add` component


With all generated bindings set up, the component can be compiled:

```sh
dart run wasm_tools compile bin/dart_wasm_adder.dart
```

This creates `bin/dart_wasm_adder.wasm`, a component we can invoke from the
CLI with [wasmtime]:

```console
$ wasmtime run --invoke 'add(1, 2)' bin/dart_wasm_adder.wasm
3
```

With this, we have successfully built and run a basic WebAssembly component with Dart 🎉

[wasm_tools]: https://github.com/simolus3/wasm.dart/
[examples]: https://github.com/simolus3/wasm.dart/tree/main/pkg/wasm_tools/example
[docs-adder]: https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/tutorial/wit/adder/world.wit
[chat]: https://bytecodealliance.zulipchat.com/#narrow/channel/394175-SIG-Guest-Languages/topic/Dart.20subgroup/with/614175797
[link hooks]: https://dart.dev/tools/hooks
[wasmtime]: https://wasmtime.dev/
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Creating Runnable Components (Dart)

> [!WARNING]
> Compiling Dart to non-web WebAssembly targets is experimental.
> This guide requires Dart version `3.14.0-251.0.dev` or later.

## Creating a command component

A _command_ is a component with a specific export that allows it to be executed directly by `wasmtime`
(or other `wasi:cli` hosts). Ignoring the specifics of defining components in Dart, this is the
equivalent of running a plain Dart program with a `main()` function.

### 1. Create a new Dart project

To create a command with Dart, start with a fresh Dart package:

```sh
dart create -t cli dart_wasm_cli
```

To configure this package for WebAssembly components, add tooling dependencies.
Additionally, the `wasi` package provides generated bindings to WASI definitions,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This note about not needing to witgen might be better as a note in the "Write the relevant Dart" section

meaning that running `dart run wasm_tools witgen` won't be necessary.

```sh
dart pub add wasi wasm_components dev:wasm_tools
```

### 2. Write the relevant Dart

The following code can be inserted into `bin/dart_wasm_cli.dart`:

```dart
import 'dart:async';
import 'dart:convert';
import 'dart:typed_data';

import 'package:wasi/cli/command.dart';
import 'package:wasi/cli.dart';
import 'package:wasm_components/wasm_components.dart';

void main() {
commandComponent((imports) => _Run(imports.cliStdout));
}

final class _Run(final Stdout stdout) implements Run {
@override
Future<Result<void, void>> run() async {
final out = StreamController<Uint8List>();
final stdoutDone = stdout.writeViaStream(data: out.stream);

out.add(utf8.encode('Hello world!\n'));
out.close();
await stdoutDone;

return const .ok(null);
}
}
```

### 3. Build the component

To build the component, use `wasm_tools compile`:

```sh
dart run wasm_tools compile bin/dart_wasm_cli.dart
```

The [link hook] of the `wasi` package detects that this Dart program defines a
command component and configures the relevant imports and exports.
This allows the component to target `wasi:cli/command@0.3.0`.

### 4. Run the component with `wasmtime`

To run your command component:

```sh
wasmtime run bin/dart_wasm_cli.wasm
```

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: Expected output might be nice to include here

[link hook]: https://github.com/simolus3/wasm.dart/blob/ec9f801ebe258fc4c8dc0dceec35af8b9447627f/pkg/wasi/hook/link.dart#L17-L21
Loading
Loading