├── .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 | --------------------------------------------------------------------------------