Skip to content
Merged
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
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,9 @@ wasm-tools component new target/gen.wasm -o target/gen.component.wasm
You may use `--gen-dir` to specify which package should be responsible for the exportation. The default is `gen` as mentioned above.
This can be useful having one project that exports multiple worlds.

Generated projects use `moon.mod` and `moon.pkg`, with WebAssembly export mappings
configured in the export package's `moon.pkg`.

When using `wit-bindgen moonbit`, you may use `--derive-show` or `--derive-eq` to derive `Show` or `Eq` traits for all types.
You may also use `--derive-error`, which will make types containing `Error` as error types in MoonBit.

Expand All @@ -424,7 +427,7 @@ toolchain are mixed with new bindings, components may still compile but fail at
runtime with corrupted strings/bytes or traps.

You will find the files to be modified with the name `**/stub.mbt`.
To avoid touching the files during regeneration (including `moon.pkg.json` or `moon.mod.json`) you may use `--ignore-stub`.
To avoid touching the files during regeneration (including `moon.pkg` or `moon.mod`) you may use `--ignore-stub`.

/!\ MoonBit is still evolving, so please check out the [Weekly Updates](https://www.moonbitlang.com/weekly-updates/) for any breaking changes or deprecations.

Expand Down
8 changes: 8 additions & 0 deletions crates/moonbit/src/async/moon.pkg
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import {
"moonbitlang/core/deque" @deque,
"moonbitlang/core/ref" @ref,
"moonbitlang/core/set" @set,
}

warnings = "-44"
supported_targets = "wasm"
9 changes: 0 additions & 9 deletions crates/moonbit/src/async/moon.pkg.json

This file was deleted.

7 changes: 2 additions & 5 deletions crates/moonbit/src/async_support.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ const ASYNC_SEMAPHORE: &str = include_str!("./async/semaphore.mbt");
const ASYNC_TASK: &str = include_str!("./async/task.mbt");
const ASYNC_TASK_GROUP: &str = include_str!("./async/task_group.mbt");
const ASYNC_TRAIT: &str = include_str!("./async/trait.mbt");
const ASYNC_PKG: &str = include_str!("./async/moon.pkg.json");
const ASYNC_PKG: &str = include_str!("./async/moon.pkg");

struct Segment<'a> {
name: &'a str,
Expand Down Expand Up @@ -463,10 +463,7 @@ impl AsyncSupport {
s.src.as_bytes(),
);
});
files.push(
&format!("{ASYNC_CORE_DIR}/moon.pkg.json"),
ASYNC_PKG.as_bytes(),
);
files.push(&format!("{ASYNC_CORE_DIR}/moon.pkg"), ASYNC_PKG.as_bytes());
}
}

