cred: isolate scripts in WASI and move RSA signing to AWS-LC
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
# Don't show changes in generated files when doing git diff
|
||||
|
||||
gen/** -diff
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/" # Location of package manifests
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
@@ -0,0 +1,780 @@
|
||||
name: ci
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- '**'
|
||||
- '!.gitignore'
|
||||
- '!LICENSE'
|
||||
- '!README.md'
|
||||
- '!docs/**'
|
||||
- '!examples/**'
|
||||
- '.github/workflows/ci.yml'
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- '**'
|
||||
- '!.gitignore'
|
||||
- '!LICENSE'
|
||||
- '!README.md'
|
||||
- '!docs/**'
|
||||
- '!examples/**'
|
||||
- '.github/workflows/ci.yml'
|
||||
|
||||
jobs:
|
||||
codegen:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: build
|
||||
run: |
|
||||
make codegen
|
||||
- name: Check if the git repository is clean
|
||||
run: (exit "$(git status --porcelain --untracked-files=no | head -255 | wc -l)") || (echo "Dirty git tree"; git diff; exit 1)
|
||||
|
||||
ci:
|
||||
runs-on: ${{ matrix.config.os }}
|
||||
name: ${{ matrix.config.os }} (${{ matrix.config.configType }}${{ matrix.config.arch }})
|
||||
env:
|
||||
ASAN_OPTIONS: halt_on_error=1
|
||||
MSAN_OPTIONS: halt_on_error=1
|
||||
UBSAN_OPTIONS: halt_on_error=1
|
||||
defaults:
|
||||
run:
|
||||
shell: ${{ matrix.config.arch == '' && 'sh' || 'alpine.sh' }} {0}
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
# see https://github.com/quickjs-ng/quickjs/issues/879 - tl;dr flaky
|
||||
#- { os: ubuntu-24.04-arm, configType: Debug }
|
||||
#- { os: ubuntu-24.04-arm, configType: Release, runTest262: true }
|
||||
- { os: ubuntu-latest, configType: Debug }
|
||||
- { os: ubuntu-latest, configType: Release, runTest262: true }
|
||||
- { os: ubuntu-latest, configType: examples }
|
||||
- { os: ubuntu-latest, configType: shared }
|
||||
- { os: ubuntu-latest, configType: asan+ubsan, runTest262: true }
|
||||
- { os: ubuntu-latest, configType: msan }
|
||||
- { os: ubuntu-latest, configType: tcc }
|
||||
- { os: ubuntu-latest, arch: x86, runTest262: true }
|
||||
- { os: ubuntu-latest, arch: riscv64 }
|
||||
- { os: ubuntu-latest, arch: s390x }
|
||||
|
||||
- { os: macos-14, configType: Debug }
|
||||
- { os: macos-14, configType: Release }
|
||||
- { os: macos-14, configType: examples }
|
||||
- { os: macos-14, configType: shared }
|
||||
- { os: macos-14, configType: asan+ubsan }
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: install TCC
|
||||
if: ${{ matrix.config.configType == 'tcc' }}
|
||||
run: |
|
||||
pushd /tmp
|
||||
git clone https://repo.or.cz/tinycc.git
|
||||
cd tinycc
|
||||
git checkout c21576f8a32715ab439690d18184b0e02022bbbd
|
||||
./configure
|
||||
make
|
||||
sudo make install
|
||||
tcc -v
|
||||
popd
|
||||
echo "CC=tcc" >> $GITHUB_ENV;
|
||||
|
||||
- name: Install extra dependencies
|
||||
if: ${{ matrix.config.arch != '' }}
|
||||
shell: 'sh'
|
||||
run: |
|
||||
sudo apt update && sudo apt install -y binfmt-support
|
||||
|
||||
- name: Setup Alpine
|
||||
if: ${{ matrix.config.arch != '' }}
|
||||
uses: jirutka/setup-alpine@v1
|
||||
with:
|
||||
arch: ${{ matrix.config.arch }}
|
||||
packages: "build-base make cmake git"
|
||||
|
||||
- name: uname
|
||||
run: uname -a
|
||||
|
||||
- name: Set build ENV vars
|
||||
run: |
|
||||
if [ "${{ matrix.config.configType }}" = "Debug" ]; then
|
||||
echo "BUILD_TYPE=Debug" >> $GITHUB_ENV;
|
||||
elif [ "${{ matrix.config.configType }}" = "examples" ]; then
|
||||
echo "QJS_BUILD_EXAMPLES=ON" >> $GITHUB_ENV;
|
||||
elif [ "${{ matrix.config.configType }}" = "shared" ]; then
|
||||
echo "BUILD_SHARED_LIBS=ON" >> $GITHUB_ENV;
|
||||
elif [ "${{ matrix.config.configType }}" = "asan+ubsan" ]; then
|
||||
echo "BUILD_TYPE=RelWithDebInfo" >> $GITHUB_ENV;
|
||||
echo "QJS_ENABLE_ASAN=ON" >> $GITHUB_ENV;
|
||||
echo "QJS_ENABLE_UBSAN=ON" >> $GITHUB_ENV;
|
||||
elif [ "${{ matrix.config.configType }}" = "msan" ]; then
|
||||
echo "BUILD_TYPE=RelWithDebInfo" >> $GITHUB_ENV;
|
||||
echo "QJS_ENABLE_MSAN=ON" >> $GITHUB_ENV;
|
||||
echo "CC=clang" >> $GITHUB_ENV;
|
||||
fi
|
||||
|
||||
- name: build
|
||||
run: |
|
||||
make \
|
||||
BUILD_TYPE=$BUILD_TYPE \
|
||||
QJS_BUILD_EXAMPLES=$QJS_BUILD_EXAMPLES \
|
||||
BUILD_SHARED_LIBS=$BUILD_SHARED_LIBS \
|
||||
QJS_ENABLE_ASAN=$QJS_ENABLE_ASAN \
|
||||
QJS_ENABLE_UBSAN=$QJS_ENABLE_UBSAN \
|
||||
QJS_ENABLE_MSAN=$QJS_ENABLE_MSAN
|
||||
|
||||
- name: stats
|
||||
if: ${{ matrix.config.configType != 'examples' }}
|
||||
run: |
|
||||
make stats
|
||||
|
||||
- name: cxxtest
|
||||
run: |
|
||||
make cxxtest
|
||||
|
||||
- name: test
|
||||
if: ${{ matrix.config.configType != 'examples' }}
|
||||
run: |
|
||||
make test
|
||||
|
||||
- name: test examples
|
||||
if: ${{ matrix.config.configType == 'examples' }}
|
||||
run: |
|
||||
cp build/fib.so examples/
|
||||
cp build/point.so examples/
|
||||
./build/qjs examples/test_fib.js
|
||||
./build/qjs examples/test_point.js
|
||||
./build/qjs tests/test_bjson.js
|
||||
./build/function_source
|
||||
|
||||
- name: test 262
|
||||
if: ${{ matrix.config.runTest262 }}
|
||||
run: |
|
||||
git submodule update --init --checkout --depth 1
|
||||
make test262
|
||||
|
||||
- name: test standalone
|
||||
run: |
|
||||
./build/qjs -c examples/hello.js -o hello
|
||||
./hello
|
||||
|
||||
- name: test api
|
||||
run: |
|
||||
./build/api-test
|
||||
|
||||
windows-msvc:
|
||||
runs-on: ${{ matrix.config.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
- { arch: x64, vsArch: x64, buildType: Debug, os: windows-latest }
|
||||
- { arch: x64, vsArch: x64, buildType: Release, os: windows-latest }
|
||||
- { arch: Win32, vsArch: x86, buildType: Debug, os: windows-latest }
|
||||
- { arch: Win32, vsArch: x86, buildType: Release, os: windows-latest }
|
||||
- { arch: ARM64, vsArch: arm64, buildType: Debug, os: windows-11-arm }
|
||||
- { arch: ARM64, vsArch: arm64, buildType: Release, os: windows-11-arm }
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: build
|
||||
run: |
|
||||
cmake -B build -DQJS_BUILD_EXAMPLES=ON -G "Visual Studio 17 2022" -A ${{matrix.config.arch}}
|
||||
cmake --build build --config ${{matrix.config.buildType}}
|
||||
- name: stats
|
||||
run: |
|
||||
build\${{matrix.config.buildType}}\qjs.exe -qd
|
||||
- name: test
|
||||
run: |
|
||||
cp build\${{matrix.config.buildType}}\fib.dll examples\
|
||||
cp build\${{matrix.config.buildType}}\point.dll examples\
|
||||
build\${{matrix.config.buildType}}\qjs.exe examples\test_fib.js
|
||||
build\${{matrix.config.buildType}}\qjs.exe examples\test_point.js
|
||||
build\${{matrix.config.buildType}}\run-test262.exe -c tests.conf
|
||||
build\${{matrix.config.buildType}}\function_source.exe
|
||||
- name: test standalone
|
||||
run: |
|
||||
build\${{matrix.config.buildType}}\qjs.exe -c examples\hello.js -o hello.exe
|
||||
.\hello.exe
|
||||
- name: test api
|
||||
run: |
|
||||
build\${{matrix.config.buildType}}\api-test.exe
|
||||
- name: Set up Visual Studio shell
|
||||
uses: egor-tensin/vs-shell@v2
|
||||
with:
|
||||
arch: ${{ matrix.config.vsArch }}
|
||||
- name: cxxtest
|
||||
run: |
|
||||
cl.exe /DJS_NAN_BOXING=0 /Zs cxxtest.cc
|
||||
cl.exe /DJS_NAN_BOXING=1 /Zs cxxtest.cc
|
||||
|
||||
windows-clang:
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
buildType: [Debug, Release]
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: build
|
||||
run: |
|
||||
git submodule update --init --checkout --depth 1
|
||||
cmake -B build -DQJS_BUILD_EXAMPLES=ON -G "Visual Studio 17 2022" -T ClangCL
|
||||
cmake --build build --config ${{matrix.buildType}}
|
||||
- name: stats
|
||||
run: |
|
||||
build\${{matrix.buildType}}\qjs.exe -qd
|
||||
- name: cxxtest
|
||||
run: |
|
||||
clang-cl.exe /DJS_NAN_BOXING=0 /Zs cxxtest.cc
|
||||
clang-cl.exe /DJS_NAN_BOXING=1 /Zs cxxtest.cc
|
||||
- name: test
|
||||
run: |
|
||||
cp build\${{matrix.buildType}}\fib.dll examples\
|
||||
cp build\${{matrix.buildType}}\point.dll examples\
|
||||
build\${{matrix.buildType}}\qjs.exe examples\test_fib.js
|
||||
build\${{matrix.buildType}}\qjs.exe examples\test_point.js
|
||||
build\${{matrix.buildType}}\run-test262.exe -c tests.conf
|
||||
build\${{matrix.buildType}}\function_source.exe
|
||||
- name: test api
|
||||
run: |
|
||||
build\${{matrix.buildType}}\api-test.exe
|
||||
|
||||
windows-ninja:
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
buildType: [Debug, Release]
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: install ninja
|
||||
run: |
|
||||
choco install ninja
|
||||
ninja.exe --version
|
||||
- name: build
|
||||
run: |
|
||||
git submodule update --init --checkout --depth 1
|
||||
cmake -B build -DQJS_BUILD_EXAMPLES=ON -DCMAKE_BUILD_TYPE=${{matrix.buildType}} -G "Ninja"
|
||||
cmake --build build
|
||||
- name: stats
|
||||
run: |
|
||||
build\qjs.exe -qd
|
||||
- name: test
|
||||
run: |
|
||||
cp build\fib.dll examples\
|
||||
cp build\point.dll examples\
|
||||
build\qjs.exe examples\test_fib.js
|
||||
build\qjs.exe examples\test_point.js
|
||||
build\run-test262.exe -c tests.conf
|
||||
build\function_source.exe
|
||||
- name: test api
|
||||
run: |
|
||||
build\api-test.exe
|
||||
|
||||
windows-sdk:
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arch: [x64, Win32]
|
||||
buildType: [Debug, Release]
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Install windows sdk
|
||||
uses: ChristopheLav/windows-sdk-install@v1
|
||||
with:
|
||||
version-sdk: 26100
|
||||
features: 'OptionId.DesktopCPPx86,OptionId.DesktopCPPx64'
|
||||
- name: build
|
||||
run: |
|
||||
cmake -B build -DQJS_BUILD_EXAMPLES=ON -DCMAKE_SYSTEM_VERSION="10.0.26100.0" -A ${{matrix.arch}}
|
||||
cmake --build build --config ${{matrix.buildType}}
|
||||
- name: stats
|
||||
run: |
|
||||
build\${{matrix.buildType}}\qjs.exe -qd
|
||||
- name: test
|
||||
run: |
|
||||
cp build\${{matrix.buildType}}\fib.dll examples\
|
||||
cp build\${{matrix.buildType}}\point.dll examples\
|
||||
build\${{matrix.buildType}}\qjs.exe examples\test_fib.js
|
||||
build\${{matrix.buildType}}\qjs.exe examples\test_point.js
|
||||
build\${{matrix.buildType}}\run-test262.exe -c tests.conf
|
||||
build\${{matrix.buildType}}\function_source.exe
|
||||
- name: test api
|
||||
run: |
|
||||
build\${{matrix.buildType}}\api-test.exe
|
||||
|
||||
windows-mingw:
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
buildType: [Debug, Release]
|
||||
sys:
|
||||
- mingw32
|
||||
- mingw64
|
||||
- clang64
|
||||
- ucrt64
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Setup MSYS2
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
update: true
|
||||
msystem: ${{matrix.sys}}
|
||||
install: >-
|
||||
git
|
||||
make
|
||||
pacboy: >-
|
||||
cmake:p
|
||||
ninja:p
|
||||
toolchain:p
|
||||
- name: build
|
||||
run: |
|
||||
make BUILD_TYPE=${{matrix.buildType}}
|
||||
- name: stats
|
||||
run: |
|
||||
make stats
|
||||
ldd build/qjs
|
||||
- name: cxxtest
|
||||
if: ${{ matrix.sys != 'clang64' }}
|
||||
run: |
|
||||
make cxxtest
|
||||
- name: cxxtest
|
||||
if: ${{ matrix.sys == 'clang64' }}
|
||||
run: |
|
||||
make cxxtest CXX=clang++
|
||||
- name: test
|
||||
run: |
|
||||
make test
|
||||
- name: test standalone
|
||||
run: |
|
||||
./build/qjs -c examples/hello.js -o hello.exe
|
||||
./hello
|
||||
- name: test api
|
||||
run: |
|
||||
./build/api-test
|
||||
windows-mingw-shared:
|
||||
runs-on: windows-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Setup MSYS2
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
install: >-
|
||||
git
|
||||
make
|
||||
pacboy: >-
|
||||
cmake:p
|
||||
ninja:p
|
||||
toolchain:p
|
||||
- name: build
|
||||
run: |
|
||||
make BUILD_SHARED_LIBS=ON
|
||||
ldd build/qjs
|
||||
- name: stats
|
||||
run: |
|
||||
make stats
|
||||
|
||||
emscripten:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: mymindstorm/setup-emsdk@v14
|
||||
- name: check emsdk
|
||||
run: emcc -v
|
||||
- name: build
|
||||
run: |
|
||||
emcmake cmake -B build -DQJS_BUILD_LIBC=ON
|
||||
emmake make -C build qjs_wasm "-j$(getconf _NPROCESSORS_ONLN)"
|
||||
- name: result
|
||||
run: ls -lh build
|
||||
wasi:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: jcbhmr/setup-wasmtime@v2
|
||||
- name: setup wasi-sdk
|
||||
run: |
|
||||
wget -nv https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-x86_64-linux.deb -P /tmp
|
||||
sudo apt install /tmp/wasi-sdk*.deb
|
||||
- name: test
|
||||
run: |
|
||||
cmake -B build -DCMAKE_TOOLCHAIN_FILE=/opt/wasi-sdk/share/cmake/wasi-sdk.cmake
|
||||
make -C build qjs_exe
|
||||
wasmtime run build/qjs -qd
|
||||
echo "console.log('hello wasi!');" > t.js
|
||||
wasmtime run --dir . build/qjs t.js
|
||||
|
||||
cygwin:
|
||||
runs-on: windows-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: C:\cygwin\bin\bash.exe --login --norc -eo pipefail -o igncr '{0}'
|
||||
env:
|
||||
CYGWIN_NOWINPATH: 1
|
||||
CHERE_INVOKING: 1
|
||||
steps:
|
||||
- name: Set up Cygwin
|
||||
uses: cygwin/cygwin-install-action@master
|
||||
with:
|
||||
packages: make cmake gcc-g++ bash
|
||||
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: build
|
||||
run: make
|
||||
|
||||
- name: stats
|
||||
run: make stats
|
||||
|
||||
- name: cxxtest
|
||||
run: |
|
||||
make cxxtest
|
||||
|
||||
- name: test
|
||||
run: make test
|
||||
|
||||
- name: test api
|
||||
run: |
|
||||
./build/api-test
|
||||
|
||||
openbsd:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: build + test
|
||||
uses: vmactions/openbsd-vm@v1
|
||||
with:
|
||||
usesh: true
|
||||
prepare: |
|
||||
pkg_add cmake gmake
|
||||
run: |
|
||||
gmake
|
||||
gmake stats
|
||||
|
||||
freebsd:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: build + test
|
||||
uses: vmactions/freebsd-vm@v1
|
||||
with:
|
||||
usesh: true
|
||||
prepare: |
|
||||
pkg install -y cmake gmake
|
||||
run: |
|
||||
gmake
|
||||
gmake stats
|
||||
|
||||
android:
|
||||
runs-on: ubuntu-latest
|
||||
container: reactnativecommunity/react-native-android:v13.0
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Configure android arm64
|
||||
# see build options you can use in https://developer.android.com/ndk/guides/cmake
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
"$ANDROID_HOME/cmake/3.22.1/bin/cmake" "-DCMAKE_TOOLCHAIN_FILE=$ANDROID_HOME/ndk/26.0.10792818/build/cmake/android.toolchain.cmake" -DCMAKE_BUILD_TYPE=Release -DANDROID_ABI="arm64-v8a" -DANDROID_PLATFORM=android-24 -DQJS_BUILD_LIBC=ON ..
|
||||
- name: Build android arm64
|
||||
run: |
|
||||
"$ANDROID_HOME/cmake/3.22.1/bin/cmake" --build build --target qjs
|
||||
ls -lh build
|
||||
|
||||
ios:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: configure
|
||||
run: |
|
||||
cmake -B build -GXcode -DCMAKE_SYSTEM_NAME:STRING=iOS -DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED:BOOL=NO -DQJS_BUILD_LIBC=ON
|
||||
- name: build
|
||||
run: |
|
||||
cmake --build build --config Release --target qjs
|
||||
ls -lh build
|
||||
|
||||
mimalloc-linux:
|
||||
runs-on: ubuntu-24.04
|
||||
env:
|
||||
QJS_BUILD_CLI_WITH_MIMALLOC: ON
|
||||
MIMALLOC_SHOW_STATS: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: install dependencies
|
||||
run: |
|
||||
sudo apt update && sudo apt -y install libmimalloc-dev
|
||||
- name: build
|
||||
run: |
|
||||
make
|
||||
- name: cxxtest
|
||||
run: |
|
||||
make cxxtest
|
||||
- name: test
|
||||
run: |
|
||||
make test
|
||||
|
||||
mimalloc-macos:
|
||||
runs-on: macos-latest
|
||||
env:
|
||||
QJS_BUILD_CLI_WITH_STATIC_MIMALLOC: ON
|
||||
MIMALLOC_SHOW_STATS: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: install dependencies
|
||||
run: |
|
||||
brew install mimalloc
|
||||
- name: build
|
||||
run: |
|
||||
make
|
||||
- name: cxxtest
|
||||
run: |
|
||||
make cxxtest
|
||||
- name: test
|
||||
run: |
|
||||
make test
|
||||
|
||||
amalgam:
|
||||
strategy:
|
||||
matrix:
|
||||
# TODO(bnoordhuis) test on windows
|
||||
config:
|
||||
- { os: ubuntu-latest }
|
||||
- { os: macos-latest }
|
||||
runs-on: ${{ matrix.config.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: build
|
||||
run: |
|
||||
make
|
||||
- name: create amalgamation
|
||||
run: |
|
||||
make amalgam
|
||||
- name: build amalgamation
|
||||
run: |
|
||||
unzip -d "$RUNNER_TEMP" build/quickjs-amalgam.zip
|
||||
cc -Wall -I. -o "$RUNNER_TEMP/run-test262.o" -c run-test262.c
|
||||
cc -Wall -I/ -DQJS_BUILD_LIBC -o "$RUNNER_TEMP/quickjs-amalgam.o" -c "$RUNNER_TEMP/quickjs-amalgam.c"
|
||||
cc -o "$RUNNER_TEMP/run-test262" "$RUNNER_TEMP/run-test262.o" "$RUNNER_TEMP/quickjs-amalgam.o" -lm
|
||||
- name: test
|
||||
run: |
|
||||
make test RUN262="$RUNNER_TEMP/run-test262"
|
||||
|
||||
jscheck:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: jscheck
|
||||
run: |
|
||||
make jscheck
|
||||
|
||||
parserless:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: build
|
||||
run: |
|
||||
make QJS_DISABLE_PARSER=ON QJS_BUILD_EXAMPLES=ON
|
||||
- name: test
|
||||
run: |
|
||||
./build/hello
|
||||
./build/hello_module
|
||||
|
||||
|
||||
meson:
|
||||
runs-on: ${{ matrix.platform }}
|
||||
name: meson on ${{ matrix.platform }} (${{ matrix.mode.name }} ${{ matrix.flavor }}, ${{ matrix.features.name }})
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
flavor:
|
||||
- debug
|
||||
- release
|
||||
features:
|
||||
- name: default
|
||||
args: ""
|
||||
- name: libc
|
||||
args: -Dlibc=true
|
||||
- name: mimalloc
|
||||
args: -Dcli_mimalloc=auto
|
||||
mode:
|
||||
- name: default
|
||||
args: -Dtests=enabled
|
||||
extra_envs: {}
|
||||
|
||||
# Alternative compiler setups
|
||||
- name: gcc
|
||||
args: -Dtests=enabled
|
||||
extra_envs:
|
||||
CC: gcc
|
||||
CXX: g++
|
||||
- name: clang
|
||||
args: -Dtests=enabled
|
||||
extra_envs:
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
|
||||
- name: sanitize
|
||||
args: >-
|
||||
"-Db_sanitize=address,undefined"
|
||||
extra_envs: {}
|
||||
|
||||
# This is for MSVC, which only supports AddressSanitizer.
|
||||
# https://learn.microsoft.com/en-us/cpp/sanitizers/
|
||||
- name: sanitize+asanonly
|
||||
args: -Db_sanitize=address
|
||||
extra_envs:
|
||||
ASAN_OPTIONS: report_globals=0:halt_on_error=1:abort_on_error=1:print_summary=1
|
||||
|
||||
- name: clang+sanitize
|
||||
args: >-
|
||||
"-Db_sanitize=address,undefined"
|
||||
extra_envs:
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
- name: clang+msan
|
||||
args: -Db_sanitize=memory
|
||||
extra_envs:
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
|
||||
# default clang on GitHub hosted runners is from MSYS2.
|
||||
# Use Visual Studio supplied clang-cl instead.
|
||||
- name: clang-cl+sanitize
|
||||
args: >-
|
||||
"-Db_sanitize=address,undefined"
|
||||
extra_envs:
|
||||
CC: clang-cl
|
||||
CXX: clang-cl
|
||||
platform:
|
||||
- ubuntu-latest
|
||||
- windows-latest
|
||||
- macos-latest
|
||||
|
||||
exclude:
|
||||
# clang-cl only makes sense on windows.
|
||||
- platform: ubuntu-latest
|
||||
mode:
|
||||
name: clang-cl+sanitize
|
||||
- platform: macos-latest
|
||||
mode:
|
||||
name: clang-cl+sanitize
|
||||
|
||||
# Use clang-cl instead of MSYS2 clang.
|
||||
#
|
||||
# we already tested clang+sanitize on linux,
|
||||
# if this doesn't work, it should be an issue for MSYS2 team to consider.
|
||||
- platform: windows-latest
|
||||
mode:
|
||||
name: clang
|
||||
- platform: windows-latest
|
||||
mode:
|
||||
name: clang+sanitize
|
||||
- platform: windows-latest
|
||||
mode:
|
||||
name: clang+msan
|
||||
|
||||
# MSVC-only sanitizers
|
||||
- platform: ubuntu-latest
|
||||
mode:
|
||||
name: sanitize+asanonly
|
||||
- platform: macos-latest
|
||||
mode:
|
||||
name: sanitize+asanonly
|
||||
- platform: windows-latest
|
||||
mode:
|
||||
name: sanitize
|
||||
|
||||
# clang is the default on macos
|
||||
# also gcc is an alias to clang
|
||||
- platform: macos-latest
|
||||
mode:
|
||||
name: clang
|
||||
- platform: macos-latest
|
||||
mode:
|
||||
name: gcc
|
||||
|
||||
# gcc is the default on linux
|
||||
- platform: ubuntu-latest
|
||||
mode:
|
||||
name: gcc
|
||||
|
||||
# only run sanitizer tests on linux
|
||||
#
|
||||
# gcc/clang's codegen shouldn't massively change across platforms,
|
||||
# and linux supports most of the sanitizers.
|
||||
- platform: macos-latest
|
||||
mode:
|
||||
name: clang+sanitize
|
||||
- platform: macos-latest
|
||||
mode:
|
||||
# macos does not support msan
|
||||
name: clang+msan
|
||||
- platform: macos-latest
|
||||
mode:
|
||||
name: sanitize
|
||||
|
||||
steps:
|
||||
- name: Setup meson
|
||||
run: |
|
||||
pipx install meson ninja
|
||||
- name: Install mimalloc
|
||||
if: ${{ matrix.platform == 'ubuntu-latest' && matrix.features.name == 'mimalloc' }}
|
||||
run: sudo apt update && sudo apt -y install libmimalloc-dev
|
||||
- name: Install mimalloc
|
||||
if: ${{ matrix.platform == 'macos-latest' && matrix.features.name == 'mimalloc' }}
|
||||
run: brew install mimalloc
|
||||
# TODO: Install mimalloc on Windows
|
||||
# You need to:
|
||||
# - checkout mimalloc
|
||||
# - `msbuild mimalloc\ide\vs2022\mimalloc.sln`
|
||||
# - not cmake, because https://github.com/microsoft/mimalloc/issues/575#issuecomment-1112723975
|
||||
# - it is possible to integrate vcpkg with meson, but:
|
||||
# - 1. the above issue
|
||||
# - 2. the vcpkg port of mimalloc is outdated, and still broken on server 2019
|
||||
# - or maintain a meson port for mimalloc (and ensure it behaves correctly)
|
||||
# - Make it findable with cmake
|
||||
# - not the simpler pkg-config. although there was pkg-config in PATH,
|
||||
# but that was from strawberry perl and thus broken
|
||||
# ... good job, microsoft :))))
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
- name: Activate MSVC and Configure
|
||||
if: ${{ matrix.platform == 'windows-latest' }}
|
||||
env: ${{ matrix.mode.extra_envs }}
|
||||
run: |
|
||||
meson setup build-${{ matrix.flavor }} --buildtype=${{ matrix.flavor }} ${{ matrix.mode.args }} ${{ matrix.features.args }} --vsenv
|
||||
- name: Configuring
|
||||
if: ${{ matrix.platform != 'windows-latest' }}
|
||||
env: ${{ matrix.mode.extra_envs }}
|
||||
run: |
|
||||
meson setup build-${{ matrix.flavor }} --buildtype=${{ matrix.flavor }} ${{ matrix.mode.args }} ${{ matrix.features.args }}
|
||||
- name: Building
|
||||
run: |
|
||||
meson compile -C build-${{ matrix.flavor }}
|
||||
|
||||
- name: Running tests
|
||||
env: ${{ matrix.mode.extra_envs }}
|
||||
run: |
|
||||
meson test -C build-${{ matrix.flavor }} --timeout-multiplier 5 --print-errorlogs
|
||||
meson test --benchmark -C build-${{ matrix.flavor }} --timeout-multiplier 5 --print-errorlogs
|
||||
- uses: actions/upload-artifact@v6
|
||||
if: ${{ failure() }}
|
||||
with:
|
||||
name: ${{ matrix.platform }}-${{ matrix.mode.name }}-${{ matrix.features.name }}-${{ matrix.flavor }}-logs
|
||||
path: build-${{ matrix.flavor }}/meson-logs
|
||||
@@ -0,0 +1,49 @@
|
||||
name: Docs
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- 'docs/**'
|
||||
- '.github/workflows/*docs.yml'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build Docusaurus
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version-file: 'docs/.nvmrc'
|
||||
- name: Install dependencies
|
||||
working-directory: ./docs
|
||||
run: npm install
|
||||
- name: Build
|
||||
working-directory: ./docs
|
||||
run: npm run build
|
||||
- name: Upload Build Artifact
|
||||
uses: actions/upload-pages-artifact@v4
|
||||
with:
|
||||
path: docs/build
|
||||
|
||||
deploy:
|
||||
name: Deploy to GitHub Pages
|
||||
needs: build
|
||||
|
||||
# Grant GITHUB_TOKEN the permissions required to make a Pages deployment
|
||||
permissions:
|
||||
pages: write # to deploy to Pages
|
||||
id-token: write # to verify the deployment originates from an appropriate source
|
||||
|
||||
# Deploy to the github-pages environment
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
||||
@@ -0,0 +1,155 @@
|
||||
name: release
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
tags:
|
||||
- "v*.*.*"
|
||||
|
||||
jobs:
|
||||
check_meson_version:
|
||||
runs-on: ubuntu-22.04
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: install meson and ninja
|
||||
run: |
|
||||
pip install --upgrade meson ninja
|
||||
- name: check meson version
|
||||
run: |
|
||||
MESON_VERSION=$(meson introspect meson.build --projectinfo | jq -r '.version')
|
||||
test "${{ github.ref_name }}" = "v${MESON_VERSION}"
|
||||
|
||||
linux:
|
||||
runs-on: ubuntu-22.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arch: [aarch64, riscv64, x86, x86_64]
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: jirutka/setup-alpine@v1
|
||||
with:
|
||||
arch: ${{matrix.arch}}
|
||||
packages: "build-base make cmake"
|
||||
- name: build
|
||||
shell: alpine.sh {0}
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DQJS_BUILD_CLI_STATIC=ON ..
|
||||
cd ..
|
||||
cmake --build build --target qjs_exe -j$(getconf _NPROCESSORS_ONLN)
|
||||
cmake --build build --target qjsc -j$(getconf _NPROCESSORS_ONLN)
|
||||
mv build/qjs build/qjs-linux-${{matrix.arch}}
|
||||
mv build/qjsc build/qjsc-linux-${{matrix.arch}}
|
||||
- name: check
|
||||
shell: alpine.sh {0}
|
||||
run: |
|
||||
file build/*-linux-${{matrix.arch}}
|
||||
- name: upload
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: qjs-linux-${{matrix.arch}}
|
||||
path: build/*-linux-${{matrix.arch}}
|
||||
|
||||
macos:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: build
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" ..
|
||||
make -j$(getconf _NPROCESSORS_ONLN)
|
||||
make -C .. amalgam # writes build/quickjs-amalgam.zip
|
||||
mv qjs qjs-darwin
|
||||
mv qjsc qjsc-darwin
|
||||
- name: check
|
||||
run: |
|
||||
lipo -info build/qjs-darwin build/qjsc-darwin
|
||||
- name: upload amalgamation
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: quickjs-amalgam.zip
|
||||
path: build/quickjs-amalgam.zip
|
||||
compression-level: 0 # already compressed
|
||||
- name: upload
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: qjs-darwin
|
||||
path: build/*-darwin
|
||||
|
||||
windows:
|
||||
runs-on: windows-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arch: [x86, x86_64]
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: Setup MSYS2
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: ${{ matrix.arch == 'x86' && 'mingw32' || 'ucrt64' }}
|
||||
install: >-
|
||||
git
|
||||
make
|
||||
pacboy: >-
|
||||
cmake:p
|
||||
ninja:p
|
||||
toolchain:p
|
||||
- name: build
|
||||
run: |
|
||||
make
|
||||
mv build/qjs.exe build/qjs-windows-${{matrix.arch}}.exe
|
||||
mv build/qjsc.exe build/qjsc-windows-${{matrix.arch}}.exe
|
||||
- name: check
|
||||
run: |
|
||||
file build/qjs-windows-${{matrix.arch}}.exe
|
||||
ldd build/qjs-windows-${{matrix.arch}}.exe build/qjsc-windows-${{matrix.arch}}.exe
|
||||
- name: upload
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: qjs-windows-${{matrix.arch}}
|
||||
path: build/*-windows-${{matrix.arch}}.exe
|
||||
|
||||
wasi:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- name: setup wasi-sdk
|
||||
run: |
|
||||
wget -nv https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-x86_64-linux.deb -P /tmp
|
||||
sudo apt install /tmp/wasi-sdk*.deb
|
||||
- name: build
|
||||
run: |
|
||||
cmake -B build -DCMAKE_TOOLCHAIN_FILE=/opt/wasi-sdk/share/cmake/wasi-sdk.cmake
|
||||
make -C build qjs_exe
|
||||
mv build/qjs build/qjs-wasi.wasm
|
||||
- name: upload
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: qjs-wasi
|
||||
path: build/qjs-wasi.wasm
|
||||
|
||||
upload-to-release:
|
||||
needs: [linux, macos, windows, wasi, check_meson_version]
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: get assets
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
path: build
|
||||
merge-multiple: true
|
||||
- run: ls -R build
|
||||
- name: release
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: |
|
||||
build/*
|
||||
@@ -0,0 +1,23 @@
|
||||
name: Test Docs
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'docs/**'
|
||||
- '.github/workflows/*docs.yml'
|
||||
|
||||
jobs:
|
||||
test-docs:
|
||||
name: Test Docusaurus build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version-file: 'docs/.nvmrc'
|
||||
- name: Install dependencies
|
||||
working-directory: ./docs
|
||||
run: npm install
|
||||
- name: Build
|
||||
working-directory: ./docs
|
||||
run: npm run build
|
||||
@@ -0,0 +1,32 @@
|
||||
name: tsan
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- '**'
|
||||
- '!.gitignore'
|
||||
- '!LICENSE'
|
||||
- '!README.md'
|
||||
- '!docs/**'
|
||||
- '!examples/**'
|
||||
- '.github/workflows/tsan.yml'
|
||||
- '.github/workflows/valgrind.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
linux:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: true
|
||||
- name: build
|
||||
run: |
|
||||
cmake -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo -DQJS_ENABLE_TSAN=ON
|
||||
cmake --build build -j`nproc`
|
||||
- name: test
|
||||
run: |
|
||||
git submodule update --init --checkout --depth 1
|
||||
./build/run-test262 -m -c test262.conf -c test262-fast.conf -a
|
||||
@@ -0,0 +1,33 @@
|
||||
name: valgrind
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- '**'
|
||||
- '!.gitignore'
|
||||
- '!LICENSE'
|
||||
- '!README.md'
|
||||
- '!docs/**'
|
||||
- '!examples/**'
|
||||
- '.github/workflows/tsan.yml'
|
||||
- '.github/workflows/valgrind.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
linux:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: true
|
||||
- name: install valgrind
|
||||
run: sudo apt-get update && sudo apt-get install valgrind
|
||||
- name: build
|
||||
run: |
|
||||
make BUILD_TYPE=RelWithDebInfo
|
||||
- name: test
|
||||
run: |
|
||||
git submodule update --init --checkout --depth 1
|
||||
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --error-exitcode=1 ./build/run-test262 -m -c test262.conf -c test262-fast.conf -a
|
||||
@@ -0,0 +1,14 @@
|
||||
*.a
|
||||
*.orig
|
||||
*.so
|
||||
.obj/
|
||||
build/
|
||||
unicode/
|
||||
.idea
|
||||
cmake-*
|
||||
.vs
|
||||
out/
|
||||
CMakeUserPresets.json
|
||||
fuzz
|
||||
.vscode/
|
||||
microbench*.txt
|
||||
@@ -0,0 +1,5 @@
|
||||
[submodule "test262"]
|
||||
path = test262
|
||||
url = https://github.com/tc39/test262
|
||||
shallow = true
|
||||
update = none
|
||||
@@ -0,0 +1,461 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
project(quickjs LANGUAGES C)
|
||||
|
||||
include(CheckCCompilerFlag)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
set(CMAKE_C_VISIBILITY_PRESET hidden)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_C_EXTENSIONS ON)
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
|
||||
# MINGW doesn't exist in older cmake versions, newer versions don't know
|
||||
# about CMAKE_COMPILER_IS_MINGW, and there is no unique CMAKE_C_COMPILER_ID
|
||||
# for mingw-based compilers...
|
||||
if(MINGW)
|
||||
# do nothing
|
||||
elseif(CMAKE_C_COMPILER MATCHES "mingw")
|
||||
set(MINGW TRUE)
|
||||
else()
|
||||
set(MINGW FALSE)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "tvOS")
|
||||
set(TVOS TRUE)
|
||||
else()
|
||||
set(TVOS FALSE)
|
||||
endif()
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "watchOS")
|
||||
set(WATCHOS TRUE)
|
||||
else()
|
||||
set(WATCHOS FALSE)
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
message(STATUS "No build type selected, default to Release")
|
||||
set(CMAKE_BUILD_TYPE "Release")
|
||||
endif()
|
||||
|
||||
message(STATUS "Building in ${CMAKE_BUILD_TYPE} mode")
|
||||
message(STATUS "Building with ${CMAKE_C_COMPILER_ID} ${CMAKE_C_COMPILER_VERSION} on ${CMAKE_SYSTEM}")
|
||||
|
||||
macro(xcheck_add_c_compiler_flag FLAG)
|
||||
string(REPLACE "-" "" FLAG_NO_HYPHEN ${FLAG})
|
||||
check_c_compiler_flag(${FLAG} COMPILER_SUPPORTS_${FLAG_NO_HYPHEN})
|
||||
if(COMPILER_SUPPORTS_${FLAG_NO_HYPHEN})
|
||||
add_compile_options(${FLAG})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
xcheck_add_c_compiler_flag(-Wall)
|
||||
if(NOT MSVC AND NOT IOS AND NOT TVOS AND NOT WATCHOS)
|
||||
xcheck_add_c_compiler_flag(-Werror)
|
||||
xcheck_add_c_compiler_flag(-Wextra)
|
||||
endif()
|
||||
xcheck_add_c_compiler_flag(-Wformat=2)
|
||||
xcheck_add_c_compiler_flag(-Wno-implicit-fallthrough)
|
||||
xcheck_add_c_compiler_flag(-Wno-sign-compare)
|
||||
xcheck_add_c_compiler_flag(-Wno-missing-field-initializers)
|
||||
xcheck_add_c_compiler_flag(-Wno-unused-parameter)
|
||||
xcheck_add_c_compiler_flag(-Wno-unused-but-set-variable)
|
||||
xcheck_add_c_compiler_flag(-Wno-unused-result)
|
||||
xcheck_add_c_compiler_flag(-Wno-stringop-truncation)
|
||||
xcheck_add_c_compiler_flag(-Wno-array-bounds)
|
||||
xcheck_add_c_compiler_flag(-funsigned-char)
|
||||
|
||||
# ClangCL is command line compatible with MSVC, so 'MSVC' is set.
|
||||
if(MSVC)
|
||||
xcheck_add_c_compiler_flag(-Wno-unsafe-buffer-usage)
|
||||
xcheck_add_c_compiler_flag(-Wno-sign-conversion)
|
||||
xcheck_add_c_compiler_flag(-Wno-nonportable-system-include-path)
|
||||
xcheck_add_c_compiler_flag(-Wno-implicit-int-conversion)
|
||||
xcheck_add_c_compiler_flag(-Wno-shorten-64-to-32)
|
||||
xcheck_add_c_compiler_flag(-Wno-reserved-macro-identifier)
|
||||
xcheck_add_c_compiler_flag(-Wno-reserved-identifier)
|
||||
xcheck_add_c_compiler_flag(-Wdeprecated-declarations)
|
||||
xcheck_add_c_compiler_flag(/experimental:c11atomics)
|
||||
xcheck_add_c_compiler_flag(/wd4018) # -Wno-sign-conversion
|
||||
xcheck_add_c_compiler_flag(/wd4061) # -Wno-implicit-fallthrough
|
||||
xcheck_add_c_compiler_flag(/wd4100) # -Wno-unused-parameter
|
||||
xcheck_add_c_compiler_flag(/wd4200) # -Wno-zero-length-array
|
||||
xcheck_add_c_compiler_flag(/wd4242) # -Wno-shorten-64-to-32
|
||||
xcheck_add_c_compiler_flag(/wd4244) # -Wno-shorten-64-to-32
|
||||
xcheck_add_c_compiler_flag(/wd4245) # -Wno-sign-compare
|
||||
xcheck_add_c_compiler_flag(/wd4267) # -Wno-shorten-64-to-32
|
||||
xcheck_add_c_compiler_flag(/wd4388) # -Wno-sign-compare
|
||||
xcheck_add_c_compiler_flag(/wd4389) # -Wno-sign-compare
|
||||
xcheck_add_c_compiler_flag(/wd4456) # Hides previous local declaration
|
||||
xcheck_add_c_compiler_flag(/wd4457) # Hides function parameter
|
||||
xcheck_add_c_compiler_flag(/wd4710) # Function not inlined
|
||||
xcheck_add_c_compiler_flag(/wd4711) # Function was inlined
|
||||
xcheck_add_c_compiler_flag(/wd4820) # Padding added after construct
|
||||
xcheck_add_c_compiler_flag(/wd4996) # -Wdeprecated-declarations
|
||||
xcheck_add_c_compiler_flag(/wd5045) # Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified
|
||||
endif()
|
||||
|
||||
# Set a 8MB default stack size on Windows.
|
||||
# It defaults to 1MB on MSVC, which is the same as our current JS stack size,
|
||||
# so it will overflow and crash otherwise.
|
||||
# On MinGW it defaults to 2MB.
|
||||
if(WIN32)
|
||||
if(MSVC)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:8388608")
|
||||
else()
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--stack,8388608")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# MacOS and GCC 11 or later need -Wno-maybe-uninitialized
|
||||
# https://github.com/quickjs-ng/quickjs/issues/453
|
||||
if(APPLE AND CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 11)
|
||||
xcheck_add_c_compiler_flag(-Wno-maybe-uninitialized)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "WASI")
|
||||
add_compile_definitions(
|
||||
_WASI_EMULATED_PROCESS_CLOCKS
|
||||
_WASI_EMULATED_SIGNAL
|
||||
)
|
||||
add_link_options(
|
||||
-lwasi-emulated-process-clocks
|
||||
-lwasi-emulated-signal
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CMAKE_BUILD_TYPE MATCHES "Debug")
|
||||
xcheck_add_c_compiler_flag(/Od)
|
||||
xcheck_add_c_compiler_flag(-O0)
|
||||
xcheck_add_c_compiler_flag(-ggdb)
|
||||
xcheck_add_c_compiler_flag(-fno-omit-frame-pointer)
|
||||
endif()
|
||||
|
||||
macro(xoption OPTION_NAME OPTION_TEXT OPTION_DEFAULT)
|
||||
option(${OPTION_NAME} ${OPTION_TEXT} ${OPTION_DEFAULT})
|
||||
if(DEFINED ENV{${OPTION_NAME}})
|
||||
# Allow setting the option through an environment variable.
|
||||
set(${OPTION_NAME} $ENV{${OPTION_NAME}})
|
||||
endif()
|
||||
if(${OPTION_NAME})
|
||||
add_definitions(-D${OPTION_NAME})
|
||||
endif()
|
||||
message(STATUS " ${OPTION_NAME}: ${${OPTION_NAME}}")
|
||||
endmacro()
|
||||
|
||||
xoption(BUILD_SHARED_LIBS "Build a shared library" OFF)
|
||||
if(BUILD_SHARED_LIBS)
|
||||
message(STATUS "Building a shared library")
|
||||
endif()
|
||||
|
||||
# note: QJS_ENABLE_TSAN is currently incompatible with the other sanitizers but we
|
||||
# don't explicitly check for that because who knows what the future will bring?
|
||||
# QJS_ENABLE_MSAN only works with clang at the time of writing; also not checked
|
||||
# for the same reason
|
||||
xoption(QJS_BUILD_EXAMPLES "Build examples" OFF)
|
||||
xoption(QJS_BUILD_CLI_STATIC "Build a static qjs executable" OFF)
|
||||
xoption(QJS_BUILD_CLI_WITH_MIMALLOC "Build the qjs executable with mimalloc" OFF)
|
||||
xoption(QJS_BUILD_CLI_WITH_STATIC_MIMALLOC "Build the qjs executable with mimalloc (statically linked)" OFF)
|
||||
xoption(QJS_DISABLE_PARSER "Disable JS source code parser" OFF)
|
||||
xoption(QJS_ENABLE_ASAN "Enable AddressSanitizer (ASan)" OFF)
|
||||
xoption(QJS_ENABLE_MSAN "Enable MemorySanitizer (MSan)" OFF)
|
||||
xoption(QJS_ENABLE_TSAN "Enable ThreadSanitizer (TSan)" OFF)
|
||||
xoption(QJS_ENABLE_UBSAN "Enable UndefinedBehaviorSanitizer (UBSan)" OFF)
|
||||
|
||||
if(QJS_ENABLE_ASAN)
|
||||
message(STATUS "Building with ASan")
|
||||
add_compile_options(
|
||||
-fsanitize=address
|
||||
-fno-sanitize-recover=all
|
||||
-fno-omit-frame-pointer
|
||||
)
|
||||
add_link_options(
|
||||
-fsanitize=address
|
||||
-fno-sanitize-recover=all
|
||||
-fno-omit-frame-pointer
|
||||
)
|
||||
endif()
|
||||
|
||||
if(QJS_ENABLE_MSAN)
|
||||
message(STATUS "Building with MSan")
|
||||
add_compile_options(
|
||||
-fsanitize=memory
|
||||
-fno-sanitize-recover=all
|
||||
-fno-omit-frame-pointer
|
||||
)
|
||||
add_link_options(
|
||||
-fsanitize=memory
|
||||
-fno-sanitize-recover=all
|
||||
-fno-omit-frame-pointer
|
||||
)
|
||||
endif()
|
||||
|
||||
if(QJS_ENABLE_TSAN)
|
||||
message(STATUS "Building with TSan")
|
||||
add_compile_options(
|
||||
-fsanitize=thread
|
||||
-fno-sanitize-recover=all
|
||||
-fno-omit-frame-pointer
|
||||
)
|
||||
add_link_options(
|
||||
-fsanitize=thread
|
||||
-fno-sanitize-recover=all
|
||||
-fno-omit-frame-pointer
|
||||
)
|
||||
endif()
|
||||
|
||||
if(QJS_ENABLE_UBSAN)
|
||||
message(STATUS "Building with UBSan")
|
||||
add_compile_options(
|
||||
-fsanitize=undefined
|
||||
-fno-sanitize-recover=all
|
||||
-fno-omit-frame-pointer
|
||||
)
|
||||
add_link_options(
|
||||
-fsanitize=undefined
|
||||
-fno-sanitize-recover=all
|
||||
-fno-omit-frame-pointer
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
# QuickJS library
|
||||
#
|
||||
|
||||
xoption(QJS_BUILD_LIBC "Build standard library modules as part of the library" OFF)
|
||||
macro(add_qjs_libc_if_needed target)
|
||||
if(NOT QJS_BUILD_LIBC)
|
||||
target_sources(${target} PRIVATE quickjs-libc.c)
|
||||
endif()
|
||||
endmacro()
|
||||
macro(add_static_if_needed target)
|
||||
if(QJS_BUILD_CLI_STATIC OR MINGW)
|
||||
target_link_options(${target} PRIVATE -static)
|
||||
if(MINGW)
|
||||
target_link_options(${target} PRIVATE -static-libgcc)
|
||||
endif()
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
set(qjs_sources
|
||||
cutils.c
|
||||
dtoa.c
|
||||
libregexp.c
|
||||
libunicode.c
|
||||
quickjs.c
|
||||
)
|
||||
|
||||
if(QJS_BUILD_LIBC)
|
||||
list(APPEND qjs_sources quickjs-libc.c)
|
||||
endif()
|
||||
list(APPEND qjs_defines _GNU_SOURCE)
|
||||
if(WIN32)
|
||||
# NB: Windows 7 is EOL and we are only supporting in so far as it doesn't interfere with progress.
|
||||
list(APPEND qjs_defines WIN32_LEAN_AND_MEAN _WIN32_WINNT=0x0601)
|
||||
endif()
|
||||
if(TVOS)
|
||||
list(APPEND qjs_defines _TVOS)
|
||||
endif()
|
||||
if(WATCHOS)
|
||||
list(APPEND qjs_defines _WATCHOS)
|
||||
endif()
|
||||
list(APPEND qjs_libs ${CMAKE_DL_LIBS})
|
||||
find_package(Threads)
|
||||
if(NOT CMAKE_SYSTEM_NAME STREQUAL "WASI")
|
||||
list(APPEND qjs_libs ${CMAKE_THREAD_LIBS_INIT})
|
||||
endif()
|
||||
|
||||
# try to find libm
|
||||
find_library(M_LIBRARIES m)
|
||||
if(M_LIBRARIES OR CMAKE_C_COMPILER_ID STREQUAL "TinyCC")
|
||||
list(APPEND qjs_libs m)
|
||||
endif()
|
||||
|
||||
add_library(qjs ${qjs_sources})
|
||||
target_compile_definitions(qjs PRIVATE ${qjs_defines})
|
||||
target_include_directories(qjs PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
)
|
||||
target_link_libraries(qjs PUBLIC ${qjs_libs})
|
||||
|
||||
if(EMSCRIPTEN)
|
||||
add_executable(qjs_wasm ${qjs_sources})
|
||||
target_link_options(qjs_wasm PRIVATE
|
||||
# in emscripten 3.x, this will be set to 16k which is too small for quickjs. #write sth. to force github rebuild
|
||||
-sSTACK_SIZE=2097152 # let it be 2m = 2 * 1024 * 1024 = 2097152, otherwise, stack overflow may be occured at bootstrap
|
||||
-sNO_INVOKE_RUN
|
||||
-sNO_EXIT_RUNTIME
|
||||
-sMODULARIZE # do not mess the global
|
||||
-sEXPORT_ES6 # export js file to morden es module
|
||||
-sEXPORT_NAME=getQuickJs # give a name
|
||||
-sTEXTDECODER=1 # it will be 2 if we use -Oz, and that will cause js -> c string convertion fail
|
||||
-sNO_DEFAULT_TO_CXX # this project is pure c project, no need for c plus plus handle
|
||||
-sEXPORTED_RUNTIME_METHODS=ccall,cwrap
|
||||
)
|
||||
target_compile_definitions(qjs_wasm PRIVATE ${qjs_defines})
|
||||
target_link_libraries(qjs_wasm m)
|
||||
endif()
|
||||
|
||||
|
||||
# QuickJS bytecode compiler
|
||||
#
|
||||
|
||||
add_executable(qjsc
|
||||
qjsc.c
|
||||
)
|
||||
add_qjs_libc_if_needed(qjsc)
|
||||
add_static_if_needed(qjsc)
|
||||
target_compile_definitions(qjsc PRIVATE ${qjs_defines})
|
||||
target_link_libraries(qjsc qjs)
|
||||
|
||||
|
||||
# QuickJS CLI
|
||||
#
|
||||
|
||||
add_executable(qjs_exe
|
||||
gen/repl.c
|
||||
gen/standalone.c
|
||||
qjs.c
|
||||
)
|
||||
add_qjs_libc_if_needed(qjs_exe)
|
||||
add_static_if_needed(qjs_exe)
|
||||
set_target_properties(qjs_exe PROPERTIES
|
||||
OUTPUT_NAME "qjs"
|
||||
)
|
||||
target_compile_definitions(qjs_exe PRIVATE ${qjs_defines})
|
||||
target_link_libraries(qjs_exe qjs)
|
||||
if(NOT WIN32)
|
||||
set_target_properties(qjs_exe PROPERTIES ENABLE_EXPORTS TRUE)
|
||||
endif()
|
||||
if(QJS_BUILD_CLI_WITH_MIMALLOC OR QJS_BUILD_CLI_WITH_STATIC_MIMALLOC)
|
||||
find_package(mimalloc REQUIRED)
|
||||
# Upstream mimalloc doesn't provide a way to know if both libraries are supported.
|
||||
if(QJS_BUILD_CLI_WITH_STATIC_MIMALLOC)
|
||||
target_link_libraries(qjs_exe mimalloc-static)
|
||||
else()
|
||||
target_link_libraries(qjs_exe mimalloc)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Test262 runner
|
||||
#
|
||||
|
||||
if(NOT EMSCRIPTEN)
|
||||
add_executable(run-test262
|
||||
run-test262.c
|
||||
)
|
||||
add_qjs_libc_if_needed(run-test262)
|
||||
target_compile_definitions(run-test262 PRIVATE ${qjs_defines})
|
||||
target_link_libraries(run-test262 qjs)
|
||||
endif()
|
||||
|
||||
# Interrupt test
|
||||
#
|
||||
|
||||
add_executable(api-test
|
||||
api-test.c
|
||||
)
|
||||
target_compile_definitions(api-test PRIVATE ${qjs_defines})
|
||||
target_link_libraries(api-test qjs)
|
||||
|
||||
# Unicode generator
|
||||
#
|
||||
|
||||
add_executable(unicode_gen EXCLUDE_FROM_ALL
|
||||
cutils.c
|
||||
libunicode.c
|
||||
unicode_gen.c
|
||||
)
|
||||
target_compile_definitions(unicode_gen PRIVATE ${qjs_defines})
|
||||
|
||||
add_executable(function_source
|
||||
gen/function_source.c
|
||||
)
|
||||
add_qjs_libc_if_needed(function_source)
|
||||
target_include_directories(function_source PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_compile_definitions(function_source PRIVATE ${qjs_defines})
|
||||
target_link_libraries(function_source qjs)
|
||||
|
||||
# Examples
|
||||
#
|
||||
|
||||
if(QJS_BUILD_EXAMPLES)
|
||||
add_executable(hello
|
||||
gen/hello.c
|
||||
)
|
||||
add_qjs_libc_if_needed(hello)
|
||||
target_include_directories(hello PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_compile_definitions(hello PRIVATE ${qjs_defines})
|
||||
target_link_libraries(hello qjs)
|
||||
|
||||
add_executable(hello_module
|
||||
gen/hello_module.c
|
||||
)
|
||||
add_qjs_libc_if_needed(hello_module)
|
||||
target_include_directories(hello_module PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_compile_definitions(hello_module PRIVATE ${qjs_defines})
|
||||
target_link_libraries(hello_module qjs)
|
||||
|
||||
add_library(fib MODULE examples/fib.c)
|
||||
set_target_properties(fib PROPERTIES
|
||||
PREFIX ""
|
||||
C_VISIBILITY_PRESET default
|
||||
)
|
||||
target_compile_definitions(fib PRIVATE JS_SHARED_LIBRARY)
|
||||
if(WIN32)
|
||||
target_link_libraries(fib qjs)
|
||||
elseif(APPLE)
|
||||
target_link_options(fib PRIVATE -undefined dynamic_lookup)
|
||||
endif()
|
||||
|
||||
add_library(point MODULE examples/point.c)
|
||||
set_target_properties(point PROPERTIES
|
||||
PREFIX ""
|
||||
C_VISIBILITY_PRESET default
|
||||
)
|
||||
target_compile_definitions(point PRIVATE JS_SHARED_LIBRARY)
|
||||
if(WIN32)
|
||||
target_link_libraries(point qjs)
|
||||
elseif(APPLE)
|
||||
target_link_options(point PRIVATE -undefined dynamic_lookup)
|
||||
endif()
|
||||
|
||||
add_executable(test_fib
|
||||
examples/fib.c
|
||||
gen/test_fib.c
|
||||
)
|
||||
add_qjs_libc_if_needed(test_fib)
|
||||
target_include_directories(test_fib PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_compile_definitions(test_fib PRIVATE ${qjs_defines})
|
||||
target_link_libraries(test_fib qjs)
|
||||
endif()
|
||||
|
||||
# Install target
|
||||
#
|
||||
|
||||
file(STRINGS quickjs.h quickjs_h REGEX QJS_VERSION)
|
||||
string(REGEX MATCH "QJS_VERSION_MAJOR ([0-9]*)" _ "${quickjs_h}")
|
||||
set(QJS_VERSION_MAJOR ${CMAKE_MATCH_1})
|
||||
string(REGEX MATCH "QJS_VERSION_MINOR ([0-9]*)" _ "${quickjs_h}")
|
||||
set(QJS_VERSION_MINOR ${CMAKE_MATCH_1})
|
||||
string(REGEX MATCH "QJS_VERSION_PATCH ([0-9]*)" _ "${quickjs_h}")
|
||||
set(QJS_VERSION_PATCH ${CMAKE_MATCH_1})
|
||||
set_target_properties(qjs PROPERTIES
|
||||
VERSION ${QJS_VERSION_MAJOR}.${QJS_VERSION_MINOR}.${QJS_VERSION_PATCH}
|
||||
SOVERSION ${QJS_VERSION_MAJOR}
|
||||
)
|
||||
install(FILES quickjs.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
if(QJS_BUILD_LIBC)
|
||||
install(FILES quickjs-libc.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
endif()
|
||||
if(NOT IOS AND NOT TVOS AND NOT WATCHOS)
|
||||
install(TARGETS qjs_exe RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
install(TARGETS qjsc RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
endif()
|
||||
install(TARGETS qjs EXPORT qjsConfig
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
install(EXPORT qjsConfig DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/quickjs)
|
||||
install(FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR})
|
||||
install(DIRECTORY examples DESTINATION ${CMAKE_INSTALL_DOCDIR})
|
||||
@@ -0,0 +1,24 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017-2024 Fabrice Bellard
|
||||
Copyright (c) 2017-2024 Charlie Gordon
|
||||
Copyright (c) 2023-2025 Ben Noordhuis
|
||||
Copyright (c) 2023-2025 Saúl Ibarra Corretgé
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
@@ -0,0 +1,147 @@
|
||||
#
|
||||
# QuickJS Javascript Engine
|
||||
#
|
||||
# Copyright (c) 2017-2024 Fabrice Bellard
|
||||
# Copyright (c) 2017-2024 Charlie Gordon
|
||||
# Copyright (c) 2023-2025 Ben Noordhuis
|
||||
# Copyright (c) 2023-2025 Saúl Ibarra Corretgé
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
|
||||
BUILD_DIR=build
|
||||
BUILD_TYPE?=Release
|
||||
INSTALL_PREFIX?=/usr/local
|
||||
|
||||
QJS=$(BUILD_DIR)/qjs
|
||||
QJSC=$(BUILD_DIR)/qjsc
|
||||
RUN262=$(BUILD_DIR)/run-test262
|
||||
|
||||
JOBS?=$(shell getconf _NPROCESSORS_ONLN)
|
||||
ifeq ($(JOBS),)
|
||||
JOBS := $(shell sysctl -n hw.ncpu)
|
||||
endif
|
||||
ifeq ($(JOBS),)
|
||||
JOBS := $(shell nproc)
|
||||
endif
|
||||
ifeq ($(JOBS),)
|
||||
JOBS := 4
|
||||
endif
|
||||
|
||||
all: $(QJS)
|
||||
|
||||
amalgam: TEMP := $(shell mktemp -d)
|
||||
amalgam: $(QJS)
|
||||
$(QJS) amalgam.js $(TEMP)/quickjs-amalgam.c
|
||||
cp quickjs.h quickjs-libc.h $(TEMP)
|
||||
cd $(TEMP) && zip -9 quickjs-amalgam.zip quickjs-amalgam.c quickjs.h quickjs-libc.h
|
||||
cp $(TEMP)/quickjs-amalgam.zip $(BUILD_DIR)
|
||||
cd $(TEMP) && $(RM) quickjs-amalgam.zip quickjs-amalgam.c quickjs.h quickjs-libc.h
|
||||
$(RM) -d $(TEMP)
|
||||
|
||||
fuzz:
|
||||
clang -g -O1 -fsanitize=address,undefined,fuzzer -o fuzz fuzz.c
|
||||
./fuzz
|
||||
|
||||
$(BUILD_DIR):
|
||||
cmake -B $(BUILD_DIR) -DCMAKE_BUILD_TYPE=$(BUILD_TYPE) -DCMAKE_INSTALL_PREFIX=$(INSTALL_PREFIX)
|
||||
|
||||
$(QJS): $(BUILD_DIR)
|
||||
cmake --build $(BUILD_DIR) -j $(JOBS)
|
||||
|
||||
$(QJSC): $(BUILD_DIR)
|
||||
cmake --build $(BUILD_DIR) --target qjsc -j $(JOBS)
|
||||
|
||||
install: $(QJS) $(QJSC)
|
||||
cmake --build $(BUILD_DIR) --target install
|
||||
|
||||
clean:
|
||||
cmake --build $(BUILD_DIR) --target clean
|
||||
|
||||
codegen: $(QJSC)
|
||||
$(QJSC) -ss -o gen/repl.c -m repl.js
|
||||
$(QJSC) -ss -o gen/standalone.c -m standalone.js
|
||||
$(QJSC) -e -o gen/function_source.c tests/function_source.js
|
||||
$(QJSC) -e -o gen/hello.c examples/hello.js
|
||||
$(QJSC) -e -o gen/hello_module.c -m examples/hello_module.js
|
||||
$(QJSC) -e -o gen/test_fib.c -m examples/test_fib.js
|
||||
$(QJSC) -C -ss -o builtin-array-fromasync.h builtin-array-fromasync.js
|
||||
|
||||
debug:
|
||||
BUILD_TYPE=Debug $(MAKE)
|
||||
|
||||
distclean:
|
||||
@rm -rf $(BUILD_DIR)
|
||||
|
||||
stats: $(QJS)
|
||||
$(QJS) -qd
|
||||
|
||||
jscheck: CFLAGS=-I. -D_GNU_SOURCE -DJS_CHECK_JSVALUE -Wall -Werror -fsyntax-only -c -o /dev/null
|
||||
jscheck:
|
||||
$(CC) $(CFLAGS) api-test.c
|
||||
$(CC) $(CFLAGS) ctest.c
|
||||
$(CC) $(CFLAGS) fuzz.c
|
||||
$(CC) $(CFLAGS) gen/function_source.c
|
||||
$(CC) $(CFLAGS) gen/hello.c
|
||||
$(CC) $(CFLAGS) gen/hello_module.c
|
||||
$(CC) $(CFLAGS) gen/repl.c
|
||||
$(CC) $(CFLAGS) gen/standalone.c
|
||||
$(CC) $(CFLAGS) gen/test_fib.c
|
||||
$(CC) $(CFLAGS) qjs.c
|
||||
$(CC) $(CFLAGS) qjsc.c
|
||||
$(CC) $(CFLAGS) quickjs-libc.c
|
||||
$(CC) $(CFLAGS) quickjs.c
|
||||
$(CC) $(CFLAGS) run-test262.c
|
||||
|
||||
# effectively .PHONY because it doesn't generate output
|
||||
ctest: CFLAGS=-std=c11 -fsyntax-only -Wall -Wextra -Werror -pedantic
|
||||
ctest: ctest.c quickjs.h
|
||||
$(CC) $(CFLAGS) -DJS_NAN_BOXING=0 $<
|
||||
$(CC) $(CFLAGS) -DJS_NAN_BOXING=1 $<
|
||||
|
||||
# effectively .PHONY because it doesn't generate output
|
||||
cxxtest: CXXFLAGS=-std=c++11 -fsyntax-only -Wall -Wextra -Werror -pedantic
|
||||
cxxtest: cxxtest.cc quickjs.h
|
||||
$(CXX) $(CXXFLAGS) -DJS_NAN_BOXING=0 $<
|
||||
$(CXX) $(CXXFLAGS) -DJS_NAN_BOXING=1 $<
|
||||
|
||||
test: $(QJS)
|
||||
$(RUN262) -c tests.conf
|
||||
|
||||
test262: $(QJS)
|
||||
$(RUN262) -m -c test262.conf -a
|
||||
|
||||
test262-fast: $(QJS)
|
||||
$(RUN262) -m -c test262.conf -c test262-fast.conf -a
|
||||
|
||||
test262-update: $(QJS)
|
||||
$(RUN262) -u -c test262.conf -a -t 1
|
||||
|
||||
test262-check: $(QJS)
|
||||
$(RUN262) -m -c test262.conf -E -a
|
||||
|
||||
microbench: $(QJS)
|
||||
$(QJS) tests/microbench.js
|
||||
|
||||
unicode_gen: $(BUILD_DIR)
|
||||
cmake --build $(BUILD_DIR) --target unicode_gen
|
||||
|
||||
libunicode-table.h: unicode_gen
|
||||
$(BUILD_DIR)/unicode_gen unicode $@
|
||||
|
||||
.PHONY: all amalgam ctest cxxtest debug fuzz jscheck install clean codegen distclean stats test test262 test262-update test262-check microbench unicode_gen $(QJS) $(QJSC)
|
||||
@@ -0,0 +1,24 @@
|
||||
# ⚡️ QuickJS - A mighty JavaScript engine
|
||||
|
||||
## Overview
|
||||
|
||||
QuickJS is a small and embeddable JavaScript engine. It aims to support the latest
|
||||
[ECMAScript] specification.
|
||||
|
||||
This project is a _fork_ of the [original QuickJS project] by Fabrice Bellard and Charlie Gordon, after it went dormant, with the intent of reigniting its development.
|
||||
|
||||
## Getting started
|
||||
|
||||
Head over to the [project website] for instructions on how to get started and more
|
||||
documentation.
|
||||
|
||||
## Authors
|
||||
|
||||
[@bnoordhuis], [@saghul], and many more [contributors].
|
||||
|
||||
[ECMAScript]: https://tc39.es/ecma262/
|
||||
[original QuickJS project]: https://bellard.org/quickjs
|
||||
[@bnoordhuis]: https://github.com/bnoordhuis
|
||||
[@saghul]: https://github.com/saghul
|
||||
[contributors]: https://github.com/quickjs-ng/quickjs/graphs/contributors
|
||||
[project website]: https://quickjs-ng.github.io/quickjs/
|
||||
@@ -0,0 +1,49 @@
|
||||
import {loadFile, writeFile} from "qjs:std"
|
||||
|
||||
const cutils_c = loadFile("cutils.c")
|
||||
const cutils_h = loadFile("cutils.h")
|
||||
const dtoa_c = loadFile("dtoa.c")
|
||||
const dtoa_h = loadFile("dtoa.h")
|
||||
const libregexp_c = loadFile("libregexp.c")
|
||||
const libregexp_h = loadFile("libregexp.h")
|
||||
const libregexp_opcode_h = loadFile("libregexp-opcode.h")
|
||||
const libunicode_c = loadFile("libunicode.c")
|
||||
const libunicode_h = loadFile("libunicode.h")
|
||||
const libunicode_table_h = loadFile("libunicode-table.h")
|
||||
const list_h = loadFile("list.h")
|
||||
const quickjs_atom_h = loadFile("quickjs-atom.h")
|
||||
const quickjs_c = loadFile("quickjs.c")
|
||||
const quickjs_c_atomics_h = loadFile("quickjs-c-atomics.h")
|
||||
const quickjs_h = loadFile("quickjs.h")
|
||||
const quickjs_libc_c = loadFile("quickjs-libc.c")
|
||||
const quickjs_libc_h = loadFile("quickjs-libc.h")
|
||||
const quickjs_opcode_h = loadFile("quickjs-opcode.h")
|
||||
const gen_builtin_array_fromasync_h = loadFile("builtin-array-fromasync.h")
|
||||
|
||||
let source = "#if defined(QJS_BUILD_LIBC) && defined(__linux__) && !defined(_GNU_SOURCE)\n"
|
||||
+ "#define _GNU_SOURCE\n"
|
||||
+ "#endif\n"
|
||||
+ quickjs_c_atomics_h
|
||||
+ cutils_h
|
||||
+ dtoa_h
|
||||
+ list_h
|
||||
+ libunicode_h // exports lre_is_id_start, used by libregexp.h
|
||||
+ libregexp_h
|
||||
+ libunicode_table_h
|
||||
+ quickjs_h
|
||||
+ quickjs_c
|
||||
+ cutils_c
|
||||
+ dtoa_c
|
||||
+ libregexp_c
|
||||
+ libunicode_c
|
||||
+ "#ifdef QJS_BUILD_LIBC\n"
|
||||
+ quickjs_libc_h
|
||||
+ quickjs_libc_c
|
||||
+ "#endif // QJS_BUILD_LIBC\n"
|
||||
source = source.replace(/#include "quickjs-atom.h"/g, quickjs_atom_h)
|
||||
source = source.replace(/#include "quickjs-opcode.h"/g, quickjs_opcode_h)
|
||||
source = source.replace(/#include "libregexp-opcode.h"/g, libregexp_opcode_h)
|
||||
source = source.replace(/#include "builtin-array-fromasync.h"/g,
|
||||
gen_builtin_array_fromasync_h)
|
||||
source = source.replace(/#include "[^"]+"/g, "")
|
||||
writeFile(execArgv[2] ?? "quickjs-amalgam.c", source)
|
||||
@@ -0,0 +1,854 @@
|
||||
#ifdef NDEBUG
|
||||
#undef NDEBUG
|
||||
#endif
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "quickjs.h"
|
||||
#include "cutils.h"
|
||||
|
||||
static JSValue eval(JSContext *ctx, const char *code)
|
||||
{
|
||||
return JS_Eval(ctx, code, strlen(code), "<input>", JS_EVAL_TYPE_GLOBAL);
|
||||
}
|
||||
|
||||
static JSValue cfunc_callback(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
return JS_ThrowTypeError(ctx, "from cfunc");
|
||||
}
|
||||
|
||||
static JSValue cfuncdata_callback(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv,
|
||||
int magic, JSValueConst *func_data)
|
||||
{
|
||||
return JS_ThrowTypeError(ctx, "from cfuncdata");
|
||||
}
|
||||
|
||||
static JSValue cclosure_callback(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv,
|
||||
int magic, void *func_data)
|
||||
{
|
||||
return JS_ThrowTypeError(ctx, "from cclosure");
|
||||
}
|
||||
|
||||
static bool closure_finalized = false;
|
||||
|
||||
static void cclosure_opaque_finalize(void *opaque)
|
||||
{
|
||||
if ((intptr_t)opaque == 12)
|
||||
closure_finalized = true;
|
||||
}
|
||||
|
||||
static void cfunctions(void)
|
||||
{
|
||||
uint32_t length;
|
||||
const char *s;
|
||||
JSValue ret, stack;
|
||||
|
||||
JSRuntime *rt = JS_NewRuntime();
|
||||
JSContext *ctx = JS_NewContext(rt);
|
||||
JSValue cfunc = JS_NewCFunction(ctx, cfunc_callback, "cfunc", 42);
|
||||
JSValue cfuncdata =
|
||||
JS_NewCFunctionData2(ctx, cfuncdata_callback, "cfuncdata",
|
||||
/*length*/1337, /*magic*/0, /*data_len*/0, NULL);
|
||||
JSValue cclosure =
|
||||
JS_NewCClosure(ctx, cclosure_callback, "cclosure", cclosure_opaque_finalize,
|
||||
/*length*/0xC0DE, /*magic*/11, /*opaque*/(void*)12);
|
||||
JSValue global = JS_GetGlobalObject(ctx);
|
||||
JS_SetPropertyStr(ctx, global, "cfunc", cfunc);
|
||||
JS_SetPropertyStr(ctx, global, "cfuncdata", cfuncdata);
|
||||
JS_SetPropertyStr(ctx, global, "cclosure", cclosure);
|
||||
JS_FreeValue(ctx, global);
|
||||
|
||||
ret = eval(ctx, "cfunc.name");
|
||||
assert(!JS_IsException(ret));
|
||||
assert(JS_IsString(ret));
|
||||
s = JS_ToCString(ctx, ret);
|
||||
JS_FreeValue(ctx, ret);
|
||||
assert(s);
|
||||
assert(!strcmp(s, "cfunc"));
|
||||
JS_FreeCString(ctx, s);
|
||||
ret = eval(ctx, "cfunc.length");
|
||||
assert(!JS_IsException(ret));
|
||||
assert(JS_IsNumber(ret));
|
||||
assert(0 == JS_ToUint32(ctx, &length, ret));
|
||||
assert(length == 42);
|
||||
|
||||
ret = eval(ctx, "cfuncdata.name");
|
||||
assert(!JS_IsException(ret));
|
||||
assert(JS_IsString(ret));
|
||||
s = JS_ToCString(ctx, ret);
|
||||
JS_FreeValue(ctx, ret);
|
||||
assert(s);
|
||||
assert(!strcmp(s, "cfuncdata"));
|
||||
JS_FreeCString(ctx, s);
|
||||
ret = eval(ctx, "cfuncdata.length");
|
||||
assert(!JS_IsException(ret));
|
||||
assert(JS_IsNumber(ret));
|
||||
assert(0 == JS_ToUint32(ctx, &length, ret));
|
||||
assert(length == 1337);
|
||||
|
||||
ret = eval(ctx, "cclosure.name");
|
||||
assert(!JS_IsException(ret));
|
||||
assert(JS_IsString(ret));
|
||||
s = JS_ToCString(ctx, ret);
|
||||
JS_FreeValue(ctx, ret);
|
||||
assert(s);
|
||||
assert(!strcmp(s, "cclosure"));
|
||||
JS_FreeCString(ctx, s);
|
||||
ret = eval(ctx, "cclosure.length");
|
||||
assert(!JS_IsException(ret));
|
||||
assert(JS_IsNumber(ret));
|
||||
assert(0 == JS_ToUint32(ctx, &length, ret));
|
||||
assert(length == 0xC0DE);
|
||||
|
||||
ret = eval(ctx, "cfunc()");
|
||||
assert(JS_IsException(ret));
|
||||
ret = JS_GetException(ctx);
|
||||
assert(JS_IsError(ret));
|
||||
stack = JS_GetPropertyStr(ctx, ret, "stack");
|
||||
assert(JS_IsString(stack));
|
||||
s = JS_ToCString(ctx, stack);
|
||||
JS_FreeValue(ctx, stack);
|
||||
assert(s);
|
||||
assert(!strcmp(s, " at cfunc (native)\n at <eval> (<input>:1:1)\n"));
|
||||
JS_FreeCString(ctx, s);
|
||||
s = JS_ToCString(ctx, ret);
|
||||
JS_FreeValue(ctx, ret);
|
||||
assert(s);
|
||||
assert(!strcmp(s, "TypeError: from cfunc"));
|
||||
JS_FreeCString(ctx, s);
|
||||
|
||||
ret = eval(ctx, "cfuncdata()");
|
||||
assert(JS_IsException(ret));
|
||||
ret = JS_GetException(ctx);
|
||||
assert(JS_IsError(ret));
|
||||
stack = JS_GetPropertyStr(ctx, ret, "stack");
|
||||
assert(JS_IsString(stack));
|
||||
s = JS_ToCString(ctx, stack);
|
||||
JS_FreeValue(ctx, stack);
|
||||
assert(s);
|
||||
assert(!strcmp(s, " at cfuncdata (native)\n at <eval> (<input>:1:1)\n"));
|
||||
JS_FreeCString(ctx, s);
|
||||
s = JS_ToCString(ctx, ret);
|
||||
JS_FreeValue(ctx, ret);
|
||||
assert(s);
|
||||
assert(!strcmp(s, "TypeError: from cfuncdata"));
|
||||
JS_FreeCString(ctx, s);
|
||||
|
||||
ret = eval(ctx, "cclosure()");
|
||||
assert(JS_IsException(ret));
|
||||
ret = JS_GetException(ctx);
|
||||
assert(JS_IsError(ret));
|
||||
stack = JS_GetPropertyStr(ctx, ret, "stack");
|
||||
assert(JS_IsString(stack));
|
||||
s = JS_ToCString(ctx, stack);
|
||||
JS_FreeValue(ctx, stack);
|
||||
assert(s);
|
||||
assert(!strcmp(s, " at cclosure (native)\n at <eval> (<input>:1:1)\n"));
|
||||
JS_FreeCString(ctx, s);
|
||||
s = JS_ToCString(ctx, ret);
|
||||
JS_FreeValue(ctx, ret);
|
||||
assert(s);
|
||||
assert(!strcmp(s, "TypeError: from cclosure"));
|
||||
JS_FreeCString(ctx, s);
|
||||
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
|
||||
assert(closure_finalized);
|
||||
}
|
||||
|
||||
#define MAX_TIME 10
|
||||
|
||||
static int timeout_interrupt_handler(JSRuntime *rt, void *opaque)
|
||||
{
|
||||
int *time = (int *)opaque;
|
||||
if (*time <= MAX_TIME)
|
||||
*time += 1;
|
||||
return *time > MAX_TIME;
|
||||
}
|
||||
|
||||
static void sync_call(void)
|
||||
{
|
||||
static const char code[] =
|
||||
"(function() { \
|
||||
try { \
|
||||
while (true) {} \
|
||||
} catch (e) {} \
|
||||
})();";
|
||||
|
||||
JSRuntime *rt = JS_NewRuntime();
|
||||
JSContext *ctx = JS_NewContext(rt);
|
||||
int time = 0;
|
||||
JS_SetInterruptHandler(rt, timeout_interrupt_handler, &time);
|
||||
JSValue ret = eval(ctx, code);
|
||||
assert(time > MAX_TIME);
|
||||
assert(JS_IsException(ret));
|
||||
JS_FreeValue(ctx, ret);
|
||||
assert(JS_HasException(ctx));
|
||||
JSValue e = JS_GetException(ctx);
|
||||
assert(JS_IsUncatchableError(e));
|
||||
JS_FreeValue(ctx, e);
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
}
|
||||
|
||||
static void async_call(void)
|
||||
{
|
||||
static const char code[] =
|
||||
"(async function() { \
|
||||
const loop = async () => { \
|
||||
await Promise.resolve(); \
|
||||
while (true) {} \
|
||||
}; \
|
||||
await loop().catch(() => {}); \
|
||||
})();";
|
||||
|
||||
JSRuntime *rt = JS_NewRuntime();
|
||||
JSContext *ctx = JS_NewContext(rt);
|
||||
int time = 0;
|
||||
JS_SetInterruptHandler(rt, timeout_interrupt_handler, &time);
|
||||
JSValue ret = eval(ctx, code);
|
||||
assert(!JS_IsException(ret));
|
||||
JS_FreeValue(ctx, ret);
|
||||
assert(JS_IsJobPending(rt));
|
||||
int r = 0;
|
||||
while (JS_IsJobPending(rt)) {
|
||||
r = JS_ExecutePendingJob(rt, &ctx);
|
||||
}
|
||||
assert(time > MAX_TIME);
|
||||
assert(r == -1);
|
||||
assert(JS_HasException(ctx));
|
||||
JSValue e = JS_GetException(ctx);
|
||||
assert(JS_IsUncatchableError(e));
|
||||
JS_FreeValue(ctx, e);
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
}
|
||||
|
||||
static JSValue save_value(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
assert(argc == 1);
|
||||
JSValue *p = (JSValue *)JS_GetContextOpaque(ctx);
|
||||
*p = JS_DupValue(ctx, argv[0]);
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static void async_call_stack_overflow(void)
|
||||
{
|
||||
static const char code[] =
|
||||
"(async function() { \
|
||||
const f = () => f(); \
|
||||
try { \
|
||||
await Promise.resolve(); \
|
||||
f(); \
|
||||
} catch (e) { \
|
||||
save_value(e); \
|
||||
} \
|
||||
})();";
|
||||
|
||||
JSRuntime *rt = JS_NewRuntime();
|
||||
JSContext *ctx = JS_NewContext(rt);
|
||||
JSValue value = JS_UNDEFINED;
|
||||
JS_SetContextOpaque(ctx, &value);
|
||||
JSValue global = JS_GetGlobalObject(ctx);
|
||||
JS_SetPropertyStr(ctx, global, "save_value", JS_NewCFunction(ctx, save_value, "save_value", 1));
|
||||
JS_FreeValue(ctx, global);
|
||||
JSValue ret = eval(ctx, code);
|
||||
assert(!JS_IsException(ret));
|
||||
JS_FreeValue(ctx, ret);
|
||||
assert(JS_IsJobPending(rt));
|
||||
int r = 0;
|
||||
while (JS_IsJobPending(rt)) {
|
||||
r = JS_ExecutePendingJob(rt, &ctx);
|
||||
}
|
||||
assert(r == 1);
|
||||
assert(!JS_HasException(ctx));
|
||||
assert(JS_IsError(value)); // stack overflow should be caught
|
||||
JS_FreeValue(ctx, value);
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
}
|
||||
|
||||
// https://github.com/quickjs-ng/quickjs/issues/914
|
||||
static void raw_context_global_var(void)
|
||||
{
|
||||
JSRuntime *rt = JS_NewRuntime();
|
||||
JSContext *ctx = JS_NewContextRaw(rt);
|
||||
JS_AddIntrinsicEval(ctx);
|
||||
{
|
||||
JSValue ret = eval(ctx, "globalThis");
|
||||
assert(JS_IsException(ret));
|
||||
JS_FreeValue(ctx, ret);
|
||||
}
|
||||
{
|
||||
JSValue ret = eval(ctx, "var x = 42");
|
||||
assert(JS_IsUndefined(ret));
|
||||
JS_FreeValue(ctx, ret);
|
||||
}
|
||||
{
|
||||
JSValue ret = eval(ctx, "function f() {}");
|
||||
assert(JS_IsUndefined(ret));
|
||||
JS_FreeValue(ctx, ret);
|
||||
}
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
}
|
||||
|
||||
static void is_array(void)
|
||||
{
|
||||
JSRuntime *rt = JS_NewRuntime();
|
||||
JSContext *ctx = JS_NewContext(rt);
|
||||
{
|
||||
JSValue ret = eval(ctx, "[]");
|
||||
assert(!JS_IsException(ret));
|
||||
assert(JS_IsArray(ret));
|
||||
JS_FreeValue(ctx, ret);
|
||||
}
|
||||
{
|
||||
JSValue ret = eval(ctx, "new Proxy([], {})");
|
||||
assert(!JS_IsException(ret));
|
||||
assert(!JS_IsArray(ret));
|
||||
assert(JS_IsProxy(ret));
|
||||
JSValue handler = JS_GetProxyHandler(ctx, ret);
|
||||
JSValue target = JS_GetProxyTarget(ctx, ret);
|
||||
assert(!JS_IsException(handler));
|
||||
assert(!JS_IsException(target));
|
||||
assert(!JS_IsProxy(handler));
|
||||
assert(!JS_IsProxy(target));
|
||||
assert(JS_IsObject(handler));
|
||||
assert(JS_IsArray(target));
|
||||
JS_FreeValue(ctx, handler);
|
||||
JS_FreeValue(ctx, target);
|
||||
JS_FreeValue(ctx, ret);
|
||||
}
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
}
|
||||
|
||||
static int loader_calls;
|
||||
|
||||
static JSModuleDef *loader(JSContext *ctx, const char *name, void *opaque)
|
||||
{
|
||||
loader_calls++;
|
||||
assert(!strcmp(name, "b"));
|
||||
static const char code[] = "export function f(x){}";
|
||||
JSValue ret = JS_Eval(ctx, code, strlen(code), "b",
|
||||
JS_EVAL_TYPE_MODULE|JS_EVAL_FLAG_COMPILE_ONLY);
|
||||
assert(!JS_IsException(ret));
|
||||
JSModuleDef *m = JS_VALUE_GET_PTR(ret);
|
||||
assert(m);
|
||||
JS_FreeValue(ctx, ret);
|
||||
return m;
|
||||
}
|
||||
|
||||
static void module_serde(void)
|
||||
{
|
||||
JSRuntime *rt = JS_NewRuntime();
|
||||
//JS_SetDumpFlags(rt, JS_DUMP_MODULE_RESOLVE);
|
||||
JS_SetModuleLoaderFunc(rt, NULL, loader, NULL);
|
||||
JSContext *ctx = JS_NewContext(rt);
|
||||
static const char code[] = "import {f} from 'b'; f()";
|
||||
assert(loader_calls == 0);
|
||||
JSValue mod = JS_Eval(ctx, code, strlen(code), "a",
|
||||
JS_EVAL_TYPE_MODULE|JS_EVAL_FLAG_COMPILE_ONLY);
|
||||
assert(loader_calls == 1);
|
||||
assert(!JS_IsException(mod));
|
||||
assert(JS_IsModule(mod));
|
||||
size_t len = 0;
|
||||
uint8_t *buf = JS_WriteObject(ctx, &len, mod,
|
||||
JS_WRITE_OBJ_BYTECODE|JS_WRITE_OBJ_REFERENCE);
|
||||
assert(buf);
|
||||
assert(len > 0);
|
||||
JS_FreeValue(ctx, mod);
|
||||
assert(loader_calls == 1);
|
||||
mod = JS_ReadObject(ctx, buf, len, JS_READ_OBJ_BYTECODE);
|
||||
js_free(ctx, buf);
|
||||
assert(loader_calls == 1); // 'b' is returned from cache
|
||||
assert(!JS_IsException(mod));
|
||||
JSValue ret = JS_EvalFunction(ctx, mod);
|
||||
assert(!JS_IsException(ret));
|
||||
assert(JS_IsPromise(ret));
|
||||
JSValue result = JS_PromiseResult(ctx, ret);
|
||||
assert(!JS_IsException(result));
|
||||
assert(JS_IsUndefined(result));
|
||||
JS_FreeValue(ctx, result);
|
||||
JS_FreeValue(ctx, ret);
|
||||
JS_FreeValue(ctx, mod);
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
}
|
||||
|
||||
static void runtime_cstring_free(void)
|
||||
{
|
||||
JSRuntime *rt = JS_NewRuntime();
|
||||
JSContext *ctx = JS_NewContext(rt);
|
||||
// string -> cstring + JS_FreeCStringRT
|
||||
{
|
||||
JSValue ret = eval(ctx, "\"testStringPleaseIgnore\"");
|
||||
assert(JS_IsString(ret));
|
||||
const char *s = JS_ToCString(ctx, ret);
|
||||
assert(s);
|
||||
assert(strcmp(s, "testStringPleaseIgnore") == 0);
|
||||
JS_FreeCStringRT(rt, s);
|
||||
JS_FreeValue(ctx, ret);
|
||||
}
|
||||
// string -> cstring + JS_FreeCStringRT, destroying the source value first
|
||||
{
|
||||
JSValue ret = eval(ctx, "\"testStringPleaseIgnore\"");
|
||||
assert(JS_IsString(ret));
|
||||
const char *s = JS_ToCString(ctx, ret);
|
||||
assert(s);
|
||||
JS_FreeValue(ctx, ret);
|
||||
assert(strcmp(s, "testStringPleaseIgnore") == 0);
|
||||
JS_FreeCStringRT(rt, s);
|
||||
}
|
||||
// number -> cstring + JS_FreeCStringRT
|
||||
{
|
||||
JSValue ret = eval(ctx, "123987");
|
||||
assert(JS_IsNumber(ret));
|
||||
const char *s = JS_ToCString(ctx, ret);
|
||||
assert(s);
|
||||
assert(strcmp(s, "123987") == 0);
|
||||
JS_FreeCStringRT(rt, s);
|
||||
JS_FreeValue(ctx, ret);
|
||||
}
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
}
|
||||
|
||||
static void two_byte_string(void)
|
||||
{
|
||||
JSRuntime *rt = JS_NewRuntime();
|
||||
JSContext *ctx = JS_NewContext(rt);
|
||||
{
|
||||
JSValue v = JS_NewTwoByteString(ctx, NULL, 0);
|
||||
assert(!JS_IsException(v));
|
||||
const char *s = JS_ToCString(ctx, v);
|
||||
assert(s);
|
||||
assert(!strcmp(s, ""));
|
||||
JS_FreeCString(ctx, s);
|
||||
JS_FreeValue(ctx, v);
|
||||
}
|
||||
{
|
||||
JSValue v = JS_NewTwoByteString(ctx, (uint16_t[]){'o','k'}, 2);
|
||||
assert(!JS_IsException(v));
|
||||
const char *s = JS_ToCString(ctx, v);
|
||||
assert(s);
|
||||
assert(!strcmp(s, "ok"));
|
||||
JS_FreeCString(ctx, s);
|
||||
JS_FreeValue(ctx, v);
|
||||
}
|
||||
{
|
||||
JSValue v = JS_NewTwoByteString(ctx, (uint16_t[]){0xD800}, 1);
|
||||
assert(!JS_IsException(v));
|
||||
const char *s = JS_ToCString(ctx, v);
|
||||
assert(s);
|
||||
// questionable but surrogates don't map to UTF-8 without WTF-8
|
||||
assert(!strcmp(s, "\xED\xA0\x80"));
|
||||
JS_FreeCString(ctx, s);
|
||||
JS_FreeValue(ctx, v);
|
||||
}
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
}
|
||||
|
||||
static void weak_map_gc_check(void)
|
||||
{
|
||||
static const char init_code[] =
|
||||
"const map = new WeakMap(); \
|
||||
function addItem() { \
|
||||
const k = { \
|
||||
text: 'a', \
|
||||
}; \
|
||||
map.set(k, {k}); \
|
||||
}";
|
||||
static const char test_code[] = "addItem()";
|
||||
|
||||
JSRuntime *rt = JS_NewRuntime();
|
||||
JSContext *ctx = JS_NewContext(rt);
|
||||
|
||||
JSValue ret = eval(ctx, init_code);
|
||||
assert(!JS_IsException(ret));
|
||||
|
||||
JSValue ret_test = eval(ctx, test_code);
|
||||
assert(!JS_IsException(ret_test));
|
||||
JS_RunGC(rt);
|
||||
JSMemoryUsage memory_usage;
|
||||
JS_ComputeMemoryUsage(rt, &memory_usage);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
JSValue ret_test2 = eval(ctx, test_code);
|
||||
assert(!JS_IsException(ret_test2));
|
||||
JS_RunGC(rt);
|
||||
JSMemoryUsage memory_usage2;
|
||||
JS_ComputeMemoryUsage(rt, &memory_usage2);
|
||||
|
||||
assert(memory_usage.memory_used_count == memory_usage2.memory_used_count);
|
||||
assert(memory_usage.memory_used_size == memory_usage2.memory_used_size);
|
||||
JS_FreeValue(ctx, ret_test2);
|
||||
}
|
||||
|
||||
JS_FreeValue(ctx, ret);
|
||||
JS_FreeValue(ctx, ret_test);
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
}
|
||||
|
||||
struct {
|
||||
int hook_type_call_count[4];
|
||||
} promise_hook_state;
|
||||
|
||||
static void promise_hook_cb(JSContext *ctx, JSPromiseHookType type,
|
||||
JSValueConst promise, JSValueConst parent_promise,
|
||||
void *opaque)
|
||||
{
|
||||
assert(type == JS_PROMISE_HOOK_INIT ||
|
||||
type == JS_PROMISE_HOOK_BEFORE ||
|
||||
type == JS_PROMISE_HOOK_AFTER ||
|
||||
type == JS_PROMISE_HOOK_RESOLVE);
|
||||
promise_hook_state.hook_type_call_count[type]++;
|
||||
assert(opaque == (void *)&promise_hook_state);
|
||||
if (!JS_IsUndefined(parent_promise)) {
|
||||
JSValue global_object = JS_GetGlobalObject(ctx);
|
||||
JS_SetPropertyStr(ctx, global_object, "actual",
|
||||
JS_DupValue(ctx, parent_promise));
|
||||
JS_FreeValue(ctx, global_object);
|
||||
}
|
||||
}
|
||||
|
||||
static void promise_hook(void)
|
||||
{
|
||||
int *cc = promise_hook_state.hook_type_call_count;
|
||||
JSContext *unused;
|
||||
JSRuntime *rt = JS_NewRuntime();
|
||||
//JS_SetDumpFlags(rt, JS_DUMP_PROMISE);
|
||||
JS_SetPromiseHook(rt, promise_hook_cb, &promise_hook_state);
|
||||
JSContext *ctx = JS_NewContext(rt);
|
||||
JSValue global_object = JS_GetGlobalObject(ctx);
|
||||
{
|
||||
// empty module; creates an outer and inner module promise;
|
||||
// JS_Eval returns the outer promise
|
||||
JSValue ret = JS_Eval(ctx, "", 0, "<input>", JS_EVAL_TYPE_MODULE);
|
||||
assert(!JS_IsException(ret));
|
||||
assert(JS_IsPromise(ret));
|
||||
assert(JS_PROMISE_FULFILLED == JS_PromiseState(ctx, ret));
|
||||
JS_FreeValue(ctx, ret);
|
||||
assert(2 == cc[JS_PROMISE_HOOK_INIT]);
|
||||
assert(0 == cc[JS_PROMISE_HOOK_BEFORE]);
|
||||
assert(0 == cc[JS_PROMISE_HOOK_AFTER]);
|
||||
assert(2 == cc[JS_PROMISE_HOOK_RESOLVE]);
|
||||
assert(!JS_IsJobPending(rt));
|
||||
}
|
||||
memset(&promise_hook_state, 0, sizeof(promise_hook_state));
|
||||
{
|
||||
// module with unresolved promise; the outer and inner module promises
|
||||
// are resolved but not the user's promise
|
||||
static const char code[] = "new Promise(() => {})";
|
||||
JSValue ret = JS_Eval(ctx, code, strlen(code), "<input>", JS_EVAL_TYPE_MODULE);
|
||||
assert(!JS_IsException(ret));
|
||||
assert(JS_IsPromise(ret));
|
||||
assert(JS_PROMISE_FULFILLED == JS_PromiseState(ctx, ret)); // outer module promise
|
||||
JS_FreeValue(ctx, ret);
|
||||
assert(3 == cc[JS_PROMISE_HOOK_INIT]);
|
||||
assert(0 == cc[JS_PROMISE_HOOK_BEFORE]);
|
||||
assert(0 == cc[JS_PROMISE_HOOK_AFTER]);
|
||||
assert(2 == cc[JS_PROMISE_HOOK_RESOLVE]); // outer and inner module promise
|
||||
assert(!JS_IsJobPending(rt));
|
||||
}
|
||||
memset(&promise_hook_state, 0, sizeof(promise_hook_state));
|
||||
{
|
||||
// module with resolved promise
|
||||
static const char code[] = "new Promise((resolve,reject) => resolve())";
|
||||
JSValue ret = JS_Eval(ctx, code, strlen(code), "<input>", JS_EVAL_TYPE_MODULE);
|
||||
assert(!JS_IsException(ret));
|
||||
assert(JS_IsPromise(ret));
|
||||
assert(JS_PROMISE_FULFILLED == JS_PromiseState(ctx, ret)); // outer module promise
|
||||
JS_FreeValue(ctx, ret);
|
||||
assert(3 == cc[JS_PROMISE_HOOK_INIT]);
|
||||
assert(0 == cc[JS_PROMISE_HOOK_BEFORE]);
|
||||
assert(0 == cc[JS_PROMISE_HOOK_AFTER]);
|
||||
assert(3 == cc[JS_PROMISE_HOOK_RESOLVE]);
|
||||
assert(!JS_IsJobPending(rt));
|
||||
}
|
||||
memset(&promise_hook_state, 0, sizeof(promise_hook_state));
|
||||
{
|
||||
// module with rejected promise
|
||||
static const char code[] = "new Promise((resolve,reject) => reject())";
|
||||
JSValue ret = JS_Eval(ctx, code, strlen(code), "<input>", JS_EVAL_TYPE_MODULE);
|
||||
assert(!JS_IsException(ret));
|
||||
assert(JS_IsPromise(ret));
|
||||
assert(JS_PROMISE_FULFILLED == JS_PromiseState(ctx, ret)); // outer module promise
|
||||
JS_FreeValue(ctx, ret);
|
||||
assert(3 == cc[JS_PROMISE_HOOK_INIT]);
|
||||
assert(0 == cc[JS_PROMISE_HOOK_BEFORE]);
|
||||
assert(0 == cc[JS_PROMISE_HOOK_AFTER]);
|
||||
assert(2 == cc[JS_PROMISE_HOOK_RESOLVE]);
|
||||
assert(!JS_IsJobPending(rt));
|
||||
}
|
||||
memset(&promise_hook_state, 0, sizeof(promise_hook_state));
|
||||
{
|
||||
// module with promise chain
|
||||
static const char code[] =
|
||||
"globalThis.count = 0;"
|
||||
"globalThis.actual = undefined;" // set by promise_hook_cb
|
||||
"globalThis.expected = new Promise(resolve => resolve());"
|
||||
"expected.then(_ => count++)";
|
||||
JSValue ret = JS_Eval(ctx, code, strlen(code), "<input>", JS_EVAL_TYPE_MODULE);
|
||||
assert(!JS_IsException(ret));
|
||||
assert(JS_IsPromise(ret));
|
||||
assert(JS_PROMISE_FULFILLED == JS_PromiseState(ctx, ret)); // outer module promise
|
||||
JS_FreeValue(ctx, ret);
|
||||
assert(4 == cc[JS_PROMISE_HOOK_INIT]);
|
||||
assert(0 == cc[JS_PROMISE_HOOK_BEFORE]);
|
||||
assert(0 == cc[JS_PROMISE_HOOK_AFTER]);
|
||||
assert(3 == cc[JS_PROMISE_HOOK_RESOLVE]);
|
||||
JSValue v = JS_GetPropertyStr(ctx, global_object, "count");
|
||||
assert(!JS_IsException(v));
|
||||
int32_t count;
|
||||
assert(0 == JS_ToInt32(ctx, &count, v));
|
||||
assert(0 == count);
|
||||
JS_FreeValue(ctx, v);
|
||||
assert(JS_IsJobPending(rt));
|
||||
assert(1 == JS_ExecutePendingJob(rt, &unused));
|
||||
assert(!JS_HasException(ctx));
|
||||
assert(4 == cc[JS_PROMISE_HOOK_INIT]);
|
||||
assert(0 == cc[JS_PROMISE_HOOK_BEFORE]);
|
||||
assert(0 == cc[JS_PROMISE_HOOK_AFTER]);
|
||||
assert(4 == cc[JS_PROMISE_HOOK_RESOLVE]);
|
||||
assert(!JS_IsJobPending(rt));
|
||||
v = JS_GetPropertyStr(ctx, global_object, "count");
|
||||
assert(!JS_IsException(v));
|
||||
assert(0 == JS_ToInt32(ctx, &count, v));
|
||||
assert(1 == count);
|
||||
JS_FreeValue(ctx, v);
|
||||
JSValue actual = JS_GetPropertyStr(ctx, global_object, "actual");
|
||||
JSValue expected = JS_GetPropertyStr(ctx, global_object, "expected");
|
||||
assert(!JS_IsException(actual));
|
||||
assert(!JS_IsException(expected));
|
||||
assert(JS_IsSameValue(ctx, actual, expected));
|
||||
JS_FreeValue(ctx, actual);
|
||||
JS_FreeValue(ctx, expected);
|
||||
}
|
||||
memset(&promise_hook_state, 0, sizeof(promise_hook_state));
|
||||
{
|
||||
// module with thenable; fires before and after hooks
|
||||
static const char code[] =
|
||||
"new Promise(resolve => resolve({then(resolve){ resolve() }}))";
|
||||
JSValue ret = JS_Eval(ctx, code, strlen(code), "<input>", JS_EVAL_TYPE_MODULE);
|
||||
assert(!JS_IsException(ret));
|
||||
assert(JS_IsPromise(ret));
|
||||
assert(JS_PROMISE_FULFILLED == JS_PromiseState(ctx, ret)); // outer module promise
|
||||
JS_FreeValue(ctx, ret);
|
||||
assert(3 == cc[JS_PROMISE_HOOK_INIT]);
|
||||
assert(0 == cc[JS_PROMISE_HOOK_BEFORE]);
|
||||
assert(0 == cc[JS_PROMISE_HOOK_AFTER]);
|
||||
assert(2 == cc[JS_PROMISE_HOOK_RESOLVE]);
|
||||
assert(JS_IsJobPending(rt));
|
||||
assert(1 == JS_ExecutePendingJob(rt, &unused));
|
||||
assert(!JS_HasException(ctx));
|
||||
assert(3 == cc[JS_PROMISE_HOOK_INIT]);
|
||||
assert(1 == cc[JS_PROMISE_HOOK_BEFORE]);
|
||||
assert(1 == cc[JS_PROMISE_HOOK_AFTER]);
|
||||
assert(3 == cc[JS_PROMISE_HOOK_RESOLVE]);
|
||||
assert(!JS_IsJobPending(rt));
|
||||
}
|
||||
JS_FreeValue(ctx, global_object);
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
}
|
||||
|
||||
static void dump_memory_usage(void)
|
||||
{
|
||||
JSMemoryUsage stats;
|
||||
|
||||
JSRuntime *rt = NULL;
|
||||
JSContext *ctx = NULL;
|
||||
|
||||
rt = JS_NewRuntime();
|
||||
ctx = JS_NewContext(rt);
|
||||
|
||||
//JS_SetDumpFlags(rt, JS_DUMP_PROMISE);
|
||||
|
||||
static const char code[] =
|
||||
"globalThis.count = 0;"
|
||||
"globalThis.actual = undefined;" // set by promise_hook_cb
|
||||
"globalThis.expected = new Promise(resolve => resolve());"
|
||||
"expected.then(_ => count++)";
|
||||
|
||||
JSValue evalVal = JS_Eval(ctx, code, strlen(code), "<input>", 0);
|
||||
JS_FreeValue(ctx, evalVal);
|
||||
|
||||
FILE *temp = tmpfile();
|
||||
assert(temp != NULL);
|
||||
JS_ComputeMemoryUsage(rt, &stats);
|
||||
JS_DumpMemoryUsage(temp, &stats, rt);
|
||||
// JS_DumpMemoryUsage(stdout, &stats, rt);
|
||||
fclose(temp);
|
||||
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
}
|
||||
|
||||
static void new_errors(void)
|
||||
{
|
||||
typedef struct {
|
||||
const char name[16];
|
||||
JSValue (*func)(JSContext *, const char *, ...);
|
||||
} Entry;
|
||||
static const Entry entries[] = {
|
||||
{"Error", JS_NewPlainError},
|
||||
{"InternalError", JS_NewInternalError},
|
||||
{"RangeError", JS_NewRangeError},
|
||||
{"ReferenceError", JS_NewReferenceError},
|
||||
{"SyntaxError", JS_NewSyntaxError},
|
||||
{"TypeError", JS_NewTypeError},
|
||||
};
|
||||
const Entry *e;
|
||||
|
||||
JSRuntime *rt = JS_NewRuntime();
|
||||
JSContext *ctx = JS_NewContext(rt);
|
||||
for (e = entries; e < endof(entries); e++) {
|
||||
JSValue obj = (*e->func)(ctx, "the %s", "needle");
|
||||
assert(!JS_IsException(obj));
|
||||
assert(JS_IsObject(obj));
|
||||
assert(JS_IsError(obj));
|
||||
const char *haystack = JS_ToCString(ctx, obj);
|
||||
char needle[256];
|
||||
snprintf(needle, sizeof(needle), "%s: the needle", e->name);
|
||||
assert(strstr(haystack, needle));
|
||||
JS_FreeCString(ctx, haystack);
|
||||
JSValue stack = JS_GetPropertyStr(ctx, obj, "stack");
|
||||
assert(!JS_IsException(stack));
|
||||
assert(JS_IsString(stack));
|
||||
JS_FreeValue(ctx, stack);
|
||||
JS_FreeValue(ctx, obj);
|
||||
}
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
}
|
||||
|
||||
static int gop_get_own_property(JSContext *ctx, JSPropertyDescriptor *desc,
|
||||
JSValueConst obj, JSAtom prop)
|
||||
{
|
||||
const char *name;
|
||||
int found;
|
||||
|
||||
found = 0;
|
||||
name = JS_AtomToCString(ctx, prop);
|
||||
if (!name)
|
||||
return -1;
|
||||
if (!strcmp(name, "answer")) {
|
||||
found = 1;
|
||||
*desc = (JSPropertyDescriptor){
|
||||
.value = JS_NewInt32(ctx, 42),
|
||||
.flags = JS_PROP_C_W_E | JS_PROP_HAS_VALUE,
|
||||
};
|
||||
}
|
||||
JS_FreeCString(ctx, name);
|
||||
return found;
|
||||
}
|
||||
|
||||
static void global_object_prototype(void)
|
||||
{
|
||||
static const char code[] = "answer";
|
||||
JSValue global_object, proto, ret;
|
||||
JSClassID class_id;
|
||||
JSRuntime *rt;
|
||||
JSContext *ctx;
|
||||
int32_t answer;
|
||||
int res;
|
||||
|
||||
{
|
||||
rt = JS_NewRuntime();
|
||||
ctx = JS_NewContext(rt);
|
||||
proto = JS_NewObject(ctx);
|
||||
assert(JS_IsObject(proto));
|
||||
JSCFunctionListEntry prop = JS_PROP_INT32_DEF("answer", 42, JS_PROP_C_W_E);
|
||||
JS_SetPropertyFunctionList(ctx, proto, &prop, 1);
|
||||
global_object = JS_GetGlobalObject(ctx);
|
||||
res = JS_SetPrototype(ctx, global_object, proto);
|
||||
assert(res == true);
|
||||
JS_FreeValue(ctx, global_object);
|
||||
JS_FreeValue(ctx, proto);
|
||||
ret = eval(ctx, code);
|
||||
assert(!JS_IsException(ret));
|
||||
assert(JS_IsNumber(ret));
|
||||
res = JS_ToInt32(ctx, &answer, ret);
|
||||
assert(res == 0);
|
||||
assert(answer == 42);
|
||||
JS_FreeValue(ctx, ret);
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
}
|
||||
{
|
||||
JSClassExoticMethods exotic = (JSClassExoticMethods){
|
||||
.get_own_property = gop_get_own_property,
|
||||
};
|
||||
JSClassDef def = (JSClassDef){
|
||||
.class_name = "Global Object",
|
||||
.exotic = &exotic,
|
||||
};
|
||||
rt = JS_NewRuntime();
|
||||
class_id = 0;
|
||||
JS_NewClassID(rt, &class_id);
|
||||
res = JS_NewClass(rt, class_id, &def);
|
||||
assert(res == 0);
|
||||
ctx = JS_NewContext(rt);
|
||||
proto = JS_NewObjectClass(ctx, class_id);
|
||||
assert(JS_IsObject(proto));
|
||||
global_object = JS_GetGlobalObject(ctx);
|
||||
res = JS_SetPrototype(ctx, global_object, proto);
|
||||
assert(res == true);
|
||||
JS_FreeValue(ctx, global_object);
|
||||
JS_FreeValue(ctx, proto);
|
||||
ret = eval(ctx, code);
|
||||
assert(!JS_IsException(ret));
|
||||
assert(JS_IsNumber(ret));
|
||||
res = JS_ToInt32(ctx, &answer, ret);
|
||||
assert(res == 0);
|
||||
assert(answer == 42);
|
||||
JS_FreeValue(ctx, ret);
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/quickjs-ng/quickjs/issues/1178
|
||||
static void slice_string_tocstring(void)
|
||||
{
|
||||
JSRuntime *rt = JS_NewRuntime();
|
||||
JSContext *ctx = JS_NewContext(rt);
|
||||
JSValue ret = eval(ctx, "'.'.repeat(16384).slice(1, -1)");
|
||||
assert(!JS_IsException(ret));
|
||||
assert(JS_IsString(ret));
|
||||
const char *str = JS_ToCString(ctx, ret);
|
||||
assert(strlen(str) == 16382);
|
||||
JS_FreeCString(ctx, str);
|
||||
JS_FreeValue(ctx, ret);
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
cfunctions();
|
||||
sync_call();
|
||||
async_call();
|
||||
async_call_stack_overflow();
|
||||
raw_context_global_var();
|
||||
is_array();
|
||||
module_serde();
|
||||
runtime_cstring_free();
|
||||
two_byte_string();
|
||||
weak_map_gc_check();
|
||||
promise_hook();
|
||||
dump_memory_usage();
|
||||
new_errors();
|
||||
global_object_prototype();
|
||||
slice_string_tocstring();
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/* File generated automatically by the QuickJS-ng compiler. */
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
const uint32_t qjsc_builtin_array_fromasync_size = 826;
|
||||
|
||||
const uint8_t qjsc_builtin_array_fromasync[826] = {
|
||||
0x15, 0x0d, 0x01, 0x1a, 0x61, 0x73, 0x79, 0x6e,
|
||||
0x63, 0x49, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f,
|
||||
0x72, 0x01, 0x10, 0x69, 0x74, 0x65, 0x72, 0x61,
|
||||
0x74, 0x6f, 0x72, 0x01, 0x12, 0x61, 0x72, 0x72,
|
||||
0x61, 0x79, 0x4c, 0x69, 0x6b, 0x65, 0x01, 0x0a,
|
||||
0x6d, 0x61, 0x70, 0x46, 0x6e, 0x01, 0x0e, 0x74,
|
||||
0x68, 0x69, 0x73, 0x41, 0x72, 0x67, 0x01, 0x0c,
|
||||
0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x01, 0x02,
|
||||
0x69, 0x01, 0x1a, 0x69, 0x73, 0x43, 0x6f, 0x6e,
|
||||
0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x6f, 0x72,
|
||||
0x01, 0x08, 0x73, 0x79, 0x6e, 0x63, 0x01, 0x0c,
|
||||
0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x01, 0x08,
|
||||
0x69, 0x74, 0x65, 0x72, 0x01, 0x1c, 0x6e, 0x6f,
|
||||
0x74, 0x20, 0x61, 0x20, 0x66, 0x75, 0x6e, 0x63,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x01, 0x08, 0x63, 0x61,
|
||||
0x6c, 0x6c, 0x0c, 0x00, 0x02, 0x00, 0xa2, 0x01,
|
||||
0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x04, 0x01,
|
||||
0xa4, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x43, 0x02,
|
||||
0x01, 0x00, 0x05, 0x00, 0x05, 0x01, 0x00, 0x01,
|
||||
0x03, 0x05, 0xaa, 0x02, 0x00, 0x01, 0x40, 0xa0,
|
||||
0x03, 0x00, 0x01, 0x40, 0xc6, 0x03, 0x00, 0x01,
|
||||
0x40, 0xcc, 0x01, 0x00, 0x01, 0x40, 0xc8, 0x03,
|
||||
0x00, 0x01, 0x40, 0x0c, 0x60, 0x02, 0x01, 0xf8,
|
||||
0x01, 0x03, 0x0e, 0x01, 0x06, 0x05, 0x00, 0x86,
|
||||
0x04, 0x11, 0xca, 0x03, 0x00, 0x01, 0x00, 0xcc,
|
||||
0x03, 0x00, 0x01, 0x00, 0xce, 0x03, 0x00, 0x01,
|
||||
0x00, 0xca, 0x03, 0x01, 0xff, 0xff, 0xff, 0xff,
|
||||
0x0f, 0x20, 0xcc, 0x03, 0x01, 0x01, 0x20, 0xce,
|
||||
0x03, 0x01, 0x02, 0x20, 0xd0, 0x03, 0x02, 0x00,
|
||||
0x20, 0xd2, 0x03, 0x02, 0x04, 0x20, 0xd4, 0x03,
|
||||
0x02, 0x05, 0x20, 0xd6, 0x03, 0x02, 0x06, 0x20,
|
||||
0xd8, 0x03, 0x02, 0x07, 0x20, 0x64, 0x06, 0x08,
|
||||
0x20, 0x82, 0x01, 0x07, 0x09, 0x20, 0xda, 0x03,
|
||||
0x0a, 0x08, 0x30, 0x82, 0x01, 0x0d, 0x0b, 0x20,
|
||||
0xd4, 0x01, 0x0d, 0x0c, 0x20, 0x10, 0x00, 0x01,
|
||||
0x00, 0xa0, 0x03, 0x01, 0x03, 0xc6, 0x03, 0x02,
|
||||
0x03, 0xc8, 0x03, 0x04, 0x03, 0xaa, 0x02, 0x00,
|
||||
0x03, 0xcc, 0x01, 0x03, 0x03, 0x08, 0xc4, 0x0d,
|
||||
0x62, 0x02, 0x00, 0x62, 0x01, 0x00, 0x62, 0x00,
|
||||
0x00, 0xd3, 0xcb, 0xd4, 0x11, 0xf4, 0xec, 0x08,
|
||||
0x0e, 0x39, 0x46, 0x00, 0x00, 0x00, 0xdc, 0xcc,
|
||||
0xd5, 0x11, 0xf4, 0xec, 0x08, 0x0e, 0x39, 0x46,
|
||||
0x00, 0x00, 0x00, 0xdd, 0xcd, 0x62, 0x07, 0x00,
|
||||
0x62, 0x06, 0x00, 0x62, 0x05, 0x00, 0x62, 0x04,
|
||||
0x00, 0x62, 0x03, 0x00, 0xd4, 0x39, 0x46, 0x00,
|
||||
0x00, 0x00, 0xb0, 0xec, 0x16, 0xd4, 0x98, 0x04,
|
||||
0x1b, 0x00, 0x00, 0x00, 0xb0, 0xec, 0x0c, 0xdf,
|
||||
0x11, 0x04, 0xee, 0x00, 0x00, 0x00, 0x21, 0x01,
|
||||
0x00, 0x30, 0x06, 0xce, 0xb6, 0xc4, 0x04, 0xc3,
|
||||
0x0d, 0xf7, 0xc4, 0x05, 0x09, 0xc4, 0x06, 0xd3,
|
||||
0xe0, 0x48, 0xc4, 0x07, 0x63, 0x07, 0x00, 0x07,
|
||||
0xad, 0xec, 0x0f, 0x0a, 0x11, 0x64, 0x06, 0x00,
|
||||
0x0e, 0xd3, 0xe1, 0x48, 0x11, 0x64, 0x07, 0x00,
|
||||
0x0e, 0x63, 0x07, 0x00, 0x07, 0xad, 0x6a, 0xa6,
|
||||
0x00, 0x00, 0x00, 0x62, 0x08, 0x00, 0x06, 0x11,
|
||||
0xf4, 0xed, 0x0c, 0x71, 0x43, 0x32, 0x00, 0x00,
|
||||
0x00, 0xc4, 0x08, 0x0e, 0xee, 0x05, 0x0e, 0xd3,
|
||||
0xee, 0xf2, 0x63, 0x08, 0x00, 0x8e, 0x11, 0xed,
|
||||
0x03, 0x0e, 0xb6, 0x11, 0x64, 0x08, 0x00, 0x0e,
|
||||
0x63, 0x05, 0x00, 0xec, 0x0c, 0xc3, 0x0d, 0x11,
|
||||
0x63, 0x08, 0x00, 0x21, 0x01, 0x00, 0xee, 0x06,
|
||||
0xe2, 0x63, 0x08, 0x00, 0xf1, 0x11, 0x64, 0x03,
|
||||
0x00, 0x0e, 0x63, 0x04, 0x00, 0x63, 0x08, 0x00,
|
||||
0xa7, 0x6a, 0x2a, 0x01, 0x00, 0x00, 0x62, 0x09,
|
||||
0x00, 0xd3, 0x63, 0x04, 0x00, 0x48, 0xc4, 0x09,
|
||||
0x63, 0x06, 0x00, 0xec, 0x0a, 0x63, 0x09, 0x00,
|
||||
0x8c, 0x11, 0x64, 0x09, 0x00, 0x0e, 0xd4, 0xec,
|
||||
0x17, 0xd4, 0x43, 0xef, 0x00, 0x00, 0x00, 0xd5,
|
||||
0x63, 0x09, 0x00, 0x63, 0x04, 0x00, 0x24, 0x03,
|
||||
0x00, 0x8c, 0x11, 0x64, 0x09, 0x00, 0x0e, 0x5f,
|
||||
0x04, 0x00, 0x63, 0x03, 0x00, 0x63, 0x04, 0x00,
|
||||
0x92, 0x64, 0x04, 0x00, 0x0b, 0x63, 0x09, 0x00,
|
||||
0x4d, 0x41, 0x00, 0x00, 0x00, 0x0a, 0x4d, 0x3e,
|
||||
0x00, 0x00, 0x00, 0x0a, 0x4d, 0x3f, 0x00, 0x00,
|
||||
0x00, 0xf3, 0x0e, 0xee, 0x9e, 0x62, 0x0a, 0x00,
|
||||
0x63, 0x07, 0x00, 0x43, 0xef, 0x00, 0x00, 0x00,
|
||||
0xd3, 0x24, 0x01, 0x00, 0xc4, 0x0a, 0x63, 0x05,
|
||||
0x00, 0xec, 0x09, 0xc3, 0x0d, 0x11, 0x21, 0x00,
|
||||
0x00, 0xee, 0x03, 0xe2, 0xf0, 0x11, 0x64, 0x03,
|
||||
0x00, 0x0e, 0x6d, 0x8c, 0x00, 0x00, 0x00, 0x62,
|
||||
0x0c, 0x00, 0x62, 0x0b, 0x00, 0x06, 0x11, 0xf4,
|
||||
0xed, 0x13, 0x71, 0x43, 0x41, 0x00, 0x00, 0x00,
|
||||
0xc4, 0x0b, 0x43, 0x6a, 0x00, 0x00, 0x00, 0xc4,
|
||||
0x0c, 0x0e, 0xee, 0x10, 0x0e, 0x63, 0x0a, 0x00,
|
||||
0x43, 0x6b, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00,
|
||||
0x8c, 0xee, 0xe0, 0x63, 0x0c, 0x00, 0xed, 0x4e,
|
||||
0x63, 0x06, 0x00, 0xec, 0x0a, 0x63, 0x0b, 0x00,
|
||||
0x8c, 0x11, 0x64, 0x0b, 0x00, 0x0e, 0xd4, 0xec,
|
||||
0x17, 0xd4, 0x43, 0xef, 0x00, 0x00, 0x00, 0xd5,
|
||||
0x63, 0x0b, 0x00, 0x63, 0x04, 0x00, 0x24, 0x03,
|
||||
0x00, 0x8c, 0x11, 0x64, 0x0b, 0x00, 0x0e, 0x5f,
|
||||
0x04, 0x00, 0x63, 0x03, 0x00, 0x63, 0x04, 0x00,
|
||||
0x92, 0x64, 0x04, 0x00, 0x0b, 0x63, 0x0b, 0x00,
|
||||
0x4d, 0x41, 0x00, 0x00, 0x00, 0x0a, 0x4d, 0x3e,
|
||||
0x00, 0x00, 0x00, 0x0a, 0x4d, 0x3f, 0x00, 0x00,
|
||||
0x00, 0xf3, 0x0e, 0xee, 0x83, 0x0e, 0x06, 0x6e,
|
||||
0x0d, 0x00, 0x00, 0x00, 0x0e, 0xee, 0x1e, 0x6e,
|
||||
0x05, 0x00, 0x00, 0x00, 0x30, 0x63, 0x0a, 0x00,
|
||||
0x42, 0x06, 0x00, 0x00, 0x00, 0xec, 0x0d, 0x63,
|
||||
0x0a, 0x00, 0x43, 0x06, 0x00, 0x00, 0x00, 0x24,
|
||||
0x00, 0x00, 0x0e, 0x6f, 0x63, 0x03, 0x00, 0x63,
|
||||
0x04, 0x00, 0x44, 0x32, 0x00, 0x00, 0x00, 0x63,
|
||||
0x03, 0x00, 0x2f, 0xc1, 0x00, 0x28, 0xc1, 0x00,
|
||||
0xcf, 0x28,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
;(function(Array, TypeError, asyncIterator, defineProperty, iterator) {
|
||||
"use strict" // result.length=i should throw if .length is not writable
|
||||
return async function fromAsync(arrayLike, mapFn=undefined, thisArg=undefined) {
|
||||
if (mapFn !== undefined && typeof mapFn !== "function") throw new TypeError("not a function")
|
||||
let result, i = 0, isConstructor = typeof this === "function"
|
||||
let sync = false, method = arrayLike[asyncIterator]
|
||||
if (method == null) sync = true, method = arrayLike[iterator]
|
||||
if (method == null) {
|
||||
let {length} = arrayLike
|
||||
length = +length || 0
|
||||
result = isConstructor ? new this(length) : Array(length)
|
||||
while (i < length) {
|
||||
let value = arrayLike[i]
|
||||
if (sync) value = await value
|
||||
if (mapFn) value = await mapFn.call(thisArg, value, i)
|
||||
defineProperty(result, i++, {value, configurable: true, writable: true})
|
||||
}
|
||||
} else {
|
||||
const iter = method.call(arrayLike)
|
||||
result = isConstructor ? new this() : Array()
|
||||
try {
|
||||
for (;;) {
|
||||
let {value, done} = await iter.next()
|
||||
if (done) break
|
||||
if (sync) value = await value
|
||||
if (mapFn) value = await mapFn.call(thisArg, value, i)
|
||||
defineProperty(result, i++, {value, configurable: true, writable: true})
|
||||
}
|
||||
} finally {
|
||||
if (iter.return) iter.return()
|
||||
}
|
||||
}
|
||||
result.length = i
|
||||
return result
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,17 @@
|
||||
// note: file is not actually compiled, only checked for C syntax errors
|
||||
#include "quickjs.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
JSRuntime *rt = JS_NewRuntime();
|
||||
JSContext *ctx = JS_NewContext(rt);
|
||||
JS_FreeValue(ctx, JS_NAN);
|
||||
JS_FreeValue(ctx, JS_UNDEFINED);
|
||||
JS_FreeValue(ctx, JS_NewFloat64(ctx, 42));
|
||||
// not a legal way of using JS_MKPTR but this is here
|
||||
// to have the compiler syntax-check its definition
|
||||
JS_FreeValue(ctx, JS_MKPTR(JS_TAG_UNINITIALIZED, 0));
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
return 0;
|
||||
}
|
||||
+1342
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,660 @@
|
||||
/*
|
||||
* C utilities
|
||||
*
|
||||
* Copyright (c) 2017 Fabrice Bellard
|
||||
* Copyright (c) 2018 Charlie Gordon
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef CUTILS_H
|
||||
#define CUTILS_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <winsock2.h>
|
||||
#include <malloc.h>
|
||||
#define alloca _alloca
|
||||
#define ssize_t ptrdiff_t
|
||||
#endif
|
||||
#if defined(__APPLE__)
|
||||
#include <malloc/malloc.h>
|
||||
#elif defined(__linux__) || defined(__ANDROID__) || defined(__CYGWIN__) || defined(__GLIBC__)
|
||||
#include <malloc.h>
|
||||
#elif defined(__FreeBSD__)
|
||||
#include <malloc_np.h>
|
||||
#elif defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#if !defined(_WIN32) && !defined(EMSCRIPTEN) && !defined(__wasi__)
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
#if !defined(_WIN32)
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
# define likely(x) (x)
|
||||
# define unlikely(x) (x)
|
||||
# define force_inline __forceinline
|
||||
# define no_inline __declspec(noinline)
|
||||
# define __maybe_unused
|
||||
# define __attribute__(x)
|
||||
# define __attribute(x)
|
||||
#else
|
||||
# define likely(x) __builtin_expect(!!(x), 1)
|
||||
# define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
# define force_inline inline __attribute__((always_inline))
|
||||
# define no_inline __attribute__((noinline))
|
||||
# define __maybe_unused __attribute__((unused))
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
#include <math.h>
|
||||
#define INF INFINITY
|
||||
#define NEG_INF -INFINITY
|
||||
#else
|
||||
#define INF (1.0/0.0)
|
||||
#define NEG_INF (-1.0/0.0)
|
||||
#endif
|
||||
|
||||
#ifndef offsetof
|
||||
#define offsetof(type, field) ((size_t) &((type *)0)->field)
|
||||
#endif
|
||||
#ifndef countof
|
||||
#define countof(x) (sizeof(x) / sizeof((x)[0]))
|
||||
#ifndef endof
|
||||
#define endof(x) ((x) + countof(x))
|
||||
#endif
|
||||
#endif
|
||||
#ifndef container_of
|
||||
/* return the pointer of type 'type *' containing 'ptr' as field 'member' */
|
||||
#define container_of(ptr, type, member) ((type *)((uint8_t *)(ptr) - offsetof(type, member)))
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) || defined(__cplusplus)
|
||||
#define minimum_length(n) n
|
||||
#else
|
||||
#define minimum_length(n) static n
|
||||
#endif
|
||||
|
||||
/* Borrowed from Folly */
|
||||
#ifndef JS_PRINTF_FORMAT
|
||||
#ifdef _MSC_VER
|
||||
#include <sal.h>
|
||||
#define JS_PRINTF_FORMAT _Printf_format_string_
|
||||
#define JS_PRINTF_FORMAT_ATTR(format_param, dots_param)
|
||||
#else
|
||||
#define JS_PRINTF_FORMAT
|
||||
#if !defined(__clang__) && defined(__GNUC__)
|
||||
#define JS_PRINTF_FORMAT_ATTR(format_param, dots_param) \
|
||||
__attribute__((format(gnu_printf, format_param, dots_param)))
|
||||
#else
|
||||
#define JS_PRINTF_FORMAT_ATTR(format_param, dots_param) \
|
||||
__attribute__((format(printf, format_param, dots_param)))
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(PATH_MAX)
|
||||
# define JS__PATH_MAX PATH_MAX
|
||||
#elif defined(_WIN32)
|
||||
# define JS__PATH_MAX 32767
|
||||
#else
|
||||
# define JS__PATH_MAX 8192
|
||||
#endif
|
||||
|
||||
void js__pstrcpy(char *buf, int buf_size, const char *str);
|
||||
char *js__pstrcat(char *buf, int buf_size, const char *s);
|
||||
int js__strstart(const char *str, const char *val, const char **ptr);
|
||||
int js__has_suffix(const char *str, const char *suffix);
|
||||
|
||||
static inline uint8_t is_be(void) {
|
||||
union {
|
||||
uint16_t a;
|
||||
uint8_t b;
|
||||
} u = { 0x100 };
|
||||
return u.b;
|
||||
}
|
||||
|
||||
static inline int max_int(int a, int b)
|
||||
{
|
||||
if (a > b)
|
||||
return a;
|
||||
else
|
||||
return b;
|
||||
}
|
||||
|
||||
static inline int min_int(int a, int b)
|
||||
{
|
||||
if (a < b)
|
||||
return a;
|
||||
else
|
||||
return b;
|
||||
}
|
||||
|
||||
static inline uint32_t max_uint32(uint32_t a, uint32_t b)
|
||||
{
|
||||
if (a > b)
|
||||
return a;
|
||||
else
|
||||
return b;
|
||||
}
|
||||
|
||||
static inline uint32_t min_uint32(uint32_t a, uint32_t b)
|
||||
{
|
||||
if (a < b)
|
||||
return a;
|
||||
else
|
||||
return b;
|
||||
}
|
||||
|
||||
static inline int64_t max_int64(int64_t a, int64_t b)
|
||||
{
|
||||
if (a > b)
|
||||
return a;
|
||||
else
|
||||
return b;
|
||||
}
|
||||
|
||||
static inline int64_t min_int64(int64_t a, int64_t b)
|
||||
{
|
||||
if (a < b)
|
||||
return a;
|
||||
else
|
||||
return b;
|
||||
}
|
||||
|
||||
/* WARNING: undefined if a = 0 */
|
||||
static inline int clz32(unsigned int a)
|
||||
{
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
unsigned long index;
|
||||
_BitScanReverse(&index, a);
|
||||
return 31 - index;
|
||||
#else
|
||||
return __builtin_clz(a);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* WARNING: undefined if a = 0 */
|
||||
static inline int clz64(uint64_t a)
|
||||
{
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
#if INTPTR_MAX == INT64_MAX
|
||||
unsigned long index;
|
||||
_BitScanReverse64(&index, a);
|
||||
return 63 - index;
|
||||
#else
|
||||
if (a >> 32)
|
||||
return clz32((unsigned)(a >> 32));
|
||||
else
|
||||
return clz32((unsigned)a) + 32;
|
||||
#endif
|
||||
#else
|
||||
return __builtin_clzll(a);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* WARNING: undefined if a = 0 */
|
||||
static inline int ctz32(unsigned int a)
|
||||
{
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
unsigned long index;
|
||||
_BitScanForward(&index, a);
|
||||
return index;
|
||||
#else
|
||||
return __builtin_ctz(a);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* WARNING: undefined if a = 0 */
|
||||
static inline int ctz64(uint64_t a)
|
||||
{
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
unsigned long index;
|
||||
_BitScanForward64(&index, a);
|
||||
return index;
|
||||
#else
|
||||
return __builtin_ctzll(a);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline uint64_t get_u64(const uint8_t *tab)
|
||||
{
|
||||
uint64_t v;
|
||||
memcpy(&v, tab, sizeof(v));
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline int64_t get_i64(const uint8_t *tab)
|
||||
{
|
||||
int64_t v;
|
||||
memcpy(&v, tab, sizeof(v));
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline void put_u64(uint8_t *tab, uint64_t val)
|
||||
{
|
||||
memcpy(tab, &val, sizeof(val));
|
||||
}
|
||||
|
||||
static inline uint32_t get_u32(const uint8_t *tab)
|
||||
{
|
||||
uint32_t v;
|
||||
memcpy(&v, tab, sizeof(v));
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline int32_t get_i32(const uint8_t *tab)
|
||||
{
|
||||
int32_t v;
|
||||
memcpy(&v, tab, sizeof(v));
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline void put_u32(uint8_t *tab, uint32_t val)
|
||||
{
|
||||
memcpy(tab, &val, sizeof(val));
|
||||
}
|
||||
|
||||
static inline uint32_t get_u16(const uint8_t *tab)
|
||||
{
|
||||
uint16_t v;
|
||||
memcpy(&v, tab, sizeof(v));
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline int32_t get_i16(const uint8_t *tab)
|
||||
{
|
||||
int16_t v;
|
||||
memcpy(&v, tab, sizeof(v));
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline void put_u16(uint8_t *tab, uint16_t val)
|
||||
{
|
||||
memcpy(tab, &val, sizeof(val));
|
||||
}
|
||||
|
||||
static inline uint32_t get_u8(const uint8_t *tab)
|
||||
{
|
||||
return *tab;
|
||||
}
|
||||
|
||||
static inline int32_t get_i8(const uint8_t *tab)
|
||||
{
|
||||
return (int8_t)*tab;
|
||||
}
|
||||
|
||||
static inline void put_u8(uint8_t *tab, uint8_t val)
|
||||
{
|
||||
*tab = val;
|
||||
}
|
||||
|
||||
#ifndef bswap16
|
||||
static inline uint16_t bswap16(uint16_t x)
|
||||
{
|
||||
return (x >> 8) | (x << 8);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef bswap32
|
||||
static inline uint32_t bswap32(uint32_t v)
|
||||
{
|
||||
return ((v & 0xff000000) >> 24) | ((v & 0x00ff0000) >> 8) |
|
||||
((v & 0x0000ff00) << 8) | ((v & 0x000000ff) << 24);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef bswap64
|
||||
static inline uint64_t bswap64(uint64_t v)
|
||||
{
|
||||
return ((v & ((uint64_t)0xff << (7 * 8))) >> (7 * 8)) |
|
||||
((v & ((uint64_t)0xff << (6 * 8))) >> (5 * 8)) |
|
||||
((v & ((uint64_t)0xff << (5 * 8))) >> (3 * 8)) |
|
||||
((v & ((uint64_t)0xff << (4 * 8))) >> (1 * 8)) |
|
||||
((v & ((uint64_t)0xff << (3 * 8))) << (1 * 8)) |
|
||||
((v & ((uint64_t)0xff << (2 * 8))) << (3 * 8)) |
|
||||
((v & ((uint64_t)0xff << (1 * 8))) << (5 * 8)) |
|
||||
((v & ((uint64_t)0xff << (0 * 8))) << (7 * 8));
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void inplace_bswap16(uint8_t *tab) {
|
||||
put_u16(tab, bswap16(get_u16(tab)));
|
||||
}
|
||||
|
||||
static inline void inplace_bswap32(uint8_t *tab) {
|
||||
put_u32(tab, bswap32(get_u32(tab)));
|
||||
}
|
||||
|
||||
static inline double fromfp16(uint16_t v) {
|
||||
double d, s;
|
||||
int e;
|
||||
if ((v & 0x7C00) == 0x7C00) {
|
||||
d = (v & 0x3FF) ? NAN : INFINITY;
|
||||
} else {
|
||||
d = (v & 0x3FF) / 1024.;
|
||||
e = (v & 0x7C00) >> 10;
|
||||
if (e == 0) {
|
||||
e = -14;
|
||||
} else {
|
||||
d += 1;
|
||||
e -= 15;
|
||||
}
|
||||
d = scalbn(d, e);
|
||||
}
|
||||
s = (v & 0x8000) ? -1.0 : 1.0;
|
||||
return d * s;
|
||||
}
|
||||
|
||||
static inline uint16_t tofp16(double d) {
|
||||
uint16_t f, s;
|
||||
double t;
|
||||
int e;
|
||||
s = 0;
|
||||
if (copysign(1, d) < 0) { // preserve sign when |d| is negative zero
|
||||
d = -d;
|
||||
s = 0x8000;
|
||||
}
|
||||
if (isinf(d))
|
||||
return s | 0x7C00;
|
||||
if (isnan(d))
|
||||
return s | 0x7C01;
|
||||
if (d == 0)
|
||||
return s | 0;
|
||||
d = 2 * frexp(d, &e);
|
||||
e--;
|
||||
if (e > 15)
|
||||
return s | 0x7C00; // out of range, return +/-infinity
|
||||
if (e < -25) {
|
||||
d = 0;
|
||||
e = 0;
|
||||
} else if (e < -14) {
|
||||
d = scalbn(d, e + 14);
|
||||
e = 0;
|
||||
} else {
|
||||
d -= 1;
|
||||
e += 15;
|
||||
}
|
||||
d *= 1024.;
|
||||
f = (uint16_t)d;
|
||||
t = d - f;
|
||||
if (t < 0.5)
|
||||
goto done;
|
||||
if (t == 0.5)
|
||||
if ((f & 1) == 0)
|
||||
goto done;
|
||||
// adjust for rounding
|
||||
if (++f == 1024) {
|
||||
f = 0;
|
||||
if (++e == 31)
|
||||
return s | 0x7C00; // out of range, return +/-infinity
|
||||
}
|
||||
done:
|
||||
return s | (e << 10) | f;
|
||||
}
|
||||
|
||||
static inline int isfp16nan(uint16_t v) {
|
||||
return (v & 0x7FFF) > 0x7C00;
|
||||
}
|
||||
|
||||
static inline int isfp16zero(uint16_t v) {
|
||||
return (v & 0x7FFF) == 0;
|
||||
}
|
||||
|
||||
/* XXX: should take an extra argument to pass slack information to the caller */
|
||||
typedef void *DynBufReallocFunc(void *opaque, void *ptr, size_t size);
|
||||
|
||||
typedef struct DynBuf {
|
||||
uint8_t *buf;
|
||||
size_t size;
|
||||
size_t allocated_size;
|
||||
bool error; /* true if a memory allocation error occurred */
|
||||
DynBufReallocFunc *realloc_func;
|
||||
void *opaque; /* for realloc_func */
|
||||
} DynBuf;
|
||||
|
||||
void dbuf_init(DynBuf *s);
|
||||
void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func);
|
||||
int dbuf_realloc(DynBuf *s, size_t new_size);
|
||||
int dbuf_write(DynBuf *s, size_t offset, const void *data, size_t len);
|
||||
int dbuf_put(DynBuf *s, const void *data, size_t len);
|
||||
int dbuf_put_self(DynBuf *s, size_t offset, size_t len);
|
||||
int dbuf_putc(DynBuf *s, uint8_t c);
|
||||
int dbuf_putstr(DynBuf *s, const char *str);
|
||||
static inline int dbuf_put_u16(DynBuf *s, uint16_t val)
|
||||
{
|
||||
return dbuf_put(s, (uint8_t *)&val, 2);
|
||||
}
|
||||
static inline int dbuf_put_u32(DynBuf *s, uint32_t val)
|
||||
{
|
||||
return dbuf_put(s, (uint8_t *)&val, 4);
|
||||
}
|
||||
static inline int dbuf_put_u64(DynBuf *s, uint64_t val)
|
||||
{
|
||||
return dbuf_put(s, (uint8_t *)&val, 8);
|
||||
}
|
||||
int JS_PRINTF_FORMAT_ATTR(2, 3) dbuf_printf(DynBuf *s, JS_PRINTF_FORMAT const char *fmt, ...);
|
||||
void dbuf_free(DynBuf *s);
|
||||
static inline bool dbuf_error(DynBuf *s) {
|
||||
return s->error;
|
||||
}
|
||||
static inline void dbuf_set_error(DynBuf *s)
|
||||
{
|
||||
s->error = true;
|
||||
}
|
||||
|
||||
/*---- UTF-8 and UTF-16 handling ----*/
|
||||
|
||||
#define UTF8_CHAR_LEN_MAX 4
|
||||
|
||||
enum {
|
||||
UTF8_PLAIN_ASCII = 0, // 7-bit ASCII plain text
|
||||
UTF8_NON_ASCII = 1, // has non ASCII code points (8-bit or more)
|
||||
UTF8_HAS_16BIT = 2, // has 16-bit code points
|
||||
UTF8_HAS_NON_BMP1 = 4, // has non-BMP1 code points, needs UTF-16 surrogate pairs
|
||||
UTF8_HAS_ERRORS = 8, // has encoding errors
|
||||
};
|
||||
int utf8_scan(const char *buf, size_t len, size_t *plen);
|
||||
size_t utf8_encode_len(uint32_t c);
|
||||
size_t utf8_encode(uint8_t buf[minimum_length(UTF8_CHAR_LEN_MAX)], uint32_t c);
|
||||
uint32_t utf8_decode_len(const uint8_t *p, size_t max_len, const uint8_t **pp);
|
||||
uint32_t utf8_decode(const uint8_t *p, const uint8_t **pp);
|
||||
size_t utf8_decode_buf8(uint8_t *dest, size_t dest_len, const char *src, size_t src_len);
|
||||
size_t utf8_decode_buf16(uint16_t *dest, size_t dest_len, const char *src, size_t src_len);
|
||||
size_t utf8_encode_buf8(char *dest, size_t dest_len, const uint8_t *src, size_t src_len);
|
||||
size_t utf8_encode_buf16(char *dest, size_t dest_len, const uint16_t *src, size_t src_len);
|
||||
|
||||
static inline bool is_surrogate(uint32_t c)
|
||||
{
|
||||
return (c >> 11) == (0xD800 >> 11); // 0xD800-0xDFFF
|
||||
}
|
||||
|
||||
static inline bool is_hi_surrogate(uint32_t c)
|
||||
{
|
||||
return (c >> 10) == (0xD800 >> 10); // 0xD800-0xDBFF
|
||||
}
|
||||
|
||||
static inline bool is_lo_surrogate(uint32_t c)
|
||||
{
|
||||
return (c >> 10) == (0xDC00 >> 10); // 0xDC00-0xDFFF
|
||||
}
|
||||
|
||||
static inline uint32_t get_hi_surrogate(uint32_t c)
|
||||
{
|
||||
return (c >> 10) - (0x10000 >> 10) + 0xD800;
|
||||
}
|
||||
|
||||
static inline uint32_t get_lo_surrogate(uint32_t c)
|
||||
{
|
||||
return (c & 0x3FF) | 0xDC00;
|
||||
}
|
||||
|
||||
static inline uint32_t from_surrogate(uint32_t hi, uint32_t lo)
|
||||
{
|
||||
return 65536 + 1024 * (hi & 1023) + (lo & 1023);
|
||||
}
|
||||
|
||||
static inline int from_hex(int c)
|
||||
{
|
||||
if (c >= '0' && c <= '9')
|
||||
return c - '0';
|
||||
else if (c >= 'A' && c <= 'F')
|
||||
return c - 'A' + 10;
|
||||
else if (c >= 'a' && c <= 'f')
|
||||
return c - 'a' + 10;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline uint8_t is_upper_ascii(uint8_t c) {
|
||||
return c >= 'A' && c <= 'Z';
|
||||
}
|
||||
|
||||
static inline uint8_t to_upper_ascii(uint8_t c) {
|
||||
return c >= 'a' && c <= 'z' ? c - 'a' + 'A' : c;
|
||||
}
|
||||
|
||||
void rqsort(void *base, size_t nmemb, size_t size,
|
||||
int (*cmp)(const void *, const void *, void *),
|
||||
void *arg);
|
||||
|
||||
static inline uint64_t float64_as_uint64(double d)
|
||||
{
|
||||
union {
|
||||
double d;
|
||||
uint64_t u64;
|
||||
} u;
|
||||
u.d = d;
|
||||
return u.u64;
|
||||
}
|
||||
|
||||
static inline double uint64_as_float64(uint64_t u64)
|
||||
{
|
||||
union {
|
||||
double d;
|
||||
uint64_t u64;
|
||||
} u;
|
||||
u.u64 = u64;
|
||||
return u.d;
|
||||
}
|
||||
|
||||
int64_t js__gettimeofday_us(void);
|
||||
uint64_t js__hrtime_ns(void);
|
||||
|
||||
static inline size_t js__malloc_usable_size(const void *ptr)
|
||||
{
|
||||
#if defined(__APPLE__)
|
||||
return malloc_size(ptr);
|
||||
#elif defined(_WIN32)
|
||||
return _msize((void *)ptr);
|
||||
#elif defined(__linux__) || defined(__ANDROID__) || defined(__CYGWIN__) || defined(__FreeBSD__) || defined(__GLIBC__)
|
||||
return malloc_usable_size((void *)ptr);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int js_exepath(char* buffer, size_t* size);
|
||||
|
||||
/* Cross-platform threading APIs. */
|
||||
|
||||
#if defined(EMSCRIPTEN) || defined(__wasi__)
|
||||
|
||||
#define JS_HAVE_THREADS 0
|
||||
|
||||
#else
|
||||
|
||||
#define JS_HAVE_THREADS 1
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define JS_ONCE_INIT INIT_ONCE_STATIC_INIT
|
||||
typedef INIT_ONCE js_once_t;
|
||||
typedef CRITICAL_SECTION js_mutex_t;
|
||||
typedef CONDITION_VARIABLE js_cond_t;
|
||||
typedef HANDLE js_thread_t;
|
||||
#else
|
||||
#define JS_ONCE_INIT PTHREAD_ONCE_INIT
|
||||
typedef pthread_once_t js_once_t;
|
||||
typedef pthread_mutex_t js_mutex_t;
|
||||
typedef pthread_cond_t js_cond_t;
|
||||
typedef pthread_t js_thread_t;
|
||||
#endif
|
||||
|
||||
void js_once(js_once_t *guard, void (*callback)(void));
|
||||
|
||||
void js_mutex_init(js_mutex_t *mutex);
|
||||
void js_mutex_destroy(js_mutex_t *mutex);
|
||||
void js_mutex_lock(js_mutex_t *mutex);
|
||||
void js_mutex_unlock(js_mutex_t *mutex);
|
||||
|
||||
void js_cond_init(js_cond_t *cond);
|
||||
void js_cond_destroy(js_cond_t *cond);
|
||||
void js_cond_signal(js_cond_t *cond);
|
||||
void js_cond_broadcast(js_cond_t *cond);
|
||||
void js_cond_wait(js_cond_t *cond, js_mutex_t *mutex);
|
||||
int js_cond_timedwait(js_cond_t *cond, js_mutex_t *mutex, uint64_t timeout);
|
||||
|
||||
enum {
|
||||
JS_THREAD_CREATE_DETACHED = 1,
|
||||
};
|
||||
|
||||
// creates threads with 2 MB stacks (glibc default)
|
||||
int js_thread_create(js_thread_t *thrd, void (*start)(void *), void *arg,
|
||||
int flags);
|
||||
int js_thread_join(js_thread_t thrd);
|
||||
|
||||
#endif /* !defined(EMSCRIPTEN) && !defined(__wasi__) */
|
||||
|
||||
// JS requires strict rounding behavior. Turn on 64-bits double precision
|
||||
// and disable x87 80-bits extended precision for intermediate floating-point
|
||||
// results. 0x300 is extended precision, 0x200 is double precision.
|
||||
// Note that `*&cw` in the asm constraints looks redundant but isn't.
|
||||
#if defined(__i386__) && !defined(_MSC_VER)
|
||||
#define JS_X87_FPCW_SAVE_AND_ADJUST(cw) \
|
||||
unsigned short cw; \
|
||||
__asm__ __volatile__("fnstcw %0" : "=m"(*&cw)); \
|
||||
do { \
|
||||
unsigned short t = 0x200 | (cw & ~0x300); \
|
||||
__asm__ __volatile__("fldcw %0" : /*empty*/ : "m"(*&t)); \
|
||||
} while (0)
|
||||
#define JS_X87_FPCW_RESTORE(cw) \
|
||||
__asm__ __volatile__("fldcw %0" : /*empty*/ : "m"(*&cw))
|
||||
#else
|
||||
#define JS_X87_FPCW_SAVE_AND_ADJUST(cw)
|
||||
#define JS_X87_FPCW_RESTORE(cw)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" { */
|
||||
#endif
|
||||
|
||||
#endif /* CUTILS_H */
|
||||
@@ -0,0 +1,2 @@
|
||||
// note: file is not actually compiled, only checked for C++ syntax errors
|
||||
#include "ctest.c"
|
||||
@@ -0,0 +1,20 @@
|
||||
# Dependencies
|
||||
/node_modules
|
||||
|
||||
# Production
|
||||
/build
|
||||
|
||||
# Generated files
|
||||
.docusaurus
|
||||
.cache-loader
|
||||
|
||||
# Misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
@@ -0,0 +1 @@
|
||||
18
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
|
||||
};
|
||||
@@ -0,0 +1,63 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
# Building
|
||||
|
||||
QuickJS uses [CMake] as its main build system, with an additional helper [Makefile].
|
||||
|
||||
:::note
|
||||
Windows users will need to run the CMake commands manually.
|
||||
:::
|
||||
|
||||
## Getting the source
|
||||
|
||||
```bash
|
||||
git clone https://github.com/quickjs-ng/quickjs.git
|
||||
cd quickjs
|
||||
```
|
||||
|
||||
## Compiling everything
|
||||
|
||||
```bash
|
||||
make
|
||||
```
|
||||
|
||||
This will build the `qjs` and `qjsc` executables and other test tools. Head over [here](./cli) for
|
||||
instructions on how to use them.
|
||||
|
||||
## Amalgamated builds
|
||||
|
||||
The amalgamated build rolls individual source files into a single big file.
|
||||
It's a good choice for projects that want to use QuickJS without CMake.
|
||||
|
||||
Download quickjs-amalgam.zip from [Releases](https://github.com/quickjs-ng/quickjs/releases)
|
||||
|
||||
To enable the std, os and bjson modules, compile quickjs-amalgam.c with
|
||||
`-DQJS_BUILD_LIBC`.
|
||||
|
||||
## Debug builds
|
||||
|
||||
```bash
|
||||
make debug
|
||||
```
|
||||
|
||||
This will produce a debug build without optimizations, suitable for developers.
|
||||
|
||||
## Running test262
|
||||
|
||||
```bash
|
||||
make test262
|
||||
```
|
||||
|
||||
This will run the test262 suite.
|
||||
|
||||
```bash
|
||||
make test262-update
|
||||
```
|
||||
|
||||
This will run the test262 suite and update the error / pass report, useful after
|
||||
implementing a new feature that would alter the result of the test suite.
|
||||
|
||||
[CMake]: https://cmake.org
|
||||
[Makefile]: https://www.gnu.org/software/make/
|
||||
@@ -0,0 +1,130 @@
|
||||
---
|
||||
sidebar_position: 4
|
||||
---
|
||||
|
||||
# The qjs and qjsc CLI tools
|
||||
|
||||
## `qjs` - The QuickJS JavaScript interpreter
|
||||
|
||||
The `qjs` executable runs the JavaScript interpreter. It includes a simple standard
|
||||
library and REPL.
|
||||
|
||||
```
|
||||
$ qjs
|
||||
usage: qjs [options] [file [args]]
|
||||
-h --help list options
|
||||
-e --eval EXPR evaluate EXPR
|
||||
-i --interactive go to interactive mode
|
||||
-m --module load as ES6 module (default=autodetect)
|
||||
--script load as ES6 script (default=autodetect)
|
||||
-I --include file include an additional file
|
||||
--std make 'std', 'os' and 'bjson' available to script
|
||||
-T --trace trace memory allocation
|
||||
-d --dump dump the memory usage stats
|
||||
-D --dump-flags flags for dumping debug data (see DUMP_* defines)
|
||||
-c --compile FILE compile the given JS file as a standalone executable
|
||||
-o --out FILE output file for standalone executables
|
||||
--exe select the executable to use as the base, defaults to the current one
|
||||
--memory-limit n limit the memory usage to 'n' Kbytes
|
||||
--stack-size n limit the stack size to 'n' Kbytes
|
||||
--unhandled-rejection dump unhandled promise rejections
|
||||
-q --quit just instantiate the interpreter and quit
|
||||
```
|
||||
|
||||
The following dump flags are supported:
|
||||
|
||||
```
|
||||
DUMP_BYTECODE_FINAL 0x01 /* dump pass 3 final byte code */
|
||||
DUMP_BYTECODE_PASS2 0x02 /* dump pass 2 code */
|
||||
DUMP_BYTECODE_PASS1 0x04 /* dump pass 1 code */
|
||||
DUMP_BYTECODE_HEX 0x10 /* dump bytecode in hex */
|
||||
DUMP_BYTECODE_PC2LINE 0x20 /* dump line number table */
|
||||
DUMP_BYTECODE_STACK 0x40 /* dump compute_stack_size */
|
||||
DUMP_BYTECODE_STEP 0x80 /* dump executed bytecode */
|
||||
DUMP_READ_OBJECT 0x100 /* dump the marshalled objects at load time */
|
||||
DUMP_FREE 0x200 /* dump every object free */
|
||||
DUMP_GC 0x400 /* dump the occurrence of the automatic GC */
|
||||
DUMP_GC_FREE 0x800 /* dump objects freed by the GC */
|
||||
DUMP_MODULE_RESOLVE 0x1000 /* dump module resolution steps */
|
||||
DUMP_PROMISE 0x2000 /* dump promise steps */
|
||||
DUMP_LEAKS 0x4000 /* dump leaked objects and strings in JS_FreeRuntime */
|
||||
DUMP_ATOM_LEAKS 0x8000 /* dump leaked atoms in JS_FreeRuntime */
|
||||
DUMP_MEM 0x10000 /* dump memory usage in JS_FreeRuntime */
|
||||
DUMP_OBJECTS 0x20000 /* dump objects in JS_FreeRuntime */
|
||||
DUMP_ATOMS 0x40000 /* dump atoms in JS_FreeRuntime */
|
||||
DUMP_SHAPES 0x80000 /* dump shapes in JS_FreeRuntime */
|
||||
```
|
||||
|
||||
### Creating standalone executables
|
||||
|
||||
With the `qjs` CLI it's possible to create standalone executables that will bundle the given JavaScript file
|
||||
alongside the binary.
|
||||
|
||||
```
|
||||
$ qjs -c app.js -o app --exe qjs
|
||||
```
|
||||
|
||||
The resulting `app` binary will have the same runtime dependencies as the `qjs` binary. This is acomplished
|
||||
by compiling the target JavaScript file to bytecode and adding it a copy of the executable, with a little
|
||||
trailer to help locate it. `--exe` expects the absolute path to `qjs`, e.g., `~/bin/qjs` or `$HOME/bin/qjs`.
|
||||
|
||||
Rather than using the current executable, it's possible to use the `--exe` switch to create standalone
|
||||
executables for other platforms.
|
||||
|
||||
No JavaScript bundling is performed, the specified JS file cannot depend on other files. A bundler such
|
||||
as `esbuild` can be used to generate an app bundle which can then be turned into the executable.
|
||||
|
||||
```
|
||||
npx esbuild my-app/index.js \
|
||||
--bundle \
|
||||
--outfile=app.js \
|
||||
--external:qjs:* \
|
||||
--minify \
|
||||
--target=es2023 \
|
||||
--platform=neutral \
|
||||
--format=esm \
|
||||
--main-fields=main,module
|
||||
```
|
||||
|
||||
## `qjsc` - The QuickJS JavaScript compiler
|
||||
|
||||
The `qjsc` executable runs the JavaScript compiler, it can generate bytecode from
|
||||
source files which can then be embedded in an executable, or it can generate the necessary
|
||||
scaffolding to build a C application which embeds QuickJS.
|
||||
|
||||
```
|
||||
$ qjsc
|
||||
usage: qjsc [options] [files]
|
||||
|
||||
options are:
|
||||
-b output raw bytecode instead of C code
|
||||
-e output main() and bytecode in a C file
|
||||
-o output set the output filename
|
||||
-n script_name set the script name (as used in stack traces)
|
||||
-N cname set the C name of the generated data
|
||||
-m compile as JavaScript module (default=autodetect)
|
||||
-D module_name compile a dynamically loaded module or worker
|
||||
-M module_name[,cname] add initialization code for an external C module
|
||||
-p prefix set the prefix of the generated C names
|
||||
-s strip the source code, specify twice to also strip debug info
|
||||
-S n set the maximum stack size to 'n' bytes (default=262144)
|
||||
```
|
||||
|
||||
Here is an example on how to create a standalone executable that embeds QuickJS
|
||||
and the `examples/hello.js` JavaScript file:
|
||||
|
||||
```bash
|
||||
# Make sure you are in the QuickJS source directory.
|
||||
$ cc hello.c cutils.c dtoa.c libregexp.c libunicode.c quickjs.c quickjs-libc.c -I. -o hello
|
||||
```
|
||||
|
||||
The resulting binary `hello` will be in the current directory.
|
||||
|
||||
```bash
|
||||
$ ./hello
|
||||
Hello World
|
||||
```
|
||||
|
||||
:::note
|
||||
See the ["Creating standalone executables"](#creating-standalone-executables) section for a simpler way.
|
||||
:::
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"label": "Developer Guide",
|
||||
"position": 6,
|
||||
"link": {
|
||||
"type": "generated-index"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
# API Reference
|
||||
|
||||
WIP.
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
# Internals
|
||||
|
||||
## Bytecode
|
||||
|
||||
The compiler generates bytecode directly with no intermediate
|
||||
representation such as a parse tree, hence it is very fast. Several
|
||||
optimizations passes are done over the generated bytecode.
|
||||
|
||||
A stack-based bytecode was chosen because it is simple and generates
|
||||
compact code.
|
||||
|
||||
For each function, the maximum stack size is computed at compile time so that
|
||||
no runtime stack overflow tests are needed.
|
||||
|
||||
A separate compressed line number table is maintained for the debug
|
||||
information.
|
||||
|
||||
Access to closure variables is optimized and is almost as fast as local
|
||||
variables.
|
||||
|
||||
Direct `eval` in strict mode is optimized.
|
||||
|
||||
## Runtime
|
||||
|
||||
### Strings
|
||||
|
||||
Strings are stored either as an 8 bit or a 16 bit array of
|
||||
characters. Hence random access to characters is always fast.
|
||||
|
||||
The C API provides functions to convert JavaScript Strings to C UTF-8 encoded
|
||||
strings. The most common case where the JavaScript string contains
|
||||
only ASCII characters involves no copying.
|
||||
|
||||
### Objects
|
||||
|
||||
The object shapes (object prototype, property names and flags) are shared
|
||||
between objects to save memory.
|
||||
|
||||
Arrays with no holes (except at the end of the array) are optimized.
|
||||
|
||||
TypedArray accesses are optimized.
|
||||
|
||||
### Atoms
|
||||
|
||||
Object property names and some strings are stored as Atoms (unique
|
||||
strings) to save memory and allow fast comparison. Atoms are
|
||||
represented as a 32 bit integer. Half of the atom range is reserved for
|
||||
immediate integer literals from 0 to 2^31-1.
|
||||
|
||||
### Numbers
|
||||
|
||||
Numbers are represented either as 32-bit signed integers or 64-bit IEEE-754
|
||||
floating point values. Most operations have fast paths for the 32-bit
|
||||
integer case.
|
||||
|
||||
### Garbage collection
|
||||
|
||||
Reference counting is used to free objects automatically and
|
||||
deterministically. A separate cycle removal pass is done when the allocated
|
||||
memory becomes too large. The cycle removal algorithm only uses the
|
||||
reference counts and the object content, so no explicit garbage
|
||||
collection roots need to be manipulated in the C code.
|
||||
|
||||
### JSValue
|
||||
|
||||
It is a JavaScript value which can be a primitive type (such as
|
||||
Number, String, ...) or an Object. NaN boxing is used in the 32-bit version
|
||||
to store 64-bit floating point numbers. The representation is
|
||||
optimized so that 32-bit integers and reference counted values can be
|
||||
efficiently tested.
|
||||
|
||||
In 64-bit code, JSValue are 128-bit large and no NaN boxing is used. The
|
||||
rationale is that in 64-bit code memory usage is less critical.
|
||||
|
||||
In both cases (32 or 64 bits), JSValue exactly fits two CPU registers,
|
||||
so it can be efficiently returned by C functions.
|
||||
|
||||
### Function call
|
||||
|
||||
The engine is optimized so that function calls are fast. The system
|
||||
stack holds the JavaScript parameters and local variables.
|
||||
|
||||
### RegExp
|
||||
|
||||
A specific regular expression engine was developed. It is both small
|
||||
and efficient and supports all the ES2020+ features including the
|
||||
Unicode properties. As the JavaScript compiler, it directly generates
|
||||
bytecode without a parse tree.
|
||||
|
||||
Backtracking with an explicit stack is used so that there is no
|
||||
recursion on the system stack. Simple quantifiers are specifically
|
||||
optimized to avoid recursions.
|
||||
|
||||
Infinite recursions coming from quantifiers with empty terms are
|
||||
avoided.
|
||||
|
||||
The full regexp library weighs about 15 KiB (x86 code), excluding the
|
||||
Unicode library.
|
||||
|
||||
### Unicode
|
||||
|
||||
A specific Unicode library was developed so that there is no
|
||||
dependency on an external large Unicode library such as ICU. All the
|
||||
Unicode tables are compressed while keeping a reasonable access
|
||||
speed.
|
||||
|
||||
The library supports case conversion, Unicode normalization, Unicode
|
||||
script queries, Unicode general category queries and all Unicode
|
||||
binary properties.
|
||||
|
||||
The full Unicode library weighs about 45 KiB (x86 code).
|
||||
|
||||
### BigInt
|
||||
|
||||
BigInt is implemented with the [libbf](https://bellard.org/libbf) library.
|
||||
It weights about 90 KiB (x86 code) and provides arbitrary precision IEEE 754 floating
|
||||
point operations and transcendental functions with exact rounding.
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# The QuickJS C API
|
||||
|
||||
The C API was designed to be simple and efficient. The C API is
|
||||
defined in the header `quickjs.h`.
|
||||
|
||||
## Runtime and contexts
|
||||
|
||||
`JSRuntime` represents a JavaScript runtime corresponding to an
|
||||
object heap. Several runtimes can exist at the same time but they
|
||||
cannot exchange objects. Inside a given runtime, no multi-threading is
|
||||
supported.
|
||||
|
||||
`JSContext` represents a JavaScript context (or Realm). Each
|
||||
JSContext has its own global objects and system objects. There can be
|
||||
several JSContexts per JSRuntime and they can share objects, similar
|
||||
to frames of the same origin sharing JavaScript objects in a
|
||||
web browser.
|
||||
|
||||
## JSValue
|
||||
|
||||
`JSValue` represents a JavaScript value which can be a primitive
|
||||
type or an object. Reference counting is used, so it is important to
|
||||
explicitly duplicate (`JS_DupValue()`, increment the reference
|
||||
count) or free (`JS_FreeValue()`, decrement the reference count)
|
||||
JSValues.
|
||||
|
||||
## C functions
|
||||
|
||||
C functions can be created with
|
||||
`JS_NewCFunction()`. `JS_SetPropertyFunctionList()` is a
|
||||
shortcut to easily add functions, setters and getters properties to a
|
||||
given object.
|
||||
|
||||
Unlike other embedded JavaScript engines, there is no implicit stack,
|
||||
so C functions get their parameters as normal C parameters. As a
|
||||
general rule, C functions take constant `JSValue`s as parameters
|
||||
(so they don't need to free them) and return a newly allocated (=live)
|
||||
`JSValue`.
|
||||
|
||||
## Exceptions
|
||||
|
||||
Most C functions can return a JavaScript exception. It
|
||||
must be explicitly tested and handled by the C code. The specific
|
||||
`JSValue` `JS_EXCEPTION` indicates that an exception
|
||||
occurred. The actual exception object is stored in the
|
||||
`JSContext` and can be retrieved with `JS_GetException()`.
|
||||
|
||||
## Script evaluation
|
||||
|
||||
Use `JS_Eval()` to evaluate a script or module source.
|
||||
|
||||
If the script or module was compiled to bytecode with `qjsc`, it
|
||||
can be evaluated by calling `js_std_eval_binary()`. The advantage
|
||||
is that no compilation is needed so it is faster and smaller because
|
||||
the compiler can be removed from the executable if no `eval` is
|
||||
required.
|
||||
|
||||
Note: the bytecode format is linked to a given QuickJS
|
||||
version. Moreover, no security check is done before its
|
||||
execution. Hence the bytecode should not be loaded from untrusted
|
||||
sources.
|
||||
|
||||
## JS Classes
|
||||
|
||||
C opaque data can be attached to a JavaScript object. The type of the
|
||||
C opaque data is determined with the class ID (`JSClassID`) of
|
||||
the object. Hence the first step is to register a new class ID and JS
|
||||
class (`JS_NewClassID()`, `JS_NewClass()`). Then you can
|
||||
create objects of this class with `JS_NewObjectClass()` and get or
|
||||
set the C opaque point with `JS_GetOpaque()` / `JS_SetOpaque()`.
|
||||
|
||||
When defining a new JS class, it is possible to declare a finalizer
|
||||
which is called when the object is destroyed. The finalizer should be
|
||||
used to release C resources. It is invalid to execute JS code from
|
||||
it. A `gc_mark` method can be provided so that the cycle removal
|
||||
algorithm can find the other objects referenced by this object. Other
|
||||
methods are available to define exotic object behaviors.
|
||||
|
||||
The Class ID are allocated per-runtime. The
|
||||
`JSClass` are allocated per `JSRuntime`. `JS_SetClassProto()`
|
||||
is used to define a prototype for a given class in a given
|
||||
`JSContext`. `JS_NewObjectClass()` sets this prototype in the
|
||||
created object.
|
||||
|
||||
Examples are available in `quickjs-libc.c`.
|
||||
|
||||
## C Modules
|
||||
|
||||
Native ES6 modules are supported and can be dynamically or statically
|
||||
linked. The standard library `quickjs-libc.c` is a good example
|
||||
of a native module.
|
||||
|
||||
## Memory handling
|
||||
|
||||
Use `JS_SetMemoryLimit()` to set a global memory allocation limit
|
||||
to a given `JSRuntime`.
|
||||
|
||||
Custom memory allocation functions can be provided with `JS_NewRuntime2()`.
|
||||
|
||||
The maximum system stack size can be set with `JS_SetMaxStackSize()`.
|
||||
|
||||
## Execution timeout and interrupts
|
||||
|
||||
Use `JS_SetInterruptHandler()` to set a callback which is
|
||||
regularly called by the engine when it is executing code. This
|
||||
callback can be used to implement an execution timeout.
|
||||
|
||||
It is used by the command line interpreter to implement a
|
||||
`Ctrl-C` handler.
|
||||
@@ -0,0 +1,68 @@
|
||||
# Differences with bellard/quickjs
|
||||
|
||||
This project aims to be a drop-in replacement for those already using QuickJS.
|
||||
Minimal API changes might be necessary.
|
||||
|
||||
## Community development
|
||||
|
||||
NG is developed in the open, interacting with the wider community and through
|
||||
these interactions many improvements have already been made, including the incorporation
|
||||
of patches previously maintained in other forks.
|
||||
|
||||
Each PR is reviewed, iterated on, and merged in GitHub.
|
||||
|
||||
To date, NG has had over 40 distinct contributors and over 400 PRs.
|
||||
|
||||
## Consistent release cadence
|
||||
|
||||
As the project moves forward, a steady cadence of releases has been maintained, with an
|
||||
average of a new release every 2 months.
|
||||
|
||||
## Testing
|
||||
|
||||
Since its inception testing has been a focus. Each PR is tested in over 50 configurations,
|
||||
involving different operating systems, build types and sanitizers.
|
||||
|
||||
The `test262` suite is also ran for every change.
|
||||
|
||||
## Cross-platform support
|
||||
|
||||
In order to better support other platforms such as Windows the build system was
|
||||
changed to use [CMake].
|
||||
|
||||
In addition, Windows is treated as a first class citizen, with the addition of support
|
||||
for the MSVC compiler.
|
||||
|
||||
[CMake]: https://cmake.org/
|
||||
|
||||
## Performance
|
||||
|
||||
While being an interpreter limits the performance in comparison with other engines which
|
||||
use a JIT, several significant performance improvements have been made:
|
||||
|
||||
- Opcode fusion
|
||||
- Polymorphic inline caching
|
||||
- Memory allocation improvements
|
||||
- Improved parse speeds
|
||||
|
||||
## New ECMAScript APIs
|
||||
|
||||
The main focus of NG is to deliver state-of-the-art JavaScript features. Typically once they
|
||||
are stable (stage 4) but sometimes even at earlier stages. Here is a non-exhaustive list
|
||||
of ES features present in NG:
|
||||
|
||||
- Resizable ArrayBuffer
|
||||
- Float16Array
|
||||
- WeakRef
|
||||
- FinalizationRegistry
|
||||
- Iterator Helpers
|
||||
- Promise.try
|
||||
- Error.isError
|
||||
- Set operations
|
||||
|
||||
Some non-standard but widely used APIs have also been added:
|
||||
|
||||
- V8's [stack trace API](https://v8.dev/docs/stack-trace-api)
|
||||
- `Error.captureStackTrace`
|
||||
- `Error.prepareStackTrace`
|
||||
- `Error.stackTraceLimit`
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
sidebar_position: 7
|
||||
---
|
||||
|
||||
# ECMAScript Features
|
||||
|
||||
QuickJS aims to support the latest available ECMAScript features once they hit the spec.
|
||||
|
||||
Progress on _test262_ compliance can be checked [here](https://test262.fyi/#|qjs_ng).
|
||||
|
||||
Due to size constraints it is unlikely QuickJS will ever support the [Intl](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl) APIs.
|
||||
@@ -0,0 +1,34 @@
|
||||
---
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
# Installation
|
||||
|
||||
Installing QuickJS is simple, and we provide several ways to do so.
|
||||
|
||||
|
||||
## Build from source
|
||||
|
||||
If you built it from source as outlined in [building](./building) you can just run:
|
||||
|
||||
```bash
|
||||
make install
|
||||
```
|
||||
|
||||
and it will be installed in your system. The default installation path is `/usr/local`.
|
||||
|
||||
|
||||
## Using a prebuilt binary
|
||||
|
||||
Each [release on GitHub] includes binaries for several systems and architectures.
|
||||
|
||||
|
||||
## Using jsvu
|
||||
|
||||
As of version 2.2.0 of `jsvu`, QuickJS-ng will be installed when the `quickjs` engine is requested.
|
||||
|
||||
```bash
|
||||
npm install jsvu -g
|
||||
```
|
||||
|
||||
[release on GitHub]: https://github.com/quickjs-ng/quickjs/releases
|
||||
@@ -0,0 +1,33 @@
|
||||
---
|
||||
slug: /
|
||||
sidebar_position: 1
|
||||
sidebar_label: Welcome
|
||||
---
|
||||
|
||||
# Welcome to QuickJS-NG
|
||||
|
||||
QuickJS is a small and embeddable JavaScript engine. It aims to support the latest
|
||||
[ECMAScript] specification.
|
||||
|
||||
This project is a _fork_ of the [original QuickJS project] by Fabrice Bellard and Charlie Gordon, after it went dormant, with the intent of reigniting its development.
|
||||
|
||||
This project is focused on (but not limited to):
|
||||
|
||||
- Community development
|
||||
- Testing
|
||||
- Cross-platform support
|
||||
- ES features
|
||||
|
||||
You can check the differences with the original project [here.](./diff)
|
||||
|
||||
:::note
|
||||
This site is under construction, the entire API is not yet documented.
|
||||
:::
|
||||
|
||||
## Getting Started
|
||||
|
||||
Head over to [building](./building) if you want to build QuickJS from source or [installation](./installation)
|
||||
for installing it from prebuilt binaries.
|
||||
|
||||
[ECMAScript]: https://tc39.es/ecma262/
|
||||
[original QuickJS project]: https://bellard.org/quickjs
|
||||
@@ -0,0 +1,44 @@
|
||||
# Projects using NG
|
||||
|
||||
Here is a list of projects currently using, supporting or migrating to QuickJS-NG.
|
||||
If you want yours to be listed here, please open a PR!
|
||||
|
||||
## [txiki.js](https://github.com/saghul/txiki.js)
|
||||
|
||||
A tiny JavaScript runtime.
|
||||
|
||||
## [radare2](https://github.com/radareorg/radare2)
|
||||
|
||||
Reverse engineering framework.
|
||||
|
||||
## [rquickjs](https://github.com/DelSkayn/rquickjs)
|
||||
|
||||
High level Rust bindings.
|
||||
|
||||
## [llrt](https://github.com/awslabs/llrt)
|
||||
|
||||
Lightweight JS runtime for serverless applications.
|
||||
|
||||
## [nx.js](https://github.com/TooTallNate/nx.js)
|
||||
|
||||
JavaScript runtime for Nintendo Switch homebrew applications.
|
||||
|
||||
## [quickjs-rusty](https://github.com/Icemic/quickjs-rusty)
|
||||
|
||||
Rust wrapper focus on embedding-ready and no-pain type conversion and interoperability.
|
||||
|
||||
## [GodotJS](https://github.com/godotjs/GodotJS)
|
||||
|
||||
This project adds TypeScript/JavaScript support for Godot 4.x. It supports multiple javascript runtimes, including QuickJS-NG.
|
||||
|
||||
## [quickjs_es_runtime](https://github.com/HiRoFa/quickjs_es_runtime)
|
||||
|
||||
Rust wrapper with typescript, modules, promises, async/await and much more.
|
||||
|
||||
## [Lua jsregexp](https://github.com/kmarius/jsregexp)
|
||||
|
||||
JavaScript regular expressions for Lua.
|
||||
|
||||
## [Edbrowse](https://edbrowse.org)
|
||||
|
||||
A combination editor, web-browser, and mail client that is 100% text based.
|
||||
@@ -0,0 +1,577 @@
|
||||
---
|
||||
sidebar_position: 5
|
||||
---
|
||||
|
||||
# Standard library
|
||||
|
||||
The standard libary is provided as part of the `qjs` executable and the `quickjs-libc.c` source file
|
||||
and it's not part of the core engine.
|
||||
|
||||
## Globals
|
||||
|
||||
### `argv0`
|
||||
|
||||
Provides the executable path.
|
||||
|
||||
### `scriptArgs`
|
||||
|
||||
Provides the command line arguments. The first argument is the script name.
|
||||
|
||||
### `print(...args)`
|
||||
|
||||
Print the arguments separated by spaces and a trailing newline.
|
||||
|
||||
### `console.log(...args)`
|
||||
|
||||
Same as `print()`.
|
||||
|
||||
### `navigator.userAgent`
|
||||
|
||||
Returns `quickjs-ng/<version>`.
|
||||
|
||||
### `gc()`
|
||||
|
||||
Shorthand for `std.gc()`.
|
||||
|
||||
## `qjs:bjson` module
|
||||
|
||||
### `bjson.write(obj, [flags])`
|
||||
|
||||
Serializes the given object into the QuickJS internal serialization format.
|
||||
Returns an ArrayBuffer with the serialized data.
|
||||
|
||||
Supported flags:
|
||||
|
||||
- `WRITE_OBJ_BYTECODE`: allow serializing functions and modules
|
||||
- `WRITE_OBJ_REFERENCE`: allow serializing object references
|
||||
- `WRITE_OBJ_SAB`: allow serializing SharedArrayBuffer instances
|
||||
- `WRITE_OBJ_STRIP_DEBUG`: strip debugging information when serializing
|
||||
- `WRITE_OBJ_STRIP_SOURCE`: strip the source information when serializing
|
||||
|
||||
### `bjson.read(buf, [pos], [len], [flags])`
|
||||
|
||||
De-serialize the given ArrayBuffer (in QuickJS internal serialization format) back into a JavaScript value.
|
||||
|
||||
Supported flags:
|
||||
|
||||
- `READ_OBJ_BYTECODE`: allow de-serializing functions and modules
|
||||
- `READ_OBJ_REFERENCE`: allow de-serializing object references
|
||||
- `READ_OBJ_SAB`: allow de-serializing SharedArrayBuffer instances
|
||||
|
||||
## `qjs:os` module
|
||||
|
||||
The `os` module provides Operating System specific functions:
|
||||
|
||||
- low level file access
|
||||
- signals
|
||||
- timers
|
||||
- basic asynchronous I/O
|
||||
- workers (threads)
|
||||
|
||||
The OS functions usually return 0 if OK or an OS specific negative
|
||||
error code.
|
||||
|
||||
### `open(filename, flags, mode = 0o666)`
|
||||
|
||||
Open a file. Return a handle or < 0 if error.
|
||||
|
||||
Supported flags:
|
||||
|
||||
- `O_RDONLY`
|
||||
- `O_WRONLY`
|
||||
- `O_RDWR`
|
||||
- `O_APPEND`
|
||||
- `O_CREAT`
|
||||
- `O_EXCL`
|
||||
- `O_TRUNC`
|
||||
|
||||
POSIX open flags.
|
||||
|
||||
- `O_TEXT`
|
||||
|
||||
(Windows specific). Open the file in text mode. The default is binary mode.
|
||||
|
||||
### `close(fd)`
|
||||
|
||||
Close the file handle `fd`.
|
||||
|
||||
### `seek(fd, offset, whence)`
|
||||
|
||||
Seek in the file. Use `std.SEEK_*` for
|
||||
`whence`. `offset` is either a number or a BigInt. If
|
||||
`offset` is a BigInt, a BigInt is returned too.
|
||||
|
||||
### `read(fd, buffer, offset, length)`
|
||||
|
||||
Read `length` bytes from the file handle `fd` to the
|
||||
ArrayBuffer `buffer` at byte position `offset`.
|
||||
Return the number of read bytes or < 0 if error.
|
||||
|
||||
### `write(fd, buffer, offset, length)`
|
||||
|
||||
Write `length` bytes to the file handle `fd` from the
|
||||
ArrayBuffer `buffer` at byte position `offset`.
|
||||
Return the number of written bytes or < 0 if error.
|
||||
|
||||
### `isatty(fd)`
|
||||
|
||||
Return `true` is `fd` is a TTY (terminal) handle.
|
||||
|
||||
### `ttyGetWinSize(fd)`
|
||||
|
||||
Return the TTY size as `[width, height]` or `null` if not available.
|
||||
|
||||
### `ttySetRaw(fd)`
|
||||
|
||||
Set the TTY in raw mode.
|
||||
|
||||
### `remove(filename)`
|
||||
|
||||
Remove a file. Return 0 if OK or `-errno`.
|
||||
|
||||
### `rename(oldname, newname)`
|
||||
|
||||
Rename a file. Return 0 if OK or `-errno`.
|
||||
|
||||
### `realpath(path)`
|
||||
|
||||
Return `[str, err]` where `str` is the canonicalized absolute
|
||||
pathname of `path` and `err` the error code.
|
||||
|
||||
### `getcwd()`
|
||||
|
||||
Return `[str, err]` where `str` is the current working directory
|
||||
and `err` the error code.
|
||||
|
||||
### `exePath()`
|
||||
|
||||
Returns the full path of the current executable or `undefined` if not available / supported.
|
||||
|
||||
### `chdir(path)`
|
||||
|
||||
Change the current directory. Return 0 if OK or `-errno`.
|
||||
|
||||
### `mkdir(path, mode = 0o777)`
|
||||
|
||||
Create a directory at `path`. Return 0 if OK or `-errno`.
|
||||
|
||||
### `stat(path)` / `lstat(path)`
|
||||
|
||||
Return `[obj, err]` where `obj` is an object containing the
|
||||
file status of `path`. `err` is the error code. The
|
||||
following fields are defined in `obj`: `dev`, `ino`, `mode`, `nlink`,
|
||||
`uid`, `gid`, `rdev`, `size`, `blocks`, `atime`, `mtime`, `ctime`. The times are
|
||||
specified in milliseconds since 1970. `lstat()` is the same as
|
||||
`stat()` excepts that it returns information about the link
|
||||
itself.
|
||||
|
||||
- `S_IFMT`
|
||||
- `S_IFIFO`
|
||||
- `S_IFCHR`
|
||||
- `S_IFDIR`
|
||||
- `S_IFBLK`
|
||||
- `S_IFREG`
|
||||
- `S_IFSOCK`
|
||||
- `S_IFLNK`
|
||||
- `S_ISGID`
|
||||
- `S_ISUID`
|
||||
|
||||
Constants to interpret the `mode` property returned by
|
||||
`stat()`. They have the same value as in the C system header
|
||||
`sys/stat.h`.
|
||||
|
||||
### `utimes(path, atime, mtime)`
|
||||
|
||||
Change the access and modification times of the file `path`. The
|
||||
times are specified in milliseconds since 1970. Return 0 if OK or `-errno`.
|
||||
|
||||
### `symlink(target, linkpath)`
|
||||
|
||||
Create a link at `linkpath` containing the string `target`. Return 0 if OK or `-errno`.
|
||||
|
||||
### `readlink(path)`
|
||||
|
||||
Return `[str, err]` where `str` is the link target and `err`
|
||||
the error code.
|
||||
|
||||
### `readdir(path)`
|
||||
|
||||
Return `[array, err]` where `array` is an array of strings
|
||||
containing the filenames of the directory `path`. `err` is
|
||||
the error code. `array` contains at least `"."` and `".."`
|
||||
if successful.
|
||||
|
||||
### `setReadHandler(fd, func)`
|
||||
|
||||
Add a read handler to the file handle `fd`. `func` is called
|
||||
each time there is data pending for `fd`. A single read handler
|
||||
per file handle is supported. Use `func = null` to remove the
|
||||
handler.
|
||||
|
||||
### `setWriteHandler(fd, func)`
|
||||
|
||||
Add a write handler to the file handle `fd`. `func` is
|
||||
called each time data can be written to `fd`. A single write
|
||||
handler per file handle is supported. Use `func = null` to remove
|
||||
the handler.
|
||||
|
||||
### `signal(signal, func)`
|
||||
|
||||
Call the function `func` when the signal `signal`
|
||||
happens. Only a single handler per signal number is supported. Use
|
||||
`null` to set the default handler or `undefined` to ignore
|
||||
the signal. Signal handlers can only be defined in the main thread.
|
||||
|
||||
- `SIGINT`
|
||||
- `SIGABRT`
|
||||
- `SIGFPE`
|
||||
- `SIGILL`
|
||||
- `SIGSEGV`
|
||||
- `SIGTERM`
|
||||
|
||||
POSIX signal numbers.
|
||||
|
||||
### `kill(pid, sig)`
|
||||
|
||||
Send the signal `sig` to the process `pid`.
|
||||
|
||||
### `exec(args[, options])`
|
||||
|
||||
Execute a process with the arguments `args`. `options` is an
|
||||
object containing optional parameters:
|
||||
|
||||
- `block` - Boolean (default = true). If true, wait until the process is
|
||||
terminated. In this case, `exec` return the exit code if positive
|
||||
or the negated signal number if the process was interrupted by a
|
||||
signal. If false, do not block and return the process id of the child.
|
||||
- `usePath` - Boolean (default = true). If true, the file is searched in the
|
||||
`PATH` environment variable.
|
||||
- `file` - String (default = `args[0]`). Set the file to be executed.
|
||||
- `cwd` - String. If present, set the working directory of the new process.
|
||||
- `stdin`, `stdout`, `stderr` - If present, set the handle in the child for stdin, stdout or stderr.
|
||||
- `env` - Object. If present, set the process environment from the object
|
||||
key-value pairs. Otherwise use the same environment as the current
|
||||
process.
|
||||
- `uid` - Integer. If present, the process uid with `setuid`.
|
||||
- `gid` - Integer. If present, the process gid with `setgid`.
|
||||
- `groups` - Array of integer. If present, the supplementary
|
||||
group IDs with `setgroup`.
|
||||
|
||||
### `waitpid(pid, options)`
|
||||
|
||||
`waitpid` Unix system call. Return the array `[ret, status]`.
|
||||
`ret` contains `-errno` in case of error.
|
||||
|
||||
- `WNOHANG`
|
||||
|
||||
Constant for the `options` argument of `waitpid`.
|
||||
|
||||
### `dup(fd)`
|
||||
|
||||
`dup` Unix system call.
|
||||
|
||||
### `dup2(oldfd, newfd)`
|
||||
|
||||
`dup2` Unix system call.
|
||||
|
||||
### `pipe()`
|
||||
|
||||
`pipe` Unix system call. Return two handles as `[read_fd, write_fd]` or null in case of error.
|
||||
|
||||
### `sleep(delay_ms)`
|
||||
|
||||
Sleep during `delay_ms` milliseconds.
|
||||
|
||||
### `sleepAsync(delay_ms)`
|
||||
|
||||
Asynchronouse sleep during `delay_ms` milliseconds. Returns a promise. Example:
|
||||
|
||||
```js
|
||||
await os.sleepAsync(500);
|
||||
```
|
||||
|
||||
### `setTimeout(func, delay)`
|
||||
|
||||
Call the function `func` after `delay` ms. Return a timer ID.
|
||||
|
||||
### `clearTimeout(id)`
|
||||
|
||||
Cancel a timer.
|
||||
|
||||
### `platform`
|
||||
|
||||
Return a string representing the platform: `"linux"`, `"darwin"`, `"win32"` or `"js"`.
|
||||
|
||||
### `Worker(module_filename)`
|
||||
|
||||
Constructor to create a new thread (worker) with an API close to that of
|
||||
`WebWorkers`. `module_filename` is a string specifying the
|
||||
module filename which is executed in the newly created thread. As for
|
||||
dynamically imported module, it is relative to the current script or
|
||||
module path. Threads normally don't share any data and communicate
|
||||
between each other with messages. Nested workers are not supported. An
|
||||
example is available in `tests/test_worker.js`.
|
||||
|
||||
The worker class has the following static properties:
|
||||
|
||||
- `parent` - In the created worker, `Worker.parent` represents the parent
|
||||
worker and is used to send or receive messages.
|
||||
|
||||
The worker instances have the following properties:
|
||||
|
||||
- `postMessage(msg)` - Send a message to the corresponding worker. `msg` is cloned in
|
||||
the destination worker using an algorithm similar to the `HTML`
|
||||
structured clone algorithm. `SharedArrayBuffer` are shared
|
||||
between workers.
|
||||
|
||||
- `onmessage` - Getter and setter. Set a function which is called each time a
|
||||
message is received. The function is called with a single
|
||||
argument. It is an object with a `data` property containing the
|
||||
received message. The thread is not terminated if there is at least
|
||||
one non `null` `onmessage` handler.
|
||||
|
||||
## `qjs:std` module
|
||||
|
||||
The `std` module provides wrappers to libc (`stdlib.h` and `stdio.h`) and a few other utilities.
|
||||
|
||||
### `exit(n)`
|
||||
|
||||
Exit the process.
|
||||
|
||||
### `evalScript(str, options = undefined)`
|
||||
|
||||
Evaluate the string `str` as a script (global
|
||||
eval). `options` is an optional object containing the following
|
||||
optional properties:
|
||||
|
||||
- `backtrace_barrier` - Boolean (default = false). If true, error backtraces do not list the
|
||||
stack frames below the evalScript.
|
||||
- `async` - Boolean (default = false). If true, `await` is accepted in the
|
||||
script and a promise is returned. The promise is resolved with an
|
||||
object whose `value` property holds the value returned by the
|
||||
script.
|
||||
|
||||
### `loadScript(filename)`
|
||||
|
||||
Evaluate the file `filename` as a script (global eval).
|
||||
|
||||
### `loadFile(filename, [options])`
|
||||
|
||||
Load the file `filename` and return it as a string assuming UTF-8
|
||||
encoding. Return `null` in case of I/O error.
|
||||
|
||||
If `options.binary` is set to `true` a `Uint8Array` is returned instead.
|
||||
|
||||
### `writeFile(filename, data)`
|
||||
|
||||
Create the file `filename` and write `data` into it.
|
||||
|
||||
`data` can be a string, a typed array or an `ArrayBuffer`. `undefined` is
|
||||
treated as the empty string.
|
||||
|
||||
When `data` is a string, the file is opened in text mode; otherwise it is
|
||||
opened in binary mode. (This distinction is only relevant on Windows.)
|
||||
|
||||
Throws an exception if the file cannot be created or written to.
|
||||
|
||||
### `open(filename, flags, errorObj = undefined)`
|
||||
|
||||
Open a file (wrapper to the libc `fopen()`). Return the FILE
|
||||
object or `null` in case of I/O error. If `errorObj` is not
|
||||
undefined, set its `errno` property to the error code or to 0 if
|
||||
no error occurred.
|
||||
|
||||
### `popen(command, flags, errorObj = undefined)`
|
||||
|
||||
Open a process by creating a pipe (wrapper to the libc
|
||||
`popen()`). Return the FILE
|
||||
object or `null` in case of I/O error. If `errorObj` is not
|
||||
undefined, set its `errno` property to the error code or to 0 if
|
||||
no error occurred.
|
||||
|
||||
### `fdopen(fd, flags, errorObj = undefined)`
|
||||
|
||||
Open a file from a file handle (wrapper to the libc
|
||||
`fdopen()`). Return the FILE
|
||||
object or null` in case of I/O error. If `errorObj` is not
|
||||
undefined, set its `errno` property to the error code or to 0 if
|
||||
no error occurred.
|
||||
|
||||
### `tmpfile(errorObj = undefined)`
|
||||
|
||||
Open a temporary file. Return the FILE
|
||||
object or `null` in case of I/O error. If `errorObj` is not
|
||||
undefined, set its `errno` property to the error code or to 0 if
|
||||
no error occurred.
|
||||
|
||||
### `puts(str)`
|
||||
|
||||
Equivalent to `std.out.puts(str)`.
|
||||
|
||||
### `printf(fmt, ...args)`
|
||||
|
||||
Equivalent to `std.out.printf(fmt, ...args)`.
|
||||
|
||||
### `sprintf(fmt, ...args)`
|
||||
|
||||
Equivalent to the libc sprintf().
|
||||
|
||||
### `in`, `out`, `err`
|
||||
|
||||
Wrappers to the libc file `stdin`, `stdout`, `stderr`.
|
||||
|
||||
### `Error`
|
||||
|
||||
Enumeration object containing the integer value of common errors
|
||||
(additional error codes may be defined):
|
||||
|
||||
- `EINVAL`
|
||||
- `EIO`
|
||||
- `EACCES`
|
||||
- `EEXIST`
|
||||
- `ENOSPC`
|
||||
- `ENOSYS`
|
||||
- `EBUSY`
|
||||
- `ENOENT`
|
||||
- `EPERM`
|
||||
- `EPIPE`
|
||||
|
||||
### `strerror(errno)`
|
||||
|
||||
Return a string that describes the error `errno`.
|
||||
|
||||
### `gc()`
|
||||
|
||||
Manually invoke the cycle removal algorithm. The cycle removal
|
||||
algorithm is automatically started when needed, so this function is
|
||||
useful in case of specific memory constraints or for testing.
|
||||
|
||||
### `getenv(name)`
|
||||
|
||||
Return the value of the environment variable `name` or
|
||||
`undefined` if it is not defined.
|
||||
|
||||
### `setenv(name, value)`
|
||||
|
||||
Set the value of the environment variable `name` to the string
|
||||
`value`.
|
||||
|
||||
### `unsetenv(name)`
|
||||
|
||||
Delete the environment variable `name`.
|
||||
|
||||
### `getenviron()`
|
||||
|
||||
Return an object containing the environment variables as key-value pairs.
|
||||
|
||||
### `urlGet(url, options = undefined)`
|
||||
|
||||
Download `url` using the `curl` command line
|
||||
utility. `options` is an optional object containing the following
|
||||
optional properties:
|
||||
|
||||
- `binary` - Boolean (default = false). If true, the response is an ArrayBuffer
|
||||
instead of a string. When a string is returned, the data is assumed
|
||||
to be UTF-8 encoded.
|
||||
- `full` - Boolean (default = false). If true, return the an object contains
|
||||
the properties `response` (response content),
|
||||
`responseHeaders` (headers separated by CRLF), `status`
|
||||
(status code). `response` is `null` is case of protocol or
|
||||
network error. If `full` is false, only the response is
|
||||
returned if the status is between 200 and 299. Otherwise `null`
|
||||
is returned.
|
||||
|
||||
### `FILE`
|
||||
|
||||
File object.
|
||||
|
||||
#### `close()`
|
||||
|
||||
Close the file. Return 0 if OK or `-errno` in case of I/O error.
|
||||
|
||||
#### `puts(str)`
|
||||
|
||||
Outputs the string with the UTF-8 encoding.
|
||||
|
||||
#### `printf(fmt, ...args)`
|
||||
|
||||
Formatted printf.
|
||||
|
||||
The same formats as the standard C library `printf` are
|
||||
supported. Integer format types (e.g. `%d`) truncate the Numbers
|
||||
or BigInts to 32 bits. Use the `l` modifier (e.g. `%ld`) to
|
||||
truncate to 64 bits.
|
||||
|
||||
#### `flush()`
|
||||
|
||||
Flush the buffered file.
|
||||
|
||||
#### `seek(offset, whence)`
|
||||
|
||||
Seek to a give file position (whence is
|
||||
`std.SEEK_*`). `offset` can be a number or a BigInt. Return
|
||||
0 if OK or `-errno` in case of I/O error.
|
||||
|
||||
- `SEEK_SET`
|
||||
- `SEEK_CUR`
|
||||
- `SEEK_END`
|
||||
|
||||
Constants for seek().
|
||||
|
||||
#### `tell()`
|
||||
|
||||
Return the current file position.
|
||||
|
||||
#### `tello()`
|
||||
|
||||
Return the current file position as a BigInt.
|
||||
|
||||
#### `eof()`
|
||||
|
||||
Return true if end of file.
|
||||
|
||||
#### `fileno()`
|
||||
|
||||
Return the associated OS handle.
|
||||
|
||||
#### `error()`
|
||||
|
||||
Return true if there was an error.
|
||||
|
||||
#### `clearerr()`
|
||||
|
||||
Clear the error indication.
|
||||
|
||||
#### `read(buffer, position, length)`
|
||||
|
||||
Read `length` bytes from the file to the ArrayBuffer `buffer` at byte
|
||||
position `position` (wrapper to the libc `fread`).
|
||||
|
||||
#### `write(buffer, position, length)`
|
||||
|
||||
Write `length` bytes to the file from the ArrayBuffer `buffer` at byte
|
||||
position `position` (wrapper to the libc `fwrite`).
|
||||
|
||||
#### `getline()`
|
||||
|
||||
Return the next line from the file, assuming UTF-8 encoding, excluding
|
||||
the trailing line feed.
|
||||
|
||||
#### `readAsArrayBuffer(max_size = undefined)`
|
||||
|
||||
Read `max_size` bytes from the file and return them as an ArrayBuffer.
|
||||
If `max_size` is not present, the file is read until its end.
|
||||
|
||||
#### `readAsString(max_size = undefined)`
|
||||
|
||||
Read `max_size` bytes from the file and return them as a string
|
||||
assuming UTF-8 encoding. If `max_size` is not present, the file
|
||||
is read until its end.
|
||||
|
||||
#### `getByte()`
|
||||
|
||||
Return the next byte from the file. Return -1 if the end of file is reached.
|
||||
|
||||
#### `putByte(c)`
|
||||
|
||||
Write one byte to the file.
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
---
|
||||
sidebar_position: 8
|
||||
---
|
||||
|
||||
# Supported Platforms
|
||||
|
||||
| System | Supported versions | Notes |
|
||||
|---|---|---|
|
||||
| GNU/Linux | * | glibc and musl are supported |
|
||||
| macOS | macOS >= 11 | Currently supported macOS releases |
|
||||
| Windows | >= Windows 7* | VS >= 2022 and Clang are supported; requires `<stdatomic.h>` |
|
||||
| FreeBSD | * | Limited testing |
|
||||
| OpenBSD | * | Limited testing |
|
||||
| NetBSD | * | Limited testing |
|
||||
| Android | NDK >= 26.0.10792818 | Limited testing |
|
||||
| iOS | * | Limited testing |
|
||||
| MinGW | MinGW-w64 | |
|
||||
| Other | N/A | Missing? Open a PR! |
|
||||
|
||||
- `*`: Windows 7 is EOL and only supported in this project as long as it doesn't interfere with its progress.
|
||||
@@ -0,0 +1,114 @@
|
||||
// @ts-check
|
||||
// `@type` JSDoc annotations allow editor autocompletion and type checking
|
||||
// (when paired with `@ts-check`).
|
||||
// There are various equivalent ways to declare your Docusaurus config.
|
||||
// See: https://docusaurus.io/docs/api/docusaurus-config
|
||||
|
||||
/** @type {import('@docusaurus/types').Config} */
|
||||
const config = {
|
||||
title: 'QuickJS-NG',
|
||||
tagline: 'QuickJS, the Next Generation: a mighty JavaScript engine',
|
||||
favicon: 'img/favicon.ico',
|
||||
|
||||
// Set the production url of your site here
|
||||
url: 'https://quickjs-ng.github.io',
|
||||
// Set the /<baseUrl>/ pathname under which your site is served
|
||||
// For GitHub pages deployment, it is often '/<projectName>/'
|
||||
baseUrl: '/quickjs/',
|
||||
|
||||
// GitHub pages deployment config.
|
||||
// If you aren't using GitHub pages, you don't need these.
|
||||
organizationName: 'quickjs-ng', // Usually your GitHub org/user name.
|
||||
projectName: 'quickjs', // Usually your repo name.
|
||||
|
||||
onBrokenLinks: 'throw',
|
||||
onBrokenMarkdownLinks: 'throw',
|
||||
|
||||
// Even if you don't use internationalization, you can use this field to set
|
||||
// useful metadata like html lang. For example, if your site is Chinese, you
|
||||
// may want to replace "en" with "zh-Hans".
|
||||
i18n: {
|
||||
defaultLocale: 'en',
|
||||
locales: ['en'],
|
||||
},
|
||||
|
||||
presets: [
|
||||
[
|
||||
'classic',
|
||||
/** @type {import('@docusaurus/preset-classic').Options} */
|
||||
({
|
||||
docs: {
|
||||
routeBasePath: '/',
|
||||
sidebarPath: './sidebars.js',
|
||||
// Please change this to your repo.
|
||||
// Remove this to remove the "edit this page" links.
|
||||
editUrl: 'https://github.com/quickjs-ng/quickjs/tree/master/docs/',
|
||||
},
|
||||
blog: false,
|
||||
theme: {
|
||||
customCss: './src/css/custom.css',
|
||||
},
|
||||
}),
|
||||
],
|
||||
],
|
||||
|
||||
themeConfig:
|
||||
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
|
||||
({
|
||||
// Replace with your project's social card
|
||||
image: 'img/docusaurus-social-card.jpg',
|
||||
navbar: {
|
||||
title: 'QuickJS-NG',
|
||||
items: [
|
||||
{
|
||||
type: 'docSidebar',
|
||||
sidebarId: 'docsSidebar',
|
||||
position: 'left',
|
||||
label: 'Documentation',
|
||||
},
|
||||
{
|
||||
href: 'https://github.com/quickjs-ng/quickjs',
|
||||
label: 'GitHub',
|
||||
position: 'right',
|
||||
},
|
||||
],
|
||||
},
|
||||
footer: {
|
||||
style: 'dark',
|
||||
links: [
|
||||
{
|
||||
title: 'Docs',
|
||||
items: [
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Community',
|
||||
items: [
|
||||
{
|
||||
label: 'GitHub Discussions',
|
||||
href: 'https://github.com/quickjs-ng/quickjs/discussions',
|
||||
},
|
||||
{
|
||||
label: 'Matrix',
|
||||
href: 'https://matrix.to/#/%23quickjs-ng%3Amatrix.org?via=matrix.org',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'More',
|
||||
items: [
|
||||
{
|
||||
label: 'GitHub',
|
||||
href: 'https://github.com/quickjs-ng/quickjs',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
copyright: `Copyright © ${new Date().getFullYear()} QuickJS-NG project contributors.`,
|
||||
},
|
||||
prism: {
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
export default config;
|
||||
+14656
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"docusaurus": "docusaurus",
|
||||
"start": "docusaurus start",
|
||||
"build": "docusaurus build",
|
||||
"swizzle": "docusaurus swizzle",
|
||||
"deploy": "docusaurus deploy",
|
||||
"clear": "docusaurus clear",
|
||||
"serve": "docusaurus serve",
|
||||
"write-translations": "docusaurus write-translations",
|
||||
"write-heading-ids": "docusaurus write-heading-ids"
|
||||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/core": "3.5.2",
|
||||
"@docusaurus/preset-classic": "3.5.2",
|
||||
"@mdx-js/react": "3.0.1",
|
||||
"clsx": "2.1.1",
|
||||
"prism-react-renderer": "2.4.0",
|
||||
"react": "18.3.1",
|
||||
"react-dom": "18.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docusaurus/module-type-aliases": "3.5.2",
|
||||
"@docusaurus/types": "3.5.2"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.5%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 3 chrome version",
|
||||
"last 3 firefox version",
|
||||
"last 5 safari version"
|
||||
]
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Creating a sidebar enables you to:
|
||||
- create an ordered group of docs
|
||||
- render a sidebar for each doc of that group
|
||||
- provide next/previous navigation
|
||||
|
||||
The sidebars can be generated from the filesystem, or explicitly defined here.
|
||||
|
||||
Create as many sidebars as you want.
|
||||
*/
|
||||
|
||||
// @ts-check
|
||||
|
||||
/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */
|
||||
const sidebars = {
|
||||
// By default, Docusaurus generates a sidebar from the docs folder structure
|
||||
docsSidebar: [{type: 'autogenerated', dirName: '.'}],
|
||||
};
|
||||
|
||||
export default sidebars;
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Any CSS included here will be global. The classic template
|
||||
* bundles Infima by default. Infima is a CSS framework designed to
|
||||
* work well for content-centric websites.
|
||||
*/
|
||||
|
||||
/* You can override the default Infima variables here. */
|
||||
:root {
|
||||
--ifm-color-primary: #2e8555;
|
||||
--ifm-color-primary-dark: #29784c;
|
||||
--ifm-color-primary-darker: #277148;
|
||||
--ifm-color-primary-darkest: #205d3b;
|
||||
--ifm-color-primary-light: #33925d;
|
||||
--ifm-color-primary-lighter: #359962;
|
||||
--ifm-color-primary-lightest: #3cad6e;
|
||||
--ifm-code-font-size: 95%;
|
||||
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* For readability concerns, you should choose a lighter palette in dark mode. */
|
||||
[data-theme='dark'] {
|
||||
--ifm-color-primary: #25c2a0;
|
||||
--ifm-color-primary-dark: #21af90;
|
||||
--ifm-color-primary-darker: #1fa588;
|
||||
--ifm-color-primary-darkest: #1a8870;
|
||||
--ifm-color-primary-light: #29d5b0;
|
||||
--ifm-color-primary-lighter: #32d8b4;
|
||||
--ifm-color-primary-lightest: #4fddbf;
|
||||
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.5 KiB |
+1619
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Tiny float64 printing and parsing library
|
||||
*
|
||||
* Copyright (c) 2024 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef DTOA_H
|
||||
#define DTOA_H
|
||||
|
||||
//#define JS_DTOA_DUMP_STATS
|
||||
|
||||
/* maximum number of digits for fixed and frac formats */
|
||||
#define JS_DTOA_MAX_DIGITS 101
|
||||
|
||||
/* radix != 10 is only supported with flags = JS_DTOA_FORMAT_FREE */
|
||||
/* use as many digits as necessary */
|
||||
#define JS_DTOA_FORMAT_FREE (0 << 0)
|
||||
/* use n_digits significant digits (1 <= n_digits <= JS_DTOA_MAX_DIGITS) */
|
||||
#define JS_DTOA_FORMAT_FIXED (1 << 0)
|
||||
/* force fractional format: [-]dd.dd with n_digits fractional digits.
|
||||
0 <= n_digits <= JS_DTOA_MAX_DIGITS */
|
||||
#define JS_DTOA_FORMAT_FRAC (2 << 0)
|
||||
#define JS_DTOA_FORMAT_MASK (3 << 0)
|
||||
|
||||
/* select exponential notation either in fixed or free format */
|
||||
#define JS_DTOA_EXP_AUTO (0 << 2)
|
||||
#define JS_DTOA_EXP_ENABLED (1 << 2)
|
||||
#define JS_DTOA_EXP_DISABLED (2 << 2)
|
||||
#define JS_DTOA_EXP_MASK (3 << 2)
|
||||
|
||||
#define JS_DTOA_MINUS_ZERO (1 << 4) /* show the minus sign for -0 */
|
||||
|
||||
/* only accepts integers (no dot, no exponent) */
|
||||
#define JS_ATOD_INT_ONLY (1 << 0)
|
||||
/* accept Oo and Ob prefixes in addition to 0x prefix if radix = 0 */
|
||||
#define JS_ATOD_ACCEPT_BIN_OCT (1 << 1)
|
||||
/* accept O prefix as octal if radix == 0 and properly formed (Annex B) */
|
||||
#define JS_ATOD_ACCEPT_LEGACY_OCTAL (1 << 2)
|
||||
/* accept _ between digits as a digit separator */
|
||||
#define JS_ATOD_ACCEPT_UNDERSCORES (1 << 3)
|
||||
|
||||
typedef struct {
|
||||
uint64_t mem[37];
|
||||
} JSDTOATempMem;
|
||||
|
||||
typedef struct {
|
||||
uint64_t mem[27];
|
||||
} JSATODTempMem;
|
||||
|
||||
/* return a maximum bound of the string length */
|
||||
int js_dtoa_max_len(double d, int radix, int n_digits, int flags);
|
||||
/* return the string length */
|
||||
int js_dtoa(char *buf, double d, int radix, int n_digits, int flags,
|
||||
JSDTOATempMem *tmp_mem);
|
||||
double js_atod(const char *str, const char **pnext, int radix, int flags,
|
||||
JSATODTempMem *tmp_mem);
|
||||
|
||||
#ifdef JS_DTOA_DUMP_STATS
|
||||
void js_dtoa_dump_stats(void);
|
||||
#endif
|
||||
|
||||
/* additional exported functions */
|
||||
size_t u32toa(char *buf, uint32_t n);
|
||||
size_t i32toa(char *buf, int32_t n);
|
||||
size_t u64toa(char *buf, uint64_t n);
|
||||
size_t i64toa(char *buf, int64_t n);
|
||||
size_t u64toa_radix(char *buf, uint64_t n, unsigned int radix);
|
||||
size_t i64toa_radix(char *buf, int64_t n, unsigned int radix);
|
||||
|
||||
#endif /* DTOA_H */
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* QuickJS: Example of C module
|
||||
*
|
||||
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "../quickjs.h"
|
||||
|
||||
#define countof(x) (sizeof(x) / sizeof((x)[0]))
|
||||
|
||||
static int fib(int n)
|
||||
{
|
||||
if (n <= 0)
|
||||
return 0;
|
||||
else if (n == 1)
|
||||
return 1;
|
||||
else
|
||||
return fib(n - 1) + fib(n - 2);
|
||||
}
|
||||
|
||||
static JSValue js_fib(JSContext *ctx, JSValue this_val,
|
||||
int argc, JSValue *argv)
|
||||
{
|
||||
int n, res;
|
||||
if (JS_ToInt32(ctx, &n, argv[0]))
|
||||
return JS_EXCEPTION;
|
||||
res = fib(n);
|
||||
return JS_NewInt32(ctx, res);
|
||||
}
|
||||
|
||||
static const JSCFunctionListEntry js_fib_funcs[] = {
|
||||
JS_CFUNC_DEF("fib", 1, js_fib ),
|
||||
};
|
||||
|
||||
static int js_fib_init(JSContext *ctx, JSModuleDef *m)
|
||||
{
|
||||
return JS_SetModuleExportList(ctx, m, js_fib_funcs,
|
||||
countof(js_fib_funcs));
|
||||
}
|
||||
|
||||
#ifdef JS_SHARED_LIBRARY
|
||||
#define JS_INIT_MODULE js_init_module
|
||||
#else
|
||||
#define JS_INIT_MODULE js_init_module_fib
|
||||
#endif
|
||||
|
||||
#ifndef JS_EXTERN
|
||||
#ifdef _WIN32
|
||||
#define JS_EXTERN __declspec(dllexport)
|
||||
#else
|
||||
#define JS_EXTERN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
JS_EXTERN JSModuleDef *JS_INIT_MODULE(JSContext *ctx, const char *module_name)
|
||||
{
|
||||
JSModuleDef *m;
|
||||
m = JS_NewCModule(ctx, module_name, js_fib_init);
|
||||
if (!m)
|
||||
return NULL;
|
||||
JS_AddModuleExportList(ctx, m, js_fib_funcs, countof(js_fib_funcs));
|
||||
return m;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/* fib module */
|
||||
export function fib(n)
|
||||
{
|
||||
if (n <= 0)
|
||||
return 0;
|
||||
else if (n == 1)
|
||||
return 1;
|
||||
else
|
||||
return fib(n - 1) + fib(n - 2);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
console.log("Hello World");
|
||||
@@ -0,0 +1,6 @@
|
||||
/* example of JS module */
|
||||
|
||||
import { fib } from "./fib_module.js";
|
||||
|
||||
console.log("Hello World");
|
||||
console.log("fib(10)=", fib(10));
|
||||
@@ -0,0 +1,19 @@
|
||||
shared_module(
|
||||
'fib',
|
||||
'fib.c',
|
||||
|
||||
name_prefix: '',
|
||||
gnu_symbol_visibility: 'default',
|
||||
c_args: ['-DJS_SHARED_LIBRARY'],
|
||||
dependencies: host_system == 'windows' ? qjs_dep : [],
|
||||
)
|
||||
|
||||
shared_module(
|
||||
'point',
|
||||
'point.c',
|
||||
|
||||
name_prefix: '',
|
||||
gnu_symbol_visibility: 'default',
|
||||
c_args: ['-DJS_SHARED_LIBRARY'],
|
||||
dependencies: host_system == 'windows' ? qjs_dep : [],
|
||||
)
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* PI computation in Javascript using the BigInt type
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
/* return floor(log2(a)) for a > 0 and 0 for a = 0 */
|
||||
function floor_log2(a)
|
||||
{
|
||||
var k_max, a1, k, i;
|
||||
k_max = 0n;
|
||||
while ((a >> (2n ** k_max)) != 0n) {
|
||||
k_max++;
|
||||
}
|
||||
k = 0n;
|
||||
a1 = a;
|
||||
for(i = k_max - 1n; i >= 0n; i--) {
|
||||
a1 = a >> (2n ** i);
|
||||
if (a1 != 0n) {
|
||||
a = a1;
|
||||
k |= (1n << i);
|
||||
}
|
||||
}
|
||||
return k;
|
||||
}
|
||||
|
||||
/* return ceil(log2(a)) for a > 0 */
|
||||
function ceil_log2(a)
|
||||
{
|
||||
return floor_log2(a - 1n) + 1n;
|
||||
}
|
||||
|
||||
/* return floor(sqrt(a)) (not efficient but simple) */
|
||||
function int_sqrt(a)
|
||||
{
|
||||
var l, u, s;
|
||||
if (a == 0n)
|
||||
return a;
|
||||
l = ceil_log2(a);
|
||||
u = 1n << ((l + 1n) / 2n);
|
||||
/* u >= floor(sqrt(a)) */
|
||||
for(;;) {
|
||||
s = u;
|
||||
u = ((a / s) + s) / 2n;
|
||||
if (u >= s)
|
||||
break;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/* return pi * 2**prec */
|
||||
function calc_pi(prec) {
|
||||
const CHUD_A = 13591409n;
|
||||
const CHUD_B = 545140134n;
|
||||
const CHUD_C = 640320n;
|
||||
const CHUD_C3 = 10939058860032000n; /* C^3/24 */
|
||||
const CHUD_BITS_PER_TERM = 47.11041313821584202247; /* log2(C/12)*3 */
|
||||
|
||||
/* return [P, Q, G] */
|
||||
function chud_bs(a, b, need_G) {
|
||||
var c, P, Q, G, P1, Q1, G1, P2, Q2, G2;
|
||||
if (a == (b - 1n)) {
|
||||
G = (2n * b - 1n) * (6n * b - 1n) * (6n * b - 5n);
|
||||
P = G * (CHUD_B * b + CHUD_A);
|
||||
if (b & 1n)
|
||||
P = -P;
|
||||
Q = b * b * b * CHUD_C3;
|
||||
} else {
|
||||
c = (a + b) >> 1n;
|
||||
[P1, Q1, G1] = chud_bs(a, c, true);
|
||||
[P2, Q2, G2] = chud_bs(c, b, need_G);
|
||||
P = P1 * Q2 + P2 * G1;
|
||||
Q = Q1 * Q2;
|
||||
if (need_G)
|
||||
G = G1 * G2;
|
||||
else
|
||||
G = 0n;
|
||||
}
|
||||
return [P, Q, G];
|
||||
}
|
||||
|
||||
var n, P, Q, G;
|
||||
/* number of serie terms */
|
||||
n = BigInt(Math.ceil(Number(prec) / CHUD_BITS_PER_TERM)) + 10n;
|
||||
[P, Q, G] = chud_bs(0n, n, false);
|
||||
Q = (CHUD_C / 12n) * (Q << prec) / (P + Q * CHUD_A);
|
||||
G = int_sqrt(CHUD_C << (2n * prec));
|
||||
return (Q * G) >> prec;
|
||||
}
|
||||
|
||||
function main(args) {
|
||||
var r, n_digits, n_bits, out;
|
||||
if (args.length < 1) {
|
||||
print("usage: pi n_digits");
|
||||
return;
|
||||
}
|
||||
n_digits = args[0] | 0;
|
||||
|
||||
/* we add more bits to reduce the probability of bad rounding for
|
||||
the last digits */
|
||||
n_bits = BigInt(Math.ceil(n_digits * Math.log2(10))) + 32n;
|
||||
r = calc_pi(n_bits);
|
||||
r = ((10n ** BigInt(n_digits)) * r) >> n_bits;
|
||||
out = r.toString();
|
||||
print(out[0] + "." + out.slice(1));
|
||||
}
|
||||
|
||||
var args;
|
||||
if (typeof scriptArgs != "undefined") {
|
||||
args = scriptArgs;
|
||||
args.shift();
|
||||
} else if (typeof arguments != "undefined") {
|
||||
args = arguments;
|
||||
} else {
|
||||
/* default: 1000 digits */
|
||||
args=[1000];
|
||||
}
|
||||
|
||||
main(args);
|
||||
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* QuickJS: Example of C module with a class
|
||||
*
|
||||
* Copyright (c) 2019 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "../quickjs.h"
|
||||
#include <math.h>
|
||||
|
||||
#define countof(x) (sizeof(x) / sizeof((x)[0]))
|
||||
|
||||
/* Point Class */
|
||||
|
||||
typedef struct {
|
||||
int x;
|
||||
int y;
|
||||
} JSPointData;
|
||||
|
||||
static JSClassID js_point_class_id;
|
||||
|
||||
static void js_point_finalizer(JSRuntime *rt, JSValue val)
|
||||
{
|
||||
JSPointData *s = JS_GetOpaque(val, js_point_class_id);
|
||||
/* Note: 's' can be NULL in case JS_SetOpaque() was not called */
|
||||
js_free_rt(rt, s);
|
||||
}
|
||||
|
||||
static JSValue js_point_ctor(JSContext *ctx,
|
||||
JSValue new_target,
|
||||
int argc, JSValue *argv)
|
||||
{
|
||||
JSPointData *s;
|
||||
JSValue obj = JS_UNDEFINED;
|
||||
JSValue proto;
|
||||
|
||||
s = js_mallocz(ctx, sizeof(*s));
|
||||
if (!s)
|
||||
return JS_EXCEPTION;
|
||||
if (JS_ToInt32(ctx, &s->x, argv[0]))
|
||||
goto fail;
|
||||
if (JS_ToInt32(ctx, &s->y, argv[1]))
|
||||
goto fail;
|
||||
/* using new_target to get the prototype is necessary when the
|
||||
class is extended. */
|
||||
proto = JS_GetPropertyStr(ctx, new_target, "prototype");
|
||||
if (JS_IsException(proto))
|
||||
goto fail;
|
||||
obj = JS_NewObjectProtoClass(ctx, proto, js_point_class_id);
|
||||
JS_FreeValue(ctx, proto);
|
||||
if (JS_IsException(obj))
|
||||
goto fail;
|
||||
JS_SetOpaque(obj, s);
|
||||
return obj;
|
||||
fail:
|
||||
js_free(ctx, s);
|
||||
JS_FreeValue(ctx, obj);
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
|
||||
static JSValue js_point_get_xy(JSContext *ctx, JSValue this_val, int magic)
|
||||
{
|
||||
JSPointData *s = JS_GetOpaque2(ctx, this_val, js_point_class_id);
|
||||
if (!s)
|
||||
return JS_EXCEPTION;
|
||||
if (magic == 0)
|
||||
return JS_NewInt32(ctx, s->x);
|
||||
else
|
||||
return JS_NewInt32(ctx, s->y);
|
||||
}
|
||||
|
||||
static JSValue js_point_set_xy(JSContext *ctx, JSValue this_val, JSValue val, int magic)
|
||||
{
|
||||
JSPointData *s = JS_GetOpaque2(ctx, this_val, js_point_class_id);
|
||||
int v;
|
||||
if (!s)
|
||||
return JS_EXCEPTION;
|
||||
if (JS_ToInt32(ctx, &v, val))
|
||||
return JS_EXCEPTION;
|
||||
if (magic == 0)
|
||||
s->x = v;
|
||||
else
|
||||
s->y = v;
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static JSValue js_point_norm(JSContext *ctx, JSValue this_val,
|
||||
int argc, JSValue *argv)
|
||||
{
|
||||
JSPointData *s = JS_GetOpaque2(ctx, this_val, js_point_class_id);
|
||||
if (!s)
|
||||
return JS_EXCEPTION;
|
||||
return JS_NewFloat64(ctx, sqrt((double)s->x * s->x + (double)s->y * s->y));
|
||||
}
|
||||
|
||||
static JSClassDef js_point_class = {
|
||||
"Point",
|
||||
.finalizer = js_point_finalizer,
|
||||
};
|
||||
|
||||
static const JSCFunctionListEntry js_point_proto_funcs[] = {
|
||||
JS_CGETSET_MAGIC_DEF("x", js_point_get_xy, js_point_set_xy, 0),
|
||||
JS_CGETSET_MAGIC_DEF("y", js_point_get_xy, js_point_set_xy, 1),
|
||||
JS_CFUNC_DEF("norm", 0, js_point_norm),
|
||||
};
|
||||
|
||||
static int js_point_init(JSContext *ctx, JSModuleDef *m)
|
||||
{
|
||||
JSValue point_proto, point_class;
|
||||
JSRuntime *rt = JS_GetRuntime(ctx);
|
||||
|
||||
/* create the Point class */
|
||||
JS_NewClassID(rt, &js_point_class_id);
|
||||
JS_NewClass(rt, js_point_class_id, &js_point_class);
|
||||
|
||||
point_proto = JS_NewObject(ctx);
|
||||
JS_SetPropertyFunctionList(ctx, point_proto, js_point_proto_funcs, countof(js_point_proto_funcs));
|
||||
|
||||
point_class = JS_NewCFunction2(ctx, js_point_ctor, "Point", 2, JS_CFUNC_constructor, 0);
|
||||
/* set proto.constructor and ctor.prototype */
|
||||
JS_SetConstructor(ctx, point_class, point_proto);
|
||||
JS_SetClassProto(ctx, js_point_class_id, point_proto);
|
||||
|
||||
JS_SetModuleExport(ctx, m, "Point", point_class);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef JS_EXTERN
|
||||
#ifdef _WIN32
|
||||
#define JS_EXTERN __declspec(dllexport)
|
||||
#else
|
||||
#define JS_EXTERN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
JS_EXTERN JSModuleDef *js_init_module(JSContext *ctx, const char *module_name)
|
||||
{
|
||||
JSModuleDef *m;
|
||||
m = JS_NewCModule(ctx, module_name, js_point_init);
|
||||
if (!m)
|
||||
return NULL;
|
||||
JS_AddModuleExport(ctx, m, "Point");
|
||||
return m;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
/* example of JS module importing a C module */
|
||||
import * as os from "qjs:os";
|
||||
|
||||
const isWin = os.platform === 'win32';
|
||||
const { fib } = await import(`./fib.${isWin ? 'dll' : 'so'}`);
|
||||
|
||||
console.log("Hello World");
|
||||
console.log("fib(10)=", fib(10));
|
||||
@@ -0,0 +1,43 @@
|
||||
/* example of JS module importing a C module */
|
||||
import * as os from "qjs:os";
|
||||
|
||||
const isWin = os.platform === 'win32';
|
||||
const { Point } = await import(`./point.${isWin ? 'dll' : 'so'}`);
|
||||
|
||||
function assert(b, str)
|
||||
{
|
||||
if (b) {
|
||||
return;
|
||||
} else {
|
||||
throw Error("assertion failed: " + str);
|
||||
}
|
||||
}
|
||||
|
||||
class ColorPoint extends Point {
|
||||
constructor(x, y, color) {
|
||||
super(x, y);
|
||||
this.color = color;
|
||||
}
|
||||
get_color() {
|
||||
return this.color;
|
||||
}
|
||||
};
|
||||
|
||||
function main()
|
||||
{
|
||||
var pt, pt2;
|
||||
|
||||
pt = new Point(2, 3);
|
||||
assert(pt.x === 2);
|
||||
assert(pt.y === 3);
|
||||
pt.x = 4;
|
||||
assert(pt.x === 4);
|
||||
assert(pt.norm() == 5);
|
||||
|
||||
pt2 = new ColorPoint(2, 3, 0xffffff);
|
||||
assert(pt2.x === 2);
|
||||
assert(pt2.color === 0xffffff);
|
||||
assert(pt2.get_color() === 0xffffff);
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -0,0 +1,22 @@
|
||||
// clang -g -O1 -fsanitize=fuzzer -o fuzz fuzz.c
|
||||
#include "quickjs.h"
|
||||
#include "quickjs.c"
|
||||
#include "cutils.c"
|
||||
#include "libregexp.c"
|
||||
#include "libunicode.c"
|
||||
#include <stdlib.h>
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len)
|
||||
{
|
||||
JSRuntime *rt = JS_NewRuntime();
|
||||
if (!rt)
|
||||
exit(1);
|
||||
JSContext *ctx = JS_NewContext(rt);
|
||||
if (!ctx)
|
||||
exit(1);
|
||||
JSValue val = JS_ReadObject(ctx, buf, len, /*flags*/0);
|
||||
JS_FreeValue(ctx, val);
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/* File generated automatically by the QuickJS-ng compiler. */
|
||||
|
||||
#include "quickjs-libc.h"
|
||||
|
||||
const uint32_t qjsc_function_source_size = 324;
|
||||
|
||||
const uint8_t qjsc_function_source[324] = {
|
||||
0x15, 0x05, 0x01, 0x30, 0x74, 0x65, 0x73, 0x74,
|
||||
0x73, 0x2f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63,
|
||||
0x65, 0x2e, 0x6a, 0x73, 0x01, 0x0c, 0x61, 0x63,
|
||||
0x74, 0x75, 0x61, 0x6c, 0x01, 0x02, 0x66, 0x01,
|
||||
0x0c, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x01,
|
||||
0x34, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x20, 0x66, 0x28, 0x29, 0x20, 0x7b, 0x20,
|
||||
0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x34,
|
||||
0x32, 0x20, 0x7d, 0x0d, 0xc6, 0x03, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x0c, 0x20, 0x0a, 0x01, 0xa2,
|
||||
0x01, 0x00, 0x05, 0x00, 0x03, 0x02, 0x01, 0x74,
|
||||
0x05, 0xc8, 0x03, 0x02, 0x00, 0x30, 0xca, 0x03,
|
||||
0x04, 0x00, 0x70, 0xc8, 0x03, 0x04, 0x02, 0x70,
|
||||
0x10, 0x00, 0x01, 0x00, 0xe4, 0x01, 0x00, 0x01,
|
||||
0x00, 0xcc, 0x03, 0x00, 0x0d, 0xca, 0x03, 0x01,
|
||||
0x01, 0x0c, 0x43, 0x0a, 0x01, 0xca, 0x03, 0x00,
|
||||
0x00, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0xbe,
|
||||
0x2a, 0x28, 0xc6, 0x03, 0x03, 0x01, 0x00, 0x1a,
|
||||
0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x20, 0x66, 0x28, 0x29, 0x20, 0x7b, 0x20, 0x72,
|
||||
0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x34, 0x32,
|
||||
0x20, 0x7d, 0x0c, 0x03, 0xc4, 0x04, 0x08, 0xce,
|
||||
0x08, 0xec, 0x05, 0xc1, 0x00, 0xe4, 0x29, 0x04,
|
||||
0xe7, 0x00, 0x00, 0x00, 0xe3, 0x62, 0x00, 0x00,
|
||||
0xe0, 0x43, 0x38, 0x00, 0x00, 0x00, 0x24, 0x00,
|
||||
0x00, 0xcb, 0x63, 0x00, 0x00, 0x66, 0x00, 0x00,
|
||||
0xb0, 0xec, 0x0b, 0x39, 0x96, 0x00, 0x00, 0x00,
|
||||
0x63, 0x00, 0x00, 0xf1, 0x30, 0x62, 0x02, 0x00,
|
||||
0x62, 0x01, 0x00, 0x39, 0x3b, 0x00, 0x00, 0x00,
|
||||
0x66, 0x00, 0x00, 0x04, 0xe5, 0x00, 0x00, 0x00,
|
||||
0x9e, 0x32, 0x01, 0x00, 0x03, 0x00, 0xcc, 0x63,
|
||||
0x01, 0x00, 0x43, 0x38, 0x00, 0x00, 0x00, 0x24,
|
||||
0x00, 0x00, 0xcd, 0x63, 0x02, 0x00, 0x66, 0x00,
|
||||
0x00, 0xb0, 0xec, 0x0b, 0x39, 0x96, 0x00, 0x00,
|
||||
0x00, 0x63, 0x02, 0x00, 0xf1, 0x30, 0x69, 0x02,
|
||||
0x00, 0x69, 0x01, 0x00, 0x06, 0x2f, 0xc6, 0x03,
|
||||
0x01, 0x01, 0x18, 0x00, 0x1c, 0x0a, 0x2a, 0x26,
|
||||
0x03, 0x20, 0x1c, 0x1b, 0x0c, 0x00, 0x10, 0x08,
|
||||
0x27, 0x11, 0x12, 0x67, 0x0d, 0x26, 0x03, 0x20,
|
||||
0x1c, 0x1b, 0x0c, 0x00,
|
||||
};
|
||||
|
||||
static JSContext *JS_NewCustomContext(JSRuntime *rt)
|
||||
{
|
||||
JSContext *ctx = JS_NewContext(rt);
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int r;
|
||||
JSRuntime *rt;
|
||||
JSContext *ctx;
|
||||
r = 0;
|
||||
rt = JS_NewRuntime();
|
||||
js_std_set_worker_new_context_func(JS_NewCustomContext);
|
||||
js_std_init_handlers(rt);
|
||||
JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);
|
||||
ctx = JS_NewCustomContext(rt);
|
||||
js_std_add_helpers(ctx, argc, argv);
|
||||
js_std_eval_binary(ctx, qjsc_function_source, qjsc_function_source_size, 0);
|
||||
r = js_std_loop(ctx);
|
||||
if (r) {
|
||||
js_std_dump_error(ctx);
|
||||
}
|
||||
js_std_free_handlers(rt);
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
return r;
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/* File generated automatically by the QuickJS-ng compiler. */
|
||||
|
||||
#include "quickjs-libc.h"
|
||||
|
||||
const uint32_t qjsc_hello_size = 103;
|
||||
|
||||
const uint8_t qjsc_hello[103] = {
|
||||
0x15, 0x04, 0x01, 0x22, 0x65, 0x78, 0x61, 0x6d,
|
||||
0x70, 0x6c, 0x65, 0x73, 0x2f, 0x68, 0x65, 0x6c,
|
||||
0x6c, 0x6f, 0x2e, 0x6a, 0x73, 0x01, 0x0e, 0x63,
|
||||
0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x01, 0x06,
|
||||
0x6c, 0x6f, 0x67, 0x01, 0x16, 0x48, 0x65, 0x6c,
|
||||
0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64,
|
||||
0x0d, 0xc6, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0c, 0x20, 0x0a, 0x01, 0xa2, 0x01, 0x00, 0x00,
|
||||
0x00, 0x03, 0x00, 0x00, 0x19, 0x00, 0x08, 0xec,
|
||||
0x02, 0x29, 0x39, 0xe4, 0x00, 0x00, 0x00, 0x43,
|
||||
0xe5, 0x00, 0x00, 0x00, 0x04, 0xe6, 0x00, 0x00,
|
||||
0x00, 0x24, 0x01, 0x00, 0x0e, 0x06, 0x2f, 0xc6,
|
||||
0x03, 0x01, 0x01, 0x02, 0x48, 0x0e, 0x00,
|
||||
};
|
||||
|
||||
static JSContext *JS_NewCustomContext(JSRuntime *rt)
|
||||
{
|
||||
JSContext *ctx = JS_NewContext(rt);
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int r;
|
||||
JSRuntime *rt;
|
||||
JSContext *ctx;
|
||||
r = 0;
|
||||
rt = JS_NewRuntime();
|
||||
js_std_set_worker_new_context_func(JS_NewCustomContext);
|
||||
js_std_init_handlers(rt);
|
||||
JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);
|
||||
ctx = JS_NewCustomContext(rt);
|
||||
js_std_add_helpers(ctx, argc, argv);
|
||||
js_std_eval_binary(ctx, qjsc_hello, qjsc_hello_size, 0);
|
||||
r = js_std_loop(ctx);
|
||||
if (r) {
|
||||
js_std_dump_error(ctx);
|
||||
}
|
||||
js_std_free_handlers(rt);
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
return r;
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/* File generated automatically by the QuickJS-ng compiler. */
|
||||
|
||||
#include "quickjs-libc.h"
|
||||
|
||||
const uint32_t qjsc_fib_module_size = 290;
|
||||
|
||||
const uint8_t qjsc_fib_module[290] = {
|
||||
0x15, 0x03, 0x01, 0x2c, 0x65, 0x78, 0x61, 0x6d,
|
||||
0x70, 0x6c, 0x65, 0x73, 0x2f, 0x66, 0x69, 0x62,
|
||||
0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2e,
|
||||
0x6a, 0x73, 0x01, 0x06, 0x66, 0x69, 0x62, 0x01,
|
||||
0x02, 0x6e, 0x0d, 0xc6, 0x03, 0x00, 0x01, 0x00,
|
||||
0x00, 0xc8, 0x03, 0x00, 0x00, 0x00, 0x0c, 0x20,
|
||||
0x0a, 0x01, 0xa2, 0x01, 0x00, 0x00, 0x00, 0x01,
|
||||
0x01, 0x01, 0x09, 0x00, 0xc8, 0x03, 0x00, 0x01,
|
||||
0x0c, 0x43, 0x0a, 0x01, 0xc8, 0x03, 0x01, 0x00,
|
||||
0x01, 0x04, 0x01, 0x00, 0x1a, 0x01, 0xca, 0x03,
|
||||
0x00, 0x01, 0x00, 0xc8, 0x03, 0x00, 0x00, 0xd3,
|
||||
0xb6, 0xa8, 0xec, 0x03, 0xb6, 0x28, 0xd3, 0xb7,
|
||||
0xad, 0xec, 0x03, 0xb7, 0x28, 0xdf, 0xd3, 0xb7,
|
||||
0x9f, 0xf1, 0xdf, 0xd3, 0xb8, 0x9f, 0xf1, 0x9e,
|
||||
0x28, 0xc6, 0x03, 0x02, 0x08, 0x0e, 0x09, 0x0c,
|
||||
0x27, 0x0a, 0x28, 0x02, 0x07, 0x08, 0x11, 0x0a,
|
||||
0x07, 0x08, 0x07, 0x08, 0x8d, 0x01, 0x66, 0x75,
|
||||
0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66,
|
||||
0x69, 0x62, 0x28, 0x6e, 0x29, 0x0a, 0x7b, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x28,
|
||||
0x6e, 0x20, 0x3c, 0x3d, 0x20, 0x30, 0x29, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x30,
|
||||
0x3b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6c,
|
||||
0x73, 0x65, 0x20, 0x69, 0x66, 0x20, 0x28, 0x6e,
|
||||
0x20, 0x3d, 0x3d, 0x20, 0x31, 0x29, 0x0a, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72,
|
||||
0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x31, 0x3b,
|
||||
0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6c, 0x73,
|
||||
0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e,
|
||||
0x20, 0x66, 0x69, 0x62, 0x28, 0x6e, 0x20, 0x2d,
|
||||
0x20, 0x31, 0x29, 0x20, 0x2b, 0x20, 0x66, 0x69,
|
||||
0x62, 0x28, 0x6e, 0x20, 0x2d, 0x20, 0x32, 0x29,
|
||||
0x3b, 0x0a, 0x7d, 0x08, 0xec, 0x05, 0xc1, 0x00,
|
||||
0xe3, 0x29, 0x06, 0x2f, 0xc6, 0x03, 0x01, 0x01,
|
||||
0x00, 0x00,
|
||||
};
|
||||
|
||||
const uint32_t qjsc_hello_module_size = 187;
|
||||
|
||||
const uint8_t qjsc_hello_module[187] = {
|
||||
0x15, 0x07, 0x01, 0x30, 0x65, 0x78, 0x61, 0x6d,
|
||||
0x70, 0x6c, 0x65, 0x73, 0x2f, 0x68, 0x65, 0x6c,
|
||||
0x6c, 0x6f, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c,
|
||||
0x65, 0x2e, 0x6a, 0x73, 0x01, 0x1e, 0x2e, 0x2f,
|
||||
0x66, 0x69, 0x62, 0x5f, 0x6d, 0x6f, 0x64, 0x75,
|
||||
0x6c, 0x65, 0x2e, 0x6a, 0x73, 0x01, 0x06, 0x66,
|
||||
0x69, 0x62, 0x01, 0x0e, 0x63, 0x6f, 0x6e, 0x73,
|
||||
0x6f, 0x6c, 0x65, 0x01, 0x06, 0x6c, 0x6f, 0x67,
|
||||
0x01, 0x16, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20,
|
||||
0x57, 0x6f, 0x72, 0x6c, 0x64, 0x01, 0x10, 0x66,
|
||||
0x69, 0x62, 0x28, 0x31, 0x30, 0x29, 0x3d, 0x0d,
|
||||
0xc6, 0x03, 0x01, 0xc8, 0x03, 0x00, 0x00, 0x01,
|
||||
0x00, 0xca, 0x03, 0x00, 0x00, 0x0c, 0x20, 0x0a,
|
||||
0x01, 0xa2, 0x01, 0x00, 0x00, 0x00, 0x05, 0x01,
|
||||
0x00, 0x32, 0x00, 0xca, 0x03, 0x00, 0x0c, 0x08,
|
||||
0xec, 0x02, 0x29, 0x39, 0xe6, 0x00, 0x00, 0x00,
|
||||
0x43, 0xe7, 0x00, 0x00, 0x00, 0x04, 0xe8, 0x00,
|
||||
0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, 0x39, 0xe6,
|
||||
0x00, 0x00, 0x00, 0x43, 0xe7, 0x00, 0x00, 0x00,
|
||||
0x04, 0xe9, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00,
|
||||
0xbe, 0x0a, 0xf1, 0x24, 0x02, 0x00, 0x0e, 0x06,
|
||||
0x2f, 0xc6, 0x03, 0x01, 0x01, 0x0c, 0x00, 0x04,
|
||||
0x08, 0x00, 0x34, 0x10, 0x30, 0x0f, 0x34, 0x10,
|
||||
0x2a, 0x20, 0x00,
|
||||
};
|
||||
|
||||
static JSContext *JS_NewCustomContext(JSRuntime *rt)
|
||||
{
|
||||
JSContext *ctx = JS_NewContext(rt);
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
js_std_eval_binary(ctx, qjsc_fib_module, qjsc_fib_module_size, 1);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int r;
|
||||
JSRuntime *rt;
|
||||
JSContext *ctx;
|
||||
r = 0;
|
||||
rt = JS_NewRuntime();
|
||||
js_std_set_worker_new_context_func(JS_NewCustomContext);
|
||||
js_std_init_handlers(rt);
|
||||
JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);
|
||||
ctx = JS_NewCustomContext(rt);
|
||||
js_std_add_helpers(ctx, argc, argv);
|
||||
js_std_eval_binary(ctx, qjsc_hello_module, qjsc_hello_module_size, 0);
|
||||
r = js_std_loop(ctx);
|
||||
if (r) {
|
||||
js_std_dump_error(ctx);
|
||||
}
|
||||
js_std_free_handlers(rt);
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
return r;
|
||||
}
|
||||
+3025
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,323 @@
|
||||
/* File generated automatically by the QuickJS-ng compiler. */
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
const uint32_t qjsc_standalone_size = 2511;
|
||||
|
||||
const uint8_t qjsc_standalone[2511] = {
|
||||
0x15, 0x4e, 0x01, 0x1a, 0x73, 0x74, 0x61, 0x6e,
|
||||
0x64, 0x61, 0x6c, 0x6f, 0x6e, 0x65, 0x2e, 0x6a,
|
||||
0x73, 0x01, 0x0e, 0x71, 0x6a, 0x73, 0x3a, 0x73,
|
||||
0x74, 0x64, 0x01, 0x0c, 0x71, 0x6a, 0x73, 0x3a,
|
||||
0x6f, 0x73, 0x01, 0x12, 0x71, 0x6a, 0x73, 0x3a,
|
||||
0x62, 0x6a, 0x73, 0x6f, 0x6e, 0x01, 0x22, 0x63,
|
||||
0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x53, 0x74,
|
||||
0x61, 0x6e, 0x64, 0x61, 0x6c, 0x6f, 0x6e, 0x65,
|
||||
0x01, 0x1a, 0x72, 0x75, 0x6e, 0x53, 0x74, 0x61,
|
||||
0x6e, 0x64, 0x61, 0x6c, 0x6f, 0x6e, 0x65, 0x01,
|
||||
0x06, 0x73, 0x74, 0x64, 0x01, 0x04, 0x6f, 0x73,
|
||||
0x01, 0x0a, 0x62, 0x6a, 0x73, 0x6f, 0x6e, 0x01,
|
||||
0x28, 0x4a, 0x53, 0x5f, 0x52, 0x45, 0x41, 0x44,
|
||||
0x5f, 0x4f, 0x42, 0x4a, 0x5f, 0x42, 0x59, 0x54,
|
||||
0x45, 0x43, 0x4f, 0x44, 0x45, 0x01, 0x2a, 0x4a,
|
||||
0x53, 0x5f, 0x52, 0x45, 0x41, 0x44, 0x5f, 0x4f,
|
||||
0x42, 0x4a, 0x5f, 0x52, 0x45, 0x46, 0x45, 0x52,
|
||||
0x45, 0x4e, 0x43, 0x45, 0x01, 0x2a, 0x4a, 0x53,
|
||||
0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, 0x5f, 0x4f,
|
||||
0x42, 0x4a, 0x5f, 0x42, 0x59, 0x54, 0x45, 0x43,
|
||||
0x4f, 0x44, 0x45, 0x01, 0x2c, 0x4a, 0x53, 0x5f,
|
||||
0x57, 0x52, 0x49, 0x54, 0x45, 0x5f, 0x4f, 0x42,
|
||||
0x4a, 0x5f, 0x52, 0x45, 0x46, 0x45, 0x52, 0x45,
|
||||
0x4e, 0x43, 0x45, 0x01, 0x32, 0x4a, 0x53, 0x5f,
|
||||
0x57, 0x52, 0x49, 0x54, 0x45, 0x5f, 0x4f, 0x42,
|
||||
0x4a, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x50, 0x5f,
|
||||
0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x01, 0x0e,
|
||||
0x54, 0x72, 0x61, 0x69, 0x6c, 0x65, 0x72, 0x01,
|
||||
0x16, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x41,
|
||||
0x73, 0x63, 0x69, 0x69, 0x01, 0x16, 0x64, 0x65,
|
||||
0x63, 0x6f, 0x64, 0x65, 0x41, 0x73, 0x63, 0x69,
|
||||
0x69, 0x01, 0x06, 0x74, 0x78, 0x74, 0x01, 0x02,
|
||||
0x63, 0x01, 0x14, 0x63, 0x68, 0x61, 0x72, 0x43,
|
||||
0x6f, 0x64, 0x65, 0x41, 0x74, 0x01, 0x06, 0x6d,
|
||||
0x61, 0x70, 0x01, 0x06, 0x62, 0x75, 0x66, 0x01,
|
||||
0x18, 0x66, 0x72, 0x6f, 0x6d, 0x43, 0x68, 0x61,
|
||||
0x72, 0x43, 0x6f, 0x64, 0x65, 0x01, 0x0c, 0x69,
|
||||
0x6e, 0x46, 0x69, 0x6c, 0x65, 0x01, 0x0e, 0x6f,
|
||||
0x75, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x01, 0x12,
|
||||
0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x45, 0x78,
|
||||
0x65, 0x01, 0x04, 0x6a, 0x73, 0x01, 0x08, 0x63,
|
||||
0x6f, 0x64, 0x65, 0x01, 0x10, 0x62, 0x79, 0x74,
|
||||
0x65, 0x63, 0x6f, 0x64, 0x65, 0x01, 0x16, 0x65,
|
||||
0x78, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x4e, 0x61,
|
||||
0x6d, 0x65, 0x01, 0x06, 0x65, 0x78, 0x65, 0x01,
|
||||
0x0e, 0x65, 0x78, 0x65, 0x53, 0x69, 0x7a, 0x65,
|
||||
0x01, 0x12, 0x6e, 0x65, 0x77, 0x42, 0x75, 0x66,
|
||||
0x66, 0x65, 0x72, 0x01, 0x0c, 0x6e, 0x65, 0x77,
|
||||
0x45, 0x78, 0x65, 0x01, 0x04, 0x64, 0x77, 0x01,
|
||||
0x0a, 0x6e, 0x65, 0x77, 0x46, 0x64, 0x01, 0x10,
|
||||
0x6c, 0x6f, 0x61, 0x64, 0x46, 0x69, 0x6c, 0x65,
|
||||
0x01, 0x1e, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64,
|
||||
0x20, 0x74, 0x6f, 0x20, 0x6f, 0x70, 0x65, 0x6e,
|
||||
0x20, 0x01, 0x14, 0x65, 0x76, 0x61, 0x6c, 0x53,
|
||||
0x63, 0x72, 0x69, 0x70, 0x74, 0x01, 0x18, 0x63,
|
||||
0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x5f, 0x6f,
|
||||
0x6e, 0x6c, 0x79, 0x01, 0x1c, 0x63, 0x6f, 0x6d,
|
||||
0x70, 0x69, 0x6c, 0x65, 0x5f, 0x6d, 0x6f, 0x64,
|
||||
0x75, 0x6c, 0x65, 0x01, 0x0a, 0x77, 0x72, 0x69,
|
||||
0x74, 0x65, 0x01, 0x0e, 0x65, 0x78, 0x65, 0x50,
|
||||
0x61, 0x74, 0x68, 0x01, 0x0a, 0x61, 0x72, 0x67,
|
||||
0x76, 0x30, 0x01, 0x0c, 0x62, 0x69, 0x6e, 0x61,
|
||||
0x72, 0x79, 0x01, 0x36, 0x66, 0x61, 0x69, 0x6c,
|
||||
0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6f, 0x70,
|
||||
0x65, 0x6e, 0x20, 0x65, 0x78, 0x65, 0x63, 0x75,
|
||||
0x74, 0x61, 0x62, 0x6c, 0x65, 0x3a, 0x20, 0x01,
|
||||
0x0c, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x01,
|
||||
0x10, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65,
|
||||
0x72, 0x01, 0x08, 0x53, 0x69, 0x7a, 0x65, 0x01,
|
||||
0x0a, 0x4d, 0x61, 0x67, 0x69, 0x63, 0x01, 0x12,
|
||||
0x4d, 0x61, 0x67, 0x69, 0x63, 0x53, 0x69, 0x7a,
|
||||
0x65, 0x01, 0x10, 0x44, 0x61, 0x74, 0x61, 0x53,
|
||||
0x69, 0x7a, 0x65, 0x01, 0x12, 0x73, 0x65, 0x74,
|
||||
0x55, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x01, 0x08,
|
||||
0x6f, 0x70, 0x65, 0x6e, 0x01, 0x10, 0x4f, 0x5f,
|
||||
0x57, 0x52, 0x4f, 0x4e, 0x4c, 0x59, 0x01, 0x0e,
|
||||
0x4f, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x01,
|
||||
0x0e, 0x4f, 0x5f, 0x54, 0x52, 0x55, 0x4e, 0x43,
|
||||
0x01, 0x22, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64,
|
||||
0x20, 0x74, 0x6f, 0x20, 0x63, 0x72, 0x65, 0x61,
|
||||
0x74, 0x65, 0x20, 0x01, 0x14, 0x62, 0x79, 0x74,
|
||||
0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x01,
|
||||
0x0a, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x01, 0x3c,
|
||||
0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x20, 0x74,
|
||||
0x6f, 0x20, 0x77, 0x72, 0x69, 0x74, 0x65, 0x20,
|
||||
0x74, 0x6f, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75,
|
||||
0x74, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x01, 0x08,
|
||||
0x66, 0x69, 0x6c, 0x65, 0x01, 0x02, 0x72, 0x01,
|
||||
0x0e, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x65, 0x72,
|
||||
0x01, 0x0a, 0x6d, 0x61, 0x67, 0x69, 0x63, 0x01,
|
||||
0x0c, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x01,
|
||||
0x04, 0x72, 0x62, 0x01, 0x08, 0x73, 0x65, 0x65,
|
||||
0x6b, 0x01, 0x10, 0x53, 0x45, 0x45, 0x4b, 0x5f,
|
||||
0x45, 0x4e, 0x44, 0x01, 0x18, 0x73, 0x65, 0x65,
|
||||
0x6b, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x3a,
|
||||
0x20, 0x01, 0x08, 0x72, 0x65, 0x61, 0x64, 0x01,
|
||||
0x40, 0x63, 0x6f, 0x72, 0x72, 0x75, 0x70, 0x74,
|
||||
0x65, 0x64, 0x20, 0x62, 0x69, 0x6e, 0x61, 0x72,
|
||||
0x79, 0x2c, 0x20, 0x6d, 0x61, 0x67, 0x69, 0x63,
|
||||
0x20, 0x6d, 0x69, 0x73, 0x6d, 0x61, 0x74, 0x63,
|
||||
0x68, 0x01, 0x12, 0x67, 0x65, 0x74, 0x55, 0x69,
|
||||
0x6e, 0x74, 0x33, 0x32, 0x01, 0x10, 0x53, 0x45,
|
||||
0x45, 0x4b, 0x5f, 0x53, 0x45, 0x54, 0x01, 0x0a,
|
||||
0x65, 0x72, 0x72, 0x6f, 0x72, 0x01, 0x14, 0x72,
|
||||
0x65, 0x61, 0x64, 0x20, 0x65, 0x72, 0x72, 0x6f,
|
||||
0x72, 0x01, 0x16, 0x65, 0x76, 0x61, 0x6c, 0x5f,
|
||||
0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x01, 0x10,
|
||||
0x71, 0x75, 0x69, 0x63, 0x6b, 0x6a, 0x73, 0x32,
|
||||
0x0d, 0xc6, 0x03, 0x03, 0xc8, 0x03, 0xca, 0x03,
|
||||
0xcc, 0x03, 0x02, 0x00, 0x0b, 0xce, 0x03, 0x00,
|
||||
0x0c, 0xd0, 0x03, 0x00, 0x03, 0x00, 0xfe, 0x01,
|
||||
0x00, 0x01, 0xfe, 0x01, 0x01, 0x02, 0xfe, 0x01,
|
||||
0x02, 0x00, 0x0c, 0x20, 0x02, 0x01, 0xa2, 0x01,
|
||||
0x00, 0x00, 0x00, 0x02, 0x0d, 0x04, 0x58, 0x00,
|
||||
0xd2, 0x03, 0x00, 0x0d, 0xd4, 0x03, 0x01, 0x0d,
|
||||
0xd6, 0x03, 0x02, 0x0d, 0xd8, 0x03, 0x00, 0x0d,
|
||||
0xda, 0x03, 0x01, 0x0d, 0xdc, 0x03, 0x02, 0x0d,
|
||||
0xde, 0x03, 0x03, 0x0d, 0xe0, 0x03, 0x04, 0x0d,
|
||||
0xe2, 0x03, 0x05, 0x0d, 0xe4, 0x03, 0x06, 0x01,
|
||||
0xe6, 0x03, 0x07, 0x01, 0xce, 0x03, 0x08, 0x01,
|
||||
0xd0, 0x03, 0x09, 0x01, 0x0c, 0x43, 0x02, 0x01,
|
||||
0xe4, 0x03, 0x01, 0x00, 0x01, 0x05, 0x00, 0x01,
|
||||
0x1e, 0x01, 0xe8, 0x03, 0x00, 0x01, 0x00, 0x0c,
|
||||
0x42, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, 0x03,
|
||||
0x00, 0x00, 0x0a, 0x01, 0xea, 0x03, 0x00, 0x01,
|
||||
0x00, 0xd3, 0x43, 0xf6, 0x00, 0x00, 0x00, 0xb6,
|
||||
0x25, 0x01, 0x00, 0x39, 0xa7, 0x00, 0x00, 0x00,
|
||||
0x11, 0xd3, 0x43, 0x5e, 0x00, 0x00, 0x00, 0xc2,
|
||||
0x24, 0x01, 0x00, 0x43, 0xf7, 0x00, 0x00, 0x00,
|
||||
0xc1, 0x00, 0x24, 0x01, 0x00, 0x21, 0x01, 0x00,
|
||||
0x28, 0x0c, 0x43, 0x02, 0x01, 0xe6, 0x03, 0x01,
|
||||
0x00, 0x01, 0x03, 0x00, 0x01, 0x21, 0x01, 0xf0,
|
||||
0x03, 0x00, 0x01, 0x00, 0x0c, 0x42, 0x02, 0x01,
|
||||
0x00, 0x01, 0x00, 0x01, 0x03, 0x00, 0x00, 0x0e,
|
||||
0x01, 0xea, 0x03, 0x00, 0x01, 0x00, 0x39, 0x98,
|
||||
0x00, 0x00, 0x00, 0x43, 0xf9, 0x00, 0x00, 0x00,
|
||||
0xd3, 0x25, 0x01, 0x00, 0x39, 0x95, 0x00, 0x00,
|
||||
0x00, 0x43, 0x7b, 0x00, 0x00, 0x00, 0xd3, 0x24,
|
||||
0x01, 0x00, 0x43, 0xf7, 0x00, 0x00, 0x00, 0xc1,
|
||||
0x00, 0x24, 0x01, 0x00, 0x43, 0x5c, 0x00, 0x00,
|
||||
0x00, 0xc2, 0x25, 0x01, 0x00, 0x0c, 0x43, 0x02,
|
||||
0x01, 0xce, 0x03, 0x03, 0x0a, 0x03, 0x07, 0x08,
|
||||
0x00, 0x96, 0x04, 0x0d, 0xf4, 0x03, 0x00, 0x01,
|
||||
0x00, 0xf6, 0x03, 0x00, 0x01, 0x00, 0xf8, 0x03,
|
||||
0x00, 0x01, 0x00, 0xfa, 0x03, 0x01, 0x00, 0x30,
|
||||
0xfc, 0x03, 0x01, 0x01, 0x30, 0xfe, 0x03, 0x01,
|
||||
0x02, 0x30, 0x80, 0x04, 0x01, 0x03, 0x30, 0x82,
|
||||
0x04, 0x01, 0x04, 0x30, 0x84, 0x04, 0x01, 0x05,
|
||||
0x30, 0x86, 0x04, 0x01, 0x06, 0x30, 0x88, 0x04,
|
||||
0x01, 0x07, 0x30, 0x8a, 0x04, 0x01, 0x08, 0x30,
|
||||
0x8c, 0x04, 0x01, 0x09, 0x30, 0xd2, 0x03, 0x00,
|
||||
0x0c, 0xd6, 0x03, 0x02, 0x0c, 0xdc, 0x03, 0x05,
|
||||
0x0c, 0xde, 0x03, 0x06, 0x0c, 0xe0, 0x03, 0x07,
|
||||
0x0c, 0xd4, 0x03, 0x01, 0x0c, 0xe2, 0x03, 0x08,
|
||||
0x0c, 0xe4, 0x03, 0x09, 0x00, 0x62, 0x09, 0x00,
|
||||
0x62, 0x08, 0x00, 0x62, 0x07, 0x00, 0x62, 0x06,
|
||||
0x00, 0x62, 0x05, 0x00, 0x62, 0x04, 0x00, 0x62,
|
||||
0x03, 0x00, 0x62, 0x02, 0x00, 0x62, 0x01, 0x00,
|
||||
0x62, 0x00, 0x00, 0x66, 0x00, 0x00, 0x43, 0x07,
|
||||
0x01, 0x00, 0x00, 0xd3, 0x24, 0x01, 0x00, 0xcb,
|
||||
0x63, 0x00, 0x00, 0x97, 0xec, 0x19, 0x39, 0x96,
|
||||
0x00, 0x00, 0x00, 0x11, 0x04, 0x08, 0x01, 0x00,
|
||||
0x00, 0x43, 0x5d, 0x00, 0x00, 0x00, 0xd3, 0x24,
|
||||
0x01, 0x00, 0x21, 0x01, 0x00, 0x30, 0x66, 0x00,
|
||||
0x00, 0x43, 0x09, 0x01, 0x00, 0x00, 0x63, 0x00,
|
||||
0x00, 0x0b, 0x0a, 0x4d, 0x0a, 0x01, 0x00, 0x00,
|
||||
0x0a, 0x4d, 0x0b, 0x01, 0x00, 0x00, 0x24, 0x02,
|
||||
0x00, 0xcc, 0x39, 0xa7, 0x00, 0x00, 0x00, 0x11,
|
||||
0x66, 0x01, 0x00, 0x43, 0x0c, 0x01, 0x00, 0x00,
|
||||
0x63, 0x01, 0x00, 0x66, 0x02, 0x00, 0x66, 0x03,
|
||||
0x00, 0xa5, 0x66, 0x04, 0x00, 0xa5, 0x24, 0x02,
|
||||
0x00, 0x21, 0x01, 0x00, 0xcd, 0xd5, 0x11, 0xb1,
|
||||
0xec, 0x1c, 0x0e, 0x66, 0x05, 0x00, 0x43, 0x0d,
|
||||
0x01, 0x00, 0x00, 0x24, 0x00, 0x00, 0x11, 0xb1,
|
||||
0xec, 0x0c, 0x0e, 0x39, 0x8d, 0x00, 0x00, 0x00,
|
||||
0x42, 0x0e, 0x01, 0x00, 0x00, 0xce, 0x66, 0x00,
|
||||
0x00, 0x43, 0x07, 0x01, 0x00, 0x00, 0x63, 0x03,
|
||||
0x00, 0x0b, 0x0a, 0x4d, 0x0f, 0x01, 0x00, 0x00,
|
||||
0x24, 0x02, 0x00, 0xc4, 0x04, 0x63, 0x04, 0x00,
|
||||
0x97, 0xec, 0x1b, 0x39, 0x96, 0x00, 0x00, 0x00,
|
||||
0x11, 0x04, 0x10, 0x01, 0x00, 0x00, 0x43, 0x5d,
|
||||
0x00, 0x00, 0x00, 0x63, 0x03, 0x00, 0x24, 0x01,
|
||||
0x00, 0x21, 0x01, 0x00, 0x30, 0x63, 0x04, 0x00,
|
||||
0xeb, 0xc4, 0x05, 0x63, 0x04, 0x00, 0x42, 0x11,
|
||||
0x01, 0x00, 0x00, 0x43, 0x12, 0x01, 0x00, 0x00,
|
||||
0x63, 0x05, 0x00, 0x63, 0x02, 0x00, 0xeb, 0x9e,
|
||||
0x66, 0x06, 0x00, 0x42, 0x13, 0x01, 0x00, 0x00,
|
||||
0x9e, 0x24, 0x01, 0x00, 0xc4, 0x06, 0x39, 0xa7,
|
||||
0x00, 0x00, 0x00, 0x11, 0x63, 0x06, 0x00, 0x21,
|
||||
0x01, 0x00, 0xc4, 0x07, 0x63, 0x07, 0x00, 0x43,
|
||||
0x43, 0x00, 0x00, 0x00, 0x63, 0x02, 0x00, 0x63,
|
||||
0x05, 0x00, 0x24, 0x02, 0x00, 0x0e, 0x63, 0x07,
|
||||
0x00, 0x43, 0x43, 0x00, 0x00, 0x00, 0x5f, 0x07,
|
||||
0x00, 0x66, 0x06, 0x00, 0x42, 0x14, 0x01, 0x00,
|
||||
0x00, 0xf1, 0x63, 0x05, 0x00, 0x63, 0x02, 0x00,
|
||||
0xeb, 0x9e, 0x24, 0x02, 0x00, 0x0e, 0x39, 0xb1,
|
||||
0x00, 0x00, 0x00, 0x11, 0x63, 0x06, 0x00, 0x63,
|
||||
0x05, 0x00, 0x63, 0x02, 0x00, 0xeb, 0x9e, 0x66,
|
||||
0x06, 0x00, 0x42, 0x15, 0x01, 0x00, 0x00, 0x9e,
|
||||
0x66, 0x06, 0x00, 0x42, 0x16, 0x01, 0x00, 0x00,
|
||||
0x21, 0x03, 0x00, 0xc4, 0x08, 0x63, 0x08, 0x00,
|
||||
0x43, 0x17, 0x01, 0x00, 0x00, 0xb6, 0x63, 0x05,
|
||||
0x00, 0x0a, 0x24, 0x03, 0x00, 0x0e, 0x66, 0x05,
|
||||
0x00, 0x43, 0x18, 0x01, 0x00, 0x00, 0xd4, 0x66,
|
||||
0x05, 0x00, 0x42, 0x19, 0x01, 0x00, 0x00, 0x66,
|
||||
0x05, 0x00, 0x42, 0x1a, 0x01, 0x00, 0x00, 0xa5,
|
||||
0x66, 0x05, 0x00, 0x42, 0x1b, 0x01, 0x00, 0x00,
|
||||
0xa5, 0xbf, 0xed, 0x01, 0x24, 0x03, 0x00, 0xc4,
|
||||
0x09, 0x63, 0x09, 0x00, 0xb6, 0xa7, 0xec, 0x19,
|
||||
0x39, 0x96, 0x00, 0x00, 0x00, 0x11, 0x04, 0x1c,
|
||||
0x01, 0x00, 0x00, 0x43, 0x5d, 0x00, 0x00, 0x00,
|
||||
0xd4, 0x24, 0x01, 0x00, 0x21, 0x01, 0x00, 0x30,
|
||||
0x66, 0x05, 0x00, 0x43, 0x0c, 0x01, 0x00, 0x00,
|
||||
0x63, 0x09, 0x00, 0x63, 0x06, 0x00, 0xb6, 0x63,
|
||||
0x06, 0x00, 0x42, 0x1d, 0x01, 0x00, 0x00, 0x24,
|
||||
0x04, 0x00, 0xb6, 0xa7, 0xec, 0x1f, 0x66, 0x05,
|
||||
0x00, 0x43, 0x1e, 0x01, 0x00, 0x00, 0x63, 0x09,
|
||||
0x00, 0x24, 0x01, 0x00, 0x0e, 0x39, 0x96, 0x00,
|
||||
0x00, 0x00, 0x11, 0x04, 0x1f, 0x01, 0x00, 0x00,
|
||||
0x21, 0x01, 0x00, 0x30, 0x66, 0x05, 0x00, 0x43,
|
||||
0x1e, 0x01, 0x00, 0x00, 0x63, 0x09, 0x00, 0x24,
|
||||
0x01, 0x00, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xd0,
|
||||
0x03, 0x00, 0x09, 0x00, 0x07, 0x07, 0x00, 0xb4,
|
||||
0x04, 0x09, 0xc0, 0x04, 0x01, 0x00, 0x30, 0x82,
|
||||
0x04, 0x01, 0x01, 0x30, 0xc2, 0x04, 0x01, 0x02,
|
||||
0x20, 0xc4, 0x04, 0x01, 0x03, 0x30, 0xc6, 0x04,
|
||||
0x01, 0x04, 0x30, 0x8a, 0x04, 0x01, 0x05, 0x30,
|
||||
0xc8, 0x04, 0x01, 0x06, 0x30, 0xfe, 0x03, 0x01,
|
||||
0x07, 0x30, 0xfc, 0x03, 0x01, 0x08, 0x30, 0xd4,
|
||||
0x03, 0x01, 0x0c, 0xd2, 0x03, 0x00, 0x0c, 0xe2,
|
||||
0x03, 0x08, 0x0c, 0xe6, 0x03, 0x0a, 0x00, 0xd6,
|
||||
0x03, 0x02, 0x0c, 0xd8, 0x03, 0x03, 0x0c, 0xda,
|
||||
0x03, 0x04, 0x0c, 0x62, 0x08, 0x00, 0x62, 0x07,
|
||||
0x00, 0x62, 0x06, 0x00, 0x62, 0x05, 0x00, 0x62,
|
||||
0x04, 0x00, 0x62, 0x03, 0x00, 0x62, 0x02, 0x00,
|
||||
0x62, 0x01, 0x00, 0x62, 0x00, 0x00, 0x66, 0x00,
|
||||
0x00, 0x43, 0x0d, 0x01, 0x00, 0x00, 0x24, 0x00,
|
||||
0x00, 0x11, 0xb1, 0xec, 0x0c, 0x0e, 0x39, 0x8d,
|
||||
0x00, 0x00, 0x00, 0x42, 0x0e, 0x01, 0x00, 0x00,
|
||||
0xcb, 0x66, 0x01, 0x00, 0x43, 0x18, 0x01, 0x00,
|
||||
0x00, 0x63, 0x00, 0x00, 0x04, 0x25, 0x01, 0x00,
|
||||
0x00, 0x24, 0x02, 0x00, 0xcc, 0x63, 0x01, 0x00,
|
||||
0x97, 0xec, 0x1b, 0x39, 0x96, 0x00, 0x00, 0x00,
|
||||
0x11, 0x04, 0x10, 0x01, 0x00, 0x00, 0x43, 0x5d,
|
||||
0x00, 0x00, 0x00, 0x63, 0x00, 0x00, 0x24, 0x01,
|
||||
0x00, 0x21, 0x01, 0x00, 0x30, 0x63, 0x01, 0x00,
|
||||
0x43, 0x26, 0x01, 0x00, 0x00, 0x66, 0x02, 0x00,
|
||||
0x42, 0x13, 0x01, 0x00, 0x00, 0x8d, 0x66, 0x01,
|
||||
0x00, 0x42, 0x27, 0x01, 0x00, 0x00, 0x24, 0x02,
|
||||
0x00, 0xcd, 0x63, 0x02, 0x00, 0xb6, 0xa7, 0xec,
|
||||
0x1c, 0x39, 0x96, 0x00, 0x00, 0x00, 0x11, 0x04,
|
||||
0x28, 0x01, 0x00, 0x00, 0x43, 0x5d, 0x00, 0x00,
|
||||
0x00, 0x63, 0x02, 0x00, 0x8d, 0x24, 0x01, 0x00,
|
||||
0x21, 0x01, 0x00, 0x30, 0x39, 0xa7, 0x00, 0x00,
|
||||
0x00, 0x11, 0x66, 0x02, 0x00, 0x42, 0x13, 0x01,
|
||||
0x00, 0x00, 0x21, 0x01, 0x00, 0xce, 0x63, 0x01,
|
||||
0x00, 0x43, 0x29, 0x01, 0x00, 0x00, 0x63, 0x03,
|
||||
0x00, 0x42, 0x11, 0x01, 0x00, 0x00, 0xb6, 0x66,
|
||||
0x02, 0x00, 0x42, 0x13, 0x01, 0x00, 0x00, 0x24,
|
||||
0x03, 0x00, 0x0e, 0x39, 0xa7, 0x00, 0x00, 0x00,
|
||||
0x11, 0x63, 0x03, 0x00, 0x42, 0x11, 0x01, 0x00,
|
||||
0x00, 0xb6, 0x66, 0x02, 0x00, 0x42, 0x15, 0x01,
|
||||
0x00, 0x00, 0x21, 0x03, 0x00, 0xc4, 0x04, 0xe2,
|
||||
0x63, 0x04, 0x00, 0xf1, 0x66, 0x02, 0x00, 0x42,
|
||||
0x14, 0x01, 0x00, 0x00, 0xb0, 0xec, 0x1c, 0x63,
|
||||
0x01, 0x00, 0x43, 0x1e, 0x01, 0x00, 0x00, 0x24,
|
||||
0x00, 0x00, 0x0e, 0x39, 0x96, 0x00, 0x00, 0x00,
|
||||
0x11, 0x04, 0x2a, 0x01, 0x00, 0x00, 0x21, 0x01,
|
||||
0x00, 0x30, 0x39, 0xb1, 0x00, 0x00, 0x00, 0x11,
|
||||
0x63, 0x03, 0x00, 0x42, 0x11, 0x01, 0x00, 0x00,
|
||||
0x66, 0x02, 0x00, 0x42, 0x15, 0x01, 0x00, 0x00,
|
||||
0x66, 0x02, 0x00, 0x42, 0x16, 0x01, 0x00, 0x00,
|
||||
0x21, 0x03, 0x00, 0xc4, 0x05, 0x63, 0x05, 0x00,
|
||||
0x43, 0x2b, 0x01, 0x00, 0x00, 0xb6, 0x0a, 0x24,
|
||||
0x02, 0x00, 0xc4, 0x06, 0x39, 0xa7, 0x00, 0x00,
|
||||
0x00, 0x11, 0x63, 0x06, 0x00, 0x66, 0x02, 0x00,
|
||||
0x42, 0x13, 0x01, 0x00, 0x00, 0x9f, 0x21, 0x01,
|
||||
0x00, 0xc4, 0x07, 0x63, 0x01, 0x00, 0x43, 0x26,
|
||||
0x01, 0x00, 0x00, 0x63, 0x06, 0x00, 0x66, 0x01,
|
||||
0x00, 0x42, 0x2c, 0x01, 0x00, 0x00, 0x24, 0x02,
|
||||
0x00, 0x11, 0x64, 0x02, 0x00, 0x0e, 0x63, 0x02,
|
||||
0x00, 0xb6, 0xa7, 0xec, 0x28, 0x63, 0x01, 0x00,
|
||||
0x43, 0x1e, 0x01, 0x00, 0x00, 0x24, 0x00, 0x00,
|
||||
0x0e, 0x39, 0x96, 0x00, 0x00, 0x00, 0x11, 0x04,
|
||||
0x28, 0x01, 0x00, 0x00, 0x43, 0x5d, 0x00, 0x00,
|
||||
0x00, 0x63, 0x02, 0x00, 0x8d, 0x24, 0x01, 0x00,
|
||||
0x21, 0x01, 0x00, 0x30, 0x63, 0x01, 0x00, 0x43,
|
||||
0x29, 0x01, 0x00, 0x00, 0x63, 0x07, 0x00, 0x42,
|
||||
0x11, 0x01, 0x00, 0x00, 0xb6, 0x63, 0x07, 0x00,
|
||||
0xeb, 0x24, 0x03, 0x00, 0x0e, 0x63, 0x01, 0x00,
|
||||
0x43, 0x2d, 0x01, 0x00, 0x00, 0x24, 0x00, 0x00,
|
||||
0xec, 0x1c, 0x63, 0x01, 0x00, 0x43, 0x1e, 0x01,
|
||||
0x00, 0x00, 0x24, 0x00, 0x00, 0x0e, 0x39, 0x96,
|
||||
0x00, 0x00, 0x00, 0x11, 0x04, 0x2e, 0x01, 0x00,
|
||||
0x00, 0x21, 0x01, 0x00, 0x30, 0x63, 0x01, 0x00,
|
||||
0x43, 0x1e, 0x01, 0x00, 0x00, 0x24, 0x00, 0x00,
|
||||
0x0e, 0x66, 0x04, 0x00, 0x43, 0x29, 0x01, 0x00,
|
||||
0x00, 0x63, 0x07, 0x00, 0x42, 0x11, 0x01, 0x00,
|
||||
0x00, 0xb6, 0x63, 0x07, 0x00, 0xeb, 0x66, 0x05,
|
||||
0x00, 0x66, 0x06, 0x00, 0xa5, 0x24, 0x04, 0x00,
|
||||
0xc4, 0x08, 0x66, 0x01, 0x00, 0x43, 0x09, 0x01,
|
||||
0x00, 0x00, 0x63, 0x08, 0x00, 0x0b, 0x0a, 0x4d,
|
||||
0x2f, 0x01, 0x00, 0x00, 0x25, 0x02, 0x00, 0x08,
|
||||
0xec, 0x16, 0xc1, 0x00, 0x60, 0x09, 0x00, 0xc1,
|
||||
0x01, 0x60, 0x0a, 0x00, 0xc1, 0x02, 0x60, 0x0b,
|
||||
0x00, 0xc1, 0x03, 0x60, 0x0c, 0x00, 0x29, 0xb7,
|
||||
0xb6, 0xa0, 0xe6, 0xb7, 0xb9, 0xa0, 0x60, 0x04,
|
||||
0x00, 0xb7, 0xb6, 0xa0, 0x60, 0x05, 0x00, 0xb7,
|
||||
0xb9, 0xa0, 0x60, 0x06, 0x00, 0xb7, 0xba, 0xa0,
|
||||
0x60, 0x07, 0x00, 0x0b, 0x04, 0x30, 0x01, 0x00,
|
||||
0x00, 0x4d, 0x14, 0x01, 0x00, 0x00, 0xbe, 0x08,
|
||||
0x4d, 0x15, 0x01, 0x00, 0x00, 0xba, 0x4d, 0x16,
|
||||
0x01, 0x00, 0x00, 0xbe, 0x0c, 0x4d, 0x13, 0x01,
|
||||
0x00, 0x00, 0x60, 0x08, 0x00, 0x06, 0x2f,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/* File generated automatically by the QuickJS-ng compiler. */
|
||||
|
||||
#include "quickjs-libc.h"
|
||||
|
||||
const uint32_t qjsc_test_fib_size = 294;
|
||||
|
||||
const uint8_t qjsc_test_fib[294] = {
|
||||
0x15, 0x0e, 0x01, 0x28, 0x65, 0x78, 0x61, 0x6d,
|
||||
0x70, 0x6c, 0x65, 0x73, 0x2f, 0x74, 0x65, 0x73,
|
||||
0x74, 0x5f, 0x66, 0x69, 0x62, 0x2e, 0x6a, 0x73,
|
||||
0x01, 0x0c, 0x71, 0x6a, 0x73, 0x3a, 0x6f, 0x73,
|
||||
0x01, 0x04, 0x6f, 0x73, 0x01, 0x0a, 0x69, 0x73,
|
||||
0x57, 0x69, 0x6e, 0x01, 0x06, 0x66, 0x69, 0x62,
|
||||
0x01, 0x10, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f,
|
||||
0x72, 0x6d, 0x01, 0x0a, 0x77, 0x69, 0x6e, 0x33,
|
||||
0x32, 0x01, 0x0c, 0x2e, 0x2f, 0x66, 0x69, 0x62,
|
||||
0x2e, 0x01, 0x06, 0x64, 0x6c, 0x6c, 0x01, 0x04,
|
||||
0x73, 0x6f, 0x01, 0x0e, 0x63, 0x6f, 0x6e, 0x73,
|
||||
0x6f, 0x6c, 0x65, 0x01, 0x06, 0x6c, 0x6f, 0x67,
|
||||
0x01, 0x16, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20,
|
||||
0x57, 0x6f, 0x72, 0x6c, 0x64, 0x01, 0x10, 0x66,
|
||||
0x69, 0x62, 0x28, 0x31, 0x30, 0x29, 0x3d, 0x0d,
|
||||
0xc6, 0x03, 0x01, 0xc8, 0x03, 0x00, 0x00, 0x01,
|
||||
0x00, 0xfe, 0x01, 0x00, 0x01, 0x0c, 0x20, 0x0a,
|
||||
0x01, 0xa2, 0x01, 0x00, 0x00, 0x00, 0x05, 0x03,
|
||||
0x00, 0x73, 0x00, 0xca, 0x03, 0x00, 0x0d, 0xcc,
|
||||
0x03, 0x00, 0x0d, 0xce, 0x03, 0x01, 0x0d, 0x08,
|
||||
0xec, 0x02, 0x29, 0x66, 0x00, 0x00, 0x42, 0xe8,
|
||||
0x00, 0x00, 0x00, 0x04, 0xe9, 0x00, 0x00, 0x00,
|
||||
0xaf, 0xe4, 0x06, 0x11, 0xf4, 0xed, 0x0b, 0x71,
|
||||
0x43, 0xe7, 0x00, 0x00, 0x00, 0xe5, 0x0e, 0xee,
|
||||
0x24, 0x0e, 0x04, 0xea, 0x00, 0x00, 0x00, 0x43,
|
||||
0x5d, 0x00, 0x00, 0x00, 0x66, 0x01, 0x00, 0xec,
|
||||
0x08, 0x04, 0xeb, 0x00, 0x00, 0x00, 0xee, 0x06,
|
||||
0x04, 0xec, 0x00, 0x00, 0x00, 0x24, 0x01, 0x00,
|
||||
0x36, 0x8c, 0xee, 0xd4, 0x39, 0xed, 0x00, 0x00,
|
||||
0x00, 0x43, 0xee, 0x00, 0x00, 0x00, 0x04, 0xef,
|
||||
0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, 0x39,
|
||||
0xed, 0x00, 0x00, 0x00, 0x43, 0xee, 0x00, 0x00,
|
||||
0x00, 0x04, 0xf0, 0x00, 0x00, 0x00, 0x66, 0x02,
|
||||
0x00, 0xbe, 0x0a, 0xf1, 0x24, 0x02, 0x00, 0x0e,
|
||||
0x06, 0x2f, 0xc6, 0x03, 0x01, 0x01, 0x0e, 0x41,
|
||||
0x3c, 0x00, 0x39, 0x06, 0x3b, 0x34, 0x10, 0x30,
|
||||
0x0f, 0x34, 0x10, 0x2a, 0x20, 0x00,
|
||||
};
|
||||
|
||||
static JSContext *JS_NewCustomContext(JSRuntime *rt)
|
||||
{
|
||||
JSContext *ctx = JS_NewContext(rt);
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
{
|
||||
extern JSModuleDef *js_init_module_os(JSContext *ctx, const char *name);
|
||||
js_init_module_os(ctx, "qjs:os");
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int r;
|
||||
JSRuntime *rt;
|
||||
JSContext *ctx;
|
||||
r = 0;
|
||||
rt = JS_NewRuntime();
|
||||
js_std_set_worker_new_context_func(JS_NewCustomContext);
|
||||
js_std_init_handlers(rt);
|
||||
JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);
|
||||
ctx = JS_NewCustomContext(rt);
|
||||
js_std_add_helpers(ctx, argc, argv);
|
||||
js_std_eval_binary(ctx, qjsc_test_fib, qjsc_test_fib_size, 0);
|
||||
r = js_std_loop(ctx);
|
||||
if (r) {
|
||||
js_std_dump_error(ctx);
|
||||
}
|
||||
js_std_free_handlers(rt);
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
return r;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Regular Expression Engine
|
||||
*
|
||||
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef DEF
|
||||
|
||||
DEF(invalid, 1) /* never used */
|
||||
DEF(char8, 2) /* 7 bits in fact */
|
||||
DEF(char16, 3)
|
||||
DEF(char32, 5)
|
||||
DEF(dot, 1)
|
||||
DEF(any, 1) /* same as dot but match any character including line terminator */
|
||||
DEF(line_start, 1)
|
||||
DEF(line_end, 1)
|
||||
DEF(goto, 5)
|
||||
DEF(split_goto_first, 5)
|
||||
DEF(split_next_first, 5)
|
||||
DEF(match, 1)
|
||||
DEF(save_start, 2) /* save start position */
|
||||
DEF(save_end, 2) /* save end position, must come after saved_start */
|
||||
DEF(save_reset, 3) /* reset save positions */
|
||||
DEF(loop, 5) /* decrement the top the stack and goto if != 0 */
|
||||
DEF(push_i32, 5) /* push integer on the stack */
|
||||
DEF(drop, 1)
|
||||
DEF(word_boundary, 1)
|
||||
DEF(not_word_boundary, 1)
|
||||
DEF(back_reference, 2)
|
||||
DEF(backward_back_reference, 2) /* must come after back_reference */
|
||||
DEF(range, 3) /* variable length */
|
||||
DEF(range32, 3) /* variable length */
|
||||
DEF(lookahead, 5)
|
||||
DEF(negative_lookahead, 5)
|
||||
DEF(push_char_pos, 1) /* push the character position on the stack */
|
||||
DEF(check_advance, 1) /* pop one stack element and check that it is different from the character position */
|
||||
DEF(prev, 1) /* go to the previous char */
|
||||
DEF(simple_greedy_quant, 17)
|
||||
|
||||
#endif /* DEF */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Regular Expression Engine
|
||||
*
|
||||
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef LIBREGEXP_H
|
||||
#define LIBREGEXP_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "libunicode.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define LRE_FLAG_GLOBAL (1 << 0)
|
||||
#define LRE_FLAG_IGNORECASE (1 << 1)
|
||||
#define LRE_FLAG_MULTILINE (1 << 2)
|
||||
#define LRE_FLAG_DOTALL (1 << 3)
|
||||
#define LRE_FLAG_UNICODE (1 << 4)
|
||||
#define LRE_FLAG_STICKY (1 << 5)
|
||||
#define LRE_FLAG_INDICES (1 << 6) /* Unused by libregexp, just recorded. */
|
||||
#define LRE_FLAG_NAMED_GROUPS (1 << 7) /* named groups are present in the regexp */
|
||||
#define LRE_FLAG_UNICODE_SETS (1 << 8)
|
||||
|
||||
#define LRE_RET_MEMORY_ERROR (-1)
|
||||
#define LRE_RET_TIMEOUT (-2)
|
||||
|
||||
uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size,
|
||||
const char *buf, size_t buf_len, int re_flags,
|
||||
void *opaque);
|
||||
int lre_get_capture_count(const uint8_t *bc_buf);
|
||||
int lre_get_flags(const uint8_t *bc_buf);
|
||||
const char *lre_get_groupnames(const uint8_t *bc_buf);
|
||||
int lre_exec(uint8_t **capture,
|
||||
const uint8_t *bc_buf, const uint8_t *cbuf, int cindex, int clen,
|
||||
int cbuf_type, void *opaque);
|
||||
|
||||
int lre_parse_escape(const uint8_t **pp, int allow_utf16);
|
||||
bool lre_is_space(int c);
|
||||
|
||||
void lre_byte_swap(uint8_t *buf, size_t len, bool is_byte_swapped);
|
||||
|
||||
/* must be provided by the user */
|
||||
bool lre_check_stack_overflow(void *opaque, size_t alloca_size);
|
||||
/* must be provided by the user, return non zero if time out */
|
||||
int lre_check_timeout(void *opaque);
|
||||
void *lre_realloc(void *opaque, void *ptr, size_t size);
|
||||
|
||||
/* JS identifier test */
|
||||
extern uint32_t const lre_id_start_table_ascii[4];
|
||||
extern uint32_t const lre_id_continue_table_ascii[4];
|
||||
|
||||
static inline int lre_js_is_ident_first(int c)
|
||||
{
|
||||
if ((uint32_t)c < 128) {
|
||||
return (lre_id_start_table_ascii[c >> 5] >> (c & 31)) & 1;
|
||||
} else {
|
||||
return lre_is_id_start(c);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int lre_js_is_ident_next(int c)
|
||||
{
|
||||
if ((uint32_t)c < 128) {
|
||||
return (lre_id_continue_table_ascii[c >> 5] >> (c & 31)) & 1;
|
||||
} else {
|
||||
/* ZWNJ and ZWJ are accepted in identifiers */
|
||||
return lre_is_id_continue(c) || c == 0x200C || c == 0x200D;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" { */
|
||||
#endif
|
||||
|
||||
#endif /* LIBREGEXP_H */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Unicode utilities
|
||||
*
|
||||
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef LIBUNICODE_H
|
||||
#define LIBUNICODE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define LRE_CC_RES_LEN_MAX 3
|
||||
|
||||
typedef enum {
|
||||
UNICODE_NFC,
|
||||
UNICODE_NFD,
|
||||
UNICODE_NFKC,
|
||||
UNICODE_NFKD,
|
||||
} UnicodeNormalizationEnum;
|
||||
|
||||
int lre_case_conv(uint32_t *res, uint32_t c, int conv_type);
|
||||
int lre_canonicalize(uint32_t c, bool is_unicode);
|
||||
bool lre_is_cased(uint32_t c);
|
||||
bool lre_is_case_ignorable(uint32_t c);
|
||||
|
||||
/* char ranges */
|
||||
|
||||
typedef struct {
|
||||
int len; /* in points, always even */
|
||||
int size;
|
||||
uint32_t *points; /* points sorted by increasing value */
|
||||
void *mem_opaque;
|
||||
void *(*realloc_func)(void *opaque, void *ptr, size_t size);
|
||||
} CharRange;
|
||||
|
||||
typedef enum {
|
||||
CR_OP_UNION,
|
||||
CR_OP_INTER,
|
||||
CR_OP_XOR,
|
||||
} CharRangeOpEnum;
|
||||
|
||||
void cr_init(CharRange *cr, void *mem_opaque, void *(*realloc_func)(void *opaque, void *ptr, size_t size));
|
||||
void cr_free(CharRange *cr);
|
||||
int cr_realloc(CharRange *cr, int size);
|
||||
int cr_copy(CharRange *cr, const CharRange *cr1);
|
||||
|
||||
static inline int cr_add_point(CharRange *cr, uint32_t v)
|
||||
{
|
||||
if (cr->len >= cr->size) {
|
||||
if (cr_realloc(cr, cr->len + 1))
|
||||
return -1;
|
||||
}
|
||||
cr->points[cr->len++] = v;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int cr_add_interval(CharRange *cr, uint32_t c1, uint32_t c2)
|
||||
{
|
||||
if ((cr->len + 2) > cr->size) {
|
||||
if (cr_realloc(cr, cr->len + 2))
|
||||
return -1;
|
||||
}
|
||||
cr->points[cr->len++] = c1;
|
||||
cr->points[cr->len++] = c2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cr_union1(CharRange *cr, const uint32_t *b_pt, int b_len);
|
||||
|
||||
static inline int cr_union_interval(CharRange *cr, uint32_t c1, uint32_t c2)
|
||||
{
|
||||
uint32_t b_pt[2];
|
||||
b_pt[0] = c1;
|
||||
b_pt[1] = c2 + 1;
|
||||
return cr_union1(cr, b_pt, 2);
|
||||
}
|
||||
|
||||
int cr_op(CharRange *cr, const uint32_t *a_pt, int a_len,
|
||||
const uint32_t *b_pt, int b_len, int op);
|
||||
|
||||
int cr_invert(CharRange *cr);
|
||||
int cr_regexp_canonicalize(CharRange *cr, bool is_unicode);
|
||||
|
||||
bool lre_is_id_start(uint32_t c);
|
||||
bool lre_is_id_continue(uint32_t c);
|
||||
bool lre_is_white_space(uint32_t c);
|
||||
|
||||
int unicode_normalize(uint32_t **pdst, const uint32_t *src, int src_len,
|
||||
UnicodeNormalizationEnum n_type,
|
||||
void *opaque, void *(*realloc_func)(void *opaque, void *ptr, size_t size));
|
||||
|
||||
/* Unicode character range functions */
|
||||
|
||||
int unicode_script(CharRange *cr,
|
||||
const char *script_name, bool is_ext);
|
||||
int unicode_general_category(CharRange *cr, const char *gc_name);
|
||||
int unicode_prop(CharRange *cr, const char *prop_name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" { */
|
||||
#endif
|
||||
|
||||
#endif /* LIBUNICODE_H */
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Linux klist like system
|
||||
*
|
||||
* Copyright (c) 2016-2017 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef LIST_H
|
||||
#define LIST_H
|
||||
|
||||
#ifndef NULL
|
||||
#include <stddef.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct list_head {
|
||||
struct list_head *prev;
|
||||
struct list_head *next;
|
||||
};
|
||||
|
||||
#define LIST_HEAD_INIT(el) { &(el), &(el) }
|
||||
|
||||
/* return the pointer of type 'type *' containing 'el' as field 'member' */
|
||||
#define list_entry(el, type, member) container_of(el, type, member)
|
||||
|
||||
static inline void init_list_head(struct list_head *head)
|
||||
{
|
||||
head->prev = head;
|
||||
head->next = head;
|
||||
}
|
||||
|
||||
/* insert 'el' between 'prev' and 'next' */
|
||||
static inline void __list_add(struct list_head *el,
|
||||
struct list_head *prev, struct list_head *next)
|
||||
{
|
||||
prev->next = el;
|
||||
el->prev = prev;
|
||||
el->next = next;
|
||||
next->prev = el;
|
||||
}
|
||||
|
||||
/* add 'el' at the head of the list 'head' (= after element head) */
|
||||
static inline void list_add(struct list_head *el, struct list_head *head)
|
||||
{
|
||||
__list_add(el, head, head->next);
|
||||
}
|
||||
|
||||
/* add 'el' at the end of the list 'head' (= before element head) */
|
||||
static inline void list_add_tail(struct list_head *el, struct list_head *head)
|
||||
{
|
||||
__list_add(el, head->prev, head);
|
||||
}
|
||||
|
||||
static inline void list_del(struct list_head *el)
|
||||
{
|
||||
struct list_head *prev, *next;
|
||||
prev = el->prev;
|
||||
next = el->next;
|
||||
prev->next = next;
|
||||
next->prev = prev;
|
||||
el->prev = NULL; /* fail safe */
|
||||
el->next = NULL; /* fail safe */
|
||||
}
|
||||
|
||||
static inline int list_empty(struct list_head *el)
|
||||
{
|
||||
return el->next == el;
|
||||
}
|
||||
|
||||
#define list_for_each(el, head) \
|
||||
for(el = (head)->next; el != (head); el = el->next)
|
||||
|
||||
#define list_for_each_safe(el, el1, head) \
|
||||
for(el = (head)->next, el1 = el->next; el != (head); \
|
||||
el = el1, el1 = el->next)
|
||||
|
||||
#define list_for_each_prev(el, head) \
|
||||
for(el = (head)->prev; el != (head); el = el->prev)
|
||||
|
||||
#define list_for_each_prev_safe(el, el1, head) \
|
||||
for(el = (head)->prev, el1 = el->prev; el != (head); \
|
||||
el = el1, el1 = el->prev)
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" { */
|
||||
#endif
|
||||
|
||||
#endif /* LIST_H */
|
||||
@@ -0,0 +1,635 @@
|
||||
project(
|
||||
'quickjs-ng',
|
||||
'c',
|
||||
version: '0.11.0',
|
||||
default_options: [
|
||||
'c_std=gnu11,c11',
|
||||
'warning_level=3',
|
||||
'default_library=static',
|
||||
],
|
||||
license: 'MIT',
|
||||
license_files: 'LICENSE',
|
||||
meson_version: '>=1.3.0',
|
||||
)
|
||||
|
||||
host_system = host_machine.system()
|
||||
cc = meson.get_compiler('c')
|
||||
|
||||
qjs_gcc_warning_args = [
|
||||
'-Wno-unsafe-buffer-usage',
|
||||
'-Wno-sign-conversion',
|
||||
'-Wno-nonportable-system-include-path',
|
||||
'-Wno-implicit-int-conversion',
|
||||
'-Wno-shorten-64-to-32',
|
||||
'-Wno-reserved-macro-identifier',
|
||||
'-Wno-reserved-identifier',
|
||||
'-Wdeprecated-declarations',
|
||||
|
||||
'-Wno-implicit-fallthrough',
|
||||
'-Wno-sign-compare',
|
||||
'-Wno-missing-field-initializers',
|
||||
'-Wno-unused-parameter',
|
||||
'-Wno-unused-but-set-variable',
|
||||
'-Wno-array-bounds',
|
||||
'-Wno-format-truncation',
|
||||
]
|
||||
qjs_gcc_args = [
|
||||
'-funsigned-char',
|
||||
]
|
||||
|
||||
if host_system == 'darwin'
|
||||
# https://github.com/quickjs-ng/quickjs/issues/453
|
||||
qjs_gcc_warning_args += '-Wno-maybe-uninitialized'
|
||||
endif
|
||||
|
||||
# https://github.com/microsoft/cpp-docs/tree/main/docs/error-messages/compiler-warnings
|
||||
qjs_msvc_warning_args = [
|
||||
'/wd4018', # -Wno-sign-conversion
|
||||
'/wd4061', # -Wno-implicit-fallthrough
|
||||
'/wd4100', # -Wno-unused-parameter
|
||||
'/wd4200', # -Wno-zero-length-array
|
||||
'/wd4242', # -Wno-shorten-64-to-32
|
||||
'/wd4244', # -Wno-shorten-64-to-32
|
||||
'/wd4245', # -Wno-sign-compare
|
||||
'/wd4267', # -Wno-shorten-64-to-32
|
||||
'/wd4388', # -Wno-sign-compare
|
||||
'/wd4389', # -Wno-sign-compare
|
||||
'/wd4710', # Function not inlined
|
||||
'/wd4711', # Function was inlined
|
||||
'/wd4820', # Padding added after construct
|
||||
'/wd4996', # -Wdeprecated-declarations
|
||||
'/wd5045', # Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified
|
||||
]
|
||||
qjs_msvc_args = [
|
||||
'/experimental:c11atomics',
|
||||
'/J', # -funsigned-char
|
||||
]
|
||||
|
||||
if cc.get_argument_syntax() == 'msvc'
|
||||
add_project_arguments(
|
||||
cc.get_supported_arguments(qjs_msvc_warning_args),
|
||||
cc.get_id().contains('clang') ? cc.get_supported_arguments(qjs_gcc_warning_args) : [],
|
||||
qjs_msvc_args,
|
||||
language: 'c',
|
||||
)
|
||||
else
|
||||
add_project_arguments(
|
||||
cc.get_supported_arguments(qjs_gcc_warning_args),
|
||||
qjs_gcc_args,
|
||||
language: 'c',
|
||||
)
|
||||
endif
|
||||
|
||||
if host_system == 'windows'
|
||||
# Set a 8MB default stack size on Windows.
|
||||
# It defaults to 1MB on MSVC, which is the same as our current JS stack size,
|
||||
# so it will overflow and crash otherwise.
|
||||
# On MinGW it defaults to 2MB.
|
||||
stack_size = 8 * 1024 * 1024
|
||||
if cc.get_argument_syntax() == 'msvc'
|
||||
add_project_link_arguments(f'/STACK:@stack_size@', language: 'c')
|
||||
else
|
||||
add_project_link_arguments(f'-Wl,--stack,@stack_size@', language: 'c')
|
||||
endif
|
||||
endif
|
||||
|
||||
if meson.is_cross_build()
|
||||
native_cc = meson.get_compiler('c', native: true)
|
||||
|
||||
if native_cc.get_argument_syntax() == 'msvc'
|
||||
# https://github.com/microsoft/cpp-docs/tree/main/docs/error-messages/compiler-warnings
|
||||
add_project_arguments(
|
||||
native_cc.get_supported_arguments(qjs_msvc_warning_args),
|
||||
native_cc.get_id().contains('clang') ? native_cc.get_supported_arguments(qjs_gcc_warning_args) : [],
|
||||
qjs_msvc_args,
|
||||
|
||||
language: 'c',
|
||||
native: true,
|
||||
)
|
||||
else
|
||||
add_project_arguments(
|
||||
native_cc.get_supported_arguments(qjs_gcc_warning_args),
|
||||
qjs_gcc_args,
|
||||
|
||||
language: 'c',
|
||||
native: true,
|
||||
)
|
||||
endif
|
||||
endif
|
||||
if get_option('debug')
|
||||
add_project_arguments(
|
||||
cc.get_supported_arguments('-fno-omit-frame-pointer'),
|
||||
language: 'c',
|
||||
)
|
||||
endif
|
||||
|
||||
qjs_sys_deps = []
|
||||
|
||||
m_dep = cc.find_library('m', required: false)
|
||||
qjs_sys_deps += m_dep
|
||||
qjs_sys_deps += dependency('threads', required: false)
|
||||
qjs_sys_deps += dependency('dl', required: false)
|
||||
|
||||
qjs_srcs = files(
|
||||
'cutils.c',
|
||||
'dtoa.c',
|
||||
'libregexp.c',
|
||||
'libunicode.c',
|
||||
'quickjs.c',
|
||||
)
|
||||
qjs_hdrs = files(
|
||||
'quickjs.h',
|
||||
)
|
||||
|
||||
qjs_libc = get_option('libc')
|
||||
qjs_libc_srcs = files('quickjs-libc.c')
|
||||
qjs_libc_hdrs = files('quickjs-libc.h')
|
||||
|
||||
if qjs_libc
|
||||
qjs_hdrs += qjs_libc_hdrs
|
||||
endif
|
||||
|
||||
qjs_parser = get_option('parser')
|
||||
|
||||
qjs_c_args = ['-D_GNU_SOURCE']
|
||||
|
||||
if host_system == 'windows'
|
||||
qjs_c_args += ['-DWIN32_LEAN_AND_MEAN', '-D_WIN32_WINNT=0x0601']
|
||||
endif
|
||||
|
||||
if not qjs_parser
|
||||
qjs_c_args += ['-DQJS_DISABLE_PARSER']
|
||||
endif
|
||||
|
||||
qjs_libc_lib = static_library(
|
||||
'quickjs-libc',
|
||||
qjs_libc_srcs,
|
||||
|
||||
dependencies: qjs_sys_deps,
|
||||
c_args: qjs_c_args,
|
||||
gnu_symbol_visibility: 'hidden',
|
||||
)
|
||||
|
||||
qjs_lib = library(
|
||||
'qjs',
|
||||
qjs_srcs,
|
||||
|
||||
# export public headers
|
||||
generator(
|
||||
find_program('cp', 'xcopy'),
|
||||
output: ['@PLAINNAME@'],
|
||||
arguments: ['@INPUT@', '@OUTPUT@'],
|
||||
).process(qjs_hdrs),
|
||||
|
||||
dependencies: qjs_sys_deps,
|
||||
link_whole: qjs_libc ? qjs_libc_lib : [],
|
||||
c_args: qjs_c_args,
|
||||
gnu_symbol_visibility: 'hidden',
|
||||
|
||||
install: true,
|
||||
version: meson.project_version(),
|
||||
)
|
||||
|
||||
qjs_export_variables = [
|
||||
f'have_parser=@qjs_parser@'
|
||||
]
|
||||
|
||||
qjs_dep = declare_dependency(
|
||||
link_with: qjs_lib,
|
||||
dependencies: qjs_sys_deps,
|
||||
include_directories: qjs_lib.private_dir_include(),
|
||||
variables: qjs_export_variables,
|
||||
)
|
||||
|
||||
if host_system == 'emscripten'
|
||||
qjs_wasm_export_name = 'getQuickJs'
|
||||
executable(
|
||||
'qjs_wasm',
|
||||
qjs_srcs,
|
||||
link_args: cc.get_supported_link_arguments(
|
||||
# in emscripten 3.x, this will be set to 16k which is too small for quickjs.
|
||||
'-sSTACK_SIZE=@0@'.format(2 * 1024 * 1024), # let it be 2m = 2 * 1024 * 1024, otherwise, stack overflow may be occured at bootstrap
|
||||
'-sNO_INVOKE_RUN',
|
||||
'-sNO_EXIT_RUNTIME',
|
||||
'-sMODULARIZE', # do not mess the global
|
||||
'-sEXPORT_ES6', # export js file to morden es module
|
||||
'-sEXPORT_NAME=@0@'.format(qjs_wasm_export_name), # give a name
|
||||
'-sTEXTDECODER=1', # it will be 2 if we use -Oz, and that will cause js -> c string convertion fail
|
||||
'-sNO_DEFAULT_TO_CXX', # this project is pure c project, no need for c plus plus handle
|
||||
'-sEXPORTED_RUNTIME_METHODS=ccall,cwrap',
|
||||
),
|
||||
dependencies: m_dep,
|
||||
c_args: qjs_c_args,
|
||||
)
|
||||
endif
|
||||
|
||||
install_headers(qjs_hdrs, subdir: 'quickjs-ng')
|
||||
|
||||
if not meson.is_subproject()
|
||||
docdir = get_option('docdir')
|
||||
datadir = get_option('datadir')
|
||||
|
||||
if docdir == ''
|
||||
docdir = datadir / 'doc' / meson.project_name()
|
||||
endif
|
||||
install_data(
|
||||
'LICENSE',
|
||||
install_dir: docdir,
|
||||
|
||||
install_tag: 'doc',
|
||||
)
|
||||
install_subdir(
|
||||
'examples',
|
||||
install_dir: docdir,
|
||||
|
||||
strip_directory: false,
|
||||
install_tag: 'doc',
|
||||
)
|
||||
endif
|
||||
|
||||
meson.override_dependency('quickjs-ng', qjs_dep)
|
||||
|
||||
import('pkgconfig').generate(
|
||||
qjs_lib,
|
||||
subdirs: 'quickjs-ng',
|
||||
name: 'quickjs-ng',
|
||||
description: 'QuickJS, the Next Generation: a mighty JavaScript engine',
|
||||
url: 'https://github.com/quickjs-ng/quickjs',
|
||||
version: meson.project_version(),
|
||||
variables: qjs_export_variables,
|
||||
)
|
||||
|
||||
if not qjs_parser
|
||||
subdir_done()
|
||||
endif
|
||||
|
||||
# QuickJS bytecode compiler
|
||||
qjsc_srcs = files(
|
||||
'qjsc.c',
|
||||
)
|
||||
qjsc_exe = executable(
|
||||
'qjsc',
|
||||
qjsc_srcs,
|
||||
|
||||
c_args: qjs_c_args,
|
||||
link_with: qjs_libc ? [] : qjs_libc_lib,
|
||||
dependencies: qjs_dep,
|
||||
|
||||
install: true,
|
||||
)
|
||||
|
||||
mimalloc_dep = []
|
||||
mimalloc_sys_dep = dependency('mimalloc', required: get_option('cli_mimalloc'))
|
||||
if mimalloc_sys_dep.found()
|
||||
mimalloc_dep = declare_dependency(
|
||||
dependencies: mimalloc_sys_dep,
|
||||
compile_args: '-DQJS_USE_MIMALLOC',
|
||||
)
|
||||
endif
|
||||
|
||||
# QuickJS CLI
|
||||
qjs_exe_srcs = files(
|
||||
'gen/repl.c',
|
||||
'gen/standalone.c',
|
||||
'qjs.c',
|
||||
)
|
||||
qjs_exe = executable(
|
||||
'qjs',
|
||||
qjs_exe_srcs,
|
||||
|
||||
c_args: qjs_c_args,
|
||||
link_with: qjs_libc ? [] : qjs_libc_lib,
|
||||
dependencies: [qjs_dep, mimalloc_dep],
|
||||
export_dynamic: true,
|
||||
|
||||
install: true,
|
||||
)
|
||||
|
||||
if meson.is_cross_build()
|
||||
mimalloc_native_dep = []
|
||||
mimalloc_sys_native_dep = dependency('mimalloc', required: get_option('cli_mimalloc'), native: true)
|
||||
if mimalloc_sys_dep.found()
|
||||
mimalloc_native_dep = declare_dependency(
|
||||
dependencies: mimalloc_sys_native_dep,
|
||||
compile_args: '-DQJS_USE_MIMALLOC',
|
||||
)
|
||||
endif
|
||||
|
||||
qjs_sys_native_deps = [
|
||||
native_cc.find_library('m', required: false),
|
||||
dependency('threads', required: false, native: true),
|
||||
dependency('dl', required: false, native: true),
|
||||
]
|
||||
qjs_native_lib = static_library(
|
||||
'qjs_native',
|
||||
qjs_srcs,
|
||||
qjs_libc_srcs,
|
||||
|
||||
dependencies: qjs_sys_native_deps,
|
||||
c_args: qjs_c_args,
|
||||
gnu_symbol_visibility: 'hidden',
|
||||
|
||||
build_by_default: false,
|
||||
native: true,
|
||||
install: false,
|
||||
)
|
||||
|
||||
meson.override_find_program(
|
||||
'qjsc',
|
||||
executable(
|
||||
'qjsc_native',
|
||||
qjsc_srcs,
|
||||
|
||||
c_args: qjs_c_args,
|
||||
link_with: qjs_native_lib,
|
||||
dependencies: qjs_sys_native_deps,
|
||||
|
||||
build_by_default: false,
|
||||
native: true,
|
||||
install: false,
|
||||
),
|
||||
)
|
||||
meson.override_find_program(
|
||||
'qjs',
|
||||
executable(
|
||||
'qjs_native',
|
||||
qjs_exe_srcs,
|
||||
|
||||
c_args: qjs_c_args,
|
||||
link_with: qjs_native_lib,
|
||||
dependencies: [qjs_sys_native_deps, mimalloc_native_dep],
|
||||
export_dynamic: true,
|
||||
|
||||
build_by_default: false,
|
||||
native: true,
|
||||
install: false,
|
||||
),
|
||||
)
|
||||
else
|
||||
meson.override_find_program('qjsc', qjsc_exe)
|
||||
meson.override_find_program('qjs', qjs_exe)
|
||||
endif
|
||||
|
||||
tests = get_option('tests').disable_auto_if(meson.is_subproject())
|
||||
examples = get_option('examples').disable_auto_if(meson.is_subproject())
|
||||
|
||||
if tests.allowed()
|
||||
if host_system != 'emscripten'
|
||||
# Test262 runner
|
||||
run262_exe = executable(
|
||||
'run-test262',
|
||||
'run-test262.c',
|
||||
qjs_libc_srcs,
|
||||
|
||||
c_args: qjs_c_args,
|
||||
dependencies: qjs_dep,
|
||||
)
|
||||
|
||||
test(
|
||||
'test',
|
||||
run262_exe,
|
||||
args: ['-c', files('tests.conf')],
|
||||
workdir: meson.current_source_dir(),
|
||||
)
|
||||
|
||||
foreach bench : [
|
||||
'empty_loop',
|
||||
|
||||
'date_now',
|
||||
|
||||
'prop_read',
|
||||
'prop_write',
|
||||
'prop_create',
|
||||
'prop_delete',
|
||||
|
||||
'array_read',
|
||||
'array_write',
|
||||
'array_prop_create',
|
||||
'array_length_decr',
|
||||
'array_hole_length_decr',
|
||||
'array_push',
|
||||
'array_pop',
|
||||
|
||||
'typed_array_read',
|
||||
'typed_array_write',
|
||||
|
||||
'global_read',
|
||||
'global_write',
|
||||
'global_write_strict',
|
||||
|
||||
'local_destruct',
|
||||
'global_destruct',
|
||||
'global_destruct_strict',
|
||||
|
||||
'func_call',
|
||||
'closure_var',
|
||||
|
||||
'int_arith',
|
||||
'float_arith',
|
||||
|
||||
'map_set',
|
||||
'map_delete',
|
||||
'weak_map_set',
|
||||
'weak_map_delete',
|
||||
|
||||
'array_for',
|
||||
'array_for_in',
|
||||
'array_for_of',
|
||||
|
||||
'math_min',
|
||||
|
||||
'object_null',
|
||||
|
||||
'regexp_ascii',
|
||||
'regexp_utf16',
|
||||
|
||||
'string_build1',
|
||||
'string_build2',
|
||||
|
||||
'string_slice1',
|
||||
'string_slice2',
|
||||
'string_slice3',
|
||||
|
||||
'sort_bench',
|
||||
|
||||
'int_to_string',
|
||||
'int_toString',
|
||||
|
||||
'float_to_string',
|
||||
'float_toString',
|
||||
'float_toFixed',
|
||||
'float_toPrecision',
|
||||
'float_toExponential',
|
||||
|
||||
'string_to_int',
|
||||
'string_to_float',
|
||||
|
||||
'bigint64_arith',
|
||||
'bigint256_arith',
|
||||
]
|
||||
benchmark(
|
||||
bench,
|
||||
qjs_exe,
|
||||
args: [files('tests/microbench.js'), bench],
|
||||
)
|
||||
endforeach
|
||||
endif
|
||||
|
||||
# API test
|
||||
test(
|
||||
'api',
|
||||
executable(
|
||||
'api-test',
|
||||
'api-test.c',
|
||||
|
||||
c_args: qjs_c_args,
|
||||
dependencies: qjs_dep,
|
||||
build_by_default: false,
|
||||
),
|
||||
)
|
||||
|
||||
# Function.toString() test
|
||||
test(
|
||||
'function_source',
|
||||
executable(
|
||||
'function_source',
|
||||
'gen/function_source.c',
|
||||
qjs_libc_srcs,
|
||||
|
||||
c_args: qjs_c_args,
|
||||
dependencies: qjs_dep,
|
||||
build_by_default: false,
|
||||
),
|
||||
)
|
||||
endif
|
||||
|
||||
# Unicode generator
|
||||
unicode_gen = executable(
|
||||
'unicode_gen',
|
||||
'cutils.c',
|
||||
'unicode_gen.c',
|
||||
|
||||
c_args: qjs_c_args,
|
||||
build_by_default: false,
|
||||
)
|
||||
|
||||
run_target(
|
||||
'libunicode-table.h',
|
||||
command: [
|
||||
unicode_gen,
|
||||
meson.current_source_dir() / 'unicode',
|
||||
files('libunicode-table.h'),
|
||||
],
|
||||
)
|
||||
|
||||
# bytecode to c source code for builtin and examples
|
||||
alias_target('codegen',
|
||||
run_target(
|
||||
'codegen_repl.c',
|
||||
command: [
|
||||
qjsc_exe,
|
||||
'-ss',
|
||||
'-o', files('gen/repl.c'),
|
||||
'-m',
|
||||
'-n', 'repl.js',
|
||||
files('repl.js'),
|
||||
],
|
||||
),
|
||||
run_target(
|
||||
'codegen_standalone.c',
|
||||
command: [
|
||||
qjsc_exe,
|
||||
'-ss',
|
||||
'-o', files('gen/standalone.c'),
|
||||
'-m',
|
||||
'-n', 'standalone.js',
|
||||
files('standalone.js'),
|
||||
],
|
||||
),
|
||||
run_target(
|
||||
'codegen_function_source.c',
|
||||
command: [
|
||||
qjsc_exe,
|
||||
'-e',
|
||||
'-o', files('gen/function_source.c'),
|
||||
'-n', 'tests/function_source.js',
|
||||
files('tests/function_source.js'),
|
||||
],
|
||||
),
|
||||
run_target(
|
||||
'codegen_hello.c',
|
||||
command: [
|
||||
qjsc_exe,
|
||||
'-e',
|
||||
'-o', files('gen/hello.c'),
|
||||
'-n', 'examples/hello.js',
|
||||
files('examples/hello.js'),
|
||||
],
|
||||
),
|
||||
run_target(
|
||||
'codegen_hello_module.c',
|
||||
command: [
|
||||
qjsc_exe,
|
||||
'-e',
|
||||
'-o', files('gen/hello_module.c'),
|
||||
'-m',
|
||||
'-n', 'examples/hello_module.js',
|
||||
files('examples/hello_module.js'),
|
||||
],
|
||||
),
|
||||
run_target(
|
||||
'codegen_test_fib.c',
|
||||
command: [
|
||||
qjsc_exe,
|
||||
'-e',
|
||||
'-o', files('gen/test_fib.c'),
|
||||
'-m',
|
||||
'-n', 'examples/test_fib.js',
|
||||
files('examples/test_fib.js'),
|
||||
],
|
||||
),
|
||||
run_target(
|
||||
'codegen_builtin-array-fromasync.h',
|
||||
command: [
|
||||
qjsc_exe,
|
||||
'-C',
|
||||
'-ss',
|
||||
'-o', files('builtin-array-fromasync.h'),
|
||||
'-n', 'builtin-array-fromasync.js',
|
||||
files('builtin-array-fromasync.js'),
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
if examples.allowed()
|
||||
executable(
|
||||
'hello',
|
||||
'gen/hello.c',
|
||||
qjs_libc_srcs,
|
||||
|
||||
c_args: qjs_c_args,
|
||||
dependencies: qjs_dep,
|
||||
)
|
||||
|
||||
executable(
|
||||
'hello_module',
|
||||
'gen/hello_module.c',
|
||||
qjs_libc_srcs,
|
||||
|
||||
c_args: qjs_c_args,
|
||||
dependencies: qjs_dep,
|
||||
)
|
||||
|
||||
subdir('examples')
|
||||
|
||||
executable(
|
||||
'test_fib',
|
||||
'examples/fib.c',
|
||||
'gen/test_fib.c',
|
||||
qjs_libc_srcs,
|
||||
|
||||
c_args: qjs_c_args,
|
||||
dependencies: qjs_dep,
|
||||
export_dynamic: true,
|
||||
)
|
||||
endif
|
||||
@@ -0,0 +1,6 @@
|
||||
option('tests', type: 'feature', description: 'build tests')
|
||||
option('examples', type: 'feature', description: 'build examples')
|
||||
option('libc', type: 'boolean', value: false, description: 'build qjs standard library modules as part of the library')
|
||||
option('cli_mimalloc', type: 'feature', value: 'disabled', description: 'build qjs cli with mimalloc')
|
||||
option('docdir', type: 'string', description: 'documentation directory')
|
||||
option('parser', type: 'boolean', value: true, description: 'Enable JS source code parser')
|
||||
+748
@@ -0,0 +1,748 @@
|
||||
/*
|
||||
* QuickJS stand alone interpreter
|
||||
*
|
||||
* Copyright (c) 2017-2021 Fabrice Bellard
|
||||
* Copyright (c) 2017-2021 Charlie Gordon
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "cutils.h"
|
||||
#include "quickjs.h"
|
||||
#include "quickjs-libc.h"
|
||||
|
||||
#ifdef QJS_USE_MIMALLOC
|
||||
#include <mimalloc.h>
|
||||
#endif
|
||||
|
||||
extern const uint8_t qjsc_repl[];
|
||||
extern const uint32_t qjsc_repl_size;
|
||||
extern const uint8_t qjsc_standalone[];
|
||||
extern const uint32_t qjsc_standalone_size;
|
||||
|
||||
// Must match standalone.js
|
||||
#define TRAILER_SIZE 12
|
||||
static const char trailer_magic[] = "quickjs2";
|
||||
static const int trailer_magic_size = sizeof(trailer_magic) - 1;
|
||||
static const int trailer_size = TRAILER_SIZE;
|
||||
|
||||
static int qjs__argc;
|
||||
static char **qjs__argv;
|
||||
|
||||
|
||||
static bool is_standalone(const char *exe)
|
||||
{
|
||||
FILE *exe_f = fopen(exe, "rb");
|
||||
if (!exe_f)
|
||||
return false;
|
||||
if (fseek(exe_f, -trailer_size, SEEK_END) < 0)
|
||||
goto fail;
|
||||
uint8_t buf[TRAILER_SIZE];
|
||||
if (fread(buf, 1, trailer_size, exe_f) != trailer_size)
|
||||
goto fail;
|
||||
fclose(exe_f);
|
||||
return !memcmp(buf, trailer_magic, trailer_magic_size);
|
||||
fail:
|
||||
fclose(exe_f);
|
||||
return false;
|
||||
}
|
||||
|
||||
static JSValue load_standalone_module(JSContext *ctx)
|
||||
{
|
||||
JSModuleDef *m;
|
||||
JSValue obj, val;
|
||||
obj = JS_ReadObject(ctx, qjsc_standalone, qjsc_standalone_size, JS_READ_OBJ_BYTECODE);
|
||||
if (JS_IsException(obj))
|
||||
goto exception;
|
||||
assert(JS_VALUE_GET_TAG(obj) == JS_TAG_MODULE);
|
||||
if (JS_ResolveModule(ctx, obj) < 0) {
|
||||
JS_FreeValue(ctx, obj);
|
||||
goto exception;
|
||||
}
|
||||
if (js_module_set_import_meta(ctx, obj, false, true) < 0) {
|
||||
JS_FreeValue(ctx, obj);
|
||||
goto exception;
|
||||
}
|
||||
val = JS_EvalFunction(ctx, JS_DupValue(ctx, obj));
|
||||
val = js_std_await(ctx, val);
|
||||
|
||||
if (JS_IsException(val)) {
|
||||
JS_FreeValue(ctx, obj);
|
||||
exception:
|
||||
js_std_dump_error(ctx);
|
||||
exit(1);
|
||||
}
|
||||
JS_FreeValue(ctx, val);
|
||||
|
||||
m = JS_VALUE_GET_PTR(obj);
|
||||
JS_FreeValue(ctx, obj);
|
||||
return JS_GetModuleNamespace(ctx, m);
|
||||
}
|
||||
|
||||
static int eval_buf(JSContext *ctx, const void *buf, int buf_len,
|
||||
const char *filename, int eval_flags)
|
||||
{
|
||||
bool use_realpath;
|
||||
JSValue val;
|
||||
int ret;
|
||||
|
||||
if ((eval_flags & JS_EVAL_TYPE_MASK) == JS_EVAL_TYPE_MODULE) {
|
||||
/* for the modules, we compile then run to be able to set
|
||||
import.meta */
|
||||
val = JS_Eval(ctx, buf, buf_len, filename,
|
||||
eval_flags | JS_EVAL_FLAG_COMPILE_ONLY);
|
||||
if (!JS_IsException(val)) {
|
||||
// ex. "<cmdline>" pr "/dev/stdin"
|
||||
use_realpath =
|
||||
!(*filename == '<' || !strncmp(filename, "/dev/", 5));
|
||||
if (js_module_set_import_meta(ctx, val, use_realpath, true) < 0) {
|
||||
js_std_dump_error(ctx);
|
||||
ret = -1;
|
||||
goto end;
|
||||
}
|
||||
val = JS_EvalFunction(ctx, val);
|
||||
}
|
||||
val = js_std_await(ctx, val);
|
||||
} else {
|
||||
val = JS_Eval(ctx, buf, buf_len, filename, eval_flags);
|
||||
}
|
||||
if (JS_IsException(val)) {
|
||||
js_std_dump_error(ctx);
|
||||
ret = -1;
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
end:
|
||||
JS_FreeValue(ctx, val);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int eval_file(JSContext *ctx, const char *filename, int module)
|
||||
{
|
||||
uint8_t *buf;
|
||||
int ret, eval_flags;
|
||||
size_t buf_len;
|
||||
|
||||
buf = js_load_file(ctx, &buf_len, filename);
|
||||
if (!buf) {
|
||||
perror(filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (module < 0) {
|
||||
module = (js__has_suffix(filename, ".mjs") ||
|
||||
JS_DetectModule((const char *)buf, buf_len));
|
||||
}
|
||||
if (module)
|
||||
eval_flags = JS_EVAL_TYPE_MODULE;
|
||||
else
|
||||
eval_flags = JS_EVAL_TYPE_GLOBAL;
|
||||
ret = eval_buf(ctx, buf, buf_len, filename, eval_flags);
|
||||
js_free(ctx, buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int64_t parse_limit(const char *arg) {
|
||||
char *p;
|
||||
unsigned long unit = 1024; /* default to traditional KB */
|
||||
double d = strtod(arg, &p);
|
||||
|
||||
if (p == arg) {
|
||||
fprintf(stderr, "Invalid limit: %s\n", arg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*p) {
|
||||
switch (*p++) {
|
||||
case 'b': case 'B': unit = 1UL << 0; break;
|
||||
case 'k': case 'K': unit = 1UL << 10; break; /* IEC kibibytes */
|
||||
case 'm': case 'M': unit = 1UL << 20; break; /* IEC mebibytes */
|
||||
case 'g': case 'G': unit = 1UL << 30; break; /* IEC gigibytes */
|
||||
default:
|
||||
fprintf(stderr, "Invalid limit: %s, unrecognized suffix, only k,m,g are allowed\n", arg);
|
||||
return -1;
|
||||
}
|
||||
if (*p) {
|
||||
fprintf(stderr, "Invalid limit: %s, only one suffix allowed\n", arg);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return (int64_t)(d * unit);
|
||||
}
|
||||
|
||||
static JSValue js_gc(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
JS_RunGC(JS_GetRuntime(ctx));
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static JSValue js_navigator_get_userAgent(JSContext *ctx, JSValueConst this_val)
|
||||
{
|
||||
char version[32];
|
||||
snprintf(version, sizeof(version), "quickjs-ng/%s", JS_GetVersion());
|
||||
return JS_NewString(ctx, version);
|
||||
}
|
||||
|
||||
static const JSCFunctionListEntry navigator_proto_funcs[] = {
|
||||
JS_CGETSET_DEF2("userAgent", js_navigator_get_userAgent, NULL, JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE),
|
||||
JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Navigator", JS_PROP_CONFIGURABLE),
|
||||
};
|
||||
|
||||
static const JSCFunctionListEntry global_obj[] = {
|
||||
JS_CFUNC_DEF("gc", 0, js_gc),
|
||||
};
|
||||
|
||||
/* also used to initialize the worker context */
|
||||
static JSContext *JS_NewCustomContext(JSRuntime *rt)
|
||||
{
|
||||
JSContext *ctx;
|
||||
ctx = JS_NewContext(rt);
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
/* system modules */
|
||||
js_init_module_std(ctx, "qjs:std");
|
||||
js_init_module_os(ctx, "qjs:os");
|
||||
js_init_module_bjson(ctx, "qjs:bjson");
|
||||
|
||||
JSValue global = JS_GetGlobalObject(ctx);
|
||||
JS_SetPropertyFunctionList(ctx, global, global_obj, countof(global_obj));
|
||||
JSValue args = JS_NewArray(ctx);
|
||||
int i;
|
||||
for(i = 0; i < qjs__argc; i++) {
|
||||
JS_SetPropertyUint32(ctx, args, i, JS_NewString(ctx, qjs__argv[i]));
|
||||
}
|
||||
JS_SetPropertyStr(ctx, global, "execArgv", args);
|
||||
JS_SetPropertyStr(ctx, global, "argv0", JS_NewString(ctx, qjs__argv[0]));
|
||||
JSValue navigator_proto = JS_NewObject(ctx);
|
||||
JS_SetPropertyFunctionList(ctx, navigator_proto, navigator_proto_funcs, countof(navigator_proto_funcs));
|
||||
JSValue navigator = JS_NewObjectProto(ctx, navigator_proto);
|
||||
JS_DefinePropertyValueStr(ctx, global, "navigator", navigator, JS_PROP_CONFIGURABLE | JS_PROP_ENUMERABLE);
|
||||
JS_FreeValue(ctx, global);
|
||||
JS_FreeValue(ctx, navigator_proto);
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
struct trace_malloc_data {
|
||||
uint8_t *base;
|
||||
};
|
||||
|
||||
static inline unsigned long long js_trace_malloc_ptr_offset(uint8_t *ptr,
|
||||
struct trace_malloc_data *dp)
|
||||
{
|
||||
return ptr - dp->base;
|
||||
}
|
||||
|
||||
static void JS_PRINTF_FORMAT_ATTR(2, 3) js_trace_malloc_printf(void *opaque, JS_PRINTF_FORMAT const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int c;
|
||||
|
||||
va_start(ap, fmt);
|
||||
while ((c = *fmt++) != '\0') {
|
||||
if (c == '%') {
|
||||
/* only handle %p and %zd */
|
||||
if (*fmt == 'p') {
|
||||
uint8_t *ptr = va_arg(ap, void *);
|
||||
if (ptr == NULL) {
|
||||
printf("NULL");
|
||||
} else {
|
||||
printf("H%+06lld.%zd",
|
||||
js_trace_malloc_ptr_offset(ptr, opaque),
|
||||
js__malloc_usable_size(ptr));
|
||||
}
|
||||
fmt++;
|
||||
continue;
|
||||
}
|
||||
if (fmt[0] == 'z' && fmt[1] == 'd') {
|
||||
size_t sz = va_arg(ap, size_t);
|
||||
printf("%zd", sz);
|
||||
fmt += 2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
putc(c, stdout);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static void js_trace_malloc_init(struct trace_malloc_data *s)
|
||||
{
|
||||
free(s->base = malloc(8));
|
||||
}
|
||||
|
||||
static void *js_trace_calloc(void *opaque, size_t count, size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
ptr = calloc(count, size);
|
||||
js_trace_malloc_printf(opaque, "C %zd %zd -> %p\n", count, size, ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static void *js_trace_malloc(void *opaque, size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
ptr = malloc(size);
|
||||
js_trace_malloc_printf(opaque, "A %zd -> %p\n", size, ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static void js_trace_free(void *opaque, void *ptr)
|
||||
{
|
||||
if (!ptr)
|
||||
return;
|
||||
js_trace_malloc_printf(opaque, "F %p\n", ptr);
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
static void *js_trace_realloc(void *opaque, void *ptr, size_t size)
|
||||
{
|
||||
js_trace_malloc_printf(opaque, "R %zd %p", size, ptr);
|
||||
ptr = realloc(ptr, size);
|
||||
js_trace_malloc_printf(opaque, " -> %p\n", ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static const JSMallocFunctions trace_mf = {
|
||||
js_trace_calloc,
|
||||
js_trace_malloc,
|
||||
js_trace_free,
|
||||
js_trace_realloc,
|
||||
js__malloc_usable_size
|
||||
};
|
||||
|
||||
#ifdef QJS_USE_MIMALLOC
|
||||
static void *js_mi_calloc(void *opaque, size_t count, size_t size)
|
||||
{
|
||||
return mi_calloc(count, size);
|
||||
}
|
||||
|
||||
static void *js_mi_malloc(void *opaque, size_t size)
|
||||
{
|
||||
return mi_malloc(size);
|
||||
}
|
||||
|
||||
static void js_mi_free(void *opaque, void *ptr)
|
||||
{
|
||||
if (!ptr)
|
||||
return;
|
||||
mi_free(ptr);
|
||||
}
|
||||
|
||||
static void *js_mi_realloc(void *opaque, void *ptr, size_t size)
|
||||
{
|
||||
return mi_realloc(ptr, size);
|
||||
}
|
||||
|
||||
static const JSMallocFunctions mi_mf = {
|
||||
js_mi_calloc,
|
||||
js_mi_malloc,
|
||||
js_mi_free,
|
||||
js_mi_realloc,
|
||||
mi_malloc_usable_size
|
||||
};
|
||||
#endif
|
||||
|
||||
#define PROG_NAME "qjs"
|
||||
|
||||
void help(void)
|
||||
{
|
||||
printf("QuickJS-ng version %s\n"
|
||||
"usage: " PROG_NAME " [options] [file [args]]\n"
|
||||
"-h --help list options\n"
|
||||
"-e --eval EXPR evaluate EXPR\n"
|
||||
"-i --interactive go to interactive mode\n"
|
||||
"-C --script load as JS classic script (default=autodetect)\n"
|
||||
"-m --module load as ES module (default=autodetect)\n"
|
||||
"-I --include file include an additional file\n"
|
||||
" --std make 'std', 'os' and 'bjson' available to script\n"
|
||||
"-T --trace trace memory allocation\n"
|
||||
"-d --dump dump the memory usage stats\n"
|
||||
"-D --dump-flags flags for dumping debug data (see DUMP_* defines)\n"
|
||||
"-c --compile FILE compile the given JS file as a standalone executable\n"
|
||||
"-o --out FILE output file for standalone executables\n"
|
||||
" --exe select the executable to use as the base, defaults to the current one\n"
|
||||
" --memory-limit n limit the memory usage to 'n' Kbytes\n"
|
||||
" --stack-size n limit the stack size to 'n' Kbytes\n"
|
||||
"-q --quit just instantiate the interpreter and quit\n", JS_GetVersion());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
JSContext *ctx;
|
||||
JSValue ret = JS_UNDEFINED;
|
||||
struct trace_malloc_data trace_data = { NULL };
|
||||
int r = 0;
|
||||
int optind = 1;
|
||||
char exebuf[JS__PATH_MAX];
|
||||
size_t exebuf_size = sizeof(exebuf);
|
||||
char *compile_file = NULL;
|
||||
char *exe = NULL;
|
||||
char *expr = NULL;
|
||||
char *dump_flags_str = NULL;
|
||||
char *out = NULL;
|
||||
int standalone = 0;
|
||||
int interactive = 0;
|
||||
int dump_memory = 0;
|
||||
int dump_flags = 0;
|
||||
int trace_memory = 0;
|
||||
int empty_run = 0;
|
||||
int module = -1;
|
||||
int load_std = 0;
|
||||
char *include_list[32];
|
||||
int i, include_count = 0;
|
||||
int64_t memory_limit = -1;
|
||||
int64_t stack_size = -1;
|
||||
|
||||
/* save for later */
|
||||
qjs__argc = argc;
|
||||
qjs__argv = argv;
|
||||
|
||||
/* check if this is a standalone executable */
|
||||
|
||||
if (!js_exepath(exebuf, &exebuf_size) && is_standalone(exebuf)) {
|
||||
standalone = 1;
|
||||
goto start;
|
||||
}
|
||||
|
||||
dump_flags_str = getenv("QJS_DUMP_FLAGS");
|
||||
dump_flags = dump_flags_str ? strtol(dump_flags_str, NULL, 16) : 0;
|
||||
|
||||
/* cannot use getopt because we want to pass the command line to
|
||||
the script */
|
||||
while (optind < argc && *argv[optind] == '-') {
|
||||
char *arg = argv[optind] + 1;
|
||||
const char *longopt = "";
|
||||
char *optarg = NULL;
|
||||
/* a single - is not an option, it also stops argument scanning */
|
||||
if (!*arg)
|
||||
break;
|
||||
optind++;
|
||||
if (*arg == '-') {
|
||||
longopt = arg + 1;
|
||||
optarg = strchr(longopt, '=');
|
||||
if (optarg)
|
||||
*optarg++ = '\0';
|
||||
arg += strlen(arg);
|
||||
/* -- stops argument scanning */
|
||||
if (!*longopt)
|
||||
break;
|
||||
}
|
||||
for (; *arg || *longopt; longopt = "") {
|
||||
char opt = *arg;
|
||||
if (opt) {
|
||||
arg++;
|
||||
if (!optarg && *arg)
|
||||
optarg = arg;
|
||||
}
|
||||
if (opt == 'h' || opt == '?' || !strcmp(longopt, "help")) {
|
||||
help();
|
||||
continue;
|
||||
}
|
||||
if (opt == 'e' || !strcmp(longopt, "eval")) {
|
||||
if (!optarg) {
|
||||
if (optind >= argc) {
|
||||
fprintf(stderr, "qjs: missing expression for -e\n");
|
||||
exit(1);
|
||||
}
|
||||
optarg = argv[optind++];
|
||||
}
|
||||
expr = optarg;
|
||||
break;
|
||||
}
|
||||
if (opt == 'I' || !strcmp(longopt, "include")) {
|
||||
if (optind >= argc) {
|
||||
fprintf(stderr, "expecting filename");
|
||||
exit(1);
|
||||
}
|
||||
if (include_count >= countof(include_list)) {
|
||||
fprintf(stderr, "too many included files");
|
||||
exit(1);
|
||||
}
|
||||
include_list[include_count++] = argv[optind++];
|
||||
continue;
|
||||
}
|
||||
if (opt == 'i' || !strcmp(longopt, "interactive")) {
|
||||
interactive++;
|
||||
continue;
|
||||
}
|
||||
if (opt == 'm' || !strcmp(longopt, "module")) {
|
||||
module = 1;
|
||||
continue;
|
||||
}
|
||||
if (opt == 'C' || !strcmp(longopt, "script")) {
|
||||
module = 0;
|
||||
continue;
|
||||
}
|
||||
if (opt == 'd' || !strcmp(longopt, "dump")) {
|
||||
dump_memory++;
|
||||
continue;
|
||||
}
|
||||
if (opt == 'D' || !strcmp(longopt, "dump-flags")) {
|
||||
dump_flags = optarg ? strtol(optarg, NULL, 16) : 0;
|
||||
break;
|
||||
}
|
||||
if (opt == 'T' || !strcmp(longopt, "trace")) {
|
||||
trace_memory++;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(longopt, "std")) {
|
||||
load_std = 1;
|
||||
continue;
|
||||
}
|
||||
if (opt == 'q' || !strcmp(longopt, "quit")) {
|
||||
empty_run++;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(longopt, "memory-limit")) {
|
||||
if (!optarg) {
|
||||
if (optind >= argc) {
|
||||
fprintf(stderr, "expecting memory limit");
|
||||
exit(1);
|
||||
}
|
||||
optarg = argv[optind++];
|
||||
}
|
||||
memory_limit = parse_limit(optarg);
|
||||
break;
|
||||
}
|
||||
if (!strcmp(longopt, "stack-size")) {
|
||||
if (!optarg) {
|
||||
if (optind >= argc) {
|
||||
fprintf(stderr, "expecting stack size");
|
||||
exit(1);
|
||||
}
|
||||
optarg = argv[optind++];
|
||||
}
|
||||
stack_size = parse_limit(optarg);
|
||||
break;
|
||||
}
|
||||
if (opt == 'c' || !strcmp(longopt, "compile")) {
|
||||
if (!optarg) {
|
||||
if (optind >= argc) {
|
||||
fprintf(stderr, "qjs: missing file for -c\n");
|
||||
exit(1);
|
||||
}
|
||||
optarg = argv[optind++];
|
||||
}
|
||||
compile_file = optarg;
|
||||
break;
|
||||
}
|
||||
if (opt == 'o' || !strcmp(longopt, "out")) {
|
||||
if (!optarg) {
|
||||
if (optind >= argc) {
|
||||
fprintf(stderr, "qjs: missing file for -o\n");
|
||||
exit(1);
|
||||
}
|
||||
optarg = argv[optind++];
|
||||
}
|
||||
out = optarg;
|
||||
break;
|
||||
}
|
||||
if (!strcmp(longopt, "exe")) {
|
||||
if (!optarg) {
|
||||
if (optind >= argc) {
|
||||
fprintf(stderr, "qjs: missing file for --exe\n");
|
||||
exit(1);
|
||||
}
|
||||
optarg = argv[optind++];
|
||||
}
|
||||
exe = optarg;
|
||||
break;
|
||||
}
|
||||
if (opt) {
|
||||
fprintf(stderr, "qjs: unknown option '-%c'\n", opt);
|
||||
} else {
|
||||
fprintf(stderr, "qjs: unknown option '--%s'\n", longopt);
|
||||
}
|
||||
help();
|
||||
}
|
||||
}
|
||||
|
||||
if (compile_file && !out)
|
||||
help();
|
||||
|
||||
start:
|
||||
|
||||
if (trace_memory) {
|
||||
js_trace_malloc_init(&trace_data);
|
||||
rt = JS_NewRuntime2(&trace_mf, &trace_data);
|
||||
} else {
|
||||
#ifdef QJS_USE_MIMALLOC
|
||||
rt = JS_NewRuntime2(&mi_mf, NULL);
|
||||
#else
|
||||
rt = JS_NewRuntime();
|
||||
#endif
|
||||
}
|
||||
if (!rt) {
|
||||
fprintf(stderr, "qjs: cannot allocate JS runtime\n");
|
||||
exit(2);
|
||||
}
|
||||
if (memory_limit >= 0)
|
||||
JS_SetMemoryLimit(rt, (size_t)memory_limit);
|
||||
if (stack_size >= 0)
|
||||
JS_SetMaxStackSize(rt, (size_t)stack_size);
|
||||
if (dump_flags != 0)
|
||||
JS_SetDumpFlags(rt, dump_flags);
|
||||
js_std_set_worker_new_context_func(JS_NewCustomContext);
|
||||
js_std_init_handlers(rt);
|
||||
ctx = JS_NewCustomContext(rt);
|
||||
if (!ctx) {
|
||||
fprintf(stderr, "qjs: cannot allocate JS context\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
/* loader for ES6 modules */
|
||||
JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);
|
||||
|
||||
/* exit on unhandled promise rejections */
|
||||
JS_SetHostPromiseRejectionTracker(rt, js_std_promise_rejection_tracker, NULL);
|
||||
|
||||
if (!empty_run) {
|
||||
js_std_add_helpers(ctx, argc - optind, argv + optind);
|
||||
|
||||
/* make 'std' and 'os' visible to non module code */
|
||||
if (load_std) {
|
||||
const char *str =
|
||||
"import * as bjson from 'qjs:bjson';\n"
|
||||
"import * as std from 'qjs:std';\n"
|
||||
"import * as os from 'qjs:os';\n"
|
||||
"globalThis.bjson = bjson;\n"
|
||||
"globalThis.std = std;\n"
|
||||
"globalThis.os = os;\n";
|
||||
eval_buf(ctx, str, strlen(str), "<input>", JS_EVAL_TYPE_MODULE);
|
||||
}
|
||||
|
||||
for(i = 0; i < include_count; i++) {
|
||||
if (eval_file(ctx, include_list[i], 0))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (standalone) {
|
||||
JSValue ns = load_standalone_module(ctx);
|
||||
if (JS_IsException(ns))
|
||||
goto fail;
|
||||
JSValue func = JS_GetPropertyStr(ctx, ns, "runStandalone");
|
||||
JS_FreeValue(ctx, ns);
|
||||
if (JS_IsException(func))
|
||||
goto fail;
|
||||
ret = JS_Call(ctx, func, JS_UNDEFINED, 0, NULL);
|
||||
JS_FreeValue(ctx, func);
|
||||
} else if (compile_file) {
|
||||
JSValue ns = load_standalone_module(ctx);
|
||||
if (JS_IsException(ns))
|
||||
goto fail;
|
||||
JSValue func = JS_GetPropertyStr(ctx, ns, "compileStandalone");
|
||||
JS_FreeValue(ctx, ns);
|
||||
if (JS_IsException(func))
|
||||
goto fail;
|
||||
JSValue args[3];
|
||||
args[0] = JS_NewString(ctx, compile_file);
|
||||
args[1] = JS_NewString(ctx, out);
|
||||
args[2] = exe != NULL ? JS_NewString(ctx, exe) : JS_UNDEFINED;
|
||||
ret = JS_Call(ctx, func, JS_UNDEFINED, 3, (JSValueConst *)args);
|
||||
JS_FreeValue(ctx, func);
|
||||
JS_FreeValue(ctx, args[0]);
|
||||
JS_FreeValue(ctx, args[1]);
|
||||
JS_FreeValue(ctx, args[2]);
|
||||
} else if (expr) {
|
||||
int flags = module ? JS_EVAL_TYPE_MODULE : 0;
|
||||
if (eval_buf(ctx, expr, strlen(expr), "<cmdline>", flags))
|
||||
goto fail;
|
||||
} else if (optind >= argc) {
|
||||
/* interactive mode */
|
||||
interactive = 1;
|
||||
} else {
|
||||
const char *filename;
|
||||
filename = argv[optind];
|
||||
if (eval_file(ctx, filename, module))
|
||||
goto fail;
|
||||
}
|
||||
if (interactive) {
|
||||
JS_SetHostPromiseRejectionTracker(rt, NULL, NULL);
|
||||
js_std_eval_binary(ctx, qjsc_repl, qjsc_repl_size, 0);
|
||||
}
|
||||
if (standalone || compile_file) {
|
||||
if (JS_IsException(ret)) {
|
||||
r = 1;
|
||||
} else {
|
||||
JS_FreeValue(ctx, ret);
|
||||
r = js_std_loop(ctx);
|
||||
}
|
||||
} else {
|
||||
r = js_std_loop(ctx);
|
||||
}
|
||||
if (r) {
|
||||
js_std_dump_error(ctx);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (dump_memory) {
|
||||
JSMemoryUsage stats;
|
||||
JS_ComputeMemoryUsage(rt, &stats);
|
||||
JS_DumpMemoryUsage(stdout, &stats, rt);
|
||||
}
|
||||
js_std_free_handlers(rt);
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
|
||||
if (empty_run && dump_memory) {
|
||||
clock_t t[5];
|
||||
double best[5] = {0};
|
||||
int i, j;
|
||||
for (i = 0; i < 100; i++) {
|
||||
t[0] = clock();
|
||||
rt = JS_NewRuntime();
|
||||
t[1] = clock();
|
||||
ctx = JS_NewContext(rt);
|
||||
t[2] = clock();
|
||||
JS_FreeContext(ctx);
|
||||
t[3] = clock();
|
||||
JS_FreeRuntime(rt);
|
||||
t[4] = clock();
|
||||
for (j = 4; j > 0; j--) {
|
||||
double ms = 1000.0 * (t[j] - t[j - 1]) / CLOCKS_PER_SEC;
|
||||
if (i == 0 || best[j] > ms)
|
||||
best[j] = ms;
|
||||
}
|
||||
}
|
||||
printf("\nInstantiation times (ms): %.3f = %.3f+%.3f+%.3f+%.3f\n",
|
||||
best[1] + best[2] + best[3] + best[4],
|
||||
best[1], best[2], best[3], best[4]);
|
||||
}
|
||||
return 0;
|
||||
fail:
|
||||
js_std_free_handlers(rt);
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
return 1;
|
||||
}
|
||||
+673
@@ -0,0 +1,673 @@
|
||||
/*
|
||||
* QuickJS command line compiler
|
||||
*
|
||||
* Copyright (c) 2018-2024 Fabrice Bellard
|
||||
* Copyright (c) 2023-2025 Ben Noordhuis
|
||||
* Copyright (c) 2023-2025 Saúl Ibarra Corretgé
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "cutils.h"
|
||||
#include "quickjs-libc.h"
|
||||
|
||||
typedef enum {
|
||||
OUTPUT_C,
|
||||
OUTPUT_C_MAIN,
|
||||
OUTPUT_RAW,
|
||||
} OutputTypeEnum;
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
char *short_name;
|
||||
int flags;
|
||||
} namelist_entry_t;
|
||||
|
||||
typedef struct namelist_t {
|
||||
namelist_entry_t *array;
|
||||
int count;
|
||||
int size;
|
||||
} namelist_t;
|
||||
|
||||
static namelist_t cname_list;
|
||||
static namelist_t cmodule_list;
|
||||
static namelist_t init_module_list;
|
||||
static OutputTypeEnum output_type;
|
||||
static FILE *outfile;
|
||||
static const char *c_ident_prefix = "qjsc_";
|
||||
static int strip;
|
||||
|
||||
void namelist_add(namelist_t *lp, const char *name, const char *short_name,
|
||||
int flags)
|
||||
{
|
||||
namelist_entry_t *e;
|
||||
if (lp->count == lp->size) {
|
||||
size_t newsize = lp->size + (lp->size >> 1) + 4;
|
||||
namelist_entry_t *a =
|
||||
realloc(lp->array, sizeof(lp->array[0]) * newsize);
|
||||
/* XXX: check for realloc failure */
|
||||
lp->array = a;
|
||||
lp->size = newsize;
|
||||
}
|
||||
e = &lp->array[lp->count++];
|
||||
e->name = strdup(name);
|
||||
if (short_name)
|
||||
e->short_name = strdup(short_name);
|
||||
else
|
||||
e->short_name = NULL;
|
||||
e->flags = flags;
|
||||
}
|
||||
|
||||
void namelist_free(namelist_t *lp)
|
||||
{
|
||||
while (lp->count > 0) {
|
||||
namelist_entry_t *e = &lp->array[--lp->count];
|
||||
free(e->name);
|
||||
free(e->short_name);
|
||||
}
|
||||
free(lp->array);
|
||||
lp->array = NULL;
|
||||
lp->size = 0;
|
||||
}
|
||||
|
||||
namelist_entry_t *namelist_find(namelist_t *lp, const char *name)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < lp->count; i++) {
|
||||
namelist_entry_t *e = &lp->array[i];
|
||||
if (!strcmp(e->name, name))
|
||||
return e;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void get_c_name(char *buf, size_t buf_size, const char *file)
|
||||
{
|
||||
const char *p, *r;
|
||||
size_t len, i;
|
||||
int c;
|
||||
char *q;
|
||||
|
||||
p = strrchr(file, '/');
|
||||
if (!p)
|
||||
p = file;
|
||||
else
|
||||
p++;
|
||||
r = strrchr(p, '.');
|
||||
if (!r)
|
||||
len = strlen(p);
|
||||
else
|
||||
len = r - p;
|
||||
js__pstrcpy(buf, buf_size, c_ident_prefix);
|
||||
q = buf + strlen(buf);
|
||||
for(i = 0; i < len; i++) {
|
||||
c = p[i];
|
||||
if (!((c >= '0' && c <= '9') ||
|
||||
(c >= 'A' && c <= 'Z') ||
|
||||
(c >= 'a' && c <= 'z'))) {
|
||||
c = '_';
|
||||
}
|
||||
if ((q - buf) < buf_size - 1)
|
||||
*q++ = c;
|
||||
}
|
||||
*q = '\0';
|
||||
}
|
||||
|
||||
static void dump_hex(FILE *f, const uint8_t *buf, size_t len)
|
||||
{
|
||||
size_t i, col;
|
||||
col = 0;
|
||||
for(i = 0; i < len; i++) {
|
||||
fprintf(f, " 0x%02x,", buf[i]);
|
||||
if (++col == 8) {
|
||||
fprintf(f, "\n");
|
||||
col = 0;
|
||||
}
|
||||
}
|
||||
if (col != 0)
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
|
||||
static void output_object_code(JSContext *ctx,
|
||||
FILE *fo, JSValue obj, const char *c_name,
|
||||
bool load_only)
|
||||
{
|
||||
uint8_t *out_buf;
|
||||
size_t out_buf_len;
|
||||
int flags = JS_WRITE_OBJ_BYTECODE;
|
||||
|
||||
if (strip) {
|
||||
flags |= JS_WRITE_OBJ_STRIP_SOURCE;
|
||||
if (strip > 1)
|
||||
flags |= JS_WRITE_OBJ_STRIP_DEBUG;
|
||||
}
|
||||
|
||||
out_buf = JS_WriteObject(ctx, &out_buf_len, obj, flags);
|
||||
if (!out_buf) {
|
||||
js_std_dump_error(ctx);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
namelist_add(&cname_list, c_name, NULL, load_only);
|
||||
|
||||
if (output_type == OUTPUT_RAW) {
|
||||
fwrite(out_buf, 1, out_buf_len, fo);
|
||||
} else {
|
||||
fprintf(fo, "const uint32_t %s_size = %u;\n\n",
|
||||
c_name, (unsigned int)out_buf_len);
|
||||
fprintf(fo, "const uint8_t %s[%u] = {\n",
|
||||
c_name, (unsigned int)out_buf_len);
|
||||
dump_hex(fo, out_buf, out_buf_len);
|
||||
fprintf(fo, "};\n\n");
|
||||
}
|
||||
|
||||
js_free(ctx, out_buf);
|
||||
}
|
||||
|
||||
static int js_module_dummy_init(JSContext *ctx, JSModuleDef *m)
|
||||
{
|
||||
/* should never be called when compiling JS code */
|
||||
abort();
|
||||
return -1; // pacify compiler
|
||||
}
|
||||
|
||||
static void find_unique_cname(char *cname, size_t cname_size)
|
||||
{
|
||||
char cname1[1024];
|
||||
int suffix_num;
|
||||
size_t len, max_len;
|
||||
assert(cname_size >= 32);
|
||||
/* find a C name not matching an existing module C name by
|
||||
adding a numeric suffix */
|
||||
len = strlen(cname);
|
||||
max_len = cname_size - 16;
|
||||
if (len > max_len)
|
||||
cname[max_len] = '\0';
|
||||
suffix_num = 1;
|
||||
for(;;) {
|
||||
snprintf(cname1, sizeof(cname1), "%s_%d", cname, suffix_num);
|
||||
if (!namelist_find(&cname_list, cname1))
|
||||
break;
|
||||
suffix_num++;
|
||||
}
|
||||
js__pstrcpy(cname, cname_size, cname1);
|
||||
}
|
||||
|
||||
JSModuleDef *jsc_module_loader(JSContext *ctx,
|
||||
const char *module_name, void *opaque)
|
||||
{
|
||||
JSModuleDef *m;
|
||||
namelist_entry_t *e;
|
||||
|
||||
/* check if it is a declared C or system module */
|
||||
e = namelist_find(&cmodule_list, module_name);
|
||||
if (e) {
|
||||
/* add in the static init module list */
|
||||
namelist_add(&init_module_list, e->name, e->short_name, 0);
|
||||
/* create a dummy module */
|
||||
m = JS_NewCModule(ctx, module_name, js_module_dummy_init);
|
||||
} else if (js__has_suffix(module_name, ".so")) {
|
||||
JS_ThrowReferenceError(ctx, "%s: dynamically linking to shared libraries not supported",
|
||||
module_name);
|
||||
return NULL;
|
||||
} else {
|
||||
size_t buf_len;
|
||||
uint8_t *buf;
|
||||
JSValue func_val;
|
||||
char cname[1000];
|
||||
|
||||
buf = js_load_file(ctx, &buf_len, module_name);
|
||||
if (!buf) {
|
||||
JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
|
||||
module_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* compile the module */
|
||||
func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name,
|
||||
JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY);
|
||||
js_free(ctx, buf);
|
||||
if (JS_IsException(func_val))
|
||||
return NULL;
|
||||
get_c_name(cname, sizeof(cname), module_name);
|
||||
if (namelist_find(&cname_list, cname)) {
|
||||
find_unique_cname(cname, sizeof(cname));
|
||||
}
|
||||
output_object_code(ctx, outfile, func_val, cname, true);
|
||||
|
||||
/* the module is already referenced, so we must free it */
|
||||
m = JS_VALUE_GET_PTR(func_val);
|
||||
JS_FreeValue(ctx, func_val);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
static void compile_file(JSContext *ctx, FILE *fo,
|
||||
const char *filename,
|
||||
const char *script_name,
|
||||
const char *c_name1,
|
||||
int module)
|
||||
{
|
||||
uint8_t *buf;
|
||||
char c_name[1024];
|
||||
int eval_flags;
|
||||
JSValue obj;
|
||||
size_t buf_len;
|
||||
|
||||
buf = js_load_file(ctx, &buf_len, filename);
|
||||
if (!buf) {
|
||||
fprintf(stderr, "Could not load '%s'\n", filename);
|
||||
exit(1);
|
||||
}
|
||||
eval_flags = JS_EVAL_FLAG_COMPILE_ONLY;
|
||||
if (module < 0) {
|
||||
module = (js__has_suffix(filename, ".mjs") ||
|
||||
JS_DetectModule((const char *)buf, buf_len));
|
||||
}
|
||||
if (module)
|
||||
eval_flags |= JS_EVAL_TYPE_MODULE;
|
||||
else
|
||||
eval_flags |= JS_EVAL_TYPE_GLOBAL;
|
||||
obj = JS_Eval(ctx, (const char *)buf, buf_len, script_name ? script_name : filename, eval_flags);
|
||||
if (JS_IsException(obj)) {
|
||||
js_std_dump_error(ctx);
|
||||
exit(1);
|
||||
}
|
||||
js_free(ctx, buf);
|
||||
if (c_name1) {
|
||||
js__pstrcpy(c_name, sizeof(c_name), c_name1);
|
||||
} else {
|
||||
get_c_name(c_name, sizeof(c_name), filename);
|
||||
}
|
||||
output_object_code(ctx, fo, obj, c_name, false);
|
||||
JS_FreeValue(ctx, obj);
|
||||
}
|
||||
|
||||
static const char main_c_template1[] =
|
||||
"int main(int argc, char **argv)\n"
|
||||
"{\n"
|
||||
" int r;\n"
|
||||
" JSRuntime *rt;\n"
|
||||
" JSContext *ctx;\n"
|
||||
" r = 0;\n"
|
||||
" rt = JS_NewRuntime();\n"
|
||||
" js_std_set_worker_new_context_func(JS_NewCustomContext);\n"
|
||||
" js_std_init_handlers(rt);\n"
|
||||
;
|
||||
|
||||
static const char main_c_template2[] =
|
||||
" r = js_std_loop(ctx);\n"
|
||||
" if (r) {\n"
|
||||
" js_std_dump_error(ctx);\n"
|
||||
" }\n"
|
||||
" js_std_free_handlers(rt);\n"
|
||||
" JS_FreeContext(ctx);\n"
|
||||
" JS_FreeRuntime(rt);\n"
|
||||
" return r;\n"
|
||||
"}\n";
|
||||
|
||||
#define PROG_NAME "qjsc"
|
||||
|
||||
void help(void)
|
||||
{
|
||||
printf("QuickJS-ng Compiler version %s\n"
|
||||
"usage: " PROG_NAME " [options] [files]\n"
|
||||
"\n"
|
||||
"options are:\n"
|
||||
"-b output raw bytecode instead of C code\n"
|
||||
"-e output main() and bytecode in a C file\n"
|
||||
"-o output set the output filename\n"
|
||||
"-n script_name set the script name (as used in stack traces)\n"
|
||||
"-N cname set the C name of the generated data\n"
|
||||
"-C compile as JS classic script (default=autodetect)\n"
|
||||
"-m compile as ES module (default=autodetect)\n"
|
||||
"-D module_name compile a dynamically loaded module or worker\n"
|
||||
"-M module_name[,cname] add initialization code for an external C module\n"
|
||||
"-p prefix set the prefix of the generated C names\n"
|
||||
"-P do not add default system modules\n"
|
||||
"-s strip the source code, specify twice to also strip debug info\n"
|
||||
"-S n set the maximum stack size to 'n' bytes (default=%d)\n",
|
||||
JS_GetVersion(),
|
||||
JS_DEFAULT_STACK_SIZE);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// TODO(bnoordhuis) share with qjs.c maybe
|
||||
static int64_t parse_limit(const char *arg) {
|
||||
char *p;
|
||||
unsigned long unit = 1; // bytes for backcompat; qjs defaults to kilobytes
|
||||
double d = strtod(arg, &p);
|
||||
|
||||
if (p == arg) {
|
||||
fprintf(stderr, "qjsc: invalid limit: %s\n", arg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*p) {
|
||||
switch (*p++) {
|
||||
case 'b': case 'B': unit = 1UL << 0; break;
|
||||
case 'k': case 'K': unit = 1UL << 10; break; /* IEC kibibytes */
|
||||
case 'm': case 'M': unit = 1UL << 20; break; /* IEC mebibytes */
|
||||
case 'g': case 'G': unit = 1UL << 30; break; /* IEC gigibytes */
|
||||
default:
|
||||
fprintf(stderr, "qjsc: invalid limit: %s, unrecognized suffix, only k,m,g are allowed\n", arg);
|
||||
return -1;
|
||||
}
|
||||
if (*p) {
|
||||
fprintf(stderr, "qjsc: invalid limit: %s, only one suffix allowed\n", arg);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return (int64_t)(d * unit);
|
||||
}
|
||||
|
||||
static void check_hasarg(int optind, int argc, int opt)
|
||||
{
|
||||
if (optind >= argc) {
|
||||
fprintf(stderr, "qjsc: missing file for -%c\n", opt);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int optind = 1;
|
||||
int i;
|
||||
const char *out_filename, *cname, *script_name;
|
||||
char cfilename[1024];
|
||||
FILE *fo;
|
||||
JSRuntime *rt;
|
||||
JSContext *ctx;
|
||||
int module;
|
||||
size_t stack_size;
|
||||
namelist_t dynamic_module_list;
|
||||
bool load_system_modules = true;
|
||||
|
||||
out_filename = NULL;
|
||||
script_name = NULL;
|
||||
output_type = OUTPUT_C;
|
||||
cname = NULL;
|
||||
module = -1;
|
||||
strip = 0;
|
||||
stack_size = 0;
|
||||
memset(&dynamic_module_list, 0, sizeof(dynamic_module_list));
|
||||
|
||||
|
||||
while (optind < argc && *argv[optind] == '-') {
|
||||
char *arg = argv[optind] + 1;
|
||||
const char *longopt = "";
|
||||
char *optarg = NULL;
|
||||
/* a single - is not an option, it also stops argument scanning */
|
||||
if (!*arg)
|
||||
break;
|
||||
optind++;
|
||||
if (*arg == '-') {
|
||||
longopt = arg + 1;
|
||||
optarg = strchr(longopt, '=');
|
||||
if (optarg)
|
||||
*optarg++ = '\0';
|
||||
arg += strlen(arg);
|
||||
/* -- stops argument scanning */
|
||||
if (!*longopt)
|
||||
break;
|
||||
}
|
||||
for (; *arg || *longopt; longopt = "") {
|
||||
char opt = *arg;
|
||||
if (opt) {
|
||||
arg++;
|
||||
if (!optarg && *arg)
|
||||
optarg = arg;
|
||||
}
|
||||
if (opt == 'h' || opt == '?' || !strcmp(longopt, "help")) {
|
||||
help();
|
||||
continue;
|
||||
}
|
||||
if (opt == 'b') {
|
||||
output_type = OUTPUT_RAW;
|
||||
continue;
|
||||
}
|
||||
if (opt == 'o') {
|
||||
if (!optarg) {
|
||||
check_hasarg(optind, argc, opt);
|
||||
optarg = argv[optind++];
|
||||
}
|
||||
out_filename = optarg;
|
||||
continue;
|
||||
}
|
||||
if (opt == 'e') {
|
||||
output_type = OUTPUT_C_MAIN;
|
||||
continue;
|
||||
}
|
||||
if (opt == 'n') {
|
||||
if (!optarg) {
|
||||
check_hasarg(optind, argc, opt);
|
||||
optarg = argv[optind++];
|
||||
}
|
||||
script_name = optarg;
|
||||
continue;
|
||||
}
|
||||
if (opt == 'N') {
|
||||
if (!optarg) {
|
||||
check_hasarg(optind, argc, opt);
|
||||
optarg = argv[optind++];
|
||||
}
|
||||
cname = optarg;
|
||||
continue;
|
||||
}
|
||||
if (opt == 'C') {
|
||||
module = 0;
|
||||
continue;
|
||||
}
|
||||
if (opt == 'm') {
|
||||
module = 1;
|
||||
continue;
|
||||
}
|
||||
if (opt == 'M') {
|
||||
char *p;
|
||||
char path[1024];
|
||||
char cname[1024];
|
||||
if (!optarg) {
|
||||
check_hasarg(optind, argc, opt);
|
||||
optarg = argv[optind++];
|
||||
}
|
||||
js__pstrcpy(path, sizeof(path), optarg);
|
||||
p = strchr(path, ',');
|
||||
if (p) {
|
||||
*p = '\0';
|
||||
js__pstrcpy(cname, sizeof(cname), p + 1);
|
||||
} else {
|
||||
get_c_name(cname, sizeof(cname), path);
|
||||
}
|
||||
namelist_add(&cmodule_list, path, cname, 0);
|
||||
continue;
|
||||
}
|
||||
if (opt == 'D') {
|
||||
if (!optarg) {
|
||||
check_hasarg(optind, argc, opt);
|
||||
optarg = argv[optind++];
|
||||
}
|
||||
namelist_add(&dynamic_module_list, optarg, NULL, 0);
|
||||
continue;
|
||||
}
|
||||
if (opt == 'P') {
|
||||
load_system_modules = false;
|
||||
continue;
|
||||
}
|
||||
if (opt == 's') {
|
||||
strip++;
|
||||
continue;
|
||||
}
|
||||
if (opt == 'p') {
|
||||
if (!optarg) {
|
||||
check_hasarg(optind, argc, opt);
|
||||
optarg = argv[optind++];
|
||||
}
|
||||
c_ident_prefix = optarg;
|
||||
continue;
|
||||
}
|
||||
if (opt == 'S') {
|
||||
if (!optarg) {
|
||||
check_hasarg(optind, argc, opt);
|
||||
optarg = argv[optind++];
|
||||
}
|
||||
stack_size = parse_limit(optarg);
|
||||
continue;
|
||||
}
|
||||
help();
|
||||
}
|
||||
}
|
||||
|
||||
if (load_system_modules) {
|
||||
/* add system modules */
|
||||
namelist_add(&cmodule_list, "qjs:std", "std", 0);
|
||||
namelist_add(&cmodule_list, "qjs:os", "os", 0);
|
||||
namelist_add(&cmodule_list, "qjs:bjson", "bjson", 0);
|
||||
namelist_add(&cmodule_list, "std", "std", 0);
|
||||
namelist_add(&cmodule_list, "os", "os", 0);
|
||||
namelist_add(&cmodule_list, "bjson", "bjson", 0);
|
||||
}
|
||||
|
||||
if (optind >= argc)
|
||||
help();
|
||||
|
||||
if (!out_filename)
|
||||
out_filename = "out.c";
|
||||
|
||||
js__pstrcpy(cfilename, sizeof(cfilename), out_filename);
|
||||
|
||||
if (output_type == OUTPUT_RAW)
|
||||
fo = fopen(cfilename, "wb");
|
||||
else
|
||||
fo = fopen(cfilename, "w");
|
||||
|
||||
if (!fo) {
|
||||
perror(cfilename);
|
||||
exit(1);
|
||||
}
|
||||
outfile = fo;
|
||||
|
||||
rt = JS_NewRuntime();
|
||||
ctx = JS_NewContext(rt);
|
||||
|
||||
/* loader for ES6 modules */
|
||||
JS_SetModuleLoaderFunc(rt, NULL, jsc_module_loader, NULL);
|
||||
|
||||
if (output_type != OUTPUT_RAW) {
|
||||
fprintf(fo, "/* File generated automatically by the QuickJS-ng compiler. */\n"
|
||||
"\n"
|
||||
);
|
||||
}
|
||||
|
||||
if (output_type == OUTPUT_C_MAIN) {
|
||||
fprintf(fo, "#include \"quickjs-libc.h\"\n"
|
||||
"\n"
|
||||
);
|
||||
} else if (output_type == OUTPUT_C) {
|
||||
fprintf(fo, "#include <inttypes.h>\n"
|
||||
"\n"
|
||||
);
|
||||
}
|
||||
|
||||
for(i = optind; i < argc; i++) {
|
||||
const char *filename = argv[i];
|
||||
compile_file(ctx, fo, filename, script_name, cname, module);
|
||||
cname = NULL;
|
||||
}
|
||||
|
||||
for(i = 0; i < dynamic_module_list.count; i++) {
|
||||
if (!jsc_module_loader(ctx, dynamic_module_list.array[i].name, NULL)) {
|
||||
fprintf(stderr, "Could not load dynamic module '%s'\n",
|
||||
dynamic_module_list.array[i].name);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (output_type == OUTPUT_C_MAIN) {
|
||||
fprintf(fo,
|
||||
"static JSContext *JS_NewCustomContext(JSRuntime *rt)\n"
|
||||
"{\n"
|
||||
" JSContext *ctx = JS_NewContext(rt);\n"
|
||||
" if (!ctx)\n"
|
||||
" return NULL;\n");
|
||||
/* add the precompiled modules (XXX: could modify the module
|
||||
loader instead) */
|
||||
for(i = 0; i < init_module_list.count; i++) {
|
||||
namelist_entry_t *e = &init_module_list.array[i];
|
||||
/* initialize the static C modules */
|
||||
|
||||
fprintf(fo,
|
||||
" {\n"
|
||||
" extern JSModuleDef *js_init_module_%s(JSContext *ctx, const char *name);\n"
|
||||
" js_init_module_%s(ctx, \"%s\");\n"
|
||||
" }\n",
|
||||
e->short_name, e->short_name, e->name);
|
||||
}
|
||||
for(i = 0; i < cname_list.count; i++) {
|
||||
namelist_entry_t *e = &cname_list.array[i];
|
||||
if (e->flags) {
|
||||
fprintf(fo, " js_std_eval_binary(ctx, %s, %s_size, 1);\n",
|
||||
e->name, e->name);
|
||||
}
|
||||
}
|
||||
fprintf(fo,
|
||||
" return ctx;\n"
|
||||
"}\n\n");
|
||||
|
||||
fputs(main_c_template1, fo);
|
||||
|
||||
if (stack_size != 0) {
|
||||
fprintf(fo, " JS_SetMaxStackSize(rt, %u);\n",
|
||||
(unsigned int)stack_size);
|
||||
}
|
||||
|
||||
/* add the module loader */
|
||||
fprintf(fo, " JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);\n");
|
||||
|
||||
fprintf(fo,
|
||||
" ctx = JS_NewCustomContext(rt);\n"
|
||||
" js_std_add_helpers(ctx, argc, argv);\n");
|
||||
|
||||
for(i = 0; i < cname_list.count; i++) {
|
||||
namelist_entry_t *e = &cname_list.array[i];
|
||||
if (!e->flags) {
|
||||
fprintf(fo, " js_std_eval_binary(ctx, %s, %s_size, 0);\n",
|
||||
e->name, e->name);
|
||||
}
|
||||
}
|
||||
fputs(main_c_template2, fo);
|
||||
}
|
||||
|
||||
JS_FreeContext(ctx);
|
||||
JS_FreeRuntime(rt);
|
||||
|
||||
fclose(fo);
|
||||
|
||||
namelist_free(&cname_list);
|
||||
namelist_free(&cmodule_list);
|
||||
namelist_free(&init_module_list);
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
* QuickJS atom definitions
|
||||
*
|
||||
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||
* Copyright (c) 2017-2018 Charlie Gordon
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef DEF
|
||||
|
||||
/* Note: first atoms are considered as keywords in the parser */
|
||||
DEF(null, "null") /* must be first */
|
||||
DEF(false, "false")
|
||||
DEF(true, "true")
|
||||
DEF(if, "if")
|
||||
DEF(else, "else")
|
||||
DEF(return, "return")
|
||||
DEF(var, "var")
|
||||
DEF(this, "this")
|
||||
DEF(delete, "delete")
|
||||
DEF(void, "void")
|
||||
DEF(typeof, "typeof")
|
||||
DEF(new, "new")
|
||||
DEF(in, "in")
|
||||
DEF(instanceof, "instanceof")
|
||||
DEF(do, "do")
|
||||
DEF(while, "while")
|
||||
DEF(for, "for")
|
||||
DEF(break, "break")
|
||||
DEF(continue, "continue")
|
||||
DEF(switch, "switch")
|
||||
DEF(case, "case")
|
||||
DEF(default, "default")
|
||||
DEF(throw, "throw")
|
||||
DEF(try, "try")
|
||||
DEF(catch, "catch")
|
||||
DEF(finally, "finally")
|
||||
DEF(function, "function")
|
||||
DEF(debugger, "debugger")
|
||||
DEF(with, "with")
|
||||
/* FutureReservedWord */
|
||||
DEF(class, "class")
|
||||
DEF(const, "const")
|
||||
DEF(enum, "enum")
|
||||
DEF(export, "export")
|
||||
DEF(extends, "extends")
|
||||
DEF(import, "import")
|
||||
DEF(super, "super")
|
||||
/* FutureReservedWords when parsing strict mode code */
|
||||
DEF(implements, "implements")
|
||||
DEF(interface, "interface")
|
||||
DEF(let, "let")
|
||||
DEF(package, "package")
|
||||
DEF(private, "private")
|
||||
DEF(protected, "protected")
|
||||
DEF(public, "public")
|
||||
DEF(static, "static")
|
||||
DEF(yield, "yield")
|
||||
DEF(await, "await")
|
||||
|
||||
/* empty string */
|
||||
DEF(empty_string, "")
|
||||
/* identifiers */
|
||||
DEF(keys, "keys")
|
||||
DEF(size, "size")
|
||||
DEF(length, "length")
|
||||
DEF(message, "message")
|
||||
DEF(cause, "cause")
|
||||
DEF(errors, "errors")
|
||||
DEF(stack, "stack")
|
||||
DEF(name, "name")
|
||||
DEF(toString, "toString")
|
||||
DEF(toLocaleString, "toLocaleString")
|
||||
DEF(valueOf, "valueOf")
|
||||
DEF(eval, "eval")
|
||||
DEF(prototype, "prototype")
|
||||
DEF(constructor, "constructor")
|
||||
DEF(configurable, "configurable")
|
||||
DEF(writable, "writable")
|
||||
DEF(enumerable, "enumerable")
|
||||
DEF(value, "value")
|
||||
DEF(get, "get")
|
||||
DEF(set, "set")
|
||||
DEF(of, "of")
|
||||
DEF(__proto__, "__proto__")
|
||||
DEF(undefined, "undefined")
|
||||
DEF(number, "number")
|
||||
DEF(boolean, "boolean")
|
||||
DEF(string, "string")
|
||||
DEF(object, "object")
|
||||
DEF(symbol, "symbol")
|
||||
DEF(integer, "integer")
|
||||
DEF(unknown, "unknown")
|
||||
DEF(arguments, "arguments")
|
||||
DEF(callee, "callee")
|
||||
DEF(caller, "caller")
|
||||
DEF(_eval_, "<eval>")
|
||||
DEF(_ret_, "<ret>")
|
||||
DEF(_var_, "<var>")
|
||||
DEF(_arg_var_, "<arg_var>")
|
||||
DEF(_with_, "<with>")
|
||||
DEF(lastIndex, "lastIndex")
|
||||
DEF(target, "target")
|
||||
DEF(index, "index")
|
||||
DEF(input, "input")
|
||||
DEF(defineProperties, "defineProperties")
|
||||
DEF(apply, "apply")
|
||||
DEF(join, "join")
|
||||
DEF(concat, "concat")
|
||||
DEF(split, "split")
|
||||
DEF(construct, "construct")
|
||||
DEF(getPrototypeOf, "getPrototypeOf")
|
||||
DEF(setPrototypeOf, "setPrototypeOf")
|
||||
DEF(isExtensible, "isExtensible")
|
||||
DEF(preventExtensions, "preventExtensions")
|
||||
DEF(has, "has")
|
||||
DEF(deleteProperty, "deleteProperty")
|
||||
DEF(defineProperty, "defineProperty")
|
||||
DEF(getOwnPropertyDescriptor, "getOwnPropertyDescriptor")
|
||||
DEF(ownKeys, "ownKeys")
|
||||
DEF(add, "add")
|
||||
DEF(done, "done")
|
||||
DEF(next, "next")
|
||||
DEF(values, "values")
|
||||
DEF(source, "source")
|
||||
DEF(flags, "flags")
|
||||
DEF(global, "global")
|
||||
DEF(unicode, "unicode")
|
||||
DEF(raw, "raw")
|
||||
DEF(new_target, "new.target")
|
||||
DEF(this_active_func, "this.active_func")
|
||||
DEF(home_object, "<home_object>")
|
||||
DEF(computed_field, "<computed_field>")
|
||||
DEF(static_computed_field, "<static_computed_field>") /* must come after computed_fields */
|
||||
DEF(class_fields_init, "<class_fields_init>")
|
||||
DEF(brand, "<brand>")
|
||||
DEF(hash_constructor, "#constructor")
|
||||
DEF(as, "as")
|
||||
DEF(from, "from")
|
||||
DEF(fromAsync, "fromAsync")
|
||||
DEF(meta, "meta")
|
||||
DEF(_default_, "*default*")
|
||||
DEF(_star_, "*")
|
||||
DEF(Module, "Module")
|
||||
DEF(then, "then")
|
||||
DEF(resolve, "resolve")
|
||||
DEF(reject, "reject")
|
||||
DEF(promise, "promise")
|
||||
DEF(proxy, "proxy")
|
||||
DEF(revoke, "revoke")
|
||||
DEF(async, "async")
|
||||
DEF(exec, "exec")
|
||||
DEF(groups, "groups")
|
||||
DEF(indices, "indices")
|
||||
DEF(status, "status")
|
||||
DEF(reason, "reason")
|
||||
DEF(globalThis, "globalThis")
|
||||
DEF(bigint, "bigint")
|
||||
DEF(not_equal, "not-equal")
|
||||
DEF(timed_out, "timed-out")
|
||||
DEF(ok, "ok")
|
||||
DEF(toJSON, "toJSON")
|
||||
DEF(maxByteLength, "maxByteLength")
|
||||
/* class names */
|
||||
DEF(Object, "Object")
|
||||
DEF(Array, "Array")
|
||||
DEF(Error, "Error")
|
||||
DEF(Number, "Number")
|
||||
DEF(String, "String")
|
||||
DEF(Boolean, "Boolean")
|
||||
DEF(Symbol, "Symbol")
|
||||
DEF(Arguments, "Arguments")
|
||||
DEF(Math, "Math")
|
||||
DEF(JSON, "JSON")
|
||||
DEF(Date, "Date")
|
||||
DEF(Function, "Function")
|
||||
DEF(GeneratorFunction, "GeneratorFunction")
|
||||
DEF(ForInIterator, "ForInIterator")
|
||||
DEF(RegExp, "RegExp")
|
||||
DEF(ArrayBuffer, "ArrayBuffer")
|
||||
DEF(SharedArrayBuffer, "SharedArrayBuffer")
|
||||
/* must keep same order as class IDs for typed arrays */
|
||||
DEF(Uint8ClampedArray, "Uint8ClampedArray")
|
||||
DEF(Int8Array, "Int8Array")
|
||||
DEF(Uint8Array, "Uint8Array")
|
||||
DEF(Int16Array, "Int16Array")
|
||||
DEF(Uint16Array, "Uint16Array")
|
||||
DEF(Int32Array, "Int32Array")
|
||||
DEF(Uint32Array, "Uint32Array")
|
||||
DEF(BigInt64Array, "BigInt64Array")
|
||||
DEF(BigUint64Array, "BigUint64Array")
|
||||
DEF(Float16Array, "Float16Array")
|
||||
DEF(Float32Array, "Float32Array")
|
||||
DEF(Float64Array, "Float64Array")
|
||||
DEF(DataView, "DataView")
|
||||
DEF(BigInt, "BigInt")
|
||||
DEF(WeakRef, "WeakRef")
|
||||
DEF(FinalizationRegistry, "FinalizationRegistry")
|
||||
DEF(Map, "Map")
|
||||
DEF(Set, "Set") /* Map + 1 */
|
||||
DEF(WeakMap, "WeakMap") /* Map + 2 */
|
||||
DEF(WeakSet, "WeakSet") /* Map + 3 */
|
||||
DEF(Iterator, "Iterator")
|
||||
DEF(IteratorConcat, "Iterator Concat")
|
||||
DEF(IteratorHelper, "Iterator Helper")
|
||||
DEF(IteratorWrap, "Iterator Wrap")
|
||||
DEF(Map_Iterator, "Map Iterator")
|
||||
DEF(Set_Iterator, "Set Iterator")
|
||||
DEF(Array_Iterator, "Array Iterator")
|
||||
DEF(String_Iterator, "String Iterator")
|
||||
DEF(RegExp_String_Iterator, "RegExp String Iterator")
|
||||
DEF(Generator, "Generator")
|
||||
DEF(Proxy, "Proxy")
|
||||
DEF(Promise, "Promise")
|
||||
DEF(PromiseResolveFunction, "PromiseResolveFunction")
|
||||
DEF(PromiseRejectFunction, "PromiseRejectFunction")
|
||||
DEF(AsyncFunction, "AsyncFunction")
|
||||
DEF(AsyncFunctionResolve, "AsyncFunctionResolve")
|
||||
DEF(AsyncFunctionReject, "AsyncFunctionReject")
|
||||
DEF(AsyncGeneratorFunction, "AsyncGeneratorFunction")
|
||||
DEF(AsyncGenerator, "AsyncGenerator")
|
||||
DEF(EvalError, "EvalError")
|
||||
DEF(RangeError, "RangeError")
|
||||
DEF(ReferenceError, "ReferenceError")
|
||||
DEF(SyntaxError, "SyntaxError")
|
||||
DEF(TypeError, "TypeError")
|
||||
DEF(URIError, "URIError")
|
||||
DEF(InternalError, "InternalError")
|
||||
DEF(DOMException, "DOMException")
|
||||
DEF(CallSite, "CallSite")
|
||||
/* private symbols */
|
||||
DEF(Private_brand, "<brand>")
|
||||
/* symbols */
|
||||
DEF(Symbol_toPrimitive, "Symbol.toPrimitive")
|
||||
DEF(Symbol_iterator, "Symbol.iterator")
|
||||
DEF(Symbol_match, "Symbol.match")
|
||||
DEF(Symbol_matchAll, "Symbol.matchAll")
|
||||
DEF(Symbol_replace, "Symbol.replace")
|
||||
DEF(Symbol_search, "Symbol.search")
|
||||
DEF(Symbol_split, "Symbol.split")
|
||||
DEF(Symbol_toStringTag, "Symbol.toStringTag")
|
||||
DEF(Symbol_isConcatSpreadable, "Symbol.isConcatSpreadable")
|
||||
DEF(Symbol_hasInstance, "Symbol.hasInstance")
|
||||
DEF(Symbol_species, "Symbol.species")
|
||||
DEF(Symbol_unscopables, "Symbol.unscopables")
|
||||
DEF(Symbol_asyncIterator, "Symbol.asyncIterator")
|
||||
|
||||
#endif /* DEF */
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* QuickJS C atomics definitions
|
||||
*
|
||||
* Copyright (c) 2023 Marcin Kolny
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#if (defined(__GNUC__) || defined(__GNUG__)) && !defined(__clang__)
|
||||
// Use GCC builtins for version < 4.9
|
||||
# if((__GNUC__ << 16) + __GNUC_MINOR__ < ((4) << 16) + 9)
|
||||
# define GCC_BUILTIN_ATOMICS
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef GCC_BUILTIN_ATOMICS
|
||||
#define atomic_fetch_add(obj, arg) \
|
||||
__atomic_fetch_add(obj, arg, __ATOMIC_SEQ_CST)
|
||||
#define atomic_compare_exchange_strong(obj, expected, desired) \
|
||||
__atomic_compare_exchange_n(obj, expected, desired, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
|
||||
#define atomic_exchange(obj, desired) \
|
||||
__atomic_exchange_n (obj, desired, __ATOMIC_SEQ_CST)
|
||||
#define atomic_load(obj) \
|
||||
__atomic_load_n(obj, __ATOMIC_SEQ_CST)
|
||||
#define atomic_store(obj, desired) \
|
||||
__atomic_store_n(obj, desired, __ATOMIC_SEQ_CST)
|
||||
#define atomic_fetch_or(obj, arg) \
|
||||
__atomic_fetch_or(obj, arg, __ATOMIC_SEQ_CST)
|
||||
#define atomic_fetch_xor(obj, arg) \
|
||||
__atomic_fetch_xor(obj, arg, __ATOMIC_SEQ_CST)
|
||||
#define atomic_fetch_and(obj, arg) \
|
||||
__atomic_fetch_and(obj, arg, __ATOMIC_SEQ_CST)
|
||||
#define atomic_fetch_sub(obj, arg) \
|
||||
__atomic_fetch_sub(obj, arg, __ATOMIC_SEQ_CST)
|
||||
#define _Atomic
|
||||
#else
|
||||
#include <stdatomic.h>
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* QuickJS C library
|
||||
*
|
||||
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef QUICKJS_LIBC_H
|
||||
#define QUICKJS_LIBC_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "quickjs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define JS_EXTERN __attribute__((visibility("default")))
|
||||
#else
|
||||
#define JS_EXTERN /* nothing */
|
||||
#endif
|
||||
|
||||
JS_EXTERN JSModuleDef *js_init_module_std(JSContext *ctx,
|
||||
const char *module_name);
|
||||
JS_EXTERN JSModuleDef *js_init_module_os(JSContext *ctx,
|
||||
const char *module_name);
|
||||
JS_EXTERN JSModuleDef *js_init_module_bjson(JSContext *ctx,
|
||||
const char *module_name);
|
||||
JS_EXTERN void js_std_add_helpers(JSContext *ctx, int argc, char **argv);
|
||||
JS_EXTERN int js_std_loop(JSContext *ctx);
|
||||
JS_EXTERN JSValue js_std_await(JSContext *ctx, JSValue obj);
|
||||
JS_EXTERN void js_std_init_handlers(JSRuntime *rt);
|
||||
JS_EXTERN void js_std_free_handlers(JSRuntime *rt);
|
||||
JS_EXTERN void js_std_dump_error(JSContext *ctx);
|
||||
JS_EXTERN uint8_t *js_load_file(JSContext *ctx, size_t *pbuf_len,
|
||||
const char *filename);
|
||||
JS_EXTERN int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val,
|
||||
bool use_realpath, bool is_main);
|
||||
JS_EXTERN JSModuleDef *js_module_loader(JSContext *ctx,
|
||||
const char *module_name, void *opaque);
|
||||
JS_EXTERN void js_std_eval_binary(JSContext *ctx, const uint8_t *buf,
|
||||
size_t buf_len, int flags);
|
||||
JS_EXTERN void js_std_promise_rejection_tracker(JSContext *ctx,
|
||||
JSValueConst promise,
|
||||
JSValueConst reason,
|
||||
bool is_handled,
|
||||
void *opaque);
|
||||
// Defaults to JS_NewRuntime, no-op if compiled without worker support.
|
||||
// Call before creating the first worker thread.
|
||||
JS_EXTERN void js_std_set_worker_new_runtime_func(JSRuntime *(*func)(void));
|
||||
// Defaults to JS_NewContext, no-op if compiled without worker support.
|
||||
// Call before creating the first worker thread.
|
||||
JS_EXTERN void js_std_set_worker_new_context_func(JSContext *(*func)(JSRuntime *rt));
|
||||
|
||||
#undef JS_EXTERN
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" { */
|
||||
#endif
|
||||
|
||||
#endif /* QUICKJS_LIBC_H */
|
||||
@@ -0,0 +1,371 @@
|
||||
/*
|
||||
* QuickJS opcode definitions
|
||||
*
|
||||
* Copyright (c) 2017-2018 Fabrice Bellard
|
||||
* Copyright (c) 2017-2018 Charlie Gordon
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef FMT
|
||||
FMT(none)
|
||||
FMT(none_int)
|
||||
FMT(none_loc)
|
||||
FMT(none_arg)
|
||||
FMT(none_var_ref)
|
||||
FMT(u8)
|
||||
FMT(i8)
|
||||
FMT(loc8)
|
||||
FMT(const8)
|
||||
FMT(label8)
|
||||
FMT(u16)
|
||||
FMT(i16)
|
||||
FMT(label16)
|
||||
FMT(npop)
|
||||
FMT(npopx)
|
||||
FMT(npop_u16)
|
||||
FMT(loc)
|
||||
FMT(arg)
|
||||
FMT(var_ref)
|
||||
FMT(u32)
|
||||
FMT(u32x2)
|
||||
FMT(i32)
|
||||
FMT(const)
|
||||
FMT(label)
|
||||
FMT(atom)
|
||||
FMT(atom_u8)
|
||||
FMT(atom_u16)
|
||||
FMT(atom_label_u8)
|
||||
FMT(atom_label_u16)
|
||||
FMT(label_u16)
|
||||
#undef FMT
|
||||
#endif /* FMT */
|
||||
|
||||
#ifdef DEF
|
||||
|
||||
#ifndef def
|
||||
#define def(id, size, n_pop, n_push, f) DEF(id, size, n_pop, n_push, f)
|
||||
#endif
|
||||
|
||||
DEF(invalid, 1, 0, 0, none) /* never emitted */
|
||||
|
||||
/* push values */
|
||||
DEF( push_i32, 5, 0, 1, i32)
|
||||
DEF( push_const, 5, 0, 1, const)
|
||||
DEF( fclosure, 5, 0, 1, const) /* must follow push_const */
|
||||
DEF(push_atom_value, 5, 0, 1, atom)
|
||||
DEF( private_symbol, 5, 0, 1, atom)
|
||||
DEF( undefined, 1, 0, 1, none)
|
||||
DEF( null, 1, 0, 1, none)
|
||||
DEF( push_this, 1, 0, 1, none) /* only used at the start of a function */
|
||||
DEF( push_false, 1, 0, 1, none)
|
||||
DEF( push_true, 1, 0, 1, none)
|
||||
DEF( object, 1, 0, 1, none)
|
||||
DEF( special_object, 2, 0, 1, u8) /* only used at the start of a function */
|
||||
DEF( rest, 3, 0, 1, u16) /* only used at the start of a function */
|
||||
|
||||
DEF( drop, 1, 1, 0, none) /* a -> */
|
||||
DEF( nip, 1, 2, 1, none) /* a b -> b */
|
||||
DEF( nip1, 1, 3, 2, none) /* a b c -> b c */
|
||||
DEF( dup, 1, 1, 2, none) /* a -> a a */
|
||||
DEF( dup1, 1, 2, 3, none) /* a b -> a a b */
|
||||
DEF( dup2, 1, 2, 4, none) /* a b -> a b a b */
|
||||
DEF( dup3, 1, 3, 6, none) /* a b c -> a b c a b c */
|
||||
DEF( insert2, 1, 2, 3, none) /* obj a -> a obj a (dup_x1) */
|
||||
DEF( insert3, 1, 3, 4, none) /* obj prop a -> a obj prop a (dup_x2) */
|
||||
DEF( insert4, 1, 4, 5, none) /* this obj prop a -> a this obj prop a */
|
||||
DEF( perm3, 1, 3, 3, none) /* obj a b -> a obj b */
|
||||
DEF( perm4, 1, 4, 4, none) /* obj prop a b -> a obj prop b */
|
||||
DEF( perm5, 1, 5, 5, none) /* this obj prop a b -> a this obj prop b */
|
||||
DEF( swap, 1, 2, 2, none) /* a b -> b a */
|
||||
DEF( swap2, 1, 4, 4, none) /* a b c d -> c d a b */
|
||||
DEF( rot3l, 1, 3, 3, none) /* x a b -> a b x */
|
||||
DEF( rot3r, 1, 3, 3, none) /* a b x -> x a b */
|
||||
DEF( rot4l, 1, 4, 4, none) /* x a b c -> a b c x */
|
||||
DEF( rot5l, 1, 5, 5, none) /* x a b c d -> a b c d x */
|
||||
|
||||
DEF(call_constructor, 3, 2, 1, npop) /* func new.target args -> ret. arguments are not counted in n_pop */
|
||||
DEF( call, 3, 1, 1, npop) /* arguments are not counted in n_pop */
|
||||
DEF( tail_call, 3, 1, 0, npop) /* arguments are not counted in n_pop */
|
||||
DEF( call_method, 3, 2, 1, npop) /* arguments are not counted in n_pop */
|
||||
DEF(tail_call_method, 3, 2, 0, npop) /* arguments are not counted in n_pop */
|
||||
DEF( array_from, 3, 0, 1, npop) /* arguments are not counted in n_pop */
|
||||
DEF( apply, 3, 3, 1, u16)
|
||||
DEF( return, 1, 1, 0, none)
|
||||
DEF( return_undef, 1, 0, 0, none)
|
||||
DEF(check_ctor_return, 1, 1, 2, none)
|
||||
DEF( check_ctor, 1, 0, 0, none)
|
||||
DEF( init_ctor, 1, 0, 1, none)
|
||||
DEF( check_brand, 1, 2, 2, none) /* this_obj func -> this_obj func */
|
||||
DEF( add_brand, 1, 2, 0, none) /* this_obj home_obj -> */
|
||||
DEF( return_async, 1, 1, 0, none)
|
||||
DEF( throw, 1, 1, 0, none)
|
||||
DEF( throw_error, 6, 0, 0, atom_u8)
|
||||
DEF( eval, 5, 1, 1, npop_u16) /* func args... -> ret_val */
|
||||
DEF( apply_eval, 3, 2, 1, u16) /* func array -> ret_eval */
|
||||
DEF( regexp, 1, 2, 1, none) /* create a RegExp object from the pattern and a
|
||||
bytecode string */
|
||||
DEF( get_super, 1, 1, 1, none)
|
||||
DEF( import, 1, 1, 1, none) /* dynamic module import */
|
||||
|
||||
DEF( check_var, 5, 0, 1, atom) /* check if a variable exists */
|
||||
DEF( get_var_undef, 5, 0, 1, atom) /* push undefined if the variable does not exist */
|
||||
DEF( get_var, 5, 0, 1, atom) /* throw an exception if the variable does not exist */
|
||||
DEF( put_var, 5, 1, 0, atom) /* must come after get_var */
|
||||
DEF( put_var_init, 5, 1, 0, atom) /* must come after put_var. Used to initialize a global lexical variable */
|
||||
DEF( put_var_strict, 5, 2, 0, atom) /* for strict mode variable write */
|
||||
|
||||
DEF( get_ref_value, 1, 2, 3, none)
|
||||
DEF( put_ref_value, 1, 3, 0, none)
|
||||
|
||||
DEF( define_var, 6, 0, 0, atom_u8)
|
||||
DEF(check_define_var, 6, 0, 0, atom_u8)
|
||||
DEF( define_func, 6, 1, 0, atom_u8)
|
||||
|
||||
// order matters, see IC counterparts
|
||||
DEF( get_field, 5, 1, 1, atom)
|
||||
DEF( get_field2, 5, 1, 2, atom)
|
||||
DEF( put_field, 5, 2, 0, atom)
|
||||
|
||||
DEF( get_private_field, 1, 2, 1, none) /* obj prop -> value */
|
||||
DEF( put_private_field, 1, 3, 0, none) /* obj value prop -> */
|
||||
DEF(define_private_field, 1, 3, 1, none) /* obj prop value -> obj */
|
||||
DEF( get_array_el, 1, 2, 1, none)
|
||||
DEF( get_array_el2, 1, 2, 2, none) /* obj prop -> obj value */
|
||||
DEF( put_array_el, 1, 3, 0, none)
|
||||
DEF(get_super_value, 1, 3, 1, none) /* this obj prop -> value */
|
||||
DEF(put_super_value, 1, 4, 0, none) /* this obj prop value -> */
|
||||
DEF( define_field, 5, 2, 1, atom)
|
||||
DEF( set_name, 5, 1, 1, atom)
|
||||
DEF(set_name_computed, 1, 2, 2, none)
|
||||
DEF( set_proto, 1, 2, 1, none)
|
||||
DEF(set_home_object, 1, 2, 2, none)
|
||||
DEF(define_array_el, 1, 3, 2, none)
|
||||
DEF( append, 1, 3, 2, none) /* append enumerated object, update length */
|
||||
DEF(copy_data_properties, 2, 3, 3, u8)
|
||||
DEF( define_method, 6, 2, 1, atom_u8)
|
||||
DEF(define_method_computed, 2, 3, 1, u8) /* must come after define_method */
|
||||
DEF( define_class, 6, 2, 2, atom_u8) /* parent ctor -> ctor proto */
|
||||
DEF( define_class_computed, 6, 3, 3, atom_u8) /* field_name parent ctor -> field_name ctor proto (class with computed name) */
|
||||
|
||||
DEF( get_loc, 3, 0, 1, loc)
|
||||
DEF( put_loc, 3, 1, 0, loc) /* must come after get_loc */
|
||||
DEF( set_loc, 3, 1, 1, loc) /* must come after put_loc */
|
||||
DEF( get_arg, 3, 0, 1, arg)
|
||||
DEF( put_arg, 3, 1, 0, arg) /* must come after get_arg */
|
||||
DEF( set_arg, 3, 1, 1, arg) /* must come after put_arg */
|
||||
DEF( get_var_ref, 3, 0, 1, var_ref)
|
||||
DEF( put_var_ref, 3, 1, 0, var_ref) /* must come after get_var_ref */
|
||||
DEF( set_var_ref, 3, 1, 1, var_ref) /* must come after put_var_ref */
|
||||
DEF(set_loc_uninitialized, 3, 0, 0, loc)
|
||||
DEF( get_loc_check, 3, 0, 1, loc)
|
||||
DEF( put_loc_check, 3, 1, 0, loc) /* must come after get_loc_check */
|
||||
DEF( put_loc_check_init, 3, 1, 0, loc)
|
||||
DEF(get_var_ref_check, 3, 0, 1, var_ref)
|
||||
DEF(put_var_ref_check, 3, 1, 0, var_ref) /* must come after get_var_ref_check */
|
||||
DEF(put_var_ref_check_init, 3, 1, 0, var_ref)
|
||||
DEF( close_loc, 3, 0, 0, loc)
|
||||
DEF( if_false, 5, 1, 0, label)
|
||||
DEF( if_true, 5, 1, 0, label) /* must come after if_false */
|
||||
DEF( goto, 5, 0, 0, label) /* must come after if_true */
|
||||
DEF( catch, 5, 0, 1, label)
|
||||
DEF( gosub, 5, 0, 0, label) /* used to execute the finally block */
|
||||
DEF( ret, 1, 1, 0, none) /* used to return from the finally block */
|
||||
DEF( nip_catch, 1, 2, 1, none) /* catch ... a -> a */
|
||||
|
||||
DEF( to_object, 1, 1, 1, none)
|
||||
//DEF( to_string, 1, 1, 1, none)
|
||||
DEF( to_propkey, 1, 1, 1, none)
|
||||
DEF( to_propkey2, 1, 2, 2, none)
|
||||
|
||||
DEF( with_get_var, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */
|
||||
DEF( with_put_var, 10, 2, 1, atom_label_u8) /* must be in the same order as scope_xxx */
|
||||
DEF(with_delete_var, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */
|
||||
DEF( with_make_ref, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */
|
||||
DEF( with_get_ref, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */
|
||||
DEF(with_get_ref_undef, 10, 1, 0, atom_label_u8)
|
||||
|
||||
DEF( make_loc_ref, 7, 0, 2, atom_u16)
|
||||
DEF( make_arg_ref, 7, 0, 2, atom_u16)
|
||||
DEF(make_var_ref_ref, 7, 0, 2, atom_u16)
|
||||
DEF( make_var_ref, 5, 0, 2, atom)
|
||||
|
||||
DEF( for_in_start, 1, 1, 1, none)
|
||||
DEF( for_of_start, 1, 1, 3, none)
|
||||
DEF(for_await_of_start, 1, 1, 3, none)
|
||||
DEF( for_in_next, 1, 1, 3, none)
|
||||
DEF( for_of_next, 2, 3, 5, u8)
|
||||
DEF(iterator_check_object, 1, 1, 1, none)
|
||||
DEF(iterator_get_value_done, 1, 1, 2, none)
|
||||
DEF( iterator_close, 1, 3, 0, none)
|
||||
DEF( iterator_next, 1, 4, 4, none)
|
||||
DEF( iterator_call, 2, 4, 5, u8)
|
||||
DEF( initial_yield, 1, 0, 0, none)
|
||||
DEF( yield, 1, 1, 2, none)
|
||||
DEF( yield_star, 1, 1, 2, none)
|
||||
DEF(async_yield_star, 1, 1, 2, none)
|
||||
DEF( await, 1, 1, 1, none)
|
||||
|
||||
/* arithmetic/logic operations */
|
||||
DEF( neg, 1, 1, 1, none)
|
||||
DEF( plus, 1, 1, 1, none)
|
||||
DEF( dec, 1, 1, 1, none)
|
||||
DEF( inc, 1, 1, 1, none)
|
||||
DEF( post_dec, 1, 1, 2, none)
|
||||
DEF( post_inc, 1, 1, 2, none)
|
||||
DEF( dec_loc, 2, 0, 0, loc8)
|
||||
DEF( inc_loc, 2, 0, 0, loc8)
|
||||
DEF( add_loc, 2, 1, 0, loc8)
|
||||
DEF( not, 1, 1, 1, none)
|
||||
DEF( lnot, 1, 1, 1, none)
|
||||
DEF( typeof, 1, 1, 1, none)
|
||||
DEF( delete, 1, 2, 1, none)
|
||||
DEF( delete_var, 5, 0, 1, atom)
|
||||
|
||||
/* warning: order matters (see js_parse_assign_expr) */
|
||||
DEF( mul, 1, 2, 1, none)
|
||||
DEF( div, 1, 2, 1, none)
|
||||
DEF( mod, 1, 2, 1, none)
|
||||
DEF( add, 1, 2, 1, none)
|
||||
DEF( sub, 1, 2, 1, none)
|
||||
DEF( shl, 1, 2, 1, none)
|
||||
DEF( sar, 1, 2, 1, none)
|
||||
DEF( shr, 1, 2, 1, none)
|
||||
DEF( and, 1, 2, 1, none)
|
||||
DEF( xor, 1, 2, 1, none)
|
||||
DEF( or, 1, 2, 1, none)
|
||||
DEF( pow, 1, 2, 1, none)
|
||||
|
||||
DEF( lt, 1, 2, 1, none)
|
||||
DEF( lte, 1, 2, 1, none)
|
||||
DEF( gt, 1, 2, 1, none)
|
||||
DEF( gte, 1, 2, 1, none)
|
||||
DEF( instanceof, 1, 2, 1, none)
|
||||
DEF( in, 1, 2, 1, none)
|
||||
DEF( eq, 1, 2, 1, none)
|
||||
DEF( neq, 1, 2, 1, none)
|
||||
DEF( strict_eq, 1, 2, 1, none)
|
||||
DEF( strict_neq, 1, 2, 1, none)
|
||||
DEF(is_undefined_or_null, 1, 1, 1, none)
|
||||
DEF( private_in, 1, 2, 1, none)
|
||||
DEF(push_bigint_i32, 5, 0, 1, i32)
|
||||
/* must be the last non short and non temporary opcode */
|
||||
DEF( nop, 1, 0, 0, none)
|
||||
|
||||
/* temporary opcodes: never emitted in the final bytecode */
|
||||
|
||||
def( enter_scope, 3, 0, 0, u16) /* emitted in phase 1, removed in phase 2 */
|
||||
def( leave_scope, 3, 0, 0, u16) /* emitted in phase 1, removed in phase 2 */
|
||||
|
||||
def( label, 5, 0, 0, label) /* emitted in phase 1, removed in phase 3 */
|
||||
|
||||
def(scope_get_var_undef, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
||||
def( scope_get_var, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
||||
def( scope_put_var, 7, 1, 0, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
||||
def(scope_delete_var, 7, 0, 1, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
||||
def( scope_make_ref, 11, 0, 2, atom_label_u16) /* emitted in phase 1, removed in phase 2 */
|
||||
def( scope_get_ref, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
||||
def(scope_put_var_init, 7, 0, 2, atom_u16) /* emitted in phase 1, removed in phase 2 */
|
||||
def(scope_get_private_field, 7, 1, 1, atom_u16) /* obj -> value, emitted in phase 1, removed in phase 2 */
|
||||
def(scope_get_private_field2, 7, 1, 2, atom_u16) /* obj -> obj value, emitted in phase 1, removed in phase 2 */
|
||||
def(scope_put_private_field, 7, 2, 0, atom_u16) /* obj value ->, emitted in phase 1, removed in phase 2 */
|
||||
def(scope_in_private_field, 7, 1, 1, atom_u16) /* obj -> res emitted in phase 1, removed in phase 2 */
|
||||
def(get_field_opt_chain, 5, 1, 1, atom) /* emitted in phase 1, removed in phase 2 */
|
||||
def(get_array_el_opt_chain, 1, 2, 1, none) /* emitted in phase 1, removed in phase 2 */
|
||||
def( set_class_name, 5, 1, 1, u32) /* emitted in phase 1, removed in phase 2 */
|
||||
|
||||
def( source_loc, 9, 0, 0, u32x2) /* emitted in phase 1, removed in phase 3 */
|
||||
|
||||
DEF( push_minus1, 1, 0, 1, none_int)
|
||||
DEF( push_0, 1, 0, 1, none_int)
|
||||
DEF( push_1, 1, 0, 1, none_int)
|
||||
DEF( push_2, 1, 0, 1, none_int)
|
||||
DEF( push_3, 1, 0, 1, none_int)
|
||||
DEF( push_4, 1, 0, 1, none_int)
|
||||
DEF( push_5, 1, 0, 1, none_int)
|
||||
DEF( push_6, 1, 0, 1, none_int)
|
||||
DEF( push_7, 1, 0, 1, none_int)
|
||||
DEF( push_i8, 2, 0, 1, i8)
|
||||
DEF( push_i16, 3, 0, 1, i16)
|
||||
DEF( push_const8, 2, 0, 1, const8)
|
||||
DEF( fclosure8, 2, 0, 1, const8) /* must follow push_const8 */
|
||||
DEF(push_empty_string, 1, 0, 1, none)
|
||||
|
||||
DEF( get_loc8, 2, 0, 1, loc8)
|
||||
DEF( put_loc8, 2, 1, 0, loc8)
|
||||
DEF( set_loc8, 2, 1, 1, loc8)
|
||||
|
||||
DEF( get_loc0_loc1, 1, 0, 2, none_loc)
|
||||
DEF( get_loc0, 1, 0, 1, none_loc)
|
||||
DEF( get_loc1, 1, 0, 1, none_loc)
|
||||
DEF( get_loc2, 1, 0, 1, none_loc)
|
||||
DEF( get_loc3, 1, 0, 1, none_loc)
|
||||
DEF( put_loc0, 1, 1, 0, none_loc)
|
||||
DEF( put_loc1, 1, 1, 0, none_loc)
|
||||
DEF( put_loc2, 1, 1, 0, none_loc)
|
||||
DEF( put_loc3, 1, 1, 0, none_loc)
|
||||
DEF( set_loc0, 1, 1, 1, none_loc)
|
||||
DEF( set_loc1, 1, 1, 1, none_loc)
|
||||
DEF( set_loc2, 1, 1, 1, none_loc)
|
||||
DEF( set_loc3, 1, 1, 1, none_loc)
|
||||
DEF( get_arg0, 1, 0, 1, none_arg)
|
||||
DEF( get_arg1, 1, 0, 1, none_arg)
|
||||
DEF( get_arg2, 1, 0, 1, none_arg)
|
||||
DEF( get_arg3, 1, 0, 1, none_arg)
|
||||
DEF( put_arg0, 1, 1, 0, none_arg)
|
||||
DEF( put_arg1, 1, 1, 0, none_arg)
|
||||
DEF( put_arg2, 1, 1, 0, none_arg)
|
||||
DEF( put_arg3, 1, 1, 0, none_arg)
|
||||
DEF( set_arg0, 1, 1, 1, none_arg)
|
||||
DEF( set_arg1, 1, 1, 1, none_arg)
|
||||
DEF( set_arg2, 1, 1, 1, none_arg)
|
||||
DEF( set_arg3, 1, 1, 1, none_arg)
|
||||
DEF( get_var_ref0, 1, 0, 1, none_var_ref)
|
||||
DEF( get_var_ref1, 1, 0, 1, none_var_ref)
|
||||
DEF( get_var_ref2, 1, 0, 1, none_var_ref)
|
||||
DEF( get_var_ref3, 1, 0, 1, none_var_ref)
|
||||
DEF( put_var_ref0, 1, 1, 0, none_var_ref)
|
||||
DEF( put_var_ref1, 1, 1, 0, none_var_ref)
|
||||
DEF( put_var_ref2, 1, 1, 0, none_var_ref)
|
||||
DEF( put_var_ref3, 1, 1, 0, none_var_ref)
|
||||
DEF( set_var_ref0, 1, 1, 1, none_var_ref)
|
||||
DEF( set_var_ref1, 1, 1, 1, none_var_ref)
|
||||
DEF( set_var_ref2, 1, 1, 1, none_var_ref)
|
||||
DEF( set_var_ref3, 1, 1, 1, none_var_ref)
|
||||
|
||||
DEF( get_length, 1, 1, 1, none)
|
||||
|
||||
DEF( if_false8, 2, 1, 0, label8)
|
||||
DEF( if_true8, 2, 1, 0, label8) /* must come after if_false8 */
|
||||
DEF( goto8, 2, 0, 0, label8) /* must come after if_true8 */
|
||||
DEF( goto16, 3, 0, 0, label16)
|
||||
|
||||
DEF( call0, 1, 1, 1, npopx)
|
||||
DEF( call1, 1, 1, 1, npopx)
|
||||
DEF( call2, 1, 1, 1, npopx)
|
||||
DEF( call3, 1, 1, 1, npopx)
|
||||
|
||||
DEF( is_undefined, 1, 1, 1, none)
|
||||
DEF( is_null, 1, 1, 1, none)
|
||||
DEF(typeof_is_undefined, 1, 1, 1, none)
|
||||
DEF( typeof_is_function, 1, 1, 1, none)
|
||||
|
||||
#undef DEF
|
||||
#undef def
|
||||
#endif /* DEF */
|
||||
+58389
File diff suppressed because it is too large
Load Diff
+1302
File diff suppressed because it is too large
Load Diff
+1927
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,129 @@
|
||||
import * as std from "qjs:std";
|
||||
import * as os from "qjs:os";
|
||||
import * as bjson from "qjs:bjson";
|
||||
|
||||
// See quickjs.h
|
||||
const JS_READ_OBJ_BYTECODE = 1 << 0;
|
||||
const JS_READ_OBJ_REFERENCE = 1 << 3;
|
||||
const JS_WRITE_OBJ_BYTECODE = 1 << 0;
|
||||
const JS_WRITE_OBJ_REFERENCE = 1 << 3;
|
||||
const JS_WRITE_OBJ_STRIP_SOURCE = 1 << 4;
|
||||
|
||||
/**
|
||||
* Trailer for standalone binaries. When some code gets bundled with the qjs
|
||||
* executable we add a 12 byte trailer. The first 8 bytes are the magic
|
||||
* string that helps us understand this is a standalone binary, and the
|
||||
* remaining 4 are the offset (from the beginning of the binary) where the
|
||||
* bundled data is located.
|
||||
*
|
||||
* The offset is stored as a 32bit little-endian number.
|
||||
*/
|
||||
const Trailer = {
|
||||
Magic: 'quickjs2',
|
||||
MagicSize: 8,
|
||||
DataSize: 4,
|
||||
Size: 12
|
||||
};
|
||||
|
||||
function encodeAscii(txt) {
|
||||
return new Uint8Array(txt.split('').map(c => c.charCodeAt(0)));
|
||||
}
|
||||
|
||||
function decodeAscii(buf) {
|
||||
return Array.from(buf).map(c => String.fromCharCode(c)).join('')
|
||||
}
|
||||
|
||||
export function compileStandalone(inFile, outFile, targetExe) {
|
||||
// Step 1: compile the source file to bytecode
|
||||
const js = std.loadFile(inFile);
|
||||
|
||||
if (!js) {
|
||||
throw new Error(`failed to open ${inFile}`);
|
||||
}
|
||||
|
||||
const code = std.evalScript(js, {
|
||||
compile_only: true,
|
||||
compile_module: true
|
||||
});
|
||||
const bytecode = new Uint8Array(bjson.write(code, JS_WRITE_OBJ_BYTECODE | JS_WRITE_OBJ_REFERENCE | JS_WRITE_OBJ_STRIP_SOURCE));
|
||||
|
||||
// Step 2: copy the bytecode to the end of the executable and add a marker.
|
||||
const exeFileName = targetExe ?? os.exePath() ?? globalThis.argv0;
|
||||
const exe = std.loadFile(exeFileName, { binary: true });
|
||||
|
||||
if (!exe) {
|
||||
throw new Error(`failed to open executable: ${exeFileName}`);
|
||||
}
|
||||
|
||||
const exeSize = exe.length;
|
||||
const newBuffer = exe.buffer.transfer(exeSize + bytecode.length + Trailer.Size);
|
||||
const newExe = new Uint8Array(newBuffer);
|
||||
|
||||
newExe.set(bytecode, exeSize);
|
||||
newExe.set(encodeAscii(Trailer.Magic), exeSize + bytecode.length);
|
||||
|
||||
const dw = new DataView(newBuffer, exeSize + bytecode.length + Trailer.MagicSize, Trailer.DataSize);
|
||||
|
||||
dw.setUint32(0, exeSize, true /* little-endian */);
|
||||
|
||||
// We use os.open() so we can set the permissions mask.
|
||||
const newFd = os.open(outFile, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o755);
|
||||
|
||||
if (newFd < 0) {
|
||||
throw new Error(`failed to create ${outFile}`);
|
||||
}
|
||||
if (os.write(newFd, newBuffer, 0, newBuffer.byteLength) < 0) {
|
||||
os.close(newFd);
|
||||
throw new Error(`failed to write to output file`);
|
||||
}
|
||||
os.close(newFd);
|
||||
}
|
||||
|
||||
export function runStandalone() {
|
||||
const file = os.exePath() ?? globalThis.argv0;
|
||||
const exe = std.open(file, 'rb');
|
||||
|
||||
if (!exe) {
|
||||
throw new Error(`failed to open executable: ${file}`);
|
||||
}
|
||||
|
||||
let r = exe.seek(-Trailer.Size, std.SEEK_END);
|
||||
if (r < 0) {
|
||||
throw new Error(`seek error: ${-r}`);
|
||||
}
|
||||
|
||||
const trailer = new Uint8Array(Trailer.Size);
|
||||
|
||||
exe.read(trailer.buffer, 0, Trailer.Size);
|
||||
|
||||
const magic = new Uint8Array(trailer.buffer, 0, Trailer.MagicSize);
|
||||
|
||||
// Shouldn't happen since qjs.c checks for it.
|
||||
if (decodeAscii(magic) !== Trailer.Magic) {
|
||||
exe.close();
|
||||
throw new Error('corrupted binary, magic mismatch');
|
||||
}
|
||||
|
||||
const dw = new DataView(trailer.buffer, Trailer.MagicSize, Trailer.DataSize);
|
||||
const offset = dw.getUint32(0, true /* little-endian */);
|
||||
const bytecode = new Uint8Array(offset - Trailer.Size);
|
||||
|
||||
r = exe.seek(offset, std.SEEK_SET);
|
||||
if (r < 0) {
|
||||
exe.close();
|
||||
throw new Error(`seek error: ${-r}`);
|
||||
}
|
||||
|
||||
exe.read(bytecode.buffer, 0, bytecode.length);
|
||||
if (exe.error()) {
|
||||
exe.close();
|
||||
throw new Error('read error');
|
||||
}
|
||||
exe.close();
|
||||
|
||||
const code = bjson.read(bytecode.buffer, 0, bytecode.length, JS_READ_OBJ_BYTECODE | JS_READ_OBJ_REFERENCE);
|
||||
|
||||
return std.evalScript(code, {
|
||||
eval_module: true
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
[exclude]
|
||||
# list excluded tests and directories here for faster operation
|
||||
|
||||
# lengthy constructed regexp (>500 ms)
|
||||
test262/test/annexB/built-ins/RegExp/RegExp-leading-escape-BMP.js
|
||||
test262/test/annexB/built-ins/RegExp/RegExp-trailing-escape-BMP.js
|
||||
|
||||
# slow notifications (> 600 ms)
|
||||
test262/test/built-ins/Atomics/notify/notify-in-order-one-time.js
|
||||
test262/test/built-ins/Atomics/notify/notify-in-order.js
|
||||
test262/test/built-ins/Atomics/wait/bigint/waiterlist-order-of-operations-is-fifo.js
|
||||
test262/test/built-ins/Atomics/wait/waiterlist-order-of-operations-is-fifo.js
|
||||
|
||||
# lengthy constructed regexp (>200 ms)
|
||||
test262/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-digit-class-escape-flags-u.js
|
||||
test262/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-digit-class-escape-plus-quantifier-flags-u.js
|
||||
test262/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-whitespace-class-escape-flags-u.js
|
||||
test262/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-whitespace-class-escape-plus-quantifier-flags-u.js
|
||||
test262/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-word-class-escape-flags-u.js
|
||||
test262/test/built-ins/RegExp/CharacterClassEscapes/character-class-non-word-class-escape-plus-quantifier-flags-u.js
|
||||
test262/test/built-ins/RegExp/character-class-escape-non-whitespace.js
|
||||
|
||||
# 417 lengty tests with huge constructed regexp (>200 ms)
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/
|
||||
|
||||
# lengthy constructed URLS (>200 ms)
|
||||
test262/test/built-ins/decodeURI/S15.1.3.1_A1.2_T1.js
|
||||
test262/test/built-ins/decodeURI/S15.1.3.1_A1.2_T2.js
|
||||
test262/test/built-ins/decodeURI/S15.1.3.1_A1.10_T1.js
|
||||
test262/test/built-ins/decodeURI/S15.1.3.1_A1.11_T1.js
|
||||
test262/test/built-ins/decodeURI/S15.1.3.1_A1.11_T2.js
|
||||
test262/test/built-ins/decodeURI/S15.1.3.1_A1.12_T1.js
|
||||
test262/test/built-ins/decodeURI/S15.1.3.1_A1.12_T2.js
|
||||
test262/test/built-ins/decodeURI/S15.1.3.1_A1.12_T3.js
|
||||
test262/test/built-ins/decodeURI/S15.1.3.1_A2.5_T1.js
|
||||
test262/test/built-ins/decodeURIComponent/S15.1.3.2_A1.2_T1.js
|
||||
test262/test/built-ins/decodeURIComponent/S15.1.3.2_A1.2_T2.js
|
||||
test262/test/built-ins/decodeURIComponent/S15.1.3.2_A1.10_T1.js
|
||||
test262/test/built-ins/decodeURIComponent/S15.1.3.2_A1.11_T1.js
|
||||
test262/test/built-ins/decodeURIComponent/S15.1.3.2_A1.11_T2.js
|
||||
test262/test/built-ins/decodeURIComponent/S15.1.3.2_A1.12_T1.js
|
||||
test262/test/built-ins/decodeURIComponent/S15.1.3.2_A1.12_T2.js
|
||||
test262/test/built-ins/decodeURIComponent/S15.1.3.2_A1.12_T3.js
|
||||
test262/test/built-ins/decodeURIComponent/S15.1.3.2_A2.5_T1.js
|
||||
|
||||
# lengthy comment tests
|
||||
test262/test/language/comments/S7.4_A5.js
|
||||
test262/test/language/comments/S7.4_A6.js
|
||||
|
||||
# lengthy unicode level tests
|
||||
test262/test/language/identifiers/start-unicode-5.2.0-class-escaped.js
|
||||
test262/test/language/identifiers/start-unicode-5.2.0-class.js
|
||||
test262/test/language/identifiers/start-unicode-8.0.0-class-escaped.js
|
||||
test262/test/language/identifiers/start-unicode-8.0.0-class.js
|
||||
test262/test/language/identifiers/start-unicode-9.0.0-class-escaped.js
|
||||
test262/test/language/identifiers/start-unicode-9.0.0-class.js
|
||||
test262/test/language/identifiers/start-unicode-10.0.0-class-escaped.js
|
||||
test262/test/language/identifiers/start-unicode-10.0.0-class.js
|
||||
test262/test/language/identifiers/start-unicode-13.0.0-class-escaped.js
|
||||
test262/test/language/identifiers/start-unicode-13.0.0-class.js
|
||||
test262/test/language/identifiers/start-unicode-15.0.0-class-escaped.js
|
||||
test262/test/language/identifiers/start-unicode-15.0.0-class.js
|
||||
|
||||
# Atomics tests with 2 second delays
|
||||
test262/test/built-ins/Atomics/notify/bigint/notify-all-on-loc.js
|
||||
test262/test/built-ins/Atomics/notify/negative-count.js
|
||||
test262/test/built-ins/Atomics/notify/notify-all-on-loc.js
|
||||
test262/test/built-ins/Atomics/notify/notify-all.js
|
||||
test262/test/built-ins/Atomics/notify/notify-nan.js
|
||||
test262/test/built-ins/Atomics/notify/notify-one.js
|
||||
test262/test/built-ins/Atomics/notify/notify-two.js
|
||||
test262/test/built-ins/Atomics/notify/notify-zero.js
|
||||
|
||||
# Atomics tests with 400 millisecond delays
|
||||
test262/test/built-ins/Atomics/wait/bigint/no-spurious-wakeup-no-operation.js
|
||||
test262/test/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-add.js
|
||||
test262/test/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-and.js
|
||||
test262/test/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-compareExchange.js
|
||||
test262/test/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-exchange.js
|
||||
test262/test/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-or.js
|
||||
test262/test/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-store.js
|
||||
test262/test/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-sub.js
|
||||
test262/test/built-ins/Atomics/wait/bigint/no-spurious-wakeup-on-xor.js
|
||||
test262/test/built-ins/Atomics/wait/no-spurious-wakeup-no-operation.js
|
||||
test262/test/built-ins/Atomics/wait/no-spurious-wakeup-on-add.js
|
||||
test262/test/built-ins/Atomics/wait/no-spurious-wakeup-on-and.js
|
||||
test262/test/built-ins/Atomics/wait/no-spurious-wakeup-on-compareExchange.js
|
||||
test262/test/built-ins/Atomics/wait/no-spurious-wakeup-on-exchange.js
|
||||
test262/test/built-ins/Atomics/wait/no-spurious-wakeup-on-or.js
|
||||
test262/test/built-ins/Atomics/wait/no-spurious-wakeup-on-store.js
|
||||
test262/test/built-ins/Atomics/wait/no-spurious-wakeup-on-sub.js
|
||||
test262/test/built-ins/Atomics/wait/no-spurious-wakeup-on-xor.js
|
||||
|
||||
# Atomics tests with 200 millisecond delays
|
||||
test262/test/built-ins/Atomics/notify/count-defaults-to-infinity-missing.js
|
||||
test262/test/built-ins/Atomics/notify/count-defaults-to-infinity-undefined.js
|
||||
test262/test/built-ins/Atomics/notify/notify-renotify-noop.js
|
||||
test262/test/built-ins/Atomics/notify/undefined-index-defaults-to-zero.js
|
||||
test262/test/built-ins/Atomics/wait/bigint/false-for-timeout-agent.js
|
||||
test262/test/built-ins/Atomics/wait/bigint/nan-for-timeout.js
|
||||
test262/test/built-ins/Atomics/wait/bigint/negative-timeout-agent.js
|
||||
test262/test/built-ins/Atomics/wait/bigint/value-not-equal.js
|
||||
test262/test/built-ins/Atomics/wait/bigint/was-woken-before-timeout.js
|
||||
test262/test/built-ins/Atomics/wait/false-for-timeout-agent.js
|
||||
test262/test/built-ins/Atomics/wait/nan-for-timeout.js
|
||||
test262/test/built-ins/Atomics/wait/negative-timeout-agent.js
|
||||
test262/test/built-ins/Atomics/wait/null-for-timeout-agent.js
|
||||
test262/test/built-ins/Atomics/wait/object-for-timeout-agent.js
|
||||
test262/test/built-ins/Atomics/wait/poisoned-object-for-timeout-throws-agent.js
|
||||
test262/test/built-ins/Atomics/wait/symbol-for-index-throws-agent.js
|
||||
test262/test/built-ins/Atomics/wait/symbol-for-timeout-throws-agent.js
|
||||
test262/test/built-ins/Atomics/wait/symbol-for-value-throws-agent.js
|
||||
test262/test/built-ins/Atomics/wait/true-for-timeout-agent.js
|
||||
test262/test/built-ins/Atomics/wait/undefined-for-timeout.js
|
||||
test262/test/built-ins/Atomics/wait/undefined-index-defaults-to-zero.js
|
||||
test262/test/built-ins/Atomics/wait/value-not-equal.js
|
||||
test262/test/built-ins/Atomics/wait/wait-index-value-not-equal.js
|
||||
test262/test/built-ins/Atomics/wait/was-woken-before-timeout.js
|
||||
|
||||
# lengthy regexp literal construction (>500 ms)
|
||||
test262/test/language/literals/regexp/S7.8.5_A1.1_T2.js
|
||||
test262/test/language/literals/regexp/S7.8.5_A1.4_T2.js
|
||||
test262/test/language/literals/regexp/S7.8.5_A2.1_T2.js
|
||||
test262/test/language/literals/regexp/S7.8.5_A2.4_T2.js
|
||||
|
||||
# lengthy built-ins tests (100-200 ms)
|
||||
test262/test/built-ins/Function/prototype/toString/built-in-function-object.js
|
||||
test262/test/built-ins/decodeURI/S15.1.3.1_A2.4_T1.js
|
||||
test262/test/built-ins/decodeURIComponent/S15.1.3.2_A2.4_T1.js
|
||||
test262/test/built-ins/encodeURI/S15.1.3.3_A2.3_T1.js
|
||||
test262/test/built-ins/encodeURIComponent/S15.1.3.4_A2.3_T1.js
|
||||
test262/test/language/expressions/dynamic-import/await-import-evaluation.js
|
||||
@@ -0,0 +1,399 @@
|
||||
[config]
|
||||
# general settings for test262 ES6 version
|
||||
|
||||
# handle tests tagged as [noStrict]: yes, no, skip
|
||||
nostrict=yes
|
||||
|
||||
# handle tests tagged as [strictOnly]: yes, no, skip
|
||||
strict=yes
|
||||
|
||||
# test mode: default, default-nostrict, default-strict, strict, nostrict, both, all
|
||||
mode=default
|
||||
|
||||
# handle tests flagged as [async]: yes, no, skip
|
||||
# for these, load 'harness/doneprintHandle.js' prior to test
|
||||
# and expect `print('Test262:AsyncTestComplete')` to be called for
|
||||
# successful termination
|
||||
async=yes
|
||||
|
||||
# handle tests flagged as [module]: yes, no, skip
|
||||
module=yes
|
||||
|
||||
# output error messages: yes, no
|
||||
verbose=yes
|
||||
|
||||
# load harness files from this directory
|
||||
harnessdir=test262/harness
|
||||
|
||||
# names of harness include files to skip
|
||||
#harnessexclude=
|
||||
|
||||
# name of the error file for known errors
|
||||
errorfile=test262_errors.txt
|
||||
|
||||
# exclude tests enumerated in this file (see also [exclude] section)
|
||||
#excludefile=test262_exclude.txt
|
||||
|
||||
# enumerate tests from this directory
|
||||
testdir=test262/test
|
||||
|
||||
[features]
|
||||
# Standard language features and proposed extensions
|
||||
# list the features that are included
|
||||
# skipped features are tagged as such to avoid warnings
|
||||
# Keep this list alpha-sorted (:sort i in vim)
|
||||
|
||||
__getter__
|
||||
__proto__
|
||||
__setter__
|
||||
AggregateError
|
||||
align-detached-buffer-semantics-with-web-reality
|
||||
arbitrary-module-namespace-names
|
||||
array-find-from-last
|
||||
array-grouping
|
||||
Array.fromAsync
|
||||
Array.prototype.at
|
||||
Array.prototype.flat
|
||||
Array.prototype.flatMap
|
||||
Array.prototype.includes
|
||||
Array.prototype.values
|
||||
ArrayBuffer
|
||||
arraybuffer-transfer
|
||||
arrow-function
|
||||
async-functions
|
||||
async-iteration
|
||||
Atomics.pause=!tcc
|
||||
Atomics.waitAsync=skip
|
||||
Atomics=!tcc # atomics are broken in recent versions of tcc
|
||||
BigInt
|
||||
caller
|
||||
canonical-tz=skip
|
||||
change-array-by-copy
|
||||
class
|
||||
class-fields-private
|
||||
class-fields-private-in
|
||||
class-fields-public
|
||||
class-methods-private
|
||||
class-static-block
|
||||
class-static-fields-private
|
||||
class-static-fields-public
|
||||
class-static-methods-private
|
||||
coalesce-expression
|
||||
computed-property-names
|
||||
const
|
||||
cross-realm
|
||||
DataView
|
||||
DataView.prototype.getFloat32
|
||||
DataView.prototype.getFloat64
|
||||
DataView.prototype.getInt16
|
||||
DataView.prototype.getInt32
|
||||
DataView.prototype.getInt8
|
||||
DataView.prototype.getUint16
|
||||
DataView.prototype.getUint32
|
||||
DataView.prototype.setUint8
|
||||
decorators=skip
|
||||
default-parameters
|
||||
destructuring-assignment
|
||||
destructuring-binding
|
||||
dynamic-import
|
||||
error-cause
|
||||
Error.isError
|
||||
explicit-resource-management=skip
|
||||
exponentiation
|
||||
export-star-as-namespace-from-module
|
||||
FinalizationRegistry
|
||||
Float16Array
|
||||
Float32Array
|
||||
Float64Array
|
||||
for-in-order
|
||||
for-of
|
||||
generators
|
||||
globalThis
|
||||
hashbang
|
||||
host-gc-required=skip
|
||||
immutable-arraybuffer=skip
|
||||
import-assertions=skip
|
||||
import-attributes=skip
|
||||
import-defer=skip
|
||||
import.meta
|
||||
Int16Array
|
||||
Int32Array
|
||||
Int8Array
|
||||
Intl-enumeration=skip
|
||||
intl-normative-optional=skip
|
||||
Intl.DateTimeFormat-datetimestyle=skip
|
||||
Intl.DateTimeFormat-dayPeriod=skip
|
||||
Intl.DateTimeFormat-extend-timezonename=skip
|
||||
Intl.DateTimeFormat-formatRange=skip
|
||||
Intl.DateTimeFormat-fractionalSecondDigits=skip
|
||||
Intl.DisplayNames-v2=skip
|
||||
Intl.DisplayNames=skip
|
||||
Intl.DurationFormat=skip
|
||||
Intl.ListFormat=skip
|
||||
Intl.Locale-info=skip
|
||||
Intl.Locale=skip
|
||||
Intl.NumberFormat-unified=skip
|
||||
Intl.NumberFormat-v3=skip
|
||||
Intl.RelativeTimeFormat=skip
|
||||
Intl.Segmenter=skip
|
||||
IsHTMLDDA
|
||||
iterator-helpers
|
||||
iterator-sequencing
|
||||
joint-iteration=skip
|
||||
json-modules=skip
|
||||
json-parse-with-source=skip
|
||||
json-superset
|
||||
legacy-regexp=skip
|
||||
let
|
||||
logical-assignment-operators
|
||||
Map
|
||||
Math.sumPrecise
|
||||
new.target
|
||||
nonextensible-applies-to-private=skip
|
||||
numeric-separator-literal
|
||||
object-rest
|
||||
object-spread
|
||||
Object.fromEntries
|
||||
Object.hasOwn
|
||||
Object.is
|
||||
optional-catch-binding
|
||||
optional-chaining
|
||||
Promise
|
||||
promise-try
|
||||
promise-with-resolvers
|
||||
Promise.allSettled
|
||||
Promise.any
|
||||
Promise.prototype.finally
|
||||
Proxy
|
||||
proxy-missing-checks
|
||||
Reflect
|
||||
Reflect.construct
|
||||
Reflect.set
|
||||
Reflect.setPrototypeOf
|
||||
regexp-dotall
|
||||
regexp-duplicate-named-groups=skip
|
||||
regexp-lookbehind
|
||||
regexp-match-indices
|
||||
regexp-modifiers=skip
|
||||
regexp-named-groups
|
||||
regexp-unicode-property-escapes
|
||||
regexp-v-flag
|
||||
RegExp.escape
|
||||
resizable-arraybuffer
|
||||
rest-parameters
|
||||
Set
|
||||
set-methods
|
||||
ShadowRealm=skip
|
||||
SharedArrayBuffer
|
||||
source-phase-imports-module-source=skip
|
||||
source-phase-imports=skip
|
||||
stable-array-sort
|
||||
stable-typedarray-sort
|
||||
string-trimming
|
||||
String.fromCodePoint
|
||||
String.prototype.at
|
||||
String.prototype.endsWith
|
||||
String.prototype.includes
|
||||
String.prototype.isWellFormed
|
||||
String.prototype.matchAll
|
||||
String.prototype.replaceAll
|
||||
String.prototype.toWellFormed
|
||||
String.prototype.trimEnd
|
||||
String.prototype.trimStart
|
||||
super
|
||||
Symbol
|
||||
Symbol.asyncIterator
|
||||
Symbol.hasInstance
|
||||
Symbol.isConcatSpreadable
|
||||
Symbol.iterator
|
||||
Symbol.match
|
||||
Symbol.matchAll
|
||||
Symbol.prototype.description
|
||||
Symbol.replace
|
||||
Symbol.search
|
||||
Symbol.species
|
||||
Symbol.split
|
||||
Symbol.toPrimitive
|
||||
Symbol.toStringTag
|
||||
Symbol.unscopables
|
||||
symbols-as-weakmap-keys
|
||||
tail-call-optimization=skip
|
||||
template
|
||||
Temporal=skip
|
||||
top-level-await
|
||||
TypedArray
|
||||
TypedArray.prototype.at
|
||||
u180e
|
||||
Uint16Array
|
||||
Uint32Array
|
||||
Uint8Array
|
||||
uint8array-base64=skip
|
||||
Uint8ClampedArray
|
||||
upsert
|
||||
WeakMap
|
||||
WeakRef
|
||||
WeakSet
|
||||
well-formed-json-stringify
|
||||
|
||||
[exclude]
|
||||
# list excluded tests and directories here
|
||||
|
||||
# intl not supported
|
||||
test262/test/intl402/
|
||||
|
||||
# incompatible with the "caller" feature
|
||||
test262/test/built-ins/Function/prototype/restricted-property-caller.js
|
||||
test262/test/built-ins/Function/prototype/restricted-property-arguments.js
|
||||
test262/test/built-ins/ThrowTypeError/unique-per-realm-function-proto.js
|
||||
|
||||
# slow tests
|
||||
#test262/test/built-ins/RegExp/CharacterClassEscapes/
|
||||
#test262/test/built-ins/RegExp/property-escapes/
|
||||
|
||||
# in progress regexp-v-flag support, see https://github.com/quickjs-ng/quickjs/issues/228
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/strings/Basic_Emoji-negative-CharacterClass.js
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/strings/Basic_Emoji-negative-P.js
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/strings/Basic_Emoji-negative-u.js
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/strings/Basic_Emoji.js
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/strings/Emoji_Keycap_Sequence-negative-CharacterClass.js
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/strings/Emoji_Keycap_Sequence-negative-P.js
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/strings/Emoji_Keycap_Sequence-negative-u.js
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/strings/Emoji_Keycap_Sequence.js
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji-negative-CharacterClass.js
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji-negative-P.js
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji-negative-u.js
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji.js
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Flag_Sequence-negative-CharacterClass.js
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Flag_Sequence-negative-P.js
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Flag_Sequence-negative-u.js
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Flag_Sequence.js
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Modifier_Sequence-negative-CharacterClass.js
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Modifier_Sequence-negative-P.js
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Modifier_Sequence-negative-u.js
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Modifier_Sequence.js
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Tag_Sequence-negative-CharacterClass.js
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Tag_Sequence-negative-P.js
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Tag_Sequence-negative-u.js
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_Tag_Sequence.js
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_ZWJ_Sequence-negative-CharacterClass.js
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_ZWJ_Sequence-negative-P.js
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_ZWJ_Sequence-negative-u.js
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/strings/RGI_Emoji_ZWJ_Sequence.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-difference-character-class-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-difference-character-class.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-difference-character-property-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-difference-character.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-difference-property-of-strings-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-difference-string-literal.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-difference-character-class-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-difference-character-class.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-difference-character-property-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-difference-character.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-difference-property-of-strings-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-difference-string-literal.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-intersection-character-class-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-intersection-character-class.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-intersection-character-property-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-intersection-character.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-intersection-property-of-strings-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-intersection-string-literal.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-union-character-class-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-union-character-class.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-union-character-property-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-union-character.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-union-property-of-strings-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-escape-union-string-literal.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-intersection-character-class-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-intersection-character-class.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-intersection-character-property-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-intersection-character.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-intersection-property-of-strings-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-intersection-string-literal.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-union-character-class-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-union-character-class.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-union-character-property-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-union-character.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-union-property-of-strings-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-class-union-string-literal.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-difference-character-class-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-difference-character-class.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-difference-character-property-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-difference-character.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-difference-property-of-strings-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-difference-string-literal.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-intersection-character-class-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-intersection-character-class.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-intersection-character-property-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-intersection-character.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-intersection-property-of-strings-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-intersection-string-literal.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-difference-character-class-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-difference-character-class.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-difference-character-property-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-difference-character.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-difference-property-of-strings-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-difference-string-literal.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-intersection-character-class-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-intersection-character-class.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-intersection-character-property-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-intersection-character.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-intersection-property-of-strings-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-intersection-string-literal.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-union-character-class-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-union-character-class.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-union-character-property-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-union-character.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-union-property-of-strings-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-property-escape-union-string-literal.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-union-character-class-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-union-character-class.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-union-character-property-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-union-character.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-union-property-of-strings-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/character-union-string-literal.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-difference-character-class-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-difference-character-class.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-difference-character-property-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-difference-character.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-difference-property-of-strings-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-difference-string-literal.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-intersection-character-class-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-intersection-character-class.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-intersection-character-property-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-intersection-character.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-intersection-property-of-strings-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-intersection-string-literal.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-union-character-class-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-union-character-class.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-union-character-property-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-union-character.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-union-property-of-strings-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/property-of-strings-escape-union-string-literal.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/rgi-emoji-13.1.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/rgi-emoji-14.0.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/rgi-emoji-15.0.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/rgi-emoji-15.1.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-difference-character-class-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-difference-character-class.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-difference-character-property-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-difference-character.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-difference-property-of-strings-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-difference-string-literal.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-intersection-character-class-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-intersection-character-class.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-intersection-character-property-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-intersection-character.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-intersection-property-of-strings-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-intersection-string-literal.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-union-character-class-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-union-character-class.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-union-character-property-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-union-character.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-union-property-of-strings-escape.js
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/string-literal-union-string-literal.js
|
||||
|
||||
# frequently broken, sometimes contain engine-dependent tests
|
||||
test262/test/staging/
|
||||
|
||||
[tests]
|
||||
# list test files or use config.testdir
|
||||
@@ -0,0 +1,93 @@
|
||||
test262/test/annexB/language/expressions/assignmenttargettype/callexpression-as-for-in-lhs.js:27: SyntaxError: invalid for in/of left hand-side
|
||||
test262/test/annexB/language/expressions/assignmenttargettype/callexpression-as-for-of-lhs.js:27: SyntaxError: invalid for in/of left hand-side
|
||||
test262/test/annexB/language/expressions/assignmenttargettype/callexpression-in-compound-assignment.js:33: SyntaxError: invalid assignment left-hand side
|
||||
test262/test/annexB/language/expressions/assignmenttargettype/callexpression-in-postfix-update.js:27: SyntaxError: invalid increment/decrement operand
|
||||
test262/test/annexB/language/expressions/assignmenttargettype/callexpression-in-prefix-update.js:27: SyntaxError: invalid increment/decrement operand
|
||||
test262/test/annexB/language/expressions/assignmenttargettype/callexpression.js:33: SyntaxError: invalid assignment left-hand side
|
||||
test262/test/annexB/language/expressions/assignmenttargettype/cover-callexpression-and-asyncarrowhead.js:20: SyntaxError: invalid assignment left-hand side
|
||||
test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/iterator-result-poisoned-wrapper.js:64: TypeError: $DONE() not called
|
||||
test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/iterator-result-poisoned-wrapper.js:64: strict mode: TypeError: $DONE() not called
|
||||
test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/next-result-poisoned-wrapper.js:69: TypeError: $DONE() not called
|
||||
test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/next-result-poisoned-wrapper.js:69: strict mode: TypeError: $DONE() not called
|
||||
test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/yield-iterator-next-rejected-promise-close.js:59: TypeError: $DONE() not called
|
||||
test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/yield-iterator-next-rejected-promise-close.js:59: strict mode: TypeError: $DONE() not called
|
||||
test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/yield-next-rejected-promise-close.js:64: TypeError: $DONE() not called
|
||||
test262/test/built-ins/AsyncFromSyncIteratorPrototype/next/yield-next-rejected-promise-close.js:64: strict mode: TypeError: $DONE() not called
|
||||
test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/iterator-result-rejected-promise-close.js:74: TypeError: $DONE() not called
|
||||
test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/iterator-result-rejected-promise-close.js:74: strict mode: TypeError: $DONE() not called
|
||||
test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/throw-result-poisoned-wrapper.js:81: TypeError: $DONE() not called
|
||||
test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/throw-result-poisoned-wrapper.js:81: strict mode: TypeError: $DONE() not called
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/Script_-_Unknown.js:16: SyntaxError: unknown unicode script
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/Script_-_Unknown.js:16: strict mode: SyntaxError: unknown unicode script
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Unknown.js:16: SyntaxError: unknown unicode script
|
||||
test262/test/built-ins/RegExp/property-escapes/generated/Script_Extensions_-_Unknown.js:16: strict mode: SyntaxError: unknown unicode script
|
||||
test262/test/built-ins/RegExp/property-escapes/special-property-value-Script_Extensions-Unknown.js:14: SyntaxError: unknown unicode script
|
||||
test262/test/built-ins/RegExp/property-escapes/special-property-value-Script_Extensions-Unknown.js:14: strict mode: SyntaxError: unknown unicode script
|
||||
test262/test/built-ins/RegExp/prototype/exec/regexp-builtin-exec-v-u-flag.js:45: Test262Error: Actual argument [null] shouldn't be primitive. Unicode property escapes with v flag
|
||||
test262/test/built-ins/RegExp/prototype/exec/regexp-builtin-exec-v-u-flag.js:45: strict mode: Test262Error: Actual argument [null] shouldn't be primitive. Unicode property escapes with v flag
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/rgi-emoji-16.0.js:16: Test262Error: `\p{RGI_Emoji}` should match 🇨🇶 (U+01F1E8 U+01F1F6)
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/rgi-emoji-16.0.js:16: strict mode: Test262Error: `\p{RGI_Emoji}` should match 🇨🇶 (U+01F1E8 U+01F1F6)
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/rgi-emoji-17.0.js:16: Test262Error: `\p{RGI_Emoji}` should match 👨🏻🐰👨🏼 (U+01F468 U+01F3FB U+00200D U+01F430 U+00200D U+01F468 U+01F3FC)
|
||||
test262/test/built-ins/RegExp/unicodeSets/generated/rgi-emoji-17.0.js:16: strict mode: Test262Error: `\p{RGI_Emoji}` should match 👨🏻🐰👨🏼 (U+01F468 U+01F3FB U+00200D U+01F430 U+00200D U+01F468 U+01F3FC)
|
||||
test262/test/built-ins/String/prototype/match/regexp-prototype-match-v-u-flag.js:10: Test262Error: Actual argument [null] shouldn't be primitive. Unicode property escapes with v flag
|
||||
test262/test/built-ins/String/prototype/match/regexp-prototype-match-v-u-flag.js:10: strict mode: Test262Error: Actual argument [null] shouldn't be primitive. Unicode property escapes with v flag
|
||||
test262/test/built-ins/String/prototype/matchAll/regexp-prototype-matchAll-v-u-flag.js:73: Test262Error: Actual [] and expected [𠮷, 𠮷, 𠮷, 0, 3, 6] should have the same contents.
|
||||
test262/test/built-ins/String/prototype/matchAll/regexp-prototype-matchAll-v-u-flag.js:73: strict mode: Test262Error: Actual [] and expected [𠮷, 𠮷, 𠮷, 0, 3, 6] should have the same contents.
|
||||
test262/test/built-ins/String/prototype/replace/regexp-prototype-replace-v-u-flag.js:9: Test262Error: Unicode property escapes with v flag Expected SameValue(«"𠮷a𠮷b𠮷"», «"XaXbX"») to be true
|
||||
test262/test/built-ins/String/prototype/replace/regexp-prototype-replace-v-u-flag.js:9: strict mode: Test262Error: Unicode property escapes with v flag Expected SameValue(«"𠮷a𠮷b𠮷"», «"XaXbX"») to be true
|
||||
test262/test/built-ins/String/prototype/search/regexp-prototype-search-v-flag.js:9: Test262Error: Unicode property escapes with v flag Expected SameValue(«-1», «0») to be true
|
||||
test262/test/built-ins/String/prototype/search/regexp-prototype-search-v-flag.js:9: strict mode: Test262Error: Unicode property escapes with v flag Expected SameValue(«-1», «0») to be true
|
||||
test262/test/built-ins/String/prototype/search/regexp-prototype-search-v-u-flag.js:9: Test262Error: Unicode property escapes with v flag Expected SameValue(«-1», «0») to be true
|
||||
test262/test/built-ins/String/prototype/search/regexp-prototype-search-v-u-flag.js:9: strict mode: Test262Error: Unicode property escapes with v flag Expected SameValue(«-1», «0») to be true
|
||||
test262/test/built-ins/TypedArray/prototype/lastIndexOf/negative-index-and-resize-to-smaller.js:23: Test262Error: For index -1 Expected SameValue(«-1», «2») to be true (Testing with Float64Array.)
|
||||
test262/test/built-ins/TypedArray/prototype/lastIndexOf/negative-index-and-resize-to-smaller.js:23: strict mode: Test262Error: For index -1 Expected SameValue(«-1», «2») to be true (Testing with Float64Array.)
|
||||
test262/test/built-ins/TypedArray/prototype/slice/speciesctor-return-same-buffer-with-offset.js:24: Test262Error: Actual [20, 30, 40, 60] and expected [20, 20, 20, 60] should have the same contents. (Testing with Float64Array.)
|
||||
test262/test/built-ins/TypedArray/prototype/slice/speciesctor-return-same-buffer-with-offset.js:24: strict mode: Test262Error: Actual [20, 30, 40, 60] and expected [20, 20, 20, 60] should have the same contents. (Testing with Float64Array.)
|
||||
test262/test/built-ins/TypedArray/prototype/subarray/byteoffset-with-detached-buffer.js:44: RangeError: invalid offset (Testing with Float64Array.)
|
||||
test262/test/built-ins/TypedArray/prototype/subarray/byteoffset-with-detached-buffer.js:44: strict mode: RangeError: invalid offset (Testing with Float64Array.)
|
||||
test262/test/built-ins/TypedArray/prototype/with/negative-index-resize-to-in-bounds.js:22: Test262Error: Expected a RangeError to be thrown but no exception was thrown at all (Testing with Float64Array.)
|
||||
test262/test/built-ins/TypedArray/prototype/with/negative-index-resize-to-in-bounds.js:22: strict mode: Test262Error: Expected a RangeError to be thrown but no exception was thrown at all (Testing with Float64Array.)
|
||||
test262/test/built-ins/TypedArray/prototype/with/negative-index-resize-to-out-of-bounds.js:22: Test262Error: Expected a RangeError to be thrown but no exception was thrown at all (Testing with Float64Array.)
|
||||
test262/test/built-ins/TypedArray/prototype/with/negative-index-resize-to-out-of-bounds.js:22: strict mode: Test262Error: Expected a RangeError to be thrown but no exception was thrown at all (Testing with Float64Array.)
|
||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-canonical-invalid-index-prototype-chain-set.js:35: Test262Error: value should not be coerced Expected SameValue(«22», «0») to be true
|
||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-canonical-invalid-index-prototype-chain-set.js:35: strict mode: Test262Error: value should not be coerced Expected SameValue(«22», «0») to be true
|
||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-canonical-invalid-index-reflect-set.js:35: Test262Error: value should not be coerced Expected SameValue(«32», «0») to be true
|
||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-canonical-invalid-index-reflect-set.js:35: strict mode: Test262Error: value should not be coerced Expected SameValue(«32», «0») to be true
|
||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-canonical-invalid-index-prototype-chain-set.js:35: Test262Error: value should not be coerced Expected SameValue(«110», «0») to be true
|
||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-canonical-invalid-index-prototype-chain-set.js:35: strict mode: Test262Error: value should not be coerced Expected SameValue(«110», «0») to be true
|
||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-canonical-invalid-index-reflect-set.js:35: Test262Error: value should not be coerced Expected SameValue(«160», «0») to be true
|
||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-canonical-invalid-index-reflect-set.js:35: strict mode: Test262Error: value should not be coerced Expected SameValue(«160», «0») to be true
|
||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-out-of-bounds-receiver-is-not-object.js:19: Test262Error: valueOf is not called Expected SameValue(«1», «0») to be true
|
||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-out-of-bounds-receiver-is-not-object.js:19: strict mode: Test262Error: valueOf is not called Expected SameValue(«1», «0») to be true
|
||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-out-of-bounds-receiver-is-not-typed-array.js:19: Test262Error: valueOf is not called Expected SameValue(«1», «0») to be true
|
||||
test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-out-of-bounds-receiver-is-not-typed-array.js:19: strict mode: Test262Error: valueOf is not called Expected SameValue(«1», «0») to be true
|
||||
test262/test/language/destructuring/binding/keyed-destructuring-property-reference-target-evaluation-order-with-bindings.js:73: Test262Error: Actual [binding::source, binding::sourceKey, sourceKey, get source, binding::defaultValue, binding::varTarget] and expected [binding::source, binding::sourceKey, sourceKey, binding::varTarget, get source, binding::defaultValue] should have the same contents.
|
||||
test262/test/language/expressions/assignment/destructuring/iterator-destructuring-property-reference-target-evaluation-order.js:42: Test262Error: Actual [source, iterator, target, target-key, target-key-tostring, iterator-step, iterator-done, set] and expected [source, iterator, target, target-key, iterator-step, iterator-done, target-key-tostring, set] should have the same contents.
|
||||
test262/test/language/expressions/assignment/destructuring/iterator-destructuring-property-reference-target-evaluation-order.js:42: strict mode: Test262Error: Actual [source, iterator, target, target-key, target-key-tostring, iterator-step, iterator-done, set] and expected [source, iterator, target, target-key, iterator-step, iterator-done, target-key-tostring, set] should have the same contents.
|
||||
test262/test/language/expressions/assignment/destructuring/keyed-destructuring-property-reference-target-evaluation-order-with-bindings.js:37: Test262Error: Actual [binding::source, binding::sourceKey, sourceKey, binding::target, binding::targetKey, targetKey, get source, binding::defaultValue, set target] and expected [binding::source, binding::sourceKey, sourceKey, binding::target, binding::targetKey, get source, binding::defaultValue, targetKey, set target] should have the same contents.
|
||||
test262/test/language/expressions/assignment/destructuring/keyed-destructuring-property-reference-target-evaluation-order.js:32: Test262Error: Actual [source, source-key, source-key-tostring, target, target-key, target-key-tostring, get, set] and expected [source, source-key, source-key-tostring, target, target-key, get, target-key-tostring, set] should have the same contents.
|
||||
test262/test/language/expressions/assignment/destructuring/keyed-destructuring-property-reference-target-evaluation-order.js:32: strict mode: Test262Error: Actual [source, source-key, source-key-tostring, target, target-key, target-key-tostring, get, set] and expected [source, source-key, source-key-tostring, target, target-key, get, target-key-tostring, set] should have the same contents.
|
||||
test262/test/language/expressions/assignment/target-member-computed-reference.js:22: Test262Error: Expected a DummyError but got a Test262Error
|
||||
test262/test/language/expressions/assignment/target-member-computed-reference.js:22: strict mode: Test262Error: Expected a DummyError but got a Test262Error
|
||||
test262/test/language/expressions/assignment/target-super-computed-reference.js:20: Test262Error: Expected a DummyError but got a Test262Error
|
||||
test262/test/language/expressions/assignment/target-super-computed-reference.js:20: strict mode: Test262Error: Expected a DummyError but got a Test262Error
|
||||
test262/test/language/expressions/in/private-field-invalid-assignment-target.js:23: unexpected error type: Test262: This statement should not be evaluated.
|
||||
test262/test/language/expressions/in/private-field-invalid-assignment-target.js:23: strict mode: unexpected error type: Test262: This statement should not be evaluated.
|
||||
test262/test/language/expressions/object/computed-property-name-topropertykey-before-value-evaluation.js:31: Test262Error: Expected SameValue(«"bad"», «"ok"») to be true
|
||||
test262/test/language/expressions/object/computed-property-name-topropertykey-before-value-evaluation.js:31: strict mode: Test262Error: Expected SameValue(«"bad"», «"ok"») to be true
|
||||
test262/test/language/module-code/ambiguous-export-bindings/import-and-export-propagates-binding.js:75: SyntaxError: export 'foo' in module 'test262/test/language/module-code/ambiguous-export-bindings/imp' is ambiguous
|
||||
test262/test/language/module-code/ambiguous-export-bindings/namespace-unambiguous-if-export-star-as-from-and-import-star-as-and-export.js:74: SyntaxError: export 'foo' in module 'test262/test/language/module-code/ambiguous-export-bindings/nam' is ambiguous
|
||||
test262/test/language/module-code/ambiguous-export-bindings/namespace-unambiguous-if-export-star-as-from.js:75: SyntaxError: export 'foo' in module 'test262/test/language/module-code/ambiguous-export-bindings/nam' is ambiguous
|
||||
test262/test/language/module-code/ambiguous-export-bindings/namespace-unambiguous-if-import-star-as-and-export.js:74: SyntaxError: export 'foo' in module 'test262/test/language/module-code/ambiguous-export-bindings/nam' is ambiguous
|
||||
test262/test/language/module-code/top-level-await/module-graphs-does-not-hang.js:10: TypeError: $DONE() not called
|
||||
test262/test/language/module-code/top-level-await/rejection-order.js:20: TypeError: $DONE() not called
|
||||
test262/test/language/statements/class/elements/syntax/valid/grammar-field-named-get-followed-by-generator-asi.js:40: SyntaxError: invalid property name
|
||||
test262/test/language/statements/class/elements/syntax/valid/grammar-field-named-get-followed-by-generator-asi.js:40: strict mode: SyntaxError: invalid property name
|
||||
test262/test/language/statements/class/elements/syntax/valid/grammar-field-named-set-followed-by-generator-asi.js:40: SyntaxError: invalid property name
|
||||
test262/test/language/statements/class/elements/syntax/valid/grammar-field-named-set-followed-by-generator-asi.js:40: strict mode: SyntaxError: invalid property name
|
||||
test262/test/language/statements/with/get-binding-value-call-with-proxy-env.js:39: Test262Error: Actual [has:Object, get:Symbol(Symbol.unscopables), get:Object] and expected [has:Object, get:Symbol(Symbol.unscopables), has:Object, get:Object] should have the same contents.
|
||||
test262/test/language/statements/with/get-binding-value-idref-with-proxy-env.js:39: Test262Error: Actual [has:Object, get:Symbol(Symbol.unscopables), get:Object] and expected [has:Object, get:Symbol(Symbol.unscopables), has:Object, get:Object] should have the same contents.
|
||||
test262/test/language/statements/with/get-mutable-binding-binding-deleted-in-get-unscopables-strict-mode.js:21: Test262Error: Expected a ReferenceError to be thrown but no exception was thrown at all
|
||||
test262/test/language/statements/with/set-mutable-binding-binding-deleted-with-typed-array-in-proto-chain.js:20: Test262Error: Expected SameValue(«[object Object]», «undefined») to be true
|
||||
test262/test/language/statements/with/set-mutable-binding-idref-compound-assign-with-proxy-env.js:58: Test262Error: Actual [has:p, get:Symbol(Symbol.unscopables), get:p, set:p, getOwnPropertyDescriptor:p, defineProperty:p] and expected [has:p, get:Symbol(Symbol.unscopables), has:p, get:p, has:p, set:p, getOwnPropertyDescriptor:p, defineProperty:p] should have the same contents.
|
||||
test262/test/language/statements/with/set-mutable-binding-idref-with-proxy-env.js:50: Test262Error: Actual [has:p, get:Symbol(Symbol.unscopables), set:p, getOwnPropertyDescriptor:p, defineProperty:p] and expected [has:p, get:Symbol(Symbol.unscopables), has:p, set:p, getOwnPropertyDescriptor:p, defineProperty:p] should have the same contents.
|
||||
@@ -0,0 +1,11 @@
|
||||
[config]
|
||||
local=yes
|
||||
verbose=yes
|
||||
testdir=tests
|
||||
|
||||
[exclude]
|
||||
tests/empty.js
|
||||
tests/fixture_cyclic_import.js
|
||||
tests/microbench.js
|
||||
tests/test_worker_module.js
|
||||
tests/fixture_string_exports.js
|
||||
@@ -0,0 +1,49 @@
|
||||
export function assert(actual, expected, message) {
|
||||
if (arguments.length === 1)
|
||||
expected = true;
|
||||
|
||||
if (typeof actual === typeof expected) {
|
||||
if (actual === expected) {
|
||||
if (actual !== 0 || (1 / actual) === (1 / expected))
|
||||
return;
|
||||
}
|
||||
if (typeof actual === 'number') {
|
||||
if (isNaN(actual) && isNaN(expected))
|
||||
return;
|
||||
}
|
||||
if (typeof actual === 'object') {
|
||||
if (actual !== null && expected !== null
|
||||
&& actual.constructor === expected.constructor
|
||||
&& actual.toString() === expected.toString())
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw Error("assertion failed: got |" + actual + "|" +
|
||||
", expected |" + expected + "|" +
|
||||
(message ? " (" + message + ")" : ""));
|
||||
}
|
||||
|
||||
export function assertThrows(err, func)
|
||||
{
|
||||
var ex;
|
||||
ex = false;
|
||||
try {
|
||||
func();
|
||||
} catch(e) {
|
||||
ex = true;
|
||||
assert(e instanceof err);
|
||||
}
|
||||
assert(ex, true, "exception expected");
|
||||
}
|
||||
|
||||
export function assertArrayEquals(a, b)
|
||||
{
|
||||
if (!Array.isArray(a) || !Array.isArray(b))
|
||||
return assert(false);
|
||||
|
||||
assert(a.length, b.length);
|
||||
|
||||
a.forEach((value, idx) => {
|
||||
assert(b[idx], value);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import {assert} from "./assert.js"
|
||||
|
||||
let caught = 0
|
||||
for (let i = 1; i <= 32; i++) {
|
||||
const prefix = "(:?".repeat(i)
|
||||
const suffix = "|)+".repeat(i)
|
||||
const between = "(?:a|)+"
|
||||
try {
|
||||
new RegExp(prefix + between + suffix)
|
||||
} catch (e) {
|
||||
assert(e instanceof SyntaxError)
|
||||
assert(e.message, "out of memory")
|
||||
caught++
|
||||
}
|
||||
}
|
||||
assert(caught, 12) // subject to change
|
||||
@@ -0,0 +1,6 @@
|
||||
/*---
|
||||
flags: [qjs:track-promise-rejections]
|
||||
---*/
|
||||
|
||||
Promise.reject().catch(() => print('oops'))
|
||||
Promise.resolve().then(() => print('ok'))
|
||||
@@ -0,0 +1,6 @@
|
||||
/*---
|
||||
flags: [qjs:track-promise-rejections]
|
||||
---*/
|
||||
|
||||
const error = await Promise.resolve().then(() => Promise.reject('reject')).catch(e => e)
|
||||
print('Got this error:', error)
|
||||
@@ -0,0 +1,7 @@
|
||||
/*---
|
||||
flags: [qjs:track-promise-rejections]
|
||||
---*/
|
||||
|
||||
const promise = Promise.reject('reject')
|
||||
const error = await Promise.resolve().then(() => promise).catch(e => e)
|
||||
print('Got this error:', error)
|
||||
@@ -0,0 +1,7 @@
|
||||
/*---
|
||||
flags: [qjs:no-detect-module]
|
||||
negative:
|
||||
phase: parse
|
||||
type: SyntaxError
|
||||
---*/
|
||||
const undefined = 42 // SyntaxError at global scope
|
||||
@@ -0,0 +1,4 @@
|
||||
/*---
|
||||
flags: [qjs:no-detect-module, module]
|
||||
---*/
|
||||
const undefined = 42 // not a SyntaxError at toplevel module scope
|
||||
@@ -0,0 +1,4 @@
|
||||
/*---
|
||||
flags: [qjs:no-detect-module]
|
||||
---*/
|
||||
{ const undefined = 42 } // not a SyntaxError, not at global scope
|
||||
@@ -0,0 +1,4 @@
|
||||
/*---
|
||||
flags: [qjs:no-detect-module]
|
||||
---*/
|
||||
;(function() { const undefined = 42 })() // not a SyntaxError, not at global scope
|
||||
@@ -0,0 +1,4 @@
|
||||
"use strict";
|
||||
|
||||
const u8 = new Uint8Array(1);
|
||||
u8[100] = 123; // Should not throw.
|
||||
@@ -0,0 +1,9 @@
|
||||
import { assert, assertThrows } from "../assert.js";
|
||||
const ab = new ArrayBuffer(1);
|
||||
const u8 = new Uint8Array(ab);
|
||||
assert(!ab.detached);
|
||||
// Detach the ArrayBuffer.
|
||||
ab.transfer();
|
||||
assert(ab.detached);
|
||||
u8[100] = 123; // Doesn't throw.
|
||||
assertThrows(TypeError, () => Object.defineProperty(u8, "100", { value: 123 }));
|
||||
@@ -0,0 +1,7 @@
|
||||
import { assert, assertThrows } from "../assert.js";
|
||||
const ab = new ArrayBuffer(16, { maxByteLength: 32 });
|
||||
const u8 = new Uint8Array(ab, 16);
|
||||
ab.resize(8);
|
||||
assert(ab.byteLength, 8);
|
||||
u8[1] = 123; // Doesn't throw.
|
||||
assertThrows(TypeError, () => Object.defineProperty(u8, "1", { value: 123 }));
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user