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 crates/runtime/src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ impl Interpreter for QjsInterpreter {
FuncKind::Method { method, .. } => {
assert!(!method.is_empty(), "invalid method name: {}", func.name());
let method_name = fn_lookup(ctx, method);
let self_val = cx.pop_value(ctx);
let self_val = cx.shift_value(ctx);
let self_obj = self_val
.as_object()
.unwrap_or_else(|| panic!("method receiver is not an object"));
Expand Down
4 changes: 4 additions & 0 deletions crates/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,10 @@ impl QjsCallContext {
self.pop_persistent().restore(ctx).expect("stack underflow")
}

pub(crate) fn shift_value<'js>(&mut self, ctx: &rquickjs::Ctx<'js>) -> Value<'js> {
self.stack.remove(0).restore(ctx).expect("stack underflow")
}

pub(crate) fn pop_persistent(&mut self) -> Persistent<Value<'static>> {
self.stack.pop().expect("stack underflow")
}
Expand Down
42 changes: 42 additions & 0 deletions tests/wit_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1711,9 +1711,16 @@ fn test_exported_resource() {
package test:res;

interface counter-api {
variant update {
add(u32),
reset,
}

resource counter {
constructor(initial: u32);
increment: func();
add: func(value: u32);
apply: func(update: update);
get-value: func() -> u32;
}
}
Expand All @@ -1731,6 +1738,11 @@ fn test_exported_resource() {
class Counter {
constructor(initial) { this.value = initial; }
increment() { this.value++; }
add(value) { this.value += value; }
apply(update) {
if (update.tag === "add") this.value += update.val;
if (update.tag === "reset") this.value = 0;
}
getValue() { return this.value; }
}
export const counterApi = { Counter };
Expand Down Expand Up @@ -1815,6 +1827,36 @@ fn test_exported_resource() {
Val::U32(43),
"value should be 43 after increment"
);

// Resource receiver is the first lowered argument; scalar and variant
// parameters follow it and must remain regular JavaScript arguments.
let add_idx = instance
.get_export_index(&mut store, Some(&iface_idx), "[method]counter.add")
.expect("[method]counter.add not found");
let add = instance.get_func(&mut store, add_idx).unwrap();
add.call(&mut store, &[counter.clone(), Val::U32(2)], &mut [])
.unwrap();

let apply_idx = instance
.get_export_index(&mut store, Some(&iface_idx), "[method]counter.apply")
.expect("[method]counter.apply not found");
let apply = instance.get_func(&mut store, apply_idx).unwrap();
apply
.call(
&mut store,
&[
counter.clone(),
Val::Variant("add".into(), Some(Box::new(Val::U32(3)))),
],
&mut [],
)
.unwrap();

let mut results = [Val::Bool(false)];
get_val
.call(&mut store, std::slice::from_ref(&counter), &mut results)
.unwrap();
assert_eq!(results[0], Val::U32(48));
}

#[test]
Expand Down
Loading