├── .DS_Store
├── .gitignore
├── LICENSE
├── README.md
├── c_test_m.c
├── c_test_m.js
├── globle_obj.js
├── hello
├── hello.js
├── libquickjs.a
├── libtest.so
├── os_m.js
├── quickjs-libc.h
├── quickjs.h
└── std_m.js
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaobowen/quickjs-examples/e9995363d685b9b52f35cd756a76b5b0772cda87/.DS_Store
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Runtime data
9 | pids
10 | *.pid
11 | *.seed
12 | *.pid.lock
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # Bower dependency directory (https://bower.io/)
27 | bower_components
28 |
29 | # node-waf configuration
30 | .lock-wscript
31 |
32 | # Compiled binary addons (https://nodejs.org/api/addons.html)
33 | build/Release
34 |
35 | # Dependency directories
36 | node_modules/
37 | jspm_packages/
38 |
39 | # TypeScript v1 declaration files
40 | typings/
41 |
42 | # Optional npm cache directory
43 | .npm
44 |
45 | # Optional eslint cache
46 | .eslintcache
47 |
48 | # Optional REPL history
49 | .node_repl_history
50 |
51 | # Output of 'npm pack'
52 | *.tgz
53 |
54 | # Yarn Integrity file
55 | .yarn-integrity
56 |
57 | # dotenv environment variables file
58 | .env
59 |
60 | # next.js build output
61 | .next
62 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 gaobowen
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # 1. QuickJS 快速入门 (QuickJS QuickStart)
4 |
5 | - [1. QuickJS 快速入门 (QuickJS QuickStart)](#1-quickjs-%e5%bf%ab%e9%80%9f%e5%85%a5%e9%97%a8-quickjs-quickstart)
6 | - [1.1. 简介](#11-%e7%ae%80%e4%bb%8b)
7 | - [1.2. 安装](#12-%e5%ae%89%e8%a3%85)
8 | - [1.3. 简单使用](#13-%e7%ae%80%e5%8d%95%e4%bd%bf%e7%94%a8)
9 | - [1.3.1. 控制台执行](#131-%e6%8e%a7%e5%88%b6%e5%8f%b0%e6%89%a7%e8%a1%8c)
10 | - [1.3.2. js脚本执行](#132-js%e8%84%9a%e6%9c%ac%e6%89%a7%e8%a1%8c)
11 | - [1.3.3. 直接编译成二进制文件执行](#133-%e7%9b%b4%e6%8e%a5%e7%bc%96%e8%af%91%e6%88%90%e4%ba%8c%e8%bf%9b%e5%88%b6%e6%96%87%e4%bb%b6%e6%89%a7%e8%a1%8c)
12 | - [1.4. 全局对象](#14-%e5%85%a8%e5%b1%80%e5%af%b9%e8%b1%a1)
13 | - [1.5. `std` 模块](#15-std-%e6%a8%a1%e5%9d%97)
14 | - [1.5.1. 常见的导出函数](#151-%e5%b8%b8%e8%a7%81%e7%9a%84%e5%af%bc%e5%87%ba%e5%87%bd%e6%95%b0)
15 | - [1.5.2. FILE 原型](#152-file-%e5%8e%9f%e5%9e%8b)
16 | - [1.5.3. std代码示例](#153-std%e4%bb%a3%e7%a0%81%e7%a4%ba%e4%be%8b)
17 | - [1.6. `os` 模块](#16-os-%e6%a8%a1%e5%9d%97)
18 | - [1.7. 自定义C模块](#17-%e8%87%aa%e5%ae%9a%e4%b9%89c%e6%a8%a1%e5%9d%97)
19 | - [1.7.1. js数据类型在C中的定义](#171-js%e6%95%b0%e6%8d%ae%e7%b1%bb%e5%9e%8b%e5%9c%a8c%e4%b8%ad%e7%9a%84%e5%ae%9a%e4%b9%89)
20 | - [1.7.2. c模块编写](#172-c%e6%a8%a1%e5%9d%97%e7%bc%96%e5%86%99)
21 | - [1.7.3. 使用.so模块](#173-%e4%bd%bf%e7%94%a8so%e6%a8%a1%e5%9d%97)
22 |
23 |
24 | ## 1.1. 简介
25 | QuickJS是一个小型的可嵌入Javascript引擎。它支持ES2020规范,包括模块、异步生成器和代理。它还支持数学扩展,比如大整数(BigInt)、大浮点数(BigFloat)和操作符重载。
26 |
27 | ## 1.2. 安装
28 | - Linux 直接下载 [源码](https://github.com/quickjs-zh/QuickJS)
29 | ```bash
30 | make && make install
31 | ```
32 |
33 | - MacOS X 下 makefile 有 [Bug](https://github.com/quickjs-zh/QuickJS/issues/7) ,可以直接使用 homebrew 安装
34 | ```bash
35 | brew install quickjs
36 | ```
37 | - 执行 `qjs` 验证安装成功
38 |
39 | ## 1.3. 简单使用
40 |
41 | ### 1.3.1. 控制台执行
42 | `qjs` 进入quickjs环境,`-h` 获取帮助,`-q` 退出环境。
43 | 直接执行js:
44 | ```js
45 | console.log(new Date())
46 | ```
47 | 输出:Wed Aug 14 2019 23:51:43 GMT+0800
48 | undefined
49 |
50 | ```js
51 | (function(){ return 1+1;})()
52 | ```
53 | 输出:2
54 |
55 |
56 | ### 1.3.2. js脚本执行
57 | 新建一个js脚本,名为`hello.js`,内容为`console.log('hello world !')`, 在js目录下执行
58 | ```bash
59 | qjs hello.js
60 | ```
61 | 输出:hello world !
62 |
63 |
64 | ### 1.3.3. 直接编译成二进制文件执行
65 | 将 ```quickjs.h```、```quickjs-libc.h```、```libquickjs.a``` 拷贝到js文件同目录下。
66 | ```bash
67 | qjsc -o hello hello.js
68 | ls
69 | ./hello
70 | ```
71 | 输出:hello world !
72 | 编译出来的可执行文件的大小只有569K(2019-9-18版本为900K),没有任何外部依赖,非常适合嵌入式设备使用。
73 |
74 |
75 | ## 1.4. 全局对象
76 | - `scriptArgs` 输入的命令行参数,第一个参数为脚本的名称。
77 | - `print(...args)`、`console.log(...args)`打印由空格和尾随换行符分隔的参数。
78 |
79 | 新建js脚本`globle_obj.js`
80 | ```js
81 | (function(){
82 | if(typeof scriptArgs != 'undefined'){
83 | print(scriptArgs);
84 | console.log(scriptArgs[1]);
85 | }
86 | })()
87 | ```
88 | ```bash
89 | qjs globle_obj.js -a 123 1234
90 | ```
91 | 输出:
92 | globle_obj.js,-a,123,1234
93 | -a
94 |
95 | ## 1.5. `std` 模块
96 | `std`模块为`quickjs-libc`提供包装器`stdlib.h`和`stdio.h`和其他一些实用程序。
97 | ### 1.5.1. 常见的导出函数
98 | - `exit(n)` 退出进程。
99 | - `evalScript(str)` 将字符串`str`以脚本方式运行(全局eval)。
100 | - `loadScript(filename)` 将文件`filename`以脚本方式运行(全局eval)。
101 | - `Error(errno)` 是 **std.Error**构造函数。错误实例包含字段`errno`(错误代码)和`message`(`std.Error.strerror(errno)`的结果)。
102 | 构造函数包含以下字段:`EINVAL`、`EIO`、`EACCES`、`EEXIST`、`ENOSPC`、`ENOSYS`、`EBUSY`、`ENOENT`、`EPERM`、`EPIPE` 常见错误的整数值 (可以定义附加错误代码)。
103 | - `strerror(errno)` 返回描述错误的字符串`errno`。
104 | - `open(filename, flags)` 打开一个文件(libc的包装器`fopen()`)。在I/O错误时抛出 `std.Error`。
105 | - `tmpfile()` 打开一个临时文件。在I/O错误时抛出`std.Error`。
106 | - `puts(str)` 相当于`std.out.puts(str)`。
107 | - `printf(fmt, ...args)` 相当于`std.out.printf(fmt, ...args)`、`sprintf(fmt, ...args)` 相当于libc的sprintf()。
108 | - `in`、`out`、`err` 包装libc文件的`stdin`、`stdout`、`stderr`。
109 | - `SEEK_SET`、`SEEK_CUR`、`SEEK_END` 是 **seek()** 的常量。
110 | - `global` 引用全局对象。
111 | - `gc()` 手动调用循环删除算法。循环移除算法在需要时自动启动,因此该功能在特定内存限制或测试时非常有用。
112 | - `getenv(name)` 返回环境变量的值 `name` ,或未定义时返回 `undefined` .
113 |
114 | ### 1.5.2. FILE 原型
115 | - `close()` 关闭文件。
116 | - `puts(str)` 使用UTF-8编码输出字符串。
117 | - `printf(fmt, ...args)` 格式化printf,与libc printf格式相同。
118 | - `flush()` 刷新缓冲的文件。
119 | - `seek(offset, whence)` 寻找特定文件位置 (从哪里`std.SEEK_*`)。在I/O错误时抛出 `std.Error`。
120 | - `tell()` 返回当前文件位置。
121 | - `eof()` 如果文件结束,则返回true。
122 | - `fileno()` 返回关联的OS句柄。
123 | - `read(buffer, position, length)`(封装 libc `fread`)。
124 | - `write(buffer, position, length)` (封装 libc `fread`)。
125 | - `getline()` 返回文件中的下一行,假设为UTF-8编码,不包括尾随换行符。
126 | - `getByte()` 返回文件中的下一个字节。
127 | - `putByte(c)` 将一个字节写入文件。
128 | ### 1.5.3. std代码示例
129 | 创建文件`std_m.js`
130 | ```js
131 | import * as std from 'std';
132 | var file = std.open('std_open_file.js','w');
133 | file.puts('var file = std.open(\"std_open_file.txt\",\"w\");\n');
134 | file.puts('file.puts(\'std_open_file line1\\n\');\n');
135 | file.puts('file.puts(\'std_open_file line2\\n\');\n');
136 | file.puts('file.close();\n');
137 | file.close();
138 | std.loadScript('std_open_file.js');
139 | var rdfile = std.open("std_open_file.txt","r");
140 | do{
141 | console.log(rdfile.getline());
142 | }while(!rdfile.eof());
143 | rdfile.close();
144 | ```
145 | 执行`qjs std_m.js` ,目录下会生成2个新文件`std_open_file.js` `std_open_file.txt`。
146 | 控制台输出:
147 | `std_open_file line1`
148 | `std_open_file line2`
149 | `null`
150 |
151 | ## 1.6. `os` 模块
152 | `os` 模块提供操作系统特定功能:底层文件访问、信号、计时器、异步 I/O。
153 | 如果是OK,OS函数通常返回0,或者OS返回特定的错误代码。
154 |
155 | 可用导出函数:
156 | - `open(filename, flags, mode = 0o666)` 打开一个文件。如果错误,返回句柄或<0。 `O_RDONLY`、`O_WRONLY`、`O_RDWR`、`O_APPEND`、`O_CREAT`、`O_EXCL`、`O_TRUNC` POSIX打开标志。`O_TEXT`
157 | (Windows特定)。以文本模式打开文件。默认为二进制模式。
158 | - `close(fd)` 关闭文件句柄`fd`。
159 | - `seek(fd, offset, whence)` 寻找文件。使用 `std.SEEK_*` 或 `whence`。
160 | - `read(fd, buffer, offset, length)` 读取指定长度的字节码。返回读取成功的字节码长度,失败返回 <0;
161 | - `write(fd, buffer, offset, length)` 写入字节码,失败返回<0。
162 | - `isatty(fd)` `fd` 是一个TTY (终端)句柄返`true` 。
163 | - `ttyGetWinSize(fd)` 返回TTY大小 `[width, height]` 或者如果不可用返回 `null` 。
164 | - `ttySetRaw(fd)` 在原始模式下设置TTY。
165 | - `remove(filename)` 删除文件。如果正常则返回0,如果错误则返回<0。
166 | - `rename(oldname, newname)` 重命名文件。如果正常则返回0,如果错误则返回<0。
167 | - `setReadHandler(fd, func)` 将读处理程序添加到文件句柄`fd`。 `fd`每次有数据待增加处理时调用`func` 。支持每个文件句柄的单个读处理程序。使用 `func = null` 来删除句柄。
168 | - `setWriteHandler(fd, func)` 将写处理程序添加到文件句柄`fd`。 `fd`每次有数据待写入处理时调用`func` . 支持每个文件句柄一个写处理程序。使用 `func = null来删除句柄。
169 | - `signal(signal, func)` 当信号 `signal` 发生时调用 `func` 。 每个信号编号只支持一个处理程序。使用 `null` 设定的默认处理或 `undefined` 忽略的信号。
170 | `SIGINT`
171 | `SIGABRT`
172 | `SIGFPE`
173 | `SIGILL`
174 | `SIGSEGV`
175 | `SIGTERM`
176 | POSIX 信号编号。
177 | - `setTimeout(func, delay)` 在 `delay` 毫秒之后调用函数 `func` 。返回计时器的句柄。
178 | - `clearTimer(handle)`取消计时器。
179 | - `platform` 返回表示该平台的字符串: `"linux"`, `"darwin"`, `"win32"` or `"js"`。
180 |
181 | ```js
182 | import * as os from 'os';
183 | os.remove('hello');
184 | os.remove('std_open_file.js');
185 | os.remove('std_open_file.txt');
186 | ```
187 | 删除生成的测试文件
188 |
189 |
190 | ## 1.7. 自定义C模块
191 | ES6模块完全支持。默认名称解析规则如下:
192 | - 模块名称带有前导.或..是相对于当前模块的路径
193 | - 模块名称没有前导.或..是系统模块,例如std或os
194 | - 模块名称以.so结尾,是使用QuickJS C API的原生模块
195 |
196 | 使用js文件模块和系统模块,参照引用原生js模块和上面的例子即可,这里就不多赘述。
197 | 这里着重讲解如何编写自己的原生C模块,并且以导入so文件的方式在js代码中使用。
198 | ### 1.7.1. js数据类型在C中的定义
199 | ```c
200 | typedef union JSValueUnion {
201 | int32_t int32; //整数值
202 | double float64; //double值
203 | void *ptr; //QuickJS引用类型的指针
204 | } JSValueUnion; //存放于同一地址,且互斥
205 |
206 | typedef struct JSValue {
207 | JSValueUnion u; //存放真实数值或着其指针
208 | int64_t tag; //JSValue类型的标示符(如 undefined 其 tag == JS_TAG_UNDEFINED)
209 | } JSValue;
210 | ```
211 | 此结构定义在 **quickjs.h** 中。
212 | ### 1.7.2. c模块编写
213 | 流程如下:
214 | 1. 自定义原生C函数
215 | 2. 定义 QuickJS C 函数
216 | 3. 定义API的函数入口名称及列表
217 | 4. 定义初始化回调方法,将函数入口列表在模块中暴露
218 | 5. 定义初始化模块方法,由系统自动调用,且函数名称不可更改
219 |
220 | 创建编写c_test_m.c文件:
221 | ```c
222 | // #include "quickjs.h"
223 | // #include "stdio.h"
224 | // #include "stdlib.h"
225 | // #include "string.h"
226 |
227 | // #define JS_INIT_MODULE js_init_module
228 | //#define countof(x) (sizeof(x) / sizeof((x)[0]))
229 |
230 | /* 自定义原生C函数 */
231 | static double test_add(int a, double b)
232 | {
233 | return a + b;
234 | }
235 |
236 | static char *test_add_str(const char *a, double b)
237 | {
238 | /* 要有足够的空间来容纳要拼接的字符串,否则可能会造成缓冲溢出的错误情况 */
239 | char instr[64];
240 | sprintf(instr, "%.2f", b);
241 | char *dest = malloc(128);
242 | memset(dest, 0, 128);
243 | strcpy(dest, a);
244 | char *retdest = strcat(dest, instr);
245 | return dest;
246 | }
247 |
248 | /*
249 | 定义 QuickJS C 函数
250 | *ctx : 运行时上下文
251 | this_val : this对象
252 | argc : 入参个数
253 | *argv : 入参列表
254 | */
255 | static JSValue js_test_add(JSContext *ctx, JSValueConst this_val,
256 | int argc, JSValueConst *argv)
257 | {
258 | int a;
259 | double b;
260 | if (JS_ToInt32(ctx, &a, argv[0]))
261 | return JS_EXCEPTION;
262 | if (JS_ToFloat64(ctx, &b, argv[1]))
263 | return JS_EXCEPTION;
264 | printf("argc = %d \n", argc);
265 | printf("a = %d \n", a);
266 | printf("b = %lf \n", b);
267 | printf("argv[1].u.float64 = %lf \n", argv[1].u.float64);
268 | return JS_NewFloat64(ctx, test_add(a, b));
269 | }
270 |
271 | static JSValue js_test_add_str(JSContext *ctx, JSValueConst this_val,
272 | int argc, JSValueConst *argv)
273 | {
274 | if (!JS_IsString(argv[0]))
275 | {
276 | return JS_EXCEPTION;
277 | }
278 | double d;
279 | if (JS_ToFloat64(ctx, &d, argv[1]))
280 | return JS_EXCEPTION;
281 | const char *jscstr = JS_ToCString(ctx, argv[0]);
282 | printf("JS_ToCString(ctx, argv[0]) = %s \n", jscstr);
283 | printf("argv[1].u.float64 = %lf \n", argv[1].u.float64);
284 | char *jsret = test_add_str(jscstr, d);
285 | return JS_NewString(ctx, jsret);
286 | }
287 |
288 | /* 定义API的函数入口名称及列表 */
289 | static const JSCFunctionListEntry js_test_funcs[] = {
290 | /* JS_CFUNC_DEF(函数入口名称,入参个数,QuickJS C 函数) */
291 | JS_CFUNC_DEF("testAdd", 2, js_test_add),
292 | JS_CFUNC_DEF("testAddStr", 2, js_test_add_str),
293 | };
294 |
295 | /* 定义初始化回调方法(由系统调用,入参格式固定),将函数入口列表 在模块中暴露 */
296 | static int js_test_init(JSContext *ctx, JSModuleDef *m)
297 | {
298 | return JS_SetModuleExportList(ctx, m, js_test_funcs,
299 | countof(js_test_funcs));
300 | }
301 |
302 | /* 定义初始化模块方法,由系统自动调用,且函数名称不可更改 */
303 | JSModuleDef *JS_INIT_MODULE(JSContext *ctx, const char *module_name)
304 | {
305 | JSModuleDef *m;
306 | m = JS_NewCModule(ctx, module_name, js_test_init);
307 | if (!m)
308 | return NULL;
309 | JS_AddModuleExportList(ctx, m, js_test_funcs, countof(js_test_funcs));
310 | return m;
311 | }
312 | ```
313 | 将 ```quickjs.h```、```quickjs-libc.h```、```libquickjs.a``` 拷贝到当前工程目录下。
314 | 执行命令
315 | ```bash
316 | gcc c_test_m.c libquickjs.a -fPIC -shared -o libtest.so
317 | ```
318 | 生成```libtest.so```文件。
319 | ### 1.7.3. 使用.so模块
320 | 创建js文件 c_test_m.js
321 | ```js
322 | import { testAdd , testAddStr} from 'libtest.so'
323 | console.log('\n')
324 | console.log(`testAdd: ${testAdd(1, 0.5)}`)
325 | console.log('\n')
326 | console.log(`testAddStr: ${testAddStr('Pi equal to about ', 3.14159)}`)
327 | console.log('\n')
328 | ```
329 | ```bash
330 | qjs c_test_m.js
331 | ```
332 | 输出:
333 | argc = 2
334 | a = 1
335 | b = 0.500000
336 | argv[1].u.float64 = 0.500000
337 | testAdd: 1.5
338 |
339 |
340 | JS_ToCString(ctx, argv[0]) = Pi equal to about
341 | argv[1].u.float64 = 3.141590
342 | testAddStr: Pi equal to about 3.14
343 |
344 |
345 | [项目地址](https://github.com/gaobowen/quickjs-examples)
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
--------------------------------------------------------------------------------
/c_test_m.c:
--------------------------------------------------------------------------------
1 | #include "quickjs.h"
2 | #include "stdio.h"
3 | #include "stdlib.h"
4 | #include "string.h"
5 |
6 | #define JS_INIT_MODULE js_init_module
7 | #define countof(x) (sizeof(x) / sizeof((x)[0]))
8 |
9 | /* 自定义原生C函数 */
10 | static double test_add(int a, double b)
11 | {
12 | return a + b;
13 | }
14 |
15 | static char *test_add_str(const char *a, double b)
16 | {
17 | /* 要有足够的空间来容纳要拼接的字符串,否则可能会造成缓冲溢出的错误情况 */
18 | char instr[64];
19 | sprintf(instr, "%.2f", b);
20 | char *dest = malloc(128);
21 | memset(dest, 0, 128);
22 | strcpy(dest, a);
23 | char *retdest = strcat(dest, instr);
24 | return dest;
25 | }
26 |
27 | /*
28 | 定义 QuickJS C 函数
29 | *ctx : 运行时上下文
30 | this_val : this对象
31 | argc : 入参个数
32 | *argv : 入参列表
33 | */
34 | static JSValue js_test_add(JSContext *ctx, JSValueConst this_val,
35 | int argc, JSValueConst *argv)
36 | {
37 | int a;
38 | double b;
39 | if (JS_ToInt32(ctx, &a, argv[0]))
40 | return JS_EXCEPTION;
41 | if (JS_ToFloat64(ctx, &b, argv[1]))
42 | return JS_EXCEPTION;
43 | printf("argc = %d \n", argc);
44 | printf("a = %d \n", a);
45 | printf("b = %lf \n", b);
46 | printf("argv[1].u.float64 = %lf \n", argv[1].u.float64);
47 | return JS_NewFloat64(ctx, test_add(a, b));
48 | }
49 |
50 | static JSValue js_test_add_str(JSContext *ctx, JSValueConst this_val,
51 | int argc, JSValueConst *argv)
52 | {
53 | if (!JS_IsString(argv[0]))
54 | {
55 | return JS_EXCEPTION;
56 | }
57 | double d;
58 | if (JS_ToFloat64(ctx, &d, argv[1]))
59 | return JS_EXCEPTION;
60 | const char *jscstr = JS_ToCString(ctx, argv[0]);
61 | printf("JS_ToCString(ctx, argv[0]) = %s \n", jscstr);
62 | printf("argv[1].u.float64 = %lf \n", argv[1].u.float64);
63 | char *jsret = test_add_str(jscstr, d);
64 | return JS_NewString(ctx, jsret);
65 | }
66 |
67 | /* 定义API的函数入口名称及列表 */
68 | static const JSCFunctionListEntry js_test_funcs[] = {
69 | /* JS_CFUNC_DEF(函数入口名称,入参个数,QuickJS C 函数) */
70 | JS_CFUNC_DEF("testAdd", 2, js_test_add),
71 | JS_CFUNC_DEF("testAddStr", 2, js_test_add_str),
72 | };
73 |
74 | /* 定义初始化回调方法(由系统调用,入参格式固定),将函数入口列表 在模块中暴露 */
75 | static int js_test_init(JSContext *ctx, JSModuleDef *m)
76 | {
77 | return JS_SetModuleExportList(ctx, m, js_test_funcs,
78 | countof(js_test_funcs));
79 | }
80 |
81 | /* 定义初始化模块方法,由系统自动调用,且函数名称不可更改 */
82 | JSModuleDef *JS_INIT_MODULE(JSContext *ctx, const char *module_name)
83 | {
84 | JSModuleDef *m;
85 | m = JS_NewCModule(ctx, module_name, js_test_init);
86 | if (!m)
87 | return NULL;
88 | JS_AddModuleExportList(ctx, m, js_test_funcs, countof(js_test_funcs));
89 | return m;
90 | }
91 |
--------------------------------------------------------------------------------
/c_test_m.js:
--------------------------------------------------------------------------------
1 | import { testAdd , testAddStr} from 'libtest.so'
2 | console.log('\n')
3 | console.log(`testAdd: ${testAdd(1, 0.5)}`)
4 | console.log('\n')
5 | console.log(`testAddStr: ${testAddStr('Pi equal to about ', 3.14159)}`)
6 | console.log('\n')
7 |
--------------------------------------------------------------------------------
/globle_obj.js:
--------------------------------------------------------------------------------
1 | (function(){
2 | if(typeof scriptArgs != 'undefined'){
3 | print(scriptArgs);
4 | console.log(scriptArgs[1]);
5 | }
6 | })()
--------------------------------------------------------------------------------
/hello:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaobowen/quickjs-examples/e9995363d685b9b52f35cd756a76b5b0772cda87/hello
--------------------------------------------------------------------------------
/hello.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | console.log('hello world !');
3 |
--------------------------------------------------------------------------------
/libquickjs.a:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaobowen/quickjs-examples/e9995363d685b9b52f35cd756a76b5b0772cda87/libquickjs.a
--------------------------------------------------------------------------------
/libtest.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gaobowen/quickjs-examples/e9995363d685b9b52f35cd756a76b5b0772cda87/libtest.so
--------------------------------------------------------------------------------
/os_m.js:
--------------------------------------------------------------------------------
1 | import * as os from 'os';
2 | os.remove('hello');
3 | os.remove('std_open_file.js');
4 | os.remove('std_open_file.txt');
5 |
6 |
--------------------------------------------------------------------------------
/quickjs-libc.h:
--------------------------------------------------------------------------------
1 | /*
2 | * QuickJS C library
3 | *
4 | * Copyright (c) 2017-2018 Fabrice Bellard
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 | #ifndef QUICKJS_LIBC_H
25 | #define QUICKJS_LIBC_H
26 |
27 | #include
28 | #include
29 |
30 | #include "quickjs.h"
31 |
32 | JSModuleDef *js_init_module_std(JSContext *ctx, const char *module_name);
33 | JSModuleDef *js_init_module_os(JSContext *ctx, const char *module_name);
34 | void js_std_add_helpers(JSContext *ctx, int argc, char **argv);
35 | void js_std_loop(JSContext *ctx);
36 | void js_std_free_handlers(JSRuntime *rt);
37 | void js_std_dump_error(JSContext *ctx);
38 | uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, const char *filename);
39 | int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val,
40 | JS_BOOL use_realpath, JS_BOOL is_main);
41 | JSModuleDef *js_module_loader(JSContext *ctx,
42 | const char *module_name, void *opaque);
43 | void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len,
44 | int flags);
45 |
46 | #endif /* QUICKJS_LIBC_H */
47 |
--------------------------------------------------------------------------------
/quickjs.h:
--------------------------------------------------------------------------------
1 | /*
2 | * QuickJS Javascript Engine
3 | *
4 | * Copyright (c) 2017-2019 Fabrice Bellard
5 | * Copyright (c) 2017-2019 Charlie Gordon
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | */
25 | #ifndef QUICKJS_H
26 | #define QUICKJS_H
27 |
28 | #include
29 | #include
30 |
31 | #ifdef __cplusplus
32 | extern "C" {
33 | #endif
34 |
35 | #if defined(__GNUC__) || defined(__clang__)
36 | #define js_likely(x) __builtin_expect(!!(x), 1)
37 | #define js_unlikely(x) __builtin_expect(!!(x), 0)
38 | #define js_force_inline inline __attribute__((always_inline))
39 | #define __js_printf_like(f, a) __attribute__((format(printf, f, a)))
40 | #else
41 | #define js_likely(x) (x)
42 | #define js_unlikely(x) (x)
43 | #define js_force_inline inline
44 | #define __js_printf_like(a, b)
45 | #endif
46 |
47 | #define JS_BOOL int
48 |
49 | typedef struct JSRuntime JSRuntime;
50 | typedef struct JSContext JSContext;
51 | typedef struct JSObject JSObject;
52 | typedef struct JSClass JSClass;
53 | typedef uint32_t JSClassID;
54 | typedef uint32_t JSAtom;
55 |
56 | #if defined(__x86_64__) || defined(__aarch64__)
57 | #define JS_PTR64
58 | #define JS_PTR64_DEF(a) a
59 | #else
60 | #define JS_PTR64_DEF(a)
61 | #endif
62 |
63 | #ifndef JS_PTR64
64 | #define JS_NAN_BOXING
65 | #endif
66 |
67 | enum {
68 | /* all tags with a reference count are negative */
69 | JS_TAG_FIRST = -10, /* first negative tag */
70 | JS_TAG_BIG_INT = -10,
71 | JS_TAG_BIG_FLOAT = -9,
72 | JS_TAG_SYMBOL = -8,
73 | JS_TAG_STRING = -7,
74 | JS_TAG_SHAPE = -6, /* used internally during GC */
75 | JS_TAG_ASYNC_FUNCTION = -5, /* used internally during GC */
76 | JS_TAG_VAR_REF = -4, /* used internally during GC */
77 | JS_TAG_MODULE = -3, /* used internally */
78 | JS_TAG_FUNCTION_BYTECODE = -2, /* used internally */
79 | JS_TAG_OBJECT = -1,
80 |
81 | JS_TAG_INT = 0,
82 | JS_TAG_BOOL = 1,
83 | JS_TAG_NULL = 2,
84 | JS_TAG_UNDEFINED = 3,
85 | JS_TAG_UNINITIALIZED = 4,
86 | JS_TAG_CATCH_OFFSET = 5,
87 | JS_TAG_EXCEPTION = 6,
88 | JS_TAG_FLOAT64 = 7,
89 | /* any larger tag is FLOAT64 if JS_NAN_BOXING */
90 | };
91 |
92 | typedef struct JSRefCountHeader {
93 | int ref_count;
94 | } JSRefCountHeader;
95 |
96 | #define JS_FLOAT64_NAN NAN
97 |
98 | #ifdef CONFIG_CHECK_JSVALUE
99 | /* JSValue consistency : it is not possible to run the code in this
100 | mode, but it is useful to detect simple reference counting
101 | errors. It would be interesting to modify a static C analyzer to
102 | handle specific annotations (clang has such annotations but only
103 | for objective C) */
104 | typedef struct __JSValue *JSValue;
105 | typedef const struct __JSValue *JSValueConst;
106 |
107 | #define JS_VALUE_GET_TAG(v) (int)((uintptr_t)(v) & 0xf)
108 | /* same as JS_VALUE_GET_TAG, but return JS_TAG_FLOAT64 with NaN boxing */
109 | #define JS_VALUE_GET_NORM_TAG(v) JS_VALUE_GET_TAG(v)
110 | #define JS_VALUE_GET_INT(v) (int)((intptr_t)(v) >> 4)
111 | #define JS_VALUE_GET_BOOL(v) JS_VALUE_GET_INT(v)
112 | #define JS_VALUE_GET_FLOAT64(v) (double)JS_VALUE_GET_INT(v)
113 | #define JS_VALUE_GET_PTR(v) (void *)((intptr_t)(v) & ~0xf)
114 |
115 | #define JS_MKVAL(tag, val) (JSValue)(intptr_t)(((val) << 4) | (tag))
116 | #define JS_MKPTR(tag, p) (JSValue)((intptr_t)(p) | (tag))
117 |
118 | #define JS_TAG_IS_FLOAT64(tag) ((unsigned)(tag) == JS_TAG_FLOAT64)
119 |
120 | #define JS_NAN JS_MKVAL(JS_TAG_FLOAT64, 1)
121 |
122 | static inline JSValue __JS_NewFloat64(JSContext *ctx, double d)
123 | {
124 | return JS_MKVAL(JS_TAG_FLOAT64, (int)d);
125 | }
126 |
127 | #elif defined(JS_NAN_BOXING)
128 |
129 | typedef uint64_t JSValue;
130 |
131 | #define JSValueConst JSValue
132 |
133 | #define JS_VALUE_GET_TAG(v) (int)((v) >> 32)
134 | #define JS_VALUE_GET_INT(v) (int)(v)
135 | #define JS_VALUE_GET_BOOL(v) (int)(v)
136 | #define JS_VALUE_GET_PTR(v) (void *)(intptr_t)(v)
137 |
138 | #define JS_MKVAL(tag, val) (((uint64_t)(tag) << 32) | (uint32_t)(val))
139 | #define JS_MKPTR(tag, ptr) (((uint64_t)(tag) << 32) | (uintptr_t)(ptr))
140 |
141 | #define JS_FLOAT64_TAG_ADDEND (0x7ff80000 - JS_TAG_FIRST + 1) /* quiet NaN encoding */
142 |
143 | static inline double JS_VALUE_GET_FLOAT64(JSValue v)
144 | {
145 | union {
146 | JSValue v;
147 | double d;
148 | } u;
149 | u.v = v;
150 | u.v += (uint64_t)JS_FLOAT64_TAG_ADDEND << 32;
151 | return u.d;
152 | }
153 |
154 | #define JS_NAN (0x7ff8000000000000 - ((uint64_t)JS_FLOAT64_TAG_ADDEND << 32))
155 |
156 | static inline JSValue __JS_NewFloat64(JSContext *ctx, double d)
157 | {
158 | union {
159 | double d;
160 | uint64_t u64;
161 | } u;
162 | JSValue v;
163 | u.d = d;
164 | /* normalize NaN */
165 | if (js_unlikely((u.u64 & 0x7fffffffffffffff) > 0x7ff0000000000000))
166 | v = JS_NAN;
167 | else
168 | v = u.u64 - ((uint64_t)JS_FLOAT64_TAG_ADDEND << 32);
169 | return v;
170 | }
171 |
172 | #define JS_TAG_IS_FLOAT64(tag) ((unsigned)((tag) - JS_TAG_FIRST) >= (JS_TAG_FLOAT64 - JS_TAG_FIRST))
173 |
174 | /* same as JS_VALUE_GET_TAG, but return JS_TAG_FLOAT64 with NaN boxing */
175 | static inline int JS_VALUE_GET_NORM_TAG(JSValue v)
176 | {
177 | uint32_t tag;
178 | tag = JS_VALUE_GET_TAG(v);
179 | if (JS_TAG_IS_FLOAT64(tag))
180 | return JS_TAG_FLOAT64;
181 | else
182 | return tag;
183 | }
184 |
185 | #else /* !JS_NAN_BOXING */
186 |
187 | typedef union JSValueUnion {
188 | int32_t int32;
189 | double float64;
190 | void *ptr;
191 | } JSValueUnion;
192 |
193 | typedef struct JSValue {
194 | JSValueUnion u;
195 | int64_t tag;
196 | } JSValue;
197 |
198 | #define JSValueConst JSValue
199 |
200 | #define JS_VALUE_GET_TAG(v) ((int32_t)(v).tag)
201 | /* same as JS_VALUE_GET_TAG, but return JS_TAG_FLOAT64 with NaN boxing */
202 | #define JS_VALUE_GET_NORM_TAG(v) JS_VALUE_GET_TAG(v)
203 | #define JS_VALUE_GET_INT(v) ((v).u.int32)
204 | #define JS_VALUE_GET_BOOL(v) ((v).u.int32)
205 | #define JS_VALUE_GET_FLOAT64(v) ((v).u.float64)
206 | #define JS_VALUE_GET_PTR(v) ((v).u.ptr)
207 |
208 | #define JS_MKVAL(tag, val) (JSValue){ (JSValueUnion){ .int32 = val }, tag }
209 | #define JS_MKPTR(tag, p) (JSValue){ (JSValueUnion){ .ptr = p }, tag }
210 |
211 | #define JS_TAG_IS_FLOAT64(tag) ((unsigned)(tag) == JS_TAG_FLOAT64)
212 |
213 | #define JS_NAN (JSValue){ .u.float64 = JS_FLOAT64_NAN, JS_TAG_FLOAT64 }
214 |
215 | static inline JSValue __JS_NewFloat64(JSContext *ctx, double d)
216 | {
217 | JSValue v;
218 | v.tag = JS_TAG_FLOAT64;
219 | v.u.float64 = d;
220 | return v;
221 | }
222 |
223 | #endif /* !JS_NAN_BOXING */
224 |
225 | #define JS_VALUE_IS_BOTH_INT(v1, v2) ((JS_VALUE_GET_TAG(v1) | JS_VALUE_GET_TAG(v2)) == 0)
226 | #define JS_VALUE_IS_BOTH_FLOAT(v1, v2) (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(v1)) && JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(v2)))
227 |
228 | #define JS_VALUE_GET_OBJ(v) ((JSObject *)JS_VALUE_GET_PTR(v))
229 | #define JS_VALUE_GET_STRING(v) ((JSString *)JS_VALUE_GET_PTR(v))
230 | #define JS_VALUE_HAS_REF_COUNT(v) ((unsigned)JS_VALUE_GET_TAG(v) >= (unsigned)JS_TAG_FIRST)
231 |
232 | /* special values */
233 | #define JS_NULL JS_MKVAL(JS_TAG_NULL, 0)
234 | #define JS_UNDEFINED JS_MKVAL(JS_TAG_UNDEFINED, 0)
235 | #define JS_FALSE JS_MKVAL(JS_TAG_BOOL, 0)
236 | #define JS_TRUE JS_MKVAL(JS_TAG_BOOL, 1)
237 | #define JS_EXCEPTION JS_MKVAL(JS_TAG_EXCEPTION, 0)
238 | #define JS_UNINITIALIZED JS_MKVAL(JS_TAG_UNINITIALIZED, 0)
239 |
240 | /* flags for object properties */
241 | #define JS_PROP_CONFIGURABLE (1 << 0)
242 | #define JS_PROP_WRITABLE (1 << 1)
243 | #define JS_PROP_ENUMERABLE (1 << 2)
244 | #define JS_PROP_C_W_E (JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE | JS_PROP_ENUMERABLE)
245 | #define JS_PROP_LENGTH (1 << 3) /* used internally in Arrays */
246 | #define JS_PROP_TMASK (3 << 4) /* mask for NORMAL, GETSET, VARREF, AUTOINIT */
247 | #define JS_PROP_NORMAL (0 << 4)
248 | #define JS_PROP_GETSET (1 << 4)
249 | #define JS_PROP_VARREF (2 << 4) /* used internally */
250 | #define JS_PROP_AUTOINIT (3 << 4) /* used internally */
251 |
252 | /* flags for JS_DefineProperty */
253 | #define JS_PROP_HAS_SHIFT 8
254 | #define JS_PROP_HAS_CONFIGURABLE (1 << 8)
255 | #define JS_PROP_HAS_WRITABLE (1 << 9)
256 | #define JS_PROP_HAS_ENUMERABLE (1 << 10)
257 | #define JS_PROP_HAS_GET (1 << 11)
258 | #define JS_PROP_HAS_SET (1 << 12)
259 | #define JS_PROP_HAS_VALUE (1 << 13)
260 |
261 | /* throw an exception if false would be returned
262 | (JS_DefineProperty/JS_SetProperty) */
263 | #define JS_PROP_THROW (1 << 14)
264 | /* throw an exception if false would be returned in strict mode
265 | (JS_SetProperty) */
266 | #define JS_PROP_THROW_STRICT (1 << 15)
267 |
268 | #define JS_PROP_NO_ADD (1 << 16) /* internal use */
269 | #define JS_PROP_NO_EXOTIC (1 << 17) /* internal use */
270 |
271 | #define JS_DEFAULT_STACK_SIZE (256 * 1024)
272 |
273 | /* JS_Eval() flags */
274 | #define JS_EVAL_TYPE_GLOBAL (0 << 0) /* global code (default) */
275 | #define JS_EVAL_TYPE_MODULE (1 << 0) /* module code */
276 | #define JS_EVAL_TYPE_DIRECT (2 << 0) /* direct call (internal use) */
277 | #define JS_EVAL_TYPE_INDIRECT (3 << 0) /* indirect call (internal use) */
278 | #define JS_EVAL_TYPE_MASK (3 << 0)
279 |
280 | #define JS_EVAL_FLAG_STRICT (1 << 3) /* force 'strict' mode */
281 | #define JS_EVAL_FLAG_STRIP (1 << 4) /* force 'strip' mode */
282 | /* compile but do not run. The result is an object with a
283 | JS_TAG_FUNCTION_BYTECODE or JS_TAG_MODULE tag. It can be executed
284 | with JS_EvalFunction(). */
285 | #define JS_EVAL_FLAG_COMPILE_ONLY (1 << 5)
286 |
287 | typedef JSValue JSCFunction(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv);
288 | typedef JSValue JSCFunctionMagic(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic);
289 | typedef JSValue JSCFunctionData(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic, JSValue *func_data);
290 |
291 | typedef struct JSMallocState {
292 | size_t malloc_count;
293 | size_t malloc_size;
294 | size_t malloc_limit;
295 | void *opaque; /* user opaque */
296 | } JSMallocState;
297 |
298 | typedef struct JSMallocFunctions {
299 | void *(*js_malloc)(JSMallocState *s, size_t size);
300 | void (*js_free)(JSMallocState *s, void *ptr);
301 | void *(*js_realloc)(JSMallocState *s, void *ptr, size_t size);
302 | size_t (*js_malloc_usable_size)(const void *ptr);
303 | } JSMallocFunctions;
304 |
305 | JSRuntime *JS_NewRuntime(void);
306 | /* info lifetime must exceed that of rt */
307 | void JS_SetRuntimeInfo(JSRuntime *rt, const char *info);
308 | void JS_SetMemoryLimit(JSRuntime *rt, size_t limit);
309 | void JS_SetGCThreshold(JSRuntime *rt, size_t gc_threshold);
310 | JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque);
311 | void JS_FreeRuntime(JSRuntime *rt);
312 | typedef void JS_MarkFunc(JSRuntime *rt, JSValueConst val);
313 | void JS_MarkValue(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func);
314 | void JS_RunGC(JSRuntime *rt);
315 | JS_BOOL JS_IsLiveObject(JSRuntime *rt, JSValueConst obj);
316 | JS_BOOL JS_IsInGCSweep(JSRuntime *rt);
317 |
318 | JSContext *JS_NewContext(JSRuntime *rt);
319 | void JS_FreeContext(JSContext *s);
320 | void *JS_GetContextOpaque(JSContext *ctx);
321 | void JS_SetContextOpaque(JSContext *ctx, void *opaque);
322 | JSRuntime *JS_GetRuntime(JSContext *ctx);
323 | void JS_SetMaxStackSize(JSContext *ctx, size_t stack_size);
324 | void JS_SetClassProto(JSContext *ctx, JSClassID class_id, JSValue obj);
325 | JSValue JS_GetClassProto(JSContext *ctx, JSClassID class_id);
326 |
327 | /* the following functions are used to select the intrinsic object to
328 | save memory */
329 | JSContext *JS_NewContextRaw(JSRuntime *rt);
330 | void JS_AddIntrinsicBaseObjects(JSContext *ctx);
331 | void JS_AddIntrinsicDate(JSContext *ctx);
332 | void JS_AddIntrinsicEval(JSContext *ctx);
333 | void JS_AddIntrinsicStringNormalize(JSContext *ctx);
334 | void JS_AddIntrinsicRegExpCompiler(JSContext *ctx);
335 | void JS_AddIntrinsicRegExp(JSContext *ctx);
336 | void JS_AddIntrinsicJSON(JSContext *ctx);
337 | void JS_AddIntrinsicProxy(JSContext *ctx);
338 | void JS_AddIntrinsicMapSet(JSContext *ctx);
339 | void JS_AddIntrinsicTypedArrays(JSContext *ctx);
340 | void JS_AddIntrinsicPromise(JSContext *ctx);
341 | JSValue js_string_codePointRange(JSContext *ctx, JSValueConst this_val,
342 | int argc, JSValueConst *argv);
343 |
344 | void *js_malloc_rt(JSRuntime *rt, size_t size);
345 | void js_free_rt(JSRuntime *rt, void *ptr);
346 | void *js_realloc_rt(JSRuntime *rt, void *ptr, size_t size);
347 | size_t js_malloc_usable_size_rt(JSRuntime *rt, const void *ptr);
348 | void *js_mallocz_rt(JSRuntime *rt, size_t size);
349 |
350 | void *js_malloc(JSContext *ctx, size_t size);
351 | void js_free(JSContext *ctx, void *ptr);
352 | void *js_realloc(JSContext *ctx, void *ptr, size_t size);
353 | size_t js_malloc_usable_size(JSContext *ctx, const void *ptr);
354 | void *js_realloc2(JSContext *ctx, void *ptr, size_t size, size_t *pslack);
355 | void *js_mallocz(JSContext *ctx, size_t size);
356 | char *js_strdup(JSContext *ctx, const char *str);
357 | char *js_strndup(JSContext *ctx, const char *s, size_t n);
358 |
359 | typedef struct JSMemoryUsage {
360 | int64_t malloc_size, malloc_limit, memory_used_size;
361 | int64_t malloc_count;
362 | int64_t memory_used_count;
363 | int64_t atom_count, atom_size;
364 | int64_t str_count, str_size;
365 | int64_t obj_count, obj_size;
366 | int64_t prop_count, prop_size;
367 | int64_t shape_count, shape_size;
368 | int64_t js_func_count, js_func_size, js_func_code_size;
369 | int64_t js_func_pc2line_count, js_func_pc2line_size;
370 | int64_t c_func_count, array_count;
371 | int64_t fast_array_count, fast_array_elements;
372 | int64_t binary_object_count, binary_object_size;
373 | } JSMemoryUsage;
374 |
375 | void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s);
376 | void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt);
377 |
378 | /* atom support */
379 | JSAtom JS_NewAtomLen(JSContext *ctx, const char *str, size_t len);
380 | JSAtom JS_NewAtom(JSContext *ctx, const char *str);
381 | JSAtom JS_NewAtomUInt32(JSContext *ctx, uint32_t n);
382 | JSAtom JS_DupAtom(JSContext *ctx, JSAtom v);
383 | void JS_FreeAtom(JSContext *ctx, JSAtom v);
384 | void JS_FreeAtomRT(JSRuntime *rt, JSAtom v);
385 | JSValue JS_AtomToValue(JSContext *ctx, JSAtom atom);
386 | JSValue JS_AtomToString(JSContext *ctx, JSAtom atom);
387 | const char *JS_AtomToCString(JSContext *ctx, JSAtom atom);
388 | JSAtom JS_ValueToAtom(JSContext *ctx, JSValueConst val);
389 |
390 | /* object class support */
391 |
392 | typedef struct JSPropertyEnum {
393 | JS_BOOL is_enumerable;
394 | JSAtom atom;
395 | } JSPropertyEnum;
396 |
397 | typedef struct JSPropertyDescriptor {
398 | int flags;
399 | JSValue value;
400 | JSValue getter;
401 | JSValue setter;
402 | } JSPropertyDescriptor;
403 |
404 | typedef struct JSClassExoticMethods {
405 | /* Return -1 if exception (can only happen in case of Proxy object),
406 | FALSE if the property does not exists, TRUE if it exists. If 1 is
407 | returned, the property descriptor 'desc' is filled if != NULL. */
408 | int (*get_own_property)(JSContext *ctx, JSPropertyDescriptor *desc,
409 | JSValueConst obj, JSAtom prop);
410 | /* '*ptab' should hold the '*plen' property keys. Return 0 if OK,
411 | -1 if exception. The 'is_enumerable' field is ignored.
412 | */
413 | int (*get_own_property_names)(JSContext *ctx, JSPropertyEnum **ptab,
414 | uint32_t *plen,
415 | JSValueConst obj);
416 | /* return < 0 if exception, or TRUE/FALSE */
417 | int (*delete_property)(JSContext *ctx, JSValueConst obj, JSAtom prop);
418 | /* return < 0 if exception or TRUE/FALSE */
419 | int (*define_own_property)(JSContext *ctx, JSValueConst this_obj,
420 | JSAtom prop, JSValueConst val,
421 | JSValueConst getter, JSValueConst setter,
422 | int flags);
423 | /* The following methods can be emulated with the previous ones,
424 | so they are usually not needed */
425 | /* return < 0 if exception or TRUE/FALSE */
426 | int (*has_property)(JSContext *ctx, JSValueConst obj, JSAtom atom);
427 | JSValue (*get_property)(JSContext *ctx, JSValueConst obj, JSAtom atom,
428 | JSValueConst receiver);
429 | /* return < 0 if exception or TRUE/FALSE */
430 | int (*set_property)(JSContext *ctx, JSValueConst obj, JSAtom atom,
431 | JSValueConst value, JSValueConst receiver, int flags);
432 | } JSClassExoticMethods;
433 |
434 | typedef void JSClassFinalizer(JSRuntime *rt, JSValue val);
435 | typedef void JSClassGCMark(JSRuntime *rt, JSValueConst val,
436 | JS_MarkFunc *mark_func);
437 | typedef JSValue JSClassCall(JSContext *ctx, JSValueConst func_obj,
438 | JSValueConst this_val, int argc, JSValueConst *argv);
439 |
440 | typedef struct JSClassDef {
441 | const char *class_name;
442 | JSClassFinalizer *finalizer;
443 | JSClassGCMark *gc_mark;
444 | JSClassCall *call;
445 | /* XXX: suppress this indirection ? It is here only to save memory
446 | because only a few classes need these methods */
447 | JSClassExoticMethods *exotic;
448 | } JSClassDef;
449 |
450 | JSClassID JS_NewClassID(JSClassID *pclass_id);
451 | int JS_NewClass(JSRuntime *rt, JSClassID class_id, const JSClassDef *class_def);
452 | int JS_IsRegisteredClass(JSRuntime *rt, JSClassID class_id);
453 |
454 | /* value handling */
455 |
456 | static js_force_inline JSValue JS_NewBool(JSContext *ctx, JS_BOOL val)
457 | {
458 | return JS_MKVAL(JS_TAG_BOOL, val);
459 | }
460 |
461 | static js_force_inline JSValue JS_NewInt32(JSContext *ctx, int32_t val)
462 | {
463 | return JS_MKVAL(JS_TAG_INT, val);
464 | }
465 |
466 | static js_force_inline JSValue JS_NewCatchOffset(JSContext *ctx, int32_t val)
467 | {
468 | return JS_MKVAL(JS_TAG_CATCH_OFFSET, val);
469 | }
470 |
471 | JSValue JS_NewInt64(JSContext *ctx, int64_t v);
472 | JSValue JS_NewBigInt64(JSContext *ctx, int64_t v);
473 | JSValue JS_NewBigUint64(JSContext *ctx, uint64_t v);
474 |
475 | static js_force_inline JSValue JS_NewFloat64(JSContext *ctx, double d)
476 | {
477 | JSValue v;
478 | int32_t val;
479 | union {
480 | double d;
481 | uint64_t u;
482 | } u, t;
483 | u.d = d;
484 | val = (int32_t)d;
485 | t.d = val;
486 | /* -0 cannot be represented as integer, so we compare the bit
487 | representation */
488 | if (u.u == t.u) {
489 | v = JS_MKVAL(JS_TAG_INT, val);
490 | } else {
491 | v = __JS_NewFloat64(ctx, d);
492 | }
493 | return v;
494 | }
495 |
496 | JS_BOOL JS_IsNumber(JSValueConst v);
497 |
498 | static inline JS_BOOL JS_IsInteger(JSValueConst v)
499 | {
500 | int tag = JS_VALUE_GET_TAG(v);
501 | return tag == JS_TAG_INT || tag == JS_TAG_BIG_INT;
502 | }
503 |
504 | static inline JS_BOOL JS_IsBigFloat(JSValueConst v)
505 | {
506 | int tag = JS_VALUE_GET_TAG(v);
507 | return tag == JS_TAG_BIG_FLOAT;
508 | }
509 |
510 | static inline JS_BOOL JS_IsBool(JSValueConst v)
511 | {
512 | return JS_VALUE_GET_TAG(v) == JS_TAG_BOOL;
513 | }
514 |
515 | static inline JS_BOOL JS_IsNull(JSValueConst v)
516 | {
517 | return JS_VALUE_GET_TAG(v) == JS_TAG_NULL;
518 | }
519 |
520 | static inline JS_BOOL JS_IsUndefined(JSValueConst v)
521 | {
522 | return JS_VALUE_GET_TAG(v) == JS_TAG_UNDEFINED;
523 | }
524 |
525 | static inline JS_BOOL JS_IsException(JSValueConst v)
526 | {
527 | return js_unlikely(JS_VALUE_GET_TAG(v) == JS_TAG_EXCEPTION);
528 | }
529 |
530 | static inline JS_BOOL JS_IsUninitialized(JSValueConst v)
531 | {
532 | return js_unlikely(JS_VALUE_GET_TAG(v) == JS_TAG_UNINITIALIZED);
533 | }
534 |
535 | static inline JS_BOOL JS_IsString(JSValueConst v)
536 | {
537 | return JS_VALUE_GET_TAG(v) == JS_TAG_STRING;
538 | }
539 |
540 | static inline JS_BOOL JS_IsSymbol(JSValueConst v)
541 | {
542 | return JS_VALUE_GET_TAG(v) == JS_TAG_SYMBOL;
543 | }
544 |
545 | static inline JS_BOOL JS_IsObject(JSValueConst v)
546 | {
547 | return JS_VALUE_GET_TAG(v) == JS_TAG_OBJECT;
548 | }
549 |
550 | JSValue JS_Throw(JSContext *ctx, JSValue obj);
551 | JSValue JS_GetException(JSContext *ctx);
552 | JS_BOOL JS_IsError(JSContext *ctx, JSValueConst val);
553 | void JS_EnableIsErrorProperty(JSContext *ctx, JS_BOOL enable);
554 | void JS_ResetUncatchableError(JSContext *ctx);
555 | JSValue JS_NewError(JSContext *ctx);
556 | JSValue __js_printf_like(2, 3) JS_ThrowSyntaxError(JSContext *ctx, const char *fmt, ...);
557 | JSValue __js_printf_like(2, 3) JS_ThrowTypeError(JSContext *ctx, const char *fmt, ...);
558 | JSValue __js_printf_like(2, 3) JS_ThrowReferenceError(JSContext *ctx, const char *fmt, ...);
559 | JSValue __js_printf_like(2, 3) JS_ThrowRangeError(JSContext *ctx, const char *fmt, ...);
560 | JSValue __js_printf_like(2, 3) JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...);
561 | JSValue JS_ThrowOutOfMemory(JSContext *ctx);
562 |
563 | void __JS_FreeValue(JSContext *ctx, JSValue v);
564 | static inline void JS_FreeValue(JSContext *ctx, JSValue v)
565 | {
566 | if (JS_VALUE_HAS_REF_COUNT(v)) {
567 | JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
568 | if (--p->ref_count <= 0) {
569 | __JS_FreeValue(ctx, v);
570 | }
571 | }
572 | }
573 | void __JS_FreeValueRT(JSRuntime *rt, JSValue v);
574 | static inline void JS_FreeValueRT(JSRuntime *rt, JSValue v)
575 | {
576 | if (JS_VALUE_HAS_REF_COUNT(v)) {
577 | JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
578 | if (--p->ref_count <= 0) {
579 | __JS_FreeValueRT(rt, v);
580 | }
581 | }
582 | }
583 |
584 | static inline JSValue JS_DupValue(JSContext *ctx, JSValueConst v)
585 | {
586 | if (JS_VALUE_HAS_REF_COUNT(v)) {
587 | JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
588 | p->ref_count++;
589 | }
590 | return (JSValue)v;
591 | }
592 |
593 | static inline JSValue JS_DupValueRT(JSRuntime *rt, JSValueConst v)
594 | {
595 | if (JS_VALUE_HAS_REF_COUNT(v)) {
596 | JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
597 | p->ref_count++;
598 | }
599 | return (JSValue)v;
600 | }
601 |
602 | int JS_ToBool(JSContext *ctx, JSValueConst val); /* return -1 for JS_EXCEPTION */
603 | int JS_ToInt32(JSContext *ctx, int32_t *pres, JSValueConst val);
604 | static int inline JS_ToUint32(JSContext *ctx, uint32_t *pres, JSValueConst val)
605 | {
606 | return JS_ToInt32(ctx, (int32_t*)pres, val);
607 | }
608 | int JS_ToInt64(JSContext *ctx, int64_t *pres, JSValueConst val);
609 | int JS_ToIndex(JSContext *ctx, uint64_t *plen, JSValueConst val);
610 | int JS_ToFloat64(JSContext *ctx, double *pres, JSValueConst val);
611 | int JS_ToBigInt64(JSContext *ctx, int64_t *pres, JSValueConst val);
612 |
613 | JSValue JS_NewStringLen(JSContext *ctx, const char *str1, size_t len1);
614 | JSValue JS_NewString(JSContext *ctx, const char *str);
615 | JSValue JS_NewAtomString(JSContext *ctx, const char *str);
616 | JSValue JS_ToString(JSContext *ctx, JSValueConst val);
617 | JSValue JS_ToPropertyKey(JSContext *ctx, JSValueConst val);
618 | const char *JS_ToCStringLen2(JSContext *ctx, size_t *plen, JSValueConst val1, JS_BOOL cesu8);
619 | static inline const char *JS_ToCStringLen(JSContext *ctx, size_t *plen, JSValueConst val1)
620 | {
621 | return JS_ToCStringLen2(ctx, plen, val1, 0);
622 | }
623 | static inline const char *JS_ToCString(JSContext *ctx, JSValueConst val1)
624 | {
625 | return JS_ToCStringLen2(ctx, NULL, val1, 0);
626 | }
627 | void JS_FreeCString(JSContext *ctx, const char *ptr);
628 |
629 | JSValue JS_NewObjectProtoClass(JSContext *ctx, JSValueConst proto, JSClassID class_id);
630 | JSValue JS_NewObjectClass(JSContext *ctx, int class_id);
631 | JSValue JS_NewObjectProto(JSContext *ctx, JSValueConst proto);
632 | JSValue JS_NewObject(JSContext *ctx);
633 |
634 | JS_BOOL JS_IsFunction(JSContext* ctx, JSValueConst val);
635 | JS_BOOL JS_IsConstructor(JSContext* ctx, JSValueConst val);
636 |
637 | JSValue JS_NewArray(JSContext *ctx);
638 | int JS_IsArray(JSContext *ctx, JSValueConst val);
639 |
640 | JSValue JS_GetPropertyInternal(JSContext *ctx, JSValueConst obj,
641 | JSAtom prop, JSValueConst receiver,
642 | JS_BOOL throw_ref_error);
643 | static js_force_inline JSValue JS_GetProperty(JSContext *ctx, JSValueConst this_obj,
644 | JSAtom prop)
645 | {
646 | return JS_GetPropertyInternal(ctx, this_obj, prop, this_obj, 0);
647 | }
648 | JSValue JS_GetPropertyStr(JSContext *ctx, JSValueConst this_obj,
649 | const char *prop);
650 | JSValue JS_GetPropertyUint32(JSContext *ctx, JSValueConst this_obj,
651 | uint32_t idx);
652 |
653 | int JS_SetPropertyInternal(JSContext *ctx, JSValueConst this_obj,
654 | JSAtom prop, JSValue val,
655 | int flags);
656 | static inline int JS_SetProperty(JSContext *ctx, JSValueConst this_obj,
657 | JSAtom prop, JSValue val)
658 | {
659 | return JS_SetPropertyInternal(ctx, this_obj, prop, val, JS_PROP_THROW);
660 | }
661 | int JS_SetPropertyUint32(JSContext *ctx, JSValueConst this_obj,
662 | uint32_t idx, JSValue val);
663 | int JS_SetPropertyInt64(JSContext *ctx, JSValueConst this_obj,
664 | int64_t idx, JSValue val);
665 | int JS_SetPropertyStr(JSContext *ctx, JSValueConst this_obj,
666 | const char *prop, JSValue val);
667 | int JS_HasProperty(JSContext *ctx, JSValueConst this_obj, JSAtom prop);
668 | int JS_IsExtensible(JSContext *ctx, JSValueConst obj);
669 | int JS_PreventExtensions(JSContext *ctx, JSValueConst obj);
670 | int JS_DeleteProperty(JSContext *ctx, JSValueConst obj, JSAtom prop, int flags);
671 | int JS_SetPrototype(JSContext *ctx, JSValueConst obj, JSValueConst proto_val);
672 | JSValueConst JS_GetPrototype(JSContext *ctx, JSValueConst val);
673 |
674 | #define JS_GPN_STRING_MASK (1 << 0)
675 | #define JS_GPN_SYMBOL_MASK (1 << 1)
676 | #define JS_GPN_PRIVATE_MASK (1 << 2)
677 | /* only include the enumerable properties */
678 | #define JS_GPN_ENUM_ONLY (1 << 4)
679 | /* set theJSPropertyEnum.is_enumerable field */
680 | #define JS_GPN_SET_ENUM (1 << 5)
681 |
682 | int JS_GetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **ptab,
683 | uint32_t *plen, JSValueConst obj, int flags);
684 | int JS_GetOwnProperty(JSContext *ctx, JSPropertyDescriptor *desc,
685 | JSValueConst obj, JSAtom prop);
686 |
687 | JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len,
688 | const char *filename);
689 | JSValue JS_Call(JSContext *ctx, JSValueConst func_obj, JSValueConst this_obj,
690 | int argc, JSValueConst *argv);
691 | JSValue JS_Invoke(JSContext *ctx, JSValueConst this_val, JSAtom atom,
692 | int argc, JSValueConst *argv);
693 | JSValue JS_CallConstructor(JSContext *ctx, JSValueConst func_obj,
694 | int argc, JSValueConst *argv);
695 | JSValue JS_CallConstructor2(JSContext *ctx, JSValueConst func_obj,
696 | JSValueConst new_target,
697 | int argc, JSValueConst *argv);
698 | JS_BOOL JS_DetectModule(const char *input, size_t input_len);
699 | JSValue JS_Eval(JSContext *ctx, const char *input, size_t input_len,
700 | const char *filename, int eval_flags);
701 | JSValue JS_EvalFunction(JSContext *ctx, JSValue fun_obj);
702 | JSValue JS_GetGlobalObject(JSContext *ctx);
703 | int JS_IsInstanceOf(JSContext *ctx, JSValueConst val, JSValueConst obj);
704 | int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj,
705 | JSAtom prop, JSValueConst val,
706 | JSValueConst getter, JSValueConst setter, int flags);
707 | int JS_DefinePropertyValue(JSContext *ctx, JSValueConst this_obj,
708 | JSAtom prop, JSValue val, int flags);
709 | int JS_DefinePropertyValueUint32(JSContext *ctx, JSValueConst this_obj,
710 | uint32_t idx, JSValue val, int flags);
711 | int JS_DefinePropertyValueStr(JSContext *ctx, JSValueConst this_obj,
712 | const char *prop, JSValue val, int flags);
713 | int JS_DefinePropertyGetSet(JSContext *ctx, JSValueConst this_obj,
714 | JSAtom prop, JSValue getter, JSValue setter,
715 | int flags);
716 | void JS_SetOpaque(JSValue obj, void *opaque);
717 | void *JS_GetOpaque(JSValueConst obj, JSClassID class_id);
718 | void *JS_GetOpaque2(JSContext *ctx, JSValueConst obj, JSClassID class_id);
719 |
720 | typedef void JSFreeArrayBufferDataFunc(JSRuntime *rt, void *opaque, void *ptr);
721 | JSValue JS_NewArrayBuffer(JSContext *ctx, uint8_t *buf, size_t len,
722 | JSFreeArrayBufferDataFunc *free_func, void *opaque,
723 | JS_BOOL is_shared);
724 | JSValue JS_NewArrayBufferCopy(JSContext *ctx, const uint8_t *buf, size_t len);
725 | void JS_DetachArrayBuffer(JSContext *ctx, JSValueConst obj);
726 | uint8_t *JS_GetArrayBuffer(JSContext *ctx, size_t *psize, JSValueConst obj);
727 |
728 | JSValue JS_NewPromiseCapability(JSContext *ctx, JSValue *resolving_funcs);
729 |
730 | /* return != 0 if the JS code needs to be interrupted */
731 | typedef int JSInterruptHandler(JSRuntime *rt, void *opaque);
732 | void JS_SetInterruptHandler(JSRuntime *rt, JSInterruptHandler *cb, void *opaque);
733 | /* if can_block is TRUE, Atomics.wait() can be used */
734 | void JS_SetCanBlock(JSRuntime *rt, JS_BOOL can_block);
735 |
736 | typedef struct JSModuleDef JSModuleDef;
737 |
738 | /* return the module specifier (allocated with js_malloc()) or NULL if
739 | exception */
740 | typedef char *JSModuleNormalizeFunc(JSContext *ctx,
741 | const char *module_base_name,
742 | const char *module_name, void *opaque);
743 | typedef JSModuleDef *JSModuleLoaderFunc(JSContext *ctx,
744 | const char *module_name, void *opaque);
745 |
746 | /* module_normalize = NULL is allowed and invokes the default module
747 | filename normalizer */
748 | void JS_SetModuleLoaderFunc(JSRuntime *rt,
749 | JSModuleNormalizeFunc *module_normalize,
750 | JSModuleLoaderFunc *module_loader, void *opaque);
751 | /* return the import.meta object of a module */
752 | JSValue JS_GetImportMeta(JSContext *ctx, JSModuleDef *m);
753 | JSAtom JS_GetModuleName(JSContext *ctx, JSModuleDef *m);
754 |
755 | /* JS Job support */
756 |
757 | typedef JSValue JSJobFunc(JSContext *ctx, int argc, JSValueConst *argv);
758 | int JS_EnqueueJob(JSContext *ctx, JSJobFunc *job_func, int argc, JSValueConst *argv);
759 |
760 | JS_BOOL JS_IsJobPending(JSRuntime *rt);
761 | int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx);
762 |
763 | /* Object Writer/Reader (currently only used to handle precompiled code) */
764 | #define JS_WRITE_OBJ_BYTECODE (1 << 0) /* allow function/module */
765 | #define JS_WRITE_OBJ_BSWAP (1 << 1) /* byte swapped output */
766 | uint8_t *JS_WriteObject(JSContext *ctx, size_t *psize, JSValueConst obj,
767 | int flags);
768 | #define JS_READ_OBJ_BYTECODE (1 << 0) /* allow function/module */
769 | #define JS_READ_OBJ_ROM_DATA (1 << 1) /* avoid duplicating 'buf' data */
770 | JSValue JS_ReadObject(JSContext *ctx, const uint8_t *buf, size_t buf_len,
771 | int flags);
772 | /* load the dependencies of the module 'obj'. Useful when JS_ReadObject()
773 | returns a module. */
774 | int JS_ResolveModule(JSContext *ctx, JSValueConst obj);
775 |
776 | /* C function definition */
777 | typedef enum JSCFunctionEnum { /* XXX: should rename for namespace isolation */
778 | JS_CFUNC_generic,
779 | JS_CFUNC_generic_magic,
780 | JS_CFUNC_constructor,
781 | JS_CFUNC_constructor_magic,
782 | JS_CFUNC_constructor_or_func,
783 | JS_CFUNC_constructor_or_func_magic,
784 | JS_CFUNC_f_f,
785 | JS_CFUNC_f_f_f,
786 | JS_CFUNC_getter,
787 | JS_CFUNC_setter,
788 | JS_CFUNC_getter_magic,
789 | JS_CFUNC_setter_magic,
790 | JS_CFUNC_iterator_next,
791 | } JSCFunctionEnum;
792 |
793 | typedef union JSCFunctionType {
794 | JSCFunction *generic;
795 | JSValue (*generic_magic)(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic);
796 | JSCFunction *constructor;
797 | JSValue (*constructor_magic)(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv, int magic);
798 | JSCFunction *constructor_or_func;
799 | double (*f_f)(double);
800 | double (*f_f_f)(double, double);
801 | JSValue (*getter)(JSContext *ctx, JSValueConst this_val);
802 | JSValue (*setter)(JSContext *ctx, JSValueConst this_val, JSValueConst val);
803 | JSValue (*getter_magic)(JSContext *ctx, JSValueConst this_val, int magic);
804 | JSValue (*setter_magic)(JSContext *ctx, JSValueConst this_val, JSValueConst val, int magic);
805 | JSValue (*iterator_next)(JSContext *ctx, JSValueConst this_val,
806 | int argc, JSValueConst *argv, int *pdone, int magic);
807 | } JSCFunctionType;
808 |
809 | JSValue JS_NewCFunction2(JSContext *ctx, JSCFunction *func,
810 | const char *name,
811 | int length, JSCFunctionEnum cproto, int magic);
812 | JSValue JS_NewCFunctionData(JSContext *ctx, JSCFunctionData *func,
813 | int length, int magic, int data_len,
814 | JSValueConst *data);
815 |
816 | static inline JSValue JS_NewCFunction(JSContext *ctx, JSCFunction *func, const char *name,
817 | int length)
818 | {
819 | return JS_NewCFunction2(ctx, func, name, length, JS_CFUNC_generic, 0);
820 | }
821 |
822 | static inline JSValue JS_NewCFunctionMagic(JSContext *ctx, JSCFunctionMagic *func,
823 | const char *name,
824 | int length, JSCFunctionEnum cproto, int magic)
825 | {
826 | return JS_NewCFunction2(ctx, (JSCFunction *)func, name, length, cproto, magic);
827 | }
828 |
829 | /* C property definition */
830 |
831 | typedef struct JSCFunctionListEntry {
832 | const char *name;
833 | uint8_t prop_flags;
834 | uint8_t def_type;
835 | int16_t magic;
836 | union {
837 | struct {
838 | uint8_t length; /* XXX: should move outside union */
839 | uint8_t cproto; /* XXX: should move outside union */
840 | JSCFunctionType cfunc;
841 | } func;
842 | struct {
843 | JSCFunctionType get;
844 | JSCFunctionType set;
845 | } getset;
846 | struct {
847 | const char *name;
848 | int base;
849 | } alias;
850 | struct {
851 | const struct JSCFunctionListEntry *tab;
852 | int len;
853 | } prop_list;
854 | const char *str;
855 | int32_t i32;
856 | int64_t i64;
857 | double f64;
858 | } u;
859 | } JSCFunctionListEntry;
860 |
861 | #define JS_DEF_CFUNC 0
862 | #define JS_DEF_CGETSET 1
863 | #define JS_DEF_CGETSET_MAGIC 2
864 | #define JS_DEF_PROP_STRING 3
865 | #define JS_DEF_PROP_INT32 4
866 | #define JS_DEF_PROP_INT64 5
867 | #define JS_DEF_PROP_DOUBLE 6
868 | #define JS_DEF_PROP_UNDEFINED 7
869 | #define JS_DEF_OBJECT 8
870 | #define JS_DEF_ALIAS 9
871 |
872 | #define JS_CFUNC_DEF(name, length, func1) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, 0, .u.func = { length, JS_CFUNC_generic, { .generic = func1 } } }
873 | #define JS_CFUNC_MAGIC_DEF(name, length, func1, magic) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, magic, .u.func = { length, JS_CFUNC_generic_magic, { .generic_magic = func1 } } }
874 | #define JS_CFUNC_SPECIAL_DEF(name, length, cproto, func1) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, 0, .u.func = { length, JS_CFUNC_ ## cproto, { .cproto = func1 } } }
875 | #define JS_ITERATOR_NEXT_DEF(name, length, func1, magic) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_CFUNC, magic, .u.func = { length, JS_CFUNC_iterator_next, { .iterator_next = func1 } } }
876 | #define JS_CGETSET_DEF(name, fgetter, fsetter) { name, JS_PROP_CONFIGURABLE, JS_DEF_CGETSET, 0, .u.getset.get.getter = fgetter, .u.getset.set.setter = fsetter }
877 | #define JS_CGETSET_MAGIC_DEF(name, fgetter, fsetter, magic) { name, JS_PROP_CONFIGURABLE, JS_DEF_CGETSET_MAGIC, magic, .u.getset.get.getter_magic = fgetter, .u.getset.set.setter_magic = fsetter }
878 | #define JS_PROP_STRING_DEF(name, cstr, prop_flags) { name, prop_flags, JS_DEF_PROP_STRING, 0, .u.str = cstr }
879 | #define JS_PROP_INT32_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_INT32, 0, .u.i32 = val }
880 | #define JS_PROP_INT64_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_INT64, 0, .u.i64 = val }
881 | #define JS_PROP_DOUBLE_DEF(name, val, prop_flags) { name, prop_flags, JS_DEF_PROP_DOUBLE, 0, .u.f64 = val }
882 | #define JS_PROP_UNDEFINED_DEF(name, prop_flags) { name, prop_flags, JS_DEF_PROP_UNDEFINED, 0, .u.i32 = 0 }
883 | #define JS_OBJECT_DEF(name, tab, len, prop_flags) { name, prop_flags, JS_DEF_OBJECT, 0, .u.prop_list = { tab, len } }
884 | #define JS_ALIAS_DEF(name, from) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_ALIAS, 0, .u.alias = { from, -1 } }
885 | #define JS_ALIAS_BASE_DEF(name, from, base) { name, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE, JS_DEF_ALIAS, 0, .u.alias = { from, base } }
886 |
887 | void JS_SetPropertyFunctionList(JSContext *ctx, JSValueConst obj,
888 | const JSCFunctionListEntry *tab,
889 | int len);
890 |
891 | /* C module definition */
892 |
893 | typedef int JSModuleInitFunc(JSContext *ctx, JSModuleDef *m);
894 |
895 | JSModuleDef *JS_NewCModule(JSContext *ctx, const char *name_str,
896 | JSModuleInitFunc *func);
897 | /* can only be called before the module is instantiated */
898 | int JS_AddModuleExport(JSContext *ctx, JSModuleDef *m, const char *name_str);
899 | int JS_AddModuleExportList(JSContext *ctx, JSModuleDef *m,
900 | const JSCFunctionListEntry *tab, int len);
901 | /* can only be called after the module is instantiated */
902 | int JS_SetModuleExport(JSContext *ctx, JSModuleDef *m, const char *export_name,
903 | JSValue val);
904 | int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m,
905 | const JSCFunctionListEntry *tab, int len);
906 |
907 | #undef js_unlikely
908 | #undef js_force_inline
909 |
910 | #ifdef __cplusplus
911 | } /* extern "C" { */
912 | #endif
913 |
914 | #endif /* QUICKJS_H */
915 |
--------------------------------------------------------------------------------
/std_m.js:
--------------------------------------------------------------------------------
1 | //import * as sstd from 'std';
2 | //unix c中一切皆文件。FILE* stdin,stdout,stderr;
3 | //https://www.zhihu.com/question/24030687
4 |
5 | var file = std.open('std_open_file.js','w');
6 | file.puts('var file = std.open(\"std_open_file.txt\",\"w\");\n');
7 | file.puts('file.puts(\'std_open_file line1\\n\');\n');
8 | file.puts('file.puts(\'std_open_file line2\\n\');\n');
9 | file.puts('file.close();\n');
10 | file.close();
11 | std.loadScript('std_open_file.js');
12 | var rdfile = std.open("std_open_file.txt","r");
13 | do{
14 | console.log(rdfile.getline());
15 | }while(!rdfile.eof());
16 | rdfile.close();
17 |
18 | //1、参考quickjs怎么写curl的
19 | //2、自己写 导出c函数
20 | // -c编写预备 gcc,makefile
21 |
22 |
--------------------------------------------------------------------------------