diff --git a/tests/test_instance.py b/tests/test_instance.py index fa4628a9..59c2e93e 100644 --- a/tests/test_instance.py +++ b/tests/test_instance.py @@ -71,6 +71,25 @@ def test_multiple_exports(self): assert(isinstance(instance.exports[1], Func)) assert(isinstance(instance.exports[2], Global)) + def test_instance_type(self): + store = Store() + module = Module(store.engine, """ + (module + (func (export "a")) + (func (export "b")) + (global (export "c") i32 (i32.const 0)) + ) + """) + ty = Instance(store, module, []).type + exports = ty.exports + self.assertEqual(len(exports), 3) + assert(isinstance(exports[0].type, FuncType)) + assert(exports[0].name == 'a') + assert(isinstance(exports[1].type, FuncType)) + assert(exports[1].name == 'b') + assert(isinstance(exports[2].type, GlobalType)) + assert(exports[2].name == 'c') + def test_import_func(self): store = Store() module = Module(store.engine, """ diff --git a/tests/test_module.py b/tests/test_module.py index bce7b45a..136154cf 100644 --- a/tests/test_module.py +++ b/tests/test_module.py @@ -110,6 +110,43 @@ def test_exports(self): self.assertEqual(ty.limits, Limits(1, None)) self.assertEqual(ty.element, ValType.funcref()) + def test_type(self): + store = Store() + module = Module(store.engine, """ + (module + (import "" "" (func)) + (import "a" "bcd" (global i32)) + (import "" "x" (table 1 funcref)) + + (func (export "a") (param i32 f32) (result f64) + f64.const 0) + (global (export "") (mut i32) (i32.const 1)) + (memory (export "mem") 1) + (table (export "table") 1 funcref) + ) + """) + ty = module.type + imports = ty.imports + exports = ty.exports + assert(imports[0].module == '') + assert(imports[0].name == '') + assert(isinstance(imports[0].type, FuncType)) + assert(imports[1].module == 'a') + assert(imports[1].name == 'bcd') + assert(isinstance(imports[1].type, GlobalType)) + assert(imports[2].module == '') + assert(imports[2].name == 'x') + assert(isinstance(imports[2].type, TableType)) + + assert(exports[0].name == 'a') + assert(isinstance(exports[0].type, FuncType)) + assert(exports[1].name == '') + assert(isinstance(exports[1].type, GlobalType)) + assert(exports[2].name == 'mem') + assert(isinstance(exports[2].type, MemoryType)) + assert(exports[3].name == 'table') + assert(isinstance(exports[3].type, TableType)) + def test_serialize(self): store = Store() module = Module(store.engine, '(module)') diff --git a/tests/test_module_linking.py b/tests/test_module_linking.py new file mode 100644 index 00000000..41554894 --- /dev/null +++ b/tests/test_module_linking.py @@ -0,0 +1,55 @@ +import unittest + +from wasmtime import * + + +class TestModuleLinking(unittest.TestCase): + def store(self): + config = Config() + config.wasm_module_linking = True + return Store(Engine(config)) + + def test_import_string_optional(self): + store = self.store() + module = Module(store.engine, """ + (module + (import "" (func)) + ) + """) + assert(module.type.imports[0].module == '') + assert(module.type.imports[0].name is None) + + def test_module_import(self): + store = self.store() + module1 = Module(store.engine, """ + (module (import "" (module))) + """) + module2 = Module(store.engine, "(module)") + Instance(store, module1, [module2]) + + def test_module_export(self): + store = self.store() + module = Module(store.engine, """ + (module (module (export ""))) + """) + i = Instance(store, module, []) + assert(isinstance(i.exports[0], Module)) + + def test_instance_import(self): + store = self.store() + module = Module(store.engine, """ + (module (import "" (instance))) + """) + instance = Instance(store, Module(store.engine, "(module)"), []) + Instance(store, module, [instance]) + + def test_instance_export(self): + store = self.store() + instance = Module(store.engine, """ + (module + (module $m) + (instance (export "") (instantiate $m)) + ) + """) + i = Instance(store, instance, []) + assert(isinstance(i.exports[0], Instance)) diff --git a/tests/test_trap.py b/tests/test_trap.py index ea454644..c44b57a0 100644 --- a/tests/test_trap.py +++ b/tests/test_trap.py @@ -53,9 +53,9 @@ def test_frames(self): self.assertEqual(str(trap), """\ wasm trap: unreachable wasm backtrace: - 0: 0x2d - module!bar - 1: 0x28 - module!foo - 2: 0x23 - module! + 0: 0x2d - module!bar + 1: 0x28 - module!foo + 2: 0x23 - module! """) def test_frames_no_module(self): diff --git a/wasmtime/__init__.py b/wasmtime/__init__.py index cf6d9f48..0e72e40c 100644 --- a/wasmtime/__init__.py +++ b/wasmtime/__init__.py @@ -18,7 +18,7 @@ from ._engine import Engine from ._store import Store from ._types import FuncType, GlobalType, MemoryType, TableType -from ._types import ValType, Limits, ImportType, ExportType +from ._types import ValType, Limits, ImportType, ExportType, ModuleType, InstanceType from ._wat2wasm import wat2wasm from ._module import Module from ._value import Val, IntoVal diff --git a/wasmtime/_bindings.py b/wasmtime/_bindings.py index 543478da..a39e3b67 100644 --- a/wasmtime/_bindings.py +++ b/wasmtime/_bindings.py @@ -1812,6 +1812,12 @@ def wasmtime_config_wasm_bulk_memory_set(arg0: Any, arg1: Any) -> None: def wasmtime_config_wasm_multi_value_set(arg0: Any, arg1: Any) -> None: return _wasmtime_config_wasm_multi_value_set(arg0, arg1) # type: ignore +_wasmtime_config_wasm_module_linking_set = dll.wasmtime_config_wasm_module_linking_set +_wasmtime_config_wasm_module_linking_set.restype = None +_wasmtime_config_wasm_module_linking_set.argtypes = [POINTER(wasm_config_t), c_bool] +def wasmtime_config_wasm_module_linking_set(arg0: Any, arg1: Any) -> None: + return _wasmtime_config_wasm_module_linking_set(arg0, arg1) # type: ignore + _wasmtime_config_strategy_set = dll.wasmtime_config_strategy_set _wasmtime_config_strategy_set.restype = POINTER(wasmtime_error_t) _wasmtime_config_strategy_set.argtypes = [POINTER(wasm_config_t), wasmtime_strategy_t] @@ -2102,3 +2108,219 @@ def wasmtime_module_serialize(module: Any, ret: Any) -> pointer: _wasmtime_module_deserialize.argtypes = [POINTER(wasm_engine_t), POINTER(wasm_byte_vec_t), POINTER(POINTER(wasm_module_t))] def wasmtime_module_deserialize(engine: Any, serialized: Any, ret: Any) -> pointer: return _wasmtime_module_deserialize(engine, serialized, ret) # type: ignore + +class wasm_instancetype_t(Structure): + pass + +_wasm_instancetype_delete = dll.wasm_instancetype_delete +_wasm_instancetype_delete.restype = None +_wasm_instancetype_delete.argtypes = [POINTER(wasm_instancetype_t)] +def wasm_instancetype_delete(arg0: Any) -> None: + return _wasm_instancetype_delete(arg0) # type: ignore + +class wasm_instancetype_vec_t(Structure): + _fields_ = [ + ("size", c_size_t), + ("data", POINTER(POINTER(wasm_instancetype_t))), + ] + +_wasm_instancetype_vec_new_empty = dll.wasm_instancetype_vec_new_empty +_wasm_instancetype_vec_new_empty.restype = None +_wasm_instancetype_vec_new_empty.argtypes = [POINTER(wasm_instancetype_vec_t)] +def wasm_instancetype_vec_new_empty(out: Any) -> None: + return _wasm_instancetype_vec_new_empty(out) # type: ignore + +_wasm_instancetype_vec_new_uninitialized = dll.wasm_instancetype_vec_new_uninitialized +_wasm_instancetype_vec_new_uninitialized.restype = None +_wasm_instancetype_vec_new_uninitialized.argtypes = [POINTER(wasm_instancetype_vec_t), c_size_t] +def wasm_instancetype_vec_new_uninitialized(out: Any, arg1: Any) -> None: + return _wasm_instancetype_vec_new_uninitialized(out, arg1) # type: ignore + +_wasm_instancetype_vec_new = dll.wasm_instancetype_vec_new +_wasm_instancetype_vec_new.restype = None +_wasm_instancetype_vec_new.argtypes = [POINTER(wasm_instancetype_vec_t), c_size_t, POINTER(POINTER(wasm_instancetype_t))] +def wasm_instancetype_vec_new(out: Any, arg1: Any, arg2: Any) -> None: + return _wasm_instancetype_vec_new(out, arg1, arg2) # type: ignore + +_wasm_instancetype_vec_copy = dll.wasm_instancetype_vec_copy +_wasm_instancetype_vec_copy.restype = None +_wasm_instancetype_vec_copy.argtypes = [POINTER(wasm_instancetype_vec_t), POINTER(wasm_instancetype_vec_t)] +def wasm_instancetype_vec_copy(out: Any, arg1: Any) -> None: + return _wasm_instancetype_vec_copy(out, arg1) # type: ignore + +_wasm_instancetype_vec_delete = dll.wasm_instancetype_vec_delete +_wasm_instancetype_vec_delete.restype = None +_wasm_instancetype_vec_delete.argtypes = [POINTER(wasm_instancetype_vec_t)] +def wasm_instancetype_vec_delete(arg0: Any) -> None: + return _wasm_instancetype_vec_delete(arg0) # type: ignore + +_wasm_instancetype_copy = dll.wasm_instancetype_copy +_wasm_instancetype_copy.restype = POINTER(wasm_instancetype_t) +_wasm_instancetype_copy.argtypes = [POINTER(wasm_instancetype_t)] +def wasm_instancetype_copy(arg0: Any) -> pointer: + return _wasm_instancetype_copy(arg0) # type: ignore + +_wasm_instancetype_exports = dll.wasm_instancetype_exports +_wasm_instancetype_exports.restype = None +_wasm_instancetype_exports.argtypes = [POINTER(wasm_instancetype_t), POINTER(wasm_exporttype_vec_t)] +def wasm_instancetype_exports(arg0: Any, out: Any) -> None: + return _wasm_instancetype_exports(arg0, out) # type: ignore + +_wasm_instancetype_as_externtype = dll.wasm_instancetype_as_externtype +_wasm_instancetype_as_externtype.restype = POINTER(wasm_externtype_t) +_wasm_instancetype_as_externtype.argtypes = [POINTER(wasm_instancetype_t)] +def wasm_instancetype_as_externtype(arg0: Any) -> pointer: + return _wasm_instancetype_as_externtype(arg0) # type: ignore + +_wasm_externtype_as_instancetype = dll.wasm_externtype_as_instancetype +_wasm_externtype_as_instancetype.restype = POINTER(wasm_instancetype_t) +_wasm_externtype_as_instancetype.argtypes = [POINTER(wasm_externtype_t)] +def wasm_externtype_as_instancetype(arg0: Any) -> pointer: + return _wasm_externtype_as_instancetype(arg0) # type: ignore + +_wasm_instancetype_as_externtype_const = dll.wasm_instancetype_as_externtype_const +_wasm_instancetype_as_externtype_const.restype = POINTER(wasm_externtype_t) +_wasm_instancetype_as_externtype_const.argtypes = [POINTER(wasm_instancetype_t)] +def wasm_instancetype_as_externtype_const(arg0: Any) -> pointer: + return _wasm_instancetype_as_externtype_const(arg0) # type: ignore + +_wasm_externtype_as_instancetype_const = dll.wasm_externtype_as_instancetype_const +_wasm_externtype_as_instancetype_const.restype = POINTER(wasm_instancetype_t) +_wasm_externtype_as_instancetype_const.argtypes = [POINTER(wasm_externtype_t)] +def wasm_externtype_as_instancetype_const(arg0: Any) -> pointer: + return _wasm_externtype_as_instancetype_const(arg0) # type: ignore + +class wasm_moduletype_t(Structure): + pass + +_wasm_moduletype_delete = dll.wasm_moduletype_delete +_wasm_moduletype_delete.restype = None +_wasm_moduletype_delete.argtypes = [POINTER(wasm_moduletype_t)] +def wasm_moduletype_delete(arg0: Any) -> None: + return _wasm_moduletype_delete(arg0) # type: ignore + +class wasm_moduletype_vec_t(Structure): + _fields_ = [ + ("size", c_size_t), + ("data", POINTER(POINTER(wasm_moduletype_t))), + ] + +_wasm_moduletype_vec_new_empty = dll.wasm_moduletype_vec_new_empty +_wasm_moduletype_vec_new_empty.restype = None +_wasm_moduletype_vec_new_empty.argtypes = [POINTER(wasm_moduletype_vec_t)] +def wasm_moduletype_vec_new_empty(out: Any) -> None: + return _wasm_moduletype_vec_new_empty(out) # type: ignore + +_wasm_moduletype_vec_new_uninitialized = dll.wasm_moduletype_vec_new_uninitialized +_wasm_moduletype_vec_new_uninitialized.restype = None +_wasm_moduletype_vec_new_uninitialized.argtypes = [POINTER(wasm_moduletype_vec_t), c_size_t] +def wasm_moduletype_vec_new_uninitialized(out: Any, arg1: Any) -> None: + return _wasm_moduletype_vec_new_uninitialized(out, arg1) # type: ignore + +_wasm_moduletype_vec_new = dll.wasm_moduletype_vec_new +_wasm_moduletype_vec_new.restype = None +_wasm_moduletype_vec_new.argtypes = [POINTER(wasm_moduletype_vec_t), c_size_t, POINTER(POINTER(wasm_moduletype_t))] +def wasm_moduletype_vec_new(out: Any, arg1: Any, arg2: Any) -> None: + return _wasm_moduletype_vec_new(out, arg1, arg2) # type: ignore + +_wasm_moduletype_vec_copy = dll.wasm_moduletype_vec_copy +_wasm_moduletype_vec_copy.restype = None +_wasm_moduletype_vec_copy.argtypes = [POINTER(wasm_moduletype_vec_t), POINTER(wasm_moduletype_vec_t)] +def wasm_moduletype_vec_copy(out: Any, arg1: Any) -> None: + return _wasm_moduletype_vec_copy(out, arg1) # type: ignore + +_wasm_moduletype_vec_delete = dll.wasm_moduletype_vec_delete +_wasm_moduletype_vec_delete.restype = None +_wasm_moduletype_vec_delete.argtypes = [POINTER(wasm_moduletype_vec_t)] +def wasm_moduletype_vec_delete(arg0: Any) -> None: + return _wasm_moduletype_vec_delete(arg0) # type: ignore + +_wasm_moduletype_copy = dll.wasm_moduletype_copy +_wasm_moduletype_copy.restype = POINTER(wasm_moduletype_t) +_wasm_moduletype_copy.argtypes = [POINTER(wasm_moduletype_t)] +def wasm_moduletype_copy(arg0: Any) -> pointer: + return _wasm_moduletype_copy(arg0) # type: ignore + +_wasm_moduletype_imports = dll.wasm_moduletype_imports +_wasm_moduletype_imports.restype = None +_wasm_moduletype_imports.argtypes = [POINTER(wasm_moduletype_t), POINTER(wasm_importtype_vec_t)] +def wasm_moduletype_imports(arg0: Any, out: Any) -> None: + return _wasm_moduletype_imports(arg0, out) # type: ignore + +_wasm_moduletype_exports = dll.wasm_moduletype_exports +_wasm_moduletype_exports.restype = None +_wasm_moduletype_exports.argtypes = [POINTER(wasm_moduletype_t), POINTER(wasm_exporttype_vec_t)] +def wasm_moduletype_exports(arg0: Any, out: Any) -> None: + return _wasm_moduletype_exports(arg0, out) # type: ignore + +_wasm_moduletype_as_externtype = dll.wasm_moduletype_as_externtype +_wasm_moduletype_as_externtype.restype = POINTER(wasm_externtype_t) +_wasm_moduletype_as_externtype.argtypes = [POINTER(wasm_moduletype_t)] +def wasm_moduletype_as_externtype(arg0: Any) -> pointer: + return _wasm_moduletype_as_externtype(arg0) # type: ignore + +_wasm_externtype_as_moduletype = dll.wasm_externtype_as_moduletype +_wasm_externtype_as_moduletype.restype = POINTER(wasm_moduletype_t) +_wasm_externtype_as_moduletype.argtypes = [POINTER(wasm_externtype_t)] +def wasm_externtype_as_moduletype(arg0: Any) -> pointer: + return _wasm_externtype_as_moduletype(arg0) # type: ignore + +_wasm_moduletype_as_externtype_const = dll.wasm_moduletype_as_externtype_const +_wasm_moduletype_as_externtype_const.restype = POINTER(wasm_externtype_t) +_wasm_moduletype_as_externtype_const.argtypes = [POINTER(wasm_moduletype_t)] +def wasm_moduletype_as_externtype_const(arg0: Any) -> pointer: + return _wasm_moduletype_as_externtype_const(arg0) # type: ignore + +_wasm_externtype_as_moduletype_const = dll.wasm_externtype_as_moduletype_const +_wasm_externtype_as_moduletype_const.restype = POINTER(wasm_moduletype_t) +_wasm_externtype_as_moduletype_const.argtypes = [POINTER(wasm_externtype_t)] +def wasm_externtype_as_moduletype_const(arg0: Any) -> pointer: + return _wasm_externtype_as_moduletype_const(arg0) # type: ignore + +_wasm_module_as_extern = dll.wasm_module_as_extern +_wasm_module_as_extern.restype = POINTER(wasm_extern_t) +_wasm_module_as_extern.argtypes = [POINTER(wasm_module_t)] +def wasm_module_as_extern(arg0: Any) -> pointer: + return _wasm_module_as_extern(arg0) # type: ignore + +_wasm_extern_as_module = dll.wasm_extern_as_module +_wasm_extern_as_module.restype = POINTER(wasm_module_t) +_wasm_extern_as_module.argtypes = [POINTER(wasm_extern_t)] +def wasm_extern_as_module(arg0: Any) -> pointer: + return _wasm_extern_as_module(arg0) # type: ignore + +_wasm_extern_as_module_const = dll.wasm_extern_as_module_const +_wasm_extern_as_module_const.restype = POINTER(wasm_module_t) +_wasm_extern_as_module_const.argtypes = [POINTER(wasm_extern_t)] +def wasm_extern_as_module_const(arg0: Any) -> pointer: + return _wasm_extern_as_module_const(arg0) # type: ignore + +_wasm_instance_as_extern = dll.wasm_instance_as_extern +_wasm_instance_as_extern.restype = POINTER(wasm_extern_t) +_wasm_instance_as_extern.argtypes = [POINTER(wasm_instance_t)] +def wasm_instance_as_extern(arg0: Any) -> pointer: + return _wasm_instance_as_extern(arg0) # type: ignore + +_wasm_extern_as_instance = dll.wasm_extern_as_instance +_wasm_extern_as_instance.restype = POINTER(wasm_instance_t) +_wasm_extern_as_instance.argtypes = [POINTER(wasm_extern_t)] +def wasm_extern_as_instance(arg0: Any) -> pointer: + return _wasm_extern_as_instance(arg0) # type: ignore + +_wasm_extern_as_instance_const = dll.wasm_extern_as_instance_const +_wasm_extern_as_instance_const.restype = POINTER(wasm_instance_t) +_wasm_extern_as_instance_const.argtypes = [POINTER(wasm_extern_t)] +def wasm_extern_as_instance_const(arg0: Any) -> pointer: + return _wasm_extern_as_instance_const(arg0) # type: ignore + +_wasm_instance_type = dll.wasm_instance_type +_wasm_instance_type.restype = POINTER(wasm_instancetype_t) +_wasm_instance_type.argtypes = [POINTER(wasm_instance_t)] +def wasm_instance_type(arg0: Any) -> pointer: + return _wasm_instance_type(arg0) # type: ignore + +_wasm_module_type = dll.wasm_module_type +_wasm_module_type.restype = POINTER(wasm_moduletype_t) +_wasm_module_type.argtypes = [POINTER(wasm_module_t)] +def wasm_module_type(arg0: Any) -> pointer: + return _wasm_module_type(arg0) # type: ignore diff --git a/wasmtime/_config.py b/wasmtime/_config.py index e450d16a..a20a57bf 100644 --- a/wasmtime/_config.py +++ b/wasmtime/_config.py @@ -94,6 +94,18 @@ def wasm_multi_value(self, enable: bool) -> None: raise TypeError('expected a bool') ffi.wasmtime_config_wasm_multi_value_set(self._ptr, enable) + @setter_property + def wasm_module_linking(self, enable: bool) -> None: + """ + Configures whether the wasm [module linking proposal] is enabled. + + [module linking proposal]: https://github.com/webassembly/module-linking + """ + + if not isinstance(enable, bool): + raise TypeError('expected a bool') + ffi.wasmtime_config_wasm_module_linking_set(self._ptr, enable) + @setter_property def strategy(self, strategy: str) -> None: """ diff --git a/wasmtime/_exportable.py b/wasmtime/_exportable.py index c612317c..8207b014 100644 --- a/wasmtime/_exportable.py +++ b/wasmtime/_exportable.py @@ -5,5 +5,7 @@ from ._globals import Global from ._memory import Memory from ._table import Table + from ._module import Module + from ._instance import Instance -AsExtern = typing.Union["Func", "Table", "Memory", "Global"] +AsExtern = typing.Union["Func", "Table", "Memory", "Global", "Instance", "Module"] diff --git a/wasmtime/_extern.py b/wasmtime/_extern.py index 2eabd8cc..4cb020a3 100644 --- a/wasmtime/_extern.py +++ b/wasmtime/_extern.py @@ -2,10 +2,11 @@ from ctypes import * from ._exportable import AsExtern from typing import Optional, Any +from wasmtime import WasmtimeError def wrap_extern(ptr: 'pointer[ffi.wasm_extern_t]', owner: Optional[Any]) -> AsExtern: - from wasmtime import Func, Table, Global, Memory + from wasmtime import Func, Table, Global, Memory, Module, Instance if not isinstance(ptr, POINTER(ffi.wasm_extern_t)): raise TypeError("wrong pointer type") @@ -25,12 +26,19 @@ def wrap_extern(ptr: 'pointer[ffi.wasm_extern_t]', owner: Optional[Any]) -> AsEx if val: return Global._from_ptr(val, owner) val = ffi.wasm_extern_as_memory(ptr) - assert(val) - return Memory._from_ptr(val, owner) + if val: + return Memory._from_ptr(val, owner) + val = ffi.wasm_extern_as_instance(ptr) + if val: + return Instance._from_ptr(val, owner) + val = ffi.wasm_extern_as_module(ptr) + if val: + return Module._from_ptr(val, owner) + raise WasmtimeError("unknown extern") def get_extern_ptr(item: AsExtern) -> "pointer[ffi.wasm_extern_t]": - from wasmtime import Func, Table, Global, Memory + from wasmtime import Func, Table, Global, Memory, Module, Instance if isinstance(item, Func): return item._as_extern() @@ -40,8 +48,12 @@ def get_extern_ptr(item: AsExtern) -> "pointer[ffi.wasm_extern_t]": return item._as_extern() elif isinstance(item, Table): return item._as_extern() + elif isinstance(item, Module): + return item._as_extern() + elif isinstance(item, Instance): + return item._as_extern() else: - raise TypeError("expected a Func, Global, Memory, or Table") + raise TypeError("expected a Func, Global, Memory, Table, Module, or Instance") class Extern: diff --git a/wasmtime/_instance.py b/wasmtime/_instance.py index 88d97d5b..3e41caab 100644 --- a/wasmtime/_instance.py +++ b/wasmtime/_instance.py @@ -1,15 +1,16 @@ from . import _ffi as ffi from ctypes import POINTER, pointer, byref -from wasmtime import Module, Trap, WasmtimeError, Store +from wasmtime import Module, Trap, WasmtimeError, Store, InstanceType from ._extern import wrap_extern, get_extern_ptr from ._exportable import AsExtern -from typing import Sequence, Union, Optional, Mapping, Iterable +from typing import Sequence, Union, Optional, Mapping, Iterable, Any class Instance: _ptr: "pointer[ffi.wasm_instance_t]" _module: Module _exports: Optional["InstanceExports"] + _owner: Optional[Any] def __init__(self, store: Store, module: Module, imports: Sequence[AsExtern]): """ @@ -47,19 +48,28 @@ def __init__(self, store: Store, module: Module, imports: Sequence[AsExtern]): if trap: raise Trap._from_ptr(trap) self._ptr = instance - self._module = module self._exports = None + self._owner = None @classmethod - def _from_ptr(cls, ptr: pointer, module: Module) -> "Instance": + def _from_ptr(cls, ptr: 'pointer[ffi.wasm_instance_t]', owner: Optional[Any]) -> "Instance": ty: "Instance" = cls.__new__(cls) if not isinstance(ptr, POINTER(ffi.wasm_instance_t)): raise TypeError("wrong pointer type") ty._ptr = ptr - ty._module = module ty._exports = None + ty._owner = owner return ty + @property + def type(self) -> InstanceType: + """ + Gets the type of this instance as an `InstanceType` + """ + + ptr = ffi.wasm_instance_type(self._ptr) + return InstanceType._from_ptr(ptr, None) + @property def exports(self) -> "InstanceExports": """ @@ -74,11 +84,14 @@ def exports(self) -> "InstanceExports": extern_list = [] for i in range(0, externs.vec.size): extern_list.append(wrap_extern(externs.vec.data[i], externs)) - self._exports = InstanceExports(extern_list, self._module) + self._exports = InstanceExports(extern_list, self.type) return self._exports + def _as_extern(self) -> "pointer[ffi.wasm_extern_t]": + return ffi.wasm_instance_as_extern(self._ptr) + def __del__(self) -> None: - if hasattr(self, '_ptr'): + if hasattr(self, '_owner') and self._owner is None: ffi.wasm_instance_delete(self._ptr) @@ -86,10 +99,10 @@ class InstanceExports: _extern_list: Sequence[AsExtern] _extern_map: Mapping[str, AsExtern] - def __init__(self, extern_list: Sequence[AsExtern], module: Module): + def __init__(self, extern_list: Sequence[AsExtern], ty: InstanceType): self._extern_list = extern_list self._extern_map = {} - exports = module.exports + exports = ty.exports for i, extern in enumerate(extern_list): self._extern_map[exports[i].name] = extern diff --git a/wasmtime/_linker.py b/wasmtime/_linker.py index 2741a6a0..07d56909 100644 --- a/wasmtime/_linker.py +++ b/wasmtime/_linker.py @@ -63,7 +63,7 @@ def instantiate(self, module: Module) -> Instance: raise WasmtimeError._from_ptr(error) if trap: raise Trap._from_ptr(trap) - return Instance._from_ptr(instance, module) + return Instance._from_ptr(instance, None) def __del__(self) -> None: if hasattr(self, '_ptr'): diff --git a/wasmtime/_module.py b/wasmtime/_module.py index 86a217f5..905a89b4 100644 --- a/wasmtime/_module.py +++ b/wasmtime/_module.py @@ -1,6 +1,7 @@ from . import _ffi as ffi +from ._types import ExportTypeList, ImportTypeList from ctypes import * -from wasmtime import Store, Engine, wat2wasm, ImportType, ExportType, WasmtimeError +from wasmtime import Store, Engine, wat2wasm, ImportType, ExportType, WasmtimeError, ModuleType import typing @@ -41,15 +42,15 @@ def __init__(self, engine: Engine, wasm: typing.Union[str, bytes]): if error: raise WasmtimeError._from_ptr(error) self._ptr = ptr - self.engine = engine + self._owner = None @classmethod - def _from_ptr(cls, ptr: "pointer[ffi.wasm_module_t]", engine: Engine) -> "Module": + def _from_ptr(cls, ptr: "pointer[ffi.wasm_module_t]", owner: typing.Optional[typing.Any]) -> "Module": ty: "Module" = cls.__new__(cls) if not isinstance(ptr, POINTER(ffi.wasm_module_t)): raise TypeError("wrong pointer type") ty._ptr = ptr - ty.engine = engine + ty._owner = owner return ty @classmethod @@ -78,7 +79,7 @@ def deserialize(cls, engine: Engine, encoded: typing.Union[bytes, bytearray]) -> raise WasmtimeError._from_ptr(error) ret: "Module" = cls.__new__(cls) ret._ptr = ptr - ret.engine = engine + ret._owner = None return ret @classmethod @@ -103,6 +104,15 @@ def validate(cls, store: Store, wasm: typing.Union[bytes, bytearray]) -> None: if error: raise WasmtimeError._from_ptr(error) + @property + def type(self) -> ModuleType: + """ + Gets the type of this module as a `ModuleType` + """ + + ptr = ffi.wasm_module_type(self._ptr) + return ModuleType._from_ptr(ptr, None) + @property def imports(self) -> typing.List[ImportType]: """ @@ -145,18 +155,9 @@ def serialize(self) -> bytearray: ffi.wasm_byte_vec_delete(byref(raw)) return ret - -class ImportTypeList: - def __init__(self) -> None: - self.vec = ffi.wasm_importtype_vec_t(0, None) - - def __del__(self) -> None: - ffi.wasm_importtype_vec_delete(byref(self.vec)) - - -class ExportTypeList: - def __init__(self) -> None: - self.vec = ffi.wasm_exporttype_vec_t(0, None) + def _as_extern(self) -> "pointer[ffi.wasm_extern_t]": + return ffi.wasm_module_as_extern(self._ptr) def __del__(self) -> None: - ffi.wasm_exporttype_vec_delete(byref(self.vec)) + if hasattr(self, '_owner') and self._owner is None: + ffi.wasm_module_delete(self._ptr) diff --git a/wasmtime/_types.py b/wasmtime/_types.py index 669407cb..d01f5550 100644 --- a/wasmtime/_types.py +++ b/wasmtime/_types.py @@ -321,6 +321,93 @@ def __del__(self) -> None: ffi.wasm_memorytype_delete(self._ptr) +class ModuleType: + _ptr: "pointer[ffi.wasm_moduletype_t]" + _owner: Optional[Any] + + def __init__(self) -> None: + raise WasmtimeError("cannot create a `ModuleType` currently") + + @classmethod + def _from_ptr(cls, ptr: "pointer[ffi.wasm_moduletype_t]", owner: Optional[Any]) -> "ModuleType": + ty: "ModuleType" = cls.__new__(cls) + if not isinstance(ptr, POINTER(ffi.wasm_moduletype_t)): + raise TypeError("wrong pointer type") + ty._ptr = ptr + ty._owner = owner + return ty + + @property + def exports(self) -> List['ExportType']: + """ + Returns the types of the exports that this module has + """ + + exports = ExportTypeList() + ffi.wasm_moduletype_exports(self._ptr, byref(exports.vec)) + ret = [] + for i in range(0, exports.vec.size): + ret.append(ExportType._from_ptr(exports.vec.data[i], exports)) + return ret + + @property + def imports(self) -> List['ImportType']: + """ + Returns the types of the imports that this module has + """ + + imports = ImportTypeList() + ffi.wasm_moduletype_imports(self._ptr, byref(imports.vec)) + ret = [] + for i in range(0, imports.vec.size): + ret.append(ImportType._from_ptr(imports.vec.data[i], imports)) + return ret + + def _as_extern(self) -> "pointer[ffi.wasm_externtype_t]": + return ffi.wasm_moduletype_as_externtype_const(self._ptr) + + def __del__(self) -> None: + if hasattr(self, '_owner') and self._owner is None: + ffi.wasm_moduletype_delete(self._ptr) + + +class InstanceType: + _ptr: "pointer[ffi.wasm_instancetype_t]" + _owner: Optional[Any] + + def __init__(self) -> None: + raise WasmtimeError("cannot create an `InstanceType` currently") + + @classmethod + def _from_ptr(cls, ptr: "pointer[ffi.wasm_instancetype_t]", owner: Optional[Any]) -> "InstanceType": + ty: "InstanceType" = cls.__new__(cls) + if not isinstance(ptr, POINTER(ffi.wasm_instancetype_t)): + raise TypeError("wrong pointer type") + ty._ptr = ptr + ty._owner = owner + return ty + + @property + def exports(self) -> List['ExportType']: + """ + Returns the types of the exports that this instance has + """ + + exports = ExportTypeList() + ffi.wasm_instancetype_exports(self._ptr, byref(exports.vec)) + ret = [] + for i in range(0, exports.vec.size): + ret.append(ExportType._from_ptr(exports.vec.data[i], exports)) + return ret + + def _as_extern(self) -> "pointer[ffi.wasm_externtype_t]": + return ffi.wasm_instancetype_as_externtype_const(self._ptr) + + def __del__(self) -> None: + if hasattr(self, '_owner') and self._owner is None: + ffi.wasm_instancetype_delete(self._ptr) + + def wrap_externtype(ptr: "pointer[ffi.wasm_externtype_t]", owner: Optional[Any]) -> "AsExternType": if not isinstance(ptr, POINTER(ffi.wasm_externtype_t)): raise TypeError("wrong pointer type") @@ -334,8 +421,15 @@ def wrap_externtype(ptr: "pointer[ffi.wasm_externtype_t]", owner: Optional[Any]) if val: return GlobalType._from_ptr(val, owner) val = ffi.wasm_externtype_as_memorytype_const(ptr) - assert(val) - return MemoryType._from_ptr(val, owner) + if val: + return MemoryType._from_ptr(val, owner) + val = ffi.wasm_externtype_as_moduletype_const(ptr) + if val: + return ModuleType._from_ptr(val, owner) + val = ffi.wasm_externtype_as_instancetype_const(ptr) + if val: + return InstanceType._from_ptr(val, owner) + raise WasmtimeError("unknown extern type") class ImportType: @@ -360,11 +454,17 @@ def module(self) -> str: return ffi.to_str(ffi.wasm_importtype_module(self._ptr).contents) @property - def name(self) -> str: + def name(self) -> Optional[str]: """ - Returns the name in the modulethis import type refers to + Returns the name in the modulethis import type refers toa. + + Note that `None` may be returned for the module linking proposal where + the field name is optional. """ - return ffi.to_str(ffi.wasm_importtype_name(self._ptr).contents) + ptr = ffi.wasm_importtype_name(self._ptr) + if ptr: + return ffi.to_str(ptr.contents) + return None @property def type(self) -> "AsExternType": @@ -412,4 +512,20 @@ def __del__(self) -> None: ffi.wasm_exporttype_delete(self._ptr) -AsExternType = Union[FuncType, TableType, MemoryType, GlobalType] +class ImportTypeList: + def __init__(self) -> None: + self.vec = ffi.wasm_importtype_vec_t(0, None) + + def __del__(self) -> None: + ffi.wasm_importtype_vec_delete(byref(self.vec)) + + +class ExportTypeList: + def __init__(self) -> None: + self.vec = ffi.wasm_exporttype_vec_t(0, None) + + def __del__(self) -> None: + ffi.wasm_exporttype_vec_delete(byref(self.vec)) + + +AsExternType = Union[FuncType, TableType, MemoryType, GlobalType, InstanceType, ModuleType]