mJS: Restricted JavaScript engine
====================================
[![License](https://img.shields.io/badge/license-GPL_2-green.svg)](https://github.com/cesanta/mjs/blob/master/LICENSE)
# Overview
mJS is designed for microcontrollers with limited resources. Main design
goals are: small footprint and simple C/C++ interoperability. mJS
implements a strict subset of ES6 (JavaScript version 6):
- Any valid mJS code is a valid ES6 code.
- Any valid ES6 code is not necessarily a valid mJS code.
On 32-bit ARM mJS engine takes about 50k of flash memory, and less than 1k
of RAM (see [intro article](http://goo.gl/zJYyWF)).
mJS is part of [MongooseOS](https://mongoose-os.com),
where it enables scripting for IoT devices.
# Restrictions
- No standard library. No String, Number, RegExp, Date, Function, etc.
- **`JSON.parse()`** and **`JSON.stringify()`** are available.
- No closures, only lexical scoping (i.e. nested functions are allowed).
- No exceptions.
- No `new`. In order to create an object with a custom prototype, use
**`Object.create()`**, which is available.
- Strict mode only.
- No `var`, only `let`.
- No `for..of`, `=>`, destructors, generators, proxies, promises.
- No getters, setters, `valueOf`, prototypes, classes, template strings.
- No `==` or `!=`, only `===` and `!==`.
- mJS strings are byte strings, not Unicode strings: `'ы'.length === 2`,
`'ы'[0] === '\xd1'`, `'ы'[1] === '\x8b'`.
mJS string can represent any binary data chunk.
# Built-in API
<dl>
<dt><tt>print(arg1, arg2, ...);</tt></dt>
<dd>Print arguments to stdout, separated by space.</dd>
<dt><tt>load('file.js', obj);</tt></dt>
<dd>Execute file <tt>file.js</tt>. <tt>obj</tt> paramenter is
optional. <tt>obj</tt> is a global namespace object.
If not specified, a current global namespace is passed to the script,
which allows <tt>file.js</tt> to modify the current namespace.</dd>
<dt><tt>die(message);</tt></dt>
<dd>Exit interpreter with the given error message</dd>
<dt><tt>let value = JSON.parse(str);</tt></dt>
<dd>Parse JSON string and return parsed value.</dd>
<dt><tt>let str = JSON.stringify(value);</tt></dt>
<dd>Get string representation of the mJS value.</dd>
<dt><tt>let proto = {foo: 1}; let o = Object.create(proto);</tt></dt>
<dd>Create an object with the provided prototype.</dd>
<dt><tt>'some_string'.slice(start, end);</tt></dt>
<dd>Return a substring between two indices. Example:
<tt>'abcdef'.slice(1,3) === 'bc';</tt></dd>
<dt><tt>'abc'.at(0);</tt></dt>
<dd>Return numeric byte value at given string index. Example:
<tt>'abc'.at(0) === 0x61;</tt></dd>
<dt><tt>'abc'.indexOf(substr[, fromIndex]);</tt></dt>
<dd>Return index of first occurence of substr within the string or `-1`
if not found.
<tt>'abc'.indexOf('bc') === 1;</tt></dd>
<dt><tt>chr(n);</tt></dt>
<dd>Return 1-byte string whose ASCII code is the integer `n`. If `n` is
not numeric or outside of `0-255` range, `null` is returned. Example:
<tt>chr(0x61) === 'a';</tt></dd>
<dt><tt>let a = [1,2,3,4,5]; a.splice(start, deleteCount, ...);</tt></dt>
<dd>Change the contents of an array by removing existing elements and/or
adding new elements. Example:
<tt>let a = [1,2,3,4,5]; a.splice(1, 2, 100, 101, 102); a === [1,100,101,102,4,5];</tt></dd>
<dt><tt>let s = mkstr(ptrVar, length);</tt></dt>
<dd>Create a string backed by a C memory chunk. A string <tt>s</tt> starts
at memory location <tt>ptrVar</tt>, and is <tt>length</tt> bytes long.</dd>
<dt><tt>let s = mkstr(ptrVar, offset, length, copy = false);</tt></dt>
<dd>Like `mkstr(ptrVar, length)`, but string <tt>s</tt> starts
at memory location <tt>ptrVar + offset</tt>, and the caller can specify
whether the string needs to be copied to the internal mjs buffer. By default
it's not copied.</dd>
<dt><tt>let f = ffi('int foo(int)');</tt></dt>
<dd>Import C function into mJS. See next section.</dd>
<dt><tt>gc(full);</tt></dt>
<dd>Perform garbage collection. If `full` is `true`, reclaim RAM to OS.</dd>
</dl>
# C/C++ interoperability
mJS requires no glue code. The mJS's Foreign Function Interface (FFI)
allows the user to call an existing C function with an arbitrary signature.
Currently mJS provides a simple implementation of the FFI trampoline
that supports up to 6 32-bit arguments, or up to 2 64-bit arguments:
```javascript
let floor = ffi('double floor(double)');
print(floor(1.23456));
```
Function arguments should be simple: only `int`, `double`, `char *`, `void *`
are supported. Use `char *` for NUL-terminated C strings, `void *` for any
other pointers. In order to import more complex functions
(e.g. the ones that use structures as arguments), write wrappers.
## Callbacks
Callbacks are implemented similarly. Consider that you have a C function
that takes a callback and user data `void *` pointer, which should be marked
as `userdata` in the signature:
```C
void timer(int seconds, void (*callback)(int, void *), void *user_data);
```
This is how to make an mJS callback - note the usage of `userdata`:
```javascript
let Timer = {
set: ffi('void timer(int, void (*)(int, userdata), userdata)')
};
Timer.set(200, function(t) {
print('Time now: ', t);
}, null);
```
## Symbol resolver
In order to make FFI work, mJS must be able to get the address of a C
function by its name. On POSIX systems, `dlsym()` API can do that. On
Windows, `GetProcAddress()`. On embedded systems, a system resolver should
be either manually written, or be implemented with some aid from a firmware
linker script. mJS resolver uses `dlsym`-compatible signature.
## Converting structs to objects
mJS provides a helper to facilitate coversion of C structs to JS objects.
The functions is called `s2o` and takes two parameters: foreign pointer to
the struct and foreign pointer to the struct's descriptor which specifies
names and offsets of the struct's members. Here's an simple example:
C/C++ side code:
```c
#include "mjs.h"
struct my_struct {
int a;
const char *b;
double c;
struct mg_str d;
struct mg_str *e;
float f;
bool g;
};
static const struct mjs_c_struct_member my_struct_descr[] = {
{"a", offsetof(struct my_struct, a), MJS_STRUCT_FIELD_TYPE_INT, NULL},
{"b", offsetof(struct my_struct, b), MJS_STRUCT_FIELD_TYPE_CHAR_PTR, NULL},
{"c", offsetof(struct my_struct, c), MJS_STRUCT_FIELD_TYPE_DOUBLE, NULL},
{"d", offsetof(struct my_struct, d), MJS_STRUCT_FIELD_TYPE_MG_STR, NULL},
{"e", offsetof(struct my_struct, e), MJS_STRUCT_FIELD_TYPE_MG_STR_PTR, NULL},
{"f", offsetof(struct my_struct, f), MJS_STRUCT_FIELD_TYPE_FLOAT, NULL},
{"g", offsetof(struct my_struct, g), MJS_STRUCT_FIELD_TYPE_BOOL, NULL},
{NULL, 0, MJS_STRUCT_FIELD_TYPE_INVALID, NULL},
};
const struct mjs_c_struct_member *get_my_struct_descr(void) {
return my_struct_descr;
};
```
JS side code:
```js
// Assuming `s` is a foreign pointer to an instance of `my_struct`, obtained elsewhere.
let sd = ffi('void *get_my_struct_descr(void)')();
let o = s2o(s, sd);
print(o.a, o.b);
```
Nested structs are also supported - use `MJS_STRUCT_FIELD_TYPE_STRUCT` field type
and provide pointer to the definition:
```c
struct my_struct2 {
int8_t i8;
int16_t i16;
uint8_t u8;
uint16_t u16;
};
static const struct mjs_c_struct_member my_struct2_descr[] = {
{"i8", offsetof(struct my_struct2, i8), MJS_STRUCT_FIELD_TYPE_INT8, NULL},
{"i16", offsetof(struct my_struct2, i16), MJS_STRUCT_FIELD_TYPE_INT16, NULL},
{"u8", offsetof(struct my_struct2, u8), MJS_STRUCT_FIELD_TYPE_UINT8, NULL},
{"u16", offsetof(struct my_struct2, u16), MJS_STRUCT_FIELD_TYPE_UINT16, NULL},
{NULL, 0, MJS_STRUCT_FIELD_TYPE_INVALID, NULL},
};
struct my_struct {
struct my_struct2 s;
struct my_struct2 *sp;
};
static const struct mjs_c_struct_member my_struct_descr[] = {
{"s", offsetof(struct my_struct, s), MJS_STRUCT_FIELD_TYPE_STRUCT, my_struct2_descr},
{"sp", offsetof(struct my_struct, sp), MJS_STRUCT_FIELD_TYPE
没有合适的资源?快使用搜索试试~ 我知道了~
mjs:适用于CC ++的嵌入式JavaScript引擎
共227个文件
h:86个
c:64个
js:20个
需积分: 28 1 下载量 105 浏览量
2021-04-05
19:07:45
上传
评论
收藏 1.29MB ZIP 举报
温馨提示
mJS:受限制JavaScript引擎 概述 mJS专为资源有限的微控制器而设计。 主要设计目标是:占地面积小和简单的C / C ++互操作性。 mJS实现了ES6(JavaScript版本6)的严格子集: 任何有效的mJS代码都是有效的ES6代码。 任何有效的ES6代码不一定是有效的mJS代码。 在32位ARM mJS引擎上,需要约50k的闪存和少于1k的RAM(请参阅)。 mJS是一部分,可在其中启用IoT设备的脚本编写。 限制 没有标准库。 没有字符串,数字,RegExp,日期,函数等。 JSON.parse()和JSON.stringify()可用。 没有闭包,只有词法作用域(即允许嵌套函数)。 没有例外。 没有new 。 为了使用自定义原型创建对象,请使用Object.create() 。 仅严格模式。 没有var ,只能let 。 没有for..of , =
资源详情
资源评论
资源推荐
收起资源包目录
mjs:适用于CC ++的嵌入式JavaScript引擎 (227个子文件)
rom.bin 448KB
rom.bin 64KB
rom.bin 64KB
rboot.bin 2KB
mjs.c 423KB
unit_test.c 125KB
frozen.c 45KB
mjs_exec.c 36KB
mjs_ffi.c 34KB
mjs_parser.c 31KB
mg_lwip_net_if.c 24KB
ffi.c 21KB
mjs_string.c 16KB
stub_flasher.c 16KB
esptool2.c 15KB
str_util.c 15KB
sl_net_if.c 14KB
mjs_json.c 14KB
mjs_gc.c 14KB
mjs_util.c 14KB
rboot.c 12KB
mjs_object.c 11KB
mjs_core.c 11KB
sl_fs.c 10KB
pic32_net_if.c 9KB
sl_fs_slfs.c 8KB
mjs_tok.c 8KB
sl_ssl_if.c 8KB
mjs_array.c 6KB
esptool2_elf.c 5KB
mjs_builtin.c 5KB
mg_lwip_ev_mgr.c 5KB
mg_str.c 5KB
mjs_bcode.c 5KB
arm_exc.c 5KB
notes.c 4KB
mbuf.c 4KB
rboot-api.c 4KB
cs_dbg.c 3KB
esp_umm_malloc.c 3KB
mjs_primitive.c 3KB
ffi_test.c 3KB
cs_time.c 3KB
cs_dirent.c 3KB
wince_libc.c 3KB
cc3200_libc.c 3KB
test_util.c 2KB
mjs_conversion.c 2KB
cs_varint.c 2KB
rboot-stage2a.c 2KB
mjs_dataview.c 2KB
mjs_main.c 2KB
cs_file.c 2KB
sl_socket.c 2KB
mbed_libc.c 1KB
esp_crypto.c 1KB
led.c 1KB
sl_mg_task.c 1KB
stub_hello.c 1KB
rboot-bigflash.c 1KB
uart.c 1KB
uart.c 1KB
arm_nsleep100.c 1KB
stub_hello.c 1KB
msp432_libc.c 951B
nrf5_libc.c 861B
windows_direct.c 825B
slip.c 729B
cc3200v1p32.cmd 3KB
rom.elf 510KB
rom.elf 78KB
.gitattributes 32B
.gitattributes 32B
.gitattributes 16B
.gitignore 8B
.gitignore 7B
.gitignore 7B
mjs.h 28KB
frozen.h 11KB
test_util.h 10KB
uart_register.h 6KB
mjs_core_public.h 6KB
str_util.h 6KB
mjs_core.h 5KB
cs_simplelink.h 5KB
platform_windows.h 4KB
platform_wince.h 4KB
platform.h 4KB
mjs_ffi.h 4KB
mjs_object_public.h 4KB
elf.h 3KB
mjs_primitive_public.h 3KB
cs_dbg.h 3KB
mjs_bcode.h 3KB
platform_cc3200.h 3KB
mbuf.h 3KB
mg_str.h 3KB
platform_unix.h 3KB
stub_flasher.h 3KB
rom_functions.h 3KB
共 227 条
- 1
- 2
- 3
HarfMoon
- 粉丝: 17
- 资源: 4560
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0