From 0470d7d014f623bb6acf2a57bd71438f500dcfc8 Mon Sep 17 00:00:00 2001 From: Graham Ollis Date: Fri, 4 Nov 2022 06:34:26 -0600 Subject: [PATCH 01/16] add wasmtime 0.28.0 to ci --- .github/workflows/linux.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 680ebcb..db51cbb 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -20,8 +20,8 @@ jobs: - tag: static - tag: "5.37" - tag: "5.36" -# - tag: "5.36" -# wasmtime: "v0.28.0" + - tag: "5.36" + wasmtime: "v0.28.0" - tag: "5.34" - tag: "5.32" - tag: "5.30" From b32556819bfc812c36d9d7decfa756fb36245823 Mon Sep 17 00:00:00 2001 From: Graham Ollis Date: Fri, 4 Nov 2022 11:45:17 -0600 Subject: [PATCH 02/16] remove gc method from store class --- .github/workflows/linux.yml | 2 ++ Changes | 2 ++ dist.ini | 6 +++--- lib/Wasm/Wasmtime/FFI.pm | 17 +++++++++++++++-- lib/Wasm/Wasmtime/Store.pm | 12 ------------ t/00_diag.t | 3 +++ t/wasm_wasmtime_store.t | 1 - 7 files changed, 25 insertions(+), 18 deletions(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index db51cbb..c500a67 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -22,6 +22,8 @@ jobs: - tag: "5.36" - tag: "5.36" wasmtime: "v0.28.0" + - tag: "5.36" + wasmtime: "v0.29.0" - tag: "5.34" - tag: "5.32" - tag: "5.30" diff --git a/Changes b/Changes index f3a97cb..aa32b0c 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,8 @@ Revision history for {{$dist->name}}, {{$NEXT}} + - removed gc method from Wasm::Wasmtime::Store as the method was + removed from wasmtime (gh#118) 0.23 2022-11-04 06:33:12 -0600 - removed wasmtime_config_max_instances_set from Wasm::Wasmtime::Config diff --git a/dist.ini b/dist.ini index 7ce7768..9f4c839 100644 --- a/dist.ini +++ b/dist.ini @@ -30,9 +30,9 @@ diag_preamble = | diag "Wasm::Wasmtime::FFI->_lib = $_" for Wasm::Wasmtime diag_preamble = | }; diag_preamble = | diag "error requiring Wasm::Wasmtime::FFI: $@" if $@; diag_preamble = | }; -;diag_preamble = | spacer(); -;diag_preamble = | require Wasm::Wasmtime::FFI; -;diag_preamble = | diag "is 0.23.0? = ", Wasm::Wasmtime::FFI::_v0_23_0(); +diag_preamble = | spacer(); +diag_preamble = | require Wasm::Wasmtime::FFI; +diag_preamble = | diag "is _ver = ", Wasm::Wasmtime::FFI::_ver(); diag_preamble = | }; [Author::Plicease::Core] diff --git a/lib/Wasm/Wasmtime/FFI.pm b/lib/Wasm/Wasmtime/FFI.pm index 7f01d2b..52d5f9b 100644 --- a/lib/Wasm/Wasmtime/FFI.pm +++ b/lib/Wasm/Wasmtime/FFI.pm @@ -46,11 +46,11 @@ sub _lib return $ENV{WASM_WASMTIME_FFI} if defined $ENV{WASM_WASMTIME_FFI}; my @symbols = ( # 0.19.0 - 'wasmtime_func_as_funcref', + #'wasmtime_func_as_funcref', # removed in 0.28.0 # 0.20.0 / 0.21.0 'wasmtime_module_serialize', 'wasmtime_module_deserialize', - 'wasmtime_store_gc', + #'wasmtime_store_gc', # removed in 0.28.0 ## 0.23.0 'wasmtime_config_consume_fuel_set', #'wasmtime_config_max_instances_set', # removed in 0.27.0 @@ -72,6 +72,19 @@ $ffi->mangler(sub { return $ffi_prefix . $name; }); +if($ffi->find_symbol('wasmtime_config_wasm_multi_memory_set')) +{ + constant->import(_ver => '0.29.0'); +} +elsif($ffi->find_symbol('wasmtime_store_gc')) +{ + constant->import(_ver => '0.27.0'); +} +else +{ + constant->import(_ver => '0.28.0'); +} + { package Wasm::Wasmtime::Vec; use FFI::Platypus::Record; record_layout_1( diff --git a/lib/Wasm/Wasmtime/Store.pm b/lib/Wasm/Wasmtime/Store.pm index 5859f32..b44663e 100644 --- a/lib/Wasm/Wasmtime/Store.pm +++ b/lib/Wasm/Wasmtime/Store.pm @@ -50,18 +50,6 @@ $ffi->attach( new => ['wasm_engine_t'] => 'wasm_store_t' => sub { $self; }); -=head2 gc - - $store->gc; - -Garbage collects Cs that are used within this store. Any -Cs that are discovered to be unreachable by other code or objects -will have their finalizers run. - -=cut - -$ffi->attach( [ wasmtime_store_gc => 'gc' ] => ['wasm_store_t'] => 'void' ); - =head2 engine my $engine = $store->engine; diff --git a/t/00_diag.t b/t/00_diag.t index a657375..8f75ffb 100644 --- a/t/00_diag.t +++ b/t/00_diag.t @@ -43,6 +43,9 @@ $post_diag = sub { }; diag "error requiring Wasm::Wasmtime::FFI: $@" if $@; }; + spacer(); + require Wasm::Wasmtime::FFI; + diag "is _ver = ", Wasm::Wasmtime::FFI::_ver(); }; my @modules = sort keys %modules; diff --git a/t/wasm_wasmtime_store.t b/t/wasm_wasmtime_store.t index 0c33b03..dd2da0a 100644 --- a/t/wasm_wasmtime_store.t +++ b/t/wasm_wasmtime_store.t @@ -10,7 +10,6 @@ is( call engine => object { call ['isa','Wasm::Wasmtime::Engine'] => T(); }; - call_list 'gc' => []; }, 'default engine', ); From fb8c4072cff53588e6a6dfffd2de78fe45871eab Mon Sep 17 00:00:00 2001 From: Graham Ollis Date: Fri, 4 Nov 2022 12:55:54 -0600 Subject: [PATCH 03/16] add context class --- Changes | 6 ++- lib/Wasm/Wasmtime/Context.pm | 61 ++++++++++++++++++++++ lib/Wasm/Wasmtime/FFI.pm | 2 +- lib/Wasm/Wasmtime/Linker.pm | 43 +++++++++------ lib/Wasm/Wasmtime/Store.pm | 87 ++++++++++++++++++++++++++++--- lib/Wasm/Wasmtime/WasiInstance.pm | 47 ++++++++++------- t/wasm_wasmtime_context.t | 19 +++++++ t/wasm_wasmtime_store.t | 1 + t/wasm_wasmtime_wasiinstance.t | 2 + 9 files changed, 221 insertions(+), 47 deletions(-) create mode 100644 lib/Wasm/Wasmtime/Context.pm create mode 100644 t/wasm_wasmtime_context.t diff --git a/Changes b/Changes index aa32b0c..618786d 100644 --- a/Changes +++ b/Changes @@ -1,8 +1,10 @@ Revision history for {{$dist->name}}, {{$NEXT}} - - removed gc method from Wasm::Wasmtime::Store as the method was - removed from wasmtime (gh#118) + - Deprecate gc method from Wasm::Wasmtime::Store. $store->context->gc + should be called instead (gh#118) + - Deprecate get_one_by_name method from Wasm::Wasmtime::Linker (gh#118) + - Added Wasm::Wasmtime::Context class (gh#118) 0.23 2022-11-04 06:33:12 -0600 - removed wasmtime_config_max_instances_set from Wasm::Wasmtime::Config diff --git a/lib/Wasm/Wasmtime/Context.pm b/lib/Wasm/Wasmtime/Context.pm new file mode 100644 index 0000000..efb7a22 --- /dev/null +++ b/lib/Wasm/Wasmtime/Context.pm @@ -0,0 +1,61 @@ +package Wasm::Wasmtime::Context; + +use strict; +use warnings; +use 5.008004; +use Wasm::Wasmtime::FFI; + +# ABSTRACT: Wasmtime context class +# VERSION + +$ffi_prefix = 'wasmtime_context_'; +$ffi->load_custom_type('::PtrObject' => 'wasmtime_context_t' => __PACKAGE__); + +=head1 SYNOPSIS + +# TODO + +=head1 DESCRIPTION + +TODO + +=head1 METHODS + +=head2 get_data + +TODO + +=head2 set_data + +TODO + +=head2 gc + +Garbage collects Cs that are used by this context. Any +Cs that are discovered to be unreachable by other code or objects +will have their finalizers run. + +=cut + +if(_ver ne '0.27.0') +{ + $ffi->attach( gc => ['wasmtime_context_t'] => 'void' ); +} + +=head2 add_fuel + +TODO + +=head2 fuel_consumed + +TODO + +=head2 set_wasi + +TODO + +=cut + +# TODO: class for wasmtime_interrupt_handler + +1; diff --git a/lib/Wasm/Wasmtime/FFI.pm b/lib/Wasm/Wasmtime/FFI.pm index 52d5f9b..bad6422 100644 --- a/lib/Wasm/Wasmtime/FFI.pm +++ b/lib/Wasm/Wasmtime/FFI.pm @@ -39,7 +39,7 @@ This is a private class used internally by L classes. =cut -our @EXPORT = qw( $ffi $ffi_prefix _generate_vec_class _generate_destroy ); +our @EXPORT = qw( $ffi $ffi_prefix _generate_vec_class _generate_destroy _ver ); sub _lib { diff --git a/lib/Wasm/Wasmtime/Linker.pm b/lib/Wasm/Wasmtime/Linker.pm index 507eb85..250ca26 100644 --- a/lib/Wasm/Wasmtime/Linker.pm +++ b/lib/Wasm/Wasmtime/Linker.pm @@ -175,6 +175,8 @@ $ffi->attach( instantiate => ['wasmtime_linker_t','wasm_module_t','opaque*','opa =head2 get_one_by_name +[deprecated: removed from wasmtime in 0.28.0] + my $extern = $linker->get_one_by_name($module,$name); Returns the L for the given C<$module> and C<$name>. @@ -182,22 +184,31 @@ C is returned if there is no such extern with that C<$name>. =cut -$ffi->attach( get_one_by_name => ['wasmtime_linker_t','wasm_byte_vec_t*','wasm_byte_vec_t*','opaque*'] => 'wasmtime_error_t' => sub { - my($xsub, $self, $module, $name) = @_; - my $vmodule = Wasm::Wasmtime::ByteVec->new($module); - my $vname = Wasm::Wasmtime::ByteVec->new($name); - my $ptr; - if(my $error = $xsub->($self, $vmodule, $vname, \$ptr)) - { - Carp::croak($error->message); - } - else - { - $ptr - ? $ffi->cast('opaque','wasm_extern_t',$ptr) - : undef; - } -}); +if(_ver ne '0.27.0') +{ + *get_one_by_name = sub { + Carp::croak("get_one_by_name is unavailable in 0.28.0 and newer"); + }; +} +else +{ + $ffi->attach( get_one_by_name => ['wasmtime_linker_t','wasm_byte_vec_t*','wasm_byte_vec_t*','opaque*'] => 'wasmtime_error_t' => sub { + my($xsub, $self, $module, $name) = @_; + my $vmodule = Wasm::Wasmtime::ByteVec->new($module); + my $vname = Wasm::Wasmtime::ByteVec->new($name); + my $ptr; + if(my $error = $xsub->($self, $vmodule, $vname, \$ptr)) + { + Carp::croak($error->message); + } + else + { + $ptr + ? $ffi->cast('opaque','wasm_extern_t',$ptr) + : undef; + } + }); +} =head2 get_default diff --git a/lib/Wasm/Wasmtime/Store.pm b/lib/Wasm/Wasmtime/Store.pm index b44663e..ae4c4ee 100644 --- a/lib/Wasm/Wasmtime/Store.pm +++ b/lib/Wasm/Wasmtime/Store.pm @@ -4,6 +4,7 @@ use strict; use warnings; use 5.008004; use Wasm::Wasmtime::FFI; +use Wasm::Wasmtime::Context; use Wasm::Wasmtime::Engine; # TODO: wasmtime_store_add_fuel @@ -25,7 +26,15 @@ This class represents storage used by the WebAssembly engine. =cut -$ffi_prefix = 'wasm_store_'; +if(_ver ne '0.27.0') +{ + $ffi_prefix = 'wasmtime_store_'; +} +else +{ + $ffi_prefix = 'wasm_store_'; +} +# TODO: we should change this to a wasmtime_store_t at some point $ffi->load_custom_type('::PtrObject' => 'wasm_store_t' => __PACKAGE__); =head1 CONSTRUCTOR @@ -42,13 +51,75 @@ isn't provided, then a new one will be created. =cut -$ffi->attach( new => ['wasm_engine_t'] => 'wasm_store_t' => sub { - my($xsub, $class, $engine) = @_; - $engine ||= Wasm::Wasmtime::Engine->new; - my $self = $xsub->($engine); - $self->{engine} = $engine; - $self; -}); +if(_ver ne '0.27.0') +{ + $ffi->attach( new => ['wasm_engine_t','opaque','(opaque)->void'] => 'wasm_store_t' => sub { + my($xsub, $class, $engine) = @_; + $engine ||= Wasm::Wasmtime::Engine->new; + my $self = $xsub->($engine,undef,undef); + $self->{engine} = $engine; + $self; + }); +} +else +{ + $ffi->attach( new => ['wasm_engine_t'] => 'wasm_store_t' => sub { + my($xsub, $class, $engine) = @_; + $engine ||= Wasm::Wasmtime::Engine->new; + my $self = $xsub->($engine); + $self->{engine} = $engine; + $self; + }); +} + +=head2 context + + my $context = $store->context; + +Returns the L for this store. + +=cut + +if(_ver ne '0.27.0') +{ + $ffi->attach( context => ['wasm_store_t'] => 'wasmtime_context_t' => sub { + my($xsub, $self) = @_; + my $context = $xsub->($self); + $context->{store} = $self; + $context; + }); +} +else +{ + *context = sub { + require Carp; + Carp::croak("Context is not available in 0.27.0"); + }; +} + +=head2 gc + +[deprecated use $store->context->gc instead] + + $store->gc; + +Garbage collects Cs that are used within this store. Any +Cs that are discovered to be unreachable by other code or objects +will have their finalizers run. + +=cut + +if(_ver ne '0.27.0') +{ + *gc = sub { + my($self) = @_; + $self->context->gc; + }; +} +else +{ + $ffi->attach( [ wasmtime_store_gc => 'gc' ] => ['wasm_store_t'] => 'void' ); +} =head2 engine diff --git a/lib/Wasm/Wasmtime/WasiInstance.pm b/lib/Wasm/Wasmtime/WasiInstance.pm index 0c8d3a7..64a3118 100644 --- a/lib/Wasm/Wasmtime/WasiInstance.pm +++ b/lib/Wasm/Wasmtime/WasiInstance.pm @@ -52,29 +52,36 @@ Create a new WASI instance. =cut -$ffi->attach( new => ['wasm_store_t', 'string', 'wasi_config_t', 'opaque*'] => 'wasi_instance_t' => sub { - my $xsub = shift; - my $class = shift; - my $store = shift; - my $name = shift; - my $config = defined $_[0] && ref($_[0]) eq 'Wasm::Wasmtime::WasiConfig' ? shift : Wasm::Wasmtime::WasiConfig->new; - my $trap; - my $instance = $xsub->($store, $name, $config, \$trap); - delete $config->{ptr}; - unless($instance) - { - if($trap) +if(_ver ne '0.27.0') +{ + *new = sub { + Carp::croak("WasiInstance is unavailable in 0.28.0 and newer"); + }; +} +else +{ + $ffi->attach( new => ['wasm_store_t', 'string', 'wasi_config_t', 'opaque*'] => 'wasi_instance_t' => sub { + my $xsub = shift; + my $class = shift; + my $store = shift; + my $name = shift; + my $config = defined $_[0] && ref($_[0]) eq 'Wasm::Wasmtime::WasiConfig' ? shift : Wasm::Wasmtime::WasiConfig->new; + my $trap; + my $instance = $xsub->($store, $name, $config, \$trap); + delete $config->{ptr}; + unless($instance) { - die Wasm::Wasmtime::Trap->new($trap); + if($trap) + { + die Wasm::Wasmtime::Trap->new($trap); + } + Carp::croak("failed to create wasi instance"); } - Carp::croak("failed to create wasi instance"); - } - $instance; -}); + $instance; + }); -# TODO: bind_import - -_generate_destroy(); + _generate_destroy(); +} 1; diff --git a/t/wasm_wasmtime_context.t b/t/wasm_wasmtime_context.t new file mode 100644 index 0000000..be25e5d --- /dev/null +++ b/t/wasm_wasmtime_context.t @@ -0,0 +1,19 @@ +use 5.008004; +use Test2::V0 -no_srand => 1; +use Wasm::Wasmtime::Store; +use Wasm::Wasmtime::Context; + +skip_all '0.28.0 and better only' unless Wasm::Wasmtime::FFI::_ver ne '0.27.0'; + +is( + Wasm::Wasmtime::Store->new, + object { + call context => object { + call [ isa => 'Wasm::Wasmtime::Context' ] => T(); + call gc => U(); + }; + }, + 'default' +); + +done_testing; diff --git a/t/wasm_wasmtime_store.t b/t/wasm_wasmtime_store.t index dd2da0a..30d69da 100644 --- a/t/wasm_wasmtime_store.t +++ b/t/wasm_wasmtime_store.t @@ -9,6 +9,7 @@ is( call ['isa','Wasm::Wasmtime::Store'] => T(); call engine => object { call ['isa','Wasm::Wasmtime::Engine'] => T(); + call gc => U(); }; }, 'default engine', diff --git a/t/wasm_wasmtime_wasiinstance.t b/t/wasm_wasmtime_wasiinstance.t index fa01aa4..8fb5930 100644 --- a/t/wasm_wasmtime_wasiinstance.t +++ b/t/wasm_wasmtime_wasiinstance.t @@ -4,6 +4,8 @@ use Wasm::Wasmtime::Store; use Wasm::Wasmtime::WasiConfig; use Wasm::Wasmtime::WasiInstance; +skip_all '0.27.0 and earlier only' unless Wasm::Wasmtime::FFI::_ver eq '0.27.0'; + is( Wasm::Wasmtime::WasiInstance->new(Wasm::Wasmtime::Store->new, "wasi_snapshot_preview1"), object { From 475ad0e19ae7a4177da47daa7e77679390345204 Mon Sep 17 00:00:00 2001 From: Graham Ollis Date: Fri, 4 Nov 2022 13:06:20 -0600 Subject: [PATCH 04/16] update signature for wat2wasm --- lib/Wasm/Wasmtime/Wat2Wasm.pm | 55 +++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/lib/Wasm/Wasmtime/Wat2Wasm.pm b/lib/Wasm/Wasmtime/Wat2Wasm.pm index b00da50..c3af141 100644 --- a/lib/Wasm/Wasmtime/Wat2Wasm.pm +++ b/lib/Wasm/Wasmtime/Wat2Wasm.pm @@ -37,22 +37,45 @@ Takes WebAssembly Text C<$wat> and converts it into the WebAssembly binary C<$wa =cut -$ffi->attach( wat2wasm => ['wasm_byte_vec_t*','wasm_byte_vec_t*'] => 'wasmtime_error_t' => sub { - my $xsub = shift; - my $wat = Wasm::Wasmtime::ByteVec->new($_[0]); - my $ret = Wasm::Wasmtime::ByteVec->new; - my $error = $xsub->($wat, $ret); - if($error) - { - Carp::croak($error->message . "\nwat2wasm error"); - } - else - { - my $wasm = $ret->get; - $ret->delete; - return $wasm; - } -}); +if(_ver ne '0.27.0') +{ + require FFI::Platypus::Buffer; + $ffi->attach( wat2wasm => ['opaque','size_t','wasm_byte_vec_t*'] => 'wasmtime_error_t' => sub { + my $xsub = shift; + my($ptr, $len) = FFI::Platypus::Buffer::scalar_to_buffer $_[0]; + my $ret = Wasm::Wasmtime::ByteVec->new; + my $error = $xsub->($ptr, $len, $ret); + if($error) + { + Carp::croak($error->message . "\nwat2wasm error"); + } + else + { + my $wasm = $ret->get; + $ret->delete; + return $wasm; + } + }); +} +else +{ + $ffi->attach( wat2wasm => ['wasm_byte_vec_t*','wasm_byte_vec_t*'] => 'wasmtime_error_t' => sub { + my $xsub = shift; + my $wat = Wasm::Wasmtime::ByteVec->new($_[0]); + my $ret = Wasm::Wasmtime::ByteVec->new; + my $error = $xsub->($wat, $ret); + if($error) + { + Carp::croak($error->message . "\nwat2wasm error"); + } + else + { + my $wasm = $ret->get; + $ret->delete; + return $wasm; + } + }); +} 1; From 1d52b461c7bfbd09dde38b54495a4fb7f026f960 Mon Sep 17 00:00:00 2001 From: Graham Ollis Date: Sun, 6 Nov 2022 05:16:32 -0700 Subject: [PATCH 05/16] partial refactor of module interface --- lib/Wasm/Wasmtime/Config.pm | 2 +- lib/Wasm/Wasmtime/Module.pm | 255 ++++++++++++++++++++++++++---------- lib/Wasm/Wasmtime/Store.pm | 4 +- t/wasm_wasmtime_module.t | 163 +++++++++++++---------- t/wasm_wasmtime_wat2wasm.t | 7 +- 5 files changed, 284 insertions(+), 147 deletions(-) diff --git a/lib/Wasm/Wasmtime/Config.pm b/lib/Wasm/Wasmtime/Config.pm index e27ffcf..2a6f0b6 100644 --- a/lib/Wasm/Wasmtime/Config.pm +++ b/lib/Wasm/Wasmtime/Config.pm @@ -37,7 +37,7 @@ Create a new instance of the config class. $ffi->attach( new => [] => 'wasm_config_t' ); -_generate_destroy(); +#_generate_destroy(); =head1 METHODS diff --git a/lib/Wasm/Wasmtime/Module.pm b/lib/Wasm/Wasmtime/Module.pm index 024363a..72f6332 100644 --- a/lib/Wasm/Wasmtime/Module.pm +++ b/lib/Wasm/Wasmtime/Module.pm @@ -30,50 +30,97 @@ This class represents a WebAssembly module. =cut -$ffi_prefix = 'wasm_module_'; $ffi->load_custom_type('::PtrObject' => 'wasm_module_t' => __PACKAGE__); -sub _args +if(_ver ne '0.27.0') { - my $wasm; - my $data; - if(@_ == 1) - { - $data = shift; - $wasm = Wasm::Wasmtime::ByteVec->new($data); - } - else + $ffi_prefix = 'wasmtime_module_'; + + require FFI::Platypus::Buffer; + *_args = sub { - my $key = shift; - if($key eq 'wat') + my $data; + if(@_ == 1) { - require Wasm::Wasmtime::Wat2Wasm; - $data = Wasm::Wasmtime::Wat2Wasm::wat2wasm(shift); - $wasm = Wasm::Wasmtime::ByteVec->new($data); + $data = shift; } - elsif($key eq 'wasm') + else + { + my $key = shift; + if($key eq 'wat') + { + require Wasm::Wasmtime::Wat2Wasm; + $data = Wasm::Wasmtime::Wat2Wasm::wat2wasm(shift); + } + elsif($key eq 'wasm') + { + $data = shift; + } + elsif($key eq 'file') + { + require Wasm::Wasmtime::Wat2Wasm; + require Path::Tiny; + my $path = Path::Tiny->new(shift); + if($path->basename =~ /\.wat/) + { + $data = Wasm::Wasmtime::Wat2Wasm::wat2wasm($path->slurp_utf8); + } + else + { + $data = $path->slurp_raw; + } + } + } + + (FFI::Platypus::Buffer::scalar_to_buffer($data), \$data); # need to return the data in order to keep it in scope + }; +} +else +{ + $ffi_prefix = 'wasm_module_'; + + *_args = sub + { + my $wasm; + my $data; + if(@_ == 1) { $data = shift; $wasm = Wasm::Wasmtime::ByteVec->new($data); } - elsif($key eq 'file') + else { - require Wasm::Wasmtime::Wat2Wasm; - require Path::Tiny; - my $path = Path::Tiny->new(shift); - if($path->basename =~ /\.wat/) + my $key = shift; + if($key eq 'wat') { - $data = Wasm::Wasmtime::Wat2Wasm::wat2wasm($path->slurp_utf8); + require Wasm::Wasmtime::Wat2Wasm; + $data = Wasm::Wasmtime::Wat2Wasm::wat2wasm(shift); $wasm = Wasm::Wasmtime::ByteVec->new($data); } - else + elsif($key eq 'wasm') { - $data = $path->slurp_raw; + $data = shift; $wasm = Wasm::Wasmtime::ByteVec->new($data); } + elsif($key eq 'file') + { + require Wasm::Wasmtime::Wat2Wasm; + require Path::Tiny; + my $path = Path::Tiny->new(shift); + if($path->basename =~ /\.wat/) + { + $data = Wasm::Wasmtime::Wat2Wasm::wat2wasm($path->slurp_utf8); + $wasm = Wasm::Wasmtime::ByteVec->new($data); + } + else + { + $data = $path->slurp_raw; + $wasm = Wasm::Wasmtime::ByteVec->new($data); + } + } } - } - (\$wasm, \$data); + (\$wasm, \$data); + }; } =head1 CONSTRUCTORS @@ -127,33 +174,66 @@ be found from the store. This form will be removed in a future version. =cut -$ffi->attach( [ wasmtime_module_new => 'new' ] => ['wasm_engine_t', 'wasm_byte_vec_t*', 'opaque*'] => 'wasmtime_error_t' => sub { - my $xsub = shift; - my $class = shift; - my $store; - my $engine; - if(defined $_[0] && is_blessed_ref $_[0]) - { - if($_[0]->isa('Wasm::Wasmtime::Engine')) +if(_ver ne '0.27.0') +{ + $ffi->attach( new => ['wasm_engine_t', 'opaque', 'size_t', 'opaque*'] => 'wasmtime_error_t' => sub { + my $xsub = shift; + my $class = shift; + my $store; + my $engine; + if(defined $_[0] && is_blessed_ref $_[0]) { - $engine = shift; + if($_[0]->isa('Wasm::Wasmtime::Engine')) + { + $engine = shift; + } + elsif($_[0]->isa('Wasm::Wasmtime::Store')) + { + Carp::carp("Passing a Wasm::Wasmtime::Store into the module constructor is deprecated, please pass a Wasm::Wasmtime::Engine object instead"); + $store = shift; + $engine = $store->engine; + } } - elsif($_[0]->isa('Wasm::Wasmtime::Store')) + $engine ||= Wasm::Wasmtime::Engine->new; + my($wasm_ptr, $wasm_len, $data) = _args(@_); + my $module_ptr; + if(my $error = $xsub->($engine, $wasm_ptr, $wasm_len, \$module_ptr)) { - Carp::carp("Passing a Wasm::Wasmtime::Store into the module constructor is deprecated, please pass a Wasm::Wasmtime::Engine object instead"); - $store = shift; - $engine = $store->engine; + Carp::croak("error creating module: " . $error->message); } - } - $engine ||= Wasm::Wasmtime::Engine->new; - my($wasm, $data) = _args(@_); - my $ptr; - if(my $error = $xsub->($engine, $$wasm, \$ptr)) - { - Carp::croak("error creating module: " . $error->message); - } - bless { ptr => $ptr, engine => $engine, store => $store }, $class; -}); + bless { ptr => $module_ptr, engine => $engine, store => $store }, $class; + }); +} +else +{ + $ffi->attach( [ wasmtime_module_new => 'new' ] => ['wasm_engine_t', 'wasm_byte_vec_t*', 'opaque*'] => 'wasmtime_error_t' => sub { + my $xsub = shift; + my $class = shift; + my $store; + my $engine; + if(defined $_[0] && is_blessed_ref $_[0]) + { + if($_[0]->isa('Wasm::Wasmtime::Engine')) + { + $engine = shift; + } + elsif($_[0]->isa('Wasm::Wasmtime::Store')) + { + Carp::carp("Passing a Wasm::Wasmtime::Store into the module constructor is deprecated, please pass a Wasm::Wasmtime::Engine object instead"); + $store = shift; + $engine = $store->engine; + } + } + $engine ||= Wasm::Wasmtime::Engine->new; + my($wasm, $data) = _args(@_); + my $ptr; + if(my $error = $xsub->($engine, $$wasm, \$ptr)) + { + Carp::croak("error creating module: " . $error->message); + } + bless { ptr => $ptr, engine => $engine, store => $store }, $class; + }); +} =head2 deserialize @@ -169,6 +249,7 @@ Build a module from serialized data. The serialized data can be gotten from the =cut +# TODO remove prefix when bump to 0.28.0 $ffi->attach( [ wasmtime_module_deserialize => 'deserialize' ] => ['wasm_engine_t', 'wasm_byte_vec_t*', 'opaque*'] => 'wasmtime_error_t' => sub { my $xsub = shift; my $class = shift; @@ -215,16 +296,33 @@ a useful diagnostic for why it was invalid. =cut -$ffi->attach( [ wasmtime_module_validate => 'validate' ] => ['wasm_store_t', 'wasm_byte_vec_t*'] => 'wasmtime_error_t' => sub { - my $xsub = shift; - my $class = shift; - my $store = defined $_[0] && ref($_[0]) eq 'Wasm::Wasmtime::Store' ? shift : Wasm::Wasmtime::Store->new; - my($wasm, $data) = _args(@_); - my $error = $xsub->($store, $$wasm); - wantarray ## no critic (Community::Wantarray) - ? $error ? (0, $error->message) : (1, '') - : $error ? 0 : 1; -}); +if(_ver ne '0.27.0') +{ + $ffi->attach( validate => ['wasm_engine_t', 'opaque', 'size_t'] => 'wasmtime_error_t' => sub { + my $xsub = shift; + my $class = shift; + # TODO: we should deprecate passing a store into this + my $store = defined $_[0] && ref($_[0]) eq 'Wasm::Wasmtime::Store' ? shift : Wasm::Wasmtime::Store->new; + my($ptr, $len, $data) = _args(@_); + my $error = $xsub->($store->engine, $ptr, $len); + wantarray ## no critic (Community::Wantarray) + ? $error ? (0, $error->message) : (1, '') + : $error ? 0 : 1; + }); +} +else +{ + $ffi->attach( [ wasmtime_module_validate => 'validate' ] => ['wasm_store_t', 'wasm_byte_vec_t*'] => 'wasmtime_error_t' => sub { + my $xsub = shift; + my $class = shift; + my $store = defined $_[0] && ref($_[0]) eq 'Wasm::Wasmtime::Store' ? shift : Wasm::Wasmtime::Store->new; + my($wasm, $data) = _args(@_); + my $error = $xsub->($store, $$wasm); + wantarray ## no critic (Community::Wantarray) + ? $error ? (0, $error->message) : (1, '') + : $error ? 0 : 1; + }); +} =head2 exports @@ -239,12 +337,18 @@ sub exports Wasm::Wasmtime::Module::Exports->new(shift); } -$ffi->attach( [ exports => '_exports' ]=> [ 'wasm_module_t', 'wasm_exporttype_vec_t*' ] => sub { - my($xsub, $self) = @_; - my $exports = Wasm::Wasmtime::ExportTypeVec->new; - $xsub->($self, $exports); - $exports->to_list; -}); +if(_ver ne '0.27.0') +{ +} +else +{ + $ffi->attach( [ exports => '_exports' ]=> [ 'wasm_module_t', 'wasm_exporttype_vec_t*' ] => sub { + my($xsub, $self) = @_; + my $exports = Wasm::Wasmtime::ExportTypeVec->new; + $xsub->($self, $exports); + $exports->to_list; + }); +} =head2 imports @@ -259,12 +363,18 @@ sub imports Wasm::Wasmtime::Module::Imports->new(shift); } -$ffi->attach( [ imports => '_imports' ] => [ 'wasm_module_t', 'wasm_importtype_vec_t*' ] => sub { - my($xsub, $self) = @_; - my $imports = Wasm::Wasmtime::ImportTypeVec->new; - $xsub->($self, $imports); - $imports->to_list; -}); +if(_ver ne '0.27.0') +{ +} +else +{ + $ffi->attach( [ imports => '_imports' ] => [ 'wasm_module_t', 'wasm_importtype_vec_t*' ] => sub { + my($xsub, $self) = @_; + my $imports = Wasm::Wasmtime::ImportTypeVec->new; + $xsub->($self, $imports); + $imports->to_list; + }); +} =head2 serialize @@ -275,7 +385,8 @@ C constructor method documented above. =cut -$ffi->attach( [ 'wasmtime_module_serialize' => 'serialize' ] => [ 'wasm_module_t', 'wasm_byte_vec_t*' ] => 'wasmtime_error_t' => sub { +# TODO remove prefix when bump to 0.28.0 +$ffi->attach( [ wasmtime_module_serialize => 'serialize' ] => [ 'wasm_module_t', 'wasm_byte_vec_t*' ] => 'wasmtime_error_t' => sub { my($xsub, $self) = @_; my $s = Wasm::Wasmtime::ByteVec->new; if(my $error = $xsub->($self, $s)) diff --git a/lib/Wasm/Wasmtime/Store.pm b/lib/Wasm/Wasmtime/Store.pm index ae4c4ee..d3184f9 100644 --- a/lib/Wasm/Wasmtime/Store.pm +++ b/lib/Wasm/Wasmtime/Store.pm @@ -84,9 +84,7 @@ if(_ver ne '0.27.0') { $ffi->attach( context => ['wasm_store_t'] => 'wasmtime_context_t' => sub { my($xsub, $self) = @_; - my $context = $xsub->($self); - $context->{store} = $self; - $context; + $self->{context} || $xsub->($self); }); } else diff --git a/t/wasm_wasmtime_module.t b/t/wasm_wasmtime_module.t index 63d69e6..0766e88 100644 --- a/t/wasm_wasmtime_module.t +++ b/t/wasm_wasmtime_module.t @@ -7,8 +7,91 @@ use Wasm::Wasmtime::Store; use Wasm::Wasmtime::Module; use Wasm::Wasmtime::Wat2Wasm; +my $wasm_binary = "\0asm\x01\0\0\0"; + +subtest 'validate' => sub { + + is( + scalar(Wasm::Wasmtime::Module->validate($wasm_binary)), + T(), + 'validate good raw', + ); + + is( + scalar(Wasm::Wasmtime::Module->validate(wat2wasm('(module)'))), + T(), + 'validate good from wat2wasm', + ); + + is( + [Wasm::Wasmtime::Module->validate(wat2wasm('(module)'))], + array { + item T(); + item ''; + end; + }, + 'validate good, list context', + ); + + is( + scalar(Wasm::Wasmtime::Module->validate( wat => '(module)' )), + T(), + 'validate good, key wat', + ); + + is( + scalar(Wasm::Wasmtime::Module->validate(Wasm::Wasmtime::Store->new, wat2wasm('(module)'))), + T(), + 'validate good with store', + ); + + is( + scalar(Wasm::Wasmtime::Module->validate(Wasm::Wasmtime::Store->new, wat => '(module)')), + T(), + 'validate good with store, key wat', + ); + + is( + scalar(Wasm::Wasmtime::Module->validate('f00f')), + F(), + 'validate bad', + ); + + is( + [Wasm::Wasmtime::Module->validate('f00f')], + array { + item F(); + item match qr/./; + end; + }, + 'validate bad, list context', + ); + + is( + scalar(Wasm::Wasmtime::Module->validate(Wasm::Wasmtime::Store->new, 'f00f')), + F(), + 'validate bad with store', + ); +}; + +subtest 'error' => sub { + is( + dies { Wasm::Wasmtime::Module->new('f00f') }, + match qr/error creating module/, + 'exception for bad wasm', + ); +}; + is( - Wasm::Wasmtime::Module->new(wat2wasm('(module)')), + Wasm::Wasmtime::Module->new(Wasm::Wasmtime::Engine->new, $wasm_binary), + object { + call ['isa', 'Wasm::Wasmtime::Module'] => T(); + }, + 'basic create', +); + +is( + Wasm::Wasmtime::Module->new(Wasm::Wasmtime::Engine->new, wat2wasm('(module)')), object { call ['isa', 'Wasm::Wasmtime::Module'] => T(); call engine => object { @@ -17,23 +100,24 @@ is( call to_string => "(module)\n"; call serialize => match qr/./; }, - 'autocreate engine', + 'explicit engine', ); is( - Wasm::Wasmtime::Module->deserialize(Wasm::Wasmtime::Module->new(wat2wasm('(module)'))->serialize), + Wasm::Wasmtime::Module->new(wat2wasm('(module)')), object { call ['isa', 'Wasm::Wasmtime::Module'] => T(); call engine => object { call ['isa', 'Wasm::Wasmtime::Engine'] => T(); }; call to_string => "(module)\n"; + call serialize => match qr/./; }, - 'created module from serealized', + 'autocreate engine', ); is( - Wasm::Wasmtime::Module->deserialize(Wasm::Wasmtime::Engine->new, Wasm::Wasmtime::Module->new(wat2wasm('(module)'))->serialize), + Wasm::Wasmtime::Module->deserialize(Wasm::Wasmtime::Module->new(wat2wasm('(module)'))->serialize), object { call ['isa', 'Wasm::Wasmtime::Module'] => T(); call engine => object { @@ -41,24 +125,19 @@ is( }; call to_string => "(module)\n"; }, - 'created module from store + serealized', -); - -is( - dies { Wasm::Wasmtime::Module->new('f00f') }, - match qr/error creating module/, - 'exception for bad wasm', + 'created module from serealized', ); is( - Wasm::Wasmtime::Module->new(Wasm::Wasmtime::Engine->new, wat2wasm('(module)')), + Wasm::Wasmtime::Module->deserialize(Wasm::Wasmtime::Engine->new, Wasm::Wasmtime::Module->new(wat2wasm('(module)'))->serialize), object { call ['isa', 'Wasm::Wasmtime::Module'] => T(); call engine => object { call ['isa', 'Wasm::Wasmtime::Engine'] => T(); }; + call to_string => "(module)\n"; }, - 'explicit engine', + 'created module from store + serealized', ); { @@ -128,62 +207,6 @@ is( 'file key', ); -is( - scalar(Wasm::Wasmtime::Module->validate(wat2wasm('(module)'))), - T(), - 'validate good', -); - -is( - [Wasm::Wasmtime::Module->validate(wat2wasm('(module)'))], - array { - item T(); - item ''; - end; - }, - 'validate good, list context', -); - -is( - scalar(Wasm::Wasmtime::Module->validate( wat => '(module)' )), - T(), - 'validate good, key wat', -); - -is( - scalar(Wasm::Wasmtime::Module->validate(Wasm::Wasmtime::Store->new, wat2wasm('(module)'))), - T(), - 'validate good with store', -); - -is( - scalar(Wasm::Wasmtime::Module->validate(Wasm::Wasmtime::Store->new, wat => '(module)')), - T(), - 'validate good with store, key wat', -); - -is( - scalar(Wasm::Wasmtime::Module->validate('f00f')), - F(), - 'validate bad', -); - -is( - [Wasm::Wasmtime::Module->validate('f00f')], - array { - item F(); - item match qr/./; - end; - }, - 'validate bad, list context', -); - -is( - scalar(Wasm::Wasmtime::Module->validate(Wasm::Wasmtime::Store->new, 'f00f')), - F(), - 'validate bad with store', -); - is( Wasm::Wasmtime::Module->new(wat => q{ (module diff --git a/t/wasm_wasmtime_wat2wasm.t b/t/wasm_wasmtime_wat2wasm.t index e392e6d..b0b3156 100644 --- a/t/wasm_wasmtime_wat2wasm.t +++ b/t/wasm_wasmtime_wat2wasm.t @@ -4,8 +4,10 @@ use Wasm::Wasmtime::Wat2Wasm; imported_ok 'wat2wasm'; +my $binary; + is( - wat2wasm('(module)'), + $binary = wat2wasm('(module)'), D(), 'okay with good module', ); @@ -16,4 +18,7 @@ is( 'dies with bad input', ); +use YAML(); +note YAML::Dump(\$binary); + done_testing; From a13df3c12c3d84f5d52a0d4d6e232de75b28230f Mon Sep 17 00:00:00 2001 From: Graham Ollis Date: Sun, 6 Nov 2022 06:56:46 -0700 Subject: [PATCH 06/16] module test works --- lib/Wasm/Wasmtime/FFI.pm | 4 ++ lib/Wasm/Wasmtime/Module.pm | 97 +++++++++++++++++++++++++-------- lib/Wasm/Wasmtime/ModuleType.pm | 67 +++++++++++++++++++++++ t/wasm_wasmtime_module.t | 6 ++ t/wasm_wasmtime_moduletype.t | 23 ++++++++ 5 files changed, 173 insertions(+), 24 deletions(-) create mode 100644 lib/Wasm/Wasmtime/ModuleType.pm create mode 100644 t/wasm_wasmtime_moduletype.t diff --git a/lib/Wasm/Wasmtime/FFI.pm b/lib/Wasm/Wasmtime/FFI.pm index bad6422..ee3bfaa 100644 --- a/lib/Wasm/Wasmtime/FFI.pm +++ b/lib/Wasm/Wasmtime/FFI.pm @@ -191,6 +191,10 @@ sub _generate_destroy { $type =~ s/^.*::wasi(.*)$/wasi_${1}_t/g; } + elsif($type =~ /::moduletype/) + { + $type = 'wasmtime_moduletype_t'; + } else { $type =~ s/^.*:://; diff --git a/lib/Wasm/Wasmtime/Module.pm b/lib/Wasm/Wasmtime/Module.pm index 72f6332..054deee 100644 --- a/lib/Wasm/Wasmtime/Module.pm +++ b/lib/Wasm/Wasmtime/Module.pm @@ -9,6 +9,7 @@ use Wasm::Wasmtime::Engine; use Wasm::Wasmtime::Store; use Wasm::Wasmtime::Module::Exports; use Wasm::Wasmtime::Module::Imports; +use Wasm::Wasmtime::ModuleType; use Wasm::Wasmtime::ImportType; use Wasm::Wasmtime::ExportType; use Ref::Util qw( is_blessed_ref ); @@ -249,20 +250,39 @@ Build a module from serialized data. The serialized data can be gotten from the =cut -# TODO remove prefix when bump to 0.28.0 -$ffi->attach( [ wasmtime_module_deserialize => 'deserialize' ] => ['wasm_engine_t', 'wasm_byte_vec_t*', 'opaque*'] => 'wasmtime_error_t' => sub { - my $xsub = shift; - my $class = shift; - my $engine; - $engine = defined $_[0] && is_blessed_ref $_[0] && $_[0]->isa('Wasm::Wasmtime::Engine') ? shift : Wasm::Wasmtime::Engine->new; - my $serialized = Wasm::Wasmtime::ByteVec->new($_[0]); - my $ptr; - if(my $error = $xsub->($engine, $serialized, \$ptr)) - { - Carp::croak("error creating module: " . $error->message); - } - bless { ptr => $ptr, store => undef, engine => $engine }, $class; -}); +if(_ver ne '0.27.0') +{ + require FFI::Platypus::Buffer; + $ffi->attach( deserialize => ['wasm_engine_t', 'opaque', 'size_t', 'opaque*'] => 'wasmtime_error_t' => sub { + my $xsub = shift; + my $class = shift; + my $engine; + $engine = defined $_[0] && is_blessed_ref $_[0] && $_[0]->isa('Wasm::Wasmtime::Engine') ? shift : Wasm::Wasmtime::Engine->new; + my($serialized_ptr, $serialized_len) = FFI::Platypus::Buffer::scalar_to_buffer($_[0]); + my $module_ptr; + if(my $error = $xsub->($engine, $serialized_ptr, $serialized_len, \$module_ptr)) + { + Carp::croak("error creating module: " . $error->message); + } + bless { ptr => $module_ptr, store => undef, engine => $engine }, $class; + }); +} +else +{ + $ffi->attach( [ wasmtime_module_deserialize => 'deserialize' ] => ['wasm_engine_t', 'wasm_byte_vec_t*', 'opaque*'] => 'wasmtime_error_t' => sub { + my $xsub = shift; + my $class = shift; + my $engine; + $engine = defined $_[0] && is_blessed_ref $_[0] && $_[0]->isa('Wasm::Wasmtime::Engine') ? shift : Wasm::Wasmtime::Engine->new; + my $serialized = Wasm::Wasmtime::ByteVec->new($_[0]); + my $ptr; + if(my $error = $xsub->($engine, $serialized, \$ptr)) + { + Carp::croak("error creating module: " . $error->message); + } + bless { ptr => $ptr, store => undef, engine => $engine }, $class; + }); +} =head1 METHODS @@ -324,24 +344,48 @@ else }); } -=head2 exports +=head2 type - my $exports = $module->exports; + my $type = $module->type; -Returns a L object that can be used to query the module exports. +Returns a L instance that can be used to get the module exports and +imports. =cut -sub exports +if(_ver ne '0.27.0') { - Wasm::Wasmtime::Module::Exports->new(shift); + $ffi->attach( type => ['wasm_module_t'] => 'wasmtime_moduletype_t'); } +else +{ + *type = sub { + Carp::croak("The Module type method is only available in 0.28.0 and newer"); + }; +} + +=head2 exports + + my $exports = $module->exports; + +Returns a L object that can be used to query the module exports. + +=cut if(_ver ne '0.27.0') { + *exports = sub { + my($self) = @_; + $self->type->exports; + }; } else { + *exports = sub + { + Wasm::Wasmtime::Module::Exports->new(shift); + }; + $ffi->attach( [ exports => '_exports' ]=> [ 'wasm_module_t', 'wasm_exporttype_vec_t*' ] => sub { my($xsub, $self) = @_; my $exports = Wasm::Wasmtime::ExportTypeVec->new; @@ -358,16 +402,20 @@ Returns a list of L objects for the objects imported =cut -sub imports -{ - Wasm::Wasmtime::Module::Imports->new(shift); -} - if(_ver ne '0.27.0') { + *imports = sub { + my($self) = @_; + $self->type->imports; + }; } else { + *imports = sub + { + Wasm::Wasmtime::Module::Imports->new(shift); + }; + $ffi->attach( [ imports => '_imports' ] => [ 'wasm_module_t', 'wasm_importtype_vec_t*' ] => sub { my($xsub, $self) = @_; my $imports = Wasm::Wasmtime::ImportTypeVec->new; @@ -447,3 +495,4 @@ _generate_destroy(); =back =cut + diff --git a/lib/Wasm/Wasmtime/ModuleType.pm b/lib/Wasm/Wasmtime/ModuleType.pm new file mode 100644 index 0000000..e30d749 --- /dev/null +++ b/lib/Wasm/Wasmtime/ModuleType.pm @@ -0,0 +1,67 @@ +package Wasm::Wasmtime::ModuleType; + +use strict; +use warnings; +use 5.008004; +use Wasm::Wasmtime::FFI; +use Wasm::Wasmtime::Module::Exports; +use Wasm::Wasmtime::Module::Imports; +use Wasm::Wasmtime::ImportType; +use Wasm::Wasmtime::ExportType; + +# ABSTRACT: Wasmtime context class +# VERSION + +$ffi_prefix = 'wasmtime_moduletype_'; +$ffi->load_custom_type('::PtrObject' => 'wasmtime_moduletype_t' => __PACKAGE__); + +=head1 SYNOPSIS + +# TODO + +=head1 DESCRIPTION + +TODO + +=head1 METHODS + +=head2 imports + +# TODO + +=head2 exports + +# TODO + +=cut + +if(_ver ne '0.27.0') +{ + $ffi->attach( [ imports => '_imports' ] => ['wasmtime_moduletype_t','wasm_importtype_vec_t*'] => sub { + my($xsub, $self) = @_; + my $imports = Wasm::Wasmtime::ImportTypeVec->new; + $xsub->($self, $imports); + $imports->to_list; + }); + + $ffi->attach( [ exports => '_exports' ] => ['wasmtime_moduletype_t','wasm_exporttype_vec_t*'] => sub { + my($xsub, $self) = @_; + my $exports = Wasm::Wasmtime::ExportTypeVec->new; + $xsub->($self, $exports); + $exports->to_list; + }); + + sub exports + { + Wasm::Wasmtime::Module::Exports->new(shift); + } + + sub imports + { + Wasm::Wasmtime::Module::Imports->new(shift); + } + + _generate_destroy(); +} + +1; diff --git a/t/wasm_wasmtime_module.t b/t/wasm_wasmtime_module.t index 0766e88..137f445 100644 --- a/t/wasm_wasmtime_module.t +++ b/t/wasm_wasmtime_module.t @@ -86,6 +86,12 @@ is( Wasm::Wasmtime::Module->new(Wasm::Wasmtime::Engine->new, $wasm_binary), object { call ['isa', 'Wasm::Wasmtime::Module'] => T(); + if(Wasm::Wasmtime::FFI::_ver ne '0.27.0') + { + call type => object { + call ['isa', 'Wasm::Wasmtime::ModuleType' ] => T(); + }; + } }, 'basic create', ); diff --git a/t/wasm_wasmtime_moduletype.t b/t/wasm_wasmtime_moduletype.t new file mode 100644 index 0000000..f59a018 --- /dev/null +++ b/t/wasm_wasmtime_moduletype.t @@ -0,0 +1,23 @@ +use 5.008004; +use Test2::V0 -no_srand => 1; +use lib 't/lib'; +use Wasm::Wasmtime::Module; +use Wasm::Wasmtime::ModuleType; + +skip_all '0.28.0 and better only' unless Wasm::Wasmtime::FFI::_ver ne '0.27.0'; + +my $wasm_binary = "\0asm\x01\0\0\0"; + +is( + Wasm::Wasmtime::Module->new($wasm_binary), + object { + call ['isa', 'Wasm::Wasmtime::Module'] => T(); + call type => object { + call ['isa', 'Wasm::Wasmtime::ModuleType' ] => T(); + call exports => object {}; + }; + }, + 'basic create', +); + +done_testing; From 36b0f06daf16924afa69d845c0a423f5f041c4fd Mon Sep 17 00:00:00 2001 From: Graham Ollis Date: Sun, 6 Nov 2022 06:57:30 -0700 Subject: [PATCH 07/16] update changes --- Changes | 1 + 1 file changed, 1 insertion(+) diff --git a/Changes b/Changes index 618786d..f745d1e 100644 --- a/Changes +++ b/Changes @@ -5,6 +5,7 @@ Revision history for {{$dist->name}}, should be called instead (gh#118) - Deprecate get_one_by_name method from Wasm::Wasmtime::Linker (gh#118) - Added Wasm::Wasmtime::Context class (gh#118) + - Added Wasm::Wasmtime::ModuleType class (gh#118) 0.23 2022-11-04 06:33:12 -0600 - removed wasmtime_config_max_instances_set from Wasm::Wasmtime::Config From e603846327286b9de86655d36b0786d5c0ab77a5 Mon Sep 17 00:00:00 2001 From: Graham Ollis Date: Sun, 6 Nov 2022 10:50:59 -0700 Subject: [PATCH 08/16] compatability layer for Context class --- examples/synopsis/context.pl | 6 +++ lib/Wasm/Wasmtime.pm | 2 + lib/Wasm/Wasmtime/Context.pm | 39 ++++++------------- lib/Wasm/Wasmtime/Store.pm | 26 ++++++------- new.pl | 51 +++++++++++++++++++++++++ t/wasm_wasmtime_context.t | 2 - t/wasm_wasmtime_store.t | 72 ++++++++++++++++++++++++++---------- 7 files changed, 135 insertions(+), 63 deletions(-) create mode 100644 examples/synopsis/context.pl create mode 100644 new.pl diff --git a/examples/synopsis/context.pl b/examples/synopsis/context.pl new file mode 100644 index 0000000..37425bf --- /dev/null +++ b/examples/synopsis/context.pl @@ -0,0 +1,6 @@ +use strict; +use warnings; +use Wasm::Wasmtime; + +my $store = Wasm::Wasmtime::Store->new; +my $context = $store->context; diff --git a/lib/Wasm/Wasmtime.pm b/lib/Wasm/Wasmtime.pm index bd057d1..0d34a7a 100644 --- a/lib/Wasm/Wasmtime.pm +++ b/lib/Wasm/Wasmtime.pm @@ -5,6 +5,7 @@ use warnings; use 5.008004; use Wasm::Wasmtime::Caller; use Wasm::Wasmtime::Config; +use Wasm::Wasmtime::Context; use Wasm::Wasmtime::Engine; use Wasm::Wasmtime::ExportType; use Wasm::Wasmtime::Extern; @@ -17,6 +18,7 @@ use Wasm::Wasmtime::ImportType; use Wasm::Wasmtime::Instance; use Wasm::Wasmtime::Linker; use Wasm::Wasmtime::Module; +use Wasm::Wasmtime::ModuleType; use Wasm::Wasmtime::Store; use Wasm::Wasmtime::TableType; use Wasm::Wasmtime::Trap; diff --git a/lib/Wasm/Wasmtime/Context.pm b/lib/Wasm/Wasmtime/Context.pm index efb7a22..1547058 100644 --- a/lib/Wasm/Wasmtime/Context.pm +++ b/lib/Wasm/Wasmtime/Context.pm @@ -4,31 +4,23 @@ use strict; use warnings; use 5.008004; use Wasm::Wasmtime::FFI; +use Wasm::Wasmtime::Store; # ABSTRACT: Wasmtime context class # VERSION $ffi_prefix = 'wasmtime_context_'; -$ffi->load_custom_type('::PtrObject' => 'wasmtime_context_t' => __PACKAGE__); =head1 SYNOPSIS -# TODO +# EXAMPLE: examples/synopsis/context.pl =head1 DESCRIPTION -TODO +A wasmtime context object. =head1 METHODS -=head2 get_data - -TODO - -=head2 set_data - -TODO - =head2 gc Garbage collects Cs that are used by this context. Any @@ -39,23 +31,14 @@ will have their finalizers run. if(_ver ne '0.27.0') { - $ffi->attach( gc => ['wasmtime_context_t'] => 'void' ); + $ffi->attach( gc => ['wasmtime_context_t'] ); +} +else +{ + $ffi->attach( [ wasmtime_store_gc => 'gc' ] => ['wasm_store_t'] => sub { + my($xsub, $self) = @_; + $xsub->($self->{store}); + }); } - -=head2 add_fuel - -TODO - -=head2 fuel_consumed - -TODO - -=head2 set_wasi - -TODO - -=cut - -# TODO: class for wasmtime_interrupt_handler 1; diff --git a/lib/Wasm/Wasmtime/Store.pm b/lib/Wasm/Wasmtime/Store.pm index d3184f9..a234d39 100644 --- a/lib/Wasm/Wasmtime/Store.pm +++ b/lib/Wasm/Wasmtime/Store.pm @@ -4,7 +4,6 @@ use strict; use warnings; use 5.008004; use Wasm::Wasmtime::FFI; -use Wasm::Wasmtime::Context; use Wasm::Wasmtime::Engine; # TODO: wasmtime_store_add_fuel @@ -36,6 +35,7 @@ else } # TODO: we should change this to a wasmtime_store_t at some point $ffi->load_custom_type('::PtrObject' => 'wasm_store_t' => __PACKAGE__); +$ffi->load_custom_type('::PtrObject' => 'wasmtime_context_t' => 'Wasm::Wasmtime::Context'); =head1 CONSTRUCTOR @@ -53,6 +53,7 @@ isn't provided, then a new one will be created. if(_ver ne '0.27.0') { + # TODO: add support for the data and finazlizer here $ffi->attach( new => ['wasm_engine_t','opaque','(opaque)->void'] => 'wasm_store_t' => sub { my($xsub, $class, $engine) = @_; $engine ||= Wasm::Wasmtime::Engine->new; @@ -84,14 +85,18 @@ if(_ver ne '0.27.0') { $ffi->attach( context => ['wasm_store_t'] => 'wasmtime_context_t' => sub { my($xsub, $self) = @_; - $self->{context} || $xsub->($self); + $self->{context} || do { + require Wasm::Wasmtime::Context; + $xsub->($self); + }; }); } else { *context = sub { - require Carp; - Carp::croak("Context is not available in 0.27.0"); + my($self) = @_; + require Wasm::Wasmtime::Context; + bless { store => $self }, 'Wasm::Wasmtime::Context'; }; } @@ -107,16 +112,11 @@ will have their finalizers run. =cut -if(_ver ne '0.27.0') -{ - *gc = sub { - my($self) = @_; - $self->context->gc; - }; -} -else +sub gc { - $ffi->attach( [ wasmtime_store_gc => 'gc' ] => ['wasm_store_t'] => 'void' ); + my($self) = @_; + Carp::carp("Calling gc on a store directly is deprecated, please use \$store->context->gc instead"); + $self->context->gc; } =head2 engine diff --git a/new.pl b/new.pl new file mode 100644 index 0000000..3a0b168 --- /dev/null +++ b/new.pl @@ -0,0 +1,51 @@ +use strict; +use warnings; + +$ENV{WASM_WASMTIME_FFI} = '/home/ollisg/opt/wasmtime/0.28.0/lib/libwasmtime.so'; + +exec @ARGV if @ARGV; + +my %wt_tests = map { $_ => 1 } qw( + t/00_diag.t + t/test2_plugin_wasm.t + t/wasm_wasmtime.t + t/wasm_wasmtime_bytevec.t + t/wasm_wasmtime_caller.t + t/wasm_wasmtime_config.t + t/wasm_wasmtime_context.t + t/wasm_wasmtime_engine.t + t/wasm_wasmtime_exporttype.t + t/wasm_wasmtime_extern.t + t/wasm_wasmtime_externtype.t + t/wasm_wasmtime_ffi.t + t/wasm_wasmtime_func.t + t/wasm_wasmtime_functype.t + t/wasm_wasmtime_global.t + t/wasm_wasmtime_globaltype.t + t/wasm_wasmtime_importtype.t + t/wasm_wasmtime_instance.t + t/wasm_wasmtime_instance_exports.t + t/wasm_wasmtime_linker.t + t/wasm_wasmtime_memory.t + t/wasm_wasmtime_memorytype.t + t/wasm_wasmtime_module.t + t/wasm_wasmtime_module_exports.t + t/wasm_wasmtime_module_imports.t + t/wasm_wasmtime_moduletype.t + t/wasm_wasmtime_store.t + t/wasm_wasmtime_table.t + t/wasm_wasmtime_tabletype.t + t/wasm_wasmtime_trap.t + t/wasm_wasmtime_valtype.t + t/wasm_wasmtime_wasiconfig.t + t/wasm_wasmtime_wasiinstance.t + t/wasm_wasmtime_wat2wasm.t +); + +delete $wt_tests{$_} for qw( t/wasm_wasmtime_caller.t t/wasm_wasmtime_extern.t t/wasm_wasmtime_func.t t/wasm_wasmtime_global.t t/wasm_wasmtime_instance.t + t/wasm_wasmtime_instance_exports.t t/wasm_wasmtime_linker.t t/wasm_wasmtime_memory.t t/wasm_wasmtime_module_exports.t + t/wasm_wasmtime_module_imports.t t/wasm_wasmtime_table.t t/wasm_wasmtime_trap.t ); + +my @wt_tests = sort keys %wt_tests; + +exec 'prove', '-l', @wt_tests; diff --git a/t/wasm_wasmtime_context.t b/t/wasm_wasmtime_context.t index be25e5d..f390cbf 100644 --- a/t/wasm_wasmtime_context.t +++ b/t/wasm_wasmtime_context.t @@ -3,8 +3,6 @@ use Test2::V0 -no_srand => 1; use Wasm::Wasmtime::Store; use Wasm::Wasmtime::Context; -skip_all '0.28.0 and better only' unless Wasm::Wasmtime::FFI::_ver ne '0.27.0'; - is( Wasm::Wasmtime::Store->new, object { diff --git a/t/wasm_wasmtime_store.t b/t/wasm_wasmtime_store.t index 30d69da..c6f1486 100644 --- a/t/wasm_wasmtime_store.t +++ b/t/wasm_wasmtime_store.t @@ -3,27 +3,59 @@ use Test2::V0 -no_srand => 1; use Wasm::Wasmtime::Engine; use Wasm::Wasmtime::Store; -is( - Wasm::Wasmtime::Store->new, - object { - call ['isa','Wasm::Wasmtime::Store'] => T(); - call engine => object { - call ['isa','Wasm::Wasmtime::Engine'] => T(); +subtest 'basic' => sub { + + my $warnings = 0; + local $SIG{__WARN__} = sub { + my $message = shift; + if($message =~ /^Calling gc on a store directly is deprecated, please use \$store->context->gc instead/) + { + note "warning: $message"; + $warnings++; + } + else + { + warn $message; + } + }; + + is( + Wasm::Wasmtime::Store->new, + object { + call ['isa','Wasm::Wasmtime::Store'] => T(); + call engine => object { + call ['isa','Wasm::Wasmtime::Engine'] => T(); + }; + call gc => U(); + call context => object { + call ['isa','Wasm::Wasmtime::Context'] => T(); + call gc => U(); + }; + }, + 'default engine', + ); + + is $warnings, 1, 'expected warnings'; + $warnings=0; + + is( + Wasm::Wasmtime::Store->new(Wasm::Wasmtime::Engine->new), + object { + call ['isa','Wasm::Wasmtime::Store'] => T(); + call engine => object { + call ['isa','Wasm::Wasmtime::Engine'] => T(); + }; call gc => U(); - }; - }, - 'default engine', -); + call context => object { + call ['isa','Wasm::Wasmtime::Context'] => T(); + call gc => U(); + }; + }, + 'explicit engine', + ); -is( - Wasm::Wasmtime::Store->new(Wasm::Wasmtime::Engine->new), - object { - call ['isa','Wasm::Wasmtime::Store'] => T(); - call engine => object { - call ['isa','Wasm::Wasmtime::Engine'] => T(); - }; - }, - 'explicit engine', -); + is $warnings, 1, 'expected warnings'; + $warnings=0; +}; done_testing; From 77e60f02bb03486377818e0ed2ff5cb7fdb69539 Mon Sep 17 00:00:00 2001 From: Graham Ollis Date: Sun, 6 Nov 2022 11:43:14 -0700 Subject: [PATCH 09/16] rename Module::{Exports,Imports} to ModuleType::{Exports,Imports} --- Changes | 2 + author.yml | 8 +- examples/synopsis/exporttype.pl | 2 +- examples/synopsis/externtype.pl | 4 +- examples/synopsis/importtype.pl | 2 +- examples/synopsis/module_exports.pl | 2 +- examples/synopsis/moduletype.pl | 6 + lib/Wasm.pm | 4 +- lib/Wasm/Wasmtime/Instance.pm | 2 +- lib/Wasm/Wasmtime/Instance/Exports.pm | 2 +- lib/Wasm/Wasmtime/Module.pm | 51 ++++---- lib/Wasm/Wasmtime/ModuleType.pm | 40 ++++-- .../{Module => ModuleType}/Exports.pm | 8 +- .../{Module => ModuleType}/Imports.pm | 8 +- t/wasm_wasmtime_exporttype.t | 2 +- t/wasm_wasmtime_externtype.t | 82 ++++++------ t/wasm_wasmtime_importtype.t | 4 +- t/wasm_wasmtime_memorytype.t | 22 ++-- t/wasm_wasmtime_module.t | 119 +++++++++--------- ...s.t => wasm_wasmtime_moduletype_exports.t} | 6 +- ...s.t => wasm_wasmtime_moduletype_imports.t} | 6 +- xt/author/cycle.t | 4 +- 22 files changed, 206 insertions(+), 180 deletions(-) create mode 100644 examples/synopsis/moduletype.pl rename lib/Wasm/Wasmtime/{Module => ModuleType}/Exports.pm (93%) rename lib/Wasm/Wasmtime/{Module => ModuleType}/Imports.pm (93%) rename t/{wasm_wasmtime_module_exports.t => wasm_wasmtime_moduletype_exports.t} (90%) rename t/{wasm_wasmtime_module_imports.t => wasm_wasmtime_moduletype_imports.t} (89%) diff --git a/Changes b/Changes index f745d1e..4664bd5 100644 --- a/Changes +++ b/Changes @@ -6,6 +6,8 @@ Revision history for {{$dist->name}}, - Deprecate get_one_by_name method from Wasm::Wasmtime::Linker (gh#118) - Added Wasm::Wasmtime::Context class (gh#118) - Added Wasm::Wasmtime::ModuleType class (gh#118) + - Wasm::Wasmtime::Module::Imports renamed to Wasm::Wasmtime::ModuleType::Imports (gh#118) + - Wasm::Wasmtime::Module::Exports renamed to Wasm::Wasmtime::ModuleType::Exports (gh#118) 0.23 2022-11-04 06:33:12 -0600 - removed wasmtime_config_max_instances_set from Wasm::Wasmtime::Config diff --git a/author.yml b/author.yml index a2bc79a..8119d16 100644 --- a/author.yml +++ b/author.yml @@ -37,9 +37,9 @@ pod_coverage: - Wasm::Wasmtime::Caller#new - Wasm::Wasmtime::Instance::Exports#new - Wasm::Wasmtime::Instance::Exports#can - - Wasm::Wasmtime::Module::Exports#new - - Wasm::Wasmtime::Module::Exports#can - - Wasm::Wasmtime::Module::Imports#new - - Wasm::Wasmtime::Module::Imports#can + - Wasm::Wasmtime::ModuleType::Exports#new + - Wasm::Wasmtime::ModuleType::Exports#can + - Wasm::Wasmtime::ModuleType::Imports#new + - Wasm::Wasmtime::ModuleType::Imports#can - Wasm::Memory#new - Test2::Plugin::Wasm diff --git a/examples/synopsis/exporttype.pl b/examples/synopsis/exporttype.pl index 96da705..277379c 100644 --- a/examples/synopsis/exporttype.pl +++ b/examples/synopsis/exporttype.pl @@ -13,7 +13,7 @@ }); -my($foo, $bar) = @{ $module->exports }; +my($foo, $bar) = @{ $module->type->exports }; print $foo->name, "\n"; # foo print $foo->type->kind, "\n"; # func diff --git a/examples/synopsis/externtype.pl b/examples/synopsis/externtype.pl index 7b90d6b..8f8156c 100644 --- a/examples/synopsis/externtype.pl +++ b/examples/synopsis/externtype.pl @@ -12,8 +12,8 @@ ) }); -my $foo = $module->exports->foo; +my $foo = $module->type->exports->foo; print $foo->kind, "\n"; # functype -my $bar = $module->exports->bar; +my $bar = $module->type->exports->bar; print $bar->kind, "\n"; # memorytype diff --git a/examples/synopsis/importtype.pl b/examples/synopsis/importtype.pl index c5e3173..a0d9005 100644 --- a/examples/synopsis/importtype.pl +++ b/examples/synopsis/importtype.pl @@ -8,7 +8,7 @@ ) }); -my $hello = $module->imports->[0]; +my $hello = $module->type->imports->[0]; print $hello->module, "\n"; # xx print $hello->name, "\n"; # hello diff --git a/examples/synopsis/module_exports.pl b/examples/synopsis/module_exports.pl index 2a2e632..78e1a7c 100644 --- a/examples/synopsis/module_exports.pl +++ b/examples/synopsis/module_exports.pl @@ -11,7 +11,7 @@ ) }); -my $exports = $module->exports; # Wasm::Wasmtime::Module::Exports +my $exports = $module->type->exports; # Wasm::Wasmtime::Module::Exports my $type1 = $exports->add; # this is the Wasm::Wasmtime::FuncType for add my $type2 = $exports->{add}; # this is also the Wasm::Wasmtime::FuncType for add diff --git a/examples/synopsis/moduletype.pl b/examples/synopsis/moduletype.pl new file mode 100644 index 0000000..9dc75ff --- /dev/null +++ b/examples/synopsis/moduletype.pl @@ -0,0 +1,6 @@ +use strict; +use warnings; +use Wasm::Wasmtime; + +my $module = Wasm::Wasmtime::Module->new( wat => '(module)' ); +my $type = $module->type; diff --git a/lib/Wasm.pm b/lib/Wasm.pm index f020b83..35a7ff7 100644 --- a/lib/Wasm.pm +++ b/lib/Wasm.pm @@ -346,7 +346,7 @@ sub import my $module = Wasm::Wasmtime::Module->new($linker->store->engine, @module); - foreach my $import (@{ $module->imports }) + foreach my $import (@{ $module->type->imports }) { my $module = $import->module; @@ -447,7 +447,7 @@ sub import $linker->define_instance($package, $instance); $WASM{$package} = "$file"; - my @me = @{ $module->exports }; + my @me = @{ $module->type->exports }; my @ie = @{ $instance->exports }; my @function_names; diff --git a/lib/Wasm/Wasmtime/Instance.pm b/lib/Wasm/Wasmtime/Instance.pm index 6c7e54f..3c16536 100644 --- a/lib/Wasm/Wasmtime/Instance.pm +++ b/lib/Wasm/Wasmtime/Instance.pm @@ -142,7 +142,7 @@ $ffi->attach( [ wasmtime_instance_new => 'new' ] => ['wasm_store_t','wasm_module my $trap; { - my @mi = @{ $module->imports }; + my @mi = @{ $module->type->imports }; if(@mi != @imports) { Carp::croak("Got @{[ scalar @imports ]} imports, but expected @{[ scalar @mi ]}"); diff --git a/lib/Wasm/Wasmtime/Instance/Exports.pm b/lib/Wasm/Wasmtime/Instance/Exports.pm index 58bcd6f..52cd3e5 100644 --- a/lib/Wasm/Wasmtime/Instance/Exports.pm +++ b/lib/Wasm/Wasmtime/Instance/Exports.pm @@ -71,7 +71,7 @@ sub new $instance->{exports} ||= do { my @exports = $instance->_exports; - my @module_exports = @{ $instance->module->exports }; + my @module_exports = @{ $instance->module->type->exports }; my %exports; foreach my $i (0..$#exports) { diff --git a/lib/Wasm/Wasmtime/Module.pm b/lib/Wasm/Wasmtime/Module.pm index 054deee..c46b6fd 100644 --- a/lib/Wasm/Wasmtime/Module.pm +++ b/lib/Wasm/Wasmtime/Module.pm @@ -7,8 +7,8 @@ use Ref::Util qw( is_blessed_ref ); use Wasm::Wasmtime::FFI; use Wasm::Wasmtime::Engine; use Wasm::Wasmtime::Store; -use Wasm::Wasmtime::Module::Exports; -use Wasm::Wasmtime::Module::Imports; +use Wasm::Wasmtime::ModuleType::Exports; +use Wasm::Wasmtime::ModuleType::Imports; use Wasm::Wasmtime::ModuleType; use Wasm::Wasmtime::ImportType; use Wasm::Wasmtime::ExportType; @@ -360,32 +360,30 @@ if(_ver ne '0.27.0') else { *type = sub { - Carp::croak("The Module type method is only available in 0.28.0 and newer"); + my($self) = @_; + bless { module => $self }, 'Wasm::Wasmtime::ModuleType'; }; } =head2 exports +[deprecated; please use $module->type->exports instead] + my $exports = $module->exports; -Returns a L object that can be used to query the module exports. +Returns a L object that can be used to query the module exports. =cut -if(_ver ne '0.27.0') +sub exports { - *exports = sub { - my($self) = @_; - $self->type->exports; - }; + my($self) = @_; + Carp::carp("The exports method on Wasm::Wasmtime::Module is deprecated, please use \$module->type->exports instead"); + $self->type->exports; } -else -{ - *exports = sub - { - Wasm::Wasmtime::Module::Exports->new(shift); - }; +if(_ver eq '0.27.0') +{ $ffi->attach( [ exports => '_exports' ]=> [ 'wasm_module_t', 'wasm_exporttype_vec_t*' ] => sub { my($xsub, $self) = @_; my $exports = Wasm::Wasmtime::ExportTypeVec->new; @@ -396,26 +394,23 @@ else =head2 imports +[deprecated; please use $module->type->imports instead] + my $imports = $module->imports; -Returns a list of L objects for the objects imported by the WebAssembly module. +Returns a L for the objects imported by the WebAssembly module. =cut -if(_ver ne '0.27.0') +sub imports { - *imports = sub { - my($self) = @_; - $self->type->imports; - }; + my($self) = @_; + Carp::carp("The imports method on Wasm::Wasmtime::Module is deprecated, please use \$module->type->imports instead"); + $self->type->imports; } -else -{ - *imports = sub - { - Wasm::Wasmtime::Module::Imports->new(shift); - }; +if(_ver eq '0.27.0') +{ $ffi->attach( [ imports => '_imports' ] => [ 'wasm_module_t', 'wasm_importtype_vec_t*' ] => sub { my($xsub, $self) = @_; my $imports = Wasm::Wasmtime::ImportTypeVec->new; @@ -470,7 +465,7 @@ Converts the module imports and exports into a string for diagnostics. sub to_string { my($self) = @_; - my @externs = (@{ $self->imports }, @{ $self->exports }); + my @externs = (@{ $self->type->imports }, @{ $self->type->exports }); return "(module)\n" unless @externs; my $string = "(module\n"; foreach my $extern (@externs) diff --git a/lib/Wasm/Wasmtime/ModuleType.pm b/lib/Wasm/Wasmtime/ModuleType.pm index e30d749..93edc78 100644 --- a/lib/Wasm/Wasmtime/ModuleType.pm +++ b/lib/Wasm/Wasmtime/ModuleType.pm @@ -4,8 +4,8 @@ use strict; use warnings; use 5.008004; use Wasm::Wasmtime::FFI; -use Wasm::Wasmtime::Module::Exports; -use Wasm::Wasmtime::Module::Imports; +use Wasm::Wasmtime::ModuleType::Exports; +use Wasm::Wasmtime::ModuleType::Imports; use Wasm::Wasmtime::ImportType; use Wasm::Wasmtime::ExportType; @@ -17,21 +17,21 @@ $ffi->load_custom_type('::PtrObject' => 'wasmtime_moduletype_t' => __PACKAGE__); =head1 SYNOPSIS -# TODO +# EXAMPLE: examples/synopsis/moduletype.pl =head1 DESCRIPTION -TODO +This class represents the type information of a module. =head1 METHODS =head2 imports -# TODO + my $imports = $type->imports; =head2 exports -# TODO + my $exports = $type->exports; =cut @@ -51,17 +51,33 @@ if(_ver ne '0.27.0') $exports->to_list; }); - sub exports + *exports = sub { - Wasm::Wasmtime::Module::Exports->new(shift); - } + Wasm::Wasmtime::ModuleType::Exports->new(shift); + }; - sub imports + *imports = sub { - Wasm::Wasmtime::Module::Imports->new(shift); - } + Wasm::Wasmtime::ModuleType::Imports->new(shift); + }; _generate_destroy(); } +else +{ + + *exports = sub + { + my($self) = @_; + Wasm::Wasmtime::ModuleType::Exports->new($self->{module}); + }; + + *imports = sub + { + my($self) = @_; + Wasm::Wasmtime::ModuleType::Imports->new($self->{module}); + }; +} + 1; diff --git a/lib/Wasm/Wasmtime/Module/Exports.pm b/lib/Wasm/Wasmtime/ModuleType/Exports.pm similarity index 93% rename from lib/Wasm/Wasmtime/Module/Exports.pm rename to lib/Wasm/Wasmtime/ModuleType/Exports.pm index d88b8ba..5fc275d 100644 --- a/lib/Wasm/Wasmtime/Module/Exports.pm +++ b/lib/Wasm/Wasmtime/ModuleType/Exports.pm @@ -1,4 +1,4 @@ -package Wasm::Wasmtime::Module::Exports; +package Wasm::Wasmtime::ModuleType::Exports; use strict; use warnings; @@ -40,14 +40,14 @@ This class represents the exports from a module. It can be used in a number of =item autoload methods - my $foo = $module->exports->foo; + my $foo = $module->type->exports->foo; Calling the name of an export as a method returns the L for the export. =item As a hash reference - my $foo = $module->exports->{foo}; + my $foo = $module->type->exports->{foo}; Using the Exports class as a hash reference allows you to get exports that might clash with common Perl methods like C, C, C, etc. The L @@ -55,7 +55,7 @@ will be returned. =item An array reference - my $foo = $module->exports->[0]; + my $foo = $module->type->exports->[0]; This will give you the list of exports in the order that they are defined in your WebAssembly. The object returned is a L, which is essentially a name and a diff --git a/lib/Wasm/Wasmtime/Module/Imports.pm b/lib/Wasm/Wasmtime/ModuleType/Imports.pm similarity index 93% rename from lib/Wasm/Wasmtime/Module/Imports.pm rename to lib/Wasm/Wasmtime/ModuleType/Imports.pm index ea664cc..e690f57 100644 --- a/lib/Wasm/Wasmtime/Module/Imports.pm +++ b/lib/Wasm/Wasmtime/ModuleType/Imports.pm @@ -1,4 +1,4 @@ -package Wasm::Wasmtime::Module::Imports; +package Wasm::Wasmtime::ModuleType::Imports; use strict; use warnings; @@ -40,14 +40,14 @@ This class represents the imports from a module. It can be used in a number of =item autoload methods - my $foo = $module->imports->foo; + my $foo = $module->type->imports->foo; Calling the name of an export as a method returns the L for the export. =item As a hash reference - my $foo = $module->imports->{foo}; + my $foo = $module->type->imports->{foo}; Using the Imports class as a hash reference allows you to get imports that might clash with common Perl methods like C, C, C, etc. The L @@ -55,7 +55,7 @@ will be returned. =item An array reference - my $foo = $module->imports->[0]; + my $foo = $module->type->imports->[0]; This will give you the list of imports in the order that they are defined in your WebAssembly. The object returned is a L, which is essentially a name and a diff --git a/t/wasm_wasmtime_exporttype.t b/t/wasm_wasmtime_exporttype.t index 0fddca9..e552440 100644 --- a/t/wasm_wasmtime_exporttype.t +++ b/t/wasm_wasmtime_exporttype.t @@ -15,7 +15,7 @@ is( ) }), object { - call_list sub { @{ shift->exports } } => array { + call_list sub { @{ shift->type->exports } } => array { item object { call [ isa => 'Wasm::Wasmtime::ExportType' ] => T(); call name => 'foo'; diff --git a/t/wasm_wasmtime_externtype.t b/t/wasm_wasmtime_externtype.t index fa09b54..7baa062 100644 --- a/t/wasm_wasmtime_externtype.t +++ b/t/wasm_wasmtime_externtype.t @@ -17,48 +17,50 @@ is( ) }), object { - call exports => object { - call foo => object { - call [ isa => 'Wasm::Wasmtime::FuncType' ] => T(); - call kind => 'functype'; - call is_functype => T(); - call is_globaltype => F(); - call is_tabletype => F(); - call is_memorytype => F(); - }; - call baz => object { - call [ isa => 'Wasm::Wasmtime::GlobalType' ] => T(); - call kind => 'globaltype'; - call is_functype => F(); - call is_globaltype => T(); - call is_tabletype => F(); - call is_memorytype => F(); - call content => object { - call [ isa => 'Wasm::Wasmtime::ValType' ] => T(); - call kind => 'i32'; + call type => object { + call exports => object { + call foo => object { + call [ isa => 'Wasm::Wasmtime::FuncType' ] => T(); + call kind => 'functype'; + call is_functype => T(); + call is_globaltype => F(); + call is_tabletype => F(); + call is_memorytype => F(); }; - call mutability => 'var'; - }; - call frooble => object { - call [ isa => 'Wasm::Wasmtime::TableType' ] => T(); - call kind => 'tabletype'; - call is_functype => F(); - call is_globaltype => F(); - call is_tabletype => T(); - call is_memorytype => F(); - call element => object { - call [ isa => 'Wasm::Wasmtime::ValType' ] => T(); - call kind => 'funcref'; + call baz => object { + call [ isa => 'Wasm::Wasmtime::GlobalType' ] => T(); + call kind => 'globaltype'; + call is_functype => F(); + call is_globaltype => T(); + call is_tabletype => F(); + call is_memorytype => F(); + call content => object { + call [ isa => 'Wasm::Wasmtime::ValType' ] => T(); + call kind => 'i32'; + }; + call mutability => 'var'; + }; + call frooble => object { + call [ isa => 'Wasm::Wasmtime::TableType' ] => T(); + call kind => 'tabletype'; + call is_functype => F(); + call is_globaltype => F(); + call is_tabletype => T(); + call is_memorytype => F(); + call element => object { + call [ isa => 'Wasm::Wasmtime::ValType' ] => T(); + call kind => 'funcref'; + }; + call limits => [ 1, 3 ]; + }; + call bar => object { + call [ isa => 'Wasm::Wasmtime::MemoryType' ] => T(); + call kind => 'memorytype'; + call is_functype => F(); + call is_globaltype => F(); + call is_tabletype => F(); + call is_memorytype => T(); }; - call limits => [ 1, 3 ]; - }; - call bar => object { - call [ isa => 'Wasm::Wasmtime::MemoryType' ] => T(); - call kind => 'memorytype'; - call is_functype => F(); - call is_globaltype => F(); - call is_tabletype => F(); - call is_memorytype => T(); }; }; }, diff --git a/t/wasm_wasmtime_importtype.t b/t/wasm_wasmtime_importtype.t index f0000b2..e82fbb9 100644 --- a/t/wasm_wasmtime_importtype.t +++ b/t/wasm_wasmtime_importtype.t @@ -11,7 +11,7 @@ is( ) }), object { - call_list sub { @{ shift->imports } } => array { + call_list sub { @{ shift->type->imports } } => array { item object { call [ isa => 'Wasm::Wasmtime::ImportType' ] => T(); call name => 'hello'; @@ -34,7 +34,7 @@ is( ) }), object { - call_list sub { @{ shift->imports } } => array { + call_list sub { @{ shift->type->imports } } => array { item object { call [ isa => 'Wasm::Wasmtime::ImportType' ] => T(); call name => 'hello'; diff --git a/t/wasm_wasmtime_memorytype.t b/t/wasm_wasmtime_memorytype.t index f031453..e16a037 100644 --- a/t/wasm_wasmtime_memorytype.t +++ b/t/wasm_wasmtime_memorytype.t @@ -11,16 +11,18 @@ is( ) }), object { - call exports => object { - call frooble => object { - call [ isa => 'Wasm::Wasmtime::MemoryType' ] => T(); - call limits => [2,6]; - call is_functype => F(); - call is_globaltype => F(); - call is_tabletype => F(); - call is_memorytype => T(); - call kind => 'memorytype'; - call to_string => '2 6'; + call type => object { + call exports => object { + call frooble => object { + call [ isa => 'Wasm::Wasmtime::MemoryType' ] => T(); + call limits => [2,6]; + call is_functype => F(); + call is_globaltype => F(); + call is_tabletype => F(); + call is_memorytype => T(); + call kind => 'memorytype'; + call to_string => '2 6'; + }; }; }; }, diff --git a/t/wasm_wasmtime_module.t b/t/wasm_wasmtime_module.t index 137f445..5b50e5a 100644 --- a/t/wasm_wasmtime_module.t +++ b/t/wasm_wasmtime_module.t @@ -228,75 +228,78 @@ is( ) }), object { - call exports => object { - call [ isa => 'Wasm::Wasmtime::Module::Exports' ] => T(); - call add => object { - call [ isa => 'Wasm::Wasmtime::FuncType' ] => T(); - }; - }; - call_list sub { @{ shift->imports } } => []; - call_list sub { @{ shift->exports } } => array { - item object { - call [ isa => 'Wasm::Wasmtime::ExportType' ] => T(); - call name => 'add'; - call type => object { + call type => object { + call [ isa => 'Wasm::Wasmtime::ModuleType' ] => T(); + call exports => object { + call [ isa => 'Wasm::Wasmtime::ModuleType::Exports' ] => T(); + call add => object { call [ isa => 'Wasm::Wasmtime::FuncType' ] => T(); - call kind => 'functype'; - call_list params => array { - item object { - call [ isa => 'Wasm::Wasmtime::ValType' ] => T(); - call kind => 'i32'; - }; - item object { - call [ isa => 'Wasm::Wasmtime::ValType' ] => T(); - call kind => 'i32'; - }; - end; - }; - call_list results => array { - item object { - call [ isa => 'Wasm::Wasmtime::ValType' ] => T(); - call kind => 'i32'; - }; - end; - }; }; }; - item object { - call [ isa => 'Wasm::Wasmtime::ExportType' ] => T(); - call name => 'sub'; - call type => object { - call kind => 'functype'; - call [ isa => 'Wasm::Wasmtime::FuncType' ] => T(); - call_list params => array { - item object { - call [ isa => 'Wasm::Wasmtime::ValType' ] => T(); - call kind => 'i64'; + call_list sub { @{ shift->imports } } => []; + call_list sub { @{ shift->exports } } => array { + item object { + call [ isa => 'Wasm::Wasmtime::ExportType' ] => T(); + call name => 'add'; + call type => object { + call [ isa => 'Wasm::Wasmtime::FuncType' ] => T(); + call kind => 'functype'; + call_list params => array { + item object { + call [ isa => 'Wasm::Wasmtime::ValType' ] => T(); + call kind => 'i32'; + }; + item object { + call [ isa => 'Wasm::Wasmtime::ValType' ] => T(); + call kind => 'i32'; + }; + end; }; - item object { - call [ isa => 'Wasm::Wasmtime::ValType' ] => T(); - call kind => 'i64'; + call_list results => array { + item object { + call [ isa => 'Wasm::Wasmtime::ValType' ] => T(); + call kind => 'i32'; + }; + end; }; - end; }; - call_list results => array { - item object { - call [ isa => 'Wasm::Wasmtime::ValType' ] => T(); - call kind => 'i64'; + }; + item object { + call [ isa => 'Wasm::Wasmtime::ExportType' ] => T(); + call name => 'sub'; + call type => object { + call kind => 'functype'; + call [ isa => 'Wasm::Wasmtime::FuncType' ] => T(); + call_list params => array { + item object { + call [ isa => 'Wasm::Wasmtime::ValType' ] => T(); + call kind => 'i64'; + }; + item object { + call [ isa => 'Wasm::Wasmtime::ValType' ] => T(); + call kind => 'i64'; + }; + end; + }; + call_list results => array { + item object { + call [ isa => 'Wasm::Wasmtime::ValType' ] => T(); + call kind => 'i64'; + }; + end; }; - end; }; }; - }; - item object { - call [ isa => 'Wasm::Wasmtime::ExportType' ] => T(); - call name => 'frooble'; - call type => object { - call [ isa => 'Wasm::Wasmtime::MemoryType' ] => T(); - call kind => 'memorytype'; + item object { + call [ isa => 'Wasm::Wasmtime::ExportType' ] => T(); + call name => 'frooble'; + call type => object { + call [ isa => 'Wasm::Wasmtime::MemoryType' ] => T(); + call kind => 'memorytype'; + }; }; + end; }; - end; }; }, 'exports', diff --git a/t/wasm_wasmtime_module_exports.t b/t/wasm_wasmtime_moduletype_exports.t similarity index 90% rename from t/wasm_wasmtime_module_exports.t rename to t/wasm_wasmtime_moduletype_exports.t index 94fcaf4..fad0625 100644 --- a/t/wasm_wasmtime_module_exports.t +++ b/t/wasm_wasmtime_moduletype_exports.t @@ -1,7 +1,7 @@ use 5.008004; use Test2::V0 -no_srand => 1; use Wasm::Wasmtime::Module; -use Wasm::Wasmtime::Module::Exports; +use Wasm::Wasmtime::ModuleType::Exports; use YAML qw( Dump ); { @@ -13,11 +13,11 @@ use YAML qw( Dump ); i32.add) ) }); - my $exports = Wasm::Wasmtime::Module::Exports->new($module); + my $exports = Wasm::Wasmtime::ModuleType::Exports->new($module); is( $exports, object { - call [ isa => 'Wasm::Wasmtime::Module::Exports' ] => T(); + call [ isa => 'Wasm::Wasmtime::ModuleType::Exports' ] => T(); call add => object { call [ isa => 'Wasm::Wasmtime::FuncType' ] => T(); }; diff --git a/t/wasm_wasmtime_module_imports.t b/t/wasm_wasmtime_moduletype_imports.t similarity index 89% rename from t/wasm_wasmtime_module_imports.t rename to t/wasm_wasmtime_moduletype_imports.t index 0a51d43..d65d1b6 100644 --- a/t/wasm_wasmtime_module_imports.t +++ b/t/wasm_wasmtime_moduletype_imports.t @@ -1,7 +1,7 @@ use 5.008004; use Test2::V0 -no_srand => 1; use Wasm::Wasmtime::Module; -use Wasm::Wasmtime::Module::Imports; +use Wasm::Wasmtime::ModuleType::Imports; use YAML qw( Dump ); { @@ -10,11 +10,11 @@ use YAML qw( Dump ); (func $hello (import "" "add")) ) }); - my $imports = Wasm::Wasmtime::Module::Imports->new($module); + my $imports = Wasm::Wasmtime::ModuleType::Imports->new($module); is( $imports, object { - call [ isa => 'Wasm::Wasmtime::Module::Imports' ] => T(); + call [ isa => 'Wasm::Wasmtime::ModuleType::Imports' ] => T(); call add => object { call [ isa => 'Wasm::Wasmtime::FuncType' ] => T(); diff --git a/xt/author/cycle.t b/xt/author/cycle.t index 3d585c2..061de09 100644 --- a/xt/author/cycle.t +++ b/xt/author/cycle.t @@ -19,8 +19,8 @@ subtest 'module' => sub { }, ); - $module->imports; - $module->exports; + $module->type->imports; + $module->type->exports; memory_cycle_ok $module; From 75fe307a7b9b9f415e10a5d2eed43a2745a7b5a0 Mon Sep 17 00:00:00 2001 From: Graham Ollis Date: Sun, 6 Nov 2022 11:50:52 -0700 Subject: [PATCH 10/16] die if the old class names are used --- lib/Wasm/Wasmtime/Module/Exports.pm | 25 +++++++++++++++++++++++++ lib/Wasm/Wasmtime/Module/Imports.pm | 26 ++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 lib/Wasm/Wasmtime/Module/Exports.pm create mode 100644 lib/Wasm/Wasmtime/Module/Imports.pm diff --git a/lib/Wasm/Wasmtime/Module/Exports.pm b/lib/Wasm/Wasmtime/Module/Exports.pm new file mode 100644 index 0000000..8022f18 --- /dev/null +++ b/lib/Wasm/Wasmtime/Module/Exports.pm @@ -0,0 +1,25 @@ +package Wasm::Wasmtime::Module::Exports; + +use strict; +use warnings; +use Carp qw( croak ); + +croak("This class was renamed to Wasm::Wasmtime::ModuleType::Exports") unless caller eq 'Pod::Coverage'; + +1; + +# ABSTRACT: Old class +# VERSION + +__END__ + +=head1 SYNOPSIS + + $ perldoc Wasm::Wasmtime::ModuleType::Exports + +=head1 DESCRIPTION + +This is the old class name for L. +Trying to use this class name will throw an exception. + +=cut diff --git a/lib/Wasm/Wasmtime/Module/Imports.pm b/lib/Wasm/Wasmtime/Module/Imports.pm new file mode 100644 index 0000000..5e29dff --- /dev/null +++ b/lib/Wasm/Wasmtime/Module/Imports.pm @@ -0,0 +1,26 @@ +package Wasm::Wasmtime::Module::Imports; + +use strict; +use warnings; +use Carp qw( croak ); + +croak("This class was renamed to Wasm::Wasmtime::ModuleType::Imports") unless caller eq 'Pod::Coverage'; + +1; + +# ABSTRACT: Old class +# VERSION + +__END__ + +=head1 SYNOPSIS + + $ perldoc Wasm::Wasmtime::ModuleType::Imports + +=head1 DESCRIPTION + +This is the old class name for L. +Trying to use this class name will throw an exception. + +=cut + From 8d27592315823e8e36f1eea84f976acbb017b051 Mon Sep 17 00:00:00 2001 From: Graham Ollis Date: Sun, 6 Nov 2022 12:00:25 -0700 Subject: [PATCH 11/16] test warnings --- t/wasm_wasmtime_module.t | 48 ++++++++++++++++++++++++++++++------ t/wasm_wasmtime_moduletype.t | 2 -- 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/t/wasm_wasmtime_module.t b/t/wasm_wasmtime_module.t index 5b50e5a..8e2f143 100644 --- a/t/wasm_wasmtime_module.t +++ b/t/wasm_wasmtime_module.t @@ -74,7 +74,8 @@ subtest 'validate' => sub { ); }; -subtest 'error' => sub { +subtest 'errors' => sub { + is( dies { Wasm::Wasmtime::Module->new('f00f') }, match qr/error creating module/, @@ -82,16 +83,49 @@ subtest 'error' => sub { ); }; +subtest 'warnings' => sub { + + my @warnings; + local $SIG{__WARN__} = sub { + my $message = shift; + if($message =~ /The .* method on Wasm::Wasmtime::Module/) + { + push @warnings, $message; + } + else + { + warn $message; + } + }; + + @warnings = (); + Wasm::Wasmtime::Module->new($wasm_binary)->exports; + is + \@warnings, + array { + item match qr/^The exports method on Wasm::Wasmtime::Module is deprecated, please use \$module->type->exports instead/; + }, + 'warning on deprecatd exports method'; + + @warnings = (); + Wasm::Wasmtime::Module->new($wasm_binary)->imports; + + is + \@warnings, + array { + item match qr/^The imports method on Wasm::Wasmtime::Module is deprecated, please use \$module->type->imports instead/; + }, + 'warning on deprecatd imports method' + +}; + is( Wasm::Wasmtime::Module->new(Wasm::Wasmtime::Engine->new, $wasm_binary), object { call ['isa', 'Wasm::Wasmtime::Module'] => T(); - if(Wasm::Wasmtime::FFI::_ver ne '0.27.0') - { - call type => object { - call ['isa', 'Wasm::Wasmtime::ModuleType' ] => T(); - }; - } + call type => object { + call ['isa', 'Wasm::Wasmtime::ModuleType' ] => T(); + }; }, 'basic create', ); diff --git a/t/wasm_wasmtime_moduletype.t b/t/wasm_wasmtime_moduletype.t index f59a018..9d04e66 100644 --- a/t/wasm_wasmtime_moduletype.t +++ b/t/wasm_wasmtime_moduletype.t @@ -4,8 +4,6 @@ use lib 't/lib'; use Wasm::Wasmtime::Module; use Wasm::Wasmtime::ModuleType; -skip_all '0.28.0 and better only' unless Wasm::Wasmtime::FFI::_ver ne '0.27.0'; - my $wasm_binary = "\0asm\x01\0\0\0"; is( From fd0e331a7dc4905cd9fe748f3e65723af57eab81 Mon Sep 17 00:00:00 2001 From: Graham Ollis Date: Sun, 6 Nov 2022 12:06:40 -0700 Subject: [PATCH 12/16] fix tests --- new.pl | 8 ++++---- t/wasm_wasmtime_moduletype_exports.t | 2 +- t/wasm_wasmtime_moduletype_imports.t | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/new.pl b/new.pl index 3a0b168..0aa0839 100644 --- a/new.pl +++ b/new.pl @@ -29,8 +29,8 @@ t/wasm_wasmtime_memory.t t/wasm_wasmtime_memorytype.t t/wasm_wasmtime_module.t - t/wasm_wasmtime_module_exports.t - t/wasm_wasmtime_module_imports.t + t/wasm_wasmtime_moduletype_exports.t + t/wasm_wasmtime_moduletype_imports.t t/wasm_wasmtime_moduletype.t t/wasm_wasmtime_store.t t/wasm_wasmtime_table.t @@ -43,8 +43,8 @@ ); delete $wt_tests{$_} for qw( t/wasm_wasmtime_caller.t t/wasm_wasmtime_extern.t t/wasm_wasmtime_func.t t/wasm_wasmtime_global.t t/wasm_wasmtime_instance.t - t/wasm_wasmtime_instance_exports.t t/wasm_wasmtime_linker.t t/wasm_wasmtime_memory.t t/wasm_wasmtime_module_exports.t - t/wasm_wasmtime_module_imports.t t/wasm_wasmtime_table.t t/wasm_wasmtime_trap.t ); + t/wasm_wasmtime_instance_exports.t t/wasm_wasmtime_linker.t t/wasm_wasmtime_memory.t t/wasm_wasmtime_table.t + t/wasm_wasmtime_trap.t ); my @wt_tests = sort keys %wt_tests; diff --git a/t/wasm_wasmtime_moduletype_exports.t b/t/wasm_wasmtime_moduletype_exports.t index fad0625..e5f1921 100644 --- a/t/wasm_wasmtime_moduletype_exports.t +++ b/t/wasm_wasmtime_moduletype_exports.t @@ -13,7 +13,7 @@ use YAML qw( Dump ); i32.add) ) }); - my $exports = Wasm::Wasmtime::ModuleType::Exports->new($module); + my $exports = $module->type->exports; is( $exports, object { diff --git a/t/wasm_wasmtime_moduletype_imports.t b/t/wasm_wasmtime_moduletype_imports.t index d65d1b6..e2372a7 100644 --- a/t/wasm_wasmtime_moduletype_imports.t +++ b/t/wasm_wasmtime_moduletype_imports.t @@ -10,7 +10,7 @@ use YAML qw( Dump ); (func $hello (import "" "add")) ) }); - my $imports = Wasm::Wasmtime::ModuleType::Imports->new($module); + my $imports = $module->type->imports; is( $imports, object { From 117a9409e4c8db57c8ee8267e7a9c4cc2193f499 Mon Sep 17 00:00:00 2001 From: Graham Ollis Date: Sun, 6 Nov 2022 16:01:13 -0700 Subject: [PATCH 13/16] deprecate passing store into instance --- Changes | 2 + examples/synopsis/func1.pl | 2 +- examples/synopsis/func2.pl | 4 +- examples/synopsis/instance.pl | 2 +- examples/synopsis/instance_exports.pl | 2 +- lib/Wasm/Wasmtime/FFI.pm | 37 ++-- lib/Wasm/Wasmtime/Instance.pm | 237 +++++++++++++++++++------- lib/Wasm/Wasmtime/Linker.pm | 2 +- lib/Wasm/Wasmtime/Module.pm | 1 + lib/Wasm/Wasmtime/Store.pm | 8 +- t/lib/Test2/Tools/Wasm.pm | 2 +- t/wasm_wasmtime_caller.t | 2 +- t/wasm_wasmtime_instance.t | 8 +- t/wasm_wasmtime_instance_exports.t | 2 +- t/wasm_wasmtime_linker.t | 2 +- 15 files changed, 218 insertions(+), 95 deletions(-) diff --git a/Changes b/Changes index 4664bd5..a360a4c 100644 --- a/Changes +++ b/Changes @@ -8,6 +8,8 @@ Revision history for {{$dist->name}}, - Added Wasm::Wasmtime::ModuleType class (gh#118) - Wasm::Wasmtime::Module::Imports renamed to Wasm::Wasmtime::ModuleType::Imports (gh#118) - Wasm::Wasmtime::Module::Exports renamed to Wasm::Wasmtime::ModuleType::Exports (gh#118) + - Passing Wasm::Wasmtime::Store into Wasm::Wasmtime::Instance->new is deprecated + pass $store->context instead (gh#118) 0.23 2022-11-04 06:33:12 -0600 - removed wasmtime_config_max_instances_set from Wasm::Wasmtime::Config diff --git a/examples/synopsis/func1.pl b/examples/synopsis/func1.pl index d34cd15..f8b00df 100644 --- a/examples/synopsis/func1.pl +++ b/examples/synopsis/func1.pl @@ -14,6 +14,6 @@ ) }); -my $instance = Wasm::Wasmtime::Instance->new($module, $store); +my $instance = Wasm::Wasmtime::Instance->new($module, $store->context); my $add = $instance->exports->add; print $add->call(1,2), "\n"; # 3 diff --git a/examples/synopsis/func2.pl b/examples/synopsis/func2.pl index 183c845..a9f4eaf 100644 --- a/examples/synopsis/func2.pl +++ b/examples/synopsis/func2.pl @@ -13,11 +13,11 @@ }); my $hello = Wasm::Wasmtime::Func->new( - $store, + $store->context, Wasm::Wasmtime::FuncType->new([],[]), sub { print "hello world!\n" }, ); -my $instance = Wasm::Wasmtime::Instance->new($module, $store, [$hello]); +my $instance = Wasm::Wasmtime::Instance->new($module, $store->context, [$hello]); $instance->exports->run->call(); # hello world! diff --git a/examples/synopsis/instance.pl b/examples/synopsis/instance.pl index e962dcc..eb5775e 100644 --- a/examples/synopsis/instance.pl +++ b/examples/synopsis/instance.pl @@ -4,4 +4,4 @@ my $store = Wasm::Wasmtime::Store->new; my $module = Wasm::Wasmtime::Module->new($store->engine, wat => '(module)'); -my $instance = Wasm::Wasmtime::Instance->new($module, $store, []); +my $instance = Wasm::Wasmtime::Instance->new($module, $store->context, []); diff --git a/examples/synopsis/instance_exports.pl b/examples/synopsis/instance_exports.pl index 6410c11..dc519cd 100644 --- a/examples/synopsis/instance_exports.pl +++ b/examples/synopsis/instance_exports.pl @@ -12,7 +12,7 @@ ) }); -my $instance = Wasm::Wasmtime::Instance->new($module, $store); +my $instance = Wasm::Wasmtime::Instance->new($module, $store->context); my $exports = $instance->exports; diff --git a/lib/Wasm/Wasmtime/FFI.pm b/lib/Wasm/Wasmtime/FFI.pm index ee3bfaa..7ef3aa3 100644 --- a/lib/Wasm/Wasmtime/FFI.pm +++ b/lib/Wasm/Wasmtime/FFI.pm @@ -63,7 +63,7 @@ sub _lib } our $ffi_prefix = 'wasm_'; -our $ffi = FFI::Platypus->new( api => 1 ); +our $ffi = FFI::Platypus->new( api => 2 ); FFI::C->ffi($ffi); $ffi->lib(__PACKAGE__->_lib); $ffi->mangler(sub { @@ -181,24 +181,33 @@ sub _wrapper_destroy sub _generate_destroy { + my %arg = @_; my $caller = caller; - my $type = lc $caller; - if($type =~ /::linker$/) + my $type; + if(defined $arg{type}) { - $type = 'wasmtime_linker_t'; - } - elsif($type =~ /::wasi/) - { - $type =~ s/^.*::wasi(.*)$/wasi_${1}_t/g; - } - elsif($type =~ /::moduletype/) - { - $type = 'wasmtime_moduletype_t'; + $type = $arg{type}; } else { - $type =~ s/^.*:://; - $type = "wasm_${type}_t"; + $type = lc $caller; + if($type =~ /::linker$/) + { + $type = 'wasmtime_linker_t'; + } + elsif($type =~ /::wasi/) + { + $type =~ s/^.*::wasi(.*)$/wasi_${1}_t/g; + } + elsif($type =~ /::moduletype/) + { + $type = 'wasmtime_moduletype_t'; + } + else + { + $type =~ s/^.*:://; + $type = "wasm_${type}_t"; + } } $ffi->attach( [ delete => join('::', $caller, 'DESTROY') ] => [ $type ] => \&_wrapper_destroy); } diff --git a/lib/Wasm/Wasmtime/Instance.pm b/lib/Wasm/Wasmtime/Instance.pm index 3c16536..e578207 100644 --- a/lib/Wasm/Wasmtime/Instance.pm +++ b/lib/Wasm/Wasmtime/Instance.pm @@ -37,11 +37,11 @@ $ffi->load_custom_type('::PtrObject' => 'wasm_instance_t' => __PACKAGE__); my $instance = Wasm::Wasmtime::Instance->new( $module, # Wasm::Wasmtime::Module - $store # Wasm::Wasmtime::Store + $context, # Wasm::Wasmtime::Context ); my $instance = Wasm::Wasmtime::Instance->new( $module, # Wasm::Wasmtime::Module - $store, # Wasm::Wasmtime::Store + $context, # Wasm::Wasmtime::Context \@imports, # array reference of Wasm::Wasmtime::Extern ); @@ -112,81 +112,178 @@ sub _cast_import require FFI::Platypus::Memory; -$ffi->attach( [ wasmtime_instance_new => 'new' ] => ['wasm_store_t','wasm_module_t','record(Wasm::Wasmtime::Vec)*','opaque*','opaque*'] => 'wasmtime_error_t' => sub { - my $xsub = shift; - my $class = shift; - my $module = shift; - my $store = is_blessed_ref($_[0]) && $_[0]->isa('Wasm::Wasmtime::Store') - ? shift - : Carp::croak('Creating a Wasm::Wasmtime::Instance instance without a Wasm::Wasmtime::Store object is no longer allowed'); +if(_ver ne '0.27.0') +{ - my $ptr; - my @keep; + $ffi->attach( [ wasmtime_instance_new => 'new' ] => ['wasmtime_context_t','wasm_module_t','opaque','size_t','opaque*','opaque*'] => 'wasmtime_error_t' => sub { + my $xsub = shift; + my $class = shift; + my $module = shift; - if(defined $_[0] && !is_ref($_[0])) - { - ($ptr) = @_; - return bless { - ptr => $ptr, - module => $module, - keep => \@keep, - }, $class; - } - else - { - my($imports) = @_; + my $context; + + if(is_blessed_ref($_[0]) && $_[0]->isa('Wasm::Wasmtime::Store')) + { + Carp::carp("Passing Store is deprecated, please pass a \$store->context instead"); + $context = shift->context; + } + elsif(is_blessed_ref($_[0]) && $_[0]->isa('Wasm::Wasmtime::Context')) + { + $context = shift; + } + else + { + Carp::croak('Creating a Wasm::Wasmtime::Instance instance without a Wasm::Wasmtime::Store object is no longer allowed'); + } - $imports ||= []; - Carp::confess("imports is not an array reference") unless ref($imports) eq 'ARRAY'; - my @imports = @$imports; - my $trap; + my $ptr; + my @keep; + if(defined $_[0] && !is_ref($_[0])) { - my @mi = @{ $module->type->imports }; - if(@mi != @imports) + ($ptr) = @_; + return bless { + ptr => $ptr, + module => $module, + keep => \@keep, + }, $class; + } + else + { + my($imports) = @_; + + $imports ||= []; + Carp::confess("imports is not an array reference") unless ref($imports) eq 'ARRAY'; + my @imports = @$imports; + my $trap; + { - Carp::croak("Got @{[ scalar @imports ]} imports, but expected @{[ scalar @mi ]}"); + my @mi = @{ $module->type->imports }; + if(@mi != @imports) + { + Carp::croak("Got @{[ scalar @imports ]} imports, but expected @{[ scalar @mi ]}"); + } + + @imports = map { _cast_import($_, shift @mi, $context, \@keep) } @imports; } - @imports = map { _cast_import($_, shift @mi, $store, \@keep) } @imports; + my $ptr; + if(my $error = $xsub->($context, $module, \@imports, scalar(@imports), \$ptr, \$trap)) + { + Carp::croak("error creating module: " . $error->message); + } + else + { + if($trap) + { + $trap = Wasm::Wasmtime::Trap->new($trap); + die $trap; + } + else + { + return bless { + ptr => $ptr, + module => $module, + keep => \@keep, + }, $class; + } + } } + }); + +} +else +{ - my $imports_vec = Wasm::Wasmtime::Vec->new( - size => scalar @imports, - data => scalar(@imports) > 0 ? do { - my $count = scalar @imports; - my $ptr = FFI::Platypus::Memory::malloc($ffi->sizeof('opaque') * $count); - # void *memcpy(void *dest, const void *src, size_t n) - FFI::Platypus->new( lib => [undef] )->function( 'memcpy' => [ 'opaque', "opaque[$count]", 'size_t' ] => 'opaque' )->call($ptr, \@imports, $ffi->sizeof('opaque') * $count); - } : undef, - ); + $ffi->attach( [ wasmtime_instance_new => 'new' ] => ['wasm_store_t','wasm_module_t','record(Wasm::Wasmtime::Vec)*','opaque*','opaque*'] => 'wasmtime_error_t' => sub { + my $xsub = shift; + my $class = shift; + my $module = shift; + + my $store; + + if(is_blessed_ref($_[0]) && $_[0]->isa('Wasm::Wasmtime::Store')) + { + Carp::carp("Passing Store is deprecated, please pass a \$store->context instead"); + $store = shift; + } + elsif(is_blessed_ref($_[0]) && $_[0]->isa('Wasm::Wasmtime::Context')) + { + $store = shift->{store}; + } + else + { + Carp::croak('Creating a Wasm::Wasmtime::Instance instance without a Wasm::Wasmtime::Store object is no longer allowed'); + } my $ptr; - if(my $error = $xsub->($store, $module, $imports_vec, \$ptr, \$trap)) + my @keep; + + if(defined $_[0] && !is_ref($_[0])) { - FFI::Platypus::Memory::free($imports_vec->data) if defined $imports_vec->data; - Carp::croak("error creating module: " . $error->message); + ($ptr) = @_; + return bless { + ptr => $ptr, + module => $module, + keep => \@keep, + }, $class; } else { - FFI::Platypus::Memory::free($imports_vec->data) if defined $imports_vec->data; - if($trap) + my($imports) = @_; + + $imports ||= []; + Carp::confess("imports is not an array reference") unless ref($imports) eq 'ARRAY'; + my @imports = @$imports; + my $trap; + { - $trap = Wasm::Wasmtime::Trap->new($trap); - die $trap; + my @mi = @{ $module->type->imports }; + if(@mi != @imports) + { + Carp::croak("Got @{[ scalar @imports ]} imports, but expected @{[ scalar @mi ]}"); + } + + @imports = map { _cast_import($_, shift @mi, $store, \@keep) } @imports; + } + + my $imports_vec = Wasm::Wasmtime::Vec->new( + size => scalar @imports, + data => scalar(@imports) > 0 ? do { + my $count = scalar @imports; + my $ptr = FFI::Platypus::Memory::malloc($ffi->sizeof('opaque') * $count); + # void *memcpy(void *dest, const void *src, size_t n) + FFI::Platypus->new( lib => [undef] )->function( 'memcpy' => [ 'opaque', "opaque[$count]", 'size_t' ] => 'opaque' )->call($ptr, \@imports, $ffi->sizeof('opaque') * $count); + } : undef, + ); + + my $ptr; + if(my $error = $xsub->($store, $module, $imports_vec, \$ptr, \$trap)) + { + FFI::Platypus::Memory::free($imports_vec->data) if defined $imports_vec->data; + Carp::croak("error creating module: " . $error->message); } else { - return bless { - ptr => $ptr, - module => $module, - keep => \@keep, - }, $class; + FFI::Platypus::Memory::free($imports_vec->data) if defined $imports_vec->data; + if($trap) + { + $trap = Wasm::Wasmtime::Trap->new($trap); + die $trap; + } + else + { + return bless { + ptr => $ptr, + module => $module, + keep => \@keep, + }, $class; + } } } - } + }); -}); +} =head1 METHODS @@ -200,6 +297,12 @@ Returns the L for this instance. sub module { shift->{module} } +=head2 type + + my $type = $instance->type; + +Returns the type of the specified instance, which will be a L instance. + =head2 exports my $exports = $instance->exports; @@ -209,19 +312,27 @@ This can be used to query and call exports from the instance. =cut -sub exports +if(_ver ne '0.27.0') { - Wasm::Wasmtime::Instance::Exports->new(shift); + # TODO: exports } +else +{ + *exports = sub + { + Wasm::Wasmtime::Instance::Exports->new(shift); + }; + + $ffi->attach( [ exports => '_exports' ] => ['wasm_instance_t','wasm_extern_vec_t*'] => sub { + my($xsub, $self) = @_; + my $externs = Wasm::Wasmtime::ExternVec->new; + $xsub->($self, $externs); + $externs->to_list; + }); -$ffi->attach( [ exports => '_exports' ] => ['wasm_instance_t','wasm_extern_vec_t*'] => sub { - my($xsub, $self) = @_; - my $externs = Wasm::Wasmtime::ExternVec->new; - $xsub->($self, $externs); - $externs->to_list; -}); + _generate_destroy(); +} -_generate_destroy(); 1; diff --git a/lib/Wasm/Wasmtime/Linker.pm b/lib/Wasm/Wasmtime/Linker.pm index 250ca26..e1bd280 100644 --- a/lib/Wasm/Wasmtime/Linker.pm +++ b/lib/Wasm/Wasmtime/Linker.pm @@ -164,7 +164,7 @@ $ffi->attach( instantiate => ['wasmtime_linker_t','wasm_module_t','opaque*','opa elsif($ptr) { return Wasm::Wasmtime::Instance->new( - $module, $self->store, $ptr, + $module, $self->store->context, $ptr, ); } else diff --git a/lib/Wasm/Wasmtime/Module.pm b/lib/Wasm/Wasmtime/Module.pm index c46b6fd..53c6c54 100644 --- a/lib/Wasm/Wasmtime/Module.pm +++ b/lib/Wasm/Wasmtime/Module.pm @@ -31,6 +31,7 @@ This class represents a WebAssembly module. =cut +# TODO: this should properly be renamed to wasmtime_module_t $ffi->load_custom_type('::PtrObject' => 'wasm_module_t' => __PACKAGE__); if(_ver ne '0.27.0') diff --git a/lib/Wasm/Wasmtime/Store.pm b/lib/Wasm/Wasmtime/Store.pm index a234d39..51d2e55 100644 --- a/lib/Wasm/Wasmtime/Store.pm +++ b/lib/Wasm/Wasmtime/Store.pm @@ -85,10 +85,10 @@ if(_ver ne '0.27.0') { $ffi->attach( context => ['wasm_store_t'] => 'wasmtime_context_t' => sub { my($xsub, $self) = @_; - $self->{context} || do { - require Wasm::Wasmtime::Context; - $xsub->($self); - }; + require Wasm::Wasmtime::Context; + my $context = $xsub->($self); + $context->{store} = $self; + $context; }); } else diff --git a/t/lib/Test2/Tools/Wasm.pm b/t/lib/Test2/Tools/Wasm.pm index 7838177..89e7d77 100644 --- a/t/lib/Test2/Tools/Wasm.pm +++ b/t/lib/Test2/Tools/Wasm.pm @@ -41,7 +41,7 @@ sub _instance my $ctx = context(); - my $instance = eval { Wasm::Wasmtime::Instance->new($module, wasm_store(), $imports) }; + my $instance = eval { Wasm::Wasmtime::Instance->new($module, wasm_store()->context, $imports) }; return $ctx->fail_and_release($name, "error creating instance", "$@") if $@; $ctx->release; diff --git a/t/wasm_wasmtime_caller.t b/t/wasm_wasmtime_caller.t index 0437875..79eddb7 100644 --- a/t/wasm_wasmtime_caller.t +++ b/t/wasm_wasmtime_caller.t @@ -29,7 +29,7 @@ is(wasmtime_caller(), U()); }, ); - my $instance = Wasm::Wasmtime::Instance->new($module, $store, [$hello]); + my $instance = Wasm::Wasmtime::Instance->new($module, $store->context, [$hello]); $instance->exports->run->call(); # hello world! isa_ok $caller, 'Wasm::Wasmtime::Caller'; diff --git a/t/wasm_wasmtime_instance.t b/t/wasm_wasmtime_instance.t index 2b1ad77..a68b08f 100644 --- a/t/wasm_wasmtime_instance.t +++ b/t/wasm_wasmtime_instance.t @@ -9,7 +9,7 @@ use Wasm::Wasmtime::Instance; my $store = wasm_store(); is( - Wasm::Wasmtime::Instance->new(Wasm::Wasmtime::Module->new($store->engine, wat => '(module)'), $store), + Wasm::Wasmtime::Instance->new(Wasm::Wasmtime::Module->new($store->engine, wat => '(module)'), $store->context), object { call [ isa => 'Wasm::Wasmtime::Instance' ] => T(); call module => object { @@ -32,7 +32,7 @@ is( i64.sub) (memory (export "frooble") 2 3) ) - }), $store), + }), $store->context), object { call [ isa => 'Wasm::Wasmtime::Instance' ] => T(); call exports => object { @@ -103,7 +103,7 @@ is( (func (export "run") (call $hello)) ) }), - $store, + $store->context, ); }, match qr/Got 0 imports, but expected 1/, @@ -127,7 +127,7 @@ is( sub { $it_works = 1 }, ); - my $instance = Wasm::Wasmtime::Instance->new($module, $store, [$hello]); + my $instance = Wasm::Wasmtime::Instance->new($module, $store->context, [$hello]); $instance->exports->run->(); is $it_works, T(), 'callback called'; diff --git a/t/wasm_wasmtime_instance_exports.t b/t/wasm_wasmtime_instance_exports.t index 84c68b9..7c2de99 100644 --- a/t/wasm_wasmtime_instance_exports.t +++ b/t/wasm_wasmtime_instance_exports.t @@ -15,7 +15,7 @@ use YAML qw( Dump ); i32.add) ) }); - my $instance = Wasm::Wasmtime::Instance->new($module, $store, []); + my $instance = Wasm::Wasmtime::Instance->new($module, $store->context, []); my $exports = Wasm::Wasmtime::Instance::Exports->new($instance); is( $exports, diff --git a/t/wasm_wasmtime_linker.t b/t/wasm_wasmtime_linker.t index 1bc4433..cf5bedb 100644 --- a/t/wasm_wasmtime_linker.t +++ b/t/wasm_wasmtime_linker.t @@ -28,7 +28,7 @@ my $wasi = Wasm::Wasmtime::WasiInstance->new( my $instance2 = Wasm::Wasmtime::Instance->new( Wasm::Wasmtime::Module->new($store->engine, wat => '(module)' ), - $store, + $store->context, ); my $module2 = Wasm::Wasmtime::Module->new($store->engine, wat => '(module)' ); From bed8e471771c5fa8125471a1894c1ea9de85557b Mon Sep 17 00:00:00 2001 From: Graham Ollis Date: Sun, 6 Nov 2022 19:26:32 -0700 Subject: [PATCH 14/16] refactor instance class to use the new internal representation --- lib/Wasm/Wasmtime/Instance.pm | 33 +++++++++++++++++------- t/wasm_wasmtime_func.t | 47 +++++++++++++++++++++++++++++++++++ t/wasm_wasmtime_instance.t | 46 ---------------------------------- 3 files changed, 71 insertions(+), 55 deletions(-) diff --git a/lib/Wasm/Wasmtime/Instance.pm b/lib/Wasm/Wasmtime/Instance.pm index e578207..229cbb6 100644 --- a/lib/Wasm/Wasmtime/Instance.pm +++ b/lib/Wasm/Wasmtime/Instance.pm @@ -3,6 +3,7 @@ package Wasm::Wasmtime::Instance; use strict; use warnings; use 5.008004; +use FFI::C; use Wasm::Wasmtime::FFI; use Wasm::Wasmtime::Module; use Wasm::Wasmtime::Extern; @@ -29,7 +30,23 @@ This class represents an instance of a WebAssembly module Lload_custom_type('::PtrObject' => 'wasm_instance_t' => __PACKAGE__); + +if(_ver ne '0.27.0') +{ + FFI::C->ffi($ffi); + FFI::C->struct( + wasm_instance_t => [ + _store_id => 'uint64', + _index => 'size_t', + ], + ); + *_new = \&new; + delete $Wasm::Wasmtime::Instance::{new}; +} +else +{ + $ffi->load_custom_type('::PtrObject' => 'wasm_instance_t' => __PACKAGE__); +} =head1 CONSTRUCTOR @@ -115,7 +132,7 @@ require FFI::Platypus::Memory; if(_ver ne '0.27.0') { - $ffi->attach( [ wasmtime_instance_new => 'new' ] => ['wasmtime_context_t','wasm_module_t','opaque','size_t','opaque*','opaque*'] => 'wasmtime_error_t' => sub { + $ffi->attach( [ wasmtime_instance_new => 'new' ] => ['wasmtime_context_t','wasm_module_t','opaque','size_t','wasm_instance_t','opaque*'] => 'wasmtime_error_t' => sub { my $xsub = shift; my $class = shift; my $module = shift; @@ -167,8 +184,8 @@ if(_ver ne '0.27.0') @imports = map { _cast_import($_, shift @mi, $context, \@keep) } @imports; } - my $ptr; - if(my $error = $xsub->($context, $module, \@imports, scalar(@imports), \$ptr, \$trap)) + my $self = __PACKAGE__->_new; + if(my $error = $xsub->($context, $module, \@imports, scalar(@imports), $self, \$trap)) { Carp::croak("error creating module: " . $error->message); } @@ -181,11 +198,9 @@ if(_ver ne '0.27.0') } else { - return bless { - ptr => $ptr, - module => $module, - keep => \@keep, - }, $class; + $self->{module} = $module; + $self->{keep} = \@keep; + return $self; } } } diff --git a/t/wasm_wasmtime_func.t b/t/wasm_wasmtime_func.t index 1282992..9c453df 100644 --- a/t/wasm_wasmtime_func.t +++ b/t/wasm_wasmtime_func.t @@ -3,6 +3,7 @@ use Test2::V0 -no_srand => 1; use lib 't/lib'; use Test2::Tools::Wasm; use Wasm::Wasmtime::Store; +use Wasm::Wasmtime::Instance; use Wasm::Wasmtime::Func; use Wasm::Wasmtime::FuncType; @@ -255,4 +256,50 @@ is( } +{ + my $it_works; + + my $store = Wasm::Wasmtime::Store->new; + my $module = Wasm::Wasmtime::Module->new( $store->engine, wat => q{ + (module + (func $hello (import "" "hello")) + (func (export "run") (call $hello)) + ) + }); + + my $hello = Wasm::Wasmtime::Func->new( + $store, + Wasm::Wasmtime::FuncType->new([],[]), + sub { $it_works = 1 }, + ); + + my $instance = Wasm::Wasmtime::Instance->new($module, $store->context, [$hello]); + $instance->exports->run->(); + + is $it_works, T(), 'callback called'; +} + +{ + my $it_works; + + is( + wasm_instance_ok([sub { $it_works = 1 }], q{ + (module + (func $hello (import "" "hello")) + (func (export "run") (call $hello)) + ) + }), + object { + call exports => object { + call run => object { + call call => U(); + }; + }; + }, + 'pass func as code ref' + ); + + is($it_works, T(), 'verified that we called the callback'); +} + done_testing; diff --git a/t/wasm_wasmtime_instance.t b/t/wasm_wasmtime_instance.t index a68b08f..afadccb 100644 --- a/t/wasm_wasmtime_instance.t +++ b/t/wasm_wasmtime_instance.t @@ -110,52 +110,6 @@ is( 'import count mismatch', ); -{ - my $it_works; - - my $store = Wasm::Wasmtime::Store->new; - my $module = Wasm::Wasmtime::Module->new( $store->engine, wat => q{ - (module - (func $hello (import "" "hello")) - (func (export "run") (call $hello)) - ) - }); - - my $hello = Wasm::Wasmtime::Func->new( - $store, - Wasm::Wasmtime::FuncType->new([],[]), - sub { $it_works = 1 }, - ); - - my $instance = Wasm::Wasmtime::Instance->new($module, $store->context, [$hello]); - $instance->exports->run->(); - - is $it_works, T(), 'callback called'; -} - -{ - my $it_works; - - is( - wasm_instance_ok([sub { $it_works = 1 }], q{ - (module - (func $hello (import "" "hello")) - (func (export "run") (call $hello)) - ) - }), - object { - call exports => object { - call run => object { - call call => U(); - }; - }; - }, - 'pass func as code ref' - ); - - is($it_works, T(), 'verified that we called the callback'); -} - { wasm_instance_ok([undef], q{ (module From 7beb61aaa1fb1e0e396a96d30f37c341572731a7 Mon Sep 17 00:00:00 2001 From: Graham Ollis Date: Mon, 7 Nov 2022 14:21:15 -0700 Subject: [PATCH 15/16] split memory integration tests --- new.pl | 43 +++------------------ t/wasm_wasmtime_memory.t | 54 ++++++++++++--------------- t/wasm_wasmtime_memory__integration.t | 39 +++++++++++++++++++ 3 files changed, 67 insertions(+), 69 deletions(-) create mode 100644 t/wasm_wasmtime_memory__integration.t diff --git a/new.pl b/new.pl index 0aa0839..8edfec7 100644 --- a/new.pl +++ b/new.pl @@ -1,50 +1,17 @@ use strict; use warnings; +use File::Glob qw( bsd_glob ); $ENV{WASM_WASMTIME_FFI} = '/home/ollisg/opt/wasmtime/0.28.0/lib/libwasmtime.so'; exec @ARGV if @ARGV; -my %wt_tests = map { $_ => 1 } qw( - t/00_diag.t - t/test2_plugin_wasm.t - t/wasm_wasmtime.t - t/wasm_wasmtime_bytevec.t - t/wasm_wasmtime_caller.t - t/wasm_wasmtime_config.t - t/wasm_wasmtime_context.t - t/wasm_wasmtime_engine.t - t/wasm_wasmtime_exporttype.t - t/wasm_wasmtime_extern.t - t/wasm_wasmtime_externtype.t - t/wasm_wasmtime_ffi.t - t/wasm_wasmtime_func.t - t/wasm_wasmtime_functype.t - t/wasm_wasmtime_global.t - t/wasm_wasmtime_globaltype.t - t/wasm_wasmtime_importtype.t - t/wasm_wasmtime_instance.t - t/wasm_wasmtime_instance_exports.t - t/wasm_wasmtime_linker.t - t/wasm_wasmtime_memory.t - t/wasm_wasmtime_memorytype.t - t/wasm_wasmtime_module.t - t/wasm_wasmtime_moduletype_exports.t - t/wasm_wasmtime_moduletype_imports.t - t/wasm_wasmtime_moduletype.t - t/wasm_wasmtime_store.t - t/wasm_wasmtime_table.t - t/wasm_wasmtime_tabletype.t - t/wasm_wasmtime_trap.t - t/wasm_wasmtime_valtype.t - t/wasm_wasmtime_wasiconfig.t - t/wasm_wasmtime_wasiinstance.t - t/wasm_wasmtime_wat2wasm.t -); +my %wt_tests = map { $_ => 1 } bsd_glob('t/wasm_wasmtime*.t'); +$wt_tests{'t/00_diag.t'} = 1; delete $wt_tests{$_} for qw( t/wasm_wasmtime_caller.t t/wasm_wasmtime_extern.t t/wasm_wasmtime_func.t t/wasm_wasmtime_global.t t/wasm_wasmtime_instance.t - t/wasm_wasmtime_instance_exports.t t/wasm_wasmtime_linker.t t/wasm_wasmtime_memory.t t/wasm_wasmtime_table.t - t/wasm_wasmtime_trap.t ); + t/wasm_wasmtime_instance_exports.t t/wasm_wasmtime_linker.t t/wasm_wasmtime_memory.t t/wasm_wasmtime_memory__integration.t + t/wasm_wasmtime_table.t t/wasm_wasmtime_trap.t ); my @wt_tests = sort keys %wt_tests; diff --git a/t/wasm_wasmtime_memory.t b/t/wasm_wasmtime_memory.t index 66d0092..daf248b 100644 --- a/t/wasm_wasmtime_memory.t +++ b/t/wasm_wasmtime_memory.t @@ -1,61 +1,53 @@ use 5.008004; use Test2::V0 -no_srand => 1; use Test2::Plugin::Wasm; -use lib 't/lib'; -use Test2::Tools::Wasm; use Wasm::Wasmtime::Memory; use Wasm::Wasmtime::Store; -use Wasm::Wasmtime::MemoryType; is( - wasm_instance_ok([], q{ - (module - (memory (export "frooble") 2 6) - ) - }), + Wasm::Wasmtime::Memory->new( + Wasm::Wasmtime::Store->new, + Wasm::Wasmtime::MemoryType->new([1,2]), + ), object { - call exports => object { - call frooble => object { - call [ isa => 'Wasm::Wasmtime::Memory' ] => T(); - call type => object { - call [ isa => 'Wasm::Wasmtime::MemoryType' ] => T(); - }; - call data => match qr/^[0-9]+$/; - call data_size => match qr/^[0-9]+$/; - call size => 2; - call [ grow => 3] => T(); - call size => 5; - call is_func => F(); - call is_global => F(); - call is_table => F(); - call is_memory => T(); - call kind => 'memory'; - }; - }; + call [ isa => 'Wasm::Wasmtime::Memory' ] => T(); }, - 'memory class basics', + 'standalone', ); is( Wasm::Wasmtime::Memory->new( Wasm::Wasmtime::Store->new, - Wasm::Wasmtime::MemoryType->new([1,2]), + [1,2], ), object { call [ isa => 'Wasm::Wasmtime::Memory' ] => T(); }, - 'standalone', + 'standalone (ii)', ); is( Wasm::Wasmtime::Memory->new( Wasm::Wasmtime::Store->new, - [1,2], + [2, 6], ), object { call [ isa => 'Wasm::Wasmtime::Memory' ] => T(); + call type => object { + call [ isa => 'Wasm::Wasmtime::MemoryType' ] => T(); + }; + call data => match qr/^[0-9]+$/; + call data_size => match qr/^[0-9]+$/; + call size => 2; + call [ grow => 3] => T(); + call size => 5; + call is_func => F(); + call is_global => F(); + call is_table => F(); + call is_memory => T(); + call kind => 'memory'; }, - 'standalone (ii)', + 'call methods' ); done_testing; diff --git a/t/wasm_wasmtime_memory__integration.t b/t/wasm_wasmtime_memory__integration.t new file mode 100644 index 0000000..73d9e82 --- /dev/null +++ b/t/wasm_wasmtime_memory__integration.t @@ -0,0 +1,39 @@ +use 5.008004; +use Test2::V0 -no_srand => 1; +use Test2::Plugin::Wasm; +use lib 't/lib'; +use Test2::Tools::Wasm; +use Wasm::Wasmtime::Memory; +use Wasm::Wasmtime::Store; +use Wasm::Wasmtime::MemoryType; + +is( + wasm_instance_ok([], q{ + (module + (memory (export "frooble") 2 6) + ) + }), + object { + call exports => object { + call frooble => object { + call [ isa => 'Wasm::Wasmtime::Memory' ] => T(); + call type => object { + call [ isa => 'Wasm::Wasmtime::MemoryType' ] => T(); + }; + call data => match qr/^[0-9]+$/; + call data_size => match qr/^[0-9]+$/; + call size => 2; + call [ grow => 3] => T(); + call size => 5; + call is_func => F(); + call is_global => F(); + call is_table => F(); + call is_memory => T(); + call kind => 'memory'; + }; + }; + }, + 'memory class basics', +); + +done_testing; From 7c3e7809f7d04f53d0686b0968c95f77696e7bb8 Mon Sep 17 00:00:00 2001 From: Graham Ollis Date: Mon, 7 Nov 2022 15:12:44 -0700 Subject: [PATCH 16/16] fix standalone memory object --- Changes | 4 + lib/Wasm/Wasmtime/Instance.pm | 21 +-- lib/Wasm/Wasmtime/Memory.pm | 236 ++++++++++++++++++++------ new.pl | 15 +- t/wasm_memory.t | 4 +- t/wasm_wasmtime_memory.t | 10 +- t/wasm_wasmtime_memory__integration.t | 2 +- 7 files changed, 220 insertions(+), 72 deletions(-) diff --git a/Changes b/Changes index a360a4c..e719d56 100644 --- a/Changes +++ b/Changes @@ -10,6 +10,10 @@ Revision history for {{$dist->name}}, - Wasm::Wasmtime::Module::Exports renamed to Wasm::Wasmtime::ModuleType::Exports (gh#118) - Passing Wasm::Wasmtime::Store into Wasm::Wasmtime::Instance->new is deprecated pass $store->context instead (gh#118) + - Wasm::Wasmtime::Memory method grow throws an exception instead of returning + a false value on error (gh#118) + - Wasm::Memory method grow throws an exception instead of returning a false + value on error (gh#118) 0.23 2022-11-04 06:33:12 -0600 - removed wasmtime_config_max_instances_set from Wasm::Wasmtime::Config diff --git a/lib/Wasm/Wasmtime/Instance.pm b/lib/Wasm/Wasmtime/Instance.pm index 229cbb6..7052b44 100644 --- a/lib/Wasm/Wasmtime/Instance.pm +++ b/lib/Wasm/Wasmtime/Instance.pm @@ -116,7 +116,7 @@ sub _cast_import if($mi->type->kind eq 'memorytype') { my $m = Wasm::Wasmtime::Memory->new( - $store, + $store->context, $mi->type, ); $$ii = $m if defined $ii; @@ -189,19 +189,16 @@ if(_ver ne '0.27.0') { Carp::croak("error creating module: " . $error->message); } + if($trap) + { + $trap = Wasm::Wasmtime::Trap->new($trap); + die $trap; + } else { - if($trap) - { - $trap = Wasm::Wasmtime::Trap->new($trap); - die $trap; - } - else - { - $self->{module} = $module; - $self->{keep} = \@keep; - return $self; - } + $self->{module} = $module; + $self->{keep} = \@keep; + return $self; } } }); diff --git a/lib/Wasm/Wasmtime/Memory.pm b/lib/Wasm/Wasmtime/Memory.pm index a20ff49..0a5f085 100644 --- a/lib/Wasm/Wasmtime/Memory.pm +++ b/lib/Wasm/Wasmtime/Memory.pm @@ -3,8 +3,8 @@ package Wasm::Wasmtime::Memory; use strict; use warnings; use 5.008004; -use base qw( Wasm::Wasmtime::Extern ); -use Ref::Util qw( is_ref is_plain_arrayref ); +use Ref::Util qw( is_ref is_plain_arrayref is_blessed_ref ); +use Wasm::Wasmtime::Extern; use Wasm::Wasmtime::FFI; use Wasm::Wasmtime::Store; use Wasm::Wasmtime::MemoryType; @@ -27,15 +27,34 @@ This class represents a WebAssembly memory object. =cut -$ffi_prefix = 'wasm_memory_'; -$ffi->load_custom_type('::PtrObject' => 'wasm_memory_t' => __PACKAGE__); +if(_ver ne '0.27.0') +{ + $ffi_prefix = 'wasmtime_memory_'; + FFI::C->ffi($ffi); + FFI::C->struct( + wasmtime_memory_t => [ + _store_id => 'uint64', + _index => 'size_t', + ], + ); + *_new = \&new; + delete $Wasm::Wasmtime::Memory::{new}; + constant->import("is_$_" => 0) for qw( func global table ); +} +else +{ + $ffi_prefix = 'wasm_memory_'; + $ffi->load_custom_type('::PtrObject' => 'wasm_memory_t' => __PACKAGE__); + our @ISA; ## no critic (ClassHierarchies::ProhibitExplicitISA) + push @ISA, 'Wasm::Wasmtime::Extern'; ## no critic (ClassHierarchies::ProhibitExplicitISA) +} =head1 CONSTRUCTOR =head2 new my $memory = Wasm::Wasmtime::Memory->new( - $store, # Wasm::Wasmtime::Store + $context, # Wasm::Wasmtime::Context $memorytype, # Wasm::Wasmtime::MemoryType ); @@ -43,25 +62,82 @@ Creates a new memory object. =cut -$ffi->attach( new => ['wasm_store_t', 'wasm_memorytype_t'] => 'wasm_memory_t' => sub { - my $xsub = shift; - my $class = shift; - if(is_ref $_[0]) - { - my($store, $memorytype) = @_; - $memorytype = Wasm::Wasmtime::MemoryType->new($memorytype) - if is_plain_arrayref $memorytype; - return $xsub->($store, $memorytype); - } - else - { - my($ptr, $owner) = @_; - return bless { - ptr => $ptr, - owner => $owner, - }, $class; - } -}); +if(_ver ne '0.27.0') +{ + $ffi->attach( new => ['wasmtime_context_t','wasm_memorytype_t','wasmtime_memory_t'] => 'wasmtime_error_t' => sub { + my $xsub = shift; + my $class = shift; + if(is_ref $_[0]) + { + my $context; + if(is_blessed_ref($_[0]) && $_[0]->isa('Wasm::Wasmtime::Store')) + { + Carp::carp("Passing Store is deprecated, please pass a \$store->context instead"); + $context = shift->context; + } + elsif(is_blessed_ref($_[0]) && $_[0]->isa('Wasm::Wasmtime::Context')) + { + $context = shift; + } + else + { + Carp::croak("Must pass in a Wasm::Wasmtime::Store or Wasm::Wasmtime::Context"); + } + my $memorytype = shift; + $memorytype = Wasm::Wasmtime::MemoryType->new($memorytype) + if is_plain_arrayref $memorytype; + my $self = __PACKAGE__->_new; + my $error = $xsub->($context, $memorytype, $self); + if($error) + { + Carp::croak("error creating memory: " . $error->message); + } + $self->{context} = $context; + return $self; + } + else + { + Carp::croak('todo'); + } + + }); +} +else +{ + $ffi->attach( new => ['wasm_store_t', 'wasm_memorytype_t'] => 'wasm_memory_t' => sub { + my $xsub = shift; + my $class = shift; + if(is_ref $_[0]) + { + my $store; + if(is_blessed_ref($_[0]) && $_[0]->isa('Wasm::Wasmtime::Store')) + { + Carp::carp("Passing Store is deprecated, please pass a \$store->context instead"); + $store = shift; + } + elsif(is_blessed_ref($_[0]) && $_[0]->isa('Wasm::Wasmtime::Context')) + { + $store = shift->{store}; + } + else + { + Carp::croak("Must pass in a Wasm::Wasmtime::Store or Wasm::Wasmtime::Context"); + } + my $memorytype = shift; + $memorytype = Wasm::Wasmtime::MemoryType->new($memorytype) + if is_plain_arrayref $memorytype; + return $xsub->($store, $memorytype); + } + else + { + my($ptr, $owner) = @_; + return bless { + ptr => $ptr, + owner => $owner, + }, $class; + } + }); +} =head1 METHODS @@ -73,12 +149,22 @@ Returns the L object for this memory object. =cut -$ffi->attach( type => ['wasm_memory_t'] => 'wasm_memorytype_t' => sub { - my($xsub, $self) = @_; - my $type = $xsub->($self); - $type->{owner} = $self->{owner} || $self if $type; - $type; -}); +if(_ver ne '0.27.0') +{ + $ffi->attach( type => ['wasmtime_context_t', 'wasmtime_memory_t'] => 'wasm_memorytype_t' => sub { + my($xsub, $self) = @_; + $xsub->($self->{context}, $self); + }); +} +else +{ + $ffi->attach( type => ['wasm_memory_t'] => 'wasm_memorytype_t' => sub { + my($xsub, $self) = @_; + my $type = $xsub->($self); + $type->{owner} = $self->{owner} || $self if $type; + $type; + }); +} =head2 data @@ -88,10 +174,20 @@ Returns a pointer to the start of the memory. =cut -$ffi->attach( data => ['wasm_memory_t'] => 'opaque' => sub { - my($xsub, $self) = @_; - $xsub->($self); -}); +if(_ver ne '0.27.0') +{ + $ffi->attach( data => ['wasmtime_context_t', 'wasmtime_memory_t'] => 'opaque' => sub { + my($xsub, $self) = @_; + $xsub->($self->{context}, $self); + }); +} +else +{ + $ffi->attach( data => ['wasm_memory_t'] => 'opaque' => sub { + my($xsub, $self) = @_; + $xsub->($self); + }); +} =head2 data_size @@ -101,10 +197,20 @@ Returns the current size of the memory in bytes. =cut -$ffi->attach( data_size => ['wasm_memory_t'] => 'size_t' => sub { - my($xsub, $self) = @_; - $xsub->($self); -}); +if(_ver ne '0.27.0') +{ + $ffi->attach( data_size => ['wasmtime_context_t', 'wasmtime_memory_t'] => 'size_t' => sub { + my($xsub, $self) = @_; + $xsub->($self->{context}, $self); + }); +} +else +{ + $ffi->attach( data_size => ['wasm_memory_t'] => 'size_t' => sub { + my($xsub, $self) = @_; + $xsub->($self); + }); +} =head2 size @@ -114,26 +220,56 @@ Returns the current size of the memory in pages. =cut -$ffi->attach( size => ['wasm_memory_t'] => 'uint32' => sub { - my($xsub, $self) = @_; - $xsub->($self); -}); +if(_ver ne '0.27.0') +{ + $ffi->attach( size => ['wasmtime_context_t', 'wasmtime_memory_t'] => 'uint32' => sub { + my($xsub, $self) = @_; + $xsub->($self->{context}, $self); + }); +} +else +{ + $ffi->attach( size => ['wasm_memory_t'] => 'uint32' => sub { + my($xsub, $self) = @_; + $xsub->($self); + }); +} =head2 grow my $bool = $memory->grow($delta); -Tries to increase the page size by the given C<$delta>. Returns true on success, false otherwise. +Tries to increase the page size by the given C<$delta>. Throws an exception in the case of +an error. =cut -$ffi->attach( grow => ['wasm_memory_t', 'uint32'] => 'bool' => sub { - my($xsub, $self, $delta) = @_; - $xsub->($self, $delta); -}); - -__PACKAGE__->_cast(3); -_generate_destroy(); +if(_ver ne '0.27.0') +{ + $ffi->attach( grow => ['wasmtime_context_t','wasmtime_memory_t', 'uint32','uint32*'] => 'bool' => sub { + my($xsub, $self, $delta) = @_; + my $error = $xsub->($self->{context}, $self, $delta, \my $old); + if($error) + { + Carp::croak("error creating memory: " . $error->message); + } + # TODO maybe return $old? Now that we are throwing an + # exception on error? + return $old; + }); +} +else +{ + $ffi->attach( grow => ['wasm_memory_t', 'uint32'] => 'bool' => sub { + my($xsub, $self, $delta) = @_; + $xsub->($self, $delta) || die "error growing memory"; + return ''; + }); + + + __PACKAGE__->_cast(3); + _generate_destroy(); +} 1; diff --git a/new.pl b/new.pl index 8edfec7..3218c63 100644 --- a/new.pl +++ b/new.pl @@ -9,9 +9,18 @@ my %wt_tests = map { $_ => 1 } bsd_glob('t/wasm_wasmtime*.t'); $wt_tests{'t/00_diag.t'} = 1; -delete $wt_tests{$_} for qw( t/wasm_wasmtime_caller.t t/wasm_wasmtime_extern.t t/wasm_wasmtime_func.t t/wasm_wasmtime_global.t t/wasm_wasmtime_instance.t - t/wasm_wasmtime_instance_exports.t t/wasm_wasmtime_linker.t t/wasm_wasmtime_memory.t t/wasm_wasmtime_memory__integration.t - t/wasm_wasmtime_table.t t/wasm_wasmtime_trap.t ); +delete $wt_tests{$_} for qw( +t/wasm_wasmtime_caller.t +t/wasm_wasmtime_extern.t +t/wasm_wasmtime_func.t +t/wasm_wasmtime_global.t +t/wasm_wasmtime_instance.t +t/wasm_wasmtime_instance_exports.t +t/wasm_wasmtime_linker.t +t/wasm_wasmtime_memory__integration.t +t/wasm_wasmtime_table.t +t/wasm_wasmtime_trap.t +); my @wt_tests = sort keys %wt_tests; diff --git a/t/wasm_memory.t b/t/wasm_memory.t index c917d71..23eaecb 100644 --- a/t/wasm_memory.t +++ b/t/wasm_memory.t @@ -10,7 +10,7 @@ my $store = Wasm::Wasmtime::Store->new; is( Wasm::Memory->new( Wasm::Wasmtime::Memory->new( - $store, [5,10], + $store->context, [5,10], ) ), object { @@ -18,7 +18,7 @@ is( call address => match qr/^[0-9]+$/; call size => 327680; call_list limits => [ 5, 5, 10 ]; - call [ grow => 2 ] => T(); + call [ grow => 2 ] => D(); call_list limits => [ 7, 5, 10 ]; }, 'create a memory object' diff --git a/t/wasm_wasmtime_memory.t b/t/wasm_wasmtime_memory.t index daf248b..c3aedc4 100644 --- a/t/wasm_wasmtime_memory.t +++ b/t/wasm_wasmtime_memory.t @@ -4,9 +4,11 @@ use Test2::Plugin::Wasm; use Wasm::Wasmtime::Memory; use Wasm::Wasmtime::Store; +my $context = Wasm::Wasmtime::Store->new->context; + is( Wasm::Wasmtime::Memory->new( - Wasm::Wasmtime::Store->new, + $context, Wasm::Wasmtime::MemoryType->new([1,2]), ), object { @@ -17,7 +19,7 @@ is( is( Wasm::Wasmtime::Memory->new( - Wasm::Wasmtime::Store->new, + $context, [1,2], ), object { @@ -28,7 +30,7 @@ is( is( Wasm::Wasmtime::Memory->new( - Wasm::Wasmtime::Store->new, + $context, [2, 6], ), object { @@ -39,7 +41,7 @@ is( call data => match qr/^[0-9]+$/; call data_size => match qr/^[0-9]+$/; call size => 2; - call [ grow => 3] => T(); + call [ grow => 3] => D(); call size => 5; call is_func => F(); call is_global => F(); diff --git a/t/wasm_wasmtime_memory__integration.t b/t/wasm_wasmtime_memory__integration.t index 73d9e82..2c60d2b 100644 --- a/t/wasm_wasmtime_memory__integration.t +++ b/t/wasm_wasmtime_memory__integration.t @@ -23,7 +23,7 @@ is( call data => match qr/^[0-9]+$/; call data_size => match qr/^[0-9]+$/; call size => 2; - call [ grow => 3] => T(); + call [ grow => 3] => D(); call size => 5; call is_func => F(); call is_global => F();