1 #include "amp_config.h"
2 #include "aos/list.h"
3 #include "aos_system.h"
4 #include "quickjs-libc.h"
5 #include "quickjs.h"
6 #include "quickjs_addon.h"
7 #include <stdbool.h>
8 #include <stdint.h>
9 #include <stdio.h>
10 #include <string.h>
11 
12 #define MOD_STR "QUICKJS_INIT"
13 
14 static JSRuntime *rt = NULL;
15 static JSContext *ctx = NULL;
16 static JSValue val;
17 
18 extern int g_repl_config;
19 extern JSModuleDef *quickjs_module_loader(JSContext *ctx, const char *module_name, void *opaque);
20 
js_get_context(void)21 JSContext *js_get_context(void)
22 {
23     return ctx;
24 }
25 
jsengine_register_addons()26 static void jsengine_register_addons()
27 {
28     module_builtin_register();
29 #if 1
30     extern uint32_t jslib_events_size;
31     extern uint8_t jslib_events[];
32     quickjs_add_prebuild_module("events", jslib_events, jslib_events_size);
33 #endif
34 #ifdef JSE_HW_ADDON_GPIO
35     module_gpio_register();
36     extern uint32_t jslib_gpio_size;
37     extern uint8_t jslib_gpio[];
38     quickjs_add_prebuild_module("gpio", jslib_gpio, jslib_gpio_size);
39 #endif
40 
41 #ifdef JSE_HW_ADDON_IR
42     module_ir_register();
43 #endif
44 
45 #ifdef JSE_HW_ADDON_PWM
46     module_pwm_register();
47     extern uint32_t jslib_pwm_size;
48     extern uint8_t jslib_pwm[];
49     quickjs_add_prebuild_module("pwm", jslib_pwm, jslib_pwm_size);
50 #endif
51 
52 #ifdef JSE_HW_ADDON_ONEWIRE
53     module_onewire_register();
54     extern uint32_t jslib_onewire_size;
55     extern uint8_t jslib_onewire[];
56     quickjs_add_prebuild_module("onewire", jslib_onewire, jslib_onewire_size);
57 #endif
58 
59 #ifdef JSE_HW_ADDON_RTC
60     module_rtc_register();
61     extern uint32_t jslib_rtc_size;
62     extern uint8_t jslib_rtc[];
63     quickjs_add_prebuild_module("rtc", jslib_rtc, jslib_rtc_size);
64 #endif
65 #ifdef JSE_CORE_ADDON_CRYPTO
66     module_crypto_register();
67     extern uint32_t jslib_crypto_size;
68     extern uint8_t jslib_crypto[];
69     quickjs_add_prebuild_module("crypto", jslib_crypto, jslib_crypto_size);
70 #endif
71 #ifdef JSE_HW_ADDON_WDG
72     module_wdg_register();
73     extern uint32_t jslib_wdg_size;
74     extern uint8_t jslib_wdg[];
75     quickjs_add_prebuild_module("wdg", jslib_wdg, jslib_wdg_size);
76 #endif
77 
78 #ifdef JSE_HW_ADDON_UART
79     module_uart_register();
80     extern uint32_t jslib_uart_size;
81     extern uint8_t jslib_uart[];
82     quickjs_add_prebuild_module("uart", jslib_uart, jslib_uart_size);
83 #endif
84 
85 #ifdef JSE_HW_ADDON_SPI
86     module_spi_register();
87     extern uint32_t jslib_spi_size;
88     extern uint8_t jslib_spi[];
89     quickjs_add_prebuild_module("spi", jslib_spi, jslib_spi_size);
90 #endif
91 
92 #ifdef JSE_HW_ADDON_ADC
93     module_adc_register();
94     extern uint32_t jslib_adc_size;
95     extern uint8_t jslib_adc[];
96     quickjs_add_prebuild_module("adc", jslib_adc, jslib_adc_size);
97 #endif
98 
99 #ifdef JSE_HW_ADDON_TIMER
100     module_timer_register();
101 #endif
102 
103 #ifdef JSE_HW_ADDON_DAC
104     module_dac_register();
105     extern uint32_t jslib_dac_size;
106     extern uint8_t jslib_dac[];
107     quickjs_add_prebuild_module("dac", jslib_dac, jslib_dac_size);
108 #endif
109 
110 #ifdef JSE_HW_ADDON_DS18B20
111     extern uint32_t jslib_ds18b20_size;
112     extern uint8_t jslib_ds18b20[];
113     quickjs_add_prebuild_module("ds18b20", jslib_ds18b20, jslib_ds18b20_size);
114 #endif
115 
116 #ifdef JSE_CORE_ADDON_SYSTIMER
117     module_systimer_register();
118 #endif
119 
120 #ifdef JSE_NET_ADDON_TCP
121     module_tcp_register();
122     extern uint32_t jslib_tcp_size;
123     extern uint8_t jslib_tcp[];
124     quickjs_add_prebuild_module("tcp", jslib_tcp, jslib_tcp_size);
125 #endif
126 
127 #ifdef JSE_NET_ADDON_UDP
128     module_udp_register();
129     extern uint32_t jslib_udp_size;
130     extern uint8_t jslib_udp[];
131     quickjs_add_prebuild_module("udp", jslib_udp, jslib_udp_size);
132 #endif
133 
134 #ifdef JSE_NET_ADDON_HTTP
135     module_http_register();
136 #endif
137 
138 #ifdef JSE_NET_ADDON_MQTT
139     module_mqtt_register();
140     extern uint32_t jslib_mqtt_size;
141     extern uint8_t jslib_mqtt[];
142     quickjs_add_prebuild_module("mqtt", jslib_mqtt, jslib_mqtt_size);
143 #endif
144 
145 #ifdef JSE_NET_ADDON_NETMGR
146     module_netmgr_register();
147     extern uint32_t jslib_netmgr_size;
148     extern uint8_t jslib_netmgr[];
149     quickjs_add_prebuild_module("netmgr", jslib_netmgr, jslib_netmgr_size);
150 #endif
151 
152 #ifdef JSE_CORE_ADDON_SYSTEM
153     module_system_register();
154 #endif
155 
156 #ifdef JSE_ADVANCED_ADDON_OTA
157     module_app_ota_register();
158     extern uint32_t jslib_appota_size;
159     extern uint8_t jslib_appota[];
160     quickjs_add_prebuild_module("appota", jslib_appota, jslib_appota_size);
161 #endif
162 
163 #ifdef JSE_ADVANCED_ADDON_UI
164     page_entry_register();
165     app_entry_register();
166     // module_vm_register();
167     module_ui_register();
168 #endif
169 
170 #ifdef JSE_HW_ADDON_LCD
171     module_lcd_register();
172 #endif
173 
174 #ifdef JSE_HW_ADDON_I2C
175     module_i2c_register();
176     extern uint32_t jslib_i2c_size;
177     extern uint8_t jslib_i2c[];
178     quickjs_add_prebuild_module("i2c", jslib_i2c, jslib_i2c_size);
179 #endif
180 
181 #ifdef JSE_ADVANCED_ADDON_AIOT_DEVICE
182     module_aiot_device_register();
183     module_aiot_gateway_register();
184     extern uint32_t jslib_iot_size;
185     extern uint8_t jslib_iot[];
186     quickjs_add_prebuild_module("iot", jslib_iot, jslib_iot_size);
187 #endif
188 
189 #ifdef JSE_CORE_ADDON_LOG
190     module_log_register();
191 #endif
192 
193 #ifdef JSE_WIRELESS_ADDON_BT_HOST
194     module_bt_host_register();
195     extern uint32_t jslib_bt_host_size;
196     extern uint8_t jslib_bt_host[];
197     quickjs_add_prebuild_module("bt_host", jslib_bt_host, jslib_bt_host_size);
198 #endif
199 
200 #ifdef JSE_CORE_ADDON_FS
201     module_fs_register();
202     extern uint32_t jslib_fs_size;
203     extern uint8_t jslib_fs[];
204     quickjs_add_prebuild_module("fs", jslib_fs, jslib_fs_size);
205 #endif
206 
207 #ifdef JSE_CORE_ADDON_KV
208     module_kv_register();
209 #endif
210 
211 #ifdef JSE_ADVANCED_ADDON_AUDIOPLAYER
212     module_audio_register();
213     extern uint32_t jslib_audioplayer_size;
214     extern uint8_t jslib_audioplayer[];
215     quickjs_add_prebuild_module("audioplayer", jslib_audioplayer, jslib_audioplayer_size);
216 #endif
217 
218 #ifdef JSE_CORE_ADDON_CHECKSUM
219     module_checksum_register();
220     extern uint32_t jslib_checksum_size;
221     extern uint8_t jslib_checksum[];
222     quickjs_add_prebuild_module("checksum", jslib_checksum, jslib_checksum_size);
223 #endif
224 
225 #ifdef JSE_ADVANCED_ADDON_BLECFGNET
226     module_blecfgnet_register();
227 #endif
228 
229 #ifdef JSE_NET_ADDON_CELLULAR
230     module_cellular_register();
231 #endif
232 
233 #if defined(JSE_NET_ADDON_NETMGR) || defined(JSE_NET_ADDON_CELLULAR)
234     module_network_register();
235     extern uint32_t jslib_network_size;
236     extern uint8_t jslib_network[];
237     quickjs_add_prebuild_module("network", jslib_network, jslib_network_size);
238 #endif
239 
240 #if (defined(JSE_NET_ADDON_NETMGR) || defined(JSE_NET_ADDON_CELLULAR)) && defined(JSE_ADVANCED_ADDON_LOCATION)
241     extern uint32_t jslib_location_size;
242     extern uint8_t jslib_location[];
243     quickjs_add_prebuild_module("location", jslib_location, jslib_location_size);
244 #endif
245 
246 #ifdef JSE_ADVANCED_ADDON_OSS
247     module_oss_register();
248 #endif
249 }
250 
amp_context_set(JSContext * context)251 int amp_context_set(JSContext *context)
252 {
253     if (!context) {
254         aos_printf("%s: context null", __func__);
255         return -1;
256     }
257     ctx = context;
258     aos_printf("%s: js context set\r\n", __func__);
259     return 0;
260 }
261 
amp_modules_load(JSContext * ctx,const char * module_name,void * opaque)262 JSModuleDef *amp_modules_load(JSContext *ctx, const char *module_name, void *opaque)
263 {
264     aos_printf("%s: load module %s\r\n", __func__, module_name ? module_name : "null");
265     return quickjs_module_loader(ctx, module_name, opaque);
266 }
267 
jsengine_init(void)268 int jsengine_init(void)
269 {
270 #ifndef HAASUI_AMP_BUILD
271     rt = JS_NewRuntime();
272     if (rt == NULL) {
273         aos_printf("JS_NewRuntime failure");
274         aos_task_exit(1);
275     }
276     js_std_init_handlers(rt);
277 
278     ctx = JS_NewContext(rt);
279     if (ctx == NULL) {
280         aos_printf("JS_NewContext failure");
281     }
282 
283     JS_SetCanBlock(rt, 1);
284 
285     /* loader for ES6 modules */
286     JS_SetModuleLoaderFunc(rt, NULL, quickjs_module_loader, NULL);
287 
288     js_std_add_helpers(ctx, -1, NULL);
289 
290     /* system modules */
291     js_init_module_std(ctx, "std");
292     js_init_module_os(ctx, "os");
293 
294     jsengine_register_addons();
295 
296     if (g_repl_config) {
297         module_repl_register();
298     }
299 
300 #else
301     js_std_add_helpers(ctx, -1, NULL);
302 
303     /* system modules */
304     js_init_module_std(ctx, "std");
305     js_init_module_os(ctx, "os");
306 
307     jsengine_register_addons();
308 #endif
309     aos_printf("quickjs engine started !\n");
310 
311     return 0;
312 }
313 
qjs_dump_obj(JSContext * ctx,JSValueConst val)314 void qjs_dump_obj(JSContext *ctx, JSValueConst val)
315 {
316     const char *str;
317 
318     str = JS_ToCString(ctx, val);
319     if (str) {
320         aos_printf("%s", str);
321         JS_FreeCString(ctx, str);
322     } else {
323         aos_printf("[exception]\n");
324     }
325 }
326 
qjs_std_dump_error1(JSContext * ctx,JSValueConst exception_val)327 void qjs_std_dump_error1(JSContext *ctx, JSValueConst exception_val)
328 {
329     JSValue val;
330     bool is_error;
331 
332     is_error = JS_IsError(ctx, exception_val);
333     qjs_dump_obj(ctx, exception_val);
334     if (is_error) {
335         val = JS_GetPropertyStr(ctx, exception_val, "stack");
336         if (!JS_IsUndefined(val)) {
337             qjs_dump_obj(ctx, val);
338         }
339         JS_FreeValue(ctx, val);
340     }
341 }
342 
qjs_std_dump_error(JSContext * ctx)343 void qjs_std_dump_error(JSContext *ctx)
344 {
345     JSValue exception_val;
346 
347     exception_val = JS_GetException(ctx);
348 
349     qjs_std_dump_error1(ctx, exception_val);
350     JS_FreeValue(ctx, exception_val);
351 }
352 
jsengine_eval_file(const char * filename)353 void jsengine_eval_file(const char *filename)
354 {
355     uint8_t *buf = NULL;
356     size_t buf_len = 0;
357     int eval_flags = JS_EVAL_TYPE_MODULE;
358 
359     aos_printf("begin eval file: %s\n", filename);
360 
361     buf = js_load_file(ctx, &buf_len, filename);
362     if (buf == NULL) {
363         aos_printf("read js file %s error\n", filename);
364         return;
365     }
366     if (filename[strlen(filename) - 1] == 's') {
367         val = JS_Eval(ctx, buf, buf_len, filename, eval_flags);
368         if (JS_IsException(val)) {
369             aos_printf("js engine eval %s error\n", filename);
370             aos_printf("app.js content: \r\n");
371             aos_printf("%s\r\n", buf);
372             qjs_std_dump_error(ctx);
373         }
374         JS_FreeValue(ctx, val);
375     } else {
376         js_std_eval_binary(ctx, buf, buf_len, 0);
377     }
378 
379     js_free(ctx, buf);
380     if (g_repl_config) {
381         extern uint32_t jslib_repl_size;
382         extern uint8_t jslib_repl[];
383         js_std_eval_binary(ctx, jslib_repl, jslib_repl_size, 0);
384     }
385 }
386 
jsengine_loop_once(void)387 void jsengine_loop_once(void)
388 {
389     js_std_loop_once(ctx);
390 }
391 
jsengine_exit(void)392 void jsengine_exit(void)
393 {
394     JS_FreeValue(ctx, val);
395     js_std_loop(ctx);
396     JS_FreeContext(ctx);
397     JS_FreeRuntime(rt);
398 }
399 
dump_quickjs_memory(void)400 void dump_quickjs_memory(void)
401 {
402     JS_RunGC(rt);
403     JSMemoryUsage stats;
404     JS_ComputeMemoryUsage(rt, &stats);
405     JS_DumpMemoryUsage(stdout, &stats, rt);
406 }