├── .editorconfig ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ ├── cmake-debug.yml │ └── cmake-release.yml ├── .gitignore ├── .gitmodules ├── .vscode └── settings.json ├── CMakeLists.txt ├── README.md ├── examples ├── fib.c ├── fib_module.js ├── hello.js ├── hello_module.js ├── pi_bigdecimal.js ├── pi_bigfloat.js ├── pi_bigint.js ├── point.c ├── test_fib.js └── test_point.js ├── include └── quickjs │ ├── cutils.h │ ├── libbf.h │ ├── libregexp-opcode.h │ ├── libregexp.h │ ├── libunicode-table.h │ ├── libunicode.h │ ├── list.h │ ├── quickjs-atom.h │ ├── quickjs-opcode.h │ └── quickjs.h ├── scripts ├── build.sh ├── ci.sh ├── test.sh ├── unicode_download.sh ├── unicode_gen.c └── unicode_gen_def.h ├── src ├── CMakeLists.txt ├── cli │ ├── qbc.c │ ├── qjs.c │ ├── qjsc.c │ ├── qjscalc.c │ ├── qjscalc.js │ ├── quickjs-libc.c │ ├── quickjs-libc.h │ ├── repl.c │ ├── repl.js │ └── run-test262.c ├── core │ ├── base.h │ ├── builtins │ │ ├── js-array.c │ │ ├── js-array.h │ │ ├── js-async-function.c │ │ ├── js-async-function.h │ │ ├── js-async-generator.c │ │ ├── js-async-generator.h │ │ ├── js-atomics.c │ │ ├── js-atomics.h │ │ ├── js-big-num.c │ │ ├── js-big-num.h │ │ ├── js-boolean.c │ │ ├── js-boolean.h │ │ ├── js-closures.c │ │ ├── js-closures.h │ │ ├── js-date.c │ │ ├── js-date.h │ │ ├── js-function.c │ │ ├── js-function.h │ │ ├── js-generator.c │ │ ├── js-generator.h │ │ ├── js-json.c │ │ ├── js-json.h │ │ ├── js-map.c │ │ ├── js-map.h │ │ ├── js-math.c │ │ ├── js-math.h │ │ ├── js-number.c │ │ ├── js-number.h │ │ ├── js-object.c │ │ ├── js-object.h │ │ ├── js-operator.c │ │ ├── js-operator.h │ │ ├── js-promise.c │ │ ├── js-promise.h │ │ ├── js-proxy.c │ │ ├── js-proxy.h │ │ ├── js-reflect.c │ │ ├── js-reflect.h │ │ ├── js-regexp.c │ │ ├── js-regexp.h │ │ ├── js-string.c │ │ ├── js-string.h │ │ ├── js-symbol.c │ │ ├── js-symbol.h │ │ ├── js-typed-array.c │ │ └── js-typed-array.h │ ├── bytecode.c │ ├── bytecode.h │ ├── conversion.c │ ├── conversion.h │ ├── exception.c │ ├── exception.h │ ├── function.c │ ├── function.h │ ├── gc.c │ ├── gc.h │ ├── ic.c │ ├── ic.h │ ├── malloc.c │ ├── malloc.h │ ├── memory.c │ ├── memory.h │ ├── module.c │ ├── module.h │ ├── object.c │ ├── object.h │ ├── parser.c │ ├── parser.h │ ├── runtime.c │ ├── runtime.h │ ├── shape.c │ ├── shape.h │ ├── string.c │ ├── string.h │ └── types.h ├── crates │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── README.md │ ├── cbindgen.toml │ ├── quickjs │ │ ├── Cargo.toml │ │ ├── build.rs │ │ └── src │ │ │ └── lib.rs │ ├── quickjs_backtrace │ │ ├── Cargo.toml │ │ └── src │ │ │ └── lib.rs │ ├── quickjs_common │ │ ├── Cargo.toml │ │ └── src │ │ │ └── lib.rs │ └── quickjs_gc │ │ ├── Cargo.toml │ │ └── src │ │ ├── lib.rs │ │ └── record.rs ├── cutils.c ├── libbf.c ├── libregexp.c └── libunicode.c └── tests ├── bjson.c ├── microbench.js ├── test-es5.conf ├── test262.conf ├── test262.patch ├── test_bignum.js ├── test_bjson.js ├── test_builtin.js ├── test_closure.js ├── test_ic_atom_free.js ├── test_language.js ├── test_line_column_num.js ├── test_loop.js ├── test_op_overloading.js ├── test_promise_gc_crash.js ├── test_qjscalc.js ├── test_std.js ├── test_worker.js └── test_worker_module.js /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*.{c,cpp,cc,h,hpp,txt}] 4 | indent_size = 2 5 | indent_style = space -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/cmake-debug.yml: -------------------------------------------------------------------------------- 1 | name: Build Debug target 2 | 3 | on: 4 | push: 5 | branches: ["main"] 6 | pull_request: 7 | branches: ["main"] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v3 15 | with: 16 | submodules: recursive 17 | 18 | - name: Cache dependencies 19 | uses: actions/cache@v3 20 | with: 21 | path: | 22 | ~/.cargo 23 | key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} 24 | 25 | - name: Install Rust toolchain 26 | uses: actions-rs/toolchain@v1 27 | with: 28 | profile: minimal 29 | toolchain: nightly 30 | override: true 31 | 32 | - name: Install cbindgen 33 | run: | 34 | if ! command -v cbindgen &> /dev/null 35 | then 36 | cargo install --force cbindgen 37 | fi 38 | 39 | - name: Install Ninja 40 | run: sudo apt install ninja-build 41 | 42 | - name: Configure CMake 43 | run: cmake -G Ninja -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=Debug 44 | 45 | - name: Build target 46 | run: cmake --build ${{github.workspace}}/build --target qjs run-test262 -j 8 47 | 48 | - name: Test 49 | run: ./bin/qjs -e 'console.log("Hello, World!")' 50 | -------------------------------------------------------------------------------- /.github/workflows/cmake-release.yml: -------------------------------------------------------------------------------- 1 | name: Build Release target 2 | 3 | on: 4 | push: 5 | branches: ["main"] 6 | pull_request: 7 | branches: ["main"] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v3 15 | with: 16 | submodules: recursive 17 | 18 | - name: Cache dependencies 19 | uses: actions/cache@v3 20 | with: 21 | path: | 22 | ~/.cargo 23 | ~/.ninja 24 | key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} 25 | 26 | - name: Install Rust toolchain 27 | uses: actions-rs/toolchain@v1 28 | with: 29 | profile: minimal 30 | toolchain: nightly 31 | override: true 32 | 33 | - name: Install cbindgen 34 | run: | 35 | if ! command -v cbindgen &> /dev/null 36 | then 37 | cargo install --force cbindgen 38 | fi 39 | 40 | - name: Install Ninja 41 | run: sudo apt install ninja-build 42 | 43 | - name: Configure CMake 44 | run: cmake -G Ninja -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=Release 45 | 46 | - name: Build target 47 | run: cmake --build ${{github.workspace}}/build --target qjs run-test262 -j 8 48 | 49 | - name: Test 50 | run: ./bin/qjs -e 'console.log("Hello, World!")' 51 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | /.idea/ 17 | cmake-build-* 18 | lib/ 19 | bin/ 20 | build/ 21 | test262/ 22 | test262*.txt -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "vendor/mimalloc"] 2 | path = vendor/mimalloc 3 | url = https://github.com/microsoft/mimalloc.git 4 | branch = v2.1.2 5 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "rust-analyzer.linkedProjects": ["src/crates/Cargo.toml"], 3 | "files.associations": { 4 | "quickjs-rs.h": "c", 5 | "js-array.h": "c", 6 | "types.h": "c", 7 | "list.h": "c", 8 | "js-function.h": "c" 9 | }, 10 | "git.inputValidationLength": 72 11 | } 12 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.9.4) 2 | project(QUICKJS C) 3 | 4 | set(C_STANDARD 17) 5 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 6 | set(MI_OVERRIDE OFF) 7 | 8 | # config build target: "Debug" or "Release" 9 | if (CMAKE_BUILD_TYPE STREQUAL "Debug") 10 | set(COMPILE_FLAGS ${COMPILE_FLAGS} -g) 11 | elseif(CMAKE_BUILD_TYPE STREQUAL "Release") 12 | set(COMPILE_FLAGS ${COMPILE_FLAGS} -O3) 13 | endif() 14 | 15 | # add -lm if on Linux to handle math.h 16 | # see: https://askubuntu.com/a/332919 17 | if(CMAKE_SYSTEM_NAME STREQUAL "Linux") 18 | list(APPEND LINK_LIBRARIES "m") 19 | endif() 20 | 21 | # set OSX arch to x86_64 eve if on M1 22 | # TODO: support cross-compiling for M1, android etc. 23 | # https://corrosion-rs.github.io/corrosion/usage.html 24 | set(CMAKE_OSX_ARCHITECTURES x86_64) 25 | 26 | # enable interprocedural optimization (IPO/LTO) if supported 27 | include(CheckIPOSupported) 28 | check_ipo_supported(RESULT supported OUTPUT error) 29 | if( supported AND NOT CMAKE_BUILD_TYPE STREQUAL "Debug") 30 | set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) 31 | endif() 32 | 33 | # config binary output path: bin/ 34 | # config library output path: lib/ 35 | set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) 36 | set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib) 37 | 38 | # include c headers 39 | include_directories(${PROJECT_SOURCE_DIR}/include) 40 | include_directories(${PROJECT_SOURCE_DIR}/vendor/mimalloc/include) 41 | include_directories(${PROJECT_SOURCE_DIR}/src/crates/include) 42 | add_subdirectory(src) 43 | add_subdirectory(vendor/mimalloc) 44 | 45 | # compile flags 46 | set(COMPILE_FLAGS -Wall -MMD -Wno-array-bounds -Wno-format-truncation) 47 | 48 | add_compile_options(${COMPILE_FLAGS}) 49 | add_compile_definitions( 50 | _GNU_SOURCE 51 | CONFIG_BIGNUM 52 | CONFIG_VERSION=${QUICKJS_VERSION} 53 | ) 54 | 55 | set(QJSC_CONFIG -DCONFIG_PREFIX="/usr/local" -DCONFIG_LTO) 56 | set(QJSC_EXE "${EXECUTABLE_OUTPUT_PATH}/qjsc") 57 | set(QJS_CONFIG ${QJSC_CONFIG} -DCONFIG_CC="clang") 58 | 59 | # build qjsc (quickjs compiler) 60 | add_executable(qjsc 61 | src/cli/qjsc.c 62 | src/cli/quickjs-libc.c 63 | ) 64 | target_link_libraries(qjsc quickjs ${LINK_LIBRARIES} mimalloc-static) 65 | target_compile_definitions(qjsc PUBLIC ${QJSC_CONFIG}) 66 | 67 | # build qjs (quickjs interpreter) 68 | add_executable(qjs 69 | src/cli/qjs.c 70 | src/cli/quickjs-libc.c 71 | src/cli/repl.c 72 | src/cli/qjscalc.c 73 | ) 74 | target_link_libraries(qjs quickjs ${LINK_LIBRARIES} mimalloc-static) 75 | 76 | # build qbc (new quickjs bytecode compiler) 77 | add_executable(qbc 78 | src/cli/qbc.c 79 | ) 80 | target_link_libraries(qbc quickjs ${LINK_LIBRARIES} mimalloc-static) 81 | 82 | # build run-test262 (quickjs test262 runner) 83 | add_executable(run-test262 84 | src/cli/run-test262.c 85 | src/cli/quickjs-libc.c 86 | ) 87 | target_link_libraries(run-test262 quickjs ${LINK_LIBRARIES} mimalloc-static) 88 | 89 | # generate repl.c and qjscalc.c 90 | # enable it if you modified repl.js or qjscalc.js 91 | # add_custom_command( 92 | # TARGET qjsc POST_BUILD 93 | # COMMAND ${QJSC_EXE} -c -o ${PROJECT_SOURCE_DIR}/repl.c -m ${PROJECT_SOURCE_DIR}/repl.js 94 | # COMMAND ${QJSC_EXE} -fbignum -c -o ${PROJECT_SOURCE_DIR}/qjscalc.c ${PROJECT_SOURCE_DIR}/qjscalc.js 95 | # ) 96 | 97 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # QuickJS 2 | 3 | > A community-driven QuickJS fork. 4 | 5 | ### Optimizations 6 | 7 | In addition to the relevant features and optimizations in the [TODO](https://github.com/openwebf/quickjs/blob/master/TODO) file, the more important optimizations are: 8 | 9 | - [x] Column number 10 | - [ ] Basic Debugger API 11 | - [x] Poly IC 12 | - [x] Self Poly IC 13 | - [x] Prototype Poly IC 14 | - [x] Replace malloc To [mimalloc](https://github.com/microsoft/mimalloc) 15 | - [ ] Improve The Performance Of GC 16 | 17 | In our plan, we first complete the above optimizations and then gradually add the remaining parts. 18 | 19 | ### Develop 20 | 21 | #### Clone 22 | 23 | ```bash 24 | git clone --recurse-submodules https://github.com/openquickjs/quickjs.git 25 | ``` 26 | 27 | #### Install Build Tools 28 | 29 | ```bash 30 | brew install cmake ninja # macOS 31 | sudo apt install cmake ninja-build # Ubuntu 32 | ``` 33 | 34 | The Windows build environment is not yet officially supported. 35 | 36 | #### Build 37 | 38 | ```shell 39 | bash scripts/build.sh # build quickjs qjs 40 | bash scripts/test.sh # run test262 tests 41 | ``` 42 | 43 | You can find `libquickjs.a` in `lib` folder and `qjs` / `run-test262` in `bin` folder. 44 | 45 | 1. If you're using Visual Studio Code, you can use the `CMake Tools` extension to build the program. 46 | 2. If you're using CLion, you can open the project directly to build the program. 47 | 48 | Using VSCode or CLion for regular development is recommended. 49 | 50 | #### Debug 51 | 52 | Install Debug Tools if you need. 53 | 54 | ```bash 55 | brew install lldb # macOS 56 | sudo apt install lldb # Ubuntu 57 | ``` 58 | 59 | If you're using VSCode, you can use the `C/C++` and `Code LLDB` extension to debug. 60 | 61 | ### Tests 62 | 63 | ```bash 64 | Average memory statistics for 75250 tests: 65 | 66 | NAME COUNT SIZE 67 | memory allocated 1011 124975 (123.6 per block) 68 | memory used 967 117030 (0 overhead, 8.2 average slack) 69 | atoms 532 26858 (50.5 per atom) 70 | objects 172 12425 (72.2 per object) 71 | properties 876 15798 (5.1 per object) 72 | shapes 60 13809 (230.2 per shape) 73 | bytecode functions 13 1685 74 | bytecode 13 931 (71.6 per function) 75 | C functions 100 76 | arrays 1 77 | fast arrays 1 78 | elements 1 16 (1.0 per fast array) 79 | 80 | Result: 515/75250 errors, 1392 excluded, 7972 skipped, 515 new 81 | ``` 82 | 83 | 84 | ### Benchmark 85 | 86 | > - Apple M1 Pro 87 | > - macOS Monterey 12.2.1 88 | > - Clang 13.0.0 arm64-apple-darwin21.3.0 89 | 90 | | | bellard/quickjs (2788d71) | openwebf/quickjs (latest) | 91 | | ------------- | ---------- | ---------- | 92 | | Richards | 1188 | 1457 | 93 | | Crypto | 1443 | 1527 | 94 | | RayTrace | 744 | 1995 | 95 | | NavierStokes | 2775 | 2979 | 96 | | DeltaBlue | 1100 | 1595 | 97 | | Total score | 1312 | 1840 (+40.2%) | 98 | | File Size(KB) | 1.3M | 1.4M | -------------------------------------------------------------------------------- /examples/fib.c: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS: Example of C module 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 | #include "../quickjs.h" 25 | 26 | #define countof(x) (sizeof(x) / sizeof((x)[0])) 27 | 28 | static int fib(int n) 29 | { 30 | if (n <= 0) 31 | return 0; 32 | else if (n == 1) 33 | return 1; 34 | else 35 | return fib(n - 1) + fib(n - 2); 36 | } 37 | 38 | static JSValue js_fib(JSContext *ctx, JSValueConst this_val, 39 | int argc, JSValueConst *argv) 40 | { 41 | int n, res; 42 | if (JS_ToInt32(ctx, &n, argv[0])) 43 | return JS_EXCEPTION; 44 | res = fib(n); 45 | return JS_NewInt32(ctx, res); 46 | } 47 | 48 | static const JSCFunctionListEntry js_fib_funcs[] = { 49 | JS_CFUNC_DEF("fib", 1, js_fib ), 50 | }; 51 | 52 | static int js_fib_init(JSContext *ctx, JSModuleDef *m) 53 | { 54 | return JS_SetModuleExportList(ctx, m, js_fib_funcs, 55 | countof(js_fib_funcs)); 56 | } 57 | 58 | #ifdef JS_SHARED_LIBRARY 59 | #define JS_INIT_MODULE js_init_module 60 | #else 61 | #define JS_INIT_MODULE js_init_module_fib 62 | #endif 63 | 64 | JSModuleDef *JS_INIT_MODULE(JSContext *ctx, const char *module_name) 65 | { 66 | JSModuleDef *m; 67 | m = JS_NewCModule(ctx, module_name, js_fib_init); 68 | if (!m) 69 | return NULL; 70 | JS_AddModuleExportList(ctx, m, js_fib_funcs, countof(js_fib_funcs)); 71 | return m; 72 | } 73 | -------------------------------------------------------------------------------- /examples/fib_module.js: -------------------------------------------------------------------------------- 1 | /* fib module */ 2 | export function fib(n) 3 | { 4 | if (n <= 0) 5 | return 0; 6 | else if (n == 1) 7 | return 1; 8 | else 9 | return fib(n - 1) + fib(n - 2); 10 | } 11 | -------------------------------------------------------------------------------- /examples/hello.js: -------------------------------------------------------------------------------- 1 | console.log("Hello World"); 2 | -------------------------------------------------------------------------------- /examples/hello_module.js: -------------------------------------------------------------------------------- 1 | /* example of JS module */ 2 | 3 | import { fib } from "./fib_module.js"; 4 | 5 | console.log("Hello World"); 6 | console.log("fib(10)=", fib(10)); 7 | -------------------------------------------------------------------------------- /examples/pi_bigdecimal.js: -------------------------------------------------------------------------------- 1 | /* 2 | * PI computation in Javascript using the QuickJS bigdecimal type 3 | * (decimal floating point) 4 | */ 5 | "use strict"; 6 | 7 | /* compute PI with a precision of 'prec' digits */ 8 | function calc_pi(prec) { 9 | const CHUD_A = 13591409m; 10 | const CHUD_B = 545140134m; 11 | const CHUD_C = 640320m; 12 | const CHUD_C3 = 10939058860032000m; /* C^3/24 */ 13 | const CHUD_DIGITS_PER_TERM = 14.18164746272548; /* log10(C/12)*3 */ 14 | 15 | /* return [P, Q, G] */ 16 | function chud_bs(a, b, need_G) { 17 | var c, P, Q, G, P1, Q1, G1, P2, Q2, G2, b1; 18 | if (a == (b - 1n)) { 19 | b1 = BigDecimal(b); 20 | G = (2m * b1 - 1m) * (6m * b1 - 1m) * (6m * b1 - 5m); 21 | P = G * (CHUD_B * b1 + CHUD_A); 22 | if (b & 1n) 23 | P = -P; 24 | G = G; 25 | Q = b1 * b1 * b1 * CHUD_C3; 26 | } else { 27 | c = (a + b) >> 1n; 28 | [P1, Q1, G1] = chud_bs(a, c, true); 29 | [P2, Q2, G2] = chud_bs(c, b, need_G); 30 | P = P1 * Q2 + P2 * G1; 31 | Q = Q1 * Q2; 32 | if (need_G) 33 | G = G1 * G2; 34 | else 35 | G = 0m; 36 | } 37 | return [P, Q, G]; 38 | } 39 | 40 | var n, P, Q, G; 41 | /* number of serie terms */ 42 | n = BigInt(Math.ceil(prec / CHUD_DIGITS_PER_TERM)) + 10n; 43 | [P, Q, G] = chud_bs(0n, n, false); 44 | Q = BigDecimal.div(Q, (P + Q * CHUD_A), 45 | { roundingMode: "half-even", 46 | maximumSignificantDigits: prec }); 47 | G = (CHUD_C / 12m) * BigDecimal.sqrt(CHUD_C, 48 | { roundingMode: "half-even", 49 | maximumSignificantDigits: prec }); 50 | return Q * G; 51 | } 52 | 53 | (function() { 54 | var r, n_digits, n_bits; 55 | if (typeof scriptArgs != "undefined") { 56 | if (scriptArgs.length < 2) { 57 | print("usage: pi n_digits"); 58 | return; 59 | } 60 | n_digits = scriptArgs[1] | 0; 61 | } else { 62 | n_digits = 1000; 63 | } 64 | /* we add more digits to reduce the probability of bad rounding for 65 | the last digits */ 66 | r = calc_pi(n_digits + 20); 67 | print(r.toFixed(n_digits, "down")); 68 | })(); 69 | -------------------------------------------------------------------------------- /examples/pi_bigfloat.js: -------------------------------------------------------------------------------- 1 | /* 2 | * PI computation in Javascript using the QuickJS bigfloat type 3 | * (binary floating point) 4 | */ 5 | "use strict"; 6 | 7 | /* compute PI with a precision of 'prec' bits */ 8 | function calc_pi() { 9 | const CHUD_A = 13591409n; 10 | const CHUD_B = 545140134n; 11 | const CHUD_C = 640320n; 12 | const CHUD_C3 = 10939058860032000n; /* C^3/24 */ 13 | const CHUD_BITS_PER_TERM = 47.11041313821584202247; /* log2(C/12)*3 */ 14 | 15 | /* return [P, Q, G] */ 16 | function chud_bs(a, b, need_G) { 17 | var c, P, Q, G, P1, Q1, G1, P2, Q2, G2; 18 | if (a == (b - 1n)) { 19 | G = (2n * b - 1n) * (6n * b - 1n) * (6n * b - 5n); 20 | P = BigFloat(G * (CHUD_B * b + CHUD_A)); 21 | if (b & 1n) 22 | P = -P; 23 | G = BigFloat(G); 24 | Q = BigFloat(b * b * b * CHUD_C3); 25 | } else { 26 | c = (a + b) >> 1n; 27 | [P1, Q1, G1] = chud_bs(a, c, true); 28 | [P2, Q2, G2] = chud_bs(c, b, need_G); 29 | P = P1 * Q2 + P2 * G1; 30 | Q = Q1 * Q2; 31 | if (need_G) 32 | G = G1 * G2; 33 | else 34 | G = 0l; 35 | } 36 | return [P, Q, G]; 37 | } 38 | 39 | var n, P, Q, G; 40 | /* number of serie terms */ 41 | n = BigInt(Math.ceil(BigFloatEnv.prec / CHUD_BITS_PER_TERM)) + 10n; 42 | [P, Q, G] = chud_bs(0n, n, false); 43 | Q = Q / (P + Q * BigFloat(CHUD_A)); 44 | G = BigFloat((CHUD_C / 12n)) * BigFloat.sqrt(BigFloat(CHUD_C)); 45 | return Q * G; 46 | } 47 | 48 | (function() { 49 | var r, n_digits, n_bits; 50 | if (typeof scriptArgs != "undefined") { 51 | if (scriptArgs.length < 2) { 52 | print("usage: pi n_digits"); 53 | return; 54 | } 55 | n_digits = scriptArgs[1]; 56 | } else { 57 | n_digits = 1000; 58 | } 59 | n_bits = Math.ceil(n_digits * Math.log2(10)); 60 | /* we add more bits to reduce the probability of bad rounding for 61 | the last digits */ 62 | BigFloatEnv.setPrec( () => { 63 | r = calc_pi(); 64 | print(r.toFixed(n_digits, BigFloatEnv.RNDZ)); 65 | }, n_bits + 32); 66 | })(); 67 | -------------------------------------------------------------------------------- /examples/pi_bigint.js: -------------------------------------------------------------------------------- 1 | /* 2 | * PI computation in Javascript using the BigInt type 3 | */ 4 | "use strict"; 5 | 6 | /* return floor(log2(a)) for a > 0 and 0 for a = 0 */ 7 | function floor_log2(a) 8 | { 9 | var k_max, a1, k, i; 10 | k_max = 0n; 11 | while ((a >> (2n ** k_max)) != 0n) { 12 | k_max++; 13 | } 14 | k = 0n; 15 | a1 = a; 16 | for(i = k_max - 1n; i >= 0n; i--) { 17 | a1 = a >> (2n ** i); 18 | if (a1 != 0n) { 19 | a = a1; 20 | k |= (1n << i); 21 | } 22 | } 23 | return k; 24 | } 25 | 26 | /* return ceil(log2(a)) for a > 0 */ 27 | function ceil_log2(a) 28 | { 29 | return floor_log2(a - 1n) + 1n; 30 | } 31 | 32 | /* return floor(sqrt(a)) (not efficient but simple) */ 33 | function int_sqrt(a) 34 | { 35 | var l, u, s; 36 | if (a == 0n) 37 | return a; 38 | l = ceil_log2(a); 39 | u = 1n << ((l + 1n) / 2n); 40 | /* u >= floor(sqrt(a)) */ 41 | for(;;) { 42 | s = u; 43 | u = ((a / s) + s) / 2n; 44 | if (u >= s) 45 | break; 46 | } 47 | return s; 48 | } 49 | 50 | /* return pi * 2**prec */ 51 | function calc_pi(prec) { 52 | const CHUD_A = 13591409n; 53 | const CHUD_B = 545140134n; 54 | const CHUD_C = 640320n; 55 | const CHUD_C3 = 10939058860032000n; /* C^3/24 */ 56 | const CHUD_BITS_PER_TERM = 47.11041313821584202247; /* log2(C/12)*3 */ 57 | 58 | /* return [P, Q, G] */ 59 | function chud_bs(a, b, need_G) { 60 | var c, P, Q, G, P1, Q1, G1, P2, Q2, G2; 61 | if (a == (b - 1n)) { 62 | G = (2n * b - 1n) * (6n * b - 1n) * (6n * b - 5n); 63 | P = G * (CHUD_B * b + CHUD_A); 64 | if (b & 1n) 65 | P = -P; 66 | Q = b * b * b * CHUD_C3; 67 | } else { 68 | c = (a + b) >> 1n; 69 | [P1, Q1, G1] = chud_bs(a, c, true); 70 | [P2, Q2, G2] = chud_bs(c, b, need_G); 71 | P = P1 * Q2 + P2 * G1; 72 | Q = Q1 * Q2; 73 | if (need_G) 74 | G = G1 * G2; 75 | else 76 | G = 0n; 77 | } 78 | return [P, Q, G]; 79 | } 80 | 81 | var n, P, Q, G; 82 | /* number of serie terms */ 83 | n = BigInt(Math.ceil(Number(prec) / CHUD_BITS_PER_TERM)) + 10n; 84 | [P, Q, G] = chud_bs(0n, n, false); 85 | Q = (CHUD_C / 12n) * (Q << prec) / (P + Q * CHUD_A); 86 | G = int_sqrt(CHUD_C << (2n * prec)); 87 | return (Q * G) >> prec; 88 | } 89 | 90 | function main(args) { 91 | var r, n_digits, n_bits, out; 92 | if (args.length < 1) { 93 | print("usage: pi n_digits"); 94 | return; 95 | } 96 | n_digits = args[0] | 0; 97 | 98 | /* we add more bits to reduce the probability of bad rounding for 99 | the last digits */ 100 | n_bits = BigInt(Math.ceil(n_digits * Math.log2(10))) + 32n; 101 | r = calc_pi(n_bits); 102 | r = ((10n ** BigInt(n_digits)) * r) >> n_bits; 103 | out = r.toString(); 104 | print(out[0] + "." + out.slice(1)); 105 | } 106 | 107 | var args; 108 | if (typeof scriptArgs != "undefined") { 109 | args = scriptArgs; 110 | args.shift(); 111 | } else if (typeof arguments != "undefined") { 112 | args = arguments; 113 | } else { 114 | /* default: 1000 digits */ 115 | args=[1000]; 116 | } 117 | 118 | main(args); 119 | -------------------------------------------------------------------------------- /examples/point.c: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS: Example of C module with a class 3 | * 4 | * Copyright (c) 2019 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 | #include "../quickjs.h" 25 | #include 26 | 27 | #define countof(x) (sizeof(x) / sizeof((x)[0])) 28 | 29 | /* Point Class */ 30 | 31 | typedef struct { 32 | int x; 33 | int y; 34 | } JSPointData; 35 | 36 | static JSClassID js_point_class_id; 37 | 38 | static void js_point_finalizer(JSRuntime *rt, JSValue val) 39 | { 40 | JSPointData *s = JS_GetOpaque(val, js_point_class_id); 41 | /* Note: 's' can be NULL in case JS_SetOpaque() was not called */ 42 | js_free_rt(rt, s); 43 | } 44 | 45 | static JSValue js_point_ctor(JSContext *ctx, 46 | JSValueConst new_target, 47 | int argc, JSValueConst *argv) 48 | { 49 | JSPointData *s; 50 | JSValue obj = JS_UNDEFINED; 51 | JSValue proto; 52 | 53 | s = js_mallocz(ctx, sizeof(*s)); 54 | if (!s) 55 | return JS_EXCEPTION; 56 | if (JS_ToInt32(ctx, &s->x, argv[0])) 57 | goto fail; 58 | if (JS_ToInt32(ctx, &s->y, argv[1])) 59 | goto fail; 60 | /* using new_target to get the prototype is necessary when the 61 | class is extended. */ 62 | proto = JS_GetPropertyStr(ctx, new_target, "prototype"); 63 | if (JS_IsException(proto)) 64 | goto fail; 65 | obj = JS_NewObjectProtoClass(ctx, proto, js_point_class_id); 66 | JS_FreeValue(ctx, proto); 67 | if (JS_IsException(obj)) 68 | goto fail; 69 | JS_SetOpaque(obj, s); 70 | return obj; 71 | fail: 72 | js_free(ctx, s); 73 | JS_FreeValue(ctx, obj); 74 | return JS_EXCEPTION; 75 | } 76 | 77 | static JSValue js_point_get_xy(JSContext *ctx, JSValueConst this_val, int magic) 78 | { 79 | JSPointData *s = JS_GetOpaque2(ctx, this_val, js_point_class_id); 80 | if (!s) 81 | return JS_EXCEPTION; 82 | if (magic == 0) 83 | return JS_NewInt32(ctx, s->x); 84 | else 85 | return JS_NewInt32(ctx, s->y); 86 | } 87 | 88 | static JSValue js_point_set_xy(JSContext *ctx, JSValueConst this_val, JSValue val, int magic) 89 | { 90 | JSPointData *s = JS_GetOpaque2(ctx, this_val, js_point_class_id); 91 | int v; 92 | if (!s) 93 | return JS_EXCEPTION; 94 | if (JS_ToInt32(ctx, &v, val)) 95 | return JS_EXCEPTION; 96 | if (magic == 0) 97 | s->x = v; 98 | else 99 | s->y = v; 100 | return JS_UNDEFINED; 101 | } 102 | 103 | static JSValue js_point_norm(JSContext *ctx, JSValueConst this_val, 104 | int argc, JSValueConst *argv) 105 | { 106 | JSPointData *s = JS_GetOpaque2(ctx, this_val, js_point_class_id); 107 | if (!s) 108 | return JS_EXCEPTION; 109 | return JS_NewFloat64(ctx, sqrt((double)s->x * s->x + (double)s->y * s->y)); 110 | } 111 | 112 | static JSClassDef js_point_class = { 113 | "Point", 114 | .finalizer = js_point_finalizer, 115 | }; 116 | 117 | static const JSCFunctionListEntry js_point_proto_funcs[] = { 118 | JS_CGETSET_MAGIC_DEF("x", js_point_get_xy, js_point_set_xy, 0), 119 | JS_CGETSET_MAGIC_DEF("y", js_point_get_xy, js_point_set_xy, 1), 120 | JS_CFUNC_DEF("norm", 0, js_point_norm), 121 | }; 122 | 123 | static int js_point_init(JSContext *ctx, JSModuleDef *m) 124 | { 125 | JSValue point_proto, point_class; 126 | 127 | /* create the Point class */ 128 | JS_NewClassID(&js_point_class_id); 129 | JS_NewClass(JS_GetRuntime(ctx), js_point_class_id, &js_point_class); 130 | 131 | point_proto = JS_NewObject(ctx); 132 | JS_SetPropertyFunctionList(ctx, point_proto, js_point_proto_funcs, countof(js_point_proto_funcs)); 133 | 134 | point_class = JS_NewCFunction2(ctx, js_point_ctor, "Point", 2, JS_CFUNC_constructor, 0); 135 | /* set proto.constructor and ctor.prototype */ 136 | JS_SetConstructor(ctx, point_class, point_proto); 137 | JS_SetClassProto(ctx, js_point_class_id, point_proto); 138 | 139 | JS_SetModuleExport(ctx, m, "Point", point_class); 140 | return 0; 141 | } 142 | 143 | JSModuleDef *js_init_module(JSContext *ctx, const char *module_name) 144 | { 145 | JSModuleDef *m; 146 | m = JS_NewCModule(ctx, module_name, js_point_init); 147 | if (!m) 148 | return NULL; 149 | JS_AddModuleExport(ctx, m, "Point"); 150 | return m; 151 | } 152 | -------------------------------------------------------------------------------- /examples/test_fib.js: -------------------------------------------------------------------------------- 1 | /* example of JS module importing a C module */ 2 | 3 | import { fib } from "./fib.so"; 4 | 5 | console.log("Hello World"); 6 | console.log("fib(10)=", fib(10)); 7 | -------------------------------------------------------------------------------- /examples/test_point.js: -------------------------------------------------------------------------------- 1 | /* example of JS module importing a C module */ 2 | import { Point } from "./point.so"; 3 | 4 | function assert(b, str) 5 | { 6 | if (b) { 7 | return; 8 | } else { 9 | throw Error("assertion failed: " + str); 10 | } 11 | } 12 | 13 | class ColorPoint extends Point { 14 | constructor(x, y, color) { 15 | super(x, y); 16 | this.color = color; 17 | } 18 | get_color() { 19 | return this.color; 20 | } 21 | }; 22 | 23 | function main() 24 | { 25 | var pt, pt2; 26 | 27 | pt = new Point(2, 3); 28 | assert(pt.x === 2); 29 | assert(pt.y === 3); 30 | pt.x = 4; 31 | assert(pt.x === 4); 32 | assert(pt.norm() == 5); 33 | 34 | pt2 = new ColorPoint(2, 3, 0xffffff); 35 | assert(pt2.x === 2); 36 | assert(pt2.color === 0xffffff); 37 | assert(pt2.get_color() === 0xffffff); 38 | } 39 | 40 | main(); 41 | -------------------------------------------------------------------------------- /include/quickjs/libregexp-opcode.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Regular Expression Engine 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 | 25 | #ifdef DEF 26 | 27 | DEF(invalid, 1) /* never used */ 28 | DEF(char, 3) 29 | DEF(char32, 5) 30 | DEF(dot, 1) 31 | DEF(any, 1) /* same as dot but match any character including line terminator */ 32 | DEF(line_start, 1) 33 | DEF(line_end, 1) 34 | DEF(goto, 5) 35 | DEF(split_goto_first, 5) 36 | DEF(split_next_first, 5) 37 | DEF(match, 1) 38 | DEF(save_start, 2) /* save start position */ 39 | DEF(save_end, 2) /* save end position, must come after saved_start */ 40 | DEF(save_reset, 3) /* reset save positions */ 41 | DEF(loop, 5) /* decrement the top the stack and goto if != 0 */ 42 | DEF(push_i32, 5) /* push integer on the stack */ 43 | DEF(drop, 1) 44 | DEF(word_boundary, 1) 45 | DEF(not_word_boundary, 1) 46 | DEF(back_reference, 2) 47 | DEF(backward_back_reference, 2) /* must come after back_reference */ 48 | DEF(range, 3) /* variable length */ 49 | DEF(range32, 3) /* variable length */ 50 | DEF(lookahead, 5) 51 | DEF(negative_lookahead, 5) 52 | DEF(push_char_pos, 1) /* push the character position on the stack */ 53 | DEF(bne_char_pos, 5) /* pop one stack element and jump if equal to the character 54 | position */ 55 | DEF(prev, 1) /* go to the previous char */ 56 | DEF(simple_greedy_quant, 17) 57 | 58 | #endif /* DEF */ 59 | -------------------------------------------------------------------------------- /include/quickjs/libregexp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Regular Expression Engine 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 LIBREGEXP_H 25 | #define LIBREGEXP_H 26 | 27 | #include 28 | 29 | #include "libunicode.h" 30 | 31 | #define LRE_BOOL int /* for documentation purposes */ 32 | 33 | #define LRE_FLAG_GLOBAL (1 << 0) 34 | #define LRE_FLAG_IGNORECASE (1 << 1) 35 | #define LRE_FLAG_MULTILINE (1 << 2) 36 | #define LRE_FLAG_DOTALL (1 << 3) 37 | #define LRE_FLAG_UTF16 (1 << 4) 38 | #define LRE_FLAG_STICKY (1 << 5) 39 | 40 | #define LRE_FLAG_NAMED_GROUPS (1 << 7) /* named groups are present in the regexp */ 41 | 42 | uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size, 43 | const char *buf, size_t buf_len, int re_flags, 44 | void *opaque); 45 | int lre_get_capture_count(const uint8_t *bc_buf); 46 | int lre_get_flags(const uint8_t *bc_buf); 47 | const char *lre_get_groupnames(const uint8_t *bc_buf); 48 | int lre_exec(uint8_t **capture, 49 | const uint8_t *bc_buf, const uint8_t *cbuf, int cindex, int clen, 50 | int cbuf_type, void *opaque); 51 | 52 | int lre_parse_escape(const uint8_t **pp, int allow_utf16); 53 | LRE_BOOL lre_is_space(int c); 54 | 55 | /* must be provided by the user */ 56 | LRE_BOOL lre_check_stack_overflow(void *opaque, size_t alloca_size); 57 | void *lre_realloc(void *opaque, void *ptr, size_t size); 58 | 59 | /* JS identifier test */ 60 | extern uint32_t const lre_id_start_table_ascii[4]; 61 | extern uint32_t const lre_id_continue_table_ascii[4]; 62 | 63 | static inline int lre_js_is_ident_first(int c) 64 | { 65 | if ((uint32_t)c < 128) { 66 | return (lre_id_start_table_ascii[c >> 5] >> (c & 31)) & 1; 67 | } else { 68 | #ifdef CONFIG_ALL_UNICODE 69 | return lre_is_id_start(c); 70 | #else 71 | return !lre_is_space(c); 72 | #endif 73 | } 74 | } 75 | 76 | static inline int lre_js_is_ident_next(int c) 77 | { 78 | if ((uint32_t)c < 128) { 79 | return (lre_id_continue_table_ascii[c >> 5] >> (c & 31)) & 1; 80 | } else { 81 | /* ZWNJ and ZWJ are accepted in identifiers */ 82 | #ifdef CONFIG_ALL_UNICODE 83 | return lre_is_id_continue(c) || c == 0x200C || c == 0x200D; 84 | #else 85 | return !lre_is_space(c) || c == 0x200C || c == 0x200D; 86 | #endif 87 | } 88 | } 89 | 90 | #undef LRE_BOOL 91 | 92 | #endif /* LIBREGEXP_H */ 93 | -------------------------------------------------------------------------------- /include/quickjs/libunicode.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Unicode utilities 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 LIBUNICODE_H 25 | #define LIBUNICODE_H 26 | 27 | #include 28 | 29 | #define LRE_BOOL int /* for documentation purposes */ 30 | 31 | /* define it to include all the unicode tables (40KB larger) */ 32 | #define CONFIG_ALL_UNICODE 33 | 34 | #define LRE_CC_RES_LEN_MAX 3 35 | 36 | typedef enum { 37 | UNICODE_NFC, 38 | UNICODE_NFD, 39 | UNICODE_NFKC, 40 | UNICODE_NFKD, 41 | } UnicodeNormalizationEnum; 42 | 43 | int lre_case_conv(uint32_t *res, uint32_t c, int conv_type); 44 | LRE_BOOL lre_is_cased(uint32_t c); 45 | LRE_BOOL lre_is_case_ignorable(uint32_t c); 46 | 47 | /* char ranges */ 48 | 49 | typedef struct { 50 | int len; /* in points, always even */ 51 | int size; 52 | uint32_t *points; /* points sorted by increasing value */ 53 | void *mem_opaque; 54 | void *(*realloc_func)(void *opaque, void *ptr, size_t size); 55 | } CharRange; 56 | 57 | typedef enum { 58 | CR_OP_UNION, 59 | CR_OP_INTER, 60 | CR_OP_XOR, 61 | } CharRangeOpEnum; 62 | 63 | void cr_init(CharRange *cr, void *mem_opaque, void *(*realloc_func)(void *opaque, void *ptr, size_t size)); 64 | void cr_free(CharRange *cr); 65 | int cr_realloc(CharRange *cr, int size); 66 | int cr_copy(CharRange *cr, const CharRange *cr1); 67 | 68 | static inline int cr_add_point(CharRange *cr, uint32_t v) 69 | { 70 | if (cr->len >= cr->size) { 71 | if (cr_realloc(cr, cr->len + 1)) 72 | return -1; 73 | } 74 | cr->points[cr->len++] = v; 75 | return 0; 76 | } 77 | 78 | static inline int cr_add_interval(CharRange *cr, uint32_t c1, uint32_t c2) 79 | { 80 | if ((cr->len + 2) > cr->size) { 81 | if (cr_realloc(cr, cr->len + 2)) 82 | return -1; 83 | } 84 | cr->points[cr->len++] = c1; 85 | cr->points[cr->len++] = c2; 86 | return 0; 87 | } 88 | 89 | int cr_union1(CharRange *cr, const uint32_t *b_pt, int b_len); 90 | 91 | static inline int cr_union_interval(CharRange *cr, uint32_t c1, uint32_t c2) 92 | { 93 | uint32_t b_pt[2]; 94 | b_pt[0] = c1; 95 | b_pt[1] = c2 + 1; 96 | return cr_union1(cr, b_pt, 2); 97 | } 98 | 99 | int cr_op(CharRange *cr, const uint32_t *a_pt, int a_len, 100 | const uint32_t *b_pt, int b_len, int op); 101 | 102 | int cr_invert(CharRange *cr); 103 | 104 | #ifdef CONFIG_ALL_UNICODE 105 | 106 | LRE_BOOL lre_is_id_start(uint32_t c); 107 | LRE_BOOL lre_is_id_continue(uint32_t c); 108 | 109 | int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len, 110 | UnicodeNormalizationEnum n_type, 111 | void *opaque, void *(*realloc_func)(void *opaque, void *ptr, size_t size)); 112 | 113 | /* Unicode character range functions */ 114 | 115 | int unicode_script(CharRange *cr, 116 | const char *script_name, LRE_BOOL is_ext); 117 | int unicode_general_category(CharRange *cr, const char *gc_name); 118 | int unicode_prop(CharRange *cr, const char *prop_name); 119 | 120 | #endif /* CONFIG_ALL_UNICODE */ 121 | 122 | #undef LRE_BOOL 123 | 124 | #endif /* LIBUNICODE_H */ 125 | -------------------------------------------------------------------------------- /include/quickjs/list.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Linux klist like system 3 | * 4 | * Copyright (c) 2016-2017 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 LIST_H 25 | #define LIST_H 26 | 27 | #ifndef NULL 28 | #include 29 | #endif 30 | 31 | #include 32 | 33 | 34 | /* 35 | * Doubly Linked List 36 | * 37 | * This file offers a C implementation of a doubly linked list. 38 | * 39 | * Initialization: 40 | * - `LIST_HEAD_INIT(el)`: Static list head initialization. 41 | * - `init_list_head(struct list_head *head)`: Dynamic list head initialization. 42 | * 43 | * Query: 44 | * - `list_entry(el, type, member)`: Retrieves the structure containing the list head. 45 | * - `list_empty(struct list_head *el)`: Checks if a list is empty. 46 | * - `list_for_each(el, head)`: Standard list iteration. 47 | * - `list_for_each_safe(el, el1, head)`: List iteration that is safe against removal of the current entry. 48 | * - `list_for_each_prev(el, head)`: Reverse list iteration. 49 | * - `list_for_each_prev_safe(el, el1, head)`: Reverse list iteration that is safe against removal of the current entry. 50 | * 51 | * Insertion: 52 | * - `__list_add(struct list_head *el, struct list_head *prev, struct list_head *next)`: Internal function to add an 53 | * entry between two known consecutive entries. 54 | * - `list_add(struct list_head *el, struct list_head *head)`: Adds an entry after the specified head, useful for stack 55 | * implementation. 56 | * - `list_add_tail(struct list_head *el, struct list_head *head)`: Adds an entry before the specified head, useful for 57 | * queue implementation. 58 | * 59 | * Deletion: 60 | * - `list_del(struct list_head *el)`: Removes an entry from the list and reinitializes it. 61 | */ 62 | struct list_head { 63 | struct list_head *prev; 64 | struct list_head *next; 65 | }; 66 | 67 | #define LIST_HEAD_INIT(el) { &(el), &(el) } 68 | 69 | /* return the pointer of type 'type *' containing 'el' as field 'member' */ 70 | #define list_entry(el, type, member) \ 71 | ((type *)((uint8_t *)(el) - offsetof(type, member))) 72 | 73 | static inline void init_list_head(struct list_head *head) 74 | { 75 | head->prev = head; 76 | head->next = head; 77 | } 78 | 79 | /* insert 'el' between 'prev' and 'next' */ 80 | static inline void __list_add(struct list_head *el, 81 | struct list_head *prev, struct list_head *next) 82 | { 83 | prev->next = el; 84 | el->prev = prev; 85 | el->next = next; 86 | next->prev = el; 87 | } 88 | 89 | /* add 'el' at the head of the list 'head' (= after element head) */ 90 | static inline void list_add(struct list_head *el, struct list_head *head) 91 | { 92 | __list_add(el, head, head->next); 93 | } 94 | 95 | /* add 'el' at the end of the list 'head' (= before element head) */ 96 | static inline void list_add_tail(struct list_head *el, struct list_head *head) 97 | { 98 | __list_add(el, head->prev, head); 99 | } 100 | 101 | static inline void list_del(struct list_head *el) 102 | { 103 | struct list_head *prev, *next; 104 | prev = el->prev; 105 | next = el->next; 106 | prev->next = next; 107 | next->prev = prev; 108 | el->prev = NULL; /* fail safe */ 109 | el->next = NULL; /* fail safe */ 110 | } 111 | 112 | static inline int list_empty(struct list_head *el) 113 | { 114 | return el->next == el; 115 | } 116 | 117 | #define list_for_each(el, head) \ 118 | for(el = (head)->next; el != (head); el = el->next) 119 | 120 | #define list_for_each_safe(el, el1, head) \ 121 | for(el = (head)->next, el1 = el->next; el != (head); \ 122 | el = el1, el1 = el->next) 123 | 124 | #define list_for_each_prev(el, head) \ 125 | for(el = (head)->prev; el != (head); el = el->prev) 126 | 127 | #define list_for_each_prev_safe(el, el1, head) \ 128 | for(el = (head)->prev, el1 = el->prev; el != (head); \ 129 | el = el1, el1 = el->prev) 130 | 131 | #endif /* LIST_H */ 132 | -------------------------------------------------------------------------------- /scripts/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -x 4 | 5 | rm -rf build bin lib 6 | mkdir build 7 | cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -B build -S . 8 | cmake --build ./build --target qjs run-test262 -j 8 -------------------------------------------------------------------------------- /scripts/ci.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -x 4 | 5 | bash scripts/build.sh 6 | bash scripts/test.sh -------------------------------------------------------------------------------- /scripts/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -x 4 | 5 | if [ ! -d test262 ]; then 6 | git clone https://github.com/tc39/test262.git test262 7 | fi 8 | 9 | cd test262 10 | # git checkout ac1c3546c393d89b37483c3a32eddfe7dd1903a7 11 | # patch -p1 < ../tests/test262.patch 12 | cd .. 13 | touch test262_errors.txt 14 | ./bin/run-test262 -m -c tests/test262.conf -a -------------------------------------------------------------------------------- /scripts/unicode_download.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | url="ftp://ftp.unicode.org/Public/14.0.0/ucd" 5 | emoji_url="${url}/emoji/emoji-data.txt" 6 | 7 | files="CaseFolding.txt DerivedNormalizationProps.txt PropList.txt \ 8 | SpecialCasing.txt CompositionExclusions.txt ScriptExtensions.txt \ 9 | UnicodeData.txt DerivedCoreProperties.txt NormalizationTest.txt Scripts.txt \ 10 | PropertyValueAliases.txt" 11 | 12 | mkdir -p unicode 13 | 14 | for f in $files; do 15 | g="${url}/${f}" 16 | wget $g -O unicode/$f 17 | done 18 | 19 | wget $emoji_url -O unicode/emoji-data.txt 20 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(FetchContent) 2 | 3 | FetchContent_Declare( 4 | Corrosion 5 | GIT_REPOSITORY https://github.com/corrosion-rs/corrosion.git 6 | GIT_TAG v0.4.1 7 | ) 8 | FetchContent_MakeAvailable(Corrosion) 9 | 10 | # config build target: "Debug" or "Release" 11 | if (CMAKE_BUILD_TYPE STREQUAL "Debug") 12 | set(COMPILE_FLAGS ${COMPILE_FLAGS} -g) 13 | elseif(CMAKE_BUILD_TYPE STREQUAL "Release") 14 | set(COMPILE_FLAGS ${COMPILE_FLAGS} -O3) 15 | endif() 16 | 17 | add_library(quickjs 18 | libbf.c 19 | cutils.c 20 | libregexp.c 21 | libunicode.c 22 | core/string.c 23 | core/function.c 24 | core/memory.c 25 | core/bytecode.c 26 | core/object.c 27 | core/exception.c 28 | core/gc.c 29 | core/malloc.c 30 | core/shape.c 31 | core/parser.c 32 | core/conversion.c 33 | core/runtime.c 34 | core/module.c 35 | core/ic.c 36 | core/builtins/js-array.c 37 | core/builtins/js-async-function.c 38 | core/builtins/js-async-generator.c 39 | core/builtins/js-atomics.c 40 | core/builtins/js-big-num.c 41 | core/builtins/js-boolean.c 42 | core/builtins/js-date.c 43 | core/builtins/js-function.c 44 | core/builtins/js-generator.c 45 | core/builtins/js-json.c 46 | core/builtins/js-map.c 47 | core/builtins/js-math.c 48 | core/builtins/js-number.c 49 | core/builtins/js-object.c 50 | core/builtins/js-closures.c 51 | core/builtins/js-operator.c 52 | core/builtins/js-promise.c 53 | core/builtins/js-proxy.c 54 | core/builtins/js-reflect.c 55 | core/builtins/js-regexp.c 56 | core/builtins/js-string.c 57 | core/builtins/js-symbol.c 58 | core/builtins/js-typed-array.c 59 | ) 60 | 61 | # create a custom target for including headers 62 | add_custom_target(include_rust_c_bindings 63 | COMMAND echo "include headers: ${PROJECT_SOURCE_DIR}/src/crates/target/include" 64 | COMMAND include_directories(${PROJECT_SOURCE_DIR}/src/crates/target/include) 65 | ) 66 | 67 | # build rust libraries 68 | corrosion_import_crate(MANIFEST_PATH ${CMAKE_SOURCE_DIR}/src/crates/Cargo.toml) 69 | target_link_libraries(quickjs quickjs_rs) 70 | 71 | set(QUICKJS_VERSION STRING "0.1.0") 72 | 73 | add_compile_options(${COMPILE_FLAGS}) 74 | 75 | target_compile_options(quickjs PUBLIC 76 | -D_GNU_SOURCE 77 | -DCONFIG_BIGNUM 78 | -DCONFIG_VERSION=${\"QUICKJS_VERSION\"} 79 | # -DDUMP_LEAKS # dump memory leaks 80 | ) -------------------------------------------------------------------------------- /src/cli/qbc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "quickjs/quickjs.h" 5 | 6 | char *change_extension(const char *path, const char *new_ext) { 7 | char *dot = strrchr(path, '.'); 8 | if (dot == NULL) { 9 | dot = path + strlen(path); // append at the end if there's no extension 10 | } 11 | size_t new_path_len = dot - path + strlen(new_ext) + 1; // +1 for null terminator 12 | char *new_path = malloc(new_path_len); 13 | strncpy(new_path, path, dot - path); 14 | strcpy(new_path + (dot - path), new_ext); 15 | return new_path; 16 | } 17 | 18 | int main(int argc, char *argv[]) { 19 | if (argc < 2 || argc > 3) { 20 | printf("Usage: %s []\n", argv[0]); 21 | return 1; 22 | } 23 | 24 | const char *source_path = argv[1]; 25 | char *output_path; 26 | if (argc == 3) { 27 | output_path = argv[2]; 28 | } else { 29 | output_path = change_extension(source_path, ".qbc"); 30 | } 31 | 32 | FILE *source_file = fopen(source_path, "r"); 33 | if (source_file == NULL) { 34 | printf("Cannot open source file: %s\n", source_path); 35 | return 1; 36 | } 37 | 38 | // get file length 39 | fseek(source_file, 0, SEEK_END); 40 | long length = ftell(source_file); 41 | fseek(source_file, 0, SEEK_SET); 42 | 43 | // read source code into buffer 44 | char *source = malloc(length); 45 | if (source) { 46 | fread(source, 1, length, source_file); 47 | } 48 | fclose(source_file); 49 | 50 | JSRuntime *rt; 51 | JSContext *ctx; 52 | 53 | rt = JS_NewRuntime(); 54 | ctx = JS_NewContext(rt); 55 | 56 | // compile source code to bytecode 57 | JSValue bytecode = JS_Eval(ctx, source, length, source_path, JS_EVAL_FLAG_COMPILE_ONLY); 58 | 59 | free(source); 60 | 61 | if (JS_IsException(bytecode)) { 62 | printf("Compilation failed.\n"); 63 | JS_FreeValue(ctx, bytecode); 64 | JS_FreeContext(ctx); 65 | JS_FreeRuntime(rt); 66 | return 1; 67 | } 68 | 69 | // write bytecode to buffer 70 | size_t bytecode_length; 71 | uint8_t *buffer = JS_WriteObject(ctx, &bytecode_length, bytecode, JS_WRITE_OBJ_BYTECODE); 72 | 73 | JS_FreeValue(ctx, bytecode); 74 | 75 | // write buffer to binary file 76 | FILE *output_file = fopen(output_path, "wb"); 77 | if (output_file == NULL) { 78 | printf("Cannot open output file: %s\n", output_path); 79 | JS_FreeContext(ctx); 80 | JS_FreeRuntime(rt); 81 | return 1; 82 | } 83 | 84 | fwrite(buffer, 1, bytecode_length, output_file); 85 | fclose(output_file); 86 | 87 | js_free(ctx, buffer); 88 | JS_FreeContext(ctx); 89 | JS_FreeRuntime(rt); 90 | 91 | printf("Bytecode has been written to: %s\n", output_path); 92 | 93 | if (argc == 2) { 94 | free(output_path); 95 | } 96 | return 0; 97 | } 98 | -------------------------------------------------------------------------------- /src/cli/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/quickjs.h" 31 | 32 | #ifdef __cplusplus 33 | extern "C" { 34 | #endif 35 | 36 | JSModuleDef *js_init_module_std(JSContext *ctx, const char *module_name); 37 | JSModuleDef *js_init_module_os(JSContext *ctx, const char *module_name); 38 | void js_std_add_helpers(JSContext *ctx, int argc, char **argv); 39 | void js_std_loop(JSContext *ctx); 40 | void js_std_init_handlers(JSRuntime *rt); 41 | void js_std_free_handlers(JSRuntime *rt); 42 | void js_std_dump_error(JSContext *ctx); 43 | uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len, const char *filename); 44 | int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val, 45 | JS_BOOL use_realpath, JS_BOOL is_main); 46 | JSModuleDef *js_module_loader(JSContext *ctx, 47 | const char *module_name, void *opaque); 48 | void js_std_eval_binary(JSContext *ctx, const uint8_t *buf, size_t buf_len, 49 | int flags); 50 | void js_std_promise_rejection_tracker(JSContext *ctx, JSValueConst promise, 51 | JSValueConst reason, 52 | JS_BOOL is_handled, void *opaque); 53 | void js_std_set_worker_new_context_func(JSContext *(*func)(JSRuntime *rt)); 54 | 55 | #ifdef __cplusplus 56 | } /* extern "C" { */ 57 | #endif 58 | 59 | #endif /* QUICKJS_LIBC_H */ 60 | -------------------------------------------------------------------------------- /src/core/base.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 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 | 26 | #ifndef QUICKJS_BASE_H 27 | #define QUICKJS_BASE_H 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #include "mimalloc.h" 41 | #ifdef CONFIG_BIGNUM 42 | #include "quickjs/libbf.h" 43 | #endif 44 | 45 | #define OPTIMIZE 1 46 | #define SHORT_OPCODES 1 47 | #if defined(EMSCRIPTEN) 48 | #define DIRECT_DISPATCH 0 49 | #else 50 | #define DIRECT_DISPATCH 1 51 | #endif 52 | 53 | #if defined(__APPLE__) 54 | #define MALLOC_OVERHEAD 0 55 | #else 56 | #define MALLOC_OVERHEAD 8 57 | #endif 58 | 59 | #if !defined(_WIN32) 60 | /* define it if printf uses the RNDN rounding mode instead of RNDNA */ 61 | #define CONFIG_PRINTF_RNDN 62 | #endif 63 | 64 | /* define to include Atomics.* operations which depend on the OS 65 | threads */ 66 | #if !defined(EMSCRIPTEN) 67 | #define CONFIG_ATOMICS 68 | #endif 69 | 70 | #if !defined(EMSCRIPTEN) 71 | /* enable stack limitation */ 72 | #define CONFIG_STACK_CHECK 73 | #endif 74 | 75 | 76 | /* dump object free */ 77 | //#define DUMP_FREE 78 | //#define DUMP_CLOSURE 79 | /* dump the bytecode of the compiled functions: combination of bits 80 | 1: dump pass 3 final byte code 81 | 2: dump pass 2 code 82 | 4: dump pass 1 code 83 | 8: dump stdlib functions 84 | 16: dump bytecode in hex 85 | 32: dump line number table 86 | */ 87 | //#define DUMP_BYTECODE (1) 88 | /* dump the occurence of the automatic GC */ 89 | //#define DUMP_GC 90 | /* dump objects freed by the garbage collector */ 91 | //#define DUMP_GC_FREE 92 | /* dump objects leaking when freeing the runtime */ 93 | //#define DUMP_LEAKS 1 94 | /* dump memory usage before running the garbage collector */ 95 | //#define DUMP_MEM 96 | //#define DUMP_OBJECTS /* dump objects in JS_FreeContext */ 97 | //#define DUMP_ATOMS /* dump atoms in JS_FreeContext */ 98 | //#define DUMP_SHAPES /* dump shapes in JS_FreeContext */ 99 | //#define DUMP_MODULE_RESOLVE 100 | //#define DUMP_PROMISE 101 | //#define DUMP_READ_OBJECT 102 | 103 | /* test the GC by forcing it before each object allocation */ 104 | //#define FORCE_GC_AT_MALLOC 105 | 106 | #ifdef CONFIG_ATOMICS 107 | #include 108 | #include 109 | #include 110 | #endif 111 | 112 | 113 | #endif -------------------------------------------------------------------------------- /src/core/builtins/js-array.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 Charlie Gordon 6 | * Copyright (c) 2023 The OpenQuickJS Team 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #ifndef QUICKJS_JS_ARRAY_H 28 | #define QUICKJS_JS_ARRAY_H 29 | 30 | #include "../types.h" 31 | #include "quickjs/cutils.h" 32 | #include "quickjs/quickjs.h" 33 | 34 | #define special_every 0 35 | #define special_some 1 36 | #define special_forEach 2 37 | #define special_map 3 38 | #define special_filter 4 39 | #define special_TA 8 40 | 41 | #define special_reduce 0 42 | #define special_reduceRight 1 43 | 44 | typedef struct JSArrayIteratorData { 45 | JSValue obj; 46 | JSIteratorKindEnum kind; 47 | uint32_t idx; 48 | } JSArrayIteratorData; 49 | 50 | JSValue js_create_iterator_result(JSContext* ctx, JSValue val, BOOL done); 51 | JSValue js_array_iterator_next(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, BOOL* pdone, int magic); 52 | 53 | JSValue js_create_array_iterator(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, int magic); 54 | BOOL js_is_fast_array(JSContext* ctx, JSValueConst obj); 55 | /* Access an Array's internal JSValue array if available */ 56 | BOOL js_get_fast_array(JSContext* ctx, JSValueConst obj, JSValue** arrpp, uint32_t* countp); 57 | 58 | int expand_fast_array(JSContext* ctx, JSObject* p, uint32_t new_len); 59 | 60 | int JS_CopySubArray(JSContext* ctx, JSValueConst obj, int64_t to_pos, int64_t from_pos, int64_t count, int dir); 61 | JSValue js_array_constructor(JSContext* ctx, JSValueConst new_target, int argc, JSValueConst* argv); 62 | JSValue js_array_from(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 63 | JSValue js_array_of(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 64 | JSValue js_array_isArray(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 65 | JSValue js_get_this(JSContext* ctx, JSValueConst this_val); 66 | JSValue JS_ArraySpeciesCreate(JSContext* ctx, JSValueConst obj, JSValueConst len_val); 67 | int JS_isConcatSpreadable(JSContext* ctx, JSValueConst obj); 68 | JSValue js_array_concat(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 69 | int js_typed_array_get_length_internal(JSContext* ctx, JSValueConst obj); 70 | JSValue js_typed_array___speciesCreate(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 71 | JSValue js_array_every(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, int special); 72 | JSValue js_array_reduce(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, int special); 73 | JSValue js_array_fill(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 74 | JSValue js_array_includes(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 75 | JSValue js_array_indexOf(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 76 | JSValue js_array_lastIndexOf(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 77 | JSValue js_array_find(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, int findIndex); 78 | JSValue js_array_toString(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 79 | JSValue js_array_join(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, int toLocaleString); 80 | JSValue js_array_pop(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, int shift); 81 | JSValue js_array_push(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, int unshift); 82 | JSValue js_array_reverse(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 83 | JSValue js_array_slice(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, int splice); 84 | JSValue js_array_copyWithin(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 85 | int64_t JS_FlattenIntoArray(JSContext* ctx, JSValueConst target, JSValueConst source, int64_t sourceLen, int64_t targetIndex, int depth, JSValueConst mapperFunction, JSValueConst thisArg); 86 | JSValue js_array_flatten(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, int map); 87 | int js_array_cmp_generic(const void* a, const void* b, void* opaque); 88 | JSValue js_array_sort(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 89 | 90 | void js_array_iterator_finalizer(JSRuntime* rt, JSValue val); 91 | void js_array_iterator_mark(JSRuntime* rt, JSValueConst val, JS_MarkFunc* mark_func); 92 | JSValue js_create_array(JSContext* ctx, int len, JSValueConst* tab); 93 | 94 | __exception int js_append_enumerate(JSContext* ctx, JSValue* sp); 95 | 96 | void js_array_finalizer(JSRuntime* rt, JSValue val); 97 | void js_array_mark(JSRuntime* rt, JSValueConst val, JS_MarkFunc* mark_func); 98 | 99 | JSValue js_iterator_proto_iterator(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 100 | 101 | #endif -------------------------------------------------------------------------------- /src/core/builtins/js-async-function.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 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 | 26 | #ifndef QUICKJS_JS_ASYNC_FUNCTION_H 27 | #define QUICKJS_JS_ASYNC_FUNCTION_H 28 | 29 | #include "quickjs/quickjs.h" 30 | #include "../types.h" 31 | 32 | JSValue async_func_resume(JSContext *ctx, JSAsyncFunctionState *s); 33 | __exception int async_func_init(JSContext *ctx, JSAsyncFunctionState *s, 34 | JSValueConst func_obj, JSValueConst this_obj, 35 | int argc, JSValueConst *argv); 36 | void async_func_free(JSRuntime *rt, JSAsyncFunctionState *s); 37 | void async_func_mark(JSRuntime *rt, JSAsyncFunctionState *s, 38 | JS_MarkFunc *mark_func); 39 | 40 | void js_async_function_terminate(JSRuntime *rt, JSAsyncFunctionData *s); 41 | void js_async_function_free0(JSRuntime *rt, JSAsyncFunctionData *s); 42 | void js_async_function_free(JSRuntime *rt, JSAsyncFunctionData *s); 43 | void js_async_function_resolve_finalizer(JSRuntime *rt, JSValue val); 44 | void js_async_function_resolve_mark(JSRuntime *rt, JSValueConst val, 45 | JS_MarkFunc *mark_func); 46 | int js_async_function_resolve_create(JSContext *ctx, 47 | JSAsyncFunctionData *s, 48 | JSValue *resolving_funcs); 49 | void js_async_function_resume(JSContext *ctx, JSAsyncFunctionData *s); 50 | JSValue js_async_function_resolve_call(JSContext *ctx, 51 | JSValueConst func_obj, 52 | JSValueConst this_obj, 53 | int argc, JSValueConst *argv, 54 | int flags); 55 | JSValue js_async_function_call(JSContext *ctx, JSValueConst func_obj, 56 | JSValueConst this_obj, 57 | int argc, JSValueConst *argv, int flags); 58 | 59 | #endif -------------------------------------------------------------------------------- /src/core/builtins/js-async-generator.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 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 | 26 | #ifndef QUICKJS_JS_ASYNC_GENERATOR_H 27 | #define QUICKJS_JS_ASYNC_GENERATOR_H 28 | 29 | #include "quickjs/quickjs.h" 30 | #include "quickjs/cutils.h" 31 | #include "../types.h" 32 | 33 | 34 | typedef enum JSAsyncGeneratorStateEnum { 35 | JS_ASYNC_GENERATOR_STATE_SUSPENDED_START, 36 | JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD, 37 | JS_ASYNC_GENERATOR_STATE_SUSPENDED_YIELD_STAR, 38 | JS_ASYNC_GENERATOR_STATE_EXECUTING, 39 | JS_ASYNC_GENERATOR_STATE_AWAITING_RETURN, 40 | JS_ASYNC_GENERATOR_STATE_COMPLETED, 41 | } JSAsyncGeneratorStateEnum; 42 | 43 | typedef struct JSAsyncGeneratorRequest { 44 | struct list_head link; 45 | /* completion */ 46 | int completion_type; /* GEN_MAGIC_x */ 47 | JSValue result; 48 | /* promise capability */ 49 | JSValue promise; 50 | JSValue resolving_funcs[2]; 51 | } JSAsyncGeneratorRequest; 52 | 53 | typedef struct JSAsyncGeneratorData { 54 | JSObject *generator; /* back pointer to the object (const) */ 55 | JSAsyncGeneratorStateEnum state; 56 | JSAsyncFunctionState func_state; 57 | struct list_head queue; /* list of JSAsyncGeneratorRequest.link */ 58 | } JSAsyncGeneratorData; 59 | 60 | void js_async_generator_free(JSRuntime *rt, 61 | JSAsyncGeneratorData *s); 62 | void js_async_generator_finalizer(JSRuntime *rt, JSValue obj); 63 | void js_async_generator_mark(JSRuntime *rt, JSValueConst val, 64 | JS_MarkFunc *mark_func); 65 | 66 | int js_async_generator_resolve_function_create(JSContext *ctx, 67 | JSValueConst generator, 68 | JSValue *resolving_funcs, 69 | BOOL is_resume_next); 70 | int js_async_generator_await(JSContext *ctx, 71 | JSAsyncGeneratorData *s, 72 | JSValueConst value); 73 | void js_async_generator_resolve_or_reject(JSContext *ctx, 74 | JSAsyncGeneratorData *s, 75 | JSValueConst result, 76 | int is_reject); 77 | 78 | void js_async_generator_resolve(JSContext *ctx, 79 | JSAsyncGeneratorData *s, 80 | JSValueConst value, 81 | BOOL done); 82 | 83 | void js_async_generator_reject(JSContext *ctx, 84 | JSAsyncGeneratorData *s, 85 | JSValueConst exception); 86 | 87 | void js_async_generator_complete(JSContext *ctx, 88 | JSAsyncGeneratorData *s); 89 | 90 | int js_async_generator_completed_return(JSContext *ctx, 91 | JSAsyncGeneratorData *s, 92 | JSValueConst value); 93 | 94 | void js_async_generator_resume_next(JSContext *ctx, 95 | JSAsyncGeneratorData *s); 96 | /* magic = GEN_MAGIC_x */ 97 | JSValue js_async_generator_next(JSContext *ctx, JSValueConst this_val, 98 | int argc, JSValueConst *argv, 99 | int magic); 100 | 101 | JSValue js_async_generator_function_call(JSContext *ctx, JSValueConst func_obj, 102 | JSValueConst this_obj, 103 | int argc, JSValueConst *argv, 104 | int flags); 105 | 106 | 107 | #endif 108 | -------------------------------------------------------------------------------- /src/core/builtins/js-atomics.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 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 | 26 | #ifndef QUICKJS_JS_ATOMICS_H 27 | #define QUICKJS_JS_ATOMICS_H 28 | 29 | #include "quickjs/quickjs.h" 30 | 31 | #ifdef CONFIG_ATOMICS 32 | void JS_AddIntrinsicAtomics(JSContext *ctx); 33 | #endif 34 | 35 | 36 | #endif -------------------------------------------------------------------------------- /src/core/builtins/js-big-num.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 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 | 26 | #ifndef QUICKJS_JS_BIG_NUM_H 27 | #define QUICKJS_JS_BIG_NUM_H 28 | 29 | #include "quickjs/quickjs.h" 30 | #include "quickjs/cutils.h" 31 | #include "../types.h" 32 | 33 | #if CONFIG_BIGNUM 34 | #include "quickjs/libbf.h" 35 | 36 | JSValue JS_NewBigInt(JSContext *ctx); 37 | JSValue JS_NewBigInt64_1(JSContext *ctx, int64_t v); 38 | 39 | no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *sp, 40 | OPCodeEnum op); 41 | no_inline __exception int js_unary_arith_slow(JSContext *ctx, 42 | JSValue *sp, 43 | OPCodeEnum op); 44 | __exception int js_post_inc_slow(JSContext *ctx, 45 | JSValue *sp, OPCodeEnum op); 46 | no_inline int js_not_slow(JSContext *ctx, JSValue *sp); 47 | int js_binary_arith_bigfloat(JSContext *ctx, OPCodeEnum op, 48 | JSValue *pres, JSValue op1, JSValue op2); 49 | int js_binary_arith_bigint(JSContext *ctx, OPCodeEnum op, 50 | JSValue *pres, JSValue op1, JSValue op2); 51 | int js_bfdec_pow(bfdec_t *r, const bfdec_t *a, const bfdec_t *b); 52 | int js_binary_arith_bigdecimal(JSContext *ctx, OPCodeEnum op, 53 | JSValue *pres, JSValue op1, JSValue op2); 54 | no_inline __exception int js_binary_logic_slow(JSContext *ctx, 55 | JSValue *sp, 56 | OPCodeEnum op); 57 | /* Note: also used for bigint */ 58 | int js_compare_bigfloat(JSContext *ctx, OPCodeEnum op, 59 | JSValue op1, JSValue op2); 60 | int js_compare_bigdecimal(JSContext *ctx, OPCodeEnum op, 61 | JSValue op1, JSValue op2); 62 | no_inline int js_relational_slow(JSContext *ctx, JSValue *sp, 63 | OPCodeEnum op); 64 | no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp, 65 | BOOL is_neq); 66 | no_inline int js_shr_slow(JSContext *ctx, JSValue *sp); 67 | JSValue js_mul_pow10_to_float64(JSContext *ctx, const bf_t *a, 68 | int64_t exponent); 69 | no_inline int js_mul_pow10(JSContext *ctx, JSValue *sp); 70 | JSBigFloat *js_new_bf(JSContext *ctx); 71 | void js_float_env_finalizer(JSRuntime *rt, JSValue val); 72 | JSValue JS_NewBigFloat(JSContext *ctx); 73 | static inline bf_t *JS_GetBigFloat(JSValueConst val) 74 | { 75 | JSBigFloat *p = JS_VALUE_GET_PTR(val); 76 | return &p->num; 77 | } 78 | JSValue JS_NewBigDecimal(JSContext *ctx); 79 | static inline bfdec_t *JS_GetBigDecimal(JSValueConst val) 80 | { 81 | JSBigDecimal *p = JS_VALUE_GET_PTR(val); 82 | return &p->num; 83 | } 84 | JSValue JS_NewBigInt(JSContext *ctx); 85 | static inline bf_t *JS_GetBigInt(JSValueConst val) { 86 | JSBigFloat *p = JS_VALUE_GET_PTR(val); 87 | return &p->num; 88 | } 89 | JSValue JS_CompactBigInt1(JSContext *ctx, JSValue val, 90 | BOOL convert_to_safe_integer); 91 | no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp); 92 | JSValue JS_CompactBigInt(JSContext *ctx, JSValue val); 93 | int JS_ToBigInt64Free(JSContext *ctx, int64_t *pres, JSValue val); 94 | bf_t *JS_ToBigInt(JSContext *ctx, bf_t *buf, JSValueConst val); 95 | __maybe_unused JSValue JS_ToBigIntValueFree(JSContext *ctx, JSValue val); 96 | void JS_FreeBigInt(JSContext *ctx, bf_t *a, bf_t *buf); 97 | bf_t *JS_ToBigFloat(JSContext *ctx, bf_t *buf, JSValueConst val); 98 | JSValue JS_ToBigDecimalFree(JSContext *ctx, JSValue val, 99 | BOOL allow_null_or_undefined); 100 | bfdec_t *JS_ToBigDecimal(JSContext *ctx, JSValueConst val); 101 | 102 | #else 103 | 104 | no_inline __exception int js_unary_arith_slow(JSContext *ctx, 105 | JSValue *sp, 106 | OPCodeEnum op); 107 | __exception int js_post_inc_slow(JSContext *ctx, 108 | JSValue *sp, OPCodeEnum op); 109 | no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp); 110 | no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *sp, 111 | OPCodeEnum op); 112 | no_inline __exception int js_binary_logic_slow(JSContext *ctx, 113 | JSValue *sp, 114 | OPCodeEnum op); 115 | no_inline int js_not_slow(JSContext *ctx, JSValue *sp); 116 | no_inline int js_relational_slow(JSContext *ctx, JSValue *sp, 117 | OPCodeEnum op); 118 | no_inline __exception int js_eq_slow(JSContext *ctx, JSValue *sp, 119 | BOOL is_neq); 120 | no_inline int js_shr_slow(JSContext *ctx, JSValue *sp); 121 | #endif 122 | 123 | 124 | #endif -------------------------------------------------------------------------------- /src/core/builtins/js-boolean.c: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 Charlie Gordon 6 | * Copyright (c) 2023 The OpenQuickJS Team 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #include "js-boolean.h" 28 | #include "../exception.h" 29 | #include "../object.h" 30 | 31 | /* Boolean */ 32 | JSValue js_boolean_constructor(JSContext* ctx, JSValueConst new_target, int argc, JSValueConst* argv) { 33 | JSValue val, obj; 34 | val = JS_NewBool(ctx, JS_ToBool(ctx, argv[0])); 35 | if (!JS_IsUndefined(new_target)) { 36 | obj = js_create_from_ctor(ctx, new_target, JS_CLASS_BOOLEAN); 37 | if (!JS_IsException(obj)) 38 | JS_SetObjectData(ctx, obj, val); 39 | return obj; 40 | } else { 41 | return val; 42 | } 43 | } 44 | 45 | JSValue js_thisBooleanValue(JSContext* ctx, JSValueConst this_val) { 46 | if (JS_VALUE_GET_TAG(this_val) == JS_TAG_BOOL) 47 | return JS_DupValue(ctx, this_val); 48 | 49 | if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) { 50 | JSObject* p = JS_VALUE_GET_OBJ(this_val); 51 | if (p->class_id == JS_CLASS_BOOLEAN) { 52 | if (JS_VALUE_GET_TAG(p->u.object_data) == JS_TAG_BOOL) 53 | return p->u.object_data; 54 | } 55 | } 56 | return JS_ThrowTypeError(ctx, "not a boolean"); 57 | } 58 | 59 | JSValue js_boolean_toString(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv) { 60 | JSValue val = js_thisBooleanValue(ctx, this_val); 61 | if (JS_IsException(val)) 62 | return val; 63 | return JS_AtomToString(ctx, JS_VALUE_GET_BOOL(val) ? JS_ATOM_true : JS_ATOM_false); 64 | } 65 | 66 | JSValue js_boolean_valueOf(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv) { 67 | return js_thisBooleanValue(ctx, this_val); 68 | } 69 | -------------------------------------------------------------------------------- /src/core/builtins/js-boolean.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 Charlie Gordon 6 | * Copyright (c) 2023 The OpenQuickJS Team 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #ifndef QUICKJS_JS_BOOLEAN_H 28 | #define QUICKJS_JS_BOOLEAN_H 29 | 30 | #include "quickjs/quickjs.h" 31 | 32 | JSValue js_boolean_constructor(JSContext* ctx, JSValueConst new_target, int argc, JSValueConst* argv); 33 | JSValue js_thisBooleanValue(JSContext* ctx, JSValueConst this_val); 34 | JSValue js_boolean_toString(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 35 | JSValue js_boolean_valueOf(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 36 | 37 | #endif -------------------------------------------------------------------------------- /src/core/builtins/js-closures.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 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 | 26 | #ifndef QUICKJS_JS_CLOSURES_H 27 | #define QUICKJS_JS_CLOSURES_H 28 | 29 | #include "quickjs/quickjs.h" 30 | #include "quickjs/cutils.h" 31 | #include "../types.h" 32 | 33 | void close_lexical_var(JSContext *ctx, JSStackFrame *sf, int idx, int is_arg); 34 | 35 | JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf, 36 | int var_idx, BOOL is_arg); 37 | 38 | JSValue js_closure2(JSContext *ctx, JSValue func_obj, 39 | JSFunctionBytecode *b, 40 | JSVarRef **cur_var_refs, 41 | JSStackFrame *sf); 42 | 43 | JSValue js_closure(JSContext *ctx, JSValue bfunc, 44 | JSVarRef **cur_var_refs, 45 | JSStackFrame *sf); 46 | 47 | void close_var_refs(JSRuntime* rt, JSStackFrame* sf); 48 | 49 | #endif -------------------------------------------------------------------------------- /src/core/builtins/js-date.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 Charlie Gordon 6 | * Copyright (c) 2023 The OpenQuickJS Team 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #ifndef QUICKJS_JS_DATE_H 28 | #define QUICKJS_JS_DATE_H 29 | 30 | #include "quickjs/quickjs.h" 31 | #include "../types.h" 32 | 33 | JSValue js___date_clock(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 34 | __exception int JS_ThisTimeValue(JSContext* ctx, double* valp, JSValueConst this_val); 35 | JSValue JS_SetThisTimeValue(JSContext* ctx, JSValueConst this_val, double v); 36 | int64_t days_from_year(int64_t y); 37 | int64_t days_in_year(int64_t y); 38 | /* return the year, update days */ 39 | int64_t year_from_days(int64_t *days); 40 | __exception int get_date_fields(JSContext *ctx, JSValueConst obj, 41 | double fields[9], int is_local, int force); 42 | double time_clip(double t); 43 | /* The spec mandates the use of 'double' and it fixes the order 44 | of the operations */ 45 | double set_date_fields(double fields[], int is_local); 46 | JSValue get_date_field(JSContext *ctx, JSValueConst this_val, 47 | int argc, JSValueConst *argv, int magic); 48 | JSValue set_date_field(JSContext *ctx, JSValueConst this_val, 49 | int argc, JSValueConst *argv, int magic); 50 | /* fmt: 51 | 0: toUTCString: "Tue, 02 Jan 2018 23:04:46 GMT" 52 | 1: toString: "Wed Jan 03 2018 00:05:22 GMT+0100 (CET)" 53 | 2: toISOString: "2018-01-02T23:02:56.927Z" 54 | 3: toLocaleString: "1/2/2018, 11:40:40 PM" 55 | part: 1=date, 2=time 3=all 56 | XXX: should use a variant of strftime(). 57 | */ 58 | JSValue get_date_string(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, int magic); 59 | /* OS dependent: return the UTC time in ms since 1970. */ 60 | int64_t date_now(void); 61 | JSValue js_date_constructor(JSContext* ctx, JSValueConst new_target, int argc, JSValueConst* argv); 62 | JSValue js_Date_UTC(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 63 | void string_skip_spaces(JSString* sp, int* pp); 64 | void string_skip_non_spaces(JSString* sp, int* pp); 65 | /* parse a numeric field with an optional sign if accept_sign is TRUE */ 66 | int string_get_digits(JSString* sp, int* pp, int64_t* pval); 67 | int string_get_signed_digits(JSString* sp, int* pp, int64_t* pval); 68 | /* parse a fixed width numeric field */ 69 | int string_get_fixed_width_digits(JSString* sp, int* pp, int n, int64_t* pval); 70 | int string_get_milliseconds(JSString* sp, int* pp, int64_t* pval); 71 | int find_abbrev(JSString* sp, int p, const char* list, int count); 72 | int string_get_month(JSString* sp, int* pp, int64_t* pval); 73 | JSValue js_Date_parse(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 74 | JSValue js_Date_now(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 75 | JSValue js_date_Symbol_toPrimitive(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 76 | JSValue js_date_getTimezoneOffset(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 77 | JSValue js_date_getTime(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 78 | JSValue js_date_setTime(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 79 | JSValue js_date_setYear(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 80 | JSValue js_date_toJSON(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 81 | 82 | #endif -------------------------------------------------------------------------------- /src/core/builtins/js-generator.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 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 | 26 | #ifndef QUICKJS_JS_GENERATOR_H 27 | #define QUICKJS_JS_GENERATOR_H 28 | 29 | #include "quickjs/quickjs.h" 30 | #include "quickjs/cutils.h" 31 | #include "../types.h" 32 | 33 | /* XXX: use enum */ 34 | #define GEN_MAGIC_NEXT 0 35 | #define GEN_MAGIC_RETURN 1 36 | #define GEN_MAGIC_THROW 2 37 | 38 | typedef enum JSGeneratorStateEnum { 39 | JS_GENERATOR_STATE_SUSPENDED_START, 40 | JS_GENERATOR_STATE_SUSPENDED_YIELD, 41 | JS_GENERATOR_STATE_SUSPENDED_YIELD_STAR, 42 | JS_GENERATOR_STATE_EXECUTING, 43 | JS_GENERATOR_STATE_COMPLETED, 44 | } JSGeneratorStateEnum; 45 | 46 | typedef struct JSGeneratorData { 47 | JSGeneratorStateEnum state; 48 | JSAsyncFunctionState func_state; 49 | } JSGeneratorData; 50 | 51 | void free_generator_stack_rt(JSRuntime *rt, JSGeneratorData *s); 52 | void js_generator_finalizer(JSRuntime *rt, JSValue obj); 53 | void free_generator_stack(JSContext *ctx, JSGeneratorData *s); 54 | void js_generator_mark(JSRuntime *rt, JSValueConst val, 55 | JS_MarkFunc *mark_func); 56 | 57 | JSValue js_generator_next(JSContext *ctx, JSValueConst this_val, 58 | int argc, JSValueConst *argv, 59 | BOOL *pdone, int magic); 60 | JSValue js_generator_function_call(JSContext *ctx, JSValueConst func_obj, 61 | JSValueConst this_obj, 62 | int argc, JSValueConst *argv, 63 | int flags); 64 | 65 | 66 | #endif -------------------------------------------------------------------------------- /src/core/builtins/js-json.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 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 | 26 | #ifndef QUICKJS_JS_JSON_H 27 | #define QUICKJS_JS_JSON_H 28 | 29 | #include "quickjs/quickjs.h" 30 | 31 | #endif -------------------------------------------------------------------------------- /src/core/builtins/js-map.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 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 | 26 | #ifndef QUICKJS_JS_MAP_H 27 | #define QUICKJS_JS_MAP_H 28 | 29 | #include "quickjs/quickjs.h" 30 | 31 | void reset_weak_ref(JSRuntime *rt, JSObject *p); 32 | 33 | #endif -------------------------------------------------------------------------------- /src/core/builtins/js-math.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 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 | 26 | #ifndef QUICKJS_JS_MATH_H 27 | #define QUICKJS_JS_MATH_H 28 | 29 | #include "quickjs/quickjs.h" 30 | #include "quickjs/cutils.h" 31 | #include "../types.h" 32 | 33 | /* precondition: a and b are not NaN */ 34 | double js_fmin(double a, double b); 35 | /* precondition: a and b are not NaN */ 36 | double js_fmax(double a, double b); 37 | JSValue js_math_min_max(JSContext *ctx, JSValueConst this_val, 38 | int argc, JSValueConst *argv, int magic); 39 | double js_math_sign(double a); 40 | double js_math_round(double a); 41 | JSValue js_math_hypot(JSContext *ctx, JSValueConst this_val, 42 | int argc, JSValueConst *argv); 43 | double js_math_fround(double a); 44 | JSValue js_math_imul(JSContext *ctx, JSValueConst this_val, 45 | int argc, JSValueConst *argv); 46 | JSValue js_math_clz32(JSContext *ctx, JSValueConst this_val, 47 | int argc, JSValueConst *argv); 48 | /* xorshift* random number generator by Marsaglia */ 49 | uint64_t xorshift64star(uint64_t *pstate); 50 | void js_random_init(JSContext *ctx); 51 | JSValue js_math_random(JSContext *ctx, JSValueConst this_val, 52 | int argc, JSValueConst *argv); 53 | 54 | #endif -------------------------------------------------------------------------------- /src/core/builtins/js-number.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 Charlie Gordon 6 | * Copyright (c) 2023 The OpenQuickJS Team 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #ifndef QUICKJS_JS_NUMBER_H 28 | #define QUICKJS_JS_NUMBER_H 29 | 30 | #include "quickjs/quickjs.h" 31 | 32 | /* Number */ 33 | JSValue js_number_constructor(JSContext *ctx, JSValueConst new_target, 34 | int argc, JSValueConst *argv); 35 | 36 | JSValue js_number_isNaN(JSContext *ctx, JSValueConst this_val, 37 | int argc, JSValueConst *argv); 38 | 39 | JSValue js_number_isFinite(JSContext *ctx, JSValueConst this_val, 40 | int argc, JSValueConst *argv); 41 | 42 | JSValue js_number_isInteger(JSContext *ctx, JSValueConst this_val, 43 | int argc, JSValueConst *argv); 44 | 45 | JSValue js_number_isSafeInteger(JSContext *ctx, JSValueConst this_val, 46 | int argc, JSValueConst *argv); 47 | 48 | JSValue js_thisNumberValue(JSContext *ctx, JSValueConst this_val); 49 | JSValue js_number_valueOf(JSContext *ctx, JSValueConst this_val, 50 | int argc, JSValueConst *argv); 51 | int js_get_radix(JSContext *ctx, JSValueConst val); 52 | JSValue js_number_toString(JSContext *ctx, JSValueConst this_val, 53 | int argc, JSValueConst *argv, int magic); 54 | JSValue js_number_toFixed(JSContext *ctx, JSValueConst this_val, 55 | int argc, JSValueConst *argv); 56 | JSValue js_number_toExponential(JSContext *ctx, JSValueConst this_val, 57 | int argc, JSValueConst *argv); 58 | JSValue js_number_toPrecision(JSContext *ctx, JSValueConst this_val, 59 | int argc, JSValueConst *argv); 60 | 61 | JSValue js_parseInt(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 62 | JSValue js_parseFloat(JSContext *ctx, JSValueConst this_val, 63 | int argc, JSValueConst *argv); 64 | 65 | #endif -------------------------------------------------------------------------------- /src/core/builtins/js-object.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 Charlie Gordon 6 | * Copyright (c) 2023 The OpenQuickJS Team 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #ifndef QUICKJS_JS_OBJECT_H 28 | #define QUICKJS_JS_OBJECT_H 29 | 30 | #include "quickjs/quickjs.h" 31 | #include "quickjs/cutils.h" 32 | #include "quickjs/list.h" 33 | #include "../types.h" 34 | 35 | JSValue JS_ToObject(JSContext* ctx, JSValueConst val); 36 | JSValue JS_ToObjectFree(JSContext* ctx, JSValue val); 37 | int js_obj_to_desc(JSContext* ctx, JSPropertyDescriptor* d, JSValueConst desc); 38 | __exception int JS_DefinePropertyDesc(JSContext* ctx, JSValueConst obj, JSAtom prop, JSValueConst desc, int flags); 39 | __exception int JS_ObjectDefineProperties(JSContext* ctx, JSValueConst obj, JSValueConst properties); 40 | JSValue js_object_constructor(JSContext* ctx, JSValueConst new_target, int argc, JSValueConst* argv); 41 | JSValue js_object_create(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 42 | JSValue js_object_getPrototypeOf(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, int magic); 43 | JSValue js_object_setPrototypeOf(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 44 | /* magic = 1 if called as Reflect.defineProperty */ 45 | JSValue js_object_defineProperty(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, int magic); 46 | JSValue js_object_defineProperties(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 47 | /* magic = 1 if called as __defineSetter__ */ 48 | JSValue js_object___defineGetter__(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, int magic); 49 | JSValue js_object_getOwnPropertyDescriptor(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, int magic); 50 | JSValue js_object_getOwnPropertyDescriptors(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 51 | JSValue js_object_getOwnPropertyNames(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 52 | JSValue js_object_getOwnPropertySymbols(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 53 | JSValue js_object_keys(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, int kind); 54 | JSValue js_object_isExtensible(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, int reflect); 55 | JSValue js_object_preventExtensions(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, int reflect); 56 | JSValue js_object_hasOwnProperty(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 57 | JSValue js_object_valueOf(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 58 | JSValue js_object_toString(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 59 | JSValue js_object_toLocaleString(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 60 | JSValue js_object_assign(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 61 | JSValue js_object_seal(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, int freeze_flag); 62 | JSValue js_object_isSealed(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, int is_frozen); 63 | JSValue js_object_fromEntries(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 64 | /* return an empty string if not an object */ 65 | JSValue js_object___getClass(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 66 | JSValue js_object_is(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 67 | JSValue JS_SpeciesConstructor(JSContext* ctx, JSValueConst obj, JSValueConst defaultConstructor); 68 | JSValue js_object_get___proto__(JSContext* ctx, JSValueConst this_val); 69 | JSValue js_object_set___proto__(JSContext* ctx, JSValueConst this_val, JSValueConst proto); 70 | JSValue js_object_isPrototypeOf(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 71 | JSValue js_object_propertyIsEnumerable(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 72 | JSValue js_object___lookupGetter__(JSContext* ctx, 73 | JSValueConst this_val, 74 | int argc, 75 | JSValueConst* argv, 76 | int setter); 77 | 78 | void js_object_data_finalizer(JSRuntime* rt, JSValue val); 79 | void js_object_data_mark(JSRuntime* rt, JSValueConst val, JS_MarkFunc* mark_func); 80 | 81 | #endif -------------------------------------------------------------------------------- /src/core/builtins/js-operator.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 Charlie Gordon 6 | * Copyright (c) 2023 The OpenQuickJS Team 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #ifndef QUICKJS_JS_OPERATOR_H 28 | #define QUICKJS_JS_OPERATOR_H 29 | 30 | #include "quickjs/cutils.h" 31 | #include "quickjs/quickjs.h" 32 | #include "../types.h" 33 | 34 | typedef struct JSAsyncFromSyncIteratorData { 35 | JSValue sync_iter; 36 | JSValue next_method; 37 | } JSAsyncFromSyncIteratorData; 38 | 39 | void js_for_in_iterator_finalizer(JSRuntime* rt, JSValue val); 40 | void js_for_in_iterator_mark(JSRuntime* rt, JSValueConst val, JS_MarkFunc* mark_func); 41 | 42 | void js_for_in_iterator_finalizer(JSRuntime* rt, JSValue val); 43 | void js_for_in_iterator_mark(JSRuntime* rt, JSValueConst val, JS_MarkFunc* mark_func); 44 | 45 | JSValue JS_GetIterator2(JSContext* ctx, JSValueConst obj, JSValueConst method); 46 | JSValue JS_CreateAsyncFromSyncIterator(JSContext* ctx, JSValueConst sync_iter); 47 | JSValue JS_GetIterator(JSContext* ctx, JSValueConst obj, BOOL is_async); 48 | JSValue JS_IteratorGetCompleteValue(JSContext* ctx, JSValueConst obj, BOOL* pdone); 49 | 50 | /* return *pdone = 2 if the iterator object is not parsed */ 51 | JSValue JS_IteratorNext2(JSContext* ctx, JSValueConst enum_obj, JSValueConst method, int argc, JSValueConst* argv, int* pdone); 52 | JSValue JS_IteratorNext(JSContext* ctx, JSValueConst enum_obj, JSValueConst method, int argc, JSValueConst* argv, BOOL* pdone); 53 | /* return < 0 in case of exception */ 54 | int JS_IteratorClose(JSContext* ctx, JSValueConst enum_obj, BOOL is_exception_pending); 55 | /* obj -> enum_rec (3 slots) */ 56 | __exception int js_for_of_start(JSContext* ctx, JSValue* sp, BOOL is_async); 57 | double js_pow(double a, double b); 58 | JSValue js_throw_type_error(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 59 | JSValue js_build_rest(JSContext* ctx, int first, int argc, JSValueConst* argv); 60 | JSValue build_for_in_iterator(JSContext* ctx, JSValue obj); 61 | /* obj -> enum_obj */ 62 | __exception int js_for_in_start(JSContext* ctx, JSValue* sp); 63 | /* enum_obj -> enum_obj value done */ 64 | __exception int js_for_in_next(JSContext* ctx, JSValue* sp); 65 | __exception int js_for_of_next(JSContext* ctx, JSValue* sp, int offset); 66 | 67 | BOOL js_strict_eq2(JSContext* ctx, JSValue op1, JSValue op2, JSStrictEqModeEnum eq_mode); 68 | BOOL js_strict_eq(JSContext* ctx, JSValue op1, JSValue op2); 69 | BOOL js_same_value(JSContext* ctx, JSValueConst op1, JSValueConst op2); 70 | BOOL js_same_value_zero(JSContext* ctx, JSValueConst op1, JSValueConst op2); 71 | no_inline int js_strict_eq_slow(JSContext* ctx, JSValue* sp, BOOL is_neq); 72 | __exception int js_operator_in(JSContext* ctx, JSValue* sp); 73 | __exception int js_has_unscopable(JSContext* ctx, JSValueConst obj, JSAtom atom); 74 | __exception int js_operator_instanceof(JSContext* ctx, JSValue* sp); 75 | __exception int js_operator_typeof(JSContext* ctx, JSValueConst op1); 76 | __exception int js_operator_delete(JSContext* ctx, JSValue* sp); 77 | 78 | __exception int js_iterator_get_value_done(JSContext* ctx, JSValue* sp); 79 | 80 | #endif -------------------------------------------------------------------------------- /src/core/builtins/js-promise.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 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 | 26 | #ifndef QUICKJS_JS_PROMISE_H 27 | #define QUICKJS_JS_PROMISE_H 28 | 29 | #include "quickjs/quickjs.h" 30 | #include "../types.h" 31 | 32 | JSValue js_promise_resolve(JSContext *ctx, JSValueConst this_val, 33 | int argc, JSValueConst *argv, int magic); 34 | 35 | __exception int perform_promise_then(JSContext *ctx, 36 | JSValueConst promise, 37 | JSValueConst *resolve_reject, 38 | JSValueConst *cap_resolving_funcs); 39 | 40 | #endif -------------------------------------------------------------------------------- /src/core/builtins/js-proxy.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 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 | 26 | #ifndef QUICKJS_JS_PROXY_H 27 | #define QUICKJS_JS_PROXY_H 28 | 29 | #include "quickjs/quickjs.h" 30 | #include "quickjs/cutils.h" 31 | 32 | int js_proxy_isExtensible(JSContext *ctx, JSValueConst obj); 33 | int js_proxy_preventExtensions(JSContext *ctx, JSValueConst obj); 34 | int js_proxy_has(JSContext *ctx, JSValueConst obj, JSAtom atom); 35 | JSValue js_proxy_get(JSContext *ctx, JSValueConst obj, JSAtom atom, 36 | JSValueConst receiver); 37 | int js_proxy_set(JSContext *ctx, JSValueConst obj, JSAtom atom, 38 | JSValueConst value, JSValueConst receiver, int flags); 39 | JSValue js_create_desc(JSContext *ctx, JSValueConst val, 40 | JSValueConst getter, JSValueConst setter, 41 | int flags); 42 | int js_proxy_get_own_property(JSContext *ctx, JSPropertyDescriptor *pdesc, 43 | JSValueConst obj, JSAtom prop); 44 | int js_proxy_define_own_property(JSContext *ctx, JSValueConst obj, 45 | JSAtom prop, JSValueConst val, 46 | JSValueConst getter, JSValueConst setter, 47 | int flags); 48 | int js_proxy_delete_property(JSContext *ctx, JSValueConst obj, 49 | JSAtom atom); 50 | /* return the index of the property or -1 if not found */ 51 | int find_prop_key(const JSPropertyEnum *tab, int n, JSAtom atom); 52 | int js_proxy_get_own_property_names(JSContext *ctx, 53 | JSPropertyEnum **ptab, 54 | uint32_t *plen, 55 | JSValueConst obj); 56 | JSValue js_proxy_call_constructor(JSContext *ctx, JSValueConst func_obj, 57 | JSValueConst new_target, 58 | int argc, JSValueConst *argv); 59 | JSValue js_proxy_call(JSContext *ctx, JSValueConst func_obj, 60 | JSValueConst this_obj, 61 | int argc, JSValueConst *argv, int flags); 62 | int js_proxy_isArray(JSContext *ctx, JSValueConst obj); 63 | JSValue js_proxy_constructor(JSContext *ctx, JSValueConst this_val, 64 | int argc, JSValueConst *argv); 65 | JSValue js_proxy_revoke(JSContext *ctx, JSValueConst this_val, 66 | int argc, JSValueConst *argv, int magic, 67 | JSValue *func_data); 68 | JSValue js_proxy_revoke_constructor(JSContext *ctx, 69 | JSValueConst proxy_obj); 70 | JSValue js_proxy_revocable(JSContext *ctx, JSValueConst this_val, 71 | int argc, JSValueConst *argv); 72 | 73 | 74 | JSValue js_proxy_getPrototypeOf(JSContext *ctx, JSValueConst obj); 75 | int js_proxy_setPrototypeOf(JSContext *ctx, JSValueConst obj, 76 | JSValueConst proto_val, BOOL throw_flag); 77 | 78 | #endif -------------------------------------------------------------------------------- /src/core/builtins/js-reflect.c: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 Charlie Gordon 6 | * Copyright (c) 2023 The OpenQuickJS Team 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #include "js-reflect.h" 28 | #include "../exception.h" 29 | #include "../object.h" 30 | #include "../runtime.h" 31 | #include "js-function.h" 32 | 33 | /* Reflect */ 34 | JSValue js_reflect_apply(JSContext *ctx, JSValueConst this_val, 35 | int argc, JSValueConst *argv) 36 | { 37 | return js_function_apply(ctx, argv[0], max_int(0, argc - 1), argv + 1, 2); 38 | } 39 | 40 | JSValue js_reflect_construct(JSContext *ctx, JSValueConst this_val, 41 | int argc, JSValueConst *argv) 42 | { 43 | JSValueConst func, array_arg, new_target; 44 | JSValue *tab, ret; 45 | uint32_t len; 46 | 47 | func = argv[0]; 48 | array_arg = argv[1]; 49 | if (argc > 2) { 50 | new_target = argv[2]; 51 | if (!JS_IsConstructor(ctx, new_target)) 52 | return JS_ThrowTypeError(ctx, "not a constructor"); 53 | } else { 54 | new_target = func; 55 | } 56 | tab = build_arg_list(ctx, &len, array_arg); 57 | if (!tab) 58 | return JS_EXCEPTION; 59 | ret = JS_CallConstructor2(ctx, func, new_target, len, (JSValueConst *)tab); 60 | free_arg_list(ctx, tab, len); 61 | return ret; 62 | } 63 | 64 | JSValue js_reflect_deleteProperty(JSContext *ctx, JSValueConst this_val, 65 | int argc, JSValueConst *argv) 66 | { 67 | JSValueConst obj; 68 | JSAtom atom; 69 | int ret; 70 | 71 | obj = argv[0]; 72 | if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) 73 | return JS_ThrowTypeErrorNotAnObject(ctx); 74 | atom = JS_ValueToAtom(ctx, argv[1]); 75 | if (unlikely(atom == JS_ATOM_NULL)) 76 | return JS_EXCEPTION; 77 | ret = JS_DeleteProperty(ctx, obj, atom, 0); 78 | JS_FreeAtom(ctx, atom); 79 | if (ret < 0) 80 | return JS_EXCEPTION; 81 | else 82 | return JS_NewBool(ctx, ret); 83 | } 84 | 85 | JSValue js_reflect_get(JSContext *ctx, JSValueConst this_val, 86 | int argc, JSValueConst *argv) 87 | { 88 | JSValueConst obj, prop, receiver; 89 | JSAtom atom; 90 | JSValue ret; 91 | 92 | obj = argv[0]; 93 | prop = argv[1]; 94 | if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) 95 | return JS_ThrowTypeErrorNotAnObject(ctx); 96 | if (argc > 2) 97 | receiver = argv[2]; 98 | else 99 | receiver = obj; 100 | atom = JS_ValueToAtom(ctx, prop); 101 | if (unlikely(atom == JS_ATOM_NULL)) 102 | return JS_EXCEPTION; 103 | ret = JS_GetPropertyInternal(ctx, obj, atom, receiver, NULL, FALSE); 104 | JS_FreeAtom(ctx, atom); 105 | return ret; 106 | } 107 | 108 | JSValue js_reflect_has(JSContext *ctx, JSValueConst this_val, 109 | int argc, JSValueConst *argv) 110 | { 111 | JSValueConst obj, prop; 112 | JSAtom atom; 113 | int ret; 114 | 115 | obj = argv[0]; 116 | prop = argv[1]; 117 | if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) 118 | return JS_ThrowTypeErrorNotAnObject(ctx); 119 | atom = JS_ValueToAtom(ctx, prop); 120 | if (unlikely(atom == JS_ATOM_NULL)) 121 | return JS_EXCEPTION; 122 | ret = JS_HasProperty(ctx, obj, atom); 123 | JS_FreeAtom(ctx, atom); 124 | if (ret < 0) 125 | return JS_EXCEPTION; 126 | else 127 | return JS_NewBool(ctx, ret); 128 | } 129 | 130 | JSValue js_reflect_set(JSContext *ctx, JSValueConst this_val, 131 | int argc, JSValueConst *argv) 132 | { 133 | JSValueConst obj, prop, val, receiver; 134 | int ret; 135 | JSAtom atom; 136 | 137 | obj = argv[0]; 138 | prop = argv[1]; 139 | val = argv[2]; 140 | if (argc > 3) 141 | receiver = argv[3]; 142 | else 143 | receiver = obj; 144 | if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) 145 | return JS_ThrowTypeErrorNotAnObject(ctx); 146 | atom = JS_ValueToAtom(ctx, prop); 147 | if (unlikely(atom == JS_ATOM_NULL)) 148 | return JS_EXCEPTION; 149 | ret = JS_SetPropertyGeneric(ctx, obj, atom, 150 | JS_DupValue(ctx, val), receiver, 0); 151 | JS_FreeAtom(ctx, atom); 152 | if (ret < 0) 153 | return JS_EXCEPTION; 154 | else 155 | return JS_NewBool(ctx, ret); 156 | } 157 | 158 | JSValue js_reflect_setPrototypeOf(JSContext *ctx, JSValueConst this_val, 159 | int argc, JSValueConst *argv) 160 | { 161 | int ret; 162 | ret = JS_SetPrototypeInternal(ctx, argv[0], argv[1], FALSE); 163 | if (ret < 0) 164 | return JS_EXCEPTION; 165 | else 166 | return JS_NewBool(ctx, ret); 167 | } 168 | 169 | JSValue js_reflect_ownKeys(JSContext *ctx, JSValueConst this_val, 170 | int argc, JSValueConst *argv) 171 | { 172 | if (JS_VALUE_GET_TAG(argv[0]) != JS_TAG_OBJECT) 173 | return JS_ThrowTypeErrorNotAnObject(ctx); 174 | return JS_GetOwnPropertyNames2(ctx, argv[0], 175 | JS_GPN_STRING_MASK | JS_GPN_SYMBOL_MASK, 176 | JS_ITERATOR_KIND_KEY); 177 | } 178 | -------------------------------------------------------------------------------- /src/core/builtins/js-reflect.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 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 | 26 | #ifndef QUICKJS_JS_REFLECT_H 27 | #define QUICKJS_JS_REFLECT_H 28 | 29 | #include "quickjs/quickjs.h" 30 | 31 | JSValue js_reflect_apply(JSContext *ctx, JSValueConst this_val, 32 | int argc, JSValueConst *argv); 33 | JSValue js_reflect_construct(JSContext *ctx, JSValueConst this_val, 34 | int argc, JSValueConst *argv); 35 | JSValue js_reflect_deleteProperty(JSContext *ctx, JSValueConst this_val, 36 | int argc, JSValueConst *argv); 37 | JSValue js_reflect_get(JSContext *ctx, JSValueConst this_val, 38 | int argc, JSValueConst *argv); 39 | JSValue js_reflect_has(JSContext *ctx, JSValueConst this_val, 40 | int argc, JSValueConst *argv); 41 | JSValue js_reflect_set(JSContext *ctx, JSValueConst this_val, 42 | int argc, JSValueConst *argv); 43 | JSValue js_reflect_setPrototypeOf(JSContext *ctx, JSValueConst this_val, 44 | int argc, JSValueConst *argv); 45 | JSValue js_reflect_ownKeys(JSContext *ctx, JSValueConst this_val, 46 | int argc, JSValueConst *argv); 47 | 48 | #endif -------------------------------------------------------------------------------- /src/core/builtins/js-regexp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 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 | 26 | #ifndef QUICKJS_JS_REGEXP_H 27 | #define QUICKJS_JS_REGEXP_H 28 | 29 | #include "quickjs/quickjs.h" 30 | 31 | JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern, 32 | JSValueConst flags); 33 | JSValue js_regexp_constructor_internal(JSContext *ctx, JSValueConst ctor, 34 | JSValue pattern, JSValue bc); 35 | 36 | #endif -------------------------------------------------------------------------------- /src/core/builtins/js-string.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 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 | 26 | #ifndef QUICKJS_JS_STRING_H 27 | #define QUICKJS_JS_STRING_H 28 | 29 | #include "quickjs/quickjs.h" 30 | #include "quickjs/cutils.h" 31 | #include "../types.h" 32 | 33 | /* ES6 Annex B 2.3.2 etc. */ 34 | enum { 35 | magic_string_anchor, 36 | magic_string_big, 37 | magic_string_blink, 38 | magic_string_bold, 39 | magic_string_fixed, 40 | magic_string_fontcolor, 41 | magic_string_fontsize, 42 | magic_string_italics, 43 | magic_string_link, 44 | magic_string_small, 45 | magic_string_strike, 46 | magic_string_sub, 47 | magic_string_sup, 48 | }; 49 | 50 | int js_string_get_own_property(JSContext* ctx, JSPropertyDescriptor* desc, JSValueConst obj, JSAtom prop); 51 | int js_string_define_own_property(JSContext* ctx, JSValueConst this_obj, JSAtom prop, JSValueConst val, JSValueConst getter, JSValueConst setter, int flags); 52 | int js_string_delete_property(JSContext* ctx, JSValueConst obj, JSAtom prop); 53 | JSValue js_string_constructor(JSContext* ctx, JSValueConst new_target, int argc, JSValueConst* argv); 54 | JSValue js_thisStringValue(JSContext* ctx, JSValueConst this_val) ; 55 | JSValue js_string_fromCharCode(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 56 | JSValue js_string_fromCodePoint(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 57 | JSValue js_string_raw(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 58 | /* only used in test262 */ 59 | JSValue js_string_codePointRange(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 60 | JSValue js_string_charCodeAt(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 61 | JSValue js_string_charAt(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 62 | JSValue js_string_codePointAt(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 63 | JSValue js_string_concat(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 64 | int string_cmp(JSString* p1, JSString* p2, int x1, int x2, int len); 65 | int string_indexof_char(JSString* p, int c, int from); 66 | int string_indexof(JSString* p1, JSString* p2, int from); 67 | int64_t string_advance_index(JSString* p, int64_t index, BOOL unicode); 68 | JSValue js_string_indexOf(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, int lastIndexOf) ; 69 | int js_is_regexp(JSContext* ctx, JSValueConst obj);; 70 | JSValue js_string_includes(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, int magic); 71 | int check_regexp_g_flag(JSContext* ctx, JSValueConst regexp); 72 | JSValue js_string_match(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, int atom); 73 | JSValue js_string___GetSubstitution(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 74 | JSValue js_string_replace(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, int is_replaceAll); 75 | JSValue js_string_split(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 76 | JSValue js_string_substring(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 77 | JSValue js_string_substr(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 78 | JSValue js_string_slice(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 79 | JSValue js_string_pad(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, int padEnd); 80 | JSValue js_string_repeat(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 81 | JSValue js_string_trim(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, int magic); 82 | JSValue js_string___quote(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 83 | int string_prevc(JSString* p, int* pidx); 84 | BOOL test_final_sigma(JSString* p, int sigma_pos); 85 | JSValue js_string_localeCompare(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 86 | JSValue js_string_toLowerCase(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, int to_lower); 87 | JSValue js_string_toString(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv); 88 | JSValue js_string_iterator_next(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, BOOL* pdone, int magic); 89 | JSValue js_string_CreateHTML(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv, int magic); 90 | 91 | #endif -------------------------------------------------------------------------------- /src/core/builtins/js-symbol.c: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 Charlie Gordon 6 | * Copyright (c) 2023 The OpenQuickJS Team 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #include "js-symbol.h" 28 | #include "../exception.h" 29 | #include "../string.h" 30 | #include "../types.h" 31 | #include "js-string.h" 32 | 33 | /* Symbol */ 34 | 35 | JSValue js_symbol_constructor(JSContext *ctx, JSValueConst new_target, 36 | int argc, JSValueConst *argv) 37 | { 38 | JSValue str; 39 | JSString *p; 40 | 41 | if (!JS_IsUndefined(new_target)) 42 | return JS_ThrowTypeError(ctx, "not a constructor"); 43 | if (argc == 0 || JS_IsUndefined(argv[0])) { 44 | p = NULL; 45 | } else { 46 | str = JS_ToString(ctx, argv[0]); 47 | if (JS_IsException(str)) 48 | return JS_EXCEPTION; 49 | p = JS_VALUE_GET_STRING(str); 50 | } 51 | return JS_NewSymbol(ctx, p, JS_ATOM_TYPE_SYMBOL); 52 | } 53 | 54 | JSValue js_thisSymbolValue(JSContext *ctx, JSValueConst this_val) 55 | { 56 | if (JS_VALUE_GET_TAG(this_val) == JS_TAG_SYMBOL) 57 | return JS_DupValue(ctx, this_val); 58 | 59 | if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT) { 60 | JSObject *p = JS_VALUE_GET_OBJ(this_val); 61 | if (p->class_id == JS_CLASS_SYMBOL) { 62 | if (JS_VALUE_GET_TAG(p->u.object_data) == JS_TAG_SYMBOL) 63 | return JS_DupValue(ctx, p->u.object_data); 64 | } 65 | } 66 | return JS_ThrowTypeError(ctx, "not a symbol"); 67 | } 68 | 69 | JSValue js_symbol_toString(JSContext *ctx, JSValueConst this_val, 70 | int argc, JSValueConst *argv) 71 | { 72 | JSValue val, ret; 73 | val = js_thisSymbolValue(ctx, this_val); 74 | if (JS_IsException(val)) 75 | return val; 76 | /* XXX: use JS_ToStringInternal() with a flags */ 77 | ret = js_string_constructor(ctx, JS_UNDEFINED, 1, (JSValueConst *)&val); 78 | JS_FreeValue(ctx, val); 79 | return ret; 80 | } 81 | 82 | JSValue js_symbol_valueOf(JSContext *ctx, JSValueConst this_val, 83 | int argc, JSValueConst *argv) 84 | { 85 | return js_thisSymbolValue(ctx, this_val); 86 | } 87 | 88 | JSValue js_symbol_get_description(JSContext *ctx, JSValueConst this_val) 89 | { 90 | JSValue val, ret; 91 | JSAtomStruct *p; 92 | 93 | val = js_thisSymbolValue(ctx, this_val); 94 | if (JS_IsException(val)) 95 | return val; 96 | p = JS_VALUE_GET_PTR(val); 97 | if (p->len == 0 && p->is_wide_char != 0) { 98 | ret = JS_UNDEFINED; 99 | } else { 100 | ret = JS_AtomToString(ctx, js_get_atom_index(ctx->rt, p)); 101 | } 102 | JS_FreeValue(ctx, val); 103 | return ret; 104 | } 105 | 106 | JSValue js_symbol_for(JSContext *ctx, JSValueConst this_val, 107 | int argc, JSValueConst *argv) 108 | { 109 | JSValue str; 110 | 111 | str = JS_ToString(ctx, argv[0]); 112 | if (JS_IsException(str)) 113 | return JS_EXCEPTION; 114 | return JS_NewSymbol(ctx, JS_VALUE_GET_STRING(str), JS_ATOM_TYPE_GLOBAL_SYMBOL); 115 | } 116 | 117 | JSValue js_symbol_keyFor(JSContext *ctx, JSValueConst this_val, 118 | int argc, JSValueConst *argv) 119 | { 120 | JSAtomStruct *p; 121 | 122 | if (!JS_IsSymbol(argv[0])) 123 | return JS_ThrowTypeError(ctx, "not a symbol"); 124 | p = JS_VALUE_GET_PTR(argv[0]); 125 | if (p->atom_type != JS_ATOM_TYPE_GLOBAL_SYMBOL) 126 | return JS_UNDEFINED; 127 | return JS_DupValue(ctx, JS_MKPTR(JS_TAG_STRING, p)); 128 | } -------------------------------------------------------------------------------- /src/core/builtins/js-symbol.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 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 | 26 | #ifndef QUICKJS_JS_SYMBOL_H 27 | #define QUICKJS_JS_SYMBOL_H 28 | 29 | #include "quickjs/quickjs.h" 30 | 31 | JSValue js_symbol_constructor(JSContext *ctx, JSValueConst new_target, 32 | int argc, JSValueConst *argv); 33 | JSValue js_thisSymbolValue(JSContext *ctx, JSValueConst this_val); 34 | JSValue js_symbol_toString(JSContext *ctx, JSValueConst this_val, 35 | int argc, JSValueConst *argv); 36 | JSValue js_symbol_valueOf(JSContext *ctx, JSValueConst this_val, 37 | int argc, JSValueConst *argv); 38 | JSValue js_symbol_get_description(JSContext *ctx, JSValueConst this_val); 39 | JSValue js_symbol_for(JSContext *ctx, JSValueConst this_val, 40 | int argc, JSValueConst *argv); 41 | JSValue js_symbol_keyFor(JSContext *ctx, JSValueConst this_val, 42 | int argc, JSValueConst *argv); 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /src/core/builtins/js-typed-array.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 Charlie Gordon 6 | * Copyright (c) 2023 The OpenQuickJS Team 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #ifndef QUICKJS_JS_TYPED_ARRAY_H 28 | #define QUICKJS_JS_TYPED_ARRAY_H 29 | 30 | #include "../types.h" 31 | #include "quickjs/cutils.h" 32 | #include "quickjs/quickjs.h" 33 | 34 | JSValue js_array_buffer_constructor3(JSContext* ctx, JSValueConst new_target, uint64_t len, JSClassID class_id, uint8_t* buf, JSFreeArrayBufferDataFunc* free_func, void* opaque, BOOL alloc_flag); 35 | JSValue js_typed_array_constructor(JSContext* ctx, JSValueConst new_target, int argc, JSValueConst* argv, int classid); 36 | 37 | JSArrayBuffer* js_get_array_buffer(JSContext* ctx, JSValueConst obj); 38 | BOOL typed_array_is_detached(JSContext* ctx, JSObject* p); 39 | JSValue JS_ThrowTypeErrorDetachedArrayBuffer(JSContext* ctx); 40 | 41 | #endif -------------------------------------------------------------------------------- /src/core/bytecode.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 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 | 26 | #ifndef QUICKJS_BYTECODE_H 27 | #define QUICKJS_BYTECODE_H 28 | 29 | #include "quickjs/quickjs.h" 30 | #include "quickjs/cutils.h" 31 | #include "types.h" 32 | 33 | void free_function_bytecode(JSRuntime *rt, JSFunctionBytecode *b); 34 | void free_bytecode_atoms(JSRuntime *rt, 35 | const uint8_t *bc_buf, int bc_len, 36 | BOOL use_short_opcodes);; 37 | 38 | #endif -------------------------------------------------------------------------------- /src/core/exception.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 Charlie Gordon 6 | * Copyright (c) 2023 The OpenQuickJS Team 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #ifndef QUICKJS_EXCEPTION_H 28 | #define QUICKJS_EXCEPTION_H 29 | 30 | #include "quickjs/cutils.h" 31 | #include "quickjs/quickjs.h" 32 | #include "types.h" 33 | 34 | #define JS_DEFINE_CLASS_HAS_HERITAGE (1 << 0) 35 | 36 | /* %s is replaced by 'atom'. The macro is used so that gcc can check 37 | the format string. */ 38 | #define JS_ThrowTypeErrorAtom(ctx, fmt, atom) __JS_ThrowTypeErrorAtom(ctx, atom, fmt, "") 39 | #define JS_ThrowSyntaxErrorAtom(ctx, fmt, atom) __JS_ThrowSyntaxErrorAtom(ctx, atom, fmt, "") 40 | 41 | JSValue __attribute__((format(printf, 2, 3))) JS_ThrowInternalError(JSContext* ctx, const char* fmt, ...); 42 | JSValue JS_ThrowError2(JSContext* ctx, JSErrorEnum error_num, const char* fmt, va_list ap, BOOL add_backtrace); 43 | JSValue JS_ThrowError(JSContext* ctx, JSErrorEnum error_num, const char* fmt, va_list ap); 44 | 45 | int __attribute__((format(printf, 3, 4))) JS_ThrowTypeErrorOrFalse(JSContext* ctx, int flags, const char* fmt, ...); 46 | JSValue __attribute__((format(printf, 3, 4))) __JS_ThrowTypeErrorAtom(JSContext* ctx, JSAtom atom, const char* fmt, ...); 47 | JSValue __attribute__((format(printf, 3, 4))) __JS_ThrowSyntaxErrorAtom(JSContext* ctx, JSAtom atom, const char* fmt, ...); 48 | 49 | JSValue JS_ThrowTypeErrorPrivateNotFound(JSContext* ctx, JSAtom atom); 50 | 51 | int JS_ThrowTypeErrorReadOnly(JSContext* ctx, int flags, JSAtom atom); 52 | JSValue JS_ThrowOutOfMemory(JSContext* ctx); 53 | JSValue JS_ThrowTypeErrorRevokedProxy(JSContext* ctx); 54 | JSValue JS_ThrowStackOverflow(JSContext* ctx); 55 | JSValue JS_ThrowTypeErrorNotAnObject(JSContext* ctx); 56 | JSValue JS_ThrowTypeErrorNotASymbol(JSContext* ctx); 57 | JSValue JS_ThrowReferenceErrorNotDefined(JSContext* ctx, JSAtom name); 58 | JSValue JS_ThrowReferenceErrorUninitialized(JSContext* ctx, JSAtom name); 59 | JSValue JS_ThrowReferenceErrorUninitialized2(JSContext* ctx, JSFunctionBytecode* b, int idx, BOOL is_ref); 60 | JSValue JS_ThrowTypeErrorInvalidClass(JSContext* ctx, int class_id); 61 | 62 | void JS_SetUncatchableError(JSContext* ctx, JSValueConst val, BOOL flag); 63 | 64 | /* used to avoid catching interrupt exceptions */ 65 | BOOL JS_IsUncatchableError(JSContext* ctx, JSValueConst val); 66 | 67 | JSValue JS_Throw(JSContext* ctx, JSValue obj); 68 | JSValue JS_GetException(JSContext* ctx); 69 | JS_BOOL JS_IsError(JSContext* ctx, JSValueConst val); 70 | void JS_ResetUncatchableError(JSContext* ctx); 71 | JSValue JS_NewError(JSContext* ctx); 72 | JSValue __js_printf_like(2, 3) JS_ThrowSyntaxError(JSContext* ctx, const char* fmt, ...); 73 | JSValue __js_printf_like(2, 3) JS_ThrowTypeError(JSContext* ctx, const char* fmt, ...); 74 | JSValue __js_printf_like(2, 3) JS_ThrowReferenceError(JSContext* ctx, const char* fmt, ...); 75 | JSValue __js_printf_like(2, 3) JS_ThrowRangeError(JSContext* ctx, const char* fmt, ...); 76 | JSValue __js_printf_like(2, 3) JS_ThrowInternalError(JSContext* ctx, const char* fmt, ...); 77 | JSValue JS_ThrowOutOfMemory(JSContext* ctx); 78 | 79 | #endif -------------------------------------------------------------------------------- /src/core/gc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 Charlie Gordon 6 | * Copyright (c) 2023 The OpenQuickJS Team 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #ifndef QUICKJS_GC_H 28 | #define QUICKJS_GC_H 29 | 30 | #include "quickjs/quickjs.h" 31 | #include "quickjs/cutils.h" 32 | #include "quickjs/list.h" 33 | #include "types.h" 34 | 35 | /* object list */ 36 | 37 | typedef struct { 38 | JSObject* obj; 39 | uint32_t hash_next; /* -1 if no next entry */ 40 | } JSObjectListEntry; 41 | 42 | /* XXX: reuse it to optimize weak references */ 43 | typedef struct { 44 | JSObjectListEntry* object_tab; 45 | int object_count; 46 | int object_size; 47 | uint32_t* hash_table; 48 | uint32_t hash_size; 49 | } JSObjectList; 50 | 51 | typedef enum JSFreeModuleEnum { 52 | JS_FREE_MODULE_ALL, 53 | JS_FREE_MODULE_NOT_RESOLVED, 54 | JS_FREE_MODULE_NOT_EVALUATED, 55 | } JSFreeModuleEnum; 56 | 57 | void js_object_list_init(JSObjectList* s); 58 | uint32_t js_object_list_get_hash(JSObject* p, uint32_t hash_size); 59 | int js_object_list_resize_hash(JSContext* ctx, JSObjectList* s, uint32_t new_hash_size); 60 | /* the reference count of 'obj' is not modified. Return 0 if OK, -1 if 61 | memory error */ 62 | int js_object_list_add(JSContext* ctx, JSObjectList* s, JSObject* obj); 63 | 64 | /* return -1 if not present or the object index */ 65 | int js_object_list_find(JSContext* ctx, JSObjectList* s, JSObject* obj); 66 | 67 | void js_object_list_end(JSContext* ctx, JSObjectList* s); 68 | void free_gc_object(JSRuntime* rt, JSGCObjectHeader* gp); 69 | void free_zero_refcount(JSRuntime* rt); 70 | 71 | /* XXX: would be more efficient with separate module lists */ 72 | void js_free_modules(JSContext* ctx, JSFreeModuleEnum flag); 73 | 74 | __maybe_unused void JS_DumpObjectHeader(JSRuntime* rt); 75 | __maybe_unused void JS_DumpObject(JSRuntime* rt, JSObject* p); 76 | __maybe_unused void JS_DumpGCObject(JSRuntime* rt, JSGCObjectHeader* p); 77 | __maybe_unused void JS_DumpValueShort(JSRuntime* rt, JSValueConst val); 78 | __maybe_unused void JS_DumpValue(JSContext* ctx, JSValueConst val); 79 | __maybe_unused void JS_PrintValue(JSContext* ctx, const char* str, JSValueConst val); 80 | 81 | /* used by the GC */ 82 | void JS_MarkContext(JSRuntime* rt, JSContext* ctx, JS_MarkFunc* mark_func); 83 | 84 | void mark_children(JSRuntime* rt, JSGCObjectHeader* gp, JS_MarkFunc* mark_func); 85 | void gc_decref_child(JSRuntime* rt, JSGCObjectHeader* p); 86 | void gc_decref(JSRuntime* rt); 87 | void gc_scan_incref_child(JSRuntime* rt, JSGCObjectHeader* p); 88 | void gc_scan_incref_child2(JSRuntime* rt, JSGCObjectHeader* p); 89 | void gc_scan(JSRuntime* rt); 90 | void gc_free_cycles(JSRuntime* rt); 91 | 92 | void free_var_ref(JSRuntime* rt, JSVarRef* var_ref); 93 | void free_object(JSRuntime* rt, JSObject* p); 94 | void add_gc_object(JSRuntime* rt, JSGCObjectHeader* h, JSGCObjectTypeEnum type); 95 | void set_cycle_flag(JSContext* ctx, JSValueConst obj); 96 | void remove_gc_object(JSGCObjectHeader* h); 97 | void js_regexp_finalizer(JSRuntime* rt, JSValue val); 98 | void js_array_buffer_finalizer(JSRuntime* rt, JSValue val); 99 | void js_typed_array_finalizer(JSRuntime* rt, JSValue val); 100 | void js_typed_array_mark(JSRuntime* rt, JSValueConst val, JS_MarkFunc* mark_func); 101 | void js_proxy_finalizer(JSRuntime* rt, JSValue val); 102 | void js_proxy_mark(JSRuntime* rt, JSValueConst val, JS_MarkFunc* mark_func); 103 | void js_map_finalizer(JSRuntime* rt, JSValue val); 104 | void js_map_mark(JSRuntime* rt, JSValueConst val, JS_MarkFunc* mark_func); 105 | void js_map_iterator_finalizer(JSRuntime* rt, JSValue val); 106 | void js_map_iterator_mark(JSRuntime* rt, JSValueConst val, JS_MarkFunc* mark_func); 107 | 108 | void js_regexp_string_iterator_finalizer(JSRuntime* rt, JSValue val); 109 | void js_regexp_string_iterator_mark(JSRuntime* rt, JSValueConst val, JS_MarkFunc* mark_func); 110 | void js_generator_finalizer(JSRuntime* rt, JSValue obj); 111 | void js_generator_mark(JSRuntime* rt, JSValueConst val, JS_MarkFunc* mark_func); 112 | void js_promise_finalizer(JSRuntime* rt, JSValue val); 113 | void js_promise_mark(JSRuntime* rt, JSValueConst val, JS_MarkFunc* mark_func); 114 | void js_promise_resolve_function_finalizer(JSRuntime* rt, JSValue val); 115 | void js_promise_resolve_function_mark(JSRuntime* rt, JSValueConst val, JS_MarkFunc* mark_func); 116 | #ifdef CONFIG_BIGNUM 117 | void js_operator_set_finalizer(JSRuntime* rt, JSValue val); 118 | void js_operator_set_mark(JSRuntime* rt, JSValueConst val, JS_MarkFunc* mark_func); 119 | #endif 120 | 121 | #endif 122 | -------------------------------------------------------------------------------- /src/core/ic.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 Charlie Gordon 6 | * Copyright (c) 2023 The OpenQuickJS Team 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #ifndef QUICKJS_IC_H 28 | #define QUICKJS_IC_H 29 | 30 | #include "quickjs/quickjs.h" 31 | #include "shape.h" 32 | #include "types.h" 33 | 34 | InlineCache *init_ic(JSContext *ctx); 35 | int rebuild_ic(InlineCache *ic); 36 | int resize_ic_hash(InlineCache *ic); 37 | int free_ic(InlineCache *ic); 38 | uint32_t add_ic_slot(InlineCache *ic, JSAtom atom, JSObject *object, 39 | uint32_t prop_offset, JSObject* prototype); 40 | uint32_t add_ic_slot1(InlineCache *ic, JSAtom atom); 41 | force_inline int32_t get_ic_prop_offset(InlineCache *ic, uint32_t cache_offset, 42 | JSShape *shape, JSObject **prototype) { 43 | uint32_t i; 44 | InlineCacheRingSlot *cr; 45 | InlineCacheRingItem *buffer; 46 | assert(cache_offset < ic->capacity); 47 | cr = ic->cache + cache_offset; 48 | i = cr->index; 49 | for (;;) { 50 | buffer = cr->buffer + i; 51 | if (likely(buffer->shape == shape)) { 52 | cr->index = i; 53 | *prototype = buffer->proto; 54 | return buffer->prop_offset; 55 | } 56 | 57 | i = (i + 1) % IC_CACHE_ITEM_CAPACITY; 58 | if (unlikely(i == cr->index)) { 59 | break; 60 | } 61 | } 62 | 63 | *prototype = NULL; 64 | return -1; 65 | } 66 | 67 | force_inline JSAtom get_ic_atom(InlineCache *ic, uint32_t cache_offset) { 68 | assert(cache_offset < ic->capacity); 69 | return ic->cache[cache_offset].atom; 70 | } 71 | 72 | int ic_watchpoint_delete_handler(JSRuntime* rt, intptr_t ref, JSAtom atom, void* target); 73 | int ic_watchpoint_free_handler(JSRuntime* rt, intptr_t ref, JSAtom atom); 74 | int ic_delete_shape_proto_watchpoints(JSRuntime *rt, JSShape *shape, JSAtom atom); 75 | int ic_free_shape_proto_watchpoints(JSRuntime *rt, JSShape *shape); 76 | #endif -------------------------------------------------------------------------------- /src/core/malloc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 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 | 26 | #ifndef QUICKJS_MALLOC_H 27 | #define QUICKJS_MALLOC_H 28 | 29 | #include "quickjs/quickjs.h" 30 | #include "quickjs/cutils.h" 31 | #include "types.h" 32 | 33 | void js_trigger_gc(JSRuntime* rt, size_t size); 34 | no_inline int js_realloc_array(JSContext* ctx, void** parray, int elem_size, int* psize, int req_size); 35 | 36 | /* resize the array and update its size if req_size > *psize */ 37 | static inline int js_resize_array(JSContext* ctx, void** parray, int elem_size, int* psize, int req_size) { 38 | if (unlikely(req_size > *psize)) 39 | return js_realloc_array(ctx, parray, elem_size, psize, req_size); 40 | else 41 | return 0; 42 | } 43 | 44 | static inline void js_dbuf_init(JSContext* ctx, DynBuf* s) { 45 | dbuf_init2(s, ctx->rt, (DynBufReallocFunc*)js_realloc_rt); 46 | } 47 | 48 | 49 | void* js_def_malloc(JSMallocState* s, size_t size); 50 | void js_def_free(JSMallocState* s, void* ptr); 51 | void* js_def_realloc(JSMallocState* s, void* ptr, size_t size); 52 | size_t js_malloc_usable_size_unknown(const void* ptr); 53 | 54 | 55 | #if CONFIG_BIGNUM 56 | void* js_bf_realloc(void* opaque, void* ptr, size_t size); 57 | #endif 58 | 59 | #endif -------------------------------------------------------------------------------- /src/core/memory.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 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 | 26 | #ifndef QUICKJS_MEMORY_H 27 | #define QUICKJS_MEMORY_H 28 | 29 | #include "quickjs/quickjs.h" 30 | #include "quickjs/cutils.h" 31 | 32 | #endif -------------------------------------------------------------------------------- /src/core/module.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 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 | 26 | #ifndef QUICKJS_MODULE_H 27 | #define QUICKJS_MODULE_H 28 | 29 | #include "quickjs/quickjs.h" 30 | #include "types.h" 31 | 32 | typedef struct JSResolveEntry { 33 | JSModuleDef *module; 34 | JSAtom name; 35 | } JSResolveEntry; 36 | 37 | typedef struct JSResolveState { 38 | JSResolveEntry *array; 39 | int size; 40 | int count; 41 | } JSResolveState; 42 | 43 | /* 'name' is freed */ 44 | JSModuleDef *js_new_module_def(JSContext *ctx, JSAtom name); 45 | 46 | void js_mark_module_def(JSRuntime *rt, JSModuleDef *m, 47 | JS_MarkFunc *mark_func); 48 | 49 | int add_req_module_entry(JSContext *ctx, JSModuleDef *m, 50 | JSAtom module_name); 51 | 52 | JSExportEntry *find_export_entry(JSContext *ctx, JSModuleDef *m, 53 | JSAtom export_name); 54 | 55 | char *js_default_module_normalize_name(JSContext *ctx, 56 | const char *base_name, 57 | const char *name); 58 | 59 | JSModuleDef *js_find_loaded_module(JSContext *ctx, JSAtom name); 60 | 61 | /* return NULL in case of exception (e.g. module could not be loaded) */ 62 | JSModuleDef *js_host_resolve_imported_module(JSContext *ctx, 63 | const char *base_cname, 64 | const char *cname1); 65 | 66 | JSModuleDef *js_host_resolve_imported_module_atom(JSContext *ctx, 67 | JSAtom base_module_name, 68 | JSAtom module_name1); 69 | 70 | int js_create_module_function(JSContext *ctx, JSModuleDef *m); 71 | 72 | /* Load all the required modules for module 'm' */ 73 | int js_resolve_module(JSContext *ctx, JSModuleDef *m); 74 | 75 | /* Prepare a module to be executed by resolving all the imported 76 | variables. */ 77 | int js_link_module(JSContext *ctx, JSModuleDef *m); 78 | 79 | /* Run the function of the module and of all its requested 80 | modules. */ 81 | JSValue js_evaluate_module(JSContext *ctx, JSModuleDef *m); 82 | 83 | JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier); 84 | 85 | #endif -------------------------------------------------------------------------------- /src/core/shape.h: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS Javascript Engine 3 | * 4 | * Copyright (c) 2017-2021 Fabrice Bellard 5 | * Copyright (c) 2017-2021 Charlie Gordon 6 | * Copyright (c) 2023 The OpenQuickJS Team 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #ifndef QUICKJS_SHAPE_H 28 | #define QUICKJS_SHAPE_H 29 | 30 | #include "quickjs/quickjs.h" 31 | #include "quickjs/cutils.h" 32 | #include "types.h" 33 | 34 | 35 | static inline size_t get_shape_size(size_t hash_size, size_t prop_size) { 36 | return hash_size * sizeof(uint32_t) + sizeof(JSShape) + prop_size * sizeof(JSShapeProperty); 37 | } 38 | 39 | static inline JSShape* get_shape_from_alloc(void* sh_alloc, size_t hash_size) { 40 | return (JSShape*)(void*)((uint32_t*)sh_alloc + hash_size); 41 | } 42 | 43 | static inline uint32_t* prop_hash_end(JSShape* sh) { 44 | return (uint32_t*)sh; 45 | } 46 | 47 | static inline void* get_alloc_from_shape(JSShape* sh) { 48 | return prop_hash_end(sh) - ((intptr_t)sh->prop_hash_mask + 1); 49 | } 50 | 51 | static inline JSShapeProperty* get_shape_prop(JSShape* sh) { 52 | return sh->prop; 53 | } 54 | 55 | int init_shape_hash(JSRuntime* rt); 56 | /* same magic hash multiplier as the Linux kernel */ 57 | uint32_t shape_hash(uint32_t h, uint32_t val); 58 | /* truncate the shape hash to 'hash_bits' bits */ 59 | uint32_t get_shape_hash(uint32_t h, int hash_bits); 60 | uint32_t shape_initial_hash(JSObject* proto); 61 | int resize_shape_hash(JSRuntime* rt, int new_shape_hash_bits); 62 | void js_shape_hash_link(JSRuntime* rt, JSShape* sh); 63 | void js_shape_hash_unlink(JSRuntime* rt, JSShape* sh); 64 | /* create a new empty shape with prototype 'proto' */ 65 | no_inline JSShape* js_new_shape2(JSContext* ctx, JSObject* proto, int hash_size, int prop_size); 66 | JSShape* js_new_shape(JSContext* ctx, JSObject* proto); 67 | 68 | /* The shape is cloned. The new shape is not inserted in the shape 69 | hash table */ 70 | JSShape* js_clone_shape(JSContext* ctx, JSShape* sh1); 71 | JSShape* js_dup_shape(JSShape* sh); 72 | void js_free_shape0(JSRuntime* rt, JSShape* sh); 73 | void js_free_shape(JSRuntime* rt, JSShape* sh); 74 | void js_free_shape_null(JSRuntime* rt, JSShape* sh); 75 | /* make space to hold at least 'count' properties */ 76 | no_inline int resize_properties(JSContext* ctx, JSShape** psh, JSObject* p, uint32_t count); 77 | /* remove the deleted properties. */ 78 | int compact_properties(JSContext* ctx, JSObject* p); 79 | int add_shape_property(JSContext* ctx, JSShape** psh, JSObject* p, JSAtom atom, int prop_flags); 80 | /* find a hashed empty shape matching the prototype. Return NULL if 81 | not found */ 82 | JSShape* find_hashed_shape_proto(JSRuntime* rt, JSObject* proto); 83 | /* find a hashed shape matching sh + (prop, prop_flags). Return NULL if 84 | not found */ 85 | JSShape* find_hashed_shape_prop(JSRuntime* rt, JSShape* sh, JSAtom atom, int prop_flags);; 86 | __maybe_unused void JS_DumpShape(JSRuntime* rt, int i, JSShape* sh); 87 | __maybe_unused void JS_DumpShapes(JSRuntime* rt); 88 | JSValue JS_NewObjectFromShape(JSContext* ctx, JSShape* sh, JSClassID class_id); 89 | /* ensure that the shape can be safely modified */ 90 | int js_shape_prepare_update(JSContext* ctx, JSObject* p, JSShapeProperty** pprs); 91 | 92 | /* the watch point of shape for prototype inline cache or something else */ 93 | int js_shape_delete_watchpoints(JSRuntime *rt, JSShape *shape, void* target); 94 | int js_shape_free_watchpoints(JSRuntime *rt, JSShape *shape); 95 | ICWatchpoint* js_shape_create_watchpoint(JSRuntime *rt, JSShape *shape, intptr_t ptr, JSAtom atom, 96 | watchpoint_delete_callback *remove_callback, 97 | watchpoint_free_callback *clear_callback); 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /src/crates/.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | include/ -------------------------------------------------------------------------------- /src/crates/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.19.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler" 16 | version = "1.0.2" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 19 | 20 | [[package]] 21 | name = "backtrace" 22 | version = "0.3.67" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" 25 | dependencies = [ 26 | "addr2line", 27 | "cc", 28 | "cfg-if", 29 | "libc", 30 | "miniz_oxide", 31 | "object", 32 | "rustc-demangle", 33 | ] 34 | 35 | [[package]] 36 | name = "cc" 37 | version = "1.0.79" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" 40 | 41 | [[package]] 42 | name = "cfg-if" 43 | version = "1.0.0" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 46 | 47 | [[package]] 48 | name = "gimli" 49 | version = "0.27.2" 50 | source = "registry+https://github.com/rust-lang/crates.io-index" 51 | checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" 52 | 53 | [[package]] 54 | name = "libc" 55 | version = "0.2.146" 56 | source = "registry+https://github.com/rust-lang/crates.io-index" 57 | checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" 58 | 59 | [[package]] 60 | name = "memchr" 61 | version = "2.5.0" 62 | source = "registry+https://github.com/rust-lang/crates.io-index" 63 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 64 | 65 | [[package]] 66 | name = "miniz_oxide" 67 | version = "0.6.2" 68 | source = "registry+https://github.com/rust-lang/crates.io-index" 69 | checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" 70 | dependencies = [ 71 | "adler", 72 | ] 73 | 74 | [[package]] 75 | name = "object" 76 | version = "0.30.4" 77 | source = "registry+https://github.com/rust-lang/crates.io-index" 78 | checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385" 79 | dependencies = [ 80 | "memchr", 81 | ] 82 | 83 | [[package]] 84 | name = "quickjs" 85 | version = "0.1.0" 86 | dependencies = [ 87 | "quickjs_backtrace", 88 | "quickjs_gc", 89 | ] 90 | 91 | [[package]] 92 | name = "quickjs_backtrace" 93 | version = "0.1.0" 94 | dependencies = [ 95 | "quickjs_common", 96 | ] 97 | 98 | [[package]] 99 | name = "quickjs_common" 100 | version = "0.1.0" 101 | dependencies = [ 102 | "backtrace", 103 | "libc", 104 | ] 105 | 106 | [[package]] 107 | name = "quickjs_gc" 108 | version = "0.1.0" 109 | dependencies = [ 110 | "quickjs_common", 111 | ] 112 | 113 | [[package]] 114 | name = "rustc-demangle" 115 | version = "0.1.23" 116 | source = "registry+https://github.com/rust-lang/crates.io-index" 117 | checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" 118 | -------------------------------------------------------------------------------- /src/crates/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "2" 3 | members = [ 4 | "quickjs", 5 | "quickjs_gc", 6 | "quickjs_backtrace", 7 | "quickjs_common" 8 | ] -------------------------------------------------------------------------------- /src/crates/README.md: -------------------------------------------------------------------------------- 1 | # Rust Crates 2 | 3 | ## Prerequisites 4 | 5 | ### `rust nightly` 6 | 7 | We rely on features that are only available in `rust nightly`. To install `rust nightly`: 8 | 9 | ```bash 10 | rustup default nightly 11 | rustup update 12 | ``` 13 | 14 | ### `cbindgen` 15 | 16 | We use `cbindgen` to generate the C header file for the Rust library. To install `cbindgen`: 17 | 18 | ```bash 19 | cargo install --force cbindgen 20 | ``` -------------------------------------------------------------------------------- /src/crates/cbindgen.toml: -------------------------------------------------------------------------------- 1 | # This is a template cbindgen.toml file with all of the default values. 2 | # Some values are commented out because their absence is the real default. 3 | # 4 | # See https://github.com/eqrion/cbindgen/blob/master/docs.md#cbindgentoml 5 | # for detailed documentation of every option here. 6 | 7 | 8 | 9 | language = "c" 10 | 11 | 12 | 13 | ############## Options for Wrapping the Contents of the Header ################# 14 | 15 | # header = "/* Text to put at the beginning of the generated file. Probably a license. */" 16 | # trailer = "/* Text to put at the end of the generated file */" 17 | # include_guard = "my_bindings_h" 18 | # pragma_once = true 19 | # autogen_warning = "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */" 20 | include_version = false 21 | # namespace = "my_namespace" 22 | namespaces = [] 23 | using_namespaces = [] 24 | sys_includes = [] 25 | includes = [] 26 | no_includes = true 27 | after_includes = "" 28 | 29 | 30 | 31 | 32 | ############################ Code Style Options ################################ 33 | 34 | braces = "SameLine" 35 | line_length = 100 36 | tab_width = 2 37 | documentation = true 38 | documentation_style = "auto" 39 | documentation_length = "full" 40 | line_endings = "LF" # also "CR", "CRLF", "Native" 41 | 42 | 43 | 44 | 45 | ############################# Codegen Options ################################## 46 | 47 | style = "both" 48 | sort_by = "Name" # default for `fn.sort_by` and `const.sort_by` 49 | usize_is_size_t = true 50 | 51 | 52 | 53 | [defines] 54 | # "target_os = freebsd" = "DEFINE_FREEBSD" 55 | # "feature = serde" = "DEFINE_SERDE" 56 | 57 | 58 | 59 | [export] 60 | include = [] 61 | exclude = ["JSGCObjectHeader"] 62 | # prefix = "CAPI_" 63 | item_types = [] 64 | renaming_overrides_prefixing = false 65 | 66 | 67 | 68 | [export.rename] 69 | 70 | 71 | 72 | [export.body] 73 | 74 | 75 | [export.mangle] 76 | 77 | 78 | [fn] 79 | rename_args = "None" 80 | # must_use = "MUST_USE_FUNC" 81 | # no_return = "NO_RETURN" 82 | # prefix = "START_FUNC" 83 | # postfix = "END_FUNC" 84 | args = "auto" 85 | sort_by = "Name" 86 | 87 | 88 | 89 | 90 | [struct] 91 | rename_fields = "None" 92 | # must_use = "MUST_USE_STRUCT" 93 | derive_constructor = false 94 | derive_eq = false 95 | derive_neq = false 96 | derive_lt = false 97 | derive_lte = false 98 | derive_gt = false 99 | derive_gte = false 100 | 101 | 102 | 103 | 104 | [enum] 105 | rename_variants = "None" 106 | # must_use = "MUST_USE_ENUM" 107 | add_sentinel = false 108 | prefix_with_name = false 109 | derive_helper_methods = false 110 | derive_const_casts = false 111 | derive_mut_casts = false 112 | # cast_assert_name = "ASSERT" 113 | derive_tagged_enum_destructor = false 114 | derive_tagged_enum_copy_constructor = false 115 | enum_class = true 116 | private_default_tagged_enum_constructor = false 117 | 118 | 119 | 120 | 121 | [const] 122 | allow_static_const = true 123 | allow_constexpr = false 124 | sort_by = "Name" 125 | 126 | 127 | 128 | 129 | [macro_expansion] 130 | bitflags = false 131 | 132 | 133 | 134 | 135 | 136 | 137 | ############## Options for How Your Rust library Should Be Parsed ############## 138 | 139 | [parse] 140 | parse_deps = true 141 | # include = [""] 142 | exclude = ["memchr"] 143 | clean = false 144 | extra_bindings = ["quickjs_gc", "quickjs_backtrace"] 145 | 146 | 147 | 148 | [parse.expand] 149 | crates = [] 150 | all_features = false 151 | default_features = true 152 | features = [] -------------------------------------------------------------------------------- /src/crates/quickjs/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "quickjs" 3 | version = "0.1.0" 4 | edition = "2021" 5 | build = "build.rs" 6 | 7 | [lib] 8 | name = "quickjs_rs" 9 | crate-type = ["staticlib"] 10 | 11 | [dependencies] 12 | 13 | quickjs_gc = { path = "../quickjs_gc" } 14 | quickjs_backtrace = { path = "../quickjs_backtrace" } -------------------------------------------------------------------------------- /src/crates/quickjs/build.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::path::PathBuf; 3 | use std::process::Command; 4 | use std::fs; 5 | 6 | fn main() { 7 | env::set_var("RUST_BACKTRACE", "1"); 8 | let current_dir = env::current_dir().unwrap(); 9 | let working_dir = current_dir.parent().unwrap(); 10 | 11 | let home_dir = env::var("HOME").expect("HOME environment variable not found."); 12 | let cbindgen_bin_path = PathBuf::from(&home_dir).join(".cargo/bin/cbindgen"); 13 | 14 | // Check if cbindgen is installed 15 | if !fs::metadata(&cbindgen_bin_path).is_ok() { 16 | panic!("cbindgen not installed, use `cargo install --force cbindgen` to install cbindgen first."); 17 | } 18 | 19 | let output = Command::new(cbindgen_bin_path) 20 | .current_dir(&working_dir) 21 | .arg("--config") 22 | .arg("cbindgen.toml") 23 | .arg("--crate") 24 | .arg("quickjs") 25 | .arg("--lang") 26 | .arg("c") 27 | .arg("--output") 28 | .arg("include/quickjs-rs.h") 29 | .output() 30 | .expect("Failed to execute command."); 31 | 32 | println!("{}", String::from_utf8_lossy(&output.stdout)); 33 | eprintln!("{}", String::from_utf8_lossy(&output.stderr)); 34 | } 35 | -------------------------------------------------------------------------------- /src/crates/quickjs/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub use quickjs_gc::{print_gc_objects, print_gc_object}; 2 | pub use quickjs_backtrace::{get_backtrace, free_backtrace_string}; -------------------------------------------------------------------------------- /src/crates/quickjs_backtrace/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "quickjs_backtrace" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | quickjs_common = { path = "../quickjs_common" } -------------------------------------------------------------------------------- /src/crates/quickjs_backtrace/src/lib.rs: -------------------------------------------------------------------------------- 1 | extern crate quickjs_common; 2 | 3 | use quickjs_common::backtrace::Backtrace; 4 | use quickjs_common::libc::c_char; 5 | use std::ffi::CString; 6 | 7 | /// Function that captures a backtrace and returns it as a C-compatible string. 8 | /// 9 | /// This function captures the current backtrace, formats it as a string, 10 | /// converts it to a C-compatible string (CString), and then returns the raw 11 | /// pointer to this string. 12 | /// 13 | /// # Returns 14 | /// 15 | /// * `*mut c_char`: Pointer to the backtrace string. This memory should be 16 | /// freed by `free_backtrace_string` when it's no longer needed. 17 | #[no_mangle] 18 | pub extern "C" fn get_backtrace() -> *mut c_char { 19 | let bt = Backtrace::new(); 20 | let trace_str = format!("{:?}", bt); 21 | 22 | // Convert the Rust String into a C string 23 | let c_string = CString::new(trace_str).unwrap(); 24 | 25 | // Return a pointer to the C string 26 | c_string.into_raw() 27 | } 28 | 29 | /// Function that frees a string returned by `get_backtrace`. 30 | /// 31 | /// This function takes a pointer to a C-compatible string, reconstitutes the 32 | /// CString, and then drops it, which deallocates the memory. It's crucial to 33 | /// call this function to avoid a memory leak. 34 | /// 35 | /// # Parameters 36 | /// 37 | /// * `ptr: *mut c_char`: Pointer to the string to free. If this pointer is null, 38 | /// the function does nothing. 39 | #[no_mangle] 40 | pub extern "C" fn free_backtrace_string(ptr: *mut c_char) { 41 | unsafe { 42 | if ptr.is_null() { 43 | return; 44 | } 45 | drop(CString::from_raw(ptr)) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/crates/quickjs_common/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "quickjs_common" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | backtrace = "0.3.67" 10 | libc = "0.2.146" -------------------------------------------------------------------------------- /src/crates/quickjs_common/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub use libc; 2 | pub use backtrace; -------------------------------------------------------------------------------- /src/crates/quickjs_gc/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "quickjs_gc" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | quickjs_common = { path = "../quickjs_common" } -------------------------------------------------------------------------------- /src/crates/quickjs_gc/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![feature(offset_of)] 2 | 3 | mod record; 4 | 5 | use std::mem::offset_of; 6 | use crate::record::{get_gc_object_backtrace_map}; 7 | use quickjs_common::backtrace::Backtrace; 8 | 9 | /// Represents a node in a doubly linked list. 10 | /// Used to keep track of garbage-collected objects. 11 | #[repr(C)] 12 | pub struct ListHead { 13 | prev: *mut ListHead, 14 | next: *mut ListHead, 15 | } 16 | 17 | /// Represents the type of a garbage-collected object. 18 | #[repr(C)] 19 | pub enum JSGCObjectTypeEnum { 20 | JsObject = 1, 21 | FunctionBytecode, 22 | Shape, 23 | VarRef, 24 | AsyncFunction, 25 | JsContext, 26 | Unknown, 27 | } 28 | 29 | /// Header for garbage-collected objects. 30 | /// These objects are C data structures with a reference count that can reference other GC objects. 31 | #[repr(C)] 32 | pub struct JSGCObjectHeader { 33 | ref_count: i32, 34 | gc_obj_mark: u8, 35 | dummy1: u8, 36 | dummy2: u16, 37 | link: ListHead, 38 | } 39 | 40 | impl ListHead { 41 | fn next(&mut self) -> &mut Self { 42 | unsafe { &mut *self.next } 43 | } 44 | } 45 | 46 | impl JSGCObjectHeader { 47 | /// Returns the GC object type as an enum value. 48 | fn gc_obj_type(&self) -> JSGCObjectTypeEnum { 49 | match self.gc_obj_mark & 0x0F { 50 | 0 => JSGCObjectTypeEnum::JsObject, 51 | 1 => JSGCObjectTypeEnum::FunctionBytecode, 52 | 2 => JSGCObjectTypeEnum::Shape, 53 | 3 => JSGCObjectTypeEnum::VarRef, 54 | 4 => JSGCObjectTypeEnum::AsyncFunction, 55 | 5 => JSGCObjectTypeEnum::JsContext, 56 | _ => JSGCObjectTypeEnum::Unknown, 57 | } 58 | } 59 | 60 | /// Returns the mark value from the GC object mark. 61 | pub fn mark(&self) -> u8 { 62 | (self.gc_obj_mark & 0xF0) >> 4 63 | } 64 | 65 | /// Prints the GC object details in a formatted output. 66 | pub fn print(&self) { 67 | let gc_obj_type_name = get_gc_obj_type_name(&self.gc_obj_type()); 68 | println!( 69 | "{:?} {:<10} {:<20} {:<10} {:<10} {:<10}", 70 | self as *const _, 71 | self.ref_count, 72 | gc_obj_type_name, 73 | self.mark(), 74 | self.dummy1, 75 | self.dummy2 76 | ); 77 | } 78 | 79 | /// Prints the GC object details in a formatted output, along with its backtrace if provided. 80 | pub fn print_with_backtrace(&self, bt: Option<&Backtrace>) { 81 | let gc_obj_type_name = get_gc_obj_type_name(&self.gc_obj_type()); 82 | println!( 83 | "{:?} {:<10} {:<20} {:<10} {:<10} {:<10} {:<30}", 84 | self as *const _, 85 | self.ref_count, 86 | gc_obj_type_name, 87 | self.mark(), 88 | self.dummy1, 89 | self.dummy2, 90 | bt.map_or("N/A".to_string(), |b| format!("{:?}", b)), 91 | ); 92 | } 93 | } 94 | 95 | /// Function that prints a GC object 96 | /// 97 | /// # Safety 98 | /// 99 | /// This function is `unsafe` because it dereferences a raw pointer. The caller 100 | /// must ensure that the `gc_object` pointer points to a valid 101 | /// `JSGCObjectHeader` object. Calling this function with an invalid pointer 102 | /// leads to undefined behavior. 103 | #[no_mangle] 104 | pub unsafe extern "C" fn print_gc_object(gc_object: *mut JSGCObjectHeader) { 105 | // Ensure the pointer is not null 106 | if !gc_object.is_null() { 107 | // Dereference the pointer and print the object 108 | (*gc_object).print(); 109 | } 110 | } 111 | 112 | /// Prints all GC objects in the list. 113 | /// 114 | /// # Safety 115 | /// 116 | /// This function is unsafe because it dereferences raw pointers. The caller 117 | /// must ensure that `list_head` is a valid pointer to a `ListHead` object, 118 | /// and that the list of GC objects is properly initialized. 119 | #[no_mangle] 120 | pub unsafe extern "C" fn print_gc_objects(list_head: *mut ListHead) { 121 | let mut cur_node = (*list_head).next(); 122 | let map = get_gc_object_backtrace_map().lock().unwrap(); 123 | let mut with_backtrace = 0; 124 | let mut without_backtrace = 0; 125 | 126 | println!( 127 | "{:<10} {:<10} {:<20} {:<10} {:<10} {:<10} {:<30}", 128 | "Node", "RefCount", "GC_Obj_Type", "Mark", "Dummy1", "Dummy2", "Backtrace" 129 | ); 130 | 131 | let mut index: i32 = 0; 132 | while cur_node as *const _ != list_head { 133 | index += 1; 134 | let gc_object = (cur_node as *mut ListHead as *mut u8) 135 | .offset(-(offset_of!(JSGCObjectHeader, link) as isize)) 136 | as *mut JSGCObjectHeader; 137 | 138 | match map.get(&(gc_object as *const _)) { 139 | Some(bt) => { 140 | (*gc_object).print_with_backtrace(Some(bt)); 141 | with_backtrace += 1; 142 | } 143 | None => { 144 | (*gc_object).print_with_backtrace(None); 145 | without_backtrace += 1; 146 | } 147 | } 148 | cur_node = (*cur_node).next(); 149 | } 150 | 151 | println!("\nTotal Nodes: {}", index); 152 | println!("Total with backtrace: {}", with_backtrace); 153 | println!("Total without backtrace: {}", without_backtrace); 154 | println!("Total GC-tracked Objects With Backtrace: {}", map.len()); 155 | } 156 | 157 | /// Returns a string representation of the given GC object type. 158 | fn get_gc_obj_type_name(gc_obj_type: &JSGCObjectTypeEnum) -> String { 159 | match gc_obj_type { 160 | JSGCObjectTypeEnum::JsObject => "JS_OBJECT".to_string(), 161 | JSGCObjectTypeEnum::FunctionBytecode => "FUNCTION_BYTECODE".to_string(), 162 | JSGCObjectTypeEnum::Shape => "SHAPE".to_string(), 163 | JSGCObjectTypeEnum::VarRef => "VAR_REF".to_string(), 164 | JSGCObjectTypeEnum::AsyncFunction => "ASYNC_FUNCTION".to_string(), 165 | JSGCObjectTypeEnum::JsContext => "JS_CONTEXT".to_string(), 166 | _ => "UNKNOWN".to_string(), 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /src/crates/quickjs_gc/src/record.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | use std::mem::offset_of; 3 | use std::sync::{Mutex, Once}; 4 | use quickjs_common::backtrace::Backtrace; 5 | use crate::{JSGCObjectHeader, ListHead}; 6 | 7 | /// Define a global static Once variable and a static mutable option of the Mutexed HashMap 8 | static INIT: Once = Once::new(); 9 | static mut GC_OBJECTS: Option>> = None; 10 | 11 | /// Function to safely initialize and get a reference to the global 12 | /// HashMap storing garbage-collected objects and their backtraces. 13 | pub fn get_gc_object_backtrace_map() -> &'static Mutex> { 14 | unsafe { 15 | INIT.call_once(|| { 16 | GC_OBJECTS = Some(Mutex::new(HashMap::new())); 17 | }); 18 | GC_OBJECTS.as_ref().unwrap() 19 | } 20 | } 21 | 22 | /// This function records the creation of a garbage-collected object. 23 | /// It takes a raw pointer to the object and stores it along with a 24 | /// backtrace in a global HashMap. 25 | #[no_mangle] 26 | pub unsafe extern "C" fn record_gc_object_creation(gc_object_link: *mut ListHead) { 27 | // Convert the pointer to the 'link' field back to a pointer to the encompassing struct 28 | let gc_object = (gc_object_link as *mut u8) 29 | .offset(-(offset_of!(JSGCObjectHeader, link) as isize)) 30 | as *mut JSGCObjectHeader; 31 | 32 | let bt = Backtrace::new(); 33 | get_gc_object_backtrace_map().lock().unwrap().insert(gc_object, bt); 34 | } 35 | -------------------------------------------------------------------------------- /tests/bjson.c: -------------------------------------------------------------------------------- 1 | /* 2 | * QuickJS: binary JSON module (test only) 3 | * 4 | * Copyright (c) 2017-2019 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 | #include "../quickjs-libc.h" 25 | #include "../cutils.h" 26 | 27 | static JSValue js_bjson_read(JSContext *ctx, JSValueConst this_val, 28 | int argc, JSValueConst *argv) 29 | { 30 | uint8_t *buf; 31 | uint64_t pos, len; 32 | JSValue obj; 33 | size_t size; 34 | int flags; 35 | 36 | if (JS_ToIndex(ctx, &pos, argv[1])) 37 | return JS_EXCEPTION; 38 | if (JS_ToIndex(ctx, &len, argv[2])) 39 | return JS_EXCEPTION; 40 | buf = JS_GetArrayBuffer(ctx, &size, argv[0]); 41 | if (!buf) 42 | return JS_EXCEPTION; 43 | if (pos + len > size) 44 | return JS_ThrowRangeError(ctx, "array buffer overflow"); 45 | flags = 0; 46 | if (JS_ToBool(ctx, argv[3])) 47 | flags |= JS_READ_OBJ_REFERENCE; 48 | obj = JS_ReadObject(ctx, buf + pos, len, flags); 49 | return obj; 50 | } 51 | 52 | static JSValue js_bjson_write(JSContext *ctx, JSValueConst this_val, 53 | int argc, JSValueConst *argv) 54 | { 55 | size_t len; 56 | uint8_t *buf; 57 | JSValue array; 58 | int flags; 59 | 60 | flags = 0; 61 | if (JS_ToBool(ctx, argv[1])) 62 | flags |= JS_WRITE_OBJ_REFERENCE; 63 | buf = JS_WriteObject(ctx, &len, argv[0], flags); 64 | if (!buf) 65 | return JS_EXCEPTION; 66 | array = JS_NewArrayBufferCopy(ctx, buf, len); 67 | js_free(ctx, buf); 68 | return array; 69 | } 70 | 71 | static const JSCFunctionListEntry js_bjson_funcs[] = { 72 | JS_CFUNC_DEF("read", 4, js_bjson_read ), 73 | JS_CFUNC_DEF("write", 2, js_bjson_write ), 74 | }; 75 | 76 | static int js_bjson_init(JSContext *ctx, JSModuleDef *m) 77 | { 78 | return JS_SetModuleExportList(ctx, m, js_bjson_funcs, 79 | countof(js_bjson_funcs)); 80 | } 81 | 82 | #ifdef JS_SHARED_LIBRARY 83 | #define JS_INIT_MODULE js_init_module 84 | #else 85 | #define JS_INIT_MODULE js_init_module_bjson 86 | #endif 87 | 88 | JSModuleDef *JS_INIT_MODULE(JSContext *ctx, const char *module_name) 89 | { 90 | JSModuleDef *m; 91 | m = JS_NewCModule(ctx, module_name, js_bjson_init); 92 | if (!m) 93 | return NULL; 94 | JS_AddModuleExportList(ctx, m, js_bjson_funcs, countof(js_bjson_funcs)); 95 | return m; 96 | } 97 | -------------------------------------------------------------------------------- /tests/test262.conf: -------------------------------------------------------------------------------- 1 | [config] 2 | # general settings for test262 ES6 version 3 | 4 | # framework style: old, new 5 | style=new 6 | 7 | # handle tests tagged as [noStrict]: yes, no, skip 8 | nostrict=yes 9 | 10 | # handle tests tagged as [strictOnly]: yes, no, skip 11 | strict=yes 12 | 13 | # test mode: default, default-nostrict, default-strict, strict, nostrict, both, all 14 | mode=default 15 | 16 | # handle tests flagged as [async]: yes, no, skip 17 | # for these, load 'harness/doneprintHandle.js' prior to test 18 | # and expect `print('Test262:AsyncTestComplete')` to be called for 19 | # successful termination 20 | async=yes 21 | 22 | # handle tests flagged as [module]: yes, no, skip 23 | module=yes 24 | 25 | # output error messages: yes, no 26 | verbose=yes 27 | 28 | # load harness files from this directory 29 | harnessdir=../test262/harness 30 | 31 | # names of harness include files to skip 32 | #harnessexclude= 33 | 34 | # name of the error file for known errors 35 | errorfile=../test262_errors.txt 36 | 37 | # exclude tests enumerated in this file (see also [exclude] section) 38 | #excludefile=test262_exclude.txt 39 | 40 | # report test results to this file 41 | reportfile=../test262_report.txt 42 | 43 | # enumerate tests from this directory 44 | testdir=../test262/test 45 | 46 | [features] 47 | # Standard language features and proposed extensions 48 | # list the features that are included 49 | # skipped features are tagged as such to avoid warnings 50 | 51 | AggregateError 52 | align-detached-buffer-semantics-with-web-reality 53 | arbitrary-module-namespace-names=skip 54 | array-find-from-last=skip 55 | Array.prototype.at=skip 56 | Array.prototype.flat 57 | Array.prototype.flatMap 58 | Array.prototype.flatten 59 | Array.prototype.values 60 | ArrayBuffer 61 | arrow-function 62 | async-functions 63 | async-iteration 64 | Atomics=skip 65 | Atomics.waitAsync=skip 66 | BigInt 67 | caller 68 | class 69 | class-fields-private 70 | class-fields-private-in=skip 71 | class-fields-public 72 | class-methods-private 73 | class-static-block=skip 74 | class-static-fields-public 75 | class-static-fields-private 76 | class-static-methods-private 77 | cleanupSome=skip 78 | coalesce-expression 79 | computed-property-names 80 | const 81 | cross-realm 82 | DataView 83 | DataView.prototype.getFloat32 84 | DataView.prototype.getFloat64 85 | DataView.prototype.getInt16 86 | DataView.prototype.getInt32 87 | DataView.prototype.getInt8 88 | DataView.prototype.getUint16 89 | DataView.prototype.getUint32 90 | DataView.prototype.setUint8 91 | default-parameters 92 | destructuring-assignment 93 | destructuring-binding 94 | dynamic-import 95 | error-cause=skip 96 | export-star-as-namespace-from-module 97 | FinalizationGroup=skip 98 | FinalizationRegistry=skip 99 | FinalizationRegistry.prototype.cleanupSome=skip 100 | Float32Array 101 | Float64Array 102 | for-in-order 103 | for-of 104 | generators 105 | globalThis 106 | hashbang 107 | host-gc-required=skip 108 | import.meta 109 | import-assertions=skip 110 | Int16Array 111 | Int32Array 112 | Int8Array 113 | IsHTMLDDA 114 | json-modules=skip 115 | json-superset 116 | legacy-regexp=skip 117 | let 118 | logical-assignment-operators 119 | Map 120 | new.target 121 | numeric-separator-literal 122 | object-rest 123 | object-spread 124 | Object.fromEntries 125 | Object.hasOwn 126 | Object.is 127 | optional-catch-binding 128 | optional-chaining 129 | Promise 130 | Promise.allSettled 131 | Promise.any 132 | Promise.prototype.finally 133 | Proxy 134 | proxy-missing-checks 135 | Reflect 136 | Reflect.construct 137 | Reflect.set 138 | Reflect.setPrototypeOf 139 | regexp-dotall 140 | regexp-lookbehind 141 | regexp-match-indices=skip 142 | regexp-named-groups 143 | regexp-unicode-property-escapes 144 | resizable-arraybuffer=skip 145 | rest-parameters 146 | Set 147 | ShadowRealm=skip 148 | SharedArrayBuffer 149 | string-trimming 150 | String.fromCodePoint 151 | String.prototype.endsWith 152 | String.prototype.includes 153 | String.prototype.at=skip 154 | String.prototype.matchAll 155 | String.prototype.replaceAll 156 | String.prototype.trimEnd 157 | String.prototype.trimStart 158 | super 159 | Symbol 160 | Symbol.asyncIterator 161 | Symbol.hasInstance 162 | Symbol.isConcatSpreadable 163 | Symbol.iterator 164 | Symbol.match 165 | Symbol.matchAll 166 | Symbol.prototype.description 167 | Symbol.replace 168 | Symbol.search 169 | Symbol.species 170 | Symbol.split 171 | Symbol.toPrimitive 172 | Symbol.toStringTag 173 | Symbol.unscopables 174 | tail-call-optimization=skip 175 | template 176 | Temporal=skip 177 | top-level-await=skip 178 | TypedArray 179 | TypedArray.prototype.at=skip 180 | u180e 181 | Uint16Array 182 | Uint32Array 183 | Uint8Array 184 | Uint8ClampedArray 185 | WeakMap 186 | WeakRef=skip 187 | WeakSet 188 | well-formed-json-stringify 189 | __getter__ 190 | __proto__ 191 | __setter__ 192 | 193 | [exclude] 194 | # list excluded tests and directories here 195 | 196 | # intl not supported 197 | test262/test/intl402/ 198 | 199 | # incompatible with the "caller" feature 200 | test262/test/built-ins/Function/prototype/restricted-property-caller.js 201 | test262/test/built-ins/Function/prototype/restricted-property-arguments.js 202 | test262/test/built-ins/ThrowTypeError/unique-per-realm-function-proto.js 203 | 204 | # slow tests 205 | #test262/test/built-ins/RegExp/CharacterClassEscapes/ 206 | #test262/test/built-ins/RegExp/property-escapes/ 207 | 208 | [tests] 209 | # list test files or use config.testdir -------------------------------------------------------------------------------- /tests/test262.patch: -------------------------------------------------------------------------------- 1 | diff --git a/harness/atomicsHelper.js b/harness/atomicsHelper.js 2 | index 9c1217351e..3c24755558 100644 3 | --- a/harness/atomicsHelper.js 4 | +++ b/harness/atomicsHelper.js 5 | @@ -227,10 +227,14 @@ $262.agent.waitUntil = function(typedArray, index, expected) { 6 | * } 7 | */ 8 | $262.agent.timeouts = { 9 | - yield: 100, 10 | - small: 200, 11 | - long: 1000, 12 | - huge: 10000, 13 | +// yield: 100, 14 | +// small: 200, 15 | +// long: 1000, 16 | +// huge: 10000, 17 | + yield: 20, 18 | + small: 20, 19 | + long: 100, 20 | + huge: 1000, 21 | }; 22 | 23 | /** 24 | diff --git a/harness/regExpUtils.js b/harness/regExpUtils.js 25 | index be7039fda0..7b38abf8df 100644 26 | --- a/harness/regExpUtils.js 27 | +++ b/harness/regExpUtils.js 28 | @@ -6,24 +6,27 @@ description: | 29 | defines: [buildString, testPropertyEscapes, matchValidator] 30 | ---*/ 31 | 32 | +if ($262 && typeof $262.codePointRange === "function") { 33 | + /* use C function to build the codePointRange (much faster with 34 | + slow JS engines) */ 35 | + codePointRange = $262.codePointRange; 36 | +} else { 37 | + codePointRange = function codePointRange(start, end) { 38 | + const codePoints = []; 39 | + let length = 0; 40 | + for (codePoint = start; codePoint < end; codePoint++) { 41 | + codePoints[length++] = codePoint; 42 | + } 43 | + return String.fromCodePoint.apply(null, codePoints); 44 | + } 45 | +} 46 | + 47 | function buildString({ loneCodePoints, ranges }) { 48 | - const CHUNK_SIZE = 10000; 49 | - let result = Reflect.apply(String.fromCodePoint, null, loneCodePoints); 50 | - for (let i = 0; i < ranges.length; i++) { 51 | - const range = ranges[i]; 52 | - const start = range[0]; 53 | - const end = range[1]; 54 | - const codePoints = []; 55 | - for (let length = 0, codePoint = start; codePoint <= end; codePoint++) { 56 | - codePoints[length++] = codePoint; 57 | - if (length === CHUNK_SIZE) { 58 | - result += Reflect.apply(String.fromCodePoint, null, codePoints); 59 | - codePoints.length = length = 0; 60 | - } 61 | + let result = String.fromCodePoint.apply(null, loneCodePoints); 62 | + for (const [start, end] of ranges) { 63 | + result += codePointRange(start, end + 1); 64 | } 65 | - result += Reflect.apply(String.fromCodePoint, null, codePoints); 66 | - } 67 | - return result; 68 | + return result; 69 | } 70 | 71 | function testPropertyEscapes(regex, string, expression) { 72 | -------------------------------------------------------------------------------- /tests/test_bjson.js: -------------------------------------------------------------------------------- 1 | import * as bjson from "./bjson.so"; 2 | 3 | function assert(actual, expected, message) { 4 | if (arguments.length == 1) 5 | expected = true; 6 | 7 | if (actual === expected) 8 | return; 9 | 10 | if (actual !== null && expected !== null 11 | && typeof actual == 'object' && typeof expected == 'object' 12 | && actual.toString() === expected.toString()) 13 | return; 14 | 15 | throw Error("assertion failed: got |" + actual + "|" + 16 | ", expected |" + expected + "|" + 17 | (message ? " (" + message + ")" : "")); 18 | } 19 | 20 | function toHex(a) 21 | { 22 | var i, s = "", tab, v; 23 | tab = new Uint8Array(a); 24 | for(i = 0; i < tab.length; i++) { 25 | v = tab[i].toString(16); 26 | if (v.length < 2) 27 | v = "0" + v; 28 | if (i !== 0) 29 | s += " "; 30 | s += v; 31 | } 32 | return s; 33 | } 34 | 35 | function isArrayLike(a) 36 | { 37 | return Array.isArray(a) || 38 | (a instanceof Uint8ClampedArray) || 39 | (a instanceof Uint8Array) || 40 | (a instanceof Uint16Array) || 41 | (a instanceof Uint32Array) || 42 | (a instanceof Int8Array) || 43 | (a instanceof Int16Array) || 44 | (a instanceof Int32Array) || 45 | (a instanceof Float32Array) || 46 | (a instanceof Float64Array); 47 | } 48 | 49 | function toStr(a) 50 | { 51 | var s, i, props, prop; 52 | 53 | switch(typeof(a)) { 54 | case "object": 55 | if (a === null) 56 | return "null"; 57 | if (a instanceof Date) { 58 | s = "Date(" + toStr(a.valueOf()) + ")"; 59 | } else if (a instanceof Number) { 60 | s = "Number(" + toStr(a.valueOf()) + ")"; 61 | } else if (a instanceof String) { 62 | s = "String(" + toStr(a.valueOf()) + ")"; 63 | } else if (a instanceof Boolean) { 64 | s = "Boolean(" + toStr(a.valueOf()) + ")"; 65 | } else if (isArrayLike(a)) { 66 | s = "["; 67 | for(i = 0; i < a.length; i++) { 68 | if (i != 0) 69 | s += ","; 70 | s += toStr(a[i]); 71 | } 72 | s += "]"; 73 | } else { 74 | props = Object.keys(a); 75 | s = "{"; 76 | for(i = 0; i < props.length; i++) { 77 | if (i != 0) 78 | s += ","; 79 | prop = props[i]; 80 | s += prop + ":" + toStr(a[prop]); 81 | } 82 | s += "}"; 83 | } 84 | return s; 85 | case "undefined": 86 | return "undefined"; 87 | case "string": 88 | return a.__quote(); 89 | case "number": 90 | case "bigfloat": 91 | if (a == 0 && 1 / a < 0) 92 | return "-0"; 93 | else 94 | return a.toString(); 95 | break; 96 | default: 97 | return a.toString(); 98 | } 99 | } 100 | 101 | function bjson_test(a) 102 | { 103 | var buf, r, a_str, r_str; 104 | a_str = toStr(a); 105 | buf = bjson.write(a); 106 | if (0) { 107 | print(a_str, "->", toHex(buf)); 108 | } 109 | r = bjson.read(buf, 0, buf.byteLength); 110 | r_str = toStr(r); 111 | if (a_str != r_str) { 112 | print(a_str); 113 | print(r_str); 114 | assert(false); 115 | } 116 | } 117 | 118 | /* test multiple references to an object including circular 119 | references */ 120 | function bjson_test_reference() 121 | { 122 | var array, buf, i, n, array_buffer; 123 | n = 16; 124 | array = []; 125 | for(i = 0; i < n; i++) 126 | array[i] = {}; 127 | array_buffer = new ArrayBuffer(n); 128 | for(i = 0; i < n; i++) { 129 | array[i].next = array[(i + 1) % n]; 130 | array[i].idx = i; 131 | array[i].typed_array = new Uint8Array(array_buffer, i, 1); 132 | } 133 | buf = bjson.write(array, true); 134 | 135 | array = bjson.read(buf, 0, buf.byteLength, true); 136 | 137 | /* check the result */ 138 | for(i = 0; i < n; i++) { 139 | assert(array[i].next, array[(i + 1) % n]); 140 | assert(array[i].idx, i); 141 | assert(array[i].typed_array.buffer, array_buffer); 142 | assert(array[i].typed_array.length, 1); 143 | assert(array[i].typed_array.byteOffset, i); 144 | } 145 | } 146 | 147 | function bjson_test_all() 148 | { 149 | var obj; 150 | 151 | bjson_test({x:1, y:2, if:3}); 152 | bjson_test([1, 2, 3]); 153 | bjson_test([1.0, "aa", true, false, undefined, null, NaN, -Infinity, -0.0]); 154 | if (typeof BigInt !== "undefined") { 155 | bjson_test([BigInt("1"), -BigInt("0x123456789"), 156 | BigInt("0x123456789abcdef123456789abcdef")]); 157 | } 158 | if (typeof BigFloat !== "undefined") { 159 | BigFloatEnv.setPrec(function () { 160 | bjson_test([BigFloat("0.1"), BigFloat("-1e30"), BigFloat("0"), 161 | BigFloat("-0"), BigFloat("Infinity"), BigFloat("-Infinity"), 162 | 0.0 / BigFloat("0"), BigFloat.MAX_VALUE, 163 | BigFloat.MIN_VALUE]); 164 | }, 113, 15); 165 | } 166 | if (typeof BigDecimal !== "undefined") { 167 | bjson_test([BigDecimal("0"), 168 | BigDecimal("0.8"), BigDecimal("123321312321321e100"), 169 | BigDecimal("-1233213123213214332333223332e100"), 170 | BigDecimal("1.233e-1000")]); 171 | } 172 | 173 | bjson_test([new Date(1234), new String("abc"), new Number(-12.1), new Boolean(true)]); 174 | 175 | bjson_test(new Int32Array([123123, 222111, -32222])); 176 | bjson_test(new Float64Array([123123, 222111.5])); 177 | 178 | /* tested with a circular reference */ 179 | obj = {}; 180 | obj.x = obj; 181 | try { 182 | bjson.write(obj); 183 | assert(false); 184 | } catch(e) { 185 | assert(e instanceof TypeError); 186 | } 187 | 188 | bjson_test_reference(); 189 | } 190 | 191 | bjson_test_all(); 192 | -------------------------------------------------------------------------------- /tests/test_closure.js: -------------------------------------------------------------------------------- 1 | function assert(actual, expected, message) { 2 | if (arguments.length == 1) 3 | expected = true; 4 | 5 | if (actual === expected) 6 | return; 7 | 8 | if (actual !== null && expected !== null 9 | && typeof actual == 'object' && typeof expected == 'object' 10 | && actual.toString() === expected.toString()) 11 | return; 12 | 13 | throw Error("assertion failed: got |" + actual + "|" + 14 | ", expected |" + expected + "|" + 15 | (message ? " (" + message + ")" : "")); 16 | } 17 | 18 | // load more elaborate version of assert if available 19 | try { __loadScript("test_assert.js"); } catch(e) {} 20 | 21 | /*----------------*/ 22 | 23 | var log_str = ""; 24 | 25 | function log(str) 26 | { 27 | log_str += str + ","; 28 | } 29 | 30 | function f(a, b, c) 31 | { 32 | var x = 10; 33 | log("a="+a); 34 | function g(d) { 35 | function h() { 36 | log("d=" + d); 37 | log("x=" + x); 38 | } 39 | log("b=" + b); 40 | log("c=" + c); 41 | h(); 42 | } 43 | g(4); 44 | return g; 45 | } 46 | 47 | var g1 = f(1, 2, 3); 48 | g1(5); 49 | 50 | assert(log_str, "a=1,b=2,c=3,d=4,x=10,b=2,c=3,d=5,x=10,", "closure1"); 51 | 52 | function test_closure1() 53 | { 54 | function f2() 55 | { 56 | var val = 1; 57 | 58 | function set(a) { 59 | val = a; 60 | } 61 | function get(a) { 62 | return val; 63 | } 64 | return { "set": set, "get": get }; 65 | } 66 | 67 | var obj = f2(); 68 | obj.set(10); 69 | var r; 70 | r = obj.get(); 71 | assert(r, 10, "closure2"); 72 | } 73 | 74 | function test_closure2() 75 | { 76 | var expr_func = function myfunc1(n) { 77 | function myfunc2(n) { 78 | return myfunc1(n - 1); 79 | } 80 | if (n == 0) 81 | return 0; 82 | else 83 | return myfunc2(n); 84 | }; 85 | var r; 86 | r = expr_func(1); 87 | assert(r, 0, "expr_func"); 88 | } 89 | 90 | function test_closure3() 91 | { 92 | function fib(n) 93 | { 94 | if (n <= 0) 95 | return 0; 96 | else if (n == 1) 97 | return 1; 98 | else 99 | return fib(n - 1) + fib(n - 2); 100 | } 101 | 102 | var fib_func = function fib1(n) 103 | { 104 | if (n <= 0) 105 | return 0; 106 | else if (n == 1) 107 | return 1; 108 | else 109 | return fib1(n - 1) + fib1(n - 2); 110 | }; 111 | 112 | assert(fib(6), 8, "fib"); 113 | assert(fib_func(6), 8, "fib_func"); 114 | } 115 | 116 | function test_arrow_function() 117 | { 118 | "use strict"; 119 | 120 | function f1() { 121 | return (() => arguments)(); 122 | } 123 | function f2() { 124 | return (() => this)(); 125 | } 126 | function f3() { 127 | return (() => eval("this"))(); 128 | } 129 | function f4() { 130 | return (() => eval("new.target"))(); 131 | } 132 | var a; 133 | 134 | a = f1(1, 2); 135 | assert(a.length, 2); 136 | assert(a[0] === 1 && a[1] === 2); 137 | 138 | assert(f2.call("this_val") === "this_val"); 139 | assert(f3.call("this_val") === "this_val"); 140 | assert(new f4() === f4); 141 | 142 | var o1 = { f() { return this; } }; 143 | var o2 = { f() { 144 | return (() => eval("super.f()"))(); 145 | } }; 146 | o2.__proto__ = o1; 147 | 148 | assert(o2.f() === o2); 149 | } 150 | 151 | function test_with() 152 | { 153 | var o1 = { x: "o1", y: "o1" }; 154 | var x = "local"; 155 | eval('var z="var_obj";'); 156 | assert(z === "var_obj"); 157 | with (o1) { 158 | assert(x === "o1"); 159 | assert(eval("x") === "o1"); 160 | var f = function () { 161 | o2 = { x: "o2" }; 162 | with (o2) { 163 | assert(x === "o2"); 164 | assert(y === "o1"); 165 | assert(z === "var_obj"); 166 | assert(eval("x") === "o2"); 167 | assert(eval("y") === "o1"); 168 | assert(eval("z") === "var_obj"); 169 | assert(eval('eval("x")') === "o2"); 170 | } 171 | }; 172 | f(); 173 | } 174 | } 175 | 176 | function test_eval_closure() 177 | { 178 | var tab; 179 | 180 | tab = []; 181 | for(let i = 0; i < 3; i++) { 182 | eval("tab.push(function g1() { return i; })"); 183 | } 184 | for(let i = 0; i < 3; i++) { 185 | assert(tab[i]() === i); 186 | } 187 | 188 | tab = []; 189 | for(let i = 0; i < 3; i++) { 190 | let f = function f() { 191 | eval("tab.push(function g2() { return i; })"); 192 | }; 193 | f(); 194 | } 195 | for(let i = 0; i < 3; i++) { 196 | assert(tab[i]() === i); 197 | } 198 | } 199 | 200 | function test_eval_const() 201 | { 202 | const a = 1; 203 | var success = false; 204 | var f = function () { 205 | eval("a = 1"); 206 | }; 207 | try { 208 | f(); 209 | } catch(e) { 210 | success = (e instanceof TypeError); 211 | } 212 | assert(success); 213 | } 214 | 215 | test_closure1(); 216 | test_closure2(); 217 | test_closure3(); 218 | test_arrow_function(); 219 | test_with(); 220 | test_eval_closure(); 221 | test_eval_const(); 222 | -------------------------------------------------------------------------------- /tests/test_op_overloading.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function assert(actual, expected, message) { 4 | if (arguments.length == 1) 5 | expected = true; 6 | 7 | if (actual === expected) 8 | return; 9 | 10 | if (actual !== null && expected !== null 11 | && typeof actual == 'object' && typeof expected == 'object' 12 | && actual.toString() === expected.toString()) 13 | return; 14 | 15 | throw Error("assertion failed: got |" + actual + "|" + 16 | ", expected |" + expected + "|" + 17 | (message ? " (" + message + ")" : "")); 18 | } 19 | 20 | /* operators overloading with Operators.create() */ 21 | function test_operators_create() { 22 | class Vec2 23 | { 24 | constructor(x, y) { 25 | this.x = x; 26 | this.y = y; 27 | } 28 | static mul_scalar(p1, a) { 29 | var r = new Vec2(); 30 | r.x = p1.x * a; 31 | r.y = p1.y * a; 32 | return r; 33 | } 34 | toString() { 35 | return "Vec2(" + this.x + "," + this.y + ")"; 36 | } 37 | } 38 | 39 | Vec2.prototype[Symbol.operatorSet] = Operators.create( 40 | { 41 | "+"(p1, p2) { 42 | var r = new Vec2(); 43 | r.x = p1.x + p2.x; 44 | r.y = p1.y + p2.y; 45 | return r; 46 | }, 47 | "-"(p1, p2) { 48 | var r = new Vec2(); 49 | r.x = p1.x - p2.x; 50 | r.y = p1.y - p2.y; 51 | return r; 52 | }, 53 | "=="(a, b) { 54 | return a.x == b.x && a.y == b.y; 55 | }, 56 | "<"(a, b) { 57 | var r; 58 | /* lexicographic order */ 59 | if (a.x == b.x) 60 | r = (a.y < b.y); 61 | else 62 | r = (a.x < b.x); 63 | return r; 64 | }, 65 | "++"(a) { 66 | var r = new Vec2(); 67 | r.x = a.x + 1; 68 | r.y = a.y + 1; 69 | return r; 70 | } 71 | }, 72 | { 73 | left: Number, 74 | "*"(a, b) { 75 | return Vec2.mul_scalar(b, a); 76 | } 77 | }, 78 | { 79 | right: Number, 80 | "*"(a, b) { 81 | return Vec2.mul_scalar(a, b); 82 | } 83 | }); 84 | 85 | var a = new Vec2(1, 2); 86 | var b = new Vec2(3, 4); 87 | var r; 88 | 89 | r = a * 2 + 3 * b; 90 | assert(r.x === 11 && r.y === 16); 91 | assert(a == a, true); 92 | assert(a == b, false); 93 | assert(a != a, false); 94 | assert(a < b, true); 95 | assert(a <= b, true); 96 | assert(b < a, false); 97 | assert(b <= a, false); 98 | assert(a <= a, true); 99 | assert(a >= a, true); 100 | a++; 101 | assert(a.x === 2 && a.y === 3); 102 | r = ++a; 103 | assert(a.x === 3 && a.y === 4); 104 | assert(r === a); 105 | } 106 | 107 | /* operators overloading thru inheritance */ 108 | function test_operators() 109 | { 110 | var Vec2; 111 | 112 | function mul_scalar(p1, a) { 113 | var r = new Vec2(); 114 | r.x = p1.x * a; 115 | r.y = p1.y * a; 116 | return r; 117 | } 118 | 119 | var vec2_ops = Operators({ 120 | "+"(p1, p2) { 121 | var r = new Vec2(); 122 | r.x = p1.x + p2.x; 123 | r.y = p1.y + p2.y; 124 | return r; 125 | }, 126 | "-"(p1, p2) { 127 | var r = new Vec2(); 128 | r.x = p1.x - p2.x; 129 | r.y = p1.y - p2.y; 130 | return r; 131 | }, 132 | "=="(a, b) { 133 | return a.x == b.x && a.y == b.y; 134 | }, 135 | "<"(a, b) { 136 | var r; 137 | /* lexicographic order */ 138 | if (a.x == b.x) 139 | r = (a.y < b.y); 140 | else 141 | r = (a.x < b.x); 142 | return r; 143 | }, 144 | "++"(a) { 145 | var r = new Vec2(); 146 | r.x = a.x + 1; 147 | r.y = a.y + 1; 148 | return r; 149 | } 150 | }, 151 | { 152 | left: Number, 153 | "*"(a, b) { 154 | return mul_scalar(b, a); 155 | } 156 | }, 157 | { 158 | right: Number, 159 | "*"(a, b) { 160 | return mul_scalar(a, b); 161 | } 162 | }); 163 | 164 | Vec2 = class Vec2 extends vec2_ops 165 | { 166 | constructor(x, y) { 167 | super(); 168 | this.x = x; 169 | this.y = y; 170 | } 171 | toString() { 172 | return "Vec2(" + this.x + "," + this.y + ")"; 173 | } 174 | } 175 | 176 | var a = new Vec2(1, 2); 177 | var b = new Vec2(3, 4); 178 | var r; 179 | 180 | r = a * 2 + 3 * b; 181 | assert(r.x === 11 && r.y === 16); 182 | assert(a == a, true); 183 | assert(a == b, false); 184 | assert(a != a, false); 185 | assert(a < b, true); 186 | assert(a <= b, true); 187 | assert(b < a, false); 188 | assert(b <= a, false); 189 | assert(a <= a, true); 190 | assert(a >= a, true); 191 | a++; 192 | assert(a.x === 2 && a.y === 3); 193 | r = ++a; 194 | assert(a.x === 3 && a.y === 4); 195 | assert(r === a); 196 | } 197 | 198 | function test_default_op() 199 | { 200 | assert(Object(1) + 2, 3); 201 | assert(Object(1) + true, 2); 202 | assert(-Object(1), -1); 203 | } 204 | 205 | test_operators_create(); 206 | test_operators(); 207 | test_default_op(); 208 | -------------------------------------------------------------------------------- /tests/test_promise_gc_crash.js: -------------------------------------------------------------------------------- 1 | async function createTask() { 2 | return Promise.resolve().then(function () { 3 | new Uint8Array(1000000) 4 | }) 5 | } 6 | 7 | run() 8 | async function run() { 9 | let fn = (v) => { console.log(v.length); } 10 | let done = (v) => fn(v) 11 | createTask().then(done) 12 | const p = new Promise(() => { }) 13 | await p 14 | } -------------------------------------------------------------------------------- /tests/test_worker.js: -------------------------------------------------------------------------------- 1 | /* os.Worker API test */ 2 | import * as std from "std"; 3 | import * as os from "os"; 4 | 5 | function assert(actual, expected, message) { 6 | if (arguments.length == 1) 7 | expected = true; 8 | 9 | if (actual === expected) 10 | return; 11 | 12 | if (actual !== null && expected !== null 13 | && typeof actual == 'object' && typeof expected == 'object' 14 | && actual.toString() === expected.toString()) 15 | return; 16 | 17 | throw Error("assertion failed: got |" + actual + "|" + 18 | ", expected |" + expected + "|" + 19 | (message ? " (" + message + ")" : "")); 20 | } 21 | 22 | var worker; 23 | 24 | function test_worker() 25 | { 26 | var counter; 27 | 28 | worker = new os.Worker("./test_worker_module.js"); 29 | 30 | counter = 0; 31 | worker.onmessage = function (e) { 32 | var ev = e.data; 33 | // print("recv", JSON.stringify(ev)); 34 | switch(ev.type) { 35 | case "num": 36 | assert(ev.num, counter); 37 | counter++; 38 | if (counter == 10) { 39 | /* test SharedArrayBuffer modification */ 40 | let sab = new SharedArrayBuffer(10); 41 | let buf = new Uint8Array(sab); 42 | worker.postMessage({ type: "sab", buf: buf }); 43 | } 44 | break; 45 | case "sab_done": 46 | { 47 | let buf = ev.buf; 48 | /* check that the SharedArrayBuffer was modified */ 49 | assert(buf[2], 10); 50 | worker.postMessage({ type: "abort" }); 51 | } 52 | break; 53 | case "done": 54 | /* terminate */ 55 | worker.onmessage = null; 56 | break; 57 | } 58 | }; 59 | } 60 | 61 | 62 | test_worker(); 63 | -------------------------------------------------------------------------------- /tests/test_worker_module.js: -------------------------------------------------------------------------------- 1 | /* Worker code for test_worker.js */ 2 | import * as std from "std"; 3 | import * as os from "os"; 4 | 5 | var parent = os.Worker.parent; 6 | 7 | function handle_msg(e) { 8 | var ev = e.data; 9 | // print("child_recv", JSON.stringify(ev)); 10 | switch(ev.type) { 11 | case "abort": 12 | parent.postMessage({ type: "done" }); 13 | break; 14 | case "sab": 15 | /* modify the SharedArrayBuffer */ 16 | ev.buf[2] = 10; 17 | parent.postMessage({ type: "sab_done", buf: ev.buf }); 18 | break; 19 | } 20 | } 21 | 22 | function worker_main() { 23 | var i; 24 | 25 | parent.onmessage = handle_msg; 26 | for(i = 0; i < 10; i++) { 27 | parent.postMessage({ type: "num", num: i }); 28 | } 29 | } 30 | 31 | worker_main(); 32 | --------------------------------------------------------------------------------