Model: claude-3-5-sonnet-latest
files-to-prompt -e py wasmtime-py/tests -c
<documents>
<document index="1">
<source>./__init__.py</source>
<document_content>
import unittest
</document_content>
</document>
<document index="2">
<source>./test_config.py</source>
<document_content>
import unittest
from contextlib import closing
from wasmtime import *
class TestConfig(unittest.TestCase):
def test_smoke(self):
config = Config()
config.debug_info = True
config.wasm_threads = True
config.wasm_tail_call = True
config.wasm_reference_types = True
config.wasm_simd = True
config.wasm_bulk_memory = True
config.wasm_multi_value = True
config.wasm_multi_memory = True
config.wasm_memory64 = True
config.cranelift_debug_verifier = True
config.strategy = "cranelift"
config.strategy = "auto"
config.cache = True
config.parallel_compilation = False
with self.assertRaises(WasmtimeError):
config.cache = "./test.toml"
with self.assertRaises(WasmtimeError):
config.strategy = "nonexistent-strategy"
config.cranelift_opt_level = "none"
config.cranelift_opt_level = "speed_and_size"
config.cranelift_opt_level = "speed"
with self.assertRaises(WasmtimeError):
config.cranelift_opt_level = "nonexistent-level"
config.profiler = "none"
with self.assertRaises(WasmtimeError):
config.profiler = "nonexistent-profiler"
config.consume_fuel = True
config.wasm_relaxed_simd = True
config.wasm_relaxed_simd_deterministic = True
with closing(config) as config:
pass
config.close()
with self.assertRaises(ValueError):
Engine(config)
with self.assertRaises(ValueError):
config.cache = True
</document_content>
</document>
<document index="3">
<source>./test_engine.py</source>
<document_content>
import unittest
from wasmtime import *
class TestEngine(unittest.TestCase):
def test_smoke(self):
Engine()
Engine(Config())
def test_errors(self):
with self.assertRaises(TypeError):
Engine(3) # type: ignore
config = Config()
Engine(config)
with self.assertRaises(ValueError):
Engine(config)
</document_content>
</document>
<document index="4">
<source>./test_func.py</source>
<document_content>
import unittest
from wasmtime import *
class TestFunc(unittest.TestCase):
def test_smoke(self):
store = Store()
ty = FuncType([], [])
func = Func(store, ty, lambda: None)
func(store)
self.assertTrue(isinstance(func.type(store), FuncType))
def test_add(self):
store = Store()
ty = FuncType([ValType.i32(), ValType.i32()], [ValType.i32()])
func = Func(store, ty, lambda a, b: a + b)
self.assertEqual(func(store, 1, 2), 3)
def test_calls(self):
store = Store()
ty = FuncType([ValType.i32()], [])
func = Func(store, ty, lambda a: self.assertEqual(a, 1))
func(store, 1)
ty = FuncType([ValType.i64()], [])
func = Func(store, ty, lambda a: self.assertEqual(a, 2))
func(store, Val.i64(2))
ty = FuncType([ValType.f32()], [])
func = Func(store, ty, lambda a: self.assertEqual(a, 3.0))
func(store, 3.0)
ty = FuncType([ValType.f64()], [])
func = Func(store, ty, lambda a: self.assertEqual(a, 4.0))
func(store, 4.0)
def test_multi_return(self):
store = Store()
ty = FuncType([], [ValType.i32(), ValType.i32()])
func = Func(store, ty, lambda: [1, 2])
self.assertEqual(func(store), [1, 2])
def test_errors(self):
store = Store()
ty = FuncType([], [])
with self.assertRaises(TypeError):
Func(1, ty, lambda: None) # type: ignore
with self.assertRaises(TypeError):
Func(store, 1, lambda: None) # type: ignore
func = Func(store, ty, lambda: None)
with self.assertRaises(WasmtimeError):
func(store, 2)
ty = FuncType([ValType.i32()], [])
func = Func(store, ty, lambda: None)
with self.assertRaises(TypeError):
func(store, 3.0)
with self.assertRaises(TypeError):
func(store, Val.i64(3))
ty = FuncType([ValType.i32()], [])
func = Func(store, ty, lambda x: x)
with self.assertRaises(WasmtimeError, msg="produced results"):
func(store, 1)
def test_produce_wrong(self):
store = Store()
ty = FuncType([], [ValType.i32(), ValType.i32()])
func = Func(store, ty, lambda: 1)
with self.assertRaises(TypeError, msg="has no len"):
func(store)
func = Func(store, ty, lambda: [1, 2, 3])
with self.assertRaises(WasmtimeError, msg="wrong number of results"):
func(store)
def test_host_exception(self):
store = Store()
ty = FuncType([], [])
def do_raise():
raise Exception("hello")
func = Func(store, ty, do_raise)
with self.assertRaises(Exception, msg="hello"):
func(store)
def test_type(self):
store = Store()
i32 = ValType.i32()
i64 = ValType.i64()
f32 = ValType.f32()
f64 = ValType.f64()
ty = FuncType([i32, i64, f32, f64], [f64, f32, i64, i32])
def rev(*args):
ret = list(args)
ret.reverse()
return ret
func = Func(store, ty, rev)
self.assertEqual(func(store, 1, 2, 3.0, 4.0), [4.0, 3.0, 2, 1])
def test_access_caller(self):
# Test that we get *something*
store = Store()
def runtest(caller):
self.assertEqual(caller.get(''), None)
self.assertEqual(caller.get('x'), None)
self.assertEqual(caller.get('y'), None)
Func(store, FuncType([], []), runtest, access_caller=True)(store)
hit = {}
# Test that `Caller` works and that it's invalidated
def runtest2(caller):
hit['yes'] = True
hit['caller'] = caller
self.assertTrue(caller.get('bar') is None)
mem = caller.get('foo')
self.assertTrue(isinstance(mem, Memory))
self.assertEqual(mem.data_ptr(caller)[0], ord('f'))
self.assertEqual(mem.data_ptr(caller)[1], ord('o'))
self.assertEqual(mem.data_ptr(caller)[2], ord('o'))
self.assertEqual(mem.data_ptr(caller)[3], 0)
module = Module(store.engine, """
(module
(import "" "" (func))
(memory (export "foo") 1)
(start 0)
(data (i32.const 0) "foo")
)
""")
func = Func(store, FuncType([], []), runtest2, access_caller=True)
Instance(store, module, [func])
self.assertTrue(hit['yes'])
self.assertTrue(hit['caller'].get('foo') is None) # type: ignore
# Test that `Caller` is invalidated even on exceptions
hit2 = {}
def runtest3(caller):
hit2['caller'] = caller
self.assertTrue(caller['foo'] is not None)
raise WasmtimeError('foo')
func = Func(store, FuncType([], []), runtest3, access_caller=True)
with self.assertRaises(WasmtimeError, msg='foo'):
Instance(store, module, [func])
self.assertTrue(hit2['caller'].get('foo') is None)
</document_content>
</document>
<document index="5">
<source>./test_global.py</source>
<document_content>
import unittest
from wasmtime import *
class TestGlobal(unittest.TestCase):
def test_new(self):
store = Store()
ty = GlobalType(ValType.i32(), True)
g = Global(store, ty, Val.i32(1))
Global(store, ty, Val.i32(1))
self.assertEqual(g.type(store).content, ValType.i32())
self.assertTrue(g.type(store).mutable)
self.assertEqual(g.value(store), 1)
g.set_value(store, Val.i32(2))
self.assertEqual(g.value(store), 2)
self.assertTrue(isinstance(g.type(store), GlobalType))
def test_falsy(self):
store = Store()
ty = GlobalType(ValType.i64(), True)
g = Global(store, ty, Val.i64(0))
val = g.value(store)
self.assertEqual(val, 0)
self.assertTrue(isinstance(val, int))
def test_errors(self):
store = Store()
ty = GlobalType(ValType.i32(), True)
with self.assertRaises(TypeError):
Global(store, ty, store)
with self.assertRaises(TypeError):
Global(store, 1, Val.i32(1)) # type: ignore
with self.assertRaises(AttributeError):
Global(1, ty, Val.i32(1)) # type: ignore
g = Global(store, ty, Val.i32(1))
with self.assertRaises(TypeError):
g.set_value(store, g)
ty = GlobalType(ValType.i32(), False)
g = Global(store, ty, Val.i32(1))
with self.assertRaises(WasmtimeError):
g.set_value(store, 1)
</document_content>
</document>
<document index="6">
<source>./test_instance.py</source>
<document_content>
import unittest
from wasmtime import *
class TestInstance(unittest.TestCase):
def test_smoke(self):
store = Store()
module = Module(store.engine, '(module)')
Instance(store, module, [])
def test_export_func(self):
store = Store()
module = Module(store.engine, '(module (func (export "")))')
instance = Instance(store, module, [])
self.assertEqual(len(instance.exports(store)), 1)
extern = instance.exports(store).by_index[0]
assert(isinstance(extern, Func))
assert(isinstance(extern.type(store), FuncType))
extern(store)
assert(instance.exports(store)[''] is not None)
with self.assertRaises(KeyError):
instance.exports(store)['x']
with self.assertRaises(IndexError):
instance.exports(store).by_index[100]
assert(instance.exports(store).get('x') is None)
def test_export_global(self):
store = Store()
module = Module(
store.engine, '(module (global (export "") i32 (i32.const 3)))')
instance = Instance(store, module, [])
self.assertEqual(len(instance.exports(store)), 1)
extern = instance.exports(store).by_index[0]
assert(isinstance(extern, Global))
self.assertEqual(extern.value(store), 3)
assert(isinstance(extern.type(store), GlobalType))
def test_export_memory(self):
store = Store()
module = Module(store.engine, '(module (memory (export "") 1))')
instance = Instance(store, module, [])
self.assertEqual(len(instance.exports(store)), 1)
extern = instance.exports(store).by_index[0]
assert(isinstance(extern, Memory))
self.assertEqual(extern.size(store), 1)
def test_export_table(self):
store = Store()
module = Module(store.engine, '(module (table (export "") 1 funcref))')
instance = Instance(store, module, [])
self.assertEqual(len(instance.exports(store)), 1)
extern = instance.exports(store).by_index[0]
assert(isinstance(extern, Table))
def test_multiple_exports(self):
store = Store()
module = Module(store.engine, """
(module
(func (export "a"))
(func (export "b"))
(global (export "c") i32 (i32.const 0))
)
""")
instance = Instance(store, module, [])
exports = instance.exports(store)
self.assertEqual(len(exports), 3)
assert isinstance(exports.by_index[0], Func)
assert isinstance(exports.by_index[1], Func)
assert isinstance(exports.by_index[2], Global)
# Test that exports acts like a normal map
assert "a" in exports
assert "b" in exports
assert "d" not in exports
assert set(exports) == {"a", "b", "c"}
assert set(exports.values()) == set(exports.by_index)
assert exports.get("d", 7) == 7
assert isinstance(exports.get("b", 7), Func)
def test_import_func(self):
store = Store()
module = Module(store.engine, """
(module
(import "" "" (func))
(start 0)
)
""")
hit = []
func = Func(store, FuncType([], []), lambda: hit.append(True))
Instance(store, module, [func])
assert(len(hit) == 1)
Instance(store, module, [func])
assert(len(hit) == 2)
def test_import_global(self):
store = Store()
module = Module(store.engine, """
(module
(import "" "" (global (mut i32)))
(func (export "") (result i32)
global.get 0)
(func (export "update")
i32.const 5
global.set 0)
)
""")
g = Global(store, GlobalType(ValType.i32(), True), 2)
instance = Instance(store, module, [g])
f = instance.exports(store).by_index[0]
assert(isinstance(f, Func))
self.assertEqual(f(store), 2)
g.set_value(store, 4)
self.assertEqual(f(store), 4)
instance2 = Instance(store, module, [g])
f2 = instance2.exports(store).by_index[0]
assert(isinstance(f2, Func))
self.assertEqual(f(store), 4)
self.assertEqual(f2(store), 4)
update = instance.exports(store).by_index[1]
assert(isinstance(update, Func))
update(store)
self.assertEqual(f(store), 5)
self.assertEqual(f2(store), 5)
def test_import_memory(self):
store = Store()
module = Module(store.engine, """
(module
(import "" "" (memory 1))
)
""")
m = Memory(store, MemoryType(Limits(1, None)))
Instance(store, module, [m])
def test_import_table(self):
store = Store()
module = Module(store.engine, """
(module
(table (export "") 1 funcref)
)
""")
table = Instance(store, module, []).exports(store).by_index[0]
module = Module(store.engine, """
(module
(import "" "" (table 1 funcref))
)
""")
Instance(store, module, [table])
def test_invalid(self):
store = Store()
with self.assertRaises(AttributeError):
Instance(store, 1, []) # type: ignore
with self.assertRaises(TypeError):
Instance(store, Module(store.engine, '(module (import "" "" (func)))'), [1]) # type: ignore
val = Func(store, FuncType([], []), lambda: None)
module = Module(store.engine, '(module (import "" "" (func)))')
Instance(store, module, [val])
with self.assertRaises(WasmtimeError):
Instance(store, module, [])
with self.assertRaises(WasmtimeError):
Instance(store, module, [val, val])
module = Module(store.engine, '(module (import "" "" (global i32)))')
with self.assertRaises(WasmtimeError):
Instance(store, module, [val])
def test_start_trap(self):
store = Store()
module = Module(store.engine, '(module (func unreachable) (start 0))')
with self.assertRaises(Trap):
Instance(store, module, [])
</document_content>
</document>
<document index="7">
<source>./test_linker.py</source>
<document_content>
import unittest
from wasmtime import *
class TestLinker(unittest.TestCase):
def test_define(self):
store = Store()
linker = Linker(store.engine)
linker.allow_shadowing = False
func = Func(store, FuncType([], []), lambda: None)
linker.define(store, "", "a", func)
g = Global(store, GlobalType(ValType.i32(), False), Val.i32(0))
linker.define(store, "", "c", g)
mem = Memory(store, MemoryType(Limits(1, None)))
linker.define(store, "", "e", mem)
module = Module(store.engine, """
(module (table (export "") 1 funcref))
""")
table = Instance(store, module, []).exports(store).by_index[0]
linker.define(store, "", "g", table)
with self.assertRaises(WasmtimeError):
linker.define(store, "", "a", func)
linker.allow_shadowing = True
linker.define(store, "", "a", func)
with self.assertRaises(TypeError):
linker.define(store, "", "", 2) # type: ignore
with self.assertRaises(AttributeError):
linker.define(store, 2, "", func) # type: ignore
with self.assertRaises(AttributeError):
linker.define(store, "", 2, func) # type: ignore
def test_define_instance(self):
store = Store()
linker = Linker(store.engine)
with self.assertRaises(TypeError):
linker.define_instance("x", 2) # type: ignore
module = Module(store.engine, "(module)")
linker.define_instance(store, "a", Instance(store, module, []))
module = Module(store.engine, "(module (func (export \"foo\")))")
instance = Instance(store, module, [])
linker.define_instance(store, "b", instance)
with self.assertRaises(WasmtimeError):
linker.define_instance(store, "b", instance)
linker.allow_shadowing = True
linker.define_instance(store, "b", instance)
def test_define_wasi(self):
linker = Linker(Engine())
linker.define_wasi()
def test_instantiate(self):
store = Store()
linker = Linker(store.engine)
module = Module(store.engine, "(module (func (export \"foo\")))")
instance = Instance(store, module, [])
linker.define_instance(store, "x", instance)
func = Func(store, FuncType([], []), lambda: None)
linker.define(store, "y", "z", func)
module = Module(store.engine, """
(module
(import "x" "foo" (func))
(import "y" "z" (func))
)
""")
linker.instantiate(store, module)
module = Module(store.engine, """
(module
(import "x" "foo" (func))
(import "y" "z" (global i32))
)
""")
with self.assertRaises(WasmtimeError):
linker.instantiate(store, module)
module = Module(store.engine, """
(module
(func unreachable)
(start 0)
)
""")
with self.assertRaises(Trap):
linker.instantiate(store, module)
module = Module(store.engine, "(module)")
linker.instantiate(store, module)
def test_errors(self):
linker = Linker(Engine())
with self.assertRaises(TypeError):
linker.allow_shadowing = 2
with self.assertRaises(AttributeError):
Linker(2) # type: ignore
with self.assertRaises(AttributeError):
linker.instantiate(Store(), 3) # type: ignore
def test_module(self):
store = Store()
linker = Linker(store.engine)
module = Module(store.engine, """
(module
(func (export "f"))
)
""")
linker.define_module(store, "foo", module)
module = Module(store.engine, """
(module
(import "foo" "f" (func))
)
""")
linker.instantiate(store, module)
def test_get_default(self):
store = Store()
linker = Linker(store.engine)
linker.get_default(store, "foo")(store)
def test_get_one_by_name(self):
store = Store()
linker = Linker(store.engine)
with self.assertRaises(WasmtimeError):
linker.get(store, "foo", "bar")
module = Module(store.engine, """
(module
(func (export "f"))
)
""")
linker.define_module(store, "foo", module)
assert(isinstance(linker.get(store, "foo", "f"), Func))
def test_define_func(self):
engine = Engine()
linker = Linker(engine)
called = {}
called['hits'] = 0
def call():
called['hits'] += 1
linker.define_func('a', 'b', FuncType([], []), call)
module = Module(engine, """
(module
(import "a" "b" (func))
(start 0)
)
""")
assert(called['hits'] == 0)
linker.instantiate(Store(engine), module)
assert(called['hits'] == 1)
linker.instantiate(Store(engine), module)
assert(called['hits'] == 2)
</document_content>
</document>
<document index="8">
<source>./test_memory.py</source>
<document_content>
import unittest
from wasmtime import *
class TestMemory(unittest.TestCase):
def test_new(self):
store = Store()
ty = MemoryType(Limits(1, None))
assert(not ty.is_64)
memory = Memory(store, ty)
self.assertEqual(memory.type(store).limits, Limits(1, None))
self.assertEqual(memory.size(store), 1)
self.assertTrue(memory.grow(store, 1))
self.assertEqual(memory.size(store), 2)
self.assertTrue(memory.grow(store, 0))
self.assertEqual(memory.size(store), 2)
with self.assertRaises(TypeError):
memory.grow(store, '') # type: ignore
with self.assertRaises(WasmtimeError):
memory.grow(store, -1)
self.assertEqual(memory.data_ptr(store)[0], 0)
self.assertEqual(memory.data_len(store), 65536 * 2)
self.assertTrue(isinstance(memory.type(store), MemoryType))
def test_grow(self):
store = Store()
ty = MemoryType(Limits(1, 2))
memory = Memory(store, ty)
assert(memory.grow(store, 1) == 1)
assert(memory.grow(store, 0) == 2)
with self.assertRaises(WasmtimeError):
memory.grow(store, 1)
def test_errors(self):
store = Store()
ty = MemoryType(Limits(1, 2))
with self.assertRaises(AttributeError):
Memory(1, ty) # type: ignore
with self.assertRaises(AttributeError):
Memory(store, 1) # type: ignore
def test_large(self):
ty = MemoryType(Limits(0x100000000, None), is_64=True)
assert(ty.limits.min == 0x100000000)
assert(ty.limits.max is None)
assert(ty.is_64)
ty = MemoryType(Limits(0x100000000, 0x100000000), is_64=True)
assert(ty.limits.min == 0x100000000)
assert(ty.limits.max == 0x100000000)
with self.assertRaises(WasmtimeError):
MemoryType(Limits(0x100000000, None))
with self.assertRaises(WasmtimeError):
MemoryType(Limits(1, 0x100000000))
def test_slices(self):
store = Store()
ty = MemoryType(Limits(1, None))
memory = Memory(store, ty)
memory.grow(store, 2)
data_ptr = memory.data_ptr(store)
ba = bytearray([i for i in range(200)])
size_bytes = memory.data_len(store)
# happy cases
offset = 2048
ba_size = len(ba)
# write with start and ommit stop
memory.write(store, ba, offset)
# check write success byte by byte, whole is asserted with read
self.assertEqual(data_ptr[offset], 0)
self.assertEqual(data_ptr[offset + 1], 1)
self.assertEqual(data_ptr[offset + 199], 199)
# read while and assert whole area
out = memory.read(store, offset, offset + ba_size)
self.assertEqual(ba, out)
self.assertEqual(len(memory.read(store, -10)), 10)
# write with start and stop
memory.write(store, ba, offset + ba_size)
out = memory.read(store, offset + ba_size, offset + ba_size + ba_size)
self.assertEqual(ba, out)
# assert old
self.assertEqual(data_ptr[offset], 0)
self.assertEqual(data_ptr[offset + 1], 1)
self.assertEqual(data_ptr[offset + 199], 199)
# assert new
self.assertEqual(data_ptr[offset + ba_size], 0)
self.assertEqual(data_ptr[offset + ba_size + 1], 1)
self.assertEqual(data_ptr[offset + ba_size + 199], 199)
# edge cases
# empty slices
self.assertEqual(len(memory.read(store, 0, 0)), 0)
self.assertEqual(len(memory.read(store, offset, offset)), 0)
self.assertEqual(len(memory.read(store, offset, offset - 1)), 0)
# out of bound access returns empty array similar to list slice
self.assertEqual(len(memory.read(store, size_bytes + 1)), 0)
# write empty
self.assertEqual(memory.write(store, bytearray(0), offset), 0)
self.assertEqual(memory.write(store, bytearray(b""), offset), 0)
with self.assertRaises(IndexError):
memory.write(store, ba, size_bytes)
with self.assertRaises(IndexError):
memory.write(store, ba, size_bytes - ba_size + 1)
self.assertEqual(memory.write(store, ba, -ba_size), ba_size)
out = memory.read(store, -ba_size)
self.assertEqual(ba, out)
</document_content>
</document>
<document index="9">
<source>./test_module.py</source>
<document_content>
import unittest
import tempfile
from wasmtime import *
class TestModule(unittest.TestCase):
def test_smoke(self):
Module(Engine(), '(module)')
Module(Engine(), bytes(b'\0asm\x01\0\0\0'))
Module(Engine(), bytearray(b'\0asm\x01\0\0\0'))
def test_invalid(self):
with self.assertRaises(AttributeError):
Module.validate(1, b'') # type: ignore
with self.assertRaises(TypeError):
Module.validate(Store(), 2) # type: ignore
with self.assertRaises(TypeError):
Module(1, b'') # type: ignore
with self.assertRaises(TypeError):
Module(Engine(), 2) # type: ignore
with self.assertRaises(WasmtimeError):
Module(Engine(), b'')
with self.assertRaises(WasmtimeError):
Module(Engine(), b'\x00')
def test_validate(self):
engine = Engine()
Module.validate(engine, b'\0asm\x01\0\0\0')
with self.assertRaises(WasmtimeError):
Module.validate(engine, b'')
def test_imports(self):
store = Store()
module = Module(store.engine, '(module)')
self.assertEqual(module.imports, [])
module = Module(store.engine, """
(module
(import "" "" (func))
(import "a" "bcd" (global i32))
(import "" "" (memory 1))
(import "" "x" (table 1 funcref))
)
""")
imports = module.imports
self.assertEqual(len(imports), 4)
self.assertEqual(imports[0].module, "")
self.assertEqual(imports[0].name, "")
ty = imports[0].type
assert(isinstance(ty, FuncType))
self.assertEqual(ty.params, [])
self.assertEqual(ty.results, [])
self.assertEqual(imports[1].module, "a")
self.assertEqual(imports[1].name, "bcd")
ty = imports[1].type
assert(isinstance(ty, GlobalType))
self.assertEqual(ty.content, ValType.i32())
self.assertFalse(ty.mutable)
self.assertEqual(imports[2].module, "")
self.assertEqual(imports[2].name, "")
ty = imports[2].type
assert(isinstance(ty, MemoryType))
self.assertEqual(ty.limits, Limits(1, None))
self.assertEqual(imports[3].module, "")
self.assertEqual(imports[3].name, "x")
ty = imports[3].type
assert(isinstance(ty, TableType))
self.assertEqual(ty.limits, Limits(1, None))
self.assertEqual(ty.element, ValType.funcref())
def test_exports(self):
store = Store()
module = Module(store.engine, '(module)')
self.assertEqual(module.exports, [])
module = Module(store.engine, """
(module
(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)
)
""")
exports = module.exports
self.assertEqual(len(exports), 4)
self.assertEqual(exports[0].name, "a")
ty = exports[0].type
assert(isinstance(ty, FuncType))
self.assertEqual(ty.params, [ValType.i32(), ValType.f32()])
self.assertEqual(ty.results, [ValType.f64()])
self.assertEqual(exports[1].name, "")
ty = exports[1].type
assert(isinstance(ty, GlobalType))
self.assertEqual(ty.content, ValType.i32())
self.assertTrue(ty.mutable)
self.assertEqual(exports[2].name, "mem")
ty = exports[2].type
assert(isinstance(ty, MemoryType))
self.assertEqual(ty.limits, Limits(1, None))
self.assertEqual(exports[3].name, "table")
ty = exports[3].type
assert(isinstance(ty, TableType))
self.assertEqual(ty.limits, Limits(1, None))
self.assertEqual(ty.element, ValType.funcref())
def test_serialize(self):
engine = Engine()
module = Module(engine, '(module)')
encoded = module.serialize()
module = Module.deserialize(engine, encoded)
assert(len(module.imports) == 0)
assert(len(module.exports) == 0)
with tempfile.TemporaryDirectory() as d:
path = d + '/module.bin'
with open(path, 'wb') as f:
f.write(encoded)
module = Module.deserialize_file(engine, path)
assert(len(module.imports) == 0)
assert(len(module.exports) == 0)
# Run the destructor for `Module` which has an mmap to the file
# which prevents deletion on Windows.
del module
</document_content>
</document>
<document index="10">
<source>./test_refs.py</source>
<document_content>
import unittest
from typing import cast
from wasmtime import *
def ref_types_store():
config = Config()
config.wasm_reference_types = True
engine = Engine(config)
return Store(engine)
def compile_and_instantiate(wat):
store = ref_types_store()
module = Module(store.engine, wat)
return (Instance(store, module, []), store)
class SetHitOnDrop:
def __init__(self, obj):
obj['hit'] = False
self.obj = obj
def __del__(self):
self.obj['hit'] = True
class TestExternRef(unittest.TestCase):
def test_smoke(self):
(instance, store) = compile_and_instantiate(
"""
(module
(func (export "f") (param externref) (result externref)
local.get 0
)
(func (export "null_externref") (result externref)
ref.null extern
)
)
"""
)
null_externref = instance.exports(store).get("null_externref")
self.assertEqual(null_externref(store), None)
f = instance.exports(store).get("f")
externs = [42, True, False, None, "Hello", {"x": 1}, [12, 13, 14], Config()]
for extern in externs:
# We can create an externref for the given extern data.
ref = Val.externref(extern)
# And the externref's value is our extern data.
self.assertEqual(ref.value, extern)
# And we can round trip the externref through Wasm and still get our
# extern data.
result = f(store, ref)
self.assertEqual(result, extern)
def test_int_to_externref(self):
wat = """
(module
(import "env" "int_to_ref" (func $int_to_ref (param $a externref) (result externref)))
(export "test" (func $int_to_ref))
)
"""
config = Config()
config.wasm_reference_types = True
engine = Engine(config)
store = Store(engine)
module = Module(store.engine, wat)
linker = Linker(engine)
ftype = FuncType([ValType.externref()], [ValType.externref()])
linker.define_func("env", "int_to_ref", ftype, lambda x: x)
instance = linker.instantiate(store, module)
f: Func
f = cast(Func, instance.exports(store).get("test"))
f(store, 5)
f = cast(Func, instance.exports(store).get("test"))
f(store, 5.7)
def test_externref_tables(self):
store = ref_types_store()
ty = TableType(ValType.externref(), Limits(10, None))
table = Table(store, ty, "init")
for i in range(0, 10):
self.assertEqual(table.get(store, i), "init")
table.grow(store, 2, "grown")
for i in range(0, 10):
self.assertEqual(table.get(store, i), "init")
for i in range(10, 12):
self.assertEqual(table.get(store, i), "grown")
table.set(store, 7, "lucky")
for i in range(0, 7):
self.assertEqual(table.get(store, i), "init")
self.assertEqual(table.get(store, 7), "lucky")
for i in range(8, 10):
self.assertEqual(table.get(store, i), "init")
for i in range(10, 12):
self.assertEqual(table.get(store, i), "grown")
def test_externref_in_global(self):
store = ref_types_store()
ty = GlobalType(ValType.externref(), True)
g = Global(store, ty, Val.externref("hello"))
self.assertEqual(g.value(store), "hello")
g.set_value(store, "goodbye")
self.assertEqual(g.value(store), "goodbye")
def test_dtor_global(self):
obj = {} # type: ignore
store = ref_types_store()
ty = GlobalType(ValType.externref(), True)
g = Global(store, ty, Val.externref(SetHitOnDrop(obj)))
assert(not obj['hit'])
g.set_value(store, None)
assert(obj['hit'])
def test_dtor_func(self):
(instance, store) = compile_and_instantiate(
"""
(module
(func (export "f") (param externref))
)
"""
)
f = instance.exports(store).get("f")
obj = {} # type: ignore
f(store, SetHitOnDrop(obj))
store.gc()
assert(obj['hit'])
class TestFuncRef(unittest.TestCase):
def test_smoke(self):
(instance, store) = compile_and_instantiate(
"""
(module
(func (export \"f\") (param funcref) (result funcref)
local.get 0
)
(func (export "null_funcref") (result funcref)
ref.null func
)
)
"""
)
null_funcref = instance.exports(store).get("null_funcref")
self.assertEqual(null_funcref(store), None)
f = instance.exports(store).get("f")
ty = FuncType([], [ValType.i32()])
g = Func(store, ty, lambda: 42)
# We can create a funcref.
ref_g_val = Val.funcref(g)
# And the funcref's points to `g`.
g2 = ref_g_val.as_funcref()
if isinstance(g2, Func):
self.assertEqual(g2(store), 42)
else:
self.fail("g2 is not a funcref: g2 = %r" % g2)
# And we can round trip the funcref through Wasm.
g3 = f(store, ref_g_val)
if isinstance(g3, Func):
self.assertEqual(g3(store), 42)
else:
self.fail("g3 is not a funcref: g3 = %r" % g3)
</document_content>
</document>
<document index="11">
<source>./test_store.py</source>
<document_content>
import unittest
from wasmtime import *
class TestStore(unittest.TestCase):
def test_smoke(self):
Store()
Store(Engine())
with Store() as store:
pass
store = Store()
store.close()
store.close()
with self.assertRaises(ValueError):
store.set_epoch_deadline(1)
def test_errors(self):
with self.assertRaises(TypeError):
Store(3) # type: ignore
def test_interrupt_handle(self):
config = Config()
config.epoch_interruption = True
engine = Engine(config)
engine.increment_epoch()
store = Store(engine)
store.set_epoch_deadline(1)
def test_interrupt_wasm(self):
config = Config()
config.epoch_interruption = True
engine = Engine(config)
store = Store(engine)
store.set_epoch_deadline(1)
module = Module(store.engine, """
(import "" "hit" (func $hit))
(import "" "interrupt" (func $interrupt))
(func $start
call $hit
call $interrupt
(loop br 0))
(start $start)
""")
interrupt = Func(store, FuncType([], []), lambda: engine.increment_epoch())
was_hit = False
def hit_callback():
nonlocal was_hit
was_hit = True
hit = Func(store, FuncType([], []), hit_callback)
with self.assertRaises(Trap):
Instance(store, module, [hit, interrupt])
self.assertTrue(was_hit)
def test_fuel(self):
store = Store()
with self.assertRaises(WasmtimeError):
store.set_fuel(1)
with self.assertRaises(WasmtimeError):
store.get_fuel()
config = Config()
config.consume_fuel = True
store = Store(Engine(config))
store.set_fuel(1)
assert(store.get_fuel() == 1)
store.set_fuel(2)
assert(store.get_fuel() == 2)
store.set_fuel(0)
assert(store.get_fuel() == 0)
def test_limits(self):
store = Store()
Memory(store, MemoryType(Limits(1, None)))
store = Store()
store.set_limits(memory_size=0)
with self.assertRaises(WasmtimeError):
Memory(store, MemoryType(Limits(1, None)))
store.set_limits(memory_size=100000)
Memory(store, MemoryType(Limits(1, None)))
store = Store()
store.set_limits(table_elements=1)
Table(store, TableType(ValType.funcref(), Limits(1, None)), None)
with self.assertRaises(WasmtimeError):
Table(store, TableType(ValType.funcref(), Limits(2, None)), None)
store = Store()
store.set_limits(memory_size=200000)
mem = Memory(store, MemoryType(Limits(1, None)))
mem.grow(store, 1)
with self.assertRaises(WasmtimeError):
mem.grow(store, 100)
</document_content>
</document>
<document index="12">
<source>./test_table.py</source>
<document_content>
import unittest
from wasmtime import *
class TestTable(unittest.TestCase):
def test_new(self):
store = Store()
module = Module(store.engine, """
(module (table (export "") 1 funcref))
""")
table = Instance(store, module, []).exports(store).by_index[0]
assert(isinstance(table, Table))
assert(isinstance(table.type(store), TableType))
self.assertEqual(table.type(store).limits, Limits(1, None))
self.assertEqual(table.size(store), 1)
ty = TableType(ValType.funcref(), Limits(1, 2))
store = Store()
func = Func(store, FuncType([], []), lambda: {})
Table(store, ty, func)
def test_grow(self):
ty = TableType(ValType.funcref(), Limits(1, 2))
store = Store()
table = Table(store, ty, None)
self.assertEqual(table.size(store), 1)
# type errors
with self.assertRaises(TypeError):
table.grow(store, 'x', None) # type: ignore
with self.assertRaises(TypeError):
table.grow(store, 2, 'x')
# growth works
table.grow(store, 1, None)
self.assertEqual(table.size(store), 2)
# can't grow beyond max
with self.assertRaises(WasmtimeError):
table.grow(store, 1, None)
def test_get(self):
ty = TableType(ValType.funcref(), Limits(1, 2))
store = Store()
table = Table(store, ty, None)
self.assertEqual(table.get(store, 0), None)
self.assertEqual(table.get(store, 1), None)
called = {}
called['hit'] = False
def set_called():
called['hit'] = True
func = Func(store, FuncType([], []), set_called)
table.grow(store, 1, func)
assert(not called['hit'])
f = table.get(store, 1)
assert(isinstance(f, Func))
f(store)
assert(called['hit'])
def test_set(self):
ty = TableType(ValType.funcref(), Limits(1, 2))
store = Store()
table = Table(store, ty, None)
func = Func(store, FuncType([], []), lambda: {})
table.set(store, 0, func)
with self.assertRaises(WasmtimeError):
table.set(store, 1, func)
</document_content>
</document>
<document index="13">
<source>./test_trap.py</source>
<document_content>
import unittest
from wasmtime import *
class TestTrap(unittest.TestCase):
def test_new(self):
trap = Trap('x')
self.assertEqual(trap.message, u'x')
def test_frames(self):
store = Store()
module = Module(store.engine, """
(module $module
(func (export "init")
call $foo)
(func $foo
call $bar)
(func $bar
unreachable)
)
""")
i = Instance(store, module, [])
with self.assertRaises(Trap) as exn:
e = i.exports(store).by_index[0]
assert(isinstance(e, Func))
e(store)
trap = exn.exception
frames = trap.frames
self.assertEqual(len(frames), 3)
self.assertEqual(frames[0].func_index, 2)
self.assertEqual(frames[1].func_index, 1)
self.assertEqual(frames[2].func_index, 0)
self.assertEqual(frames[0].func_name, 'bar')
self.assertEqual(frames[1].func_name, 'foo')
self.assertEqual(frames[2].func_name, None)
self.assertEqual(frames[0].module_name, 'module')
self.assertEqual(frames[1].module_name, 'module')
self.assertEqual(frames[2].module_name, 'module')
self.assertEqual(str(trap), """\
error while executing at wasm backtrace:
0: 0x2d - module!bar
1: 0x28 - module!foo
2: 0x23 - module!<wasm function 0>
Caused by:
wasm trap: wasm `unreachable` instruction executed\
""")
self.assertEqual(trap.trap_code, TrapCode.UNREACHABLE)
def test_frames_no_module(self):
store = Store()
module = Module(store.engine, """
(module
(func (export "init") unreachable)
)
""")
i = Instance(store, module, [])
with self.assertRaises(Trap) as exn:
e = i.exports(store).by_index[0]
assert(isinstance(e, Func))
e(store)
trap = exn.exception
frames = trap.frames
self.assertEqual(len(frames), 1)
self.assertEqual(frames[0].func_index, 0)
self.assertEqual(frames[0].func_name, None)
self.assertEqual(frames[0].module_name, None)
def test_wasi_exit(self):
linker = Linker(Engine())
linker.define_wasi()
module = Module(linker.engine, """
(module
(import "wasi_snapshot_preview1" "proc_exit" (func $exit (param i32)))
(memory (export "memory") 1)
(func (export "exit") (param i32)
local.get 0
call $exit)
)
""")
store = Store(linker.engine)
store.set_wasi(WasiConfig())
instance = linker.instantiate(store, module)
exit = instance.exports(store)["exit"]
assert(isinstance(exit, Func))
with self.assertRaises(ExitTrap) as exn:
exit(store, 0)
self.assertEqual(exn.exception.code, 0)
self.assertRegex(str(exn.exception), 'Exited with i32 exit status 0')
with self.assertRaises(ExitTrap) as exn:
exit(store, 1)
self.assertEqual(exn.exception.code, 1)
</document_content>
</document>
<document index="14">
<source>./test_types.py</source>
<document_content>
import unittest
from wasmtime import FuncType, ValType
class TestTypes(unittest.TestCase):
def test_valtypes(self):
ValType.i32()
ValType.i64()
ValType.f32()
ValType.f64()
def test_new(self):
FuncType([], [])
FuncType([ValType.i32()], [ValType.i64()])
</document_content>
</document>
<document index="15">
<source>./test_value.py</source>
<document_content>
import unittest
from wasmtime import *
class TestValue(unittest.TestCase):
def test_i32(self):
with self.assertRaises(TypeError):
Val.i32('') # type: ignore
with self.assertRaises(TypeError):
Val.i32(1.2) # type: ignore
i = Val.i32(1)
self.assertEqual(i.as_i32(), 1)
i = Val.i32(0xffffffff)
self.assertEqual(i.as_i32(), -1)
i = Val.i32(0x800000000)
self.assertEqual(i.as_i32(), 0)
self.assertEqual(None, i.as_i64())
self.assertEqual(None, i.as_f32())
self.assertEqual(None, i.as_f64())
self.assertEqual(i.type, ValType.i32())
def test_i64(self):
with self.assertRaises(TypeError):
Val.i64('') # type: ignore
with self.assertRaises(TypeError):
Val.i64(1.2) # type: ignore
i = Val.i64(1)
self.assertEqual(i.as_i64(), 1)
i = Val.i64(0xffffffff)
self.assertEqual(i.as_i64(), 0xffffffff)
i = Val.i64(0x800000000)
self.assertEqual(i.as_i64(), 0x800000000)
i = Val.i64(0xffffffffffffffff)
self.assertEqual(i.as_i64(), -1)
i = Val.i64(0x80000000000000000)
self.assertEqual(i.as_i64(), 0)
self.assertEqual(None, i.as_i32())
self.assertEqual(None, i.as_f32())
self.assertEqual(None, i.as_f64())
self.assertEqual(i.type, ValType.i64())
def test_f32(self):
with self.assertRaises(TypeError):
Val.f32('') # type: ignore
with self.assertRaises(TypeError):
Val.f32(1)
i = Val.f32(1.0)
self.assertEqual(i.as_f32(), 1.0)
self.assertEqual(None, i.as_i64())
self.assertEqual(None, i.as_i32())
self.assertEqual(None, i.as_f64())
self.assertEqual(i.type, ValType.f32())
def test_f64(self):
with self.assertRaises(TypeError):
Val.f64('') # type: ignore
with self.assertRaises(TypeError):
Val.f64(1)
i = Val.f64(1.0)
self.assertEqual(i.as_f64(), 1.0)
self.assertEqual(None, i.as_i32())
self.assertEqual(None, i.as_i64())
self.assertEqual(None, i.as_f32())
self.assertEqual(i.type, ValType.f64())
</document_content>
</document>
<document index="16">
<source>./test_wasi.py</source>
<document_content>
import unittest
import tempfile
from wasmtime import *
from pathlib import Path
class TestWasi(unittest.TestCase):
def test_config(self):
config = WasiConfig()
config.argv = ['a', 'b']
config.inherit_argv()
config.env = [['a', 'b']]
config.inherit_env()
with tempfile.NamedTemporaryFile() as f:
config.stdin_file = f.name
config.stdin_file = Path(f.name)
config.inherit_stdin()
config.stdout_file = f.name
config.stdout_file = Path(f.name)
config.inherit_stdout()
config.stderr_file = f.name
config.stderr_file = Path(f.name)
config.inherit_stderr()
with self.assertRaises(WasmtimeError):
config.stdin_file = 'somewhere-over-the-rainboat'
with self.assertRaises(WasmtimeError):
config.stdout_file = 'some-directory/without-a-rainbow'
with self.assertRaises(WasmtimeError):
config.stderr_file = 'some-directory/without-a-rainbow'
config.preopen_dir('wasmtime', 'other')
def test_preview1(self):
linker = Linker(Engine())
linker.define_wasi()
module = Module(linker.engine, """
(module
(import "wasi_snapshot_preview1" "random_get"
(func (param i32 i32) (result i32)))
)
""")
store = Store(linker.engine)
store.set_wasi(WasiConfig())
linker.instantiate(store, module)
def preopen_nonexistent(self):
config = WasiConfig()
with self.assertRaises(WasmtimeError):
config.preopen_dir('/path/to/nowhere', '/')
</document_content>
</document>
<document index="17">
<source>./test_wat2wasm.py</source>
<document_content>
import unittest
from wasmtime import *
class TestWat2Wasm(unittest.TestCase):
def test_wat2wasm(self):
wasm = wat2wasm('(module)')
self.assertEqual(wasm, b'\0asm\x01\0\0\0')
def test_errors(self):
with self.assertRaises(WasmtimeError):
wat2wasm('x')
</document_content>
</document>
<document index="18">
<source>./codegen/__init__.py</source>
<document_content>
# The `codegen` directory here is intended to test the bindings generator for
# components in Python. Each file represents a distinct test where an input
# wasm file is bound and then the generated bindings are imported dynamically.
#
# This structure is done so a general `pytest` will execute everything,
# generating bindings during test collection and otherwise setting up everything
# to be naturally checked with mypy and other tests configured.
from wasmtime import wat2wasm
from wasmtime.bindgen import generate
from pathlib import Path
import os
# Helper function to generate bindings for the `wat` specified into the
# `generated` sub-folder. After calling this method the bindings can be
# imported with:
#
# from .generated.name import Name
#
# and then used to type-check everything.
def bindgen(name: str, wat: str) -> None:
files = generate(name, wat2wasm(wat))
root = Path(__file__).parent.joinpath('generated')
dst = root.joinpath(name)
for name, contents in files.items():
# If the file already has the desired contents then skip writing. This
# is an attempt to fix CI issues on windows.
file = dst.joinpath(name)
if file.exists():
with open(file, 'rb') as f:
if f.read() == contents:
continue
# Write the contents to a temporary file and then attempt to atomically
# replace the previous file, if any, with the new contents. This
# is done to hopefully fix an apparent issue in `pytest` where it seems
# that there are multiple threads of the python interpreter, perhaps for
# pytest itself, mypy, and flake8, and overwriting files in-place causes
# issues are partial files may be seen.
tmp_file = file.with_suffix('.tmp')
if not file.parent.exists():
file.parent.mkdir(parents=True)
tmp_file.write_bytes(contents)
os.replace(tmp_file, file)
REALLOC = """
(global $last (mut i32) (i32.const 1000))
(func $realloc (export "realloc")
(param $old_ptr i32)
(param $old_size i32)
(param $align i32)
(param $new_size i32)
(result i32)
(local $ret i32)
;; Test if the old pointer is non-null
local.get $old_ptr
if
;; If the old size is bigger than the new size then
;; this is a shrink and transparently allow it
local.get $old_size
local.get $new_size
i32.gt_u
if
local.get $old_ptr
return
end
;; otherwise fall through to allocate a new chunk which will later
;; copy data over
end
;; align up `$last`
(global.set $last
(i32.and
(i32.add
(global.get $last)
(i32.add
(local.get $align)
(i32.const -1)))
(i32.xor
(i32.add
(local.get $align)
(i32.const -1))
(i32.const -1))))
;; save the current value of `$last` as the return value
global.get $last
local.set $ret
;; bump our pointer
(global.set $last
(i32.add
(global.get $last)
(local.get $new_size)))
;; while `memory.size` is less than `$last`, grow memory
;; by one page
(loop $loop
(if
(i32.lt_u
(i32.mul (memory.size) (i32.const 65536))
(global.get $last))
(then
i32.const 1
memory.grow
;; test to make sure growth succeeded
i32.const -1
i32.eq
if unreachable end
br $loop)))
;; ensure anything necessary is set to valid data by spraying a bit
;; pattern that is invalid
local.get $ret
i32.const 0xde
local.get $new_size
memory.fill
;; If the old pointer is present then that means this was a reallocation
;; of an existing chunk which means the existing data must be copied.
local.get $old_ptr
if
local.get $ret ;; destination
local.get $old_ptr ;; source
local.get $old_size ;; size
memory.copy
end
local.get $ret
)
"""
</document_content>
</document>
<document index="19">
<source>./codegen/test_bare_funcs.py</source>
<document_content>
from . import bindgen
from wasmtime import Store
module = """
(component
(import "foo-import" (func $foo-import (param "a" s32) (result s32)))
(core func $foo-import-lowered (canon lower (func $foo-import)))
(core module $m
(import "" "foo" (func $foo (param i32) (result i32)))
(func (export "foo") (param i32) (result i32)
(call $foo (local.get 0))
)
)
(core instance $i (instantiate $m
(with "" (instance
(export "foo" (func $foo-import-lowered))
))
))
(func $foo-export-lifted (param "a" s32) (result s32) (canon lift (core func $i "foo")))
(export "foo-export" (func $foo-export-lifted))
)
"""
bindgen('bare_funcs', module)
from .generated.bare_funcs import Root, RootImports, imports
class Host(imports.Host):
def foo_import(self, a):
return a + 1
def test_bindings():
store = Store()
bindings = Root(store, RootImports(host=Host()))
assert 101 == bindings.foo_export(store, 100)
</document_content>
</document>
<document index="20">
<source>./codegen/test_empty.py</source>
<document_content>
from . import bindgen
from wasmtime import Store
module = """
(component)
"""
bindgen('empty', module)
from .generated.empty import Root
def test_bindings(tmp_path):
Root(Store())
</document_content>
</document>
<document index="21">
<source>./codegen/test_empty_import.py</source>
<document_content>
from . import bindgen
from wasmtime import Store
module = """
(component
(import "host" (instance))
)
"""
bindgen('empty_import', module)
from .generated.empty_import import Root
from .generated.empty_import.imports import RootImports
def test_bindings(tmp_path) -> None:
Root(Store(), RootImports(host={}))
</document_content>
</document>
<document index="22">
<source>./codegen/test_export_resources.py</source>
<document_content>
from . import bindgen
from wasmtime import Store
module = """
(component
(core module $core-mod
(import "[export]component:basicresource/my-interface-name" "[resource-drop]demo-resource-class" (func $resource-drop (param i32)))
(import "[export]component:basicresource/my-interface-name" "[resource-new]demo-resource-class" (func $resource-new (param i32) (result i32)))
(import "[export]component:basicresource/my-interface-name" "[resource-rep]demo-resource-class" (func $resource-rep (param i32) (result i32)))
(func $core-create-demo-resource (param i32 i32) (result i32)
unreachable
)
(func $core-demo-resource-greet (param i32 i32 i32) (result i32)
unreachable
)
(func $core-cabi-realloc (param i32 i32 i32 i32) (result i32)
unreachable
)
(memory (;0;) 0)
(export "component:basicresource/my-interface-name#[constructor]demo-resource-class" (func $core-create-demo-resource))
(export "component:basicresource/my-interface-name#[method]demo-resource-class.greet" (func $core-demo-resource-greet))
(export "memory" (memory 0))
(export "cabi_realloc" (func $core-cabi-realloc))
)
(type $demo-resource-type (resource (rep i32)))
(core func $core-resource-drop (canon resource.drop $demo-resource-type))
(core func $core-resource-rep (canon resource.rep $demo-resource-type))
(core func $core-resource-new (canon resource.new $demo-resource-type))
(core instance $canon-instance
(export "[resource-drop]demo-resource-class" (func $core-resource-drop))
(export "[resource-new]demo-resource-class" (func $core-resource-new))
(export "[resource-rep]demo-resource-class" (func $core-resource-rep))
)
(core instance $core-instance (instantiate $core-mod
(with "[export]component:basicresource/my-interface-name" (instance $canon-instance))
)
)
(alias core export $core-instance "memory" (core memory (;0;)))
(alias core export $core-instance "cabi_realloc" (core func $cabi-realloc))
(type $constructor-type (func (param "name" string) (result (own $demo-resource-type))))
(alias core export $core-instance "component:basicresource/my-interface-name#[constructor]demo-resource-class" (core func $core-constructor))
(func $lift-demo-resource-constructor (type $constructor-type) (canon lift (core func $core-constructor) (memory 0) (realloc $cabi-realloc) string-encoding=utf8))
(type $greet-type (func (param "self" (borrow $demo-resource-type)) (param "greeting" string) (result string)))
(alias core export $core-instance "component:basicresource/my-interface-name#[method]demo-resource-class.greet" (core func $core-greet))
(func $lift-demo-resource-greet (type $greet-type) (canon lift (core func $core-greet) (memory 0) (realloc $cabi-realloc) string-encoding=utf8))
(component $comp-api
(import "import-type-demo-resource-class" (type $demo-resource (sub resource)))
(type $constructor-type (func (param "name" string) (result (own $demo-resource))))
(import "import-constructor-demo-resource-class" (func $constructor-import (type $constructor-type)))
(type $greet-type (func (param "self" (borrow $demo-resource)) (param "greeting" string) (result string)))
(import "import-method-demo-resource-class-greet" (func $greet-import (type $greet-type)))
(export $demo-resource-export "demo-resource-class" (type $demo-resource))
(type $constructor-type-export (func (param "name" string) (result (own $demo-resource-export))))
(export "[constructor]demo-resource-class" (func $constructor-import) (func (type $constructor-type-export)))
(type $greet-type-export (func (param "self" (borrow $demo-resource-export)) (param "greeting" string) (result string)))
(export "[method]demo-resource-class.greet" (func $greet-import) (func (type $greet-type-export)))
)
(instance $api-instance (instantiate $comp-api
(with "import-constructor-demo-resource-class" (func $lift-demo-resource-constructor))
(with "import-method-demo-resource-class-greet" (func $lift-demo-resource-greet))
(with "import-type-demo-resource-class" (type $demo-resource-type))
)
)
(export "component:basicresource/my-interface-name" (instance $api-instance))
)
"""
bindgen("export_resources", module)
from .generated.export_resources import Root
from .generated.export_resources import my_interface_name
def test_bindings():
store = Store()
root = Root(store)
interface = root.my_interface_name()
# We can't test round tripping until support for resource imports
# is added. For now, we can check that the structure of the
# generated code looks right.
assert hasattr(interface, "DemoResourceClass")
assert hasattr(my_interface_name, "DemoResourceClass")
resource_cls = my_interface_name.DemoResourceClass
assert resource_cls.greet.__annotations__ == {
"caller": Store,
"greeting": str,
"return": str,
}
</document_content>
</document>
<document index="23">
<source>./codegen/test_external_types.py</source>
<document_content>
from . import bindgen, REALLOC
from wasmtime import Store
module = """
(component $OuterComp
(type $types
(instance
(type $runtime-value (variant
(case "id" string) (case "id2" string)))
(export $runtime-value-export "runtime-value"
(type (eq $runtime-value)))
)
)
(import "types" (instance $types (type $types)))
(alias export $types "runtime-value" (type $runtime-value-export))
(import "host" (instance $inst
(alias outer $OuterComp 1 (type $runtime-value))
(export $export "runtime-value" (type (eq $runtime-value)))
(export "some-fn" (func (param "v" $export) (result $export)))
))
(core module $libc
(memory (export "mem") 1)
{}
)
(core instance $libc (instantiate $libc))
(core module $mod
(import "libc" "mem" (memory 1))
(import "" "lowered-fn-import"
(func $lowered-fn (param i32 i32 i32 i32)))
(func (export "core-fn") (param i32 i32 i32) (result i32)
(call $lowered-fn
(local.get 0) (local.get 1) (local.get 2) (local.get 2))
(local.get 2))
)
(core func $lowered-fn
(canon lower (func $inst "some-fn") (memory $libc "mem")
(realloc (func $libc "realloc"))))
(core instance $inst
(instantiate $mod
(with "libc" (instance $libc))
(with "" (instance
(export "lowered-fn-import" (func $lowered-fn))
))
)
)
(type $runtime-value (variant (case "id" string) (case "id2" string)))
(func $lifted-core-fn (param "a" $runtime-value) (result $runtime-value)
(canon lift (core func $inst "core-fn") (memory $libc "mem")
(realloc (func $libc "realloc"))))
(instance (export "e")
(export "runtime-value" (type $runtime-value))
(export "some-fn" (func $lifted-core-fn))
)
)
""".format(REALLOC)
bindgen('external_types', module)
from .generated.external_types import Root, RootImports, imports
from .generated.external_types.imports import host
from .generated.external_types import e
class Host(imports.HostHost):
def some_fn(self, v: host.RuntimeValue) -> host.RuntimeValue:
return v
def test_bindings(tmp_path):
store = Store()
wasm = Root(store, RootImports(None, host=Host()))
exports = wasm.e()
rt_id = exports.some_fn(store, e.RuntimeValueId('1234'))
assert rt_id == e.RuntimeValueId('1234')
</document_content>
</document>
<document index="24">
<source>./codegen/test_keywords.py</source>
<document_content>
from . import bindgen
from wasmtime import Store
module = """
(component
(import "false" (instance $i
(type $c1 (variant (case "break" s32) (case "class" s64) (case "true" s64)))
(export $c1' "none" (type (eq $c1)))
(export "as" (func (param "import" $c1') (result s64)))
(type $r1 (record (field "else" u8) (field "not" u8) (field "except" u8)))
(export $r1' "true" (type (eq $r1)))
(export "lambda" (func (param "def" $r1') (result u32)))
))
(core func $as (canon lower (func $i "as")))
(core func $lambda (canon lower (func $i "lambda")))
(core module $m
(import "" "as" (func $as (param i32 i64) (result i64)))
(import "" "lambda" (func $lambda (param i32 i32 i32) (result i32)))
(func (export "await") (result i32)
i32.const 100)
(func (export "as") (param i32 i64) (result i64)
(call $as (local.get 0) (local.get 1)))
(func (export "lambda") (param i32 i32 i32) (result i32)
(call $lambda (local.get 0) (local.get 1) (local.get 2)))
)
(core instance $i (instantiate $m
(with "" (instance
(export "as" (func $as))
(export "lambda" (func $lambda))
))
))
(type $c1 (variant (case "break" s32) (case "class" s64) (case "true" s64)))
(type $r1 (record (field "else" u8) (field "not" u8) (field "except" u8)))
(func $await-export (result u8) (canon lift (core func $i "await")))
(func $as-export (param "import" $c1) (result s64)
(canon lift (core func $i "as")))
(func $lambda-export (param "def" $r1) (result u32)
(canon lift (core func $i "lambda")))
(instance (export "for")
(export "none" (type $c1))
(export "true" (type $r1))
(export "await" (func $await-export))
(export "as" (func $as-export))
(export "lambda" (func $lambda-export))
)
)
"""
bindgen('keywords', module)
from .generated.keywords import Root, RootImports, imports
from .generated.keywords import for_
from .generated.keywords.imports import false
class Host(imports.HostFalse):
def as_(self, import_):
if isinstance(import_, false.None_Break):
return import_.value + 1
if isinstance(import_, false.None_Class):
return import_.value + 2
if isinstance(import_, false.None_True_):
return import_.value + 3
else:
raise ValueError("Invalid input value!")
def lambda_(self, def_):
return def_.else_ + def_.not_ + def_.except_
def test_bindings():
store = Store()
bindings = Root(store, RootImports(false=Host()))
assert 100 == bindings.for_().await_(store)
assert 101 == bindings.for_().as_(store, for_.None_Break(100))
assert 102 == bindings.for_().as_(store, for_.None_Class(100))
assert 103 == bindings.for_().as_(store, for_.None_True_(100))
assert 24 == bindings.for_().lambda_(store, for_.True_(7, 8, 9))
</document_content>
</document>
<document index="25">
<source>./codegen/test_lists.py</source>
<document_content>
from . import bindgen, REALLOC
from wasmtime import Store
from typing import List
module = """
(component
(import "host" (instance $i
(export "strings" (func (param "a" string) (result string)))
(export "bytes" (func (param "a" (list u8)) (result (list u8))))
(export "ints" (func (param "a" (list u32)) (result (list u32))))
(export "string-list" (func (param "a" (list string)) (result (list string))))
))
(core module $libc
(memory (export "mem") 1)
{}
)
(core instance $libc (instantiate $libc))
(core func $strings (canon lower (func $i "strings")
(memory $libc "mem") (realloc (func $libc "realloc"))))
(core func $bytes (canon lower (func $i "bytes")
(memory $libc "mem") (realloc (func $libc "realloc"))))
(core func $ints (canon lower (func $i "ints")
(memory $libc "mem") (realloc (func $libc "realloc"))))
(core func $string-list (canon lower (func $i "string-list")
(memory $libc "mem") (realloc (func $libc "realloc"))))
(core module $m
(import "libc" "mem" (memory 1))
(import "" "strings" (func $strings (param i32 i32 i32)))
(import "" "bytes" (func $bytes (param i32 i32 i32)))
(import "" "ints" (func $ints (param i32 i32 i32)))
(import "" "string-list" (func $string-list (param i32 i32 i32)))
(func (export "strings") (param i32 i32) (result i32)
(call $strings (local.get 0) (local.get 1) (i32.const 8))
i32.const 8)
(func (export "bytes") (param i32 i32) (result i32)
(call $bytes (local.get 0) (local.get 1) (i32.const 8))
i32.const 8)
(func (export "ints") (param i32 i32) (result i32)
(call $ints (local.get 0) (local.get 1) (i32.const 8))
i32.const 8)
(func (export "string-list") (param i32 i32) (result i32)
(call $string-list (local.get 0) (local.get 1) (i32.const 8))
i32.const 8)
)
(core instance $i (instantiate $m
(with "libc" (instance $libc))
(with "" (instance
(export "strings" (func $strings))
(export "bytes" (func $bytes))
(export "ints" (func $ints))
(export "string-list" (func $string-list))
))
))
(func (export "strings") (param "a" string) (result string)
(canon lift (core func $i "strings")
(memory $libc "mem") (realloc (func $libc "realloc"))))
(func (export "bytes") (param "a" (list u8)) (result (list u8))
(canon lift (core func $i "bytes")
(memory $libc "mem") (realloc (func $libc "realloc"))))
(func (export "ints") (param "a" (list u32)) (result (list u32))
(canon lift (core func $i "ints")
(memory $libc "mem") (realloc (func $libc "realloc"))))
(func (export "string-list") (param "a" (list string)) (result (list string))
(canon lift (core func $i "string-list")
(memory $libc "mem") (realloc (func $libc "realloc"))))
)
""".format(REALLOC)
bindgen('lists', module)
from .generated.lists import Root, RootImports, imports
class Host(imports.HostHost):
def strings(self, a: str) -> str:
return a
def bytes(self, a: bytes) -> bytes:
return a
def ints(self, a: List[int]) -> List[int]:
return a
def string_list(self, a: List[str]) -> List[str]:
return a
def test_bindings():
store = Store()
wasm = Root(store, RootImports(host=Host()))
assert wasm.strings(store, '') == ''
assert wasm.strings(store, 'a') == 'a'
assert wasm.strings(store, 'hello world') == 'hello world'
assert wasm.strings(store, 'hello ⚑ world') == 'hello ⚑ world'
assert wasm.bytes(store, b'') == b''
assert wasm.bytes(store, b'a') == b'a'
assert wasm.bytes(store, b'\x01\x02') == b'\x01\x02'
assert wasm.ints(store, []) == []
assert wasm.ints(store, [1]) == [1]
assert wasm.ints(store, [1, 2, 100, 10000]) == [1, 2, 100, 10000]
assert wasm.string_list(store, []) == []
assert wasm.string_list(store, ['']) == ['']
assert wasm.string_list(store, ['a', 'b', '', 'd', 'hello']) == ['a', 'b', '', 'd', 'hello']
</document_content>
</document>
<document index="26">
<source>./codegen/test_many_arguments.py</source>
<document_content>
from . import bindgen
from wasmtime import Store
module = """
(component
(import "host" (instance $i
(export "many-arguments" (func
(param "a1" u64)
(param "a2" u64)
(param "a3" u64)
(param "a4" u64)
(param "a5" u64)
(param "a6" u64)
(param "a7" u64)
(param "a8" u64)
(param "a9" u64)
(param "a10" u64)
(param "a11" u64)
(param "a12" u64)
(param "a13" u64)
(param "a14" u64)
(param "a15" u64)
(param "a16" u64)
))
))
(core module $m
(import "" "" (func $f (param
i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64
)))
(func (export "")
(param
i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64 i64
)
local.get 0
local.get 1
local.get 2
local.get 3
local.get 4
local.get 5
local.get 6
local.get 7
local.get 8
local.get 9
local.get 10
local.get 11
local.get 12
local.get 13
local.get 14
local.get 15
call $f
)
)
(core func $f (canon lower (func $i "many-arguments")))
(core instance $i (instantiate $m
(with "" (instance (export "" (func $f))))
))
(func (export "many-arguments")
(param "a1" u64)
(param "a2" u64)
(param "a3" u64)
(param "a4" u64)
(param "a5" u64)
(param "a6" u64)
(param "a7" u64)
(param "a8" u64)
(param "a9" u64)
(param "a10" u64)
(param "a11" u64)
(param "a12" u64)
(param "a13" u64)
(param "a14" u64)
(param "a15" u64)
(param "a16" u64)
(canon lift (core func $i "")))
)
"""
bindgen('many_arguments', module)
from .generated.many_arguments import Root, RootImports, imports
class MyImports(imports.HostHost):
def many_arguments(self,
a1: int,
a2: int,
a3: int,
a4: int,
a5: int,
a6: int,
a7: int,
a8: int,
a9: int,
a10: int,
a11: int,
a12: int,
a13: int,
a14: int,
a15: int,
a16: int) -> None:
assert(a1 == 1)
assert(a2 == 2)
assert(a3 == 3)
assert(a4 == 4)
assert(a5 == 5)
assert(a6 == 6)
assert(a7 == 7)
assert(a8 == 8)
assert(a9 == 9)
assert(a10 == 10)
assert(a11 == 11)
assert(a12 == 12)
assert(a13 == 13)
assert(a14 == 14)
assert(a15 == 15)
assert(a16 == 16)
def test_bindings():
store = Store()
wasm = Root(store, RootImports(MyImports()))
wasm.many_arguments(store, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)
</document_content>
</document>
<document index="27">
<source>./codegen/test_records.py</source>
<document_content>
from . import bindgen
from typing import Tuple
from wasmtime import Store
module = """
(component
(type $tuple (tuple u8 u32))
(type $flag1 (flags "a" "b"))
(type $flag2 (flags "a" "b" "c"))
(type $flag8 (flags "a1" "a2" "a3" "a4" "a5" "a6" "a7" "a8"))
(type $flag16 (flags
"a1" "a2" "a3" "a4" "a5" "a6" "a7" "a8" "a9" "a10" "a11" "a12" "a13"
"a14" "a15" "a16"
))
(type $flag32 (flags
"a1" "a2" "a3" "a4" "a5" "a6" "a7" "a8" "a9" "a10" "a11" "a12" "a13"
"a14" "a15" "a16" "a17" "a18" "a19" "a20" "a21" "a22" "a23" "a24"
"a25" "a26" "a27" "a28" "a29" "a30" "a31" "a32"
))
(type $r1 (record (field "a" u8) (field "b" $flag1)))
(import "host" (instance $i
(export "multiple-results" (func (result (tuple u8 u16))))
(export "swap" (func (param "a" $tuple) (result $tuple)))
(export $f1 "flag1" (type (eq $flag1)))
(export $f2 "flag2" (type (eq $flag2)))
(export $f8 "flag8" (type (eq $flag8)))
(export $f16 "flag16" (type (eq $flag16)))
(export $f32 "flag32" (type (eq $flag32)))
(export "roundtrip-flag1" (func (param "a" $f1) (result $f1)))
(export "roundtrip-flag2" (func (param "a" $f2) (result $f2)))
(export "roundtrip-flag8" (func (param "a" $f8) (result $f8)))
(export "roundtrip-flag16" (func (param "a" $f16) (result $f16)))
(export "roundtrip-flag32" (func (param "a" $f32) (result $f32)))
(type $r1 (record (field "a" u8) (field "b" $f1)))
(export $r1' "r1" (type (eq $r1)))
(export "roundtrip-r1" (func (param "a" $r1') (result $r1')))
))
(core module $libc
(memory (export "mem") 1)
)
(core instance $libc (instantiate $libc))
(core func $multi (canon lower (func $i "multiple-results") (memory $libc "mem")))
(core func $swap (canon lower (func $i "swap") (memory $libc "mem")))
(core func $r-flag1 (canon lower (func $i "roundtrip-flag1")))
(core func $r-flag2 (canon lower (func $i "roundtrip-flag2")))
(core func $r-flag8 (canon lower (func $i "roundtrip-flag8")))
(core func $r-flag16 (canon lower (func $i "roundtrip-flag16")))
(core func $r-flag32 (canon lower (func $i "roundtrip-flag32")))
(core func $r-r1 (canon lower (func $i "roundtrip-r1") (memory $libc "mem")))
(core module $m
(import "" "r-flag1" (func $r-flag1 (param i32) (result i32)))
(import "" "r-flag2" (func $r-flag2 (param i32) (result i32)))
(import "" "r-flag8" (func $r-flag8 (param i32) (result i32)))
(import "" "r-flag16" (func $r-flag16 (param i32) (result i32)))
(import "" "r-flag32" (func $r-flag32 (param i32) (result i32)))
(import "" "multi" (func $multi (param i32)))
(import "" "swap" (func $swap (param i32 i32 i32)))
(import "" "r-r1" (func $r-r1 (param i32 i32 i32)))
(import "libc" "mem" (memory 1))
(func (export "multi") (result i32)
(call $multi (i32.const 100))
i32.const 100)
(func (export "swap") (param i32 i32) (result i32)
(call $swap (local.get 0) (local.get 1) (i32.const 100))
i32.const 100)
(func (export "r-flag1") (param i32) (result i32)
(call $r-flag1 (local.get 0)))
(func (export "r-flag2") (param i32) (result i32)
(call $r-flag2 (local.get 0)))
(func (export "r-flag8") (param i32) (result i32)
(call $r-flag8 (local.get 0)))
(func (export "r-flag16") (param i32) (result i32)
(call $r-flag16 (local.get 0)))
(func (export "r-flag32") (param i32) (result i32)
(call $r-flag32 (local.get 0)))
(func (export "r-r1") (param i32 i32) (result i32)
(call $r-r1 (local.get 0) (local.get 1) (i32.const 100))
i32.const 100)
)
(core instance $i (instantiate $m
(with "libc" (instance $libc))
(with "" (instance
(export "multi" (func $multi))
(export "swap" (func $swap))
(export "r-flag1" (func $r-flag1))
(export "r-flag2" (func $r-flag2))
(export "r-flag8" (func $r-flag8))
(export "r-flag16" (func $r-flag16))
(export "r-flag32" (func $r-flag32))
(export "r-r1" (func $r-r1))
))
))
(func $multiple-results (result (tuple u8 u16))
(canon lift (core func $i "multi") (memory $libc "mem")))
(func $swap (param "a" $tuple) (result $tuple)
(canon lift (core func $i "swap") (memory $libc "mem")))
(func $roundtrip-flag1 (param "a" $flag1) (result $flag1)
(canon lift (core func $i "r-flag1")))
(func $roundtrip-flag2 (param "a" $flag2) (result $flag2)
(canon lift (core func $i "r-flag2")))
(func $roundtrip-flag8 (param "a" $flag8) (result $flag8)
(canon lift (core func $i "r-flag8")))
(func $roundtrip-flag16 (param "a" $flag16) (result $flag16)
(canon lift (core func $i "r-flag16")))
(func $roundtrip-flag32 (param "a" $flag32) (result $flag32)
(canon lift (core func $i "r-flag32")))
(func $roundtrip-r1 (param "a" $r1) (result $r1)
(canon lift (core func $i "r-r1") (memory $libc "mem")))
(instance (export "e")
(export "flag1" (type $flag1))
(export "flag2" (type $flag2))
(export "flag8" (type $flag8))
(export "flag16" (type $flag16))
(export "flag32" (type $flag32))
(export "r1" (type $r1))
(export "multiple-results" (func $multiple-results))
(export "swap" (func $swap))
(export "roundtrip-flag1" (func $roundtrip-flag1))
(export "roundtrip-flag2" (func $roundtrip-flag2))
(export "roundtrip-flag8" (func $roundtrip-flag8))
(export "roundtrip-flag16" (func $roundtrip-flag16))
(export "roundtrip-flag32" (func $roundtrip-flag32))
(export "roundtrip-r1" (func $roundtrip-r1))
)
)
"""
bindgen('records', module)
from .generated.records import Root, RootImports, imports
from .generated.records.exports.e import Flag1, Flag2, Flag8, Flag16, Flag32, R1
from .generated.records.imports import host
class Host(imports.HostHost):
def multiple_results(self) -> Tuple[int, int]:
return 1, 2
def swap(self, tuple: Tuple[int, int]) -> Tuple[int, int]:
a, b = tuple
return b, a
def roundtrip_flag1(self, f: host.Flag1) -> host.Flag1:
return f
def roundtrip_flag2(self, f: host.Flag2) -> host.Flag2:
return f
def roundtrip_flag8(self, f: host.Flag8) -> host.Flag8:
return f
def roundtrip_flag16(self, f: host.Flag16) -> host.Flag16:
return f
def roundtrip_flag32(self, f: host.Flag32) -> host.Flag32:
return f
def roundtrip_r1(self, f: host.R1) -> host.R1:
return f
def test_bindings():
store = Store()
bindings = Root(store, RootImports(host=Host()))
assert bindings.e().multiple_results(store) == (1, 2)
assert bindings.e().swap(store, (3, 4)) == (4, 3)
assert bindings.e().roundtrip_flag1(store, Flag1(0)) == Flag1(0)
for f1 in Flag1:
assert bindings.e().roundtrip_flag1(store, f1) == f1
assert bindings.e().roundtrip_flag2(store, Flag2(0)) == Flag2(0)
for f2 in Flag2:
assert bindings.e().roundtrip_flag2(store, f2) == f2
assert bindings.e().roundtrip_flag8(store, Flag8(0)) == Flag8(0)
for f8 in Flag8:
assert bindings.e().roundtrip_flag8(store, f8) == f8
assert bindings.e().roundtrip_flag16(store, Flag16(0)) == Flag16(0)
for f16 in Flag16:
assert bindings.e().roundtrip_flag16(store, f16) == f16
assert bindings.e().roundtrip_flag32(store, Flag32(0)) == Flag32(0)
for f32 in Flag32:
assert bindings.e().roundtrip_flag32(store, f32) == f32
r = bindings.e().roundtrip_r1(store, R1(8, Flag1(0)))
assert r.a == 8
assert r.b == Flag1(0)
r = bindings.e().roundtrip_r1(store, R1(a=100, b=Flag1.A | Flag1.B))
assert r.a == 100
assert r.b == Flag1.A | Flag1.B
</document_content>
</document>
<document index="28">
<source>./codegen/test_scalars.py</source>
<document_content>
from . import bindgen
import math
from wasmtime import Store
module = """
(component
(import "host" (instance $i
(export "roundtrip-u8" (func (param "a" u8) (result u8)))
(export "roundtrip-s8" (func (param "a" s8) (result s8)))
(export "roundtrip-u16" (func (param "a" u16) (result u16)))
(export "roundtrip-s16" (func (param "a" s16) (result s16)))
(export "roundtrip-u32" (func (param "a" u32) (result u32)))
(export "roundtrip-s32" (func (param "a" s32) (result s32)))
(export "roundtrip-u64" (func (param "a" u64) (result u64)))
(export "roundtrip-s64" (func (param "a" s64) (result s64)))
(export "roundtrip-float32" (func (param "a" float32) (result float32)))
(export "roundtrip-float64" (func (param "a" float64) (result float64)))
(export "roundtrip-char" (func (param "a" char) (result char)))
(export "roundtrip-bool" (func (param "a" bool) (result bool)))
))
(core module $m
(import "" "roundtrip-u8" (func $u8 (param i32) (result i32)))
(import "" "roundtrip-s8" (func $s8 (param i32) (result i32)))
(import "" "roundtrip-u16" (func $u16 (param i32) (result i32)))
(import "" "roundtrip-s16" (func $s16 (param i32) (result i32)))
(import "" "roundtrip-u32" (func $u32 (param i32) (result i32)))
(import "" "roundtrip-s32" (func $s32 (param i32) (result i32)))
(import "" "roundtrip-u64" (func $u64 (param i64) (result i64)))
(import "" "roundtrip-s64" (func $s64 (param i64) (result i64)))
(import "" "roundtrip-float32" (func $float32 (param f32) (result f32)))
(import "" "roundtrip-float64" (func $float64 (param f64) (result f64)))
(import "" "roundtrip-char" (func $char (param i32) (result i32)))
(import "" "roundtrip-bool" (func $bool (param i32) (result i32)))
(func (export "roundtrip-u8") (param i32) (result i32)
local.get 0 call $u8)
(func (export "roundtrip-s8") (param i32) (result i32)
local.get 0 call $s8)
(func (export "roundtrip-u16") (param i32) (result i32)
local.get 0 call $u16)
(func (export "roundtrip-s16") (param i32) (result i32)
local.get 0 call $s16)
(func (export "roundtrip-u32") (param i32) (result i32)
local.get 0 call $u32)
(func (export "roundtrip-s32") (param i32) (result i32)
local.get 0 call $s32)
(func (export "roundtrip-u64") (param i64) (result i64)
local.get 0 call $u64)
(func (export "roundtrip-s64") (param i64) (result i64)
local.get 0 call $s64)
(func (export "roundtrip-float32") (param f32) (result f32)
local.get 0 call $float32)
(func (export "roundtrip-float64") (param f64) (result f64)
local.get 0 call $float64)
(func (export "roundtrip-char") (param i32) (result i32)
local.get 0 call $char)
(func (export "roundtrip-bool") (param i32) (result i32)
local.get 0 call $bool)
)
(core func $u8 (canon lower (func $i "roundtrip-u8")))
(core func $s8 (canon lower (func $i "roundtrip-s8")))
(core func $u16 (canon lower (func $i "roundtrip-u16")))
(core func $s16 (canon lower (func $i "roundtrip-s16")))
(core func $u32 (canon lower (func $i "roundtrip-u32")))
(core func $s32 (canon lower (func $i "roundtrip-s32")))
(core func $u64 (canon lower (func $i "roundtrip-u64")))
(core func $s64 (canon lower (func $i "roundtrip-s64")))
(core func $float32 (canon lower (func $i "roundtrip-float32")))
(core func $float64 (canon lower (func $i "roundtrip-float64")))
(core func $char (canon lower (func $i "roundtrip-char")))
(core func $bool (canon lower (func $i "roundtrip-bool")))
(core instance $i (instantiate $m
(with "" (instance
(export "roundtrip-u8" (func $u8))
(export "roundtrip-s8" (func $s8))
(export "roundtrip-u16" (func $u16))
(export "roundtrip-s16" (func $s16))
(export "roundtrip-u32" (func $u32))
(export "roundtrip-s32" (func $s32))
(export "roundtrip-u64" (func $u64))
(export "roundtrip-s64" (func $s64))
(export "roundtrip-float32" (func $float32))
(export "roundtrip-float64" (func $float64))
(export "roundtrip-char" (func $char))
(export "roundtrip-bool" (func $bool))
))
))
(func (export "roundtrip-u8") (param "a" u8) (result u8)
(canon lift (core func $i "roundtrip-u8")))
(func (export "roundtrip-s8") (param "a" s8) (result s8)
(canon lift (core func $i "roundtrip-s8")))
(func (export "roundtrip-u16") (param "a" u16) (result u16)
(canon lift (core func $i "roundtrip-u16")))
(func (export "roundtrip-s16") (param "a" s16) (result s16)
(canon lift (core func $i "roundtrip-s16")))
(func (export "roundtrip-u32") (param "a" u32) (result u32)
(canon lift (core func $i "roundtrip-u32")))
(func (export "roundtrip-s32") (param "a" s32) (result s32)
(canon lift (core func $i "roundtrip-s32")))
(func (export "roundtrip-u64") (param "a" u64) (result u64)
(canon lift (core func $i "roundtrip-u64")))
(func (export "roundtrip-s64") (param "a" s64) (result s64)
(canon lift (core func $i "roundtrip-s64")))
(func (export "roundtrip-float32") (param "a" float32) (result float32)
(canon lift (core func $i "roundtrip-float32")))
(func (export "roundtrip-float64") (param "a" float64) (result float64)
(canon lift (core func $i "roundtrip-float64")))
(func (export "roundtrip-char") (param "a" char) (result char)
(canon lift (core func $i "roundtrip-char")))
(func (export "roundtrip-bool") (param "a" bool) (result bool)
(canon lift (core func $i "roundtrip-bool")))
)
"""
bindgen('scalars', module)
from .generated.scalars import Root, RootImports, imports
class Host(imports.HostHost):
def roundtrip_u8(self, val: int) -> int:
assert val >= 0
assert val <= (1 << 8) - 1
return val
def roundtrip_s8(self, val: int) -> int:
assert val >= -(1 << (8 - 1))
assert val <= (1 << (8 - 1)) - 1
return val
def roundtrip_u16(self, val: int) -> int:
assert val >= 0
assert val <= (1 << 16) - 1
return val
def roundtrip_s16(self, val: int) -> int:
assert val >= -(1 << (16 - 1))
assert val <= (1 << (16 - 1)) - 1
return val
def roundtrip_u32(self, val: int) -> int:
assert val >= 0
assert val <= (1 << 32) - 1
return val
def roundtrip_s32(self, val: int) -> int:
assert val >= -(1 << (32 - 1))
assert val <= (1 << (32 - 1)) - 1
return val
def roundtrip_u64(self, val: int) -> int:
assert val >= 0
assert val <= (1 << 64) - 1
return val
def roundtrip_s64(self, val: int) -> int:
assert val >= -(1 << (64 - 1))
assert val <= (1 << (64 - 1)) - 1
return val
def roundtrip_float32(self, a: float) -> float:
return a
def roundtrip_float64(self, a: float) -> float:
return a
def roundtrip_char(self, a: str) -> str:
return a
def roundtrip_bool(self, a: bool) -> bool:
return a
def test_bindings():
store = Store()
bindings = Root(store, RootImports(host=Host()))
assert bindings.roundtrip_u8(store, 0) == 0
assert bindings.roundtrip_u8(store, (1 << 8) - 1) == (1 << 8) - 1
assert bindings.roundtrip_u16(store, 0) == 0
assert bindings.roundtrip_u16(store, (1 << 16) - 1) == (1 << 16) - 1
assert bindings.roundtrip_u32(store, 0) == 0
assert bindings.roundtrip_u32(store, (1 << 32) - 1) == (1 << 32) - 1
assert bindings.roundtrip_u64(store, 0) == 0
assert bindings.roundtrip_u64(store, (1 << 64) - 1) == (1 << 64) - 1
assert bindings.roundtrip_s8(store, 0) == 0
assert bindings.roundtrip_s8(store, (1 << (8 - 1)) - 1) == (1 << (8 - 1)) - 1
assert bindings.roundtrip_s8(store, -(1 << (8 - 1))) == -(1 << (8 - 1))
assert bindings.roundtrip_s16(store, 0) == 0
assert bindings.roundtrip_s16(store, (1 << (16 - 1)) - 1) == (1 << (16 - 1)) - 1
assert bindings.roundtrip_s16(store, -(1 << (16 - 1))) == -(1 << (16 - 1))
assert bindings.roundtrip_s32(store, 0) == 0
assert bindings.roundtrip_s32(store, (1 << (32 - 1)) - 1) == (1 << (32 - 1)) - 1
assert bindings.roundtrip_s32(store, -(1 << (32 - 1))) == -(1 << (32 - 1))
assert bindings.roundtrip_s64(store, 0) == 0
assert bindings.roundtrip_s64(store, (1 << (64 - 1)) - 1) == (1 << (64 - 1)) - 1
assert bindings.roundtrip_s64(store, -(1 << (64 - 1))) == -(1 << (64 - 1))
inf = float('inf')
assert bindings.roundtrip_float32(store, 1.0) == 1.0
assert bindings.roundtrip_float32(store, inf) == inf
assert bindings.roundtrip_float32(store, -inf) == -inf
assert math.isnan(bindings.roundtrip_float32(store, float('nan')))
assert bindings.roundtrip_float64(store, 1.0) == 1.0
assert bindings.roundtrip_float64(store, inf) == inf
assert bindings.roundtrip_float64(store, -inf) == -inf
assert math.isnan(bindings.roundtrip_float64(store, float('nan')))
assert bindings.roundtrip_char(store, 'a') == 'a'
assert bindings.roundtrip_char(store, ' ') == ' '
assert bindings.roundtrip_char(store, '🚩') == '🚩'
assert bindings.roundtrip_bool(store, True)
assert not bindings.roundtrip_bool(store, False)
</document_content>
</document>
<document index="29">
<source>./codegen/test_simple_export.py</source>
<document_content>
from . import bindgen
from wasmtime import Store
module = """
(component
(core module $m
(func (export "get") (result i32)
i32.const 100)
)
(core instance $i (instantiate $m))
(func (export "get") (result u8) (canon lift (core func $i "get")))
)
"""
bindgen('simple_export', module)
from .generated.simple_export import Root
def test_bindings():
store = Store()
bindings = Root(store)
result = bindings.get(store)
assert result == 100
</document_content>
</document>
<document index="30">
<source>./codegen/test_simple_import.py</source>
<document_content>
from . import bindgen
from wasmtime import Store
module = """
(component
(import "host" (instance $host
(export "thunk" (func))
))
(core module $m
(import "host" "thunk" (func $thunk))
(start $thunk)
)
(core func $thunk (canon lower (func $host "thunk")))
(core instance $i (instantiate $m
(with "host" (instance (export "thunk" (func $thunk))))
))
)
"""
bindgen('simple_import', module)
from .generated.simple_import import Root, RootImports, imports
class Host(imports.HostHost):
def thunk(self):
self.hit = True
def test_bindings():
store = Store()
host = Host()
Root(store, RootImports(host=host))
assert host.hit
</document_content>
</document>
<document index="31">
<source>./codegen/test_two_exports.py</source>
<document_content>
from . import bindgen
from wasmtime import Store
module = """
(component
(import "i" (instance $i
(export "f1" (func))
(export "f2" (func))
))
(core func $f1 (canon lower (func $i "f1")))
(core func $f2 (canon lower (func $i "f2")))
(func $f1' (canon lift (core func $f1)))
(func $f2' (canon lift (core func $f2)))
(instance (export "i1") (export "f1" (func $f1')))
(instance (export "i2") (export "f2" (func $f2')))
)
"""
bindgen('two_exports', module)
from .generated.two_exports import Root, RootImports, imports
class Host(imports.HostI):
def f1(self) -> None:
self.f1_hit = True
def f2(self) -> None:
self.f2_hit = True
def test_bindings():
store = Store()
host = Host()
wasm = Root(store, RootImports(i=host))
wasm.i1().f1(store)
assert(host.f1_hit)
wasm.i2().f2(store)
assert(host.f2_hit)
</document_content>
</document>
<document index="32">
<source>./codegen/test_variants.py</source>
<document_content>
from . import bindgen
from wasmtime import Store
from typing import Optional
module = """
(component
(import "host" (instance $i
(type $e1 (enum "a" "b"))
(type $c1 (variant (case "a" s32) (case "b" s64)))
(type $c2 (variant (case "a" s32) (case "b" float32)))
(type $c3 (variant (case "a" s32) (case "b" float64)))
(type $c4 (variant (case "a" s64) (case "b" float32)))
(type $c5 (variant (case "a" s64) (case "b" float64)))
(type $c6 (variant (case "a" float32) (case "b" float64)))
(type $z1 (variant (case "a" s32) (case "b")))
(type $z2 (variant (case "a" s64) (case "b")))
(type $z3 (variant (case "a" float32) (case "b")))
(type $z4 (variant (case "a" float64) (case "b")))
(type $all-integers (variant
(case "bool" bool)
(case "u8" u8)
(case "u16" u16)
(case "u32" u32)
(case "u64" u64)
(case "s8" s8)
(case "s16" s16)
(case "s32" s32)
(case "s64" s64)
))
(type $all-floats (variant (case "f32" float32) (case "f64" float64)))
(type $duplicated-s32 (variant
(case "c1" s32)
(case "c2" s32)
(case "c3" s32)
))
(type $distinguished (variant (case "s32" s32) (case "float32" float32)))
(export $distinguished' "distinguished" (type (eq $distinguished)))
(type $nested-union (variant
(case "d" $distinguished')
(case "s32" s32)
(case "float32" float32)
))
(type $option-in-union (variant (case "o" (option s32)) (case "i" s32)))
(export $e1' "e1" (type (eq $e1)))
(export $c1' "c1" (type (eq $c1)))
(export $c2' "c2" (type (eq $c2)))
(export $c3' "c3" (type (eq $c3)))
(export $c4' "c4" (type (eq $c4)))
(export $c5' "c5" (type (eq $c5)))
(export $c6' "c6" (type (eq $c6)))
(type $casts (tuple $c1' $c2' $c3' $c4' $c5' $c6'))
(export $casts' "casts" (type (eq $casts)))
(export $z1' "z1" (type (eq $z1)))
(export $z2' "z2" (type (eq $z2)))
(export $z3' "z3" (type (eq $z3)))
(export $z4' "z4" (type (eq $z4)))
(type $zeros (tuple $z1' $z2' $z3' $z4'))
(export $zeros' "zeros" (type (eq $zeros)))
(export $all-integers' "all-integers" (type (eq $all-integers)))
(export $all-floats' "all-floats" (type (eq $all-floats)))
(export $duplicated-s32' "duplicated-s32" (type (eq $duplicated-s32)))
(export $nested-union' "nested-union" (type (eq $nested-union)))
(export $option-in-union' "option-in-union" (type (eq $option-in-union)))
(export "roundtrip-option" (func (param "a" (option float32)) (result (option u8))))
(export "roundtrip-result" (func
(param "a" (result u32 (error float32)))
(result (result float64 (error u8)))
))
(export "roundtrip-enum" (func (param "a" $e1') (result $e1')))
(export "variant-casts" (func (param "a" $casts') (result $casts')))
(export "variant-zeros" (func (param "a" $zeros') (result $zeros')))
(export "add-one-all-integers" (func (param "a" $all-integers') (result $all-integers')))
(export "add-one-all-floats" (func (param "a" $all-floats') (result $all-floats')))
(export "add-one-duplicated-s32" (func (param "a" $duplicated-s32') (result $duplicated-s32')))
(export "add-one-distinguished" (func (param "a" $distinguished') (result $distinguished')))
(export "add-one-nested-union" (func (param "a" $nested-union') (result $nested-union')))
(export "add-one-option-in-union" (func (param "a" $option-in-union') (result $option-in-union')))
(export "add-one-option-in-option" (func (param "a" (option (option s32))) (result (option (option s32)))))
))
(core module $libc (memory (export "m") 1))
(core instance $libc (instantiate $libc))
(core func $r-opt (canon lower (func $i "roundtrip-option") (memory $libc "m")))
(core func $r-result (canon lower (func $i "roundtrip-result") (memory $libc "m")))
(core func $r-enum (canon lower (func $i "roundtrip-enum")))
(core func $v-casts (canon lower (func $i "variant-casts") (memory $libc "m")))
(core func $v-zeros (canon lower (func $i "variant-zeros") (memory $libc "m")))
(core func $a-int (canon lower (func $i "add-one-all-integers") (memory $libc "m")))
(core func $a-float (canon lower (func $i "add-one-all-floats") (memory $libc "m")))
(core func $a-dup (canon lower (func $i "add-one-duplicated-s32") (memory $libc "m")))
(core func $a-dist (canon lower (func $i "add-one-distinguished") (memory $libc "m")))
(core func $a-nest (canon lower (func $i "add-one-nested-union") (memory $libc "m")))
(core func $a-oinu (canon lower (func $i "add-one-option-in-union") (memory $libc "m")))
(core func $a-oino (canon lower (func $i "add-one-option-in-option") (memory $libc "m")))
(core module $m
(import "libc" "m" (memory 1))
(import "" "r-opt" (func $r-opt (param i32 f32 i32)))
(import "" "r-result" (func $r-result (param i32 i32 i32)))
(import "" "r-enum" (func $r-enum (param i32) (result i32)))
(import "" "v-casts" (func $v-casts
(param i32 i64 i32 i32 i32 i64 i32 i64 i32 i64 i32 i64 i32)
))
(import "" "v-zeros" (func $v-zeros
(param i32 i32 i32 i64 i32 f32 i32 f64 i32)
))
(import "" "a-int" (func $a-int (param i32 i64 i32)))
(import "" "a-float" (func $a-float (param i32 i64 i32)))
(import "" "a-dup" (func $a-dup (param i32 i32 i32)))
(import "" "a-dist" (func $a-dist (param i32 i32 i32)))
(import "" "a-nest" (func $a-nest (param i32 i32 i32 i32)))
(import "" "a-oinu" (func $a-oinu (param i32 i32 i32 i32)))
(import "" "a-oino" (func $a-oino (param i32 i32 i32 i32)))
(func (export "r-opt") (param i32 f32) (result i32)
(call $r-opt (local.get 0) (local.get 1) (i32.const 100))
i32.const 100)
(func (export "r-result") (param i32 i32) (result i32)
(call $r-result (local.get 0) (local.get 1) (i32.const 100))
i32.const 100)
(func (export "r-enum") (param i32) (result i32)
(call $r-enum (local.get 0)))
(func (export "v-casts")
(param i32 i64 i32 i32 i32 i64 i32 i64 i32 i64 i32 i64)
(result i32)
local.get 0
local.get 1
local.get 2
local.get 3
local.get 4
local.get 5
local.get 6
local.get 7
local.get 8
local.get 9
local.get 10
local.get 11
i32.const 80
call $v-casts
i32.const 80)
(func (export "v-zeros")
(param i32 i32 i32 i64 i32 f32 i32 f64)
(result i32)
local.get 0
local.get 1
local.get 2
local.get 3
local.get 4
local.get 5
local.get 6
local.get 7
i32.const 80
call $v-zeros
i32.const 80)
(func (export "a-int") (param i32 i64) (result i32)
(call $a-int (local.get 0) (local.get 1) (i32.const 80))
i32.const 80)
(func (export "a-float") (param i32 i64) (result i32)
(call $a-float (local.get 0) (local.get 1) (i32.const 80))
i32.const 80)
(func (export "a-dup") (param i32 i32) (result i32)
(call $a-dup (local.get 0) (local.get 1) (i32.const 80))
i32.const 80)
(func (export "a-dist") (param i32 i32) (result i32)
(call $a-dist (local.get 0) (local.get 1) (i32.const 80))
i32.const 80)
(func (export "a-nest") (param i32 i32 i32) (result i32)
(call $a-nest (local.get 0) (local.get 1) (local.get 2) (i32.const 80))
i32.const 80)
(func (export "a-oinu") (param i32 i32 i32) (result i32)
(call $a-oinu (local.get 0) (local.get 1) (local.get 2) (i32.const 80))
i32.const 80)
(func (export "a-oino") (param i32 i32 i32) (result i32)
(call $a-oino (local.get 0) (local.get 1) (local.get 2) (i32.const 80))
i32.const 80)
)
(core instance $i (instantiate $m
(with "libc" (instance $libc))
(with "" (instance
(export "r-opt" (func $r-opt))
(export "r-result" (func $r-result))
(export "r-enum" (func $r-enum))
(export "v-casts" (func $v-casts))
(export "v-zeros" (func $v-zeros))
(export "a-int" (func $a-int))
(export "a-float" (func $a-float))
(export "a-dup" (func $a-dup))
(export "a-dist" (func $a-dist))
(export "a-nest" (func $a-nest))
(export "a-oinu" (func $a-oinu))
(export "a-oino" (func $a-oino))
))
))
(type $e1 (enum "a" "b"))
(type $c1 (variant (case "a" s32) (case "b" s64)))
(type $c2 (variant (case "a" s32) (case "b" float32)))
(type $c3 (variant (case "a" s32) (case "b" float64)))
(type $c4 (variant (case "a" s64) (case "b" float32)))
(type $c5 (variant (case "a" s64) (case "b" float64)))
(type $c6 (variant (case "a" float32) (case "b" float64)))
(type $casts (tuple $c1 $c2 $c3 $c4 $c5 $c6))
(type $z1 (variant (case "a" s32) (case "b")))
(type $z2 (variant (case "a" s64) (case "b")))
(type $z3 (variant (case "a" float32) (case "b")))
(type $z4 (variant (case "a" float64) (case "b")))
(type $zeros (tuple $z1 $z2 $z3 $z4))
(type $all-integers (variant
(case "bool" bool)
(case "u8" u8)
(case "u16" u16)
(case "u32" u32)
(case "u64" u64)
(case "s8" s8)
(case "s16" s16)
(case "s32" s32)
(case "s64" s64)
))
(type $all-floats (variant (case "f32" float32) (case "f64" float64)))
(type $duplicated-s32 (variant
(case "c1" s32)
(case "c2" s32)
(case "c3" s32)
))
(type $distinguished (variant (case "s32" s32) (case "float32" float32)))
(type $nested-union (variant
(case "d" $distinguished)
(case "s32" s32)
(case "float32" float32)
))
(type $option-in-union (variant (case "o" (option s32)) (case "i" s32)))
(func $roundtrip-option (param "a" (option float32)) (result (option u8))
(canon lift (core func $i "r-opt") (memory $libc "m")))
(func $roundtrip-result
(param "a" (result u32 (error float32)))
(result (result float64 (error u8)))
(canon lift (core func $i "r-result") (memory $libc "m")))
(func $roundtrip-enum (param "a" $e1) (result $e1)
(canon lift (core func $i "r-enum")))
(func $variant-casts (param "a" $casts) (result $casts)
(canon lift (core func $i "v-casts") (memory $libc "m")))
(func $variant-zeros (param "a" $zeros) (result $zeros)
(canon lift (core func $i "v-zeros") (memory $libc "m")))
(func $add-one-all-integers (param "a" $all-integers) (result $all-integers)
(canon lift (core func $i "a-int") (memory $libc "m")))
(func $add-one-all-floats (param "a" $all-floats) (result $all-floats)
(canon lift (core func $i "a-float") (memory $libc "m")))
(func $add-one-duplicated-s32 (param "a" $duplicated-s32) (result $duplicated-s32)
(canon lift (core func $i "a-dup") (memory $libc "m")))
(func $add-one-distinguished (param "a" $distinguished) (result $distinguished)
(canon lift (core func $i "a-dist") (memory $libc "m")))
(func $add-one-nested-union (param "a" $nested-union) (result $nested-union)
(canon lift (core func $i "a-nest") (memory $libc "m")))
(func $add-one-option-in-union (param "a" $option-in-union) (result $option-in-union)
(canon lift (core func $i "a-oinu") (memory $libc "m")))
(func $add-one-option-in-option (param "a" (option (option s32))) (result (option (option s32)))
(canon lift (core func $i "a-oino") (memory $libc "m")))
(instance (export "e")
(export "e1" (type $e1))
(export "c1" (type $c1))
(export "c2" (type $c2))
(export "c3" (type $c3))
(export "c4" (type $c4))
(export "c5" (type $c5))
(export "c6" (type $c6))
(export "casts" (type $casts))
(export "z1" (type $z1))
(export "z2" (type $z2))
(export "z3" (type $z3))
(export "z4" (type $z4))
(export "zeros" (type $zeros))
(export "all-integers" (type $all-integers))
(export "all-floats" (type $all-floats))
(export "duplicated-s32" (type $duplicated-s32))
(export "distinguished" (type $distinguished))
(export "nested-union" (type $nested-union))
(export "option-in-union" (type $option-in-union))
(export "roundtrip-option" (func $roundtrip-option))
(export "roundtrip-result" (func $roundtrip-result))
(export "roundtrip-enum" (func $roundtrip-enum))
(export "variant-casts" (func $variant-casts))
(export "variant-zeros" (func $variant-zeros))
(export "add-one-all-integers" (func $add-one-all-integers))
(export "add-one-all-floats" (func $add-one-all-floats))
(export "add-one-duplicated-s32" (func $add-one-duplicated-s32))
(export "add-one-distinguished" (func $add-one-distinguished))
(export "add-one-nested-union" (func $add-one-nested-union))
(export "add-one-option-in-union" (func $add-one-option-in-union))
(export "add-one-option-in-option" (func $add-one-option-in-option))
)
)
"""
bindgen('variants', module)
from .generated.variants import Root, RootImports, imports
from .generated.variants import e
from .generated.variants.imports import host
from .generated.variants.types import Result, Ok, Err, Some
class Host(imports.HostHost):
def roundtrip_option(self, a: Optional[float]) -> Optional[int]:
if a:
return int(a)
return None
def roundtrip_result(self, a: Result[int, float]) -> Result[float, int]:
if isinstance(a, Ok):
return Ok(float(a.value))
return Err(int(a.value))
def roundtrip_enum(self, a: host.E1) -> host.E1:
return a
def variant_casts(self, a: host.Casts) -> host.Casts:
return a
def variant_zeros(self, a: host.Zeros) -> host.Zeros:
return a
def add_one_all_integers(self, num: host.AllIntegers) -> host.AllIntegers:
# Bool
if isinstance(num, host.AllIntegersBool):
assert num.value in (True, False)
return host.AllIntegersBool(not num.value)
# The unsigned numbers
elif isinstance(num, host.AllIntegersU8):
lower_limit = 0
upper_limit = 2**8
assert lower_limit <= num.value < upper_limit
return host.AllIntegersU8((num.value + 1) % upper_limit)
elif isinstance(num, host.AllIntegersU16):
lower_limit = 0
upper_limit = 2**16
assert lower_limit <= num.value < upper_limit
return host.AllIntegersU16((num.value + 1) % upper_limit)
elif isinstance(num, host.AllIntegersU32):
lower_limit = 0
upper_limit = 2**32
assert lower_limit <= num.value < upper_limit
return host.AllIntegersU32((num.value + 1) % upper_limit)
elif isinstance(num, host.AllIntegersU64):
lower_limit = 0
upper_limit = 2**64
assert lower_limit <= num.value < upper_limit
return host.AllIntegersU64((num.value + 1) % upper_limit)
# The signed numbers
elif isinstance(num, host.AllIntegersS8):
lower_limit = -2**7
upper_limit = 2**7
assert lower_limit <= num.value < upper_limit
return host.AllIntegersS8(num.value + 1)
elif isinstance(num, host.AllIntegersS16):
lower_limit = -2**15
upper_limit = 2**15
assert lower_limit <= num.value < upper_limit
return host.AllIntegersS16(num.value + 1)
elif isinstance(num, host.AllIntegersS32):
lower_limit = -2**31
upper_limit = 2**31
assert lower_limit <= num.value < upper_limit
return host.AllIntegersS32(num.value + 1)
elif isinstance(num, host.AllIntegersS64):
lower_limit = -2**63
upper_limit = 2**63
assert lower_limit <= num.value < upper_limit
return host.AllIntegersS64(num.value + 1)
else:
raise ValueError("Invalid input value!")
def add_one_all_floats(self, num: host.AllFloats) -> host.AllFloats:
if isinstance(num, host.AllFloatsF32):
return host.AllFloatsF32(num.value + 1)
if isinstance(num, host.AllFloatsF64):
return host.AllFloatsF64(num.value + 1)
else:
raise ValueError("Invalid input value!")
def add_one_duplicated_s32(self, num: host.DuplicatedS32) -> host.DuplicatedS32:
if isinstance(num, host.DuplicatedS32C1):
return host.DuplicatedS32C1(num.value + 1)
if isinstance(num, host.DuplicatedS32C2):
return host.DuplicatedS32C2(num.value + 1)
if isinstance(num, host.DuplicatedS32C3):
return host.DuplicatedS32C3(num.value + 1)
else:
raise ValueError("Invalid input value!")
def add_one_distinguished(self, a: host.Distinguished) -> host.Distinguished:
a.value += 1
return a
def add_one_nested_union(self, a: host.NestedUnion) -> host.NestedUnion:
if isinstance(a, host.NestedUnionD):
a.value.value += 1
return host.NestedUnionD(a.value)
if isinstance(a, host.NestedUnionS32):
return host.NestedUnionS32(a.value + 1)
if isinstance(a, host.NestedUnionFloat32):
return host.NestedUnionFloat32(a.value + 1)
else:
raise ValueError("Invalid input value!")
def add_one_option_in_union(self, a: host.OptionInUnion) -> host.OptionInUnion:
if isinstance(a, host.OptionInUnionO):
if a.value is None:
return host.OptionInUnionO(None)
else:
return host.OptionInUnionO(a.value + 1)
if isinstance(a, host.OptionInUnionI):
return host.OptionInUnionI(a.value + 1)
else:
raise ValueError("Invalid input value!")
def add_one_option_in_option(self, a: Optional[Some[Optional[int]]]) -> Optional[Some[Optional[int]]]:
if isinstance(a, Some):
if a.value is None:
return Some(None)
else:
return Some(a.value + 1)
if a is None:
return None
else:
raise ValueError("Invalid input value!")
def test_bindings():
store = Store()
wasm = Root(store, RootImports(host=Host()))
exports = wasm.e()
assert exports.roundtrip_option(store, 1.) == 1
assert exports.roundtrip_option(store, None) is None
assert exports.roundtrip_option(store, 2.) == 2
assert exports.roundtrip_result(store, Ok(2)) == Ok(2)
assert exports.roundtrip_result(store, Ok(4)) == Ok(4)
assert exports.roundtrip_result(store, Err(5)) == Err(5)
assert exports.roundtrip_enum(store, e.E1.A) == e.E1.A
assert exports.roundtrip_enum(store, e.E1.B) == e.E1.B
a1, a2, a3, a4, a5, a6 = exports.variant_casts(store, (
e.C1A(1),
e.C2A(2),
e.C3A(3),
e.C4A(4),
e.C5A(5),
e.C6A(6.),
))
assert a1 == e.C1A(1)
assert a2 == e.C2A(2)
assert a3 == e.C3A(3)
assert a4 == e.C4A(4)
assert a5 == e.C5A(5)
assert a6 == e.C6A(6.)
b1, b2, b3, b4, b5, b6 = exports.variant_casts(store, (
e.C1B(1),
e.C2B(2),
e.C3B(3),
e.C4B(4),
e.C5B(5),
e.C6B(6.),
))
assert b1 == e.C1B(1)
assert b2 == e.C2B(2)
assert b3 == e.C3B(3)
assert b4 == e.C4B(4)
assert b5 == e.C5B(5)
assert b6 == e.C6B(6.)
z1, z2, z3, z4 = exports.variant_zeros(store, (
e.Z1A(1),
e.Z2A(2),
e.Z3A(3.),
e.Z4A(4.),
))
assert z1 == e.Z1A(1)
assert z2 == e.Z2A(2)
assert z3 == e.Z3A(3.)
assert z4 == e.Z4A(4.)
# All-Integers
# Booleans
assert exports.add_one_all_integers(store, e.AllIntegersBool(False)) == e.AllIntegersBool(True)
assert exports.add_one_all_integers(store, e.AllIntegersBool(True)) == e.AllIntegersBool(False)
# Unsigned integers
assert exports.add_one_all_integers(store, e.AllIntegersU8(0)) == e.AllIntegersU8(1)
assert exports.add_one_all_integers(store, e.AllIntegersU8(2**8 - 1)) == e.AllIntegersU8(0)
assert exports.add_one_all_integers(store, e.AllIntegersU16(0)) == e.AllIntegersU16(1)
assert exports.add_one_all_integers(store, e.AllIntegersU16(2**16 - 1)) == e.AllIntegersU16(0)
assert exports.add_one_all_integers(store, e.AllIntegersU32(0)) == e.AllIntegersU32(1)
assert exports.add_one_all_integers(store, e.AllIntegersU32(2**32 - 1)) == e.AllIntegersU32(0)
assert exports.add_one_all_integers(store, e.AllIntegersU64(0)) == e.AllIntegersU64(1)
assert exports.add_one_all_integers(store, e.AllIntegersU64(2**64 - 1)) == e.AllIntegersU64(0)
# Signed integers
assert exports.add_one_all_integers(store, e.AllIntegersS8(0)) == e.AllIntegersS8(1)
assert exports.add_one_all_integers(store, e.AllIntegersS8(2**7 - 2)) == e.AllIntegersS8(2**7 - 1)
assert exports.add_one_all_integers(store, e.AllIntegersS8(-8)) == e.AllIntegersS8(-7)
assert exports.add_one_all_integers(store, e.AllIntegersS16(0)) == e.AllIntegersS16(1)
assert exports.add_one_all_integers(store, e.AllIntegersS16(2**15 - 2)) == e.AllIntegersS16(2**15 - 1)
assert exports.add_one_all_integers(store, e.AllIntegersS16(-8)) == e.AllIntegersS16(-7)
assert exports.add_one_all_integers(store, e.AllIntegersS32(0)) == e.AllIntegersS32(1)
assert exports.add_one_all_integers(store, e.AllIntegersS32(2**31 - 2)) == e.AllIntegersS32(2**31 - 1)
assert exports.add_one_all_integers(store, e.AllIntegersS32(-8)) == e.AllIntegersS32(-7)
assert exports.add_one_all_integers(store, e.AllIntegersS64(0)) == e.AllIntegersS64(1)
assert exports.add_one_all_integers(store, e.AllIntegersS64(2**63 - 2)) == e.AllIntegersS64(2**63 - 1)
assert exports.add_one_all_integers(store, e.AllIntegersS64(-8)) == e.AllIntegersS64(-7)
assert exports.add_one_all_floats(store, e.AllFloatsF32(0.0)) == e.AllFloatsF32(1.0)
assert exports.add_one_all_floats(store, e.AllFloatsF64(0.0)) == e.AllFloatsF64(1.0)
assert exports.add_one_duplicated_s32(store, e.DuplicatedS32C1(0)) == e.DuplicatedS32C1(1)
assert exports.add_one_duplicated_s32(store, e.DuplicatedS32C2(1)) == e.DuplicatedS32C2(2)
assert exports.add_one_duplicated_s32(store, e.DuplicatedS32C3(2)) == e.DuplicatedS32C3(3)
assert exports.add_one_distinguished(store, e.DistinguishedS32(1)) == e.DistinguishedS32(2)
assert exports.add_one_distinguished(store, e.DistinguishedFloat32(2.)) == e.DistinguishedFloat32(3.)
assert exports.add_one_nested_union(store, e.NestedUnionD(e.DistinguishedS32(1))) == e.NestedUnionD(e.DistinguishedS32(2))
assert exports.add_one_nested_union(store, e.NestedUnionD(e.DistinguishedFloat32(2.))) == e.NestedUnionD(e.DistinguishedFloat32(3.))
assert exports.add_one_nested_union(store, e.NestedUnionS32(3)) == e.NestedUnionS32(4)
assert exports.add_one_nested_union(store, e.NestedUnionFloat32(4.)) == e.NestedUnionFloat32(5.)
assert exports.add_one_option_in_union(store, e.OptionInUnionO(1)) == e.OptionInUnionO(2)
assert exports.add_one_option_in_union(store, e.OptionInUnionO(None)) == e.OptionInUnionO(None)
assert exports.add_one_option_in_union(store, e.OptionInUnionI(1)) == e.OptionInUnionI(2)
assert exports.add_one_option_in_option(store, Some(1)) == Some(2)
assert exports.add_one_option_in_option(store, Some(None)) == Some(None)
assert exports.add_one_option_in_option(store, None) is None
</document_content>
</document>
<document index="33">
<source>./bindgen/__init__.py</source>
<document_content>
import sys
import pytest
# componentize-py requires Python 3.10
if sys.version_info < (3, 10):
pytest.skip("skipping componentize-py tests", allow_module_level=True)
</document_content>
</document>
<document index="34">
<source>./bindgen/conftest.py</source>
<document_content>
"""Fixtures to define test suites for generated code Python guest code.
These tests work by allowing you to write a WIT file, implement the guest
code in Python via componentize-py, and then test the generated Python
bindings. To add a new test, first create the needed fixtures:
* Create a new sub directory.
* Within that directory create a `.wit` file.
* Create an `app.py` file in that directory implementing the guest code.
Then to write the test itself:
* Create a `test_<name>.py` in the same directory.
* Use the `bindgest_testcase` in your test to create the wasm component
and generate python bindings for this component.
## Example
Given this directory:
```
bare_funcs/
├── app.py <-- guest code implementation
├── barefuncs <-- componentize-py bindings
│ ├── __init__.py
│ └── types.py
├── component.wit <-- test .wit file
└── test_mycomp.py <-- pytest test case of bindings
```
With a `component.wit` file of:
```wit
package component:barefuncs;
world barefuncs {
export foo: func(a: s32) -> s32;
}
```
And guest code of:
```python
class Barefuncs:
def foo(self, a: int) -> int:
return a + 1
```
You can write a testcase for this using:
```python
from pathlib import Path
def test_bare_funcs(bindgen_testcase):
testcase = bindgen_testcase(
guest_code_dir=Path(__file__).parent,
world_name='barefuncs',
)
store, root = generate_bindings(testcase)
assert root.foo(store, 10) == 11
```
"""
from pathlib import Path
from dataclasses import dataclass, field
import importlib
import tempfile
import subprocess
import shutil
from pytest import fixture
import wasmtime
from wasmtime.bindgen import generate
TEST_ROOT = Path(__file__).parent
BINDGEN_DIR = TEST_ROOT / 'generated'
@dataclass
class BindgenTestCase:
guest_code_dir: Path
world_name: str
wit_filename: str = 'component.wit'
app_dir: Path = field(init=False)
app_name: str = field(init=False, default='app', repr=False)
def __post_init__(self):
self.app_dir = Path(self.guest_code_dir).resolve()
@property
def wit_full_path(self):
return self.guest_code_dir.joinpath(self.wit_filename)
@property
def testsuite_name(self):
# The name of the directory that contains the
# guest Python code is used as the identifier for
# package names, etc.
return self.guest_code_dir.name
def generate_bindings(guest_code_dir: Path,
world_name: str,
wit_filename: str = 'component.wit'):
tc = BindgenTestCase(
guest_code_dir=guest_code_dir,
world_name=world_name,
wit_filename=wit_filename)
return _generate_bindings(tc)
def _generate_bindings(testcase: BindgenTestCase):
wit_path = testcase.wit_full_path
componentize_py = shutil.which('componentize-py')
if componentize_py is None:
raise RuntimeError("Could not find componentize-py executable.")
with tempfile.NamedTemporaryFile('w') as f:
output_wasm = str(f.name + '.wasm')
subprocess.run([
componentize_py, '-d', str(wit_path), '-w', testcase.world_name,
'componentize', '--stub-wasi', testcase.app_name,
'-o', output_wasm
], check=True, cwd=testcase.guest_code_dir)
# Once we've done that now generate the python bindings.
testsuite_name = testcase.testsuite_name
with open(output_wasm, 'rb') as out:
# Mapping of filename -> content_bytes
results = generate(testsuite_name, out.read())
for filename, contents in results.items():
path = BINDGEN_DIR / testsuite_name / filename
path.parent.mkdir(parents=True, exist_ok=True)
path.write_bytes(contents)
# Return an instantiated module for the caller to test.
pkg = importlib.import_module(f'.generated.{testsuite_name}',
package=__package__)
store = wasmtime.Store()
root = pkg.Root(store)
return store, root
@fixture
def bindgen_testcase():
return generate_bindings
</document_content>
</document>
<document index="35">
<source>./bindgen/export_resources/app.py</source>
<document_content>
import sys
from types import ModuleType
class MyInterfaceName:
def interface_func(self, foo: str) -> str:
return f"hello {foo}"
# componentize-py expects that resources within an interface are defined
# as a class in a separate module that matches the interface name.
#
# Normally, you'd want to go the more typical route of running
#
# componentize-py -d component.wit -w testworld bindings .
#
# to generate the types and protocols to help you write guest code,
# and then split the code into multiple files, but we're taking a
# shortcut here so we can write all the guest code in a single file.
class DemoResourceClass:
def __init__(self, name: str) -> None:
self.name = name
def greet(self, greeting: str) -> str:
return f'{greeting}, {self.name}!'
mod = ModuleType("my_interface_name")
mod.DemoResourceClass = DemoResourceClass
sys.modules['my_interface_name'] = mod
</document_content>
</document>
<document index="36">
<source>./bindgen/export_resources/test_export_resources.py</source>
<document_content>
from pathlib import Path
def test_bare_funcs(bindgen_testcase):
store, root = bindgen_testcase(
guest_code_dir=Path(__file__).parent,
world_name='testworld',
)
interface = root.my_interface_name()
instance = interface.DemoResourceClass(store, 'myname')
result = instance.greet(store, 'Hello there')
assert result == 'Hello there, myname!'
</document_content>
</document>
<document index="37">
<source>./bindgen/bare_funcs/app.py</source>
<document_content>
class Barefuncs:
def foo(self, a):
return a + 1
</document_content>
</document>
<document index="38">
<source>./bindgen/bare_funcs/test_bare_funcs.py</source>
<document_content>
from pathlib import Path
def test_bare_funcs(bindgen_testcase):
store, root = bindgen_testcase(
guest_code_dir=Path(__file__).parent,
world_name='barefuncs',
)
assert root.foo(store, 10) == 11
</document_content>
</document>
<document index="39">
<source>./bindgen/list_types/app.py</source>
<document_content>
from typing import List
class Lists:
def strings(self, a: str) -> str:
return a
def bytes(self, a: bytes) -> bytes:
return a
def ints(self, a: List[int]) -> List[int]:
return a
def string_list(self, a: List[str]) -> List[str]:
return a
</document_content>
</document>
<document index="40">
<source>./bindgen/list_types/test_lists.py</source>
<document_content>
from pathlib import Path
def test_lists(bindgen_testcase):
store, root = bindgen_testcase(
guest_code_dir=Path(__file__).parent,
world_name='lists',
)
assert root.strings(store, '') == ''
assert root.strings(store, 'a') == 'a'
assert root.strings(store, 'hello world') == 'hello world'
assert root.strings(store, 'hello ⚑ world') == 'hello ⚑ world'
assert root.bytes(store, b'') == b''
assert root.bytes(store, b'a') == b'a'
assert root.bytes(store, b'\x01\x02') == b'\x01\x02'
assert root.ints(store, []) == []
assert root.ints(store, [1]) == [1]
assert root.ints(store, [1, 2, 100, 10000]) == [1, 2, 100, 10000]
assert root.string_list(store, []) == []
assert root.string_list(store, ['']) == ['']
assert root.string_list(
store, ['a', 'b', '', 'd', 'hello']
) == ['a', 'b', '', 'd', 'hello']
</document_content>
</document>
</documents>
write detailed usage documentation including realistic examples
Based on the test files, I'll provide comprehensive documentation for the wasmtime Python bindings:
The wasmtime Python package provides bindings to the Wasmtime WebAssembly runtime. It allows you to instantiate and execute WebAssembly modules from Python.
from wasmtime import Engine, Store
# Create an engine
engine = Engine()
# Create a store
store = Store(engine)
The Engine handles compilation settings and caching. The Store holds runtime state for instances.
from wasmtime import Module
# From WAT text format
module = Module(engine, '(module)')
# From binary Wasm
with open('module.wasm', 'rb') as f:
module = Module(engine, f.read())
from wasmtime import FuncType, ValType, Func
# Create function type
func_type = FuncType([ValType.i32(), ValType.i32()], [ValType.i32()])
# Create function
def add(a: int, b: int) -> int:
return a + b
func = Func(store, func_type, add)
# Call function
result = func(store, 1, 2) # Returns 3
from wasmtime import MemoryType, Memory, Limits
# Create memory type with initial 1 page size
mem_type = MemoryType(Limits(1, None))
# Create memory instance
memory = Memory(store, mem_type)
# Get/set memory data
data_ptr = memory.data_ptr(store)
data_len = memory.data_len(store)
# Grow memory
memory.grow(store, 1) # Grow by 1 page
from wasmtime import TableType, Table, ValType
# Create table type for function references
table_type = TableType(ValType.funcref(), Limits(1, None))
# Create table
func = Func(store, FuncType([], []), lambda: None)
table = Table(store, table_type, func)
# Get/set elements
elem = table.get(store, 0)
table.set(store, 0, func)
from wasmtime import GlobalType, Global, Val
# Create mutable global type
global_type = GlobalType(ValType.i32(), True)
# Create global instance
global_inst = Global(store, global_type, Val.i32(1))
# Get/set value
value = global_inst.value(store)
global_inst.set_value(store, Val.i32(2))
from wasmtime import Instance, Module
# Create instance from module
module = Module(engine, '(module)')
instance = Instance(store, module, [])
# Access exports
exports = instance.exports(store)
func = exports['function_name']
mem = exports['memory']
from wasmtime import WasiConfig
# Configure WASI
config = WasiConfig()
config.inherit_argv()
config.inherit_env()
config.inherit_stdin()
config.inherit_stdout()
config.inherit_stderr()
config.preopen_dir('/', '/')
# Set WASI on store
store.set_wasi(config)
The bindings use custom exception types:
WasmtimeError
: General runtime errorsTrap
: WebAssembly trap exceptionsExitTrap
: WASI program exit
try:
instance = Instance(store, module, [])
except WasmtimeError as e:
print(f"Error instantiating module: {e}")
Resources are automatically cleaned up when Python objects are garbage collected, but can be explicitly closed:
store = Store()
store.close()
module = Module(engine, '(module)')
module.close()
This documentation covers the core functionality. The bindings also support more advanced features like:
- Component model and interface types
- Resource types and references
- Custom linking and importing
- Memory management controls
- Execution limits and interruption
Let me know if you would like me to expand on any of these topics!
write a detailed section about memory management and one about execution limits
Here are detailed sections on memory management and execution limits in the Wasmtime Python bindings:
from wasmtime import Memory, MemoryType, Limits
store = Store()
# Create memory type with initial and maximum pages (64KB per page)
mem_type = MemoryType(Limits(
minimum=1, # 1 page (64KB) initial size
maximum=10 # Optional maximum of 10 pages (640KB)
))
# Create memory instance
memory = Memory(store, mem_type)
# Get raw pointer to memory data
data_ptr = memory.data_ptr(store)
# Get total length in bytes
data_len = memory.data_len(store)
# Read/write memory using slices
memory.write(store, bytes_data, offset)
read_data = memory.read(store, offset, length)
# Memory size in pages
current_pages = memory.size(store)
# Grow by specified number of pages
success = memory.grow(store, pages=1)
# Growth can fail if it would exceed maximum
if not success:
print("Failed to grow memory")
# Growth beyond type limits raises error
try:
memory.grow(store, 1000)
except WasmtimeError:
print("Growth exceeds maximum")
store = Store()
# Set memory size limit in bytes
store.set_limits(memory_size=1024 * 1024) # 1MB limit
# Will raise WasmtimeError if module tries to exceed limit
try:
Memory(store, MemoryType(Limits(20))) # 20 pages > 1MB
except WasmtimeError:
print("Memory allocation exceeds store limit")
# Limit table elements
store.set_limits(table_elements=1000)
try:
table = Table(store,
TableType(ValType.funcref(), Limits(2000)),
None)
except WasmtimeError:
print("Table size exceeds limit")
Fuel allows metering execution by counting instructions:
# Enable fuel consumption in config
config = Config()
config.consume_fuel = True
engine = Engine(config)
store = Store(engine)
# Add fuel to store
store.set_fuel(1000000) # 1M units of fuel
# Get remaining fuel
remaining = store.get_fuel()
# Execution fails when fuel runs out
try:
# ... execute wasm ...
except Trap as e:
print("Out of fuel!")
Support interrupting long-running Wasm code:
# Enable epoch interruption
config = Config()
config.epoch_interruption = True
engine = Engine(config)
store = Store(engine)
# Set deadline in epochs
store.set_epoch_deadline(1)
# Increment epoch to trigger interrupt
engine.increment_epoch()
# Example of interrupting infinite loop
module = Module(engine, """
(module
(func (export "loop")
(loop br 0) ;; infinite loop
)
)
""")
try:
instance = Instance(store, module, [])
instance.exports(store)["loop"](store)
except Trap:
print("Execution interrupted!")
Control various resource limits per store:
store = Store()
# Set memory limits
store.set_limits(
memory_size=100000, # Max total memory in bytes
table_elements=10000, # Max table elements
)
# Growth operations will fail if they exceed limits
try:
memory.grow(store, too_many_pages)
except WasmtimeError:
print("Growth exceeds store memory limit")
try:
table.grow(store, too_many_elements, None)
except WasmtimeError:
print("Growth exceeds store table limit")
-
Always set appropriate limits to prevent resource exhaustion:
store.set_limits( memory_size=reasonable_size, table_elements=reasonable_count )
-
Use fuel for untrusted code:
config.consume_fuel = True store.set_fuel(max_instructions)
-
Enable interruption for long-running operations:
config.epoch_interruption = True store.set_epoch_deadline(deadline)
-
Catch and handle resource errors:
try: result = instance.exports(store)["function"](store) except Trap as e: if "fuel" in str(e): handle_out_of_fuel() elif "interrupted" in str(e): handle_interruption() except WasmtimeError as e: handle_resource_error()
These mechanisms provide fine-grained control over WebAssembly execution resources and help ensure safe execution of potentially untrusted or resource-intensive code.