cesanta / mjs Goto Github PK
View Code? Open in Web Editor NEWEmbedded JavaScript engine for C/C++
Home Page: https://mongoose-os.com
License: Other
Embedded JavaScript engine for C/C++
Home Page: https://mongoose-os.com
License: Other
I try the mJs UART APIs to receive datas on ESP32 uart port.
Data rate: 46 bytes per 20ms, total 23000 bytes in 10s.
There are some performance problems.
let rxAcc = ""; // to store all the bytes received
let rx_total = 0; // total number of received bytes
// Configure UART at 115200 baud
UART.setConfig(1,{
baudRate: 115200,
});
UART.setDispatcher(1, function(uartNo, ud) {
let ra = UART.readAvail(uartNo);
if (ra > 0) {
let data = UART.read(uartNo);
rxAcc += data;
rx_total += data.length;
}
}, null);
// Enable Rx
UART.setRxEnabled(1, true);
UART.write(1,"go"); // signal, a nodejs serialport connected to EPS32 will start
sending data
Timer.set(15000 /* milliseconds */, false /* repeat */, function() {
print("rxAcc lent: "); // =>13150, some datas are lost by rxAcc += data; !!!
print(rxAcc.length);
print("rx_total: "); // =>23000, all the datas are transfered from C to mJs.
print(rx_total);
}, null);
Here, rx_total = 23000 means that all the datas are received and transfered to mJs by mongoose os kernel.
And, rxAcc.length = 13510 means some datas are lost when "rxAcc += data" is executed !!!
If I change the data rate to 46 bytes per 40ms , rxAcc.length = 23000 all the time, no bytes are lost.
If I delete the "rxAcc += data" line, no data will be lost at the MAX data rate: 46 bytes per 7ms, about 52500bps. Code is here:
UART.setDispatcher(1, function(uartNo, ud) { let ra = UART.readAvail(uartNo); if (ra > 0) { let data = UART.read(uartNo); // rxAcc += data; rx_total += data.length; } }, null);
I have tried to tune the rx buffer size to 1024/2048, the same result.
My questions are:
How can I store datas without losing at data rate: 46 bytes per 20ms?
Is 52500bps the TOP speed of mJs UART APIs?
Is there some way to improve the performance of mJs UART APIs?
In old v7 versions there was v7_interrupt in order to
"It sets a flag that will cause the interpreter to throw an InterruptedError"
is this available in mjs or the only way is to invoke internal die()?
i want export function using c code ,because ffi using much rom ,but i'm not find method,like this https://github.com/cesanta/v7/blob/master/examples/call_c_from_js/call_c_from_js.c
Hello!
My experience with Mongoose OS has been great! I'm currently writing an article and I had a thought.
For onboarding of other JS users, it may be helpful to support require
as well as load
. Both could just reference the same function like so:
Line 130 in 49cb625
Does mJs support UART on ESP8266/ESP32?
If it does, How many UART ports can be used on the same ESP32?
any plan to implement array.push() as built in function?
Functions are not considered objects, though in JS everything is an object.
Sample code:
let a = function () {
// stuff
}
// errors out
a.test = {}
Sample stack trace:
MJS error: parse error at line 6: [.test = {}]
Another test:
$ mjs -e '(function(){let a=function(){};a.test={}}())'
at <stdin>:1
at <stdin>:1
MJS error: unsupported object type
Now that SPI support has been added to Mongoose OS. Would it be possible to add the API to mjs. Thanks!
Hello,
I was using American Fuzzy Lop (afl-fuzz) to fuzz input the mjs program on Linux. Is fixing the crashes from these input files something you're interested in? The input files can be found here: https://github.com/rwhitworth/mjs-fuzz/tree/master/2017-05-10. I used mjs compiled from git commit 8fe46f1, as mentioned in issue #32. If there is a better way to compile this for Linux on x86_64 please let me know so I can use the latest version.
The files can be executed as ./mjs id_filename
to cause seg faults.
Let me know if I can provide any more information to help narrow down this issue.
Hi, I'll like help about this;
I like the idea of a interpreter for stm32f100 with 128k of memory ROM.
I tried compiled for this, and I have this problems:
../mJS/mjs.c:1526:20: fatal error: memory.h: No such file or directory
compilation terminated.
Makefile:123: recipe for target 'build/mjs.o' failed
make: *** [build/mjs.o] Error 1
and this is similary for
#include <stm32_sdk_hal.h>
fine, I searched about this (stm32_sdk_hal.h) and I did not get results.
Can you help me, some configuration that i can follow ?
Thank you,
regards.
Johnny
It fails if the code is just ;
. That's valid JS.
I've made a small toy environment for controlling strips of neopixels.
I think I hit a bug in the FFI parser.
With the following JS:
let fade = ffi("void fade(int keep)");
let update = ffi("void update()");
let rgb = ffi("void rgb(int p, int r, int g, int b)");
let rgbl = ffi("void rgbl(int p, int r, int g, int b, int keep)");
let hue = ffi("void hue(int p, int h)");
let msleep = ffi("void msleep(int ms)");
let i = 0;
let j = 0;
while (true) {
hue(i, j);
update();
i = (i + 1) % 10;
j = (j + 13) & 768;
msleep(33);
}
It crashes with the error:
failed to call FFI signature "void hue(int p, int h)": wrong arg type: failed to parse val type "int p"
I don't see any error with this line. I'm using the same syntax and conventions of the other ffi lines that appear to work.
hi,
There is no problem when use mjs. But How can I modify it? e.g. include var keyword, or String functions.
And I find It's hard to debug mjs(the source code is mixed by multi file).
Any information or suggest about this? Thanks.
CPU load almost 100% on mjs manage about 3M memory.
Here is my test code and data, tested on osx x86_64.
load.c
#include "mjs.h"
#include <dlfcn.h>
#include <string.h>
#include <sys/time.h>
int main(int argc, char *argv[])
{
/*
* prepare big object
*/
char strbuf[10000];
int len = 0;
FILE *fp = fopen("./x.json", "r");
if (fp) {
memset(strbuf, 0x0, sizeof(strbuf));
len = fread(strbuf, 1, 10000, fp);
fclose(fp);
printf("read %d bytes from x.json\n", len);
} else {
printf("can't open x.json\n");
return 1;
}
struct mjs *jsm = mjs_create();
mjs_set_ffi_resolver(jsm, dlsym);
mjs_err_t jerr;
mjs_val_t res;
jerr = mjs_exec_file(jsm, "./x.js", &res);
if (jerr != MJS_OK) {
printf("%s\n", mjs_strerror(jsm, jerr));
}
mjs_val_t global = mjs_get_global(jsm);
mjs_val_t object = mjs_get(jsm, global, "myObject", ~0);
mjs_val_t function = mjs_get(jsm, object, "test_func", ~0);
struct timeval total_tvs, total_tve;
gettimeofday(&total_tvs, NULL);
for (int i = 0; i < 100; i++) {
struct timeval tvs, tve;
gettimeofday(&tvs, NULL);
mjs_val_t a1 = mjs_mk_string(jsm, strbuf, len, 0);
jerr = mjs_call(jsm, &res, function, object, 1, a1);
if (jerr != MJS_OK) {
printf("%s", mjs_strerror(jsm, jerr));
}
gettimeofday(&tve, NULL);
//unsigned long ela = (tve.tv_sec - tvs.tv_sec) * 1000000ul + (tve.tv_usec - tvs.tv_usec);
printf("call %d elapsed %d seconds\n", i, tve.tv_sec - tvs.tv_sec);
}
gettimeofday(&total_tve, NULL);
printf("totoal elapsed %d seconds\n", total_tve.tv_sec - total_tvs.tv_sec);
mjs_destroy(jsm);
return 0;
}
x.js
let myObject = {
arrs: [],
test_func: function(orders) {
this.arrs[this.arrs.length] = JSON.parse(orders);
//JSON.parse(orders);
//print(orders);
print(this.arrs.length);
}
};
x.json
{"orders":[{"type_desc":"已买入","count":2000,"price":460000,"type":4,"bid":true,"channel":"CXA","code":"OCC","id":"36C8E003"},{"type_desc":"已买入","count":2000,"price":320000,"type":4,"bid":true,"channel":"CXA","code":"DRM","id":"37CBE003"},{"type_desc":"已买入","count":2000,"price":500000,"type":4,"bid":true,"channel":"CXA","code":"AWE","id":"10CDE003"},{"type_desc":"已卖出","count":2000,"price":325000,"type":5,"bid":false,"channel":"CXA","code":"DRM","id":"20CEE003"},{"type_desc":"委托买入","count":2000,"price":250000,"type":1,"bid":true,"channel":"CXA","code":"BLG","id":"31D0E003"},{"type_desc":"委托买入","count":2000,"price":440000,"type":1,"bid":true,"channel":"CXA","code":"BIG","id":"57D0E003"},{"type_desc":"取消委托","count":2000,"price":465000,"type":3,"bid":false,"channel":"CXA","code":"OCC","id":"80D0E003"},{"type_desc":"已买入","count":10000,"price":95000,"type":4,"bid":true,"channel":"CXA","code":"FGR","id":"B6D0E003"},{"type_desc":"已卖出","count":2000,"price":460000,"type":5,"bid":false,"channel":"CXA","code":"OCC","id":"97D1E003"},{"type_desc":"已买入","count":2000,"price":320000,"type":4,"bid":true,"channel":"CXA","code":"DRM","id":"FBD1E003"},{"type_desc":"已卖出","count":324,"price":325000,"type":5,"bid":false,"channel":"CXA","code":"DRM","id":"8CD2E003"},{"type_desc":"已卖出","count":1676,"price":325000,"type":5,"bid":false,"channel":"CXA","code":"DRM","id":"2ED3E003"},{"type_desc":"已买入","count":2000,"price":320000,"type":4,"bid":true,"channel":"CXA","code":"DRM","id":"CED3E003"},{"type_desc":"已买入","count":2000,"price":450000,"type":4,"bid":true,"channel":"CXA","code":"OCC","id":"DDD3E003"},{"type_desc":"已买入","count":2000,"price":455000,"type":4,"bid":true,"channel":"CXA","code":"OCC","id":"F2D4E003"},{"type_desc":"已卖出","count":2000,"price":460000,"type":5,"bid":false,"channel":"CXA","code":"OCC","id":"40D6E003"},{"type_desc":"已卖出","count":2000,"price":455000,"type":5,"bid":false,"channel":"ASXT","code":"OCC","id":"44D7E003"},{"type_desc":"委托买入","count":1250,"price":450000,"type":1,"bid":true,"channel":"CXA","code":"OCC","id":"4AD7E003"},{"type_desc":"委托买入","count":2000,"price":310000,"type":1,"bid":true,"channel":"CXA","code":"LBT","id":"9AD8E003"},{"type_desc":"委托买入","count":2000,"price":415000,"type":1,"bid":true,"channel":"CXA","code":"PLS","id":"A7D8E003"},{"type_desc":"已买入","count":2000,"price":685000,"type":4,"bid":true,"channel":"CXA","code":"MMJ","id":"AADAE003"},{"type_desc":"已买入","count":2000,"price":2570000,"type":4,"bid":true,"channel":"CXA","code":"WAM","id":"83DCE003"},{"type_desc":"已买入","count":2000,"price":165000,"type":4,"bid":true,"channel":"CXA","code":"SCU","id":"4EE1E003"},{"type_desc":"取消委托","count":2000,"price":805000,"type":3,"bid":true,"channel":"CXA","code":"AC8","id":"75E1E003"},{"type_desc":"已买入","count":2000,"price":800000,"type":4,"bid":true,"channel":"CXA","code":"AC8","id":"96E3E003"},{"type_desc":"取消委托","count":2000,"price":690000,"type":3,"bid":false,"channel":"CXA","code":"MMJ","id":"A2E4E003"},{"type_desc":"已买入","count":2000,"price":675000,"type":4,"bid":true,"channel":"CXA","code":"MMJ","id":"E9E4E003"},{"type_desc":"已卖出","count":2000,"price":685000,"type":5,"bid":false,"channel":"CXA","code":"MMJ","id":"6DE5E003"},{"type_desc":"取消委托","count":7400,"price":96000,"type":3,"bid":false,"channel":"CXA","code":"FGR","id":"1FF4E003"},{"type_desc":"已卖出","count":2000,"price":805000,"type":5,"bid":false,"channel":"CXA","code":"AC8","id":"4DF4E003"},{"type_desc":"已买入","count":2000,"price":800000,"type":4,"bid":true,"channel":"CXA","code":"AC8","id":"A7FDE003"},{"type_desc":"已买入","count":2000,"price":680000,"type":4,"bid":true,"channel":"CXA","code":"MMJ","id":"6FFEE003"},{"type_desc":"取消委托","count":2000,"price":775000,"type":3,"bid":true,"channel":"CXA","code":"AC8","id":"ABFFE003"},{"type_desc":"委托买入","count":2000,"price":770000,"type":1,"bid":true,"channel":"CXA","code":"AC8","id":"D8FFE003"},{"type_desc":"已卖出","count":2000,"price":790000,"type":5,"bid":false,"channel":"CXA","code":"AC8","id":"E5FFE003"},{"type_desc":"取消委托","count":2000,"price":685000,"type":3,"bid":false,"channel":"CXA","code":"MMJ","id":"AD00E103"},{"type_desc":"已卖出","count":2000,"price":680000,"type":5,"bid":false,"channel":"CXA","code":"MMJ","id":"E300E103"},{"type_desc":"取消委托","count":2000,"price":680000,"type":3,"bid":false,"channel":"CXA","code":"MMJ","id":"F104E103"},{"type_desc":"已买入","count":500,"price":25000,"type":4,"bid":true,"channel":"ASXT","code":"AGO","id":"1D05E103"},{"type_desc":"取消委托","count":500,"price":26000,"type":3,"bid":false,"channel":"CXA","code":"AGO","id":"2405E103"},{"type_desc":"取消委托","count":10000,"price":96000,"type":3,"bid":false,"channel":"CXA","code":"FGR","id":"2B05E103"},{"type_desc":"取消委托","count":500,"price":25000,"type":3,"bid":false,"channel":"CXA","code":"AGO","id":"F805E103"},{"type_desc":"已买入","count":2000,"price":780000,"type":4,"bid":true,"channel":"CXA","code":"AC8","id":"190BE103"},{"type_desc":"取消委托","count":2000,"price":170000,"type":3,"bid":false,"channel":"CXA","code":"SCU","id":"840CE103"},{"type_desc":"取消委托","count":2000,"price":502500,"type":3,"bid":false,"channel":"CXAM","code":"AWE","id":"FE0FE103"},{"type_desc":"已买入","count":3000,"price":495000,"type":4,"bid":true,"channel":"CXA","code":"AWE","id":"EF10E103"},{"type_desc":"取消委托","count":2000,"price":500000,"type":3,"bid":true,"channel":"CXA","code":"AWE","id":"FC10E103"},{"type_desc":"已卖出","count":1254,"price":505000,"type":5,"bid":false,"channel":"CXA","code":"AWE","id":"1012E103"},{"type_desc":"已卖出","count":2000,"price":165000,"type":5,"bid":false,"channel":"CXA","code":"SCU","id":"C915E103"},{"type_desc":"已买入","count":2000,"price":405000,"type":4,"bid":true,"channel":"CXA","code":"ESE","id":"1217E103"},{"type_desc":"取消委托","count":2000,"price":410000,"type":3,"bid":false,"channel":"CXA","code":"ESE","id":"A117E103"},{"type_desc":"取消委托","count":2000,"price":385000,"type":3,"bid":true,"channel":"CXA","code":"ESE","id":"AA17E103"},{"type_desc":"取消委托","count":2000,"price":395000,"type":3,"bid":false,"channel":"CXA","code":"ESE","id":"D317E103"},{"type_desc":"取消委托","count":1494,"price":410000,"type":3,"bid":false,"channel":"CXA","code":"ESE","id":"EA17E103"},{"type_desc":"取消委托","count":1494,"price":405000,"type":3,"bid":false,"channel":"ASXT","code":"ESE","id":"F117E103"},{"type_desc":"取消委托","count":1494,"price":395000,"type":3,"bid":false,"channel":"CXA","code":"ESE","id":"F717E103"},{"type_desc":"取消委托","count":1494,"price":390000,"type":3,"bid":false,"channel":"CXA","code":"ESE","id":"0618E103"},{"type_desc":"取消委托","count":1494,"price":405000,"type":3,"bid":false,"channel":"ASXT","code":"ESE","id":"2218E103"},{"type_desc":"取消委托","count":1494,"price":390000,"type":3,"bid":false,"channel":"CXA","code":"ESE","id":"3018E103"},{"type_desc":"已卖出","count":1494,"price":395000,"type":5,"bid":false,"channel":"ASXT","code":"ESE","id":"3E18E103"},{"type_desc":"已买入","count":2000,"price":400000,"type":4,"bid":true,"channel":"ASXT","code":"ESE","id":"FC20E103"},{"type_desc":"已买入","count":2000,"price":775000,"type":4,"bid":true,"channel":"ASXT","code":"CPH","id":"D621E103"},{"type_desc":"取消委托","count":2000,"price":770000,"type":3,"bid":true,"channel":"CXA","code":"CPH","id":"D821E103"},{"type_desc":"已卖出","count":2000,"price":780000,"type":5,"bid":false,"channel":"CXA","code":"CPH","id":"4322E103"},{"type_desc":"委托卖出","count":10000,"price":95000,"type":2,"bid":false,"channel":"CXA","code":"FGR","id":"9C22E103"},{"type_desc":"取消委托","count":2000,"price":775000,"type":3,"bid":true,"channel":"CXA","code":"CPH","id":"2824E103"},{"type_desc":"取消委托","count":2000,"price":2575000,"type":3,"bid":false,"channel":"CXAM","code":"WAM","id":"7E25E103"},{"type_desc":"已卖出","count":2000,"price":2570000,"type":5,"bid":false,"channel":"CXA","code":"WAM","id":"0926E103"},{"type_desc":"已卖出","count":2000,"price":785000,"type":5,"bid":false,"channel":"CXA","code":"AC8","id":"7426E103"},{"type_desc":"委托卖出","count":500,"price":24000,"type":2,"bid":false,"channel":"CXA","code":"AGO","id":"3127E103"},{"type_desc":"已卖出","count":2000,"price":325000,"type":5,"bid":false,"channel":"CXA","code":"DRM","id":"B42BE103"},{"type_desc":"未知类型","count":10000,"price":990000,"type":0,"bid":true,"channel":"CXA","code":"PAI","id":"212DE103"},{"type_desc":"取消委托","count":2000,"price":675000,"type":3,"bid":false,"channel":"CXA","code":"MMJ","id":"C12EE103"},{"type_desc":"取消委托","count":2000,"price":670000,"type":3,"bid":false,"channel":"CXA","code":"MMJ","id":"B72FE103"},{"type_desc":"已卖出","count":2000,"price":665000,"type":5,"bid":false,"channel":"CXA","code":"MMJ","id":"0431E103"},{"type_desc":"委托买入","count":2000,"price":660000,"type":1,"bid":true,"channel":"CXA","code":"MMJ","id":"BE31E103"},{"type_desc":"委托买入","count":2000,"price":320000,"type":1,"bid":true,"channel":"CXA","code":"DRM","id":"2233E103"},{"type_desc":"委托卖出","count":3000,"price":497500,"type":2,"bid":false,"channel":"CXAM","code":"AWE","id":"FD33E103"},{"type_desc":"委托买入","count":2000,"price":765000,"type":1,"bid":true,"channel":"ASXT","code":"CPH","id":"5236E103"},{"type_desc":"委托卖出","count":2000,"price":405000,"type":2,"bid":false,"channel":"ASXT","code":"ESE","id":"8636E103"}]}
Here is the output:
read 9705 bytes from x.json
1
call 0 elapsed 0 seconds
2
call 1 elapsed 0 seconds
3
call 2 elapsed 0 seconds
4
call 3 elapsed 0 seconds
5
call 4 elapsed 0 seconds
6
call 5 elapsed 0 seconds
7
call 6 elapsed 0 seconds
8
call 7 elapsed 0 seconds
9
call 8 elapsed 0 seconds
10
call 9 elapsed 0 seconds
11
call 10 elapsed 0 seconds
12
call 11 elapsed 0 seconds
13
call 12 elapsed 0 seconds
14
call 13 elapsed 0 seconds
15
call 14 elapsed 0 seconds
16
call 15 elapsed 1 seconds
17
call 16 elapsed 0 seconds
18
call 17 elapsed 0 seconds
19
call 18 elapsed 0 seconds
20
call 19 elapsed 1 seconds
21
call 20 elapsed 0 seconds
22
call 21 elapsed 0 seconds
23
call 22 elapsed 1 seconds
24
call 23 elapsed 0 seconds
25
call 24 elapsed 0 seconds
26
call 25 elapsed 0 seconds
27
call 26 elapsed 1 seconds
28
call 27 elapsed 1 seconds
29
call 28 elapsed 1 seconds
30
call 29 elapsed 1 seconds
31
call 30 elapsed 1 seconds
32
call 31 elapsed 1 seconds
33
call 32 elapsed 1 seconds
34
call 33 elapsed 1 seconds
35
call 34 elapsed 0 seconds
36
call 35 elapsed 1 seconds
37
call 36 elapsed 1 seconds
38
call 37 elapsed 1 seconds
39
call 38 elapsed 1 seconds
40
call 39 elapsed 1 seconds
41
call 40 elapsed 1 seconds
42
call 41 elapsed 4 seconds
43
call 42 elapsed 5 seconds
44
call 43 elapsed 3 seconds
45
call 44 elapsed 4 seconds
46
call 45 elapsed 3 seconds
47
call 46 elapsed 2 seconds
48
call 47 elapsed 3 seconds
49
call 48 elapsed 1 seconds
50
call 49 elapsed 1 seconds
51
call 50 elapsed 1 seconds
52
call 51 elapsed 2 seconds
53
call 52 elapsed 4 seconds
54
call 53 elapsed 2 seconds
55
call 54 elapsed 1 seconds
56
call 55 elapsed 1 seconds
57
call 56 elapsed 3 seconds
58
call 57 elapsed 3 seconds
59
call 58 elapsed 3 seconds
60
call 59 elapsed 1 seconds
61
call 60 elapsed 2 seconds
62
call 61 elapsed 4 seconds
63
call 62 elapsed 10 seconds
64
call 63 elapsed 7 seconds
65
call 64 elapsed 8 seconds
66
call 65 elapsed 8 seconds
67
call 66 elapsed 9 seconds
68
call 67 elapsed 13 seconds
69
call 68 elapsed 7 seconds
70
call 69 elapsed 2 seconds
71
call 70 elapsed 2 seconds
72
call 71 elapsed 4 seconds
73
call 72 elapsed 6 seconds
74
call 73 elapsed 4 seconds
75
call 74 elapsed 2 seconds
76
call 75 elapsed 3 seconds
77
call 76 elapsed 4 seconds
78
call 77 elapsed 7 seconds
79
call 78 elapsed 5 seconds
80
call 79 elapsed 2 seconds
81
call 80 elapsed 3 seconds
82
call 81 elapsed 5 seconds
83
call 82 elapsed 8 seconds
84
call 83 elapsed 6 seconds
85
call 84 elapsed 2 seconds
86
call 85 elapsed 3 seconds
87
call 86 elapsed 6 seconds
88
call 87 elapsed 9 seconds
89
call 88 elapsed 6 seconds
90
call 89 elapsed 3 seconds
91
call 90 elapsed 4 seconds
92
call 91 elapsed 6 seconds
93
call 92 elapsed 14 seconds
94
call 93 elapsed 17 seconds
95
call 94 elapsed 19 seconds
96
call 95 elapsed 18 seconds
97
call 96 elapsed 20 seconds
98
call 97 elapsed 25 seconds
99
call 98 elapsed 20 seconds
100
call 99 elapsed 20 seconds
totoal elapsed 387 seconds
My load:
PID COMMAND %CPU TIME #TH #WQ #POR MEM PURG CMPR PGRP PPID STATE BOOSTS %CPU_ME %CPU_OTHRS UID FAULT COW MSGS MSGR SYSB SYSM CSW PAGE IDLE POWE
4750 load 98.8 01:27.67 1/1 0 10 2240K 0B 0B 4750 978 running *0[1] 0.00000 0.00000 501 1310 126 36 15 110 63 72816+ 0 0 98.8
I am writing up the grammar for mjs. While doing so I discovered that a parenthesized expression as a literal does not correctly check for a closing parenthesis. Any character seems to work fine:
$ mjs -e '(123+5]+6'
yields 134 without a syntax error.
say this code:
#include "mjs.h"
#include <dlfcn.h>
#include <limits.h>
int main(int argc, char *argv[])
{
struct mjs *jsm = mjs_create();
mjs_set_ffi_resolver(jsm, dlsym);
mjs_err_t jerr;
mjs_val_t res;
jerr = mjs_exec_file(jsm, argv[1], &res);
if (jerr != MJS_OK) {
printf("js file error %s\n", mjs_strerror(jsm, jerr));
return 1;
}
for (int i = 0 ; i < 3; i++) {
mjs_val_t obj = mjs_get(jsm, mjs_get_global(jsm), "obj", ~0);
mjs_val_t f1 = mjs_get(jsm, obj, "f1", ~0);
jerr = mjs_call(jsm, &res, f1, obj, 1, mjs_mk_number(jsm, 212));
if (jerr != MJS_OK) {
printf("%s\n", mjs_strerror(jsm, jerr));
}
if (i == 1) {
obj = mjs_get(jsm, mjs_get_global(jsm), "obj", ~0);
f1 = mjs_get(jsm, obj, "funexist", ~0);
jerr = mjs_call(jsm, &res, f1, obj, 1, mjs_mk_number(jsm, 212));
if (jerr != MJS_OK) {
printf("%s\n", mjs_strerror(jsm, jerr));
}
}
}
return 0;
}
With the follow x.js
let obj = {
arr: []
f1: function(a) {
this.arr[this.arr.length] = a;
//print('first ' + a);
print(JSON.stringify(this.arr));
}
};
Output:
maliang@bogon ~/code/mjs/mjs/tests$ gcc -std=c99 -o x x.c -I ../../ -L ../build/ -lmjs
maliang@bogon ~/code/mjs/mjs/tests$ ./x x.js
[212]
[212,212]
[212]
There are 3 problems:
parse x.js arr: []
whithout ,
terminate don't return error.
call an unexist method funexist
don't return error.
After funexist
called, obj.arr[] reseted to empty.
Just a remind, mjs ffi dlsym can't resolve funciton on mac osx.
After modify these lines in mjs/ffi.c , turns ok.
#ifndef RTLD_DEFAULT
#if defined(__APPLE__)
#define RTLD_DEFAULT ((void *) -2)
#else
#define RTLD_DEFAULT NULL
#endif
#endif
Hi. mjs.c
seems to be generated/combined from many individual .c
files.
Is the non-amalgated source available anywhere, or do you have plans to provide this?
SequenceExpressions (i.e. comma-separated expressions) are used as a minification strategy in most minifiers (i.e. babili, uglifyjs) but they cause mjs to error out:
// this is valid javascript
print('1'),print('2')
// should result in:
// 1
// 2
^ this causes mjs to error out at runtime: MJS error: parse error at line 1: [,print('2']
This specific case can be solved by using a semicolon instead of a comma, but this doesn't work for when a minifier uses a sequence expression in a return statement.
I understand the goal of being a restricted JS engine, but parser support for sequence expressions would be very useful for reserving space in mos firmwares that use mjs. By running my firmware through a minifier first, I can improve performance and squeeze more code into the microcontroller.
It seems that at build time, when uses of ffi()
are searched for in the JS code, the search also checks comments.
For instance, the following code can cause the build to error out:
// just to kill things: ffi('void non-existent-function(double)')
Which means that when debugging, if I want to comment out the ffi()
use, I have to change the name of the function to ffi_
or anything else - I can't just comment it out.
Perhaps the defining of ffi_exports
can be moved into a header file (i.e. main.h
) or through main.c
since they are converted to C anyways during the build process. Having the build process pull it out of the JS can lead to other issues as well and gives the illusion of dynamic interoperability - which isn't really the case anyways.
I use mjs on linux x86 64. My appilication has 1M max size string. Seems works fine after enlarge this macro. Is there any other limits on mjs for larger memory system? e.g. object prop key size, array size, js source file size...
i put mjs.h and mjs.c into a empty project ,define MARCO #define CS_PLATFORM CS_P_STM32
in mjs.h.
then compile the project by arm-none-eabi-gcc,the code is very large.
'Invoking: Cross ARM GNU Print Size'
arm-none-eabi-size --format=berkeley "test.elf"
text data bss dec hex filename
110796 2772 356 113924 1bd04 test.elf
Finished building: test.siz
the compile command is
arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -O0 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections --specs=nosys.specs -g3 -T "D:\workspace\test\START\stm32_flash.ld" -Xlinker --gc-sections -Wl,-Map,"test.map" -o "test.elf" ./mjs/mjs.o ./USER/io.o ./USER/main.o ./USER/uart.o ./START/startup/startup_stm32f10x_md.o ./START/system_stm32f10x.o ./LIB/stm32f10x_gpio.o ./LIB/stm32f10x_rcc.o ./LIB/stm32f10x_tim.o ./LIB/stm32f10x_usart.o ./CMSIS/core_cm3.o
mkdir -p build
clang -lm -W -Wall -g -I. -I.. -Isrc -DMJS_MAIN -DMJS_EXPOSE_PRIVATE -DCS_ENABLE_STDIO -DMJS_ENABLE_DEBUG -DCS_MMAP -Wl,--no-as-needed -ldl src/../../common/cs_dbg.c src/../../common/cs_file.c src/../../common/cs_varint.c src/../../common/mbuf.c src/../../common/str_util.c src/../../frozen/frozen.c src/ffi/ffi.c src/mjs_array.c src/mjs_bcode.c src/mjs_builtin.c src/mjs_conversion.c src/mjs_core.c src/mjs_dataview.c src/mjs_exec.c src/mjs_ffi.c src/mjs_gc.c src/mjs_json.c src/mjs_main.c src/mjs_object.c src/mjs_parser.c src/mjs_primitive.c src/mjs_string.c src/mjs_tok.c src/mjs_util.c -o build/mjs
In file included from src/../../common/cs_dbg.c:13:
../common/str_util.h:13:10: fatal error: 'common/mg_str.h' file not found
#include "common/mg_str.h"
^
1 error generated.
let s = "hello";
print(s); // => hello
print(s.length); // => mgos_app_init MJS exec error: type error
s.length throws MJS exec error: type error.
=> means outputs
Just for fun, I decided to see if I can bind to various libuv functions to make a really light-weight node.js.
As a test, I tried one of the simpler functions:
int uv_exepath(char* buffer, size_t* size)
At a high level, this takes no arguments and returns a string, but this is C and memory management is hard in C.
In JavaScript I'd ideally have a function like this:
let path = exepath();
I wrote something that works, but it leaks memory and is ugly.
// Wrapper function in C
char* exepath() {
size_t size = 2*PATH_MAX;
char exe_path[2*PATH_MAX];
int ret = uv_exepath(exe_path, &size);
if (ret < 0) return "[error]";
exe_path[size] = 0;
char* path = malloc(size + 1);
for (int i = 0; i < size; i++) {
path[i] = exe_path[i];
}
path[size] = 0;
return path;
}
let exepath = ffi("char *exepath()");
What are the rules about returning strings from C and how does ownership work? In all the scripting languages I've ever worked with before, the C code lends a buffer which the VM copies into itself and manages using the GC. The C code then has ownership of the original again.
I don't see any way to do this here? Does this language engine simply not care about strings in this manner?
New mjs code, under osx, This is my test.js
let o = {
s: '',
x: function(str) {
this.s = str;
print(this.s);
},
};
o.x('hello mjs');
maliang@bogon ~/code/mjs/mjs$ ./build/mjs tests/y.js
Assertion failed: (top >= 4 && (top % 4) == 0), function mjs_get_this_for_js_call, file src/mjs_exec.c, line 39.
Abort trap: 6
for example, I wan't to trace messages on js side.
How can I import printf into mjs, or, any other solution to pass variable number of arguments to c code?
On conditional express, such as if (expa && expb)
, if expa is false, expb should not be excuted.
for example:
maliang@bogon ~/code/mjs/mjs$ ./build/mjs -e "let a = 1, b = 2; if (a > 1 && (b = b+1) > 2) print(a); print(b)"
3
undefined
b
should not add 1
I use mg_base64_decode to do base64 decode work on ESP32.
let n = ffi('int mg_base64_decode(void *, int, void *)')(src, len, dst);
when n < 1580, It can work.
when n >1580, It will crash:
ERROR: wrong bcode offset 18443
at :1
MJS callback error: implicit type conversion is prohibited
lemonhall@HalldeMacBook-Pro:~/Downloads/mjs/mjs$ make
Makefile:87: ../common.mk: No such file or directory
make: *** No rule to make target `../common.mk'. Stop.
lemonhall@HalldeMacBook-Pro:~/Downloads/mjs/mjs$
i am getting errors building it on visual studio 2017?
has anyone compiled it on windows?
hello, i would like to integrate mjs into my firmware but i can not understand how to do it. I tried to include the sources but I can not compile. thank you
Say I need to pop out an item from an array, Since there is no prototypes for Array, I couldn't use array.prototype.pop() to do this.
I notice that there is a function mjs_op_getprop() nearly to it. So, Can I write my own pop
properity for array val? This function is used to get valriable(push an val to &vm->dstack), not for just modify Array. I couldn't make sure is it properly?
BTW, I use array[array.length] = newitem to performe array.push(newitem), It should be more user friendly if i extended the later way.
Can't find the js example for interate over array or object, how to do this?
Is there any function to trace the js execution error, like v7_printf_error() in v7?
I use mjs_str_error() currently, and it's output isn't readable as much as v7_printf_error(), especially error occured with in multipile js files.
Here is my test js files:
1.js
let x = {
floor: ffi('double floor(double)'),
floor2: ffi('double floor_unexist(double)')
};
2.js
load("tests/1.js")
let y = {
foo: function(n) {
return x.floor(n);
},
foo2: function(n) {
return x.floor2(n);
}
};
y.foo(12.3);
y.foo2(12.3);
Here is the error output:
maliang@bogon ~/code/mjs/mjs$ ./build/mjs tests/2.js
at tests/2.js:8
at tests/2.js:14
undefined
There are 3 main problem:
tests/1.js
not appeared in error string.failed to call FFI...
)BTW, If I have some spell mistake in 1.js. e.g.:
let x = {
floor: ffi('double floor(double)');
floor2: ffi('double floor_unexist(double)')
};
Error trace message can't totoaly understood.
maliang@bogon ~/code/mjs/mjs$ ./build/mjs tests/2.js
at tests/2.js:1
undefined
If i use mjs_strerror(mjs, res) instead of mjs_strerror(mjs, mjs->error):
at tests/2.js:1
NO_ERROR
undefined
As mentioned on title, tested under osx and x86_64 linux.
Here is my exe.c
#include <dlfcn.h>
#include "mjs.h"
int main(int argc, char *argv[])
{
if (argc < 2) {
printf("useage: %s js file\n", argv[0]);
return 1;
}
struct mjs *jsm = mjs_create();
mjs_set_ffi_resolver(jsm, dlsym);
mjs_err_t jserr;
mjs_val_t res;
jserr = mjs_exec_file(jsm, argv[1], &res);
if (jserr != MJS_OK) {
printf("%s\n", mjs_strerror(jsm, jserr));
}
mjs_println(jsm, res);
return 0;
}
And there are two js file: 1.js, 2.js
let x = '{"a":1,"b":1,"c":1,"d":1,"e":1,"f":1,"g":1,"h":1,"i":1,"j":1,"k":1,"l":1,"m":1,"n":1,"o":1,"p":1,"q":1,"r":1,"s":1,"t":1}';
let xo = JSON.parse(x);
let x = '{"a":1,"b":1,"c":1,"d":1,"e":1,"f":1,"g":1,"h":1,"i":1,"j":1,"k":1,"l":1,"m":1,"n":1,"o":1,"p":1,"q":1,"r":1,"s":1,"t":1, "u": 1}';
let xo = JSON.parse(x);
Here is the output:
maliang@bogon ~/tmp/x/mjs$ ./exec 1.js
[object Object]
maliang@bogon ~/tmp/x/mjs$ ./exec 2.js
invalid JSON string
undefined
When I use cc mjs.c -DMJS_MAIN -D_DARWIN_C_SOURCE -o mjsexec, and the later js work ok when it is the command parameter
maliang@bogon ~/tmp/x/mjs$ ./mjsexec -e "let x = '{"a":1,"b":1,"c":1,"d":1,"e":1,"f":1,"g":1,"h":1,"i":1,"j":1,"k":1,"l":1,"m":1,"n":1,"o":1,"p":1,"q":1,"r":1,"s":1,"t":1, "u":1,"v":1}'; let xo = JSON.parse(x)"
[object Object]
I had some trouble running the unit tests to all PASS.
This is on a Centos 6 32-bit machine. I discovered that it is best to use -rdynamic as extra
CFLAGS in the Makefile. Also, I extended the typedefs in ffi.c to include the 2 and 3 argument cases
and added explicit code to detect and handle them. The problem I was seeing that f(int, double)
was not handled correctly and gave me wrong argument values.
Surprisingly, on a Centos x86_64 none of these problems occurred.
I'm working on STM32F103C8 (Blue-Pill) and am unable to understand the basics of callbacks, at least so it seems since I don't get the expected results.
Here is my C code, just a simple callback test:
void (*my_callback)(int, void *);
void *my_user_data;
void timer(int seconds, void (*callback)(int, void *), void *user_data) {
my_callback = callback;
my_user_data = user_data;
}
void *my_dlsym(void *handle, const char *name) {
if (strcmp(name, "timer") == 0)
return (void *) timer;
return NULL;
}
int main() {
...
struct mjs *mjs = mjs_create();
mjs_set_ffi_resolver(mjs, my_dlsym);
mjs_exec(mjs, APP_JS, NULL);
int j = 0;
while (1) {
for (uint32_t i = 0; i < 0xFFFFFF; i++) {
asm("nop");
}
my_callback(++j, my_user_data);
}
}
And a little JS:
let Timer = {
set: ffi('void timer(int, void (*)(int, userdata), userdata)')
};
Timer.set(200, function(t) {
print('Time now: ', t);
}, null);
print('JS is initialized');
Console output:
JS is initialized
Time now: ld <-- this repeats, but actually should be counting up from 0
Also maybe the relevant build options:
Building file: ../3rdparty/mjs.c
Invoking: GNU ARM Cross C Compiler
arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -O0 -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -flto -g -DSTM32F103xB -DMG_ENABLE_FILESYSTEM=0 -DCS_PLATFORM=CS_P_STM32 -DHSE_VALUE=8000000U -I"/home/ivan/eclipse-workspace/blue-squirrel/3rdparty/CMSIS/Include" -I"/home/ivan/eclipse-workspace/blue-squirrel/include" -I"/home/ivan/eclipse-workspace/blue-squirrel/3rdparty/CMSIS/Device/ST/STM32F1xx/Include" -std=gnu11 -MMD -MP -MF"3rdparty/mjs.d" -MT"3rdparty/mjs.o" -c -o "3rdparty/mjs.o" "../3rdparty/mjs.c"
Finished building: ../3rdparty/mjs.c
Also I had to remove two lines in the condensed mjs.c file, since it didn't work with them:
Line 2200: #include <dirent.h> --> #error "<dirent.h> not supported"
Line 1528: #include <stm32_sdk_hal.h> --> Not using it, not required, I do the low level stuff myself
Any help is apprechiated, thx for this great project btw.
mjs will not compile any more as a library with mongoose-os mos tool on esp8266
the compillation-error output boils down to these lines around the new changes:
In function 'mjs_fprintf':
/tmp/fwbuild-volumes/users/test/esp8266mos_rebuild/build_requests/build_req_065270790/modules/mjs/mjs.c:12534:7: error: array subscript has type 'char' [-Werror=char-subscripts]
if (isprint(s[i])) {
^
am i doing something wrong?
~/.mos/bin/mos update
Up to date.
$proj/mos.yml:
author: Daniel Jürgen
description: Just a mos-project
version: 0.5.7
arch: esp8266
mongoose_os_version: master
tags:
Hello! I'm trying to bind this c function:
void sc_register_callback(void (*_callback)(char *)){
}
with mjs like so:
ffi('void sc_register_callback(void (*)(char *))')
but mjs keeps asking about userdata arg:
MJS error: failed to exec file "api_websocket.js": bad ffi signature: "void sc_register_callback(void (*)(char ))": bad ffi signature: "void ()(char *)": no userdata arg
this is a great project , i want deep learn this code ,but Very few lines of code,How to split header file and source file into some single file.
I hope to have nothing to do with the platform, like Lua, do not rely too much on the library.
Here is the test case:
./build/mjs -e "let y = {foo: function(s){return s}, foo2: function(){y.foo('xxx' + 10)}}; y.foo2();"
at <stdin>:1
at <stdin>:1
ERROR: wrong bcode offset -2147483648
at <unknown-filename>:1
Error: TYPE_ERROR
This is the js file in pretty format:
let y = {
foo: function(s) {
return s;
},
foo2: function() {
return y.foo('xxx' + 10);
}
};
y.foo2();
let s = "hello";
print(s); // => hello
print(s.length); // =>5
let b = s.slice(1,3); // => mgos_app_init MJS exec error: type error
print(b); // => nothing output
Today, when I build my mos project, I get much more ffi_exports.c erros, like this:
/app/build/gen/ffi_exports.c:146:6: error: conflicting types for 'mgos_conf_value_type'
int mgos_conf_value_type(void *);
^
/app/build/gen/ffi_exports.c:145:6: note: previous declaration of 'mgos_conf_value_type' was here
void mgos_conf_value_type(void);
The mos project can be built some days ago.
I have updated the mos tool.
I'm trying to implement mjs into my own os called RossOS, and I'm just getting reboots and page faults.
./build/mjs -e "let x = [{'f': 1}, {'f':2}, {'f':3}]; x.splice(1,0, {'f': 100}); print(JSON.stringify(x));"
[{"f":1},{"f":100},null,{"f":3}]
undefined
{'f': 2}
not moved to new position.
init.js:
let floor = ffi('double floor(double)');
print(floor(1.23456));
mgos_app_init MJS exec error: failed to call FFI signature "double floor(double)": cannot resolve function �
Hi, mJS looks very promising, running it on quite restricted micro (STM32L0)!
But I have some problems with using arrays.
let a=[2,3,4];
print(a[1]);
The elements seem to have a strange type... is it float? It can't access them properly (sometimes stalls my micro, need to investigate)...
Are there any examples for the use of arrays with mJS already?
Example from the documentation:
let printf = ffi('int printf(char *, int, char *)');
printf('Hi %d %s\n', 123, 'foo');
Result: MJS callback error: failed to call FFI signature "int printf(char *, int, char *)": cannot resolve function � : failed to call FFI signature "int printf(char *, int, char *)": cannot resolve function m : failed to call FFI signature "int printf(char *, int, char *)": cannot resolve function } : failed to call FFI signature "int printf(char *, int, char *)": cannot resolve function �
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.