|
|
@ -6,22 +6,22 @@ MicroPython for [WebAssembly](https://webassembly.org/). |
|
|
|
Dependencies |
|
|
|
------------ |
|
|
|
|
|
|
|
Building webassembly port bears the same requirements as the standard |
|
|
|
MicroPython ports with the addition of Emscripten (and uglify-js for the |
|
|
|
minified file). |
|
|
|
Building the webassembly port bears the same requirements as the standard |
|
|
|
MicroPython ports with the addition of Emscripten, and optionally terser for |
|
|
|
the minified file. |
|
|
|
|
|
|
|
The output includes `micropython.js` (a JavaScript wrapper for the |
|
|
|
MicroPython runtime) and `firmware.wasm` (actual MicroPython compiled to |
|
|
|
The output includes `micropython.mjs` (a JavaScript wrapper for the |
|
|
|
MicroPython runtime) and `micropython.wasm` (actual MicroPython compiled to |
|
|
|
WASM). |
|
|
|
|
|
|
|
Build instructions |
|
|
|
------------------ |
|
|
|
|
|
|
|
In order to build micropython.js, run: |
|
|
|
In order to build `micropython.mjs`, run: |
|
|
|
|
|
|
|
$ make |
|
|
|
|
|
|
|
To generate the minified file micropython.min.js, run: |
|
|
|
To generate the minified file `micropython.min.mjs`, run: |
|
|
|
|
|
|
|
$ make min |
|
|
|
|
|
|
@ -30,55 +30,90 @@ Running with Node.js |
|
|
|
|
|
|
|
Access the repl with: |
|
|
|
|
|
|
|
$ node build/micropython.js |
|
|
|
$ make repl |
|
|
|
|
|
|
|
Stack size may be modified using: |
|
|
|
This is the same as running: |
|
|
|
|
|
|
|
$ node build/micropython.js -X stack=64K |
|
|
|
$ node build-standard/micropython.mjs |
|
|
|
|
|
|
|
Where stack size may be represented in Bytes, KiB or MiB. |
|
|
|
The initial MicroPython GC heap size may be modified using: |
|
|
|
|
|
|
|
$ node build-standard/micropython.mjs -X heapsize=64k |
|
|
|
|
|
|
|
Where stack size may be represented in bytes, or have a `k` or `m` suffix. |
|
|
|
|
|
|
|
MicroPython scripts may be executed using: |
|
|
|
|
|
|
|
$ node build/micropython.js hello.py |
|
|
|
$ node build-standard/micropython.mjs hello.py |
|
|
|
|
|
|
|
Alternatively micropython.js may by accessed by other javascript programs in node |
|
|
|
Alternatively `micropython.mjs` may by accessed by other JavaScript programs in node |
|
|
|
using the require command and the general API outlined below. For example: |
|
|
|
|
|
|
|
```javascript |
|
|
|
var mp_js = require('./build/micropython.js'); |
|
|
|
const mp_mjs = await import("micropython.mjs"); |
|
|
|
const mp = await mp_mjs.loadMicroPython(); |
|
|
|
|
|
|
|
mp.runPython("print('hello world')"); |
|
|
|
``` |
|
|
|
|
|
|
|
mp_js_init(64 * 1024); |
|
|
|
await mp_js_do_str("print('hello world')\n"); |
|
|
|
Or without await notation: |
|
|
|
|
|
|
|
```javascript |
|
|
|
import("micropython.mjs").then((mp_mjs) => { |
|
|
|
mp_mjs.loadMicroPython().then((mp) => { |
|
|
|
mp.runPython("print('hello world')"); |
|
|
|
}); |
|
|
|
}); |
|
|
|
``` |
|
|
|
|
|
|
|
Running with HTML |
|
|
|
----------------- |
|
|
|
|
|
|
|
The prerequisite for browser operation of micropython.js is to listen to the |
|
|
|
`micropython-print` event, which is passed data when MicroPython code prints |
|
|
|
something to stdout. The following code demonstrates basic functionality: |
|
|
|
The following code demonstrates the simplest way to load `micropython.mjs` in a |
|
|
|
browser, create an interpreter context, and run some Python code: |
|
|
|
|
|
|
|
```html |
|
|
|
<!doctype html> |
|
|
|
<html> |
|
|
|
<head> |
|
|
|
<script src="build-standard/micropython.mjs" type="module"></script> |
|
|
|
</head> |
|
|
|
<body> |
|
|
|
<script type="module"> |
|
|
|
const mp = await loadMicroPython(); |
|
|
|
mp.runPython("print('hello world')"); |
|
|
|
</script> |
|
|
|
</body> |
|
|
|
</html> |
|
|
|
``` |
|
|
|
|
|
|
|
The output in the above example will go to the JavaScript console. It's possible |
|
|
|
to instead capture the output and print it somewhere else, for example in an |
|
|
|
HTML element. The following example shows how to do this, and also demonstrates |
|
|
|
the use of top-level await and the `js` module: |
|
|
|
|
|
|
|
```html |
|
|
|
<!doctype html> |
|
|
|
<html> |
|
|
|
<head> |
|
|
|
<script src="build/micropython.js"></script> |
|
|
|
<script src="build-standard/micropython.mjs" type="module"></script> |
|
|
|
</head> |
|
|
|
<body> |
|
|
|
<pre id="micropython-stdout"></pre> |
|
|
|
<script> |
|
|
|
document.addEventListener("micropython-print", function(e) { |
|
|
|
let output = document.getElementById("micropython-stdout"); |
|
|
|
output.innerText += new TextDecoder().decode(e.detail); |
|
|
|
}, false); |
|
|
|
|
|
|
|
var mp_js_startup = Module["onRuntimeInitialized"]; |
|
|
|
Module["onRuntimeInitialized"] = async function() { |
|
|
|
mp_js_startup(); |
|
|
|
mp_js_init(64 * 1024); |
|
|
|
await mp_js_do_str("print('hello world')"); |
|
|
|
<script type="module"> |
|
|
|
const stdoutWriter = (line) => { |
|
|
|
document.getElementById("micropython-stdout").innerText += line + "\n"; |
|
|
|
}; |
|
|
|
const mp = await loadMicroPython({stdout:stdoutWriter}); |
|
|
|
await mp.runPythonAsync(` |
|
|
|
import js |
|
|
|
url = "https://api.github.com/users/micropython" |
|
|
|
print(f"fetching {url}...") |
|
|
|
res = await js.fetch(url) |
|
|
|
json = await res.json() |
|
|
|
for i in dir(json): |
|
|
|
print(f"{i}: {json[i]}") |
|
|
|
`); |
|
|
|
</script> |
|
|
|
</body> |
|
|
|
</html> |
|
|
@ -98,31 +133,41 @@ Run the test suite using: |
|
|
|
API |
|
|
|
--- |
|
|
|
|
|
|
|
The following functions have been exposed to javascript. |
|
|
|
The following functions have been exposed to JavaScript through the interpreter |
|
|
|
context, created and returned by `loadMicroPython()`. |
|
|
|
|
|
|
|
``` |
|
|
|
mp_js_init(stack_size) |
|
|
|
``` |
|
|
|
- `PyProxy`: the type of the object that proxies Python objects. |
|
|
|
|
|
|
|
Initialize MicroPython with the given stack size in bytes. This must be |
|
|
|
called before attempting to interact with MicroPython. |
|
|
|
- `FS`: the Emscripten filesystem object. |
|
|
|
|
|
|
|
``` |
|
|
|
await mp_js_do_str(code) |
|
|
|
``` |
|
|
|
- `globals`: an object exposing the globals from the Python `__main__` module, |
|
|
|
with methods `get(key)`, `set(key, value)` and `delete(key)`. |
|
|
|
|
|
|
|
Execute the input code. `code` must be a `string`. |
|
|
|
- `registerJsModule(name, module)`: register a JavaScript object as importable |
|
|
|
from Python with the given name. |
|
|
|
|
|
|
|
``` |
|
|
|
mp_js_init_repl() |
|
|
|
``` |
|
|
|
- `pyimport`: import a Python module and return it. |
|
|
|
|
|
|
|
Initialize MicroPython repl. Must be called before entering characters into |
|
|
|
the repl. |
|
|
|
- `runPython(code)`: execute Python code and return the result. |
|
|
|
|
|
|
|
``` |
|
|
|
await mp_js_process_char(char) |
|
|
|
``` |
|
|
|
- `runPythonAsync(code)`: execute Python code and return the result, allowing for |
|
|
|
top-level await expressions (this call must be await'ed on the JavaScript side). |
|
|
|
|
|
|
|
- `replInit()`: initialise the REPL. |
|
|
|
|
|
|
|
- `replProcessChar(chr)`: process an incoming character at the REPL. |
|
|
|
|
|
|
|
- `replProcessCharWithAsyncify(chr)`: process an incoming character at the REPL, |
|
|
|
for use when ASYNCIFY is enabled. |
|
|
|
|
|
|
|
Proxying |
|
|
|
-------- |
|
|
|
|
|
|
|
A Python `dict` instance is proxied such that: |
|
|
|
|
|
|
|
for (const key in dict) { |
|
|
|
print(key, dict[key]); |
|
|
|
} |
|
|
|
|
|
|
|
Input character into MicroPython repl. `char` must be of type `number`. This |
|
|
|
will execute MicroPython code when necessary. |
|
|
|
works as expected on the JavaScript side and iterates through the keys of the |
|
|
|
Python `dict`. |
|
|
|