Class: Wasmtime::Component::LinkerInstance

Inherits:
Object
  • Object
show all
Defined in:
ext/src/ruby_api/component/linker.rs

Overview

LinkerInstances are builder-style, ephemeral objects that can only be used within the block to which they get yielded. Calling methods outside of the block will raise.

Instance Method Summary collapse

Instance Method Details

#func_new(name) {|*args| ... } ⇒ LinkerInstance

Define a host function in this linker instance.

Host functions return plain Ruby values which are automatically validated and converted based on the function's type signature from the component.

Examples:

Simple scalar return

root.func_new("add") do |a, b|
  a + b  # Returns u32
end

Returning a list

root.func_new("get-numbers") do
  [1, 2, 3]  # Returns list<s32>
end

Returning a tuple

root.func_new("make-tuple") do |n, s, b|
  [n, s, b]  # Returns tuple<u32, string, bool>
end

Complex types (records, results, etc.)

root.func_new("make-point") do |x, y|
  {"x" => x, "y" => y}  # Returns record with x and y fields
end

Parameters:

  • name (String)

    The function name

Yields:

  • (*args)

    The block implementing the host function

Yield Parameters:

  • args (Array<Object>)

    The function arguments, converted from component values

Yield Returns:

  • (Object)

    Result value matching the function's return type. Use arrays for lists and tuples, hashes for records.

Returns:



315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
# File 'ext/src/ruby_api/component/linker.rs', line 315

fn func_new(_ruby: &Ruby, rb_self: Obj<Self>, args: &[Value]) -> Result<Obj<Self>, Error> {
    let args = scan_args::<(RString,), (), (), (), (), Proc>(args)?;
    let (name,) = args.required;
    let callable = args.block;

    let name_str = unsafe { name.as_str() }?;

    // Get parent Linker - we'll store the callable there to prevent GC
    // (rb_self is ephemeral and won't keep references alive after the block ends)
    let parent_linker: Obj<Linker> = Obj::try_convert(rb_self.parent_linker)?;
    parent_linker.refs.borrow_mut().push(callable.as_value());

    // Create the closure that will be called from Wasm
    let func_closure = make_component_func_closure(callable.into());

    let Ok(mut maybe_instance) = rb_self.inner.try_borrow_mut() else {
        return err!("LinkerInstance is not reentrant");
    };

    let inner = maybe_instance.get_mut()?;
    inner
        .func_new(name_str, func_closure)
        .map_err(|e| error!("failed to define host function: {}", e))?;

    Ok(rb_self)
}

#instance(name) {|instance| ... } ⇒ LinkerInstance

Defines a nested instance within the instance.

Parameters:

  • name (String)

Yields:

Yield Parameters:

Returns:



253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
# File 'ext/src/ruby_api/component/linker.rs', line 253

fn instance(ruby: &Ruby, rb_self: Obj<Self>, name: RString) -> Result<Obj<Self>, Error> {
    let Ok(mut maybe_instance) = rb_self.inner.try_borrow_mut() else {
        return err!("LinkerInstance is not reentrant");
    };

    let name_str = unsafe { name.as_str() }?;
    let inner = maybe_instance.get_mut()?;
    let nested_inner = inner.instance(name_str).map_err(|e| error!("{}", e))?;

    // Build nested path: if parent is "", use name; otherwise "parent/name"
    let nested_path = if rb_self.path.is_empty() {
        name_str.to_string()
    } else {
        format!("{}/{}", rb_self.path, name_str)
    };

    let nested_instance = ruby.obj_wrap(LinkerInstance::from_inner(
        nested_inner,
        nested_path,
        rb_self.parent_linker,
    ));
    let block_result: Result<Value, _> = ruby.yield_value(nested_instance);
    nested_instance.take_inner();

    match block_result {
        Ok(_) => Ok(rb_self),
        Err(e) => Err(e),
    }
}

#module(name, mod) ⇒ Object

Parameters:



232
233
234
235
236
237
238
239
240
241
242
243
# File 'ext/src/ruby_api/component/linker.rs', line 232

fn module(rb_self: Obj<Self>, name: RString, module: &Module) -> Result<Obj<Self>, Error> {
    let Ok(mut maybe_instance) = rb_self.inner.try_borrow_mut() else {
        return err!("LinkerInstance is not reentrant");
    };

    let inner = maybe_instance.get_mut()?;
    inner
        .module(unsafe { name.as_str()? }, module.get())
        .map_err(|e| error!("{}", e))?;

    Ok(rb_self)
}