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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ jobs:
- name: Install cargo-component
run: cargo binstall --force --locked cargo-component@0.21.1
- name: Tests
run: cargo test -- --nocapture --report-time --format junit --logfile target/report.xml
run: cargo test -- --nocapture --test-threads=1 --report-time
- name: Publish Test Report
uses: mikepenz/action-junit-report@v5
if: success() || failure() # always run even if the previous step fails
Expand Down
5 changes: 3 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/wasm-rquickjs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ camino = { workspace = true }
fs_extra = { workspace = true }
heck = { workspace = true }
include_dir = { workspace = true }
indexmap = "2.11.0"
prettier-please = { workspace = true }
proc-macro2 = { workspace = true }
quote = { workspace = true }
Expand Down
24 changes: 17 additions & 7 deletions crates/wasm-rquickjs/src/conversions.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::GeneratorContext;
use crate::javascript::escape_js_ident;
use crate::rust_bindgen::escape_rust_ident;
use crate::rust_bindgen::{RustType, TypeOwnershipStyle, escape_rust_ident, type_mode_for};
use crate::types::{get_wrapped_type, type_id_to_type_ref};
use anyhow::{Context, anyhow};
use heck::{ToLowerCamelCase, ToShoutySnakeCase, ToSnakeCase, ToUpperCamelCase};
Expand Down Expand Up @@ -80,13 +80,18 @@ fn generate_conversion_instances_for_type(
);
let field_name_lit = Lit::Str(LitStr::new(&js_field_name, Span::call_site()));

let field_type = get_wrapped_type(context, &field.ty)?;
let rust_type = RustType::from_type(
context,
&field.ty,
type_mode_for(context, &field.ty, TypeOwnershipStyle::Owned, "'_"),
);
let field_type = get_wrapped_type(context, &rust_type, &rust_type, &field.ty)?;

let original_field_type = &field_type.original_type_ref;
let wrapped_field_type = &field_type.wrapped_type_ref;

