|
| 1 | +# mJS3 - a JS engine for embedded Arduino IDE systems |
| 2 | + |
| 3 | +[](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html) |
| 4 | + |
| 5 | +mJS3 is a single-source-file JavaScript engine for Arduino IDE microcontrollers. |
| 6 | + |
| 7 | +## Demo Install |
| 8 | + |
| 9 | +- Download (Clone) this github repository and copy the folder (as is no need to rename it) into your user Arduino Folder (C:\Users\USER\Documents\Arduino\mjs3-Arduino) |
| 10 | +- Load the sketch using the Arduino IDE menu (File->Sketchbook->mjs3-Arduino) |
| 11 | +- Build and Upload (*note: currently does not build on AVR platforms) |
| 12 | + |
| 13 | +## Features |
| 14 | + |
| 15 | +- Clean ISO C, ISO C++. Builds on old (VC98) and modern compilers, from 8-bit (e.g. Arduino mini) to 64-bit systems |
| 16 | +- No dependencies |
| 17 | +- Implements a restricted subset of ES6 with limitations |
| 18 | +- Preallocates all necessary memory and never calls `malloc`, `realloc` |
| 19 | + at run time. Upon OOM, the VM is halted |
| 20 | +- Object pool, property pool, and string pool sizes are defined at compile time |
| 21 | +- The minimal configuration takes only a few hundred bytes of RAM |
| 22 | +- RAM usage: an object takes 6 bytes, each property: 16 bytes, |
| 23 | + a string: length + 6 bytes, any other type: 4 bytes |
| 24 | +- Strings are byte strings, not Unicode. |
| 25 | + For example, `'ы'.length === 2`, `'ы'[0] === '\xd1'`, `'ы'[1] === '\x8b'` |
| 26 | +- Limitations: max string length is 256 bytes, numbers hold |
| 27 | + 32-bit float value, no standard JS library |
| 28 | +- mJS VM executes JS source directly, no AST/bytecode is generated |
| 29 | +- Simple FFI API to inject existing C functions into JS |
| 30 | + |
| 31 | +## Example - blinky in JavaScript on Arduino Platform |
| 32 | + |
| 33 | +```c++ |
| 34 | +#define MJS_STRING_POOL_SIZE 200 // Buffer for all strings |
| 35 | +#include "mjs3-Arduino.c" |
| 36 | + |
| 37 | +extern void myDelay(int x) { |
| 38 | + delay(x); |
| 39 | +} |
| 40 | + |
| 41 | +extern void myDigitalWrite(int x, int y) { |
| 42 | + digitalWrite(x, y); |
| 43 | +} |
| 44 | + |
| 45 | +void setup() { |
| 46 | + pinMode(16, OUTPUT); // Initialize the LED_BUILTIN pin as an output |
| 47 | + |
| 48 | + struct mjs *vm = mjs_create(); // Create JS instance |
| 49 | + mjs_ffi(vm, "delay", (cfn_t) myDelay, "vi"); // Import delay() |
| 50 | + mjs_ffi(vm, "write", (cfn_t) myDigitalWrite, "vii"); // Import write() |
| 51 | + |
| 52 | + mjs_eval(vm, "while (1) { write(16, 0); delay(500); write(16, 1); delay(500); }", -1); |
| 53 | +} |
| 54 | + |
| 55 | +void loop() { |
| 56 | + //delay(1000); |
| 57 | +} |
| 58 | + |
| 59 | +``` |
| 60 | +
|
| 61 | +``` |
| 62 | +Sketch uses 272668 bytes (26%) of program storage space. Maximum is 1044464 bytes. |
| 63 | +Global variables use 27812 bytes (33%) of dynamic memory, leaving 54108 bytes for local variables. Maximum is 81920 bytes. |
| 64 | +``` |
| 65 | +
|
| 66 | +## Supported standard operations and constructs |
| 67 | +
|
| 68 | +| Name | Operation | |
| 69 | +| ----------------- | ---------------------------- | |
| 70 | +| Operations | All but `!=`, `==`. Use `!==`, `===` instead | |
| 71 | +| typeof | `typeof(...)` | |
| 72 | +| delete | `delete obj.k` | |
| 73 | +| while | `while (...) {...}` | |
| 74 | +| Declarations | `let a, b, c = 12.3, d = 'a'; ` | |
| 75 | +| Simple types | `let a = null, b = undefined, c = false, d = true;` | |
| 76 | +| Functions | `let f = function(x, y) { return x + y; }; ` | |
| 77 | +| Objects | `let obj = {a: 1, f: function(x) { return x * 2}}; obj.f();` | |
| 78 | +| Arrays | `let arr = [1, 2, 'hi there']` | |
| 79 | +
|
| 80 | +
|
| 81 | +## Unsupported standard operations and constructs |
| 82 | +
|
| 83 | +| Name | Operation | |
| 84 | +| ----------------- | ----------------------------------------- | |
| 85 | +| Loops/switch | `for (...) { ... }`,`for (let k in obj) { ... }`, `do { ... } while (...)`, `switch (...) {...}` | |
| 86 | +| Equality | `==`, `!=` (note: use strict equality `===`, `!==`) | |
| 87 | +| var | `var ...` (note: use `let ...`) | |
| 88 | +| Closures | `let f = function() { let x = 1; return function() { return x; } };` | |
| 89 | +| Const, etc | `const ...`, `await ...` , `void ...` , `new ...`, `instanceof ...` | |
| 90 | +| Standard types | No `Date`, `ReGexp`, `Function`, `String`, `Number` | |
| 91 | +| Prototypes | No prototype based inheritance | |
| 92 | +
|
| 93 | +## Supported non-standard JS API |
| 94 | +
|
| 95 | +| Function | Description | |
| 96 | +| ----------------- | ----------------------------------------- | |
| 97 | +| `s[offset]` | Return byte value at `offset`. `s` is either a string, or a number. A number is interprepted as `uint8_t *` pointer. Example: `'abc'[0]` returns 0x61. To read a byte at address `0x100`, use `0x100[0];`. | | |
| 98 | +
|
| 99 | +
|
| 100 | +## LICENSE |
| 101 | +
|
| 102 | +Dual license: GPLv2 or commercial. For commercial |
| 103 | +licensing, please contact support@mongoose-os.com |
0 commit comments