All notable changes to this project will be documented in this file.
- Added support for Python 3.11 (#696)
- Added support for Python 3.10 (#680)
- Improvements to the documentation (e880e25)
- Updated to the latest version of Maturin (0.14.17) to fix failing Windows builds (#715)
- Fixed compatibility issues with Python 3.11 (#696)
- Fixed compatibility issues with Python 3.10 (#680)
- Fixed typos in the documentation (#639, #681)
1.1.0 - 2022-01-05
Exports
can now be iterated over.- Host functions can now type-hint results with
None
and tuples. - Added
int64
andfloat32
/float64
views of memory. - Imports can now be specified using a
dict
instead of anImportObject
.
- Wasmer has been updated to version 2.1.0.
- Python exceptions can now be thrown across Wasm calls.
- Memory view lengths are now returned correctly.
- Unsigned values that fit in
u32
/u64
no longer cause overflow errors when passed in/out of Wasm. - Indexing a memory view with a slice now always returns a list of values.
- Indexing a memory view with a slice can use steps.
- Indexing a memory view with an empty slice no longer returns an error.
1.0.0 - 2021-01-18
-
The whole API changed to better match Wasmer and Wasm C API
from wasmer import engine, wat2wasm, Module, Store, Instance from wasmer_compiler_cranelift import Compiler # Create an Engine jit = engine.JIT(Compiler) # Create a store. store = Store(jit) # Let's compile the Wasm module. module = Module(store, wasm_bytes) # Create an empty import object. import_object = {} # Let's instantiate the Wasm module. instance = Instance(module, import_object)
Please refer to the examples and documentation to learn more about the changes.
0.4.1 - 2020-02-02
-
New
Buffer
class to read memory fast (#125 by @Hywan)To get the memory buffer, use the
Memory.buffer
getter. ABuffer
implements the Python Buffer Protocol. The goal is to get faster reading operations than the existing memory views API.bytearray(instance.memory.buffer)
is 15x faster thaninstance.memory.int8_view()
.memoryview(instance.memory.buffer)
is 14x faster thaninstance.memory.int8_view()
.# Get the memory buffer. buffer = Instance(wasm_bytes).memory.buffer # Use the buffer with `memoryview` memory_view = memoryview(buffer) # Use the buffer with `byte_array` byte_array = bytearray(buffer) # Enjoy the byte array API! assert byte_array[3:9].decode() == 'Wasmer'
-
Support exported globals through the
Instance.globals
API (#120 by @Hywan)instance = Instance(wasm_bytes) x = instance.globals.x assert x.value == 7 assert x.mutable == True x.value = 153 assert x.value == 153
-
Implement a WebAssembly custom section query API (#118 by @Hywan)
Module.custom_section_names
is used to list all the custom section names.Module.custom_section
is used to read the value of a specific custom section. If the custom section does not exist,None
is returned.assert Module(wasm_bytes).custom_section('hello') == b'World!'
-
Add the
Module.imports
getter to list all imports, and introduce theImportKind
enum (#117 by @Hywan)assert Module(wasm_bytes).imports == [ { 'kind': ImportKind.FUNCTION, 'namespace': 'ns', 'name': 'f1', }, { 'kind': ImportKind.FUNCTION, 'namespace': 'ns', 'name': 'f2', }, { 'kind': ImportKind.MEMORY, 'namespace': 'ns', 'name': 'm1', # Additional pairs specific to `MEMORY` 'minimum_pages': 3, 'maximum_pages': 4, }, { 'kind': ImportKind.GLOBAL, 'namespace': 'ns', 'name': 'g1', # Additional pairs specific to `GLOBAL` 'mutable': False, 'type': 'f32' }, { 'kind': ImportKind.TABLE, 'namespace': 'ns', 'name': 't1', # Additional pairs specific to `TABLE` 'minimum_elements': 1, 'maximum_elements': 2, 'element_type': 'anyfunc', } ]
-
Add the
Module.exports
getter to list all exports, and introduce theExportKind
enum (#115 and #116 by @Hywan)assert Module(wasm_bytes).exports == [ { 'name': 'memory', 'kind': ExportKind.MEMORY, }, { 'name': '__heap_base', 'kind': ExportKind.GLOBAL, }, { 'name': '__data_end', 'kind': ExportKind.GLOBAL, }, { 'name': 'sum', 'kind': ExportKind.FUNCTION, }, ]
-
Support modules without an exported memory (#114 by @Hywan)
instance = Instance(wasm_bytes) # Now the `memory` getter can return `None` assert instance.memory == None
-
Add Rust trait to allow inspection of exported functions (#71 by @Mec-iS)
instance = Instance(wasm_bytes) assert isinstance(instance.exports.sum.getfullargspec, str) assert isinstance(instance.exports.sum.getargs, str)
-
Memory views support slice assignment (#63 by @Hywan).
memory = instance.memory.uint8_view() memory[0:4] = b"abcd"
The slice is bound to the memory view length. The slice accepts start, stop, and step parameters, so it is possible to write
view[0:5:2]
for instance. There is a huge difference with list slice assignment in Python: Elements in memory cannot be moved, so the assignment only overwrite elements.// With regular Python list a = [1, 2, 3, 4, 5] a[1:3] = [10, 11, 12] assert a == [1, 10, 11, 12, 4, 5] // With WebAssembly memory views view[0:5] = [1, 2, 3, 4, 5] view[1:3] = [10, 11, 12] assert view[0:5] == [1, 10, 11, 4, 5]
It is 10 times faster than a regular loop to write data in memory.
Read the pull request to learn more.
-
Make wasmer silently available anywhere with
wasmer-any
(#62 by @syrusakbary)
- Improve documentation of
Memory
(#127 by @Hywan) - Add a C to WebAssembly example in the documentation (#122 by @Hywan)
- Explain new features (#119 by @Hywan)
- Migrate to Github Actions for the CI (#97, #98 #99 and #101 by @Hywan)
- Update Wasmer from 0.6.0 to 0.14 (#70, #80, #88, #95, #113 and #132 by @Hywan)
- Update Pyo3 from 0.8.2 to 0.8.4 (#93, #96)
- Bump
spin
from 0.5.0 to 0.5.2 (#72]
0.3.0 - 2019-07-16
-
Bound slice to the size of the memory view —allow to write
memory_view[0:]
with no error— (#54 by @Hywan) -
Add
wasmer.__core_version__
to get the runtime [Wasmer] version (#51 by @Hywan) -
Support module serialization with
Module.serialize
andModule.deserialize
(#48 by @Hywan)from wasmer import Module # Get the Wasm bytes. wasm_bytes = open('my_program.wasm', 'rb').read() # Compile the bytes into a Wasm module. module1 = Module(wasm_bytes) # Serialize the module. serialized_module = module1.serialize() # Let's forget about the module for this example. del module1 # Deserialize the module. module2 = Module.deserialize(serialized_module) # Instantiate and use it. result = module2.instantiate().exports.sum(1, 2)
-
Introduce the
Module
class, withModule.validate
andModule.instantiate
(#47 by @Hywan)from wasmer import Module # Get the Wasm bytes. wasm_bytes = open('my_program.wasm', 'rb').read() # Compile the Wasm bytes into a Wasm module. module = Module(wasm_bytes) # Instantiate the Wasm module. instance = module.instantiate() # Call a function on it. result = instance.exports.sum(1, 2) print(result) # 3
-
Add
wasmer.__version__
to get the extension version (#27 by @Mec-iS)
- Handle exported functions that return nothing, aka void functions (#38 by @Hywan)
- More Python idiomatic examples (#55 by @Hywan)
- Add the
greet
example (#43 by @Hywan) - Improve code documentation (#36 by @Mec-iS)
- Fix typos (#25 by @Hywan)
- Fix comments in examples (#19 by @Hywan)
- Setup Bors (#35 by @Hywan)
- Add Github templates (#31 by @Hywan)
- Rename
just rust
tojust build
(#30 by @Hywan) - Update Wasmer to 0.5.5 (#59 by @Hywan)
- Update Wasmer to 0.4.2 (#42 by @Hywan)
- Update Wasmer to 0.4.0 (#26 by @Hywan)