let wrapped_field = (field_type.wrap)(quote! { self.#rust_field_ident });
let unwrapped_field = (field_type.unwrap)(quote! { #rust_field_ident });
let wrapped_field = field_type.wrap.run(quote! { self.#rust_field_ident });
let unwrapped_field = field_type.unwrap.run(quote! { #rust_field_ident });

set_fields.push(quote! {
let #rust_field_ident: #wrapped_field_type = #wrapped_field;
Expand Down Expand Up @@ -175,9 +180,14 @@ fn generate_conversion_instances_for_type(
let case_name_lit = Lit::Str(LitStr::new(&case.name, Span::call_site()));

if let Some(ty) = &case.ty {
let wrapped_type = get_wrapped_type(context, ty)?;
let wrapped_inner = (wrapped_type.wrap)(quote! { inner });
let unwrapped_inner = (wrapped_type.unwrap)(quote! { inner });
let rust_type = RustType::from_type(
context,
ty,
type_mode_for(context, ty, TypeOwnershipStyle::Owned, "'_"),
);
let wrapped_type = get_wrapped_type(context, &rust_type, &rust_type, ty)?;
let wrapped_inner = wrapped_type.wrap.run(quote! { inner });
let unwrapped_inner = wrapped_type.unwrap.run(quote! { inner });
let wrapped_type = &wrapped_type.wrapped_type_ref;

into_cases.push(quote! {
Expand Down
64 changes: 43 additions & 21 deletions crates/wasm-rquickjs/src/exports.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
use crate::javascript::escape_js_ident;
use crate::rust_bindgen::escape_rust_ident;
use crate::rust_bindgen::RustWitFunction;
use crate::types::{
ProcessedParameter, WrappedType, get_function_name, get_wrapped_type,
ident_in_exported_interface, ident_in_exported_interface_or_global, identity_wrapper,
param_refs_as_tuple, process_parameter, to_original_func_arg_list, to_wrapped_param_refs,
type_borrows_resource,
ident_in_exported_interface, ident_in_exported_interface_or_global, param_refs_as_tuple,
process_parameter, to_original_func_arg_list, to_wrapped_param_refs, type_borrows_resource,
};
use crate::{EmbeddingMode, GeneratorContext, JsModuleSpec};
use anyhow::{Context, anyhow};
use heck::{ToLowerCamelCase, ToSnakeCase, ToUpperCamelCase};
use heck::{ToLowerCamelCase, ToUpperCamelCase};
use proc_macro2::{Ident, Span, TokenStream};
use quote::quote;
use std::collections::BTreeMap;
Expand Down Expand Up @@ -294,18 +293,32 @@ fn generate_exported_function_impl(
name: &str,
function: &Function,
) -> anyhow::Result<TokenStream> {
let func_name = Ident::new(&escape_rust_ident(&name.to_snake_case()), Span::call_site());
let rust_fn = RustWitFunction::new(context, name, function);
let func_name = rust_fn.function_name_ident();

let param_ident_type: Vec<_> = function
.params
.iter()
.map(|(param_name, param_type)| process_parameter(context, param_name, param_type))
.zip(rust_fn.export_parameters)
.zip(rust_fn.import_parameters)
.map(
|(((param_name, param_type), export_parameter), import_parameter)| {
process_parameter(
context,
param_name,
param_type,
&export_parameter,
&import_parameter,
)
},
)
.collect::<anyhow::Result<Vec<_>>>()?;

let func_arg_list = to_original_func_arg_list(&param_ident_type);
let func_ret = match &function.result {
Some(typ) => get_wrapped_type(context, typ)
Some(typ) => get_wrapped_type(context, &rust_fn.return_type, &rust_fn.return_type, typ)
.context(format!("Failed to encode result type for {name}"))?,
None => WrappedType::unit(false),
None => WrappedType::unit(),
};

let param_refs = to_wrapped_param_refs(&param_ident_type);
Expand Down Expand Up @@ -346,7 +359,7 @@ fn generate_exported_function_impl(
let original_result = &func_ret.original_type_ref;
let wrapped_result = &func_ret.wrapped_type_ref;
let unwrap = &func_ret.unwrap;
let unwrap_result = (unwrap)(quote! { result });
let unwrap_result = unwrap.run(quote! { result });
let func_impl = quote! {
fn #func_name(#(#func_arg_list),*) -> #original_result {
crate::internal::async_exported_function(async move {
Expand All @@ -371,15 +384,16 @@ fn generate_exported_resource_function_impl(
function: &Function,
) -> anyhow::Result<TokenStream> {
let func_name = get_function_name(name, &function)?;
let func_name_ident = Ident::new(
&escape_rust_ident(&func_name.to_snake_case()),
Span::call_site(),
);

let rust_fn = RustWitFunction::new(context, &func_name, function);
let func_name_ident = rust_fn.function_name_ident();

let param_ident_type: Vec<_> = function
.params
.iter()
.map(|(param_name, param_type)| {
.zip(rust_fn.export_parameters)
.zip(rust_fn.import_parameters)
.map(|(((param_name, param_type), export_param), import_param)| {
if matches!(
function.kind,
FunctionKind::Method(_) | FunctionKind::AsyncMethod(_)
Expand All @@ -388,21 +402,29 @@ fn generate_exported_resource_function_impl(
Ok(ProcessedParameter {
ident: Ident::new(param_name, Span::call_site()),
wrapped_type: None,
export_parameter: export_param,
import_parameter: import_param,
})
} else {
process_parameter(context, param_name, param_type)
process_parameter(
context,
param_name,
param_type,
&export_param,
&import_param,
)
}
})
.collect::<anyhow::Result<Vec<_>>>()?;

let func_arg_list = to_original_func_arg_list(&param_ident_type);
let func_ret = if matches!(function.kind, FunctionKind::Constructor(_)) {
WrappedType::no_wrapping(quote! { Self }, identity_wrapper())
WrappedType::no_wrapping(quote! { Self })
} else {
match &function.result {
Some(typ) => get_wrapped_type(context, typ)
Some(typ) => get_wrapped_type(context, &rust_fn.return_type, &rust_fn.return_type, typ)
.context(format!("Failed to encode result type for {name}"))?,
None => WrappedType::unit(false),
None => WrappedType::unit(),
}
};

Expand Down Expand Up @@ -489,7 +511,7 @@ fn generate_exported_resource_function_impl(
let original_result = &func_ret.original_type_ref;
let wrapped_result = &func_ret.wrapped_type_ref;
let unwrap = &func_ret.unwrap;
let unwrap_result = (unwrap)(quote! { result });
let unwrap_result = unwrap.run(quote! { result });
quote! {
fn #func_name_ident(#(#func_arg_list),*) -> #original_result {
crate::internal::async_exported_function(async move {
Expand All @@ -510,7 +532,7 @@ fn generate_exported_resource_function_impl(
let original_result = &func_ret.original_type_ref;
let wrapped_result = &func_ret.wrapped_type_ref;
let unwrap = &func_ret.unwrap;
let unwrap_result = (unwrap)(quote! { result });
let unwrap_result = unwrap.run(quote! { result });
quote! {
fn #func_name_ident(#(#func_arg_list),*) -> #original_result {
crate::internal::async_exported_function(async move {
Expand Down
83 changes: 65 additions & 18 deletions crates/wasm-rquickjs/src/imports.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::javascript::escape_js_ident;
use crate::rust_bindgen::escape_rust_ident;
use crate::rust_bindgen::RustWitFunction;
use crate::types::{
WrappedType, get_function_name, get_wrapped_type, ident_in_imported_interface_or_global,
process_parameter, to_unwrapped_param_refs, to_wrapped_func_arg_list,
Expand Down Expand Up @@ -163,10 +163,13 @@ fn generate_import_module(
for (name, function) in &import.functions {
match &function.kind {
FunctionKind::Freestanding => {
let rust_fn = RustWitFunction::new(context, name, function);

let rust_function_name = &rust_fn.function_name;
let rust_function_ident = rust_fn.function_name_ident();

let js_function_name = escape_js_ident(name.to_lower_camel_case());
let js_function_lit = LitStr::new(&js_function_name, Span::call_site());
let rust_function_name = escape_rust_ident(&name.to_snake_case());
let rust_function_ident = Ident::new(&rust_function_name, Span::call_site());
let js_bridge_name = format!("js_{rust_function_name}");
let js_bridge_ident = Ident::new(&js_bridge_name, Span::call_site());

Expand All @@ -183,22 +186,35 @@ fn generate_import_module(
let parameters = function
.params
.iter()
.map(|(param_name, param_type)| {
process_parameter(context, param_name, param_type)
})
.zip(rust_fn.export_parameters)
.zip(rust_fn.import_parameters)
.map(
|(((param_name, param_type), export_parameter), import_parameter)| {
process_parameter(
context,
param_name,
param_type,
&export_parameter,
&import_parameter,
)
},
)
.collect::<anyhow::Result<Vec<_>>>()?;

let param_list: Vec<TokenStream> = to_wrapped_func_arg_list(&parameters);

let param_refs: Vec<TokenStream> = to_unwrapped_param_refs(&parameters);
let func_ret = match &function.result {
Some(typ) => get_wrapped_type(context, typ)
.context(format!("Failed to encode result type for {name}"))?,
None => WrappedType::unit(false),
Some(typ) => {
get_wrapped_type(context, &rust_fn.return_type, &rust_fn.return_type, typ)
.context(format!("Failed to encode result type for {name}"))?
}
None => WrappedType::unit(),
};
let original_result = &func_ret.original_type_ref;
let wrapped_result = &func_ret.wrapped_type_ref;
let wrap = &func_ret.wrap;
let wrap_result = (wrap)(quote! { result });
let wrap_result = wrap.run(quote! { result });

bridge_functions.push(quote! {
#[rquickjs::function]
Expand Down Expand Up @@ -256,10 +272,24 @@ fn generate_import_module(
.iter()
.find(|(_, f)| matches!(f.kind, FunctionKind::Constructor(_)));
let constructor = if let Some((_, constructor_function)) = constructor_function {
let rust_fn = RustWitFunction::new(context, "new", constructor_function);

let parameters = constructor_function
.params
.iter()
.map(|(param_name, param_type)| process_parameter(context, param_name, param_type))
.zip(rust_fn.export_parameters)
.zip(rust_fn.import_parameters)
.map(
|(((param_name, param_type), export_parameter), import_parameter)| {
process_parameter(
context,
param_name,
param_type,
&export_parameter,
&import_parameter,
)
},
)
.collect::<anyhow::Result<Vec<_>>>()?;

let param_list: Vec<TokenStream> = to_wrapped_func_arg_list(&parameters);
Expand All @@ -279,27 +309,44 @@ fn generate_import_module(
let mut methods: Vec<TokenStream> = Vec::new();
for (name, function) in resource_funcs {
let name = get_function_name(name, function)?;
let rust_method_name = escape_rust_ident(&name.to_snake_case());
let rust_method_name_ident = Ident::new(&rust_method_name, Span::call_site());

let rust_fn = RustWitFunction::new(context, &name, function);

let rust_method_name_ident = rust_fn.function_name_ident();

let parameters = function
.params
.iter()
.map(|(param_name, param_type)| process_parameter(context, param_name, param_type))
.zip(rust_fn.export_parameters)
.zip(rust_fn.import_parameters)
.map(
|(((param_name, param_type), export_parameter), import_parameter)| {
process_parameter(
context,
param_name,
param_type,
&export_parameter,
&import_parameter,
)
},
)
.collect::<anyhow::Result<Vec<_>>>()?;

let param_list: Vec<TokenStream> = to_wrapped_func_arg_list(&parameters);

let param_refs: Vec<TokenStream> = to_unwrapped_param_refs(&parameters);

let func_ret = match &function.result {
Some(typ) => get_wrapped_type(context, typ)
.context(format!("Failed to encode result type for {name}"))?,
None => WrappedType::unit(false),
Some(typ) => {
get_wrapped_type(context, &rust_fn.return_type, &rust_fn.return_type, typ)
.context(format!("Failed to encode result type for {name}"))?
}
None => WrappedType::unit(),
};
let original_result = &func_ret.original_type_ref;
let wrapped_result = &func_ret.wrapped_type_ref;
let wrap = &func_ret.wrap;
let wrap_result = (wrap)(quote! { result });
let wrap_result = wrap.run(quote! { result });

match &function.kind {
FunctionKind::Method(_) => {
Expand Down
Loading
Loading