Expand Down
77 changes: 37 additions & 40 deletions crates/moonbit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ pub struct Opts {
#[cfg_attr(feature = "clap", arg(long, default_value_t = false))]
pub ignore_stub: bool,

/// Whether or not to generate moon.mod.json ; useful if the project is part of a larger project
/// Whether or not to generate moon.mod ; useful if the project is part of a larger project
#[cfg_attr(feature = "clap", arg(long, default_value_t = false))]
pub ignore_module_file: bool,

Expand Down Expand Up @@ -156,41 +156,34 @@ impl MoonBit {
}

fn write_moon_pkg(&self, moon_pkg: &mut Source, imports: Option<&Imports>, link: bool) {
// Disable warning for invalid inline wasm
moon_pkg.push_str("{\n\"warn-list\": \"-44\"");
// Dependencies
if let Some(imports) = imports {
moon_pkg.push_str(",\n\"import\": [\n");
moon_pkg.indent(1);
moon_pkg.push_str("import {\n");
let mut deps = imports
.packages
.iter()
.map(|(k, v)| {
format!(
"{{ \"path\" : \"{}/{}\", \"alias\" : \"{}\" }}",
self.project_name,
k.replace(".", "/"),
v
)
})
.map(|(k, v)| format!("\"{}/{}\" @{},", self.project_name, k.replace(".", "/"), v))
.collect::<Vec<_>>();
deps.sort();
uwrite!(moon_pkg, "{}", deps.join(",\n"));
moon_pkg.deindent(1);
moon_pkg.push_str("\n]");
uwriteln!(moon_pkg, "{}", deps.join("\n"));
moon_pkg.push_str("}\n\n");
}
// Disable warning for invalid inline wasm.
moon_pkg.push_str("warnings = \"-44\"\n");
let imports_async_core =
imports.is_some_and(|imports| imports.packages.contains_key(ASYNC_CORE_DIR));
if imports_async_core || (link && self.async_support.is_required()) {
moon_pkg.push_str(",\n\"supported-targets\": \"+wasm\"");
moon_pkg.push_str("supported_targets = \"wasm\"\n");
}
// Link target
if link {
let memory_name = self.pkg_resolver.resolve.wasm_export_name(
ManglingAndAbi::Legacy(LiftLowerAbi::Sync),
WasmExport::Memory,
);
moon_pkg.push_str(",\n\"link\": {\n\"wasm\": {\n");
moon_pkg.push_str("\npkgtype(kind: \"foreign_library\")\n\noptions(\n");
moon_pkg.indent(1);
moon_pkg.push_str("link: {\n\"wasm\": {\n");
moon_pkg.push_str(&format!("\"export-memory-name\": \"{memory_name}\",\n"));
moon_pkg.push_str("\"heap-start-address\": 16,\n");
moon_pkg.push_str("\"exports\": [\n");
Expand All @@ -210,9 +203,10 @@ impl MoonBit {
exports.sort();
uwrite!(moon_pkg, "{}", exports.join(",\n"));
moon_pkg.deindent(1);
moon_pkg.push_str("\n]\n}\n}\n");
moon_pkg.push_str("\n],\n},\n},\n");
moon_pkg.deindent(1);
moon_pkg.push_str(")\n");
}
moon_pkg.push_str("\n}\n");
}
}

Expand All @@ -227,7 +221,7 @@ impl MoonBit {
/// - `preprocess`: Initialize generator-wide state (package resolver,
/// project name, and size/align information) for the current world.
/// - `import_interface` / `export_interface`: Generate per-interface
/// sources, FFI glue, README documentation and `moon.pkg.json` metadata.
/// sources, FFI glue, README documentation and `moon.pkg` metadata.
/// - `import_funcs` / `export_funcs` / `import_types`: Collect and accumulate
/// world-level functions and types (the `$root` module) into fragments
/// that are later written out by `finish_imports` or `finish`.
Expand Down Expand Up @@ -313,14 +307,14 @@ impl WorldGenerator for MoonBit {
}
files.push(&format!("{directory}/ffi.mbt"), indent(&ffi).as_bytes());

// moon.pkg.json
// moon.pkg
let mut moon_pkg = Source::default();
self.write_moon_pkg(
&mut moon_pkg,
self.pkg_resolver.package_import.get(&name),
false,
);
files.push(&format!("{directory}/moon.pkg.json"), moon_pkg.as_bytes());
files.push(&format!("{directory}/moon.pkg"), moon_pkg.as_bytes());
}

Ok(())
Expand Down Expand Up @@ -397,14 +391,14 @@ impl WorldGenerator for MoonBit {
&format!("{directory}/ffi_import.mbt"),
indent(&ffi).as_bytes(),
);
// moon.pkg.json
// moon.pkg
let mut moon_pkg = Source::default();
self.write_moon_pkg(
&mut moon_pkg,
self.pkg_resolver.package_import.get(&name),
false,
);
files.push(&format!("{directory}/moon.pkg.json"), moon_pkg.as_bytes());
files.push(&format!("{directory}/moon.pkg"), moon_pkg.as_bytes());
Ok(())
}

Expand Down Expand Up @@ -454,14 +448,14 @@ impl WorldGenerator for MoonBit {
files.push(&format!("{directory}/top.mbt"), indent(&src).as_bytes());

if !self.opts.ignore_stub {
// moon.pkg.json
// moon.pkg
let mut moon_pkg = Source::default();
self.write_moon_pkg(
&mut moon_pkg,
self.pkg_resolver.package_import.get(&name),
false,
);
files.push(&format!("{directory}/moon.pkg.json"), moon_pkg.as_bytes());
files.push(&format!("{directory}/moon.pkg"), moon_pkg.as_bytes());
}

// FFI
Expand Down Expand Up @@ -508,14 +502,14 @@ impl WorldGenerator for MoonBit {
files.push(&format!("{directory}/top.mbt"), indent(&src).as_bytes());

if !self.opts.ignore_stub {
// moon.pkg.json
// moon.pkg
let mut moon_pkg = Source::default();
self.write_moon_pkg(
&mut moon_pkg,
self.pkg_resolver.package_import.get(&name),
false,
);
files.push(&format!("{directory}/moon.pkg.json"), moon_pkg.as_bytes());
files.push(&format!("{directory}/moon.pkg"), moon_pkg.as_bytes());
}

// FFI
Expand Down Expand Up @@ -544,10 +538,10 @@ impl WorldGenerator for MoonBit {
let mut body = Source::default();
uwriteln!(
&mut body,
"{{ \"name\": \"{}\", \"preferred-target\": \"wasm\" }}",
"name = {:?}\n\npreferred_target = \"wasm\"",
self.project_name
);
files.push("moon.mod.json", body.as_bytes());
files.push("moon.mod", body.as_bytes());
}

// Export project entry point
Expand All @@ -574,8 +568,8 @@ impl WorldGenerator for MoonBit {
true,
);
files.push(
&format!("{}/moon.pkg.json", self.opts.r#gen_dir),
indent(&moon_pkg).as_bytes(),
&format!("{}/moon.pkg", self.opts.r#gen_dir),
moon_pkg.as_bytes(),
);

Ok(())
Expand Down Expand Up @@ -3252,8 +3246,11 @@ mod tests {
.iter()
.all(|(name, _)| !name.starts_with("async-core/async_"))
);
let package = file(&files, "gen/moon.pkg.json");
assert!(!package.contains("supported-targets"), "{package}");
let package = file(&files, "gen/moon.pkg");
assert!(!package.contains("supported_targets"), "{package}");
let module = file(&files, "moon.mod");
assert!(module.contains("preferred_target = \"wasm\""), "{module}");
assert!(files.iter().all(|(name, _)| !name.ends_with(".json")));
}

#[test]
Expand Down Expand Up @@ -3352,17 +3349,17 @@ mod tests {

let source = file(&files, "interface/a/b/types/top.mbt");
assert!(source.contains("@async-core.Future[UInt]"), "{source}");
let package = file(&files, "interface/a/b/types/moon.pkg.json");
let package = file(&files, "interface/a/b/types/moon.pkg");
assert!(
package.contains("\"supported-targets\": \"+wasm\""),
package.contains("supported_targets = \"wasm\""),
"{package}"
);
let link_package = file(&files, "gen/moon.pkg.json");
let link_package = file(&files, "gen/moon.pkg");
assert!(
link_package.contains("\"supported-targets\": \"+wasm\""),
link_package.contains("supported_targets = \"wasm\""),
"{link_package}"
);
file(&files, "async-core/moon.pkg.json");
file(&files, "async-core/moon.pkg");
file(&files, "async-core/async_trait.mbt");
}

Expand Down
4 changes: 2 additions & 2 deletions crates/test/src/moonbit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,14 @@ impl LanguageMethods for MoonBit {
let dest_path = compile.bindings_dir.join(&config.path);
std::fs::copy(src_path, dest_path)?;

// Write the moon.pkg.json if provided
// Write the moon.pkg if provided
if let Some(pkg_config) = config.pkg_config {
let dest_path = compile
.bindings_dir
.join(&config.path)
.parent()
.unwrap()
.join("moon.pkg.json");
.join("moon.pkg");
std::fs::write(dest_path, pkg_config)?;
}
}
Expand Down
6 changes: 5 additions & 1 deletion tests/runtime/list-in-variant/runner.mbt
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
//@ [lang]
//@ path = 'gen/world/runner/stub.mbt'
//@ pkg_config = """{ "import": ["test/list-in-variant/interface/test/list-in-variant/to-test"] }"""
//@ pkg_config = '''
//@ import {
//@ "test/list-in-variant/interface/test/list-in-variant/to-test",
//@ }
//@ '''

///|
pub fn run() -> Unit {
Expand Down
10 changes: 9 additions & 1 deletion tests/runtime/moonbit/async-import-cancel/runner.mbt
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
//@ wasmtime-flags = '-Wcomponent-model-async'
//@ [lang]
//@ path = 'gen/world/runner/stub.mbt'
//@ pkg_config = """{ "supported-targets": "+wasm", "import": [{ "path": "test/async-import-cancel/async-core", "alias": "async-core" }, { "path": "test/async-import-cancel/interface/test/async-import-cancel/pending", "alias": "pending" }, { "path": "test/async-import-cancel/interface/test/async-import-cancel/gate-control", "alias": "gate-control" }] }"""
//@ pkg_config = '''
//@ import {
//@ "test/async-import-cancel/async-core" @async-core,
//@ "test/async-import-cancel/interface/test/async-import-cancel/pending" @pending,
//@ "test/async-import-cancel/interface/test/async-import-cancel/gate-control" @gate-control,
//@ }
//@
//@ supported_targets = "wasm"
//@ '''

///|
async fn settle_leaf_counts(expected_drops : UInt) -> Unit {
Expand Down
11 changes: 10 additions & 1 deletion tests/runtime/moonbit/concurrent-export-isolation/runner.mbt
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
//@ wasmtime-flags = '-Wcomponent-model-async'
//@ [lang]
//@ path = 'gen/world/runner/stub.mbt'
//@ pkg_config = """{ "warn-list": "-44", "supported-targets": "+wasm", "import": [{ "path": "test/moonbit-concurrent-export-isolation/async-core", "alias": "async-core" }, { "path": "test/moonbit-concurrent-export-isolation/interface/test/moonbit-concurrent-export-isolation/operations", "alias": "operations" }] }"""
//@ pkg_config = '''
//@ import {
//@ "test/moonbit-concurrent-export-isolation/async-core" @async-core,
//@ "test/moonbit-concurrent-export-isolation/interface/test/moonbit-concurrent-export-isolation/operations" @operations,
//@ }
//@
//@ warnings = "-44"
//@
//@ supported_targets = "wasm"
//@ '''

///|
pub async fn run(background_group : @async-core.TaskGroup[Unit]) -> Unit {
Expand Down
12 changes: 11 additions & 1 deletion tests/runtime/moonbit/http-background-hook/runner.mbt
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
//@ wasmtime-flags = '-Wcomponent-model-async -S p3 -S http'
//@ [lang]
//@ path = 'gen/world/runner/stub.mbt'
//@ pkg_config = """{ "warn-list": "-44", "supported-targets": "+wasm", "import": [{ "path": "example/background-hook/async-core", "alias": "async-core" }, { "path": "example/background-hook/interface/wasi/http/handler", "alias": "handler" }, { "path": "example/background-hook/interface/wasi/http/types", "alias": "types" }] }"""
//@ pkg_config = '''
//@ import {
//@ "example/background-hook/async-core" @async-core,
//@ "example/background-hook/interface/wasi/http/handler" @handler,
//@ "example/background-hook/interface/wasi/http/types" @types,
//@ }
//@
//@ warnings = "-44"
//@
//@ supported_targets = "wasm"
//@ '''

///|
async fn run_hook(payload : Bytes, expected_error : String?) -> Unit {
Expand Down
10 changes: 9 additions & 1 deletion tests/runtime/moonbit/http-background-hook/test.mbt
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
//@ wasmtime-flags = '-Wcomponent-model-async -S p3 -S http'
//@ [lang]
//@ path = 'gen/interface/wasi/http/handler/stub.mbt'
//@ pkg_config = """{ "supported-targets": "+wasm", "import": [{ "path": "moonbitlang/core/buffer", "alias": "buffer" }, { "path": "example/background-hook/async-core", "alias": "async-core" }, { "path": "example/background-hook/interface/wasi/http/types", "alias": "types" }] }"""
//@ pkg_config = '''
//@ import {
//@ "moonbitlang/core/buffer" @buffer,
//@ "example/background-hook/async-core" @async-core,
//@ "example/background-hook/interface/wasi/http/types" @types,
//@ }
//@
//@ supported_targets = "wasm"
//@ '''

///|
pub async fn handle(
Expand Down
9 changes: 8 additions & 1 deletion tests/runtime/moonbit/local-async-primitives/runner.mbt
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
//@ wasmtime-flags = '-Wcomponent-model-async'
//@ [lang]
//@ path = 'gen/world/runner/stub.mbt'
//@ pkg_config = """{ "supported-targets": "+wasm", "import": [{ "path": "test/moonbit-local-async-primitives/async-core", "alias": "async-core" }, { "path": "test/moonbit-local-async-primitives/interface/test/moonbit-local-async-primitives/operations", "alias": "operations" }] }"""
//@ pkg_config = '''
//@ import {
//@ "test/moonbit-local-async-primitives/async-core" @async-core,
//@ "test/moonbit-local-async-primitives/interface/test/moonbit-local-async-primitives/operations" @operations,
//@ }
//@
//@ supported_targets = "wasm"
//@ '''

///|
pub async fn run(_background_group : @async-core.TaskGroup[Unit]) -> Unit {
Expand Down
Loading
Loading