From 171be516572928ce5d2b46c43e394ea872e5bf7a Mon Sep 17 00:00:00 2001 From: buke <1013738+buke@users.noreply.github.com> Date: Sat, 1 Aug 2026 03:27:50 +0000 Subject: [PATCH] chore: sync quickjs-ng release v0.16.0 --- deps/quickjs-release.env | 8 +- deps/quickjs/.github/workflows/ci.yml | 83 +- deps/quickjs/.github/workflows/docs.yml | 4 +- deps/quickjs/.github/workflows/gc-stress.yml | 61 + deps/quickjs/.github/workflows/release.yml | 48 +- deps/quickjs/.github/workflows/test-docs.yml | 4 +- deps/quickjs/.github/workflows/tsan.yml | 2 +- deps/quickjs/.github/workflows/valgrind.yml | 2 +- deps/quickjs/CMakeLists.txt | 8 + deps/quickjs/api-test.c | 702 ++++ deps/quickjs/builtin-array-fromasync.h | 73 +- deps/quickjs/builtin-array-fromasync.js | 4 +- deps/quickjs/builtin-iterator-zip-keyed.h | 2 +- deps/quickjs/builtin-iterator-zip.h | 2 +- deps/quickjs/cutils.h | 1 + deps/quickjs/docs/docs/projects.md | 11 +- deps/quickjs/gc-stress-skip.txt | 3 + deps/quickjs/gen/function_source.c | 15 +- deps/quickjs/gen/hello.c | 2 +- deps/quickjs/gen/hello_module.c | 53 +- deps/quickjs/gen/repl.c | 3418 ++++++++--------- deps/quickjs/gen/standalone.c | 2 +- deps/quickjs/gen/test_fib.c | 12 +- deps/quickjs/libregexp-opcode.h | 37 +- deps/quickjs/libregexp.c | 2385 ++++++++---- deps/quickjs/libregexp.h | 7 +- deps/quickjs/libunicode-table.h | 466 +++ deps/quickjs/libunicode.c | 339 +- deps/quickjs/libunicode.h | 50 +- deps/quickjs/lre-test.c | 68 +- deps/quickjs/meson.build | 4 +- deps/quickjs/qjs.c | 48 +- deps/quickjs/qjs.man | 90 + deps/quickjs/qjsc.man | 78 + deps/quickjs/quickjs-libc.c | 25 +- deps/quickjs/quickjs.c | 2858 ++++++++++---- deps/quickjs/quickjs.h | 60 +- deps/quickjs/run-test262.c | 2 +- deps/quickjs/test262.conf | 151 +- deps/quickjs/test262_errors.txt | 50 +- deps/quickjs/tests.conf | 4 + .../tests/array-fromasync-enumerable.js | 23 + deps/quickjs/tests/atomics-store-leak.js | 36 + deps/quickjs/tests/bug1221.js | 16 - deps/quickjs/tests/bug1552.js | 87 + deps/quickjs/tests/bug1557.js | 55 + deps/quickjs/tests/bug1562.js | 65 + deps/quickjs/tests/bug1564.js | 5 + deps/quickjs/tests/bug1565.js | 16 + deps/quickjs/tests/bug1571.js | 13 + deps/quickjs/tests/bug1572.js | 18 + deps/quickjs/tests/bug1591.js | 26 + deps/quickjs/tests/bug567.js | 5 + deps/quickjs/tests/callsite-isconstructor.js | 30 + .../quickjs/tests/callsite-native-position.js | 19 + deps/quickjs/tests/destructured-export.js | 14 +- .../tests/dynamic_import_rejection_handled.js | 7 + deps/quickjs/tests/fixture_cyclic_import.js | 2 +- .../tests/fixture_import_attributes.json | 1 + deps/quickjs/tests/fixture_reexport_direct.js | 1 + .../quickjs/tests/fixture_reexport_missing.js | 1 + deps/quickjs/tests/fixture_reexport_source.js | 1 + deps/quickjs/tests/fixture_throwing_module.js | 1 + deps/quickjs/tests/for-await-normal-close.js | 50 + deps/quickjs/tests/global-reference-column.js | 19 + .../tests/import-attributes-identity.js | 35 + deps/quickjs/tests/iterator-filter-leak.js | 21 + .../tests/iterator-tostringtag-setter.js | 44 + deps/quickjs/tests/parse-error-column.js | 26 + deps/quickjs/tests/reexport-error-module.js | 14 + .../tests/suspended-coroutine-closure-gc.js | 35 + ...suspended-coroutine-mapped-arguments-gc.js | 28 + .../tests/suspended-generator-closure-gc.js | 33 + deps/quickjs/tests/test_bigint.js | 30 + deps/quickjs/tests/test_bjson.js | 10 +- deps/quickjs/tests/test_builtin.js | 51 +- deps/quickjs/tests/test_cyclic_import.js | 12 - .../tests/typedarray-lastindexof-shrink.js | 73 + .../tests/typedarray-set-invalid-index.js | 50 + .../quickjs/tests/typedarray-slice-overlap.js | 48 + .../tests/typedarray-subarray-species.js | 82 + deps/quickjs/unicode_download.sh | 5 +- deps/quickjs/unicode_gen.c | 17 +- 83 files changed, 8740 insertions(+), 3627 deletions(-) create mode 100644 deps/quickjs/.github/workflows/gc-stress.yml create mode 100644 deps/quickjs/gc-stress-skip.txt create mode 100644 deps/quickjs/qjs.man create mode 100644 deps/quickjs/qjsc.man create mode 100644 deps/quickjs/tests/array-fromasync-enumerable.js create mode 100644 deps/quickjs/tests/atomics-store-leak.js delete mode 100644 deps/quickjs/tests/bug1221.js create mode 100644 deps/quickjs/tests/bug1552.js create mode 100644 deps/quickjs/tests/bug1557.js create mode 100644 deps/quickjs/tests/bug1562.js create mode 100644 deps/quickjs/tests/bug1564.js create mode 100644 deps/quickjs/tests/bug1565.js create mode 100644 deps/quickjs/tests/bug1571.js create mode 100644 deps/quickjs/tests/bug1572.js create mode 100644 deps/quickjs/tests/bug1591.js create mode 100644 deps/quickjs/tests/bug567.js create mode 100644 deps/quickjs/tests/callsite-isconstructor.js create mode 100644 deps/quickjs/tests/callsite-native-position.js create mode 100644 deps/quickjs/tests/dynamic_import_rejection_handled.js create mode 100644 deps/quickjs/tests/fixture_import_attributes.json create mode 100644 deps/quickjs/tests/fixture_reexport_direct.js create mode 100644 deps/quickjs/tests/fixture_reexport_missing.js create mode 100644 deps/quickjs/tests/fixture_reexport_source.js create mode 100644 deps/quickjs/tests/fixture_throwing_module.js create mode 100644 deps/quickjs/tests/for-await-normal-close.js create mode 100644 deps/quickjs/tests/global-reference-column.js create mode 100644 deps/quickjs/tests/import-attributes-identity.js create mode 100644 deps/quickjs/tests/iterator-filter-leak.js create mode 100644 deps/quickjs/tests/iterator-tostringtag-setter.js create mode 100644 deps/quickjs/tests/parse-error-column.js create mode 100644 deps/quickjs/tests/reexport-error-module.js create mode 100644 deps/quickjs/tests/suspended-coroutine-closure-gc.js create mode 100644 deps/quickjs/tests/suspended-coroutine-mapped-arguments-gc.js create mode 100644 deps/quickjs/tests/suspended-generator-closure-gc.js delete mode 100644 deps/quickjs/tests/test_cyclic_import.js create mode 100644 deps/quickjs/tests/typedarray-lastindexof-shrink.js create mode 100644 deps/quickjs/tests/typedarray-set-invalid-index.js create mode 100644 deps/quickjs/tests/typedarray-slice-overlap.js create mode 100644 deps/quickjs/tests/typedarray-subarray-species.js diff --git a/deps/quickjs-release.env b/deps/quickjs-release.env index 1bbeed4..33f4366 100644 --- a/deps/quickjs-release.env +++ b/deps/quickjs-release.env @@ -1,5 +1,5 @@ QUICKJS_NG_REPO="quickjs-ng/quickjs" -QUICKJS_NG_TAG="v0.15.1" -QUICKJS_NG_TARBALL_URL="https://api.github.com/repos/quickjs-ng/quickjs/tarball/v0.15.1" -QUICKJS_NG_RELEASE_URL="https://github.com/quickjs-ng/quickjs/releases/tag/v0.15.1" -QUICKJS_NG_RELEASED_AT="2026-06-04T14:57:07Z" +QUICKJS_NG_TAG="v0.16.0" +QUICKJS_NG_TARBALL_URL="https://api.github.com/repos/quickjs-ng/quickjs/tarball/v0.16.0" +QUICKJS_NG_RELEASE_URL="https://github.com/quickjs-ng/quickjs/releases/tag/v0.16.0" +QUICKJS_NG_RELEASED_AT="2026-07-31T13:24:42Z" diff --git a/deps/quickjs/.github/workflows/ci.yml b/deps/quickjs/.github/workflows/ci.yml index e58c8c4..c22bf73 100644 --- a/deps/quickjs/.github/workflows/ci.yml +++ b/deps/quickjs/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: codegen: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: build run: | make codegen @@ -67,7 +67,7 @@ jobs: - { os: macos-14, configType: shared } - { os: macos-14, configType: asan+ubsan, runTest262: true } steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: submodules: true @@ -178,17 +178,17 @@ jobs: 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 } + - { arch: x64, vsArch: x64, buildType: Debug, os: windows-latest, msvc: 18 } + - { arch: x64, vsArch: x64, buildType: Release, os: windows-latest, msvc: 18 } + - { arch: Win32, vsArch: x86, buildType: Debug, os: windows-latest, msvc: 18 } + - { arch: Win32, vsArch: x86, buildType: Release, os: windows-latest, msvc: 18 } + - { arch: ARM64, vsArch: arm64, buildType: Debug, os: windows-11-arm, msvc: 17 } + - { arch: ARM64, vsArch: arm64, buildType: Release, os: windows-11-arm, msvc: 17 } steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: build run: | - cmake -B build -DQJS_BUILD_WERROR=ON -DQJS_BUILD_EXAMPLES=ON -G "Visual Studio 17 2022" -A ${{matrix.config.arch}} + cmake -B build -DQJS_BUILD_WERROR=ON -DQJS_BUILD_EXAMPLES=ON -G "Visual Studio ${{matrix.config.msvc}}" -A ${{matrix.config.arch}} cmake --build build --config ${{matrix.config.buildType}} - name: stats run: | @@ -227,7 +227,7 @@ jobs: matrix: buildType: [Debug, Release] steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: install ninja run: | choco install ninja @@ -260,11 +260,11 @@ jobs: matrix: buildType: [Debug, Release] steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: build run: | git submodule update --init --checkout --depth 1 - cmake -B build -DQJS_BUILD_WERROR=ON -DQJS_BUILD_EXAMPLES=ON -G "Visual Studio 17 2022" -T ClangCL + cmake -B build -DQJS_BUILD_WERROR=ON -DQJS_BUILD_EXAMPLES=ON -G "Visual Studio 18" -T ClangCL cmake --build build --config ${{matrix.buildType}} - name: stats run: | @@ -295,7 +295,7 @@ jobs: matrix: buildType: [Debug, Release] steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: install ninja run: | choco install ninja @@ -331,7 +331,7 @@ jobs: arch: [x64, Win32] buildType: [Debug, Release] steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Install windows sdk uses: ChristopheLav/windows-sdk-install@v1 with: @@ -374,7 +374,7 @@ jobs: run: shell: msys2 {0} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Setup MSYS2 uses: msys2/setup-msys2@v2 with: @@ -421,7 +421,7 @@ jobs: run: shell: msys2 {0} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Setup MSYS2 uses: msys2/setup-msys2@v2 with: @@ -443,7 +443,7 @@ jobs: emscripten: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - uses: mymindstorm/setup-emsdk@v16 - name: check emsdk run: emcc -v @@ -456,7 +456,7 @@ jobs: wasi: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - uses: jcbhmr/setup-wasmtime@v2 - name: setup wasi-sdk run: | @@ -489,7 +489,7 @@ jobs: with: packages: make cmake gcc-g++ bash - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: build run: make @@ -515,7 +515,7 @@ jobs: openbsd: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: build + test uses: vmactions/openbsd-vm@v1 with: @@ -529,7 +529,7 @@ jobs: freebsd: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: build + test uses: vmactions/freebsd-vm@v1 with: @@ -544,7 +544,7 @@ jobs: runs-on: ubuntu-latest container: reactnativecommunity/react-native-android:v13.0 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Configure android arm64 # see build options you can use in https://developer.android.com/ndk/guides/cmake run: | @@ -559,7 +559,7 @@ jobs: ios: runs-on: macos-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: configure run: | cmake -B build -GXcode -DQJS_BUILD_WERROR=ON -DCMAKE_SYSTEM_NAME:STRING=iOS -DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED:BOOL=NO -DQJS_BUILD_LIBC=ON @@ -574,7 +574,7 @@ jobs: QJS_BUILD_CLI_WITH_MIMALLOC: ON MIMALLOC_SHOW_STATS: 1 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: install dependencies run: | sudo apt update && sudo apt -y install libmimalloc-dev @@ -594,7 +594,7 @@ jobs: QJS_BUILD_CLI_WITH_STATIC_MIMALLOC: ON MIMALLOC_SHOW_STATS: 1 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: install dependencies run: | brew install mimalloc @@ -617,7 +617,7 @@ jobs: - { os: macos-latest } runs-on: ${{ matrix.config.os }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: build run: | make @@ -637,7 +637,7 @@ jobs: jscheck: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: jscheck run: | make jscheck @@ -645,7 +645,7 @@ jobs: parserless: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: build run: | make QJS_DISABLE_PARSER=ON QJS_BUILD_EXAMPLES=ON @@ -717,13 +717,20 @@ jobs: # default clang on GitHub hosted runners is from MSYS2. # Use Visual Studio supplied clang-cl instead. + # clang-cl's AddressSanitizer does not support the debug CRT (/MDd), + # so force the release CRT (/MD) for both debug and release builds. - name: clang-cl+sanitize args: >- "-Db_sanitize=address,undefined" "-Db_lundef=false" + "-Db_vscrt=md" extra_envs: CC: clang-cl CXX: clang-cl + # clang-cl's AddressSanitizer reports false positive + # global-buffer-overflows on pooled string literals on Windows, + # same as MSVC; disable global checks (covered on Linux). + ASAN_OPTIONS: report_globals=0:halt_on_error=1:abort_on_error=1:print_summary=1 platform: - ubuntu-latest - windows-latest @@ -817,12 +824,26 @@ jobs: # ... good job, microsoft :)))) - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@v7 - 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 + $extraArgs = @() + if ($env:CC -eq 'clang-cl') { + # Newer clang-cl no longer emits the asan runtime /defaultlib directives + # when -fsanitize is passed through /clang:, and meson links with lld-link + # directly (not the clang driver), so the asan/ubsan runtime is never pulled + # in. Link it explicitly and make its directory discoverable at link and run + # time (the dynamic runtime ships as a DLL). + $runtimeDir = (clang -print-runtime-dir).Trim() + $env:LIB = "$runtimeDir;$env:LIB" + "LIB=$env:LIB" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 + $runtimeDir | Out-File -FilePath $env:GITHUB_PATH -Append -Encoding utf8 + $libs = "clang_rt.asan_dynamic-x86_64.lib clang_rt.asan_dynamic_runtime_thunk-x86_64.lib" + $extraArgs = @("-Dc_link_args=$libs", "-Dcpp_link_args=$libs") + } + meson setup build-${{ matrix.flavor }} --buildtype=${{ matrix.flavor }} ${{ matrix.mode.args }} ${{ matrix.features.args }} --vsenv @extraArgs - name: Configuring if: ${{ matrix.platform != 'windows-latest' }} env: ${{ matrix.mode.extra_envs }} diff --git a/deps/quickjs/.github/workflows/docs.yml b/deps/quickjs/.github/workflows/docs.yml index cc3c2f3..b5e0f89 100644 --- a/deps/quickjs/.github/workflows/docs.yml +++ b/deps/quickjs/.github/workflows/docs.yml @@ -13,8 +13,8 @@ jobs: name: Build Docusaurus runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 - - uses: actions/setup-node@v6 + - uses: actions/checkout@v7 + - uses: actions/setup-node@v7 with: node-version-file: 'docs/.nvmrc' - name: Install dependencies diff --git a/deps/quickjs/.github/workflows/gc-stress.yml b/deps/quickjs/.github/workflows/gc-stress.yml new file mode 100644 index 0000000..e64a883 --- /dev/null +++ b/deps/quickjs/.github/workflows/gc-stress.yml @@ -0,0 +1,61 @@ +name: gc-stress + +on: + pull_request: + paths: + - '**' + - '!.gitignore' + - '!LICENSE' + - '!README.md' + - '!docs/**' + - '!examples/**' + - '.github/workflows/gc-stress.yml' + push: + branches: + - master + paths: + - '**' + - '!.gitignore' + - '!LICENSE' + - '!README.md' + - '!docs/**' + - '!examples/**' + - '.github/workflows/gc-stress.yml' + +jobs: + gc-stress: + runs-on: ${{ matrix.os }} + name: ${{ matrix.os }} + timeout-minutes: 30 + defaults: + run: + shell: ${{ matrix.os == 'windows-latest' && 'msys2 {0}' || 'bash' }} + env: + ASAN_OPTIONS: halt_on_error=1:detect_leaks=0 + strategy: + fail-fast: false + matrix: + include: + - { os: ubuntu-latest, asan: 'ON' } + - { os: macos-latest, asan: 'ON' } + - { os: windows-latest, asan: 'OFF' } + steps: + - uses: actions/checkout@v7 + - name: Setup MSYS2 + if: matrix.os == 'windows-latest' + uses: msys2/setup-msys2@v2 + with: + install: >- + git + make + pacboy: >- + cmake:p + ninja:p + toolchain:p + - name: build & test + run: >- + make test + BUILD_TYPE=RelWithDebInfo + QJS_ENABLE_GC_STRESS=ON + QJS_ENABLE_ASAN=${{ matrix.asan }} + RUN262='build/run-test262 -x gc-stress-skip.txt' diff --git a/deps/quickjs/.github/workflows/release.yml b/deps/quickjs/.github/workflows/release.yml index 00c7f95..aef241e 100644 --- a/deps/quickjs/.github/workflows/release.yml +++ b/deps/quickjs/.github/workflows/release.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-22.04 if: ${{ startsWith(github.ref, 'refs/tags/v') }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: install meson and ninja run: | pip install --upgrade meson ninja @@ -27,17 +27,22 @@ jobs: matrix: arch: [aarch64, armv7, riscv64, x86, x86_64] steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - uses: jirutka/setup-alpine@v1 with: + # mimalloc v3 (mimalloc3-dev) lives in the edge testing repo; enable it. + # riscv64 has no v3 build there, so it falls back to mimalloc2-dev. + branch: edge arch: ${{matrix.arch}} - packages: "build-base make cmake" + extra-repositories: | + http://dl-cdn.alpinelinux.org/alpine/edge/testing + packages: "build-base make cmake ${{ matrix.arch == 'riscv64' && 'mimalloc2-dev' || 'mimalloc3-dev' }}" - name: build shell: alpine.sh {0} run: | mkdir build cd build - cmake -DQJS_BUILD_WERROR=ON -DQJS_BUILD_CLI_STATIC=ON .. + cmake -DQJS_BUILD_WERROR=ON -DQJS_BUILD_CLI_STATIC=ON -DQJS_BUILD_CLI_WITH_STATIC_MIMALLOC=ON .. cd .. cmake --build build --target qjs_exe -j$(getconf _NPROCESSORS_ONLN) cmake --build build --target qjsc -j$(getconf _NPROCESSORS_ONLN) @@ -55,21 +60,33 @@ jobs: macos: runs-on: macos-latest + strategy: + fail-fast: false + matrix: + arch: [arm64, x86_64] steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 + - name: install mimalloc + if: ${{ matrix.arch == 'arm64' }} + run: brew install mimalloc - name: build run: | mkdir build cd build - cmake -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -DQJS_BUILD_WERROR=ON .. + cmake -DCMAKE_OSX_ARCHITECTURES=${{matrix.arch}} -DQJS_BUILD_WERROR=ON ${{ matrix.arch == 'arm64' && '-DQJS_BUILD_CLI_WITH_STATIC_MIMALLOC=ON -DCMAKE_PREFIX_PATH=/opt/homebrew' || '' }} .. make -j$(getconf _NPROCESSORS_ONLN) - make -C .. amalgam # writes build/quickjs-amalgam.zip - mv qjs qjs-darwin - mv qjsc qjsc-darwin + - name: build amalgamation + if: ${{ matrix.arch == 'arm64' }} + run: make amalgam # writes build/quickjs-amalgam.zip; runs qjs natively on arm64 + - name: rename + run: | + mv build/qjs build/qjs-darwin-${{matrix.arch}} + mv build/qjsc build/qjsc-darwin-${{matrix.arch}} - name: check run: | - lipo -info build/qjs-darwin build/qjsc-darwin + lipo -info build/qjs-darwin-${{matrix.arch}} build/qjsc-darwin-${{matrix.arch}} - name: upload amalgamation + if: ${{ matrix.arch == 'arm64' }} uses: actions/upload-artifact@v7 with: name: quickjs-amalgam.zip @@ -78,8 +95,8 @@ jobs: - name: upload uses: actions/upload-artifact@v7 with: - name: qjs-darwin - path: build/*-darwin + name: qjs-darwin-${{matrix.arch}} + path: build/*-darwin-${{matrix.arch}} windows: runs-on: windows-latest @@ -91,7 +108,7 @@ jobs: run: shell: msys2 {0} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: Setup MSYS2 uses: msys2/setup-msys2@v2 with: @@ -103,7 +120,10 @@ jobs: cmake:p ninja:p toolchain:p + ${{ matrix.arch == 'x86_64' && 'mimalloc:p' || '' }} - name: build + env: + QJS_BUILD_CLI_WITH_STATIC_MIMALLOC: ${{ matrix.arch == 'x86_64' && 'ON' || 'OFF' }} run: | make mv build/qjs.exe build/qjs-windows-${{matrix.arch}}.exe @@ -121,7 +141,7 @@ jobs: wasi: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 - name: setup wasi-sdk run: | wget -nv https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-29/wasi-sdk-29.0-x86_64-linux.deb -P /tmp diff --git a/deps/quickjs/.github/workflows/test-docs.yml b/deps/quickjs/.github/workflows/test-docs.yml index 9572d20..93784d5 100644 --- a/deps/quickjs/.github/workflows/test-docs.yml +++ b/deps/quickjs/.github/workflows/test-docs.yml @@ -11,8 +11,8 @@ jobs: name: Test Docusaurus build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 - - uses: actions/setup-node@v6 + - uses: actions/checkout@v7 + - uses: actions/setup-node@v7 with: node-version-file: 'docs/.nvmrc' - name: Install dependencies diff --git a/deps/quickjs/.github/workflows/tsan.yml b/deps/quickjs/.github/workflows/tsan.yml index 54125c0..57f6e78 100644 --- a/deps/quickjs/.github/workflows/tsan.yml +++ b/deps/quickjs/.github/workflows/tsan.yml @@ -19,7 +19,7 @@ jobs: linux: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: submodules: true - name: build diff --git a/deps/quickjs/.github/workflows/valgrind.yml b/deps/quickjs/.github/workflows/valgrind.yml index c135639..b29b085 100644 --- a/deps/quickjs/.github/workflows/valgrind.yml +++ b/deps/quickjs/.github/workflows/valgrind.yml @@ -19,7 +19,7 @@ jobs: linux: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@v7 with: submodules: true - name: install valgrind diff --git a/deps/quickjs/CMakeLists.txt b/deps/quickjs/CMakeLists.txt index 4b4bf8e..a76caf1 100644 --- a/deps/quickjs/CMakeLists.txt +++ b/deps/quickjs/CMakeLists.txt @@ -40,6 +40,7 @@ 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) +xoption(QJS_ENABLE_GC_STRESS "Force a full GC before every allocation (GC stress test)" OFF) # Used to properly define JS_LIBC_EXTERN. add_compile_definitions(QUICKJS_NG_BUILD) @@ -244,6 +245,11 @@ add_link_options( ) endif() +if(QJS_ENABLE_GC_STRESS) +message(STATUS "Building with GC stress (FORCE_GC_AT_MALLOC)") +add_compile_definitions(FORCE_GC_AT_MALLOC) +endif() + # QuickJS library # @@ -555,6 +561,8 @@ if (QJS_ENABLE_INSTALL) 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}) + install(FILES qjs.man DESTINATION ${CMAKE_INSTALL_DATADIR}/man/man1/qjs.1) + install(FILES qjsc.man DESTINATION ${CMAKE_INSTALL_DATADIR}/man/man1/qjsc.1) endif() install(TARGETS qjs EXPORT qjsConfig RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} diff --git a/deps/quickjs/api-test.c b/deps/quickjs/api-test.c index a45dfb3..ef38a7f 100644 --- a/deps/quickjs/api-test.c +++ b/deps/quickjs/api-test.c @@ -391,6 +391,158 @@ static void module_serde(void) JS_FreeRuntime(rt); } +struct rejection_counts { + int reject_count; + int handle_count; +}; + +static void rejection_counter(JSContext *ctx, JSValueConst promise, + JSValueConst reason, bool is_handled, void *opaque) +{ + struct rejection_counts *c = opaque; + if (is_handled) + c->handle_count++; + else + c->reject_count++; +} + +// A synchronous module that throws at top level must surface exactly one unhandled rejection +static void module_unhandled_rejection(void) +{ + struct rejection_counts c = {0, 0}; + JSRuntime *rt = new_runtime(); + JS_SetHostPromiseRejectionTracker(rt, rejection_counter, &c); + JSContext *ctx = JS_NewContext(rt); + + static const char code[] = "throw new Error('Nuke the entire site from orbit. It\\'s the only way to be sure.')"; + JSValue v = JS_Eval(ctx, code, strlen(code), "", JS_EVAL_TYPE_MODULE); + JS_FreeValue(ctx, v); + + JSContext *c1; + while (JS_ExecutePendingJob(rt, &c1) > 0) + ; + + // net unhandled rejections == (2 rejects - 1 handled) + assert(c.reject_count == 2); + assert(c.handle_count == 1); + + JS_FreeContext(ctx); + JS_FreeRuntime(rt); +} + +static void promise_mark_as_handled(void) +{ + struct rejection_counts c = {0, 0}; + JSRuntime *rt = new_runtime(); + JS_SetHostPromiseRejectionTracker(rt, rejection_counter, &c); + JSContext *ctx = JS_NewContext(rt); + JSContext *c1; + + // marking an already-rejected promise notifies the tracker exactly once + static const char code[] = "Promise.reject('kaboom')"; + JSValue promise = JS_Eval(ctx, code, strlen(code), "", JS_EVAL_TYPE_GLOBAL); + assert(JS_IsPromise(promise)); + while (JS_ExecutePendingJob(rt, &c1) > 0) + ; + assert(c.reject_count == 1); + assert(c.handle_count == 0); + JS_PromiseMarkAsHandled(ctx, promise); + assert(c.handle_count == 1); + JS_PromiseMarkAsHandled(ctx, promise); + assert(c.handle_count == 1); + JS_FreeValue(ctx, promise); + + // marking a pending promise suppresses the report when it later rejects + JSValue resolving_funcs[2]; + JSValue promise2 = JS_NewPromiseCapability(ctx, resolving_funcs); + JS_PromiseMarkAsHandled(ctx, promise2); + JSValue reason = JS_NewString(ctx, "unseen"); + JSValue ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, 1, + (JSValueConst *)&reason); + while (JS_ExecutePendingJob(rt, &c1) > 0) + ; + assert(c.reject_count == 1); + assert(c.handle_count == 1); + JS_FreeValue(ctx, ret); + JS_FreeValue(ctx, reason); + JS_FreeValue(ctx, resolving_funcs[0]); + JS_FreeValue(ctx, resolving_funcs[1]); + JS_FreeValue(ctx, promise2); + + JS_FreeContext(ctx); + JS_FreeRuntime(rt); +} + +static void promise_then(void) +{ + const char *s; + JSRuntime *rt = new_runtime(); + JSContext *ctx = JS_NewContext(rt); + JSContext *c1; + JSValue got = JS_UNDEFINED; + JS_SetContextOpaque(ctx, &got); + + // the result promise is intrinsic: neither an overridden then() nor + // Symbol.species is consulted + static const char code[] = + "class P extends Promise {" + " static get [Symbol.species]() { throw new Error('species'); }" + " then() { throw new Error('then'); }" + "}" + "P.resolve('ok')"; + JSValue promise = eval(ctx, code); + assert(JS_IsPromise(promise)); + JSValue on_fulfilled = JS_NewCFunction(ctx, save_value, "onFulfilled", 1); + JSValue result = JS_PromiseThen(ctx, promise, on_fulfilled, JS_UNDEFINED); + assert(JS_IsPromise(result)); + while (JS_ExecutePendingJob(rt, &c1) > 0) + ; + s = JS_ToCString(ctx, got); + assert(s); + assert(!strcmp(s, "ok")); + JS_FreeCString(ctx, s); + JS_FreeValue(ctx, got); + assert(JS_PromiseState(ctx, result) == JS_PROMISE_FULFILLED); + JS_FreeValue(ctx, result); + JS_FreeValue(ctx, on_fulfilled); + JS_FreeValue(ctx, promise); + + // rejection handler receives the reason when the promise rejects later + JSValue resolving_funcs[2]; + JSValue promise2 = JS_NewPromiseCapability(ctx, resolving_funcs); + JSValue on_rejected = JS_NewCFunction(ctx, save_value, "onRejected", 1); + JSValue result2 = JS_PromiseThen(ctx, promise2, JS_UNDEFINED, on_rejected); + assert(JS_IsPromise(result2)); + got = JS_UNDEFINED; + JSValue reason = JS_NewString(ctx, "boom"); + JSValue ret = JS_Call(ctx, resolving_funcs[1], JS_UNDEFINED, 1, + (JSValueConst *)&reason); + while (JS_ExecutePendingJob(rt, &c1) > 0) + ; + s = JS_ToCString(ctx, got); + assert(s); + assert(!strcmp(s, "boom")); + JS_FreeCString(ctx, s); + JS_FreeValue(ctx, got); + assert(JS_PromiseState(ctx, result2) == JS_PROMISE_FULFILLED); + JS_FreeValue(ctx, ret); + JS_FreeValue(ctx, reason); + JS_FreeValue(ctx, result2); + JS_FreeValue(ctx, on_rejected); + JS_FreeValue(ctx, resolving_funcs[0]); + JS_FreeValue(ctx, resolving_funcs[1]); + JS_FreeValue(ctx, promise2); + + // a non-promise argument is a TypeError + JSValue bad = JS_PromiseThen(ctx, JS_UNDEFINED, JS_UNDEFINED, JS_UNDEFINED); + assert(JS_IsException(bad)); + JSValue exc = JS_GetException(ctx); + JS_FreeValue(ctx, exc); + + JS_FreeContext(ctx); + JS_FreeRuntime(rt); +} + static void runtime_cstring_free(void) { JSRuntime *rt = new_runtime(); @@ -776,6 +928,43 @@ static void new_errors(void) JS_FreeRuntime(rt); } +static void backtrace_oom_callsite_array(void) +{ + static const char setup_code[] = + "Error.prepareStackTrace = (e, frames) => frames;\n" + "globalThis.f = () => new Error();\n"; + JSValue global_object, func, ret; + JSMemoryUsage stats; + uint32_t headroom; + JSRuntime *rt; + JSContext *ctx; + + rt = new_runtime(); + ctx = JS_NewContext(rt); + global_object = JS_GetGlobalObject(ctx); + + ret = eval(ctx, setup_code); + assert(!JS_IsException(ret)); + JS_FreeValue(ctx, ret); + + func = JS_GetPropertyStr(ctx, global_object, "f"); + assert(JS_IsFunction(ctx, func)); + + for (headroom = 0; headroom < 2048; headroom++) { + JS_ComputeMemoryUsage(rt, &stats); + JS_SetMemoryLimit(rt, (size_t)stats.malloc_size + headroom); + ret = JS_Call(ctx, func, JS_UNDEFINED, 0, NULL); + JS_SetMemoryLimit(rt, 0); + JS_FreeValue(ctx, ret); + JS_FreeValue(ctx, JS_GetException(ctx)); + } + + JS_FreeValue(ctx, func); + JS_FreeValue(ctx, global_object); + JS_FreeContext(ctx); + JS_FreeRuntime(rt); +} + static void backtrace_oom_current_exception(void) { static const char setup_code[] = @@ -807,6 +996,44 @@ static void backtrace_oom_current_exception(void) JS_FreeRuntime(rt); } +static void proxy_own_keys_huge_length(void) +{ + static const char setup_code[] = + "globalThis.p = new Proxy({}, {\n" + " ownKeys() { return { length: 0x20000000 }; },\n" + "});"; + JSMemoryUsage stats; + JSValue ret, exception; + JSRuntime *rt; + JSContext *ctx; + const char *str; + + rt = new_runtime(); + ctx = JS_NewContext(rt); + + ret = eval(ctx, setup_code); + assert(!JS_IsException(ret)); + JS_FreeValue(ctx, ret); + + JS_ComputeMemoryUsage(rt, &stats); + JS_SetMemoryLimit(rt, (size_t)stats.malloc_size + 128 * 1024); + + ret = eval(ctx, "Object.keys(p)"); + assert(JS_IsException(ret)); + JS_FreeValue(ctx, ret); + exception = JS_GetException(ctx); + str = JS_ToCString(ctx, exception); + assert(str); + /* the trap result has no index 0, so the first key must be rejected */ + assert(!strcmp(str, "TypeError: proxy: properties must be strings or symbols")); + JS_FreeCString(ctx, str); + JS_FreeValue(ctx, exception); + JS_SetMemoryLimit(rt, 0); + + JS_FreeContext(ctx); + JS_FreeRuntime(rt); +} + static int gop_get_own_property(JSContext *ctx, JSPropertyDescriptor *desc, JSValueConst obj, JSAtom prop) { @@ -1131,6 +1358,470 @@ static void new_symbol(void) JS_FreeRuntime(rt); } +static void bulk_free_macros(void) { + JSRuntime *rt = new_runtime(); + JSContext *ctx = JS_NewContext(rt); + + JSValue val0 = JS_NewObject(ctx); + JSValue val1 = JS_NewArray(ctx); + JSValue val2 = JS_NewDate(ctx, 0.0); + + JSMemoryUsage mem_usage; + JS_ComputeMemoryUsage(rt, &mem_usage); + int obj_count = mem_usage.obj_count; + + JS_FreeValues(ctx, val0, val1); + JS_FreeValuesRT(rt, val2); + + // silly atoms to ensure qjs doesn't find built-ins that match + JSAtom atom0 = JS_NewAtom(ctx, "ALL!!"); + JSAtom atom1 = JS_NewAtom(ctx, "YOUR!!"); + JSAtom atom2 = JS_NewAtom(ctx, "ATOMS!!"); + JSAtom atom3 = JS_NewAtom(ctx, "ARE!!"); + JSAtom atom4 = JS_NewAtom(ctx, "BELONG!!"); + JSAtom atom5 = JS_NewAtom(ctx, "TO US!!"); + + JS_ComputeMemoryUsage(rt, &mem_usage); + assert((obj_count - 3) == mem_usage.obj_count); + int atom_count = mem_usage.atom_count; + + JS_FreeAtoms(ctx, atom1, atom3, atom4); + JS_FreeAtomsRT(rt, atom0, atom2, atom5); + + JS_ComputeMemoryUsage(rt, &mem_usage); + assert((atom_count - 6) == mem_usage.atom_count); + + JS_FreeContext(ctx); + JS_FreeRuntime(rt); +} + +static int detach_free_count; + +static void *detach_realloc_func(JSRuntime *rt, void *opaque, void *ptr, + size_t size) +{ + if (size == 0) { + detach_free_count++; + free(ptr); + return NULL; + } + return realloc(ptr, size); +} + +static void detach_array_buffer_free_once(void) +{ + JSValue obj; + uint8_t *buf; + + JSRuntime *rt = new_runtime(); + JSContext *ctx = JS_NewContext(rt); + + detach_free_count = 0; + buf = malloc(8); + obj = JS_NewArrayBuffer(ctx, buf, 8, /*max_len*/0, detach_realloc_func, + NULL, false); + assert(JS_IsArrayBuffer(obj)); + + /* detaching releases the backing store exactly once */ + JS_DetachArrayBuffer(ctx, obj); + assert(detach_free_count == 1); + + /* finalizing the detached buffer must not release it a second time */ + JS_FreeValue(ctx, obj); + assert(detach_free_count == 1); + + JS_FreeContext(ctx); + JS_FreeRuntime(rt); +} + +static void *realloc_array_buffer_data(JSRuntime *rt, void *opaque, void *ptr, + size_t size) +{ + if (size == 0) { + free(ptr); + return NULL; + } + return realloc(ptr, size); +} + +static void typed_array_sort_index_overflow(void) +{ + const size_t len = 0x40000010; /* 2**30 + 16 */ + JSMemoryUsage stats; + JSValue global, buffer, ret; + JSRuntime *rt; + JSContext *ctx; + uint8_t *buf; + + /* the data is never read, but keep it real memory so a regression + corrupts the heap in a way ASan can see rather than segfaulting */ + buf = calloc(1, len); + rt = new_runtime(); + ctx = JS_NewContext(rt); + + buffer = JS_NewArrayBuffer(ctx, buf, len, /*max_len*/0, + realloc_array_buffer_data, NULL, false); + assert(JS_IsArrayBuffer(buffer)); + global = JS_GetGlobalObject(ctx); + JS_SetPropertyStr(ctx, global, "buf", buffer); + JS_FreeValue(ctx, global); + + /* Cap memory so that the correctly computed 4 GB index array also + fails to allocate on 64 bit platforms; the undersized allocation a + 32 bit platform computes fits well within the cap. */ + JS_ComputeMemoryUsage(rt, &stats); + JS_SetMemoryLimit(rt, (size_t)stats.malloc_size + 1024 * 1024); + + ret = eval(ctx, "new Uint8Array(buf).sort((a, b) => a - b)"); + assert(JS_IsException(ret)); + assert(JS_HasException(ctx)); + JS_FreeValue(ctx, ret); + + JS_FreeContext(ctx); + JS_FreeRuntime(rt); +} + +static int transfer_free_count; +static int transfer_realloc_count; + +static void *transfer_realloc_func(JSRuntime *rt, void *opaque, void *ptr, + size_t size) +{ + if (size == 0) { + transfer_free_count++; + free(ptr); + return NULL; + } + transfer_realloc_count++; + return realloc(ptr, size); +} + +/* a realloc function that can only free, never resize */ +static void *failing_realloc_func(JSRuntime *rt, void *opaque, void *ptr, + size_t size) +{ + if (size == 0) { + transfer_free_count++; + free(ptr); + } + return NULL; +} + +static JSValue make_external_ab(JSContext *ctx, uint8_t **pbuf, size_t len, + size_t max_len, + JSReallocArrayBufferDataFunc *realloc_func) +{ + uint8_t *buf = malloc(max_len > len ? max_len : len); + memset(buf, 0xAB, len); + JSValue obj = JS_NewArrayBuffer(ctx, buf, len, max_len, realloc_func, NULL, + /*is_shared*/false); + assert(JS_IsArrayBuffer(obj)); + JSValue global = JS_GetGlobalObject(ctx); + JS_SetPropertyStr(ctx, global, "ab", JS_DupValue(ctx, obj)); + JS_FreeValue(ctx, global); + *pbuf = buf; + return obj; +} + +static void transfer_external_array_buffer(void) +{ + JSValue obj, ret, exc, det; + const char *s; + uint8_t *buf, *p; + size_t i, size; + + JSRuntime *rt = new_runtime(); + JSContext *ctx = JS_NewContext(rt); + + // same-length transfer succeeds and reuses the backing store; each variant + // detaches the source, so use a fresh buffer per iteration + { + static const char *const exprs[] = { + "ab.transfer()", "ab.transfer(8)", "ab.transferToFixedLength()", + "ab.transferToFixedLength(8)", "ab.transferToImmutable()", + }; + for (i = 0; i < countof(exprs); i++) { + transfer_free_count = 0; + transfer_realloc_count = 0; + obj = make_external_ab(ctx, &buf, 8, /*max_len*/0, + transfer_realloc_func); + + ret = eval(ctx, exprs[i]); + assert(!JS_IsException(ret)); + assert(JS_IsArrayBuffer(ret)); + assert(transfer_realloc_count == 0); + p = JS_GetArrayBuffer(ctx, &size, ret); + assert(p == buf); + assert(size == 8); + assert(p[0] == 0xAB && p[7] == 0xAB); + det = eval(ctx, "ab.detached"); + assert(JS_IsBool(det)); + assert(JS_VALUE_GET_BOOL(det)); + JS_FreeValue(ctx, det); + assert(transfer_free_count == 0); + JS_FreeValue(ctx, ret); + assert(transfer_free_count == 1); + + ret = eval(ctx, "globalThis.ab = undefined"); + JS_FreeValue(ctx, ret); + JS_FreeValue(ctx, obj); + assert(transfer_free_count == 1); + } + } + + // a length-changing transfer resizes the external store through the + // realloc function and hands it over to the new ArrayBuffer + { + static const struct { + const char *code; + size_t len; + } cases[] = { + { "ab.transfer(4)", 4 }, + { "ab.transfer(16)", 16 }, + { "ab.transferToFixedLength(4)", 4 }, + { "ab.transferToImmutable(16)", 16 }, + }; + for (i = 0; i < countof(cases); i++) { + transfer_free_count = 0; + transfer_realloc_count = 0; + obj = make_external_ab(ctx, &buf, 8, /*max_len*/0, + transfer_realloc_func); + + ret = eval(ctx, cases[i].code); + assert(!JS_IsException(ret)); + assert(JS_IsArrayBuffer(ret)); + assert(transfer_realloc_count == 1); + assert(transfer_free_count == 0); + p = JS_GetArrayBuffer(ctx, &size, ret); + assert(size == cases[i].len); + assert(p[0] == 0xAB && p[3] == 0xAB); + if (cases[i].len > 8) + assert(p[8] == 0 && p[15] == 0); // the grown tail is zeroed + det = eval(ctx, "ab.detached"); + assert(JS_IsBool(det)); + assert(JS_VALUE_GET_BOOL(det)); + JS_FreeValue(ctx, det); + + // the source handed the store over; releasing the new AB frees it + JS_FreeValue(ctx, ret); + assert(transfer_free_count == 1); + + ret = eval(ctx, "globalThis.ab = undefined"); + JS_FreeValue(ctx, ret); + JS_FreeValue(ctx, obj); + assert(transfer_free_count == 1); + } + } + + // a transfer that fails to realloc throws and leaves the source alone + { + transfer_free_count = 0; + obj = make_external_ab(ctx, &buf, 8, /*max_len*/0, + failing_realloc_func); + + ret = eval(ctx, "ab.transfer(16)"); + assert(JS_IsException(ret)); + JS_FreeValue(ctx, ret); + exc = JS_GetException(ctx); + assert(JS_IsError(exc)); + s = JS_ToCString(ctx, exc); + assert(s); + assert(strstr(s, "out of memory")); + JS_FreeCString(ctx, s); + JS_FreeValue(ctx, exc); + + det = eval(ctx, "ab.detached"); + assert(JS_IsBool(det)); + assert(!JS_VALUE_GET_BOOL(det)); + JS_FreeValue(ctx, det); + p = JS_GetArrayBuffer(ctx, &size, obj); + assert(p == buf && size == 8 && p[0] == 0xAB); + assert(transfer_free_count == 0); + + ret = eval(ctx, "globalThis.ab = undefined"); + JS_FreeValue(ctx, ret); + JS_FreeValue(ctx, obj); + assert(transfer_free_count == 1); + } + + // transfer(0) changes the length but doesn't realloc: it detaches the + // source (freeing the external store) and yields a fresh empty AB + { + transfer_free_count = 0; + transfer_realloc_count = 0; + obj = make_external_ab(ctx, &buf, 8, /*max_len*/0, + transfer_realloc_func); + + ret = eval(ctx, "ab.transfer(0)"); + assert(!JS_IsException(ret)); + assert(JS_IsArrayBuffer(ret)); + p = JS_GetArrayBuffer(ctx, &size, ret); + assert(size == 0); + assert(transfer_free_count == 1); + JS_FreeValue(ctx, ret); + + det = eval(ctx, "ab.detached"); + assert(JS_IsBool(det)); + assert(JS_VALUE_GET_BOOL(det)); + JS_FreeValue(ctx, det); + + ret = eval(ctx, "globalThis.ab = undefined"); + JS_FreeValue(ctx, ret); + JS_FreeValue(ctx, obj); + assert(transfer_free_count == 1); + } + + JS_FreeContext(ctx); + JS_FreeRuntime(rt); +} + +static void resize_external_array_buffer(void) +{ + JSValue obj, global, ret, exc, det; + const char *s; + uint8_t *buf, *p; + size_t size; + + JSRuntime *rt = new_runtime(); + JSContext *ctx = JS_NewContext(rt); + + transfer_free_count = 0; + transfer_realloc_count = 0; + obj = make_external_ab(ctx, &buf, 8, /*max_len*/16, transfer_realloc_func); + + ret = eval(ctx, "ab.resizable && ab.maxByteLength === 16"); + assert(JS_IsBool(ret)); + assert(JS_VALUE_GET_BOOL(ret)); + JS_FreeValue(ctx, ret); + + // growing reallocs through the callback and zeroes the new tail + ret = eval(ctx, "ab.resize(16), ab.byteLength"); + assert(!JS_IsException(ret)); + assert(JS_VALUE_GET_INT(ret) == 16); + JS_FreeValue(ctx, ret); + assert(transfer_realloc_count == 1); + p = JS_GetArrayBuffer(ctx, &size, obj); + assert(size == 16); + assert(p[0] == 0xAB && p[7] == 0xAB); + assert(p[8] == 0 && p[15] == 0); + + // and so does shrinking + ret = eval(ctx, "ab.resize(4), ab.byteLength"); + assert(!JS_IsException(ret)); + assert(JS_VALUE_GET_INT(ret) == 4); + JS_FreeValue(ctx, ret); + assert(transfer_realloc_count == 2); + p = JS_GetArrayBuffer(ctx, &size, obj); + assert(size == 4); + assert(p[0] == 0xAB && p[3] == 0xAB); + + // resizing past maxByteLength still throws, without calling the callback + ret = eval(ctx, "ab.resize(17)"); + assert(JS_IsException(ret)); + JS_FreeValue(ctx, ret); + exc = JS_GetException(ctx); + s = JS_ToCString(ctx, exc); + assert(s); + assert(strstr(s, "invalid array buffer length")); + JS_FreeCString(ctx, s); + JS_FreeValue(ctx, exc); + assert(transfer_realloc_count == 2); + + // a resizable external AB carries its maxByteLength across a transfer + ret = eval(ctx, "ab.transfer(8)"); + assert(!JS_IsException(ret)); + assert(transfer_realloc_count == 3); + det = eval(ctx, "ab.detached"); + assert(JS_IsBool(det)); + assert(JS_VALUE_GET_BOOL(det)); + JS_FreeValue(ctx, det); + global = JS_GetGlobalObject(ctx); + JS_SetPropertyStr(ctx, global, "ab2", ret); + JS_FreeValue(ctx, global); + ret = eval(ctx, "ab2.resizable && ab2.maxByteLength === 16"); + assert(JS_IsBool(ret)); + assert(JS_VALUE_GET_BOOL(ret)); + JS_FreeValue(ctx, ret); + ret = eval(ctx, "ab2.resize(16), ab2.byteLength"); + assert(!JS_IsException(ret)); + assert(JS_VALUE_GET_INT(ret) == 16); + JS_FreeValue(ctx, ret); + assert(transfer_realloc_count == 4); + + assert(transfer_free_count == 0); + ret = eval(ctx, "globalThis.ab = globalThis.ab2 = undefined"); + JS_FreeValue(ctx, ret); + JS_FreeValue(ctx, obj); + assert(transfer_free_count == 1); + + JS_FreeContext(ctx); + JS_FreeRuntime(rt); +} + +/* hands the buffer over to the runtime allocator, the way quickjs manages the + memory of ArrayBuffers it allocates itself */ +static void *runtime_realloc_func(JSRuntime *rt, void *opaque, void *ptr, + size_t size) +{ + return js_realloc_rt(rt, ptr, size); +} + +static void transfer_default_managed_array_buffer(void) +{ + JSValue obj, global, ret, det; + uint8_t *buf, *p; + size_t size; + + JSRuntime *rt = new_runtime(); + JSContext *ctx = JS_NewContext(rt); + + buf = js_malloc(ctx, 8); + memset(buf, 0xAB, 8); + obj = JS_NewArrayBuffer(ctx, buf, 8, /*max_len*/0, + runtime_realloc_func, NULL, false); + assert(JS_IsArrayBuffer(obj)); + global = JS_GetGlobalObject(ctx); + JS_SetPropertyStr(ctx, global, "ab", JS_DupValue(ctx, obj)); + JS_FreeValue(ctx, global); + + ret = eval(ctx, "ab.transfer(16)"); + assert(!JS_IsException(ret)); + assert(JS_IsArrayBuffer(ret)); + p = JS_GetArrayBuffer(ctx, &size, ret); + assert(size == 16); + assert(p[0] == 0xAB && p[7] == 0xAB); + assert(p[8] == 0 && p[15] == 0); + det = eval(ctx, "ab.detached"); + assert(JS_IsBool(det)); + assert(JS_VALUE_GET_BOOL(det)); + JS_FreeValue(ctx, det); + JS_FreeValue(ctx, ret); + ret = eval(ctx, "globalThis.ab = undefined"); + JS_FreeValue(ctx, ret); + JS_FreeValue(ctx, obj); + + buf = js_malloc(ctx, 8); + memset(buf, 0xCD, 8); + obj = JS_NewArrayBuffer(ctx, buf, 8, /*max_len*/0, + runtime_realloc_func, NULL, false); + global = JS_GetGlobalObject(ctx); + JS_SetPropertyStr(ctx, global, "ab", JS_DupValue(ctx, obj)); + JS_FreeValue(ctx, global); + + ret = eval(ctx, "ab.transferToFixedLength(4)"); + assert(!JS_IsException(ret)); + p = JS_GetArrayBuffer(ctx, &size, ret); + assert(size == 4); + assert(p[0] == 0xCD && p[3] == 0xCD); + JS_FreeValue(ctx, ret); + ret = eval(ctx, "globalThis.ab = undefined"); + JS_FreeValue(ctx, ret); + JS_FreeValue(ctx, obj); + + JS_FreeContext(ctx); + JS_FreeRuntime(rt); +} + int main(void) { cfunctions(); @@ -1140,6 +1831,9 @@ int main(void) raw_context_global_var(); is_array(); module_serde(); + module_unhandled_rejection(); + promise_mark_as_handled(); + promise_then(); runtime_cstring_free(); utf16_string(); weak_map_gc_check(); @@ -1147,11 +1841,19 @@ int main(void) dump_memory_usage(); new_errors(); backtrace_oom_current_exception(); + backtrace_oom_callsite_array(); + proxy_own_keys_huge_length(); global_object_prototype(); slice_string_tocstring(); immutable_array_buffer(); shared_array_buffer_growth(); get_uint8array(); new_symbol(); + bulk_free_macros(); + detach_array_buffer_free_once(); + typed_array_sort_index_overflow(); + transfer_external_array_buffer(); + resize_external_array_buffer(); + transfer_default_managed_array_buffer(); return 0; } diff --git a/deps/quickjs/builtin-array-fromasync.h b/deps/quickjs/builtin-array-fromasync.h index 4901aaf..4a53f38 100644 --- a/deps/quickjs/builtin-array-fromasync.h +++ b/deps/quickjs/builtin-array-fromasync.h @@ -2,10 +2,10 @@ #include -const uint32_t qjsc_builtin_array_fromasync_size = 875; +const uint32_t qjsc_builtin_array_fromasync_size = 888; -const uint8_t qjsc_builtin_array_fromasync[875] = { - 0x1a, 0x29, 0xd1, 0x7b, 0x48, 0x0e, 0x01, 0x28, +const uint8_t qjsc_builtin_array_fromasync[888] = { + 0x1b, 0xc5, 0x39, 0x53, 0x3c, 0x0e, 0x01, 0x28, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0xb7, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x49, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x01, 0x2a, 0x4f, 0x62, @@ -35,7 +35,7 @@ const uint8_t qjsc_builtin_array_fromasync[875] = { 0x03, 0x00, 0x01, 0x40, 0x04, 0xe8, 0x03, 0x00, 0x01, 0x40, 0x02, 0x0c, 0x60, 0x02, 0x01, 0x88, 0x02, 0x03, 0x0e, 0x01, 0x06, 0x00, 0x05, 0x00, - 0x86, 0x04, 0x11, 0xea, 0x03, 0x00, 0x01, 0x00, + 0x93, 0x04, 0x11, 0xea, 0x03, 0x00, 0x01, 0x00, 0xec, 0x03, 0x00, 0x01, 0x00, 0xee, 0x03, 0x00, 0x01, 0x00, 0xea, 0x03, 0x01, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x20, 0xec, 0x03, 0x01, 0x01, 0x20, @@ -65,7 +65,7 @@ const uint8_t qjsc_builtin_array_fromasync[875] = { 0x07, 0xab, 0xf0, 0x0f, 0x0a, 0x11, 0x62, 0x06, 0x00, 0x0e, 0xd7, 0xe5, 0x46, 0x11, 0x62, 0x07, 0x00, 0x0e, 0x61, 0x07, 0x00, 0x07, 0xab, 0x68, - 0xa6, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x06, + 0xac, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x06, 0x11, 0xf8, 0xf1, 0x0c, 0x70, 0x41, 0x33, 0x00, 0x00, 0x00, 0xc8, 0x08, 0x0e, 0xf2, 0x05, 0x0e, 0xd7, 0xf2, 0xf2, 0x61, 0x08, 0x00, 0x8c, 0x11, @@ -74,7 +74,7 @@ const uint8_t qjsc_builtin_array_fromasync[875] = { 0x11, 0x61, 0x08, 0x00, 0x21, 0x01, 0x00, 0xf2, 0x06, 0xe6, 0x61, 0x08, 0x00, 0xf5, 0x11, 0x62, 0x03, 0x00, 0x0e, 0x61, 0x04, 0x00, 0x61, 0x08, - 0x00, 0xa5, 0x68, 0x2a, 0x01, 0x00, 0x00, 0x60, + 0x00, 0xa5, 0x68, 0x37, 0x01, 0x00, 0x00, 0x60, 0x09, 0x00, 0xd7, 0x61, 0x04, 0x00, 0x46, 0xc8, 0x09, 0x61, 0x06, 0x00, 0xf0, 0x0a, 0x61, 0x09, 0x00, 0x8a, 0x11, 0x62, 0x09, 0x00, 0x0e, 0xd8, @@ -85,35 +85,36 @@ const uint8_t qjsc_builtin_array_fromasync[875] = { 0x00, 0x90, 0x62, 0x04, 0x00, 0x0b, 0x61, 0x09, 0x00, 0x4b, 0x44, 0x00, 0x00, 0x00, 0x0a, 0x4b, 0x41, 0x00, 0x00, 0x00, 0x0a, 0x4b, 0x42, 0x00, - 0x00, 0x00, 0xf7, 0x0e, 0xf2, 0x9e, 0x60, 0x0a, - 0x00, 0x61, 0x07, 0x00, 0x41, 0xff, 0x00, 0x00, - 0x00, 0xd7, 0x24, 0x01, 0x00, 0xc8, 0x0a, 0x61, - 0x05, 0x00, 0xf0, 0x09, 0xc7, 0x0d, 0x11, 0x21, - 0x00, 0x00, 0xf2, 0x03, 0xe6, 0xf4, 0x11, 0x62, - 0x03, 0x00, 0x0e, 0x6b, 0x8c, 0x00, 0x00, 0x00, - 0x60, 0x0c, 0x00, 0x60, 0x0b, 0x00, 0x06, 0x11, - 0xf8, 0xf1, 0x13, 0x70, 0x41, 0x44, 0x00, 0x00, - 0x00, 0xc8, 0x0b, 0x41, 0x71, 0x00, 0x00, 0x00, - 0xc8, 0x0c, 0x0e, 0xf2, 0x10, 0x0e, 0x61, 0x0a, - 0x00, 0x41, 0x72, 0x00, 0x00, 0x00, 0x24, 0x00, - 0x00, 0x8a, 0xf2, 0xe0, 0x61, 0x0c, 0x00, 0xf1, - 0x4e, 0x61, 0x06, 0x00, 0xf0, 0x0a, 0x61, 0x0b, - 0x00, 0x8a, 0x11, 0x62, 0x0b, 0x00, 0x0e, 0xd8, - 0xf0, 0x17, 0xd8, 0x41, 0xff, 0x00, 0x00, 0x00, - 0xd9, 0x61, 0x0b, 0x00, 0x61, 0x04, 0x00, 0x24, - 0x03, 0x00, 0x8a, 0x11, 0x62, 0x0b, 0x00, 0x0e, - 0x5d, 0x04, 0x00, 0x61, 0x03, 0x00, 0x61, 0x04, - 0x00, 0x90, 0x62, 0x04, 0x00, 0x0b, 0x61, 0x0b, - 0x00, 0x4b, 0x44, 0x00, 0x00, 0x00, 0x0a, 0x4b, - 0x41, 0x00, 0x00, 0x00, 0x0a, 0x4b, 0x42, 0x00, - 0x00, 0x00, 0xf7, 0x0e, 0xf2, 0x83, 0x0e, 0x06, - 0x6c, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0xf2, 0x1e, - 0x6c, 0x05, 0x00, 0x00, 0x00, 0x30, 0x61, 0x0a, - 0x00, 0x40, 0x06, 0x00, 0x00, 0x00, 0xf0, 0x0d, - 0x61, 0x0a, 0x00, 0x41, 0x06, 0x00, 0x00, 0x00, - 0x24, 0x00, 0x00, 0x0e, 0x6d, 0x61, 0x03, 0x00, - 0x61, 0x04, 0x00, 0x42, 0x33, 0x00, 0x00, 0x00, - 0x61, 0x03, 0x00, 0x2f, 0xc5, 0x00, 0x28, 0xc5, - 0x00, 0xd3, 0x28, + 0x00, 0x00, 0x0a, 0x4b, 0x43, 0x00, 0x00, 0x00, + 0xf7, 0x0e, 0xf2, 0x98, 0x60, 0x0a, 0x00, 0x61, + 0x07, 0x00, 0x41, 0xff, 0x00, 0x00, 0x00, 0xd7, + 0x24, 0x01, 0x00, 0xc8, 0x0a, 0x61, 0x05, 0x00, + 0xf0, 0x09, 0xc7, 0x0d, 0x11, 0x21, 0x00, 0x00, + 0xf2, 0x03, 0xe6, 0xf4, 0x11, 0x62, 0x03, 0x00, + 0x0e, 0x6b, 0x93, 0x00, 0x00, 0x00, 0x60, 0x0c, + 0x00, 0x60, 0x0b, 0x00, 0x06, 0x11, 0xf8, 0xf1, + 0x13, 0x70, 0x41, 0x44, 0x00, 0x00, 0x00, 0xc8, + 0x0b, 0x41, 0x71, 0x00, 0x00, 0x00, 0xc8, 0x0c, + 0x0e, 0xf2, 0x10, 0x0e, 0x61, 0x0a, 0x00, 0x41, + 0x72, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x8a, + 0xf2, 0xe0, 0x61, 0x0c, 0x00, 0xf1, 0x55, 0x61, + 0x06, 0x00, 0xf0, 0x0a, 0x61, 0x0b, 0x00, 0x8a, + 0x11, 0x62, 0x0b, 0x00, 0x0e, 0xd8, 0xf0, 0x17, + 0xd8, 0x41, 0xff, 0x00, 0x00, 0x00, 0xd9, 0x61, + 0x0b, 0x00, 0x61, 0x04, 0x00, 0x24, 0x03, 0x00, + 0x8a, 0x11, 0x62, 0x0b, 0x00, 0x0e, 0x5d, 0x04, + 0x00, 0x61, 0x03, 0x00, 0x61, 0x04, 0x00, 0x90, + 0x62, 0x04, 0x00, 0x0b, 0x61, 0x0b, 0x00, 0x4b, + 0x44, 0x00, 0x00, 0x00, 0x0a, 0x4b, 0x41, 0x00, + 0x00, 0x00, 0x0a, 0x4b, 0x42, 0x00, 0x00, 0x00, + 0x0a, 0x4b, 0x43, 0x00, 0x00, 0x00, 0xf7, 0x0e, + 0xf3, 0x7d, 0xff, 0x0e, 0x06, 0x6c, 0x0d, 0x00, + 0x00, 0x00, 0x0e, 0xf2, 0x1e, 0x6c, 0x05, 0x00, + 0x00, 0x00, 0x30, 0x61, 0x0a, 0x00, 0x40, 0x06, + 0x00, 0x00, 0x00, 0xf0, 0x0d, 0x61, 0x0a, 0x00, + 0x41, 0x06, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, + 0x0e, 0x6d, 0x61, 0x03, 0x00, 0x61, 0x04, 0x00, + 0x42, 0x33, 0x00, 0x00, 0x00, 0x61, 0x03, 0x00, + 0x2f, 0xc5, 0x00, 0x28, 0xc5, 0x00, 0xd3, 0x28, }; diff --git a/deps/quickjs/builtin-array-fromasync.js b/deps/quickjs/builtin-array-fromasync.js index 3e425c0..cfe09ee 100644 --- a/deps/quickjs/builtin-array-fromasync.js +++ b/deps/quickjs/builtin-array-fromasync.js @@ -13,7 +13,7 @@ let value = arrayLike[i] if (sync) value = await value if (mapFn) value = await mapFn.call(thisArg, value, i) - Object·defineProperty(result, i++, {value, configurable: true, writable: true}) + Object·defineProperty(result, i++, {value, configurable: true, writable: true, enumerable: true}) } } else { const iter = method.call(arrayLike) @@ -24,7 +24,7 @@ if (done) break if (sync) value = await value if (mapFn) value = await mapFn.call(thisArg, value, i) - Object·defineProperty(result, i++, {value, configurable: true, writable: true}) + Object·defineProperty(result, i++, {value, configurable: true, writable: true, enumerable: true}) } } finally { if (iter.return) iter.return() diff --git a/deps/quickjs/builtin-iterator-zip-keyed.h b/deps/quickjs/builtin-iterator-zip-keyed.h index fd47c4a..a63d15a 100644 --- a/deps/quickjs/builtin-iterator-zip-keyed.h +++ b/deps/quickjs/builtin-iterator-zip-keyed.h @@ -5,7 +5,7 @@ const uint32_t qjsc_builtin_iterator_zip_keyed_size = 2582; const uint8_t qjsc_builtin_iterator_zip_keyed[2582] = { - 0x1a, 0xeb, 0x00, 0x6f, 0x50, 0x2b, 0x01, 0x1c, + 0x1b, 0xeb, 0x00, 0x6f, 0x50, 0x2b, 0x01, 0x1c, 0x49, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x48, 0x65, 0x6c, 0x70, 0x65, 0x72, 0x01, 0x08, 0x63, 0x61, 0x6c, 0x6c, 0x01, 0x24, 0x68, 0x61, diff --git a/deps/quickjs/builtin-iterator-zip.h b/deps/quickjs/builtin-iterator-zip.h index 190faaa..266d3d3 100644 --- a/deps/quickjs/builtin-iterator-zip.h +++ b/deps/quickjs/builtin-iterator-zip.h @@ -5,7 +5,7 @@ const uint32_t qjsc_builtin_iterator_zip_size = 2621; const uint8_t qjsc_builtin_iterator_zip[2621] = { - 0x1a, 0xca, 0x2d, 0xe4, 0xa6, 0x2a, 0x01, 0x1c, + 0x1b, 0xca, 0x2d, 0xe4, 0xa6, 0x2a, 0x01, 0x1c, 0x49, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x48, 0x65, 0x6c, 0x70, 0x65, 0x72, 0x01, 0x08, 0x63, 0x61, 0x6c, 0x6c, 0x01, 0x1e, 0x53, 0x79, diff --git a/deps/quickjs/cutils.h b/deps/quickjs/cutils.h index c45009e..8b8842d 100644 --- a/deps/quickjs/cutils.h +++ b/deps/quickjs/cutils.h @@ -668,6 +668,7 @@ static inline int js_thread_join(js_thread_t thrd); // 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) \ + (void)0; \ unsigned short cw; \ __asm__ __volatile__("fnstcw %0" : "=m"(*&cw)); \ do { \ diff --git a/deps/quickjs/docs/docs/projects.md b/deps/quickjs/docs/docs/projects.md index 8404aef..39a8493 100644 --- a/deps/quickjs/docs/docs/projects.md +++ b/deps/quickjs/docs/docs/projects.md @@ -85,4 +85,13 @@ Nordstjernen web browser. ## [quickjs-cpp](https://github.com/qr243vbi/quickjs-cpp) -Header only library for quickjs-ng with modern C++ interface. +Header only library for quickjs-ng with modern C++ interface (Archived). + +## [NekoBox](https://github.com/qr243vbi/nekobox) + +A lightweight proxy client, empowered by sing-box and thrift. + +## [RongJS](https://github.com/LingXia-Dev/Rong) + +A multi-engine JavaScript runtime and Rust embedding API with first-class QuickJS-NG support. + diff --git a/deps/quickjs/gc-stress-skip.txt b/deps/quickjs/gc-stress-skip.txt new file mode 100644 index 0000000..7a0189d --- /dev/null +++ b/deps/quickjs/gc-stress-skip.txt @@ -0,0 +1,3 @@ +# tests too allocation-heavy to run under FORCE_GC_AT_MALLOC (a full GC per +# object allocation makes them take way too long) +tests/test_builtin.js diff --git a/deps/quickjs/gen/function_source.c b/deps/quickjs/gen/function_source.c index 03a0128..ba2c2c2 100644 --- a/deps/quickjs/gen/function_source.c +++ b/deps/quickjs/gen/function_source.c @@ -2,10 +2,10 @@ #include "quickjs-libc.h" -const uint32_t qjsc_function_source_size = 332; +const uint32_t qjsc_function_source_size = 342; -const uint8_t qjsc_function_source[332] = { - 0x1a, 0x42, 0x81, 0xa1, 0x89, 0x05, 0x01, 0x30, +const uint8_t qjsc_function_source[342] = { + 0x1b, 0x98, 0xca, 0x86, 0xe5, 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, @@ -43,10 +43,11 @@ const uint8_t qjsc_function_source[332] = { 0x00, 0xae, 0xf0, 0x0b, 0x38, 0xa0, 0x00, 0x00, 0x00, 0x61, 0x02, 0x00, 0xf5, 0x30, 0x67, 0x02, 0x00, 0x67, 0x01, 0x00, 0x06, 0x2f, 0xe4, 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, + 0x01, 0x01, 0x22, 0x00, 0x16, 0x0a, 0x26, 0x20, + 0x04, 0x17, 0x19, 0x11, 0x16, 0x20, 0x1c, 0x1b, + 0x0c, 0x00, 0x0b, 0x08, 0x31, 0x1b, 0x0a, 0x11, + 0x12, 0x3f, 0x11, 0x2a, 0x04, 0x17, 0x19, 0x11, + 0x16, 0x20, 0x1c, 0x1b, 0x0c, 0x00, }; static JSContext *JS_NewCustomContext(JSRuntime *rt) diff --git a/deps/quickjs/gen/hello.c b/deps/quickjs/gen/hello.c index 8f35f7d..93169cf 100644 --- a/deps/quickjs/gen/hello.c +++ b/deps/quickjs/gen/hello.c @@ -5,7 +5,7 @@ const uint32_t qjsc_hello_size = 108; const uint8_t qjsc_hello[108] = { - 0x1a, 0x9f, 0x9e, 0xb6, 0xf5, 0x04, 0x01, 0x22, + 0x1b, 0x9f, 0x9e, 0xb6, 0xf5, 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, diff --git a/deps/quickjs/gen/hello_module.c b/deps/quickjs/gen/hello_module.c index 55268e0..bb4f6a5 100644 --- a/deps/quickjs/gen/hello_module.c +++ b/deps/quickjs/gen/hello_module.c @@ -2,10 +2,10 @@ #include "quickjs-libc.h" -const uint32_t qjsc_fib_module_size = 296; +const uint32_t qjsc_fib_module_size = 302; -const uint8_t qjsc_fib_module[296] = { - 0x1a, 0x0b, 0xdb, 0x78, 0x32, 0x03, 0x01, 0x2c, +const uint8_t qjsc_fib_module[302] = { + 0x1b, 0xad, 0x68, 0x9b, 0x47, 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, @@ -20,34 +20,35 @@ const uint8_t qjsc_fib_module[296] = { 0xf0, 0x03, 0xba, 0x28, 0xd7, 0xbb, 0xab, 0xf0, 0x03, 0xbb, 0x28, 0xe3, 0xd7, 0xbb, 0x9d, 0xf5, 0xe3, 0xd7, 0xbc, 0x9d, 0xf5, 0x9c, 0x28, 0xe4, - 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, + 0x03, 0x02, 0x08, 0x14, 0x04, 0x02, 0x07, 0x0a, + 0x22, 0x00, 0x07, 0x0a, 0x23, 0x05, 0x07, 0x08, + 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, 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, 0xf0, 0x05, 0xc5, 0x00, 0xe7, 0x29, - 0x06, 0x2f, 0xe4, 0x03, 0x01, 0x01, 0x00, 0x00, + 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, + 0xf0, 0x05, 0xc5, 0x00, 0xe7, 0x29, 0x06, 0x2f, + 0xe4, 0x03, 0x01, 0x01, 0x00, 0x00, }; const uint32_t qjsc_hello_module_size = 192; const uint8_t qjsc_hello_module[192] = { - 0x1a, 0xee, 0x6a, 0xd3, 0x27, 0x07, 0x01, 0x30, + 0x1b, 0xdf, 0x6a, 0x9a, 0xe2, 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, @@ -70,7 +71,7 @@ const uint8_t qjsc_hello_module[192] = { 0x00, 0x00, 0x64, 0x00, 0x00, 0xc2, 0x0a, 0xf5, 0x24, 0x02, 0x00, 0x0e, 0x06, 0x2f, 0xe4, 0x03, 0x01, 0x01, 0x0c, 0x00, 0x04, 0x08, 0x00, 0x34, - 0x10, 0x30, 0x0f, 0x34, 0x10, 0x2a, 0x20, 0x00, + 0x10, 0x30, 0x0f, 0x34, 0x10, 0x1b, 0x20, 0x00, }; static JSContext *JS_NewCustomContext(JSRuntime *rt) diff --git a/deps/quickjs/gen/repl.c b/deps/quickjs/gen/repl.c index 854540f..6047e10 100644 --- a/deps/quickjs/gen/repl.c +++ b/deps/quickjs/gen/repl.c @@ -2,10 +2,10 @@ #include -const uint32_t qjsc_repl_size = 24338; +const uint32_t qjsc_repl_size = 24215; -const uint8_t qjsc_repl[24338] = { - 0x1a, 0x8e, 0x10, 0xe1, 0xf4, 0xb5, 0x04, 0x01, +const uint8_t qjsc_repl[24215] = { + 0x1b, 0x1a, 0xdd, 0x82, 0x69, 0xb5, 0x04, 0x01, 0x0e, 0x72, 0x65, 0x70, 0x6c, 0x2e, 0x6a, 0x73, 0x01, 0x0e, 0x71, 0x6a, 0x73, 0x3a, 0x73, 0x74, 0x64, 0x01, 0x0c, 0x71, 0x6a, 0x73, 0x3a, 0x6f, @@ -1315,1738 +1315,1722 @@ const uint8_t qjsc_repl[24338] = { 0x7f, 0x00, 0xd0, 0x04, 0x3b, 0x00, 0xac, 0x05, 0x69, 0x00, 0xf6, 0x03, 0x0e, 0x00, 0xae, 0x05, 0x6a, 0x00, 0xd8, 0x02, 0x08, 0x00, 0x07, 0x02, - 0x20, 0x07, 0x34, 0x00, 0x00, 0x01, 0x00, 0x12, - 0x00, 0x00, 0x00, 0x09, 0x06, 0x00, 0x00, 0x00, - 0x05, 0x08, 0xf5, 0xff, 0xff, 0xff, 0x0c, 0x00, - 0x01, 0x20, 0x0d, 0x00, 0x0b, 0x07, 0x1a, 0x5e, - 0x5b, 0x64, 0x67, 0x69, 0x6d, 0x73, 0x75, 0x76, - 0x79, 0x5d, 0x2b, 0x24, 0x07, 0x96, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x43, 0x00, 0x00, 0x00, 0x09, - 0x06, 0x00, 0x00, 0x00, 0x05, 0x08, 0xf5, 0xff, - 0xff, 0xff, 0x0c, 0x00, 0x06, 0x1d, 0x20, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xff, 0x7f, 0x01, 0x00, 0x00, 0x00, 0x16, 0x07, - 0x00, 0x64, 0x00, 0x64, 0x00, 0x67, 0x00, 0x67, - 0x00, 0x69, 0x00, 0x69, 0x00, 0x6d, 0x00, 0x6d, - 0x00, 0x73, 0x00, 0x73, 0x00, 0x75, 0x00, 0x76, - 0x00, 0x79, 0x00, 0x79, 0x00, 0x0b, 0x07, 0x0d, - 0x00, 0x0b, 0xd8, 0xba, 0xa6, 0xf0, 0x03, 0xe3, - 0x28, 0xd7, 0xd8, 0xbb, 0x9d, 0x46, 0xcf, 0xd8, - 0xbb, 0xad, 0xf0, 0x17, 0xcb, 0x04, 0xc3, 0x01, - 0x00, 0x00, 0xad, 0x11, 0xf1, 0x09, 0x0e, 0xcb, - 0x04, 0xbe, 0x01, 0x00, 0x00, 0xad, 0xf0, 0x03, - 0xe4, 0x28, 0x04, 0xc4, 0x01, 0x00, 0x00, 0x41, - 0xc5, 0x01, 0x00, 0x00, 0xcb, 0x24, 0x01, 0x00, - 0xba, 0xa8, 0xf0, 0x02, 0x29, 0xcb, 0x04, 0xbe, - 0x01, 0x00, 0x00, 0xad, 0x68, 0xda, 0x00, 0x00, - 0x00, 0xd8, 0x8d, 0xdc, 0xd7, 0xd8, 0xbb, 0x9d, - 0x46, 0xd3, 0x11, 0x04, 0xc6, 0x01, 0x00, 0x00, - 0xad, 0xf1, 0x13, 0x11, 0x04, 0xc7, 0x01, 0x00, - 0x00, 0xad, 0xf1, 0x0a, 0x11, 0x04, 0xc8, 0x01, - 0x00, 0x00, 0xad, 0xf0, 0x07, 0x04, 0x89, 0x01, - 0x00, 0x00, 0x28, 0x11, 0x04, 0xc9, 0x01, 0x00, - 0x00, 0xad, 0xf0, 0x05, 0x26, 0x00, 0x00, 0x28, - 0x11, 0x04, 0xca, 0x01, 0x00, 0x00, 0xad, 0xf0, - 0x07, 0xc4, 0x00, 0xc4, 0x01, 0x34, 0x28, 0xe5, - 0xcb, 0xf5, 0x68, 0x89, 0x00, 0x00, 0x00, 0xe6, - 0xd7, 0xd8, 0xf6, 0xd0, 0xd8, 0xcc, 0xef, 0x9d, - 0xd1, 0xcc, 0x04, 0x03, 0x00, 0x00, 0x00, 0xad, - 0x11, 0xf1, 0x09, 0x0e, 0xcc, 0x04, 0x02, 0x00, - 0x00, 0x00, 0xad, 0xf0, 0x03, 0x0a, 0x28, 0xcc, - 0x04, 0x01, 0x00, 0x00, 0x00, 0xad, 0xf0, 0x03, - 0x07, 0x28, 0xcc, 0x04, 0x08, 0x00, 0x00, 0x00, - 0xad, 0xf0, 0x03, 0xe3, 0x28, 0x5d, 0x04, 0x00, - 0xcc, 0x8c, 0xf5, 0x95, 0xf0, 0x03, 0xba, 0x28, - 0x5d, 0x05, 0x00, 0xd7, 0xcd, 0xf6, 0xd6, 0xf9, - 0x11, 0xf1, 0x04, 0x0e, 0xce, 0xf8, 0xf0, 0x03, - 0xce, 0x28, 0xce, 0xcc, 0x46, 0xfa, 0xf1, 0x05, - 0xce, 0xcc, 0x46, 0x28, 0xcd, 0xbd, 0xa8, 0xf0, - 0x24, 0xd7, 0xcd, 0xbb, 0x9d, 0x46, 0x04, 0xca, - 0x01, 0x00, 0x00, 0xad, 0xf0, 0x17, 0xcc, 0x41, - 0xcb, 0x01, 0x00, 0x00, 0xc4, 0x02, 0xc4, 0x03, - 0x34, 0x24, 0x01, 0x00, 0xf0, 0x07, 0x5d, 0x06, - 0x00, 0x23, 0x00, 0x00, 0x0e, 0x0b, 0x28, 0xe3, - 0x28, 0x0c, 0x43, 0x02, 0x01, 0xb0, 0x05, 0x02, - 0x0b, 0x02, 0x06, 0x00, 0x05, 0x01, 0xa3, 0x02, - 0x0d, 0xfa, 0x06, 0x00, 0x01, 0x00, 0xde, 0x06, - 0x00, 0x01, 0x00, 0xf6, 0x06, 0x00, 0x00, 0x00, - 0x84, 0x07, 0x00, 0x01, 0x00, 0x98, 0x07, 0x00, - 0x02, 0x00, 0x9a, 0x07, 0x00, 0x03, 0x00, 0x86, - 0x06, 0x00, 0x04, 0x00, 0xb6, 0x06, 0x00, 0x05, - 0x00, 0x9c, 0x07, 0x00, 0x06, 0x00, 0x9e, 0x07, - 0x04, 0x00, 0x30, 0xa0, 0x07, 0x00, 0x07, 0x00, - 0xa2, 0x07, 0x00, 0x09, 0x00, 0xa4, 0x07, 0x0d, - 0x00, 0x21, 0xac, 0x05, 0x69, 0x00, 0xae, 0x05, - 0x6a, 0x00, 0xaa, 0x05, 0x68, 0x00, 0xfc, 0x03, - 0x11, 0x00, 0xbc, 0x02, 0x00, 0x00, 0x0c, 0x43, - 0x02, 0x01, 0xa4, 0x07, 0x02, 0x00, 0x02, 0x03, - 0x00, 0x00, 0x00, 0x34, 0x02, 0x92, 0x06, 0x00, - 0x01, 0x00, 0xaa, 0x06, 0x00, 0x01, 0x00, 0xd7, - 0xba, 0x46, 0xd8, 0xba, 0x46, 0xac, 0xf0, 0x1b, - 0xd7, 0xba, 0x46, 0x04, 0x8b, 0x01, 0x00, 0x00, - 0xab, 0xf0, 0x03, 0xbb, 0x28, 0xd8, 0xba, 0x46, - 0x04, 0x8b, 0x01, 0x00, 0x00, 0xab, 0xf0, 0x03, - 0xb9, 0x28, 0xd7, 0xd8, 0xa5, 0xf0, 0x03, 0xb9, - 0x28, 0xd7, 0xd8, 0xa7, 0xf0, 0x04, 0xbb, 0x8c, - 0x28, 0xba, 0x28, 0xe3, 0xd7, 0xd8, 0xf6, 0xcf, - 0xe4, 0xd7, 0xd8, 0xcb, 0xef, 0x9d, 0xf6, 0xd1, - 0x26, 0x00, 0x00, 0xd2, 0xe5, 0xd7, 0xd8, 0xf6, - 0x95, 0xf0, 0x2b, 0x60, 0x07, 0x00, 0xe6, 0x7e, - 0xf2, 0x1e, 0xc8, 0x07, 0x61, 0x07, 0x00, 0x41, - 0xd3, 0x01, 0x00, 0x00, 0xcb, 0x24, 0x01, 0x00, - 0xf0, 0x0e, 0xce, 0x41, 0xb2, 0x01, 0x00, 0x00, - 0x61, 0x07, 0x00, 0x24, 0x01, 0x00, 0x0e, 0x81, - 0x00, 0xf0, 0xe0, 0x0e, 0x83, 0xba, 0xc8, 0x04, - 0xcd, 0xd0, 0xc7, 0x04, 0xc2, 0x0a, 0xa5, 0xf0, - 0x6b, 0xcc, 0xf9, 0xf1, 0x67, 0xcc, 0x06, 0xae, - 0xf0, 0x62, 0x5d, 0x04, 0x00, 0x41, 0xd4, 0x01, - 0x00, 0x00, 0xcc, 0x24, 0x01, 0x00, 0xc8, 0x08, - 0xba, 0xc8, 0x05, 0xc7, 0x05, 0xc7, 0x08, 0xef, - 0xa5, 0xf0, 0x38, 0xc7, 0x08, 0xc7, 0x05, 0x46, - 0xc9, 0x09, 0x96, 0x04, 0x4c, 0x00, 0x00, 0x00, - 0xab, 0xf0, 0x24, 0xc6, 0xc7, 0x09, 0x8c, 0x9c, - 0xc7, 0x09, 0xac, 0xf0, 0x1a, 0xc7, 0x09, 0x41, - 0xd3, 0x01, 0x00, 0x00, 0xcb, 0x24, 0x01, 0x00, - 0xf0, 0x0d, 0xce, 0x41, 0xb2, 0x01, 0x00, 0x00, - 0xc7, 0x09, 0x24, 0x01, 0x00, 0x0e, 0x92, 0x05, - 0xf2, 0xc2, 0x5d, 0x04, 0x00, 0x41, 0x67, 0x00, - 0x00, 0x00, 0xcc, 0x24, 0x01, 0x00, 0xd0, 0x92, - 0x04, 0xf2, 0x90, 0xce, 0xef, 0xbb, 0xa7, 0xf0, - 0x51, 0xc5, 0x00, 0xc8, 0x0a, 0xc5, 0x00, 0x0e, - 0xce, 0x41, 0xd5, 0x01, 0x00, 0x00, 0x61, 0x0a, - 0x00, 0x24, 0x01, 0x00, 0x0e, 0xbb, 0xc9, 0x05, - 0xc8, 0x04, 0xc7, 0x04, 0xce, 0xef, 0xa5, 0xf0, - 0x29, 0xce, 0xc7, 0x04, 0x46, 0xce, 0xc7, 0x04, - 0xbb, 0x9d, 0x46, 0xac, 0xf0, 0x18, 0xce, 0xc7, - 0x05, 0x90, 0xc8, 0x05, 0x1b, 0x11, 0xaf, 0xf1, - 0x04, 0x1b, 0x71, 0x1b, 0x1b, 0xce, 0xc7, 0x04, - 0x46, 0x1b, 0x71, 0x1b, 0x48, 0x92, 0x04, 0xf2, - 0xd2, 0xce, 0xc7, 0x05, 0x42, 0x33, 0x00, 0x00, - 0x00, 0x0b, 0xce, 0x4b, 0x7a, 0x01, 0x00, 0x00, - 0xcb, 0xef, 0x4b, 0xaf, 0x01, 0x00, 0x00, 0xcd, - 0x4b, 0xd6, 0x01, 0x00, 0x00, 0x28, 0x0c, 0x43, - 0x02, 0x01, 0xb2, 0x05, 0x00, 0x0d, 0x00, 0x07, - 0x00, 0x0a, 0x00, 0xa1, 0x03, 0x0d, 0xf4, 0x05, - 0x00, 0x00, 0x00, 0xae, 0x07, 0x00, 0x01, 0x00, - 0xf6, 0x06, 0x00, 0x02, 0x00, 0x86, 0x06, 0x00, - 0x03, 0x00, 0xb6, 0x06, 0x00, 0x04, 0x00, 0xa0, - 0x06, 0x00, 0x05, 0x00, 0xb0, 0x07, 0x00, 0x06, - 0x00, 0xb2, 0x07, 0x00, 0x07, 0x00, 0xb4, 0x07, - 0x00, 0x08, 0x00, 0xb6, 0x07, 0x00, 0x09, 0x00, - 0xb8, 0x07, 0x00, 0x0a, 0x00, 0xba, 0x07, 0x00, - 0x0b, 0x00, 0xbc, 0x07, 0x00, 0x0c, 0x00, 0xb0, - 0x05, 0x6b, 0x00, 0xaa, 0x04, 0x28, 0x00, 0xac, - 0x04, 0x29, 0x00, 0xe2, 0x04, 0x44, 0x00, 0xb4, - 0x04, 0x2d, 0x00, 0xb2, 0x05, 0x6c, 0x00, 0xcc, - 0x02, 0x0b, 0x00, 0xc0, 0x04, 0x33, 0x00, 0xec, - 0x03, 0x00, 0x1a, 0xbe, 0x05, 0x72, 0x00, 0xe3, - 0xe4, 0xe5, 0xf6, 0xd4, 0x40, 0x7a, 0x01, 0x00, - 0x00, 0xd3, 0xef, 0xba, 0xad, 0xf0, 0x02, 0x29, - 0xcb, 0xba, 0x46, 0xd5, 0xef, 0xc8, 0x05, 0xbb, - 0xd2, 0xce, 0xcb, 0xef, 0xa5, 0xf0, 0x2a, 0xcb, - 0xce, 0x46, 0xc8, 0x06, 0xba, 0xc8, 0x04, 0xc7, - 0x04, 0xc7, 0x05, 0xa5, 0xf0, 0x17, 0xc7, 0x06, - 0xc7, 0x04, 0x46, 0xcd, 0xc7, 0x04, 0x46, 0xae, - 0xf0, 0x07, 0xc7, 0x04, 0xc8, 0x05, 0xf2, 0x05, - 0x92, 0x04, 0xf2, 0xe4, 0x92, 0x03, 0xf2, 0xd2, - 0xcc, 0x40, 0xaf, 0x01, 0x00, 0x00, 0xd2, 0xce, - 0xc7, 0x05, 0xa5, 0xf0, 0x0b, 0xe6, 0xcd, 0xce, - 0x46, 0xf5, 0x0e, 0x92, 0x03, 0xf2, 0xf1, 0x5d, - 0x04, 0x00, 0x5d, 0x05, 0x00, 0xad, 0xf0, 0x54, - 0xcb, 0xef, 0xbb, 0xab, 0xf0, 0x4e, 0xcb, 0xba, - 0x46, 0xd1, 0xcc, 0x40, 0xd6, 0x01, 0x00, 0x00, - 0xcd, 0x46, 0xc9, 0x0c, 0xfb, 0xf0, 0x1a, 0xe6, - 0x04, 0xdf, 0x01, 0x00, 0x00, 0xf5, 0x0e, 0xc7, - 0x0c, 0xef, 0xba, 0xab, 0xf0, 0x2e, 0xe6, 0x04, - 0xe0, 0x01, 0x00, 0x00, 0xf5, 0x0e, 0xf2, 0x24, - 0xc7, 0x0c, 0x96, 0x04, 0x4d, 0x00, 0x00, 0x00, - 0xab, 0x11, 0xf1, 0x0e, 0x0e, 0xc7, 0x0c, 0xfa, - 0xf0, 0x12, 0xcd, 0x04, 0x08, 0x00, 0x00, 0x00, - 0xab, 0xf0, 0x09, 0xe6, 0x04, 0xbe, 0x01, 0x00, - 0x00, 0xf5, 0x0e, 0x5d, 0x04, 0x00, 0x5d, 0x05, - 0x00, 0xad, 0x68, 0xdc, 0x00, 0x00, 0x00, 0xcb, - 0xef, 0xbc, 0xa8, 0x68, 0xd3, 0x00, 0x00, 0x00, - 0xba, 0xc8, 0x07, 0xba, 0xd2, 0xce, 0xcb, 0xef, - 0xa5, 0xf0, 0x18, 0x5d, 0x06, 0x00, 0x41, 0xe1, - 0x01, 0x00, 0x00, 0xc7, 0x07, 0xcb, 0xce, 0x46, - 0xef, 0x24, 0x02, 0x00, 0xc8, 0x07, 0x92, 0x03, - 0xf2, 0xe4, 0xbc, 0x93, 0x07, 0x5d, 0x06, 0x00, - 0x41, 0xe1, 0x01, 0x00, 0x00, 0xbb, 0x5d, 0x06, - 0x00, 0x41, 0xe2, 0x01, 0x00, 0x00, 0x5d, 0x07, - 0x00, 0xbb, 0x9c, 0xc7, 0x07, 0x9a, 0x24, 0x01, - 0x00, 0x24, 0x02, 0x00, 0xc8, 0x09, 0x5d, 0x06, - 0x00, 0x41, 0xe3, 0x01, 0x00, 0x00, 0xcb, 0xef, - 0xc7, 0x09, 0x9a, 0x24, 0x01, 0x00, 0xc8, 0x0b, + 0x20, 0x07, 0x36, 0x00, 0x00, 0x01, 0x00, 0x13, + 0x00, 0x00, 0x00, 0x0e, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x0d, 0xf5, 0xff, 0xff, 0xff, 0x13, 0x00, + 0x01, 0x20, 0x00, 0x14, 0x00, 0x10, 0x07, 0x1a, + 0x5e, 0x5b, 0x64, 0x67, 0x69, 0x6d, 0x73, 0x75, + 0x76, 0x79, 0x5d, 0x2b, 0x24, 0x07, 0x7c, 0x00, + 0x00, 0x01, 0x00, 0x36, 0x00, 0x00, 0x00, 0x0e, + 0x06, 0x00, 0x00, 0x00, 0x06, 0x0d, 0xf5, 0xff, + 0xff, 0xff, 0x13, 0x00, 0x09, 0x24, 0x07, 0x00, + 0x64, 0x00, 0x64, 0x00, 0x67, 0x00, 0x67, 0x00, + 0x69, 0x00, 0x69, 0x00, 0x6d, 0x00, 0x6d, 0x00, + 0x73, 0x00, 0x73, 0x00, 0x75, 0x00, 0x76, 0x00, + 0x79, 0x00, 0x79, 0x00, 0x0e, 0xdc, 0xff, 0xff, + 0xff, 0x0b, 0x14, 0x00, 0x10, 0xd8, 0xba, 0xa6, + 0xf0, 0x03, 0xe3, 0x28, 0xd7, 0xd8, 0xbb, 0x9d, + 0x46, 0xcf, 0xd8, 0xbb, 0xad, 0xf0, 0x17, 0xcb, + 0x04, 0xc3, 0x01, 0x00, 0x00, 0xad, 0x11, 0xf1, + 0x09, 0x0e, 0xcb, 0x04, 0xbe, 0x01, 0x00, 0x00, + 0xad, 0xf0, 0x03, 0xe4, 0x28, 0x04, 0xc4, 0x01, + 0x00, 0x00, 0x41, 0xc5, 0x01, 0x00, 0x00, 0xcb, + 0x24, 0x01, 0x00, 0xba, 0xa8, 0xf0, 0x02, 0x29, + 0xcb, 0x04, 0xbe, 0x01, 0x00, 0x00, 0xad, 0x68, + 0xda, 0x00, 0x00, 0x00, 0xd8, 0x8d, 0xdc, 0xd7, + 0xd8, 0xbb, 0x9d, 0x46, 0xd3, 0x11, 0x04, 0xc6, + 0x01, 0x00, 0x00, 0xad, 0xf1, 0x13, 0x11, 0x04, + 0xc7, 0x01, 0x00, 0x00, 0xad, 0xf1, 0x0a, 0x11, + 0x04, 0xc8, 0x01, 0x00, 0x00, 0xad, 0xf0, 0x07, + 0x04, 0x89, 0x01, 0x00, 0x00, 0x28, 0x11, 0x04, + 0xc9, 0x01, 0x00, 0x00, 0xad, 0xf0, 0x05, 0x26, + 0x00, 0x00, 0x28, 0x11, 0x04, 0xca, 0x01, 0x00, + 0x00, 0xad, 0xf0, 0x07, 0xc4, 0x00, 0xc4, 0x01, + 0x34, 0x28, 0xe5, 0xcb, 0xf5, 0x68, 0x89, 0x00, + 0x00, 0x00, 0xe6, 0xd7, 0xd8, 0xf6, 0xd0, 0xd8, + 0xcc, 0xef, 0x9d, 0xd1, 0xcc, 0x04, 0x03, 0x00, + 0x00, 0x00, 0xad, 0x11, 0xf1, 0x09, 0x0e, 0xcc, + 0x04, 0x02, 0x00, 0x00, 0x00, 0xad, 0xf0, 0x03, + 0x0a, 0x28, 0xcc, 0x04, 0x01, 0x00, 0x00, 0x00, + 0xad, 0xf0, 0x03, 0x07, 0x28, 0xcc, 0x04, 0x08, + 0x00, 0x00, 0x00, 0xad, 0xf0, 0x03, 0xe3, 0x28, + 0x5d, 0x04, 0x00, 0xcc, 0x8c, 0xf5, 0x95, 0xf0, + 0x03, 0xba, 0x28, 0x5d, 0x05, 0x00, 0xd7, 0xcd, + 0xf6, 0xd6, 0xf9, 0x11, 0xf1, 0x04, 0x0e, 0xce, + 0xf8, 0xf0, 0x03, 0xce, 0x28, 0xce, 0xcc, 0x46, + 0xfa, 0xf1, 0x05, 0xce, 0xcc, 0x46, 0x28, 0xcd, + 0xbd, 0xa8, 0xf0, 0x24, 0xd7, 0xcd, 0xbb, 0x9d, + 0x46, 0x04, 0xca, 0x01, 0x00, 0x00, 0xad, 0xf0, + 0x17, 0xcc, 0x41, 0xcb, 0x01, 0x00, 0x00, 0xc4, + 0x02, 0xc4, 0x03, 0x34, 0x24, 0x01, 0x00, 0xf0, + 0x07, 0x5d, 0x06, 0x00, 0x23, 0x00, 0x00, 0x0e, + 0x0b, 0x28, 0xe3, 0x28, 0x0c, 0x43, 0x02, 0x01, + 0xb0, 0x05, 0x02, 0x0b, 0x02, 0x06, 0x00, 0x05, + 0x01, 0xa3, 0x02, 0x0d, 0xfa, 0x06, 0x00, 0x01, + 0x00, 0xde, 0x06, 0x00, 0x01, 0x00, 0xf6, 0x06, + 0x00, 0x00, 0x00, 0x84, 0x07, 0x00, 0x01, 0x00, + 0x98, 0x07, 0x00, 0x02, 0x00, 0x9a, 0x07, 0x00, + 0x03, 0x00, 0x86, 0x06, 0x00, 0x04, 0x00, 0xb6, + 0x06, 0x00, 0x05, 0x00, 0x9c, 0x07, 0x00, 0x06, + 0x00, 0x9e, 0x07, 0x04, 0x00, 0x30, 0xa0, 0x07, + 0x00, 0x07, 0x00, 0xa2, 0x07, 0x00, 0x09, 0x00, + 0xa4, 0x07, 0x0d, 0x00, 0x21, 0xac, 0x05, 0x69, + 0x00, 0xae, 0x05, 0x6a, 0x00, 0xaa, 0x05, 0x68, + 0x00, 0xfc, 0x03, 0x11, 0x00, 0xbc, 0x02, 0x00, + 0x00, 0x0c, 0x43, 0x02, 0x01, 0xa4, 0x07, 0x02, + 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x34, 0x02, + 0x92, 0x06, 0x00, 0x01, 0x00, 0xaa, 0x06, 0x00, + 0x01, 0x00, 0xd7, 0xba, 0x46, 0xd8, 0xba, 0x46, + 0xac, 0xf0, 0x1b, 0xd7, 0xba, 0x46, 0x04, 0x8b, + 0x01, 0x00, 0x00, 0xab, 0xf0, 0x03, 0xbb, 0x28, + 0xd8, 0xba, 0x46, 0x04, 0x8b, 0x01, 0x00, 0x00, + 0xab, 0xf0, 0x03, 0xb9, 0x28, 0xd7, 0xd8, 0xa5, + 0xf0, 0x03, 0xb9, 0x28, 0xd7, 0xd8, 0xa7, 0xf0, + 0x04, 0xbb, 0x8c, 0x28, 0xba, 0x28, 0xe3, 0xd7, + 0xd8, 0xf6, 0xcf, 0xe4, 0xd7, 0xd8, 0xcb, 0xef, + 0x9d, 0xf6, 0xd1, 0x26, 0x00, 0x00, 0xd2, 0xe5, + 0xd7, 0xd8, 0xf6, 0x95, 0xf0, 0x2b, 0x60, 0x07, + 0x00, 0xe6, 0x7e, 0xf2, 0x1e, 0xc8, 0x07, 0x61, + 0x07, 0x00, 0x41, 0xd3, 0x01, 0x00, 0x00, 0xcb, + 0x24, 0x01, 0x00, 0xf0, 0x0e, 0xce, 0x41, 0xb2, + 0x01, 0x00, 0x00, 0x61, 0x07, 0x00, 0x24, 0x01, + 0x00, 0x0e, 0x81, 0x00, 0xf0, 0xe0, 0x0e, 0x83, + 0xba, 0xc8, 0x04, 0xcd, 0xd0, 0xc7, 0x04, 0xc2, + 0x0a, 0xa5, 0xf0, 0x6b, 0xcc, 0xf9, 0xf1, 0x67, + 0xcc, 0x06, 0xae, 0xf0, 0x62, 0x5d, 0x04, 0x00, + 0x41, 0xd4, 0x01, 0x00, 0x00, 0xcc, 0x24, 0x01, + 0x00, 0xc8, 0x08, 0xba, 0xc8, 0x05, 0xc7, 0x05, + 0xc7, 0x08, 0xef, 0xa5, 0xf0, 0x38, 0xc7, 0x08, + 0xc7, 0x05, 0x46, 0xc9, 0x09, 0x96, 0x04, 0x4c, + 0x00, 0x00, 0x00, 0xab, 0xf0, 0x24, 0xc6, 0xc7, + 0x09, 0x8c, 0x9c, 0xc7, 0x09, 0xac, 0xf0, 0x1a, + 0xc7, 0x09, 0x41, 0xd3, 0x01, 0x00, 0x00, 0xcb, + 0x24, 0x01, 0x00, 0xf0, 0x0d, 0xce, 0x41, 0xb2, + 0x01, 0x00, 0x00, 0xc7, 0x09, 0x24, 0x01, 0x00, + 0x0e, 0x92, 0x05, 0xf2, 0xc2, 0x5d, 0x04, 0x00, + 0x41, 0x67, 0x00, 0x00, 0x00, 0xcc, 0x24, 0x01, + 0x00, 0xd0, 0x92, 0x04, 0xf2, 0x90, 0xce, 0xef, + 0xbb, 0xa7, 0xf0, 0x51, 0xc5, 0x00, 0xc8, 0x0a, + 0xc5, 0x00, 0x0e, 0xce, 0x41, 0xd5, 0x01, 0x00, + 0x00, 0x61, 0x0a, 0x00, 0x24, 0x01, 0x00, 0x0e, + 0xbb, 0xc9, 0x05, 0xc8, 0x04, 0xc7, 0x04, 0xce, + 0xef, 0xa5, 0xf0, 0x29, 0xce, 0xc7, 0x04, 0x46, + 0xce, 0xc7, 0x04, 0xbb, 0x9d, 0x46, 0xac, 0xf0, + 0x18, 0xce, 0xc7, 0x05, 0x90, 0xc8, 0x05, 0x1b, + 0x11, 0xaf, 0xf1, 0x04, 0x1b, 0x71, 0x1b, 0x1b, + 0xce, 0xc7, 0x04, 0x46, 0x1b, 0x71, 0x1b, 0x48, + 0x92, 0x04, 0xf2, 0xd2, 0xce, 0xc7, 0x05, 0x42, + 0x33, 0x00, 0x00, 0x00, 0x0b, 0xce, 0x4b, 0x7a, + 0x01, 0x00, 0x00, 0xcb, 0xef, 0x4b, 0xaf, 0x01, + 0x00, 0x00, 0xcd, 0x4b, 0xd6, 0x01, 0x00, 0x00, + 0x28, 0x0c, 0x43, 0x02, 0x01, 0xb2, 0x05, 0x00, + 0x0d, 0x00, 0x07, 0x00, 0x0a, 0x00, 0xa1, 0x03, + 0x0d, 0xf4, 0x05, 0x00, 0x00, 0x00, 0xae, 0x07, + 0x00, 0x01, 0x00, 0xf6, 0x06, 0x00, 0x02, 0x00, + 0x86, 0x06, 0x00, 0x03, 0x00, 0xb6, 0x06, 0x00, + 0x04, 0x00, 0xa0, 0x06, 0x00, 0x05, 0x00, 0xb0, + 0x07, 0x00, 0x06, 0x00, 0xb2, 0x07, 0x00, 0x07, + 0x00, 0xb4, 0x07, 0x00, 0x08, 0x00, 0xb6, 0x07, + 0x00, 0x09, 0x00, 0xb8, 0x07, 0x00, 0x0a, 0x00, + 0xba, 0x07, 0x00, 0x0b, 0x00, 0xbc, 0x07, 0x00, + 0x0c, 0x00, 0xb0, 0x05, 0x6b, 0x00, 0xaa, 0x04, + 0x28, 0x00, 0xac, 0x04, 0x29, 0x00, 0xe2, 0x04, + 0x44, 0x00, 0xb4, 0x04, 0x2d, 0x00, 0xb2, 0x05, + 0x6c, 0x00, 0xcc, 0x02, 0x0b, 0x00, 0xc0, 0x04, + 0x33, 0x00, 0xec, 0x03, 0x00, 0x1a, 0xbe, 0x05, + 0x72, 0x00, 0xe3, 0xe4, 0xe5, 0xf6, 0xd4, 0x40, + 0x7a, 0x01, 0x00, 0x00, 0xd3, 0xef, 0xba, 0xad, + 0xf0, 0x02, 0x29, 0xcb, 0xba, 0x46, 0xd5, 0xef, + 0xc8, 0x05, 0xbb, 0xd2, 0xce, 0xcb, 0xef, 0xa5, + 0xf0, 0x2a, 0xcb, 0xce, 0x46, 0xc8, 0x06, 0xba, + 0xc8, 0x04, 0xc7, 0x04, 0xc7, 0x05, 0xa5, 0xf0, + 0x17, 0xc7, 0x06, 0xc7, 0x04, 0x46, 0xcd, 0xc7, + 0x04, 0x46, 0xae, 0xf0, 0x07, 0xc7, 0x04, 0xc8, + 0x05, 0xf2, 0x05, 0x92, 0x04, 0xf2, 0xe4, 0x92, + 0x03, 0xf2, 0xd2, 0xcc, 0x40, 0xaf, 0x01, 0x00, + 0x00, 0xd2, 0xce, 0xc7, 0x05, 0xa5, 0xf0, 0x0b, + 0xe6, 0xcd, 0xce, 0x46, 0xf5, 0x0e, 0x92, 0x03, + 0xf2, 0xf1, 0x5d, 0x04, 0x00, 0x5d, 0x05, 0x00, + 0xad, 0xf0, 0x54, 0xcb, 0xef, 0xbb, 0xab, 0xf0, + 0x4e, 0xcb, 0xba, 0x46, 0xd1, 0xcc, 0x40, 0xd6, + 0x01, 0x00, 0x00, 0xcd, 0x46, 0xc9, 0x0c, 0xfb, + 0xf0, 0x1a, 0xe6, 0x04, 0xdf, 0x01, 0x00, 0x00, + 0xf5, 0x0e, 0xc7, 0x0c, 0xef, 0xba, 0xab, 0xf0, + 0x2e, 0xe6, 0x04, 0xe0, 0x01, 0x00, 0x00, 0xf5, + 0x0e, 0xf2, 0x24, 0xc7, 0x0c, 0x96, 0x04, 0x4d, + 0x00, 0x00, 0x00, 0xab, 0x11, 0xf1, 0x0e, 0x0e, + 0xc7, 0x0c, 0xfa, 0xf0, 0x12, 0xcd, 0x04, 0x08, + 0x00, 0x00, 0x00, 0xab, 0xf0, 0x09, 0xe6, 0x04, + 0xbe, 0x01, 0x00, 0x00, 0xf5, 0x0e, 0x5d, 0x04, + 0x00, 0x5d, 0x05, 0x00, 0xad, 0x68, 0xdc, 0x00, + 0x00, 0x00, 0xcb, 0xef, 0xbc, 0xa8, 0x68, 0xd3, + 0x00, 0x00, 0x00, 0xba, 0xc8, 0x07, 0xba, 0xd2, + 0xce, 0xcb, 0xef, 0xa5, 0xf0, 0x18, 0x5d, 0x06, + 0x00, 0x41, 0xe1, 0x01, 0x00, 0x00, 0xc7, 0x07, + 0xcb, 0xce, 0x46, 0xef, 0x24, 0x02, 0x00, 0xc8, + 0x07, 0x92, 0x03, 0xf2, 0xe4, 0xbc, 0x93, 0x07, + 0x5d, 0x06, 0x00, 0x41, 0xe1, 0x01, 0x00, 0x00, + 0xbb, 0x5d, 0x06, 0x00, 0x41, 0xe2, 0x01, 0x00, + 0x00, 0x5d, 0x07, 0x00, 0xbb, 0x9c, 0xc7, 0x07, + 0x9a, 0x24, 0x01, 0x00, 0x24, 0x02, 0x00, 0xc8, + 0x09, 0x5d, 0x06, 0x00, 0x41, 0xe3, 0x01, 0x00, + 0x00, 0xcb, 0xef, 0xc7, 0x09, 0x9a, 0x24, 0x01, + 0x00, 0xc8, 0x0b, 0x64, 0x08, 0x00, 0x41, 0x9d, + 0x01, 0x00, 0x00, 0x04, 0xa4, 0x01, 0x00, 0x00, + 0x24, 0x01, 0x00, 0x0e, 0xba, 0xc8, 0x0a, 0xc7, + 0x0a, 0xc7, 0x0b, 0xa5, 0xf0, 0x58, 0xba, 0xc8, + 0x08, 0xc7, 0x08, 0xc7, 0x09, 0xa5, 0xf0, 0x39, + 0xc7, 0x08, 0xc7, 0x0b, 0x99, 0xc7, 0x0a, 0x9c, + 0xd6, 0xcb, 0xef, 0xa8, 0xf1, 0x2b, 0xcb, 0xce, + 0x46, 0xd1, 0xc7, 0x08, 0xc7, 0x09, 0xbb, 0x9d, + 0xac, 0xf0, 0x0d, 0xcd, 0x41, 0xe4, 0x01, 0x00, + 0x00, 0xc7, 0x07, 0x24, 0x01, 0x00, 0xd1, 0x64, + 0x08, 0x00, 0x41, 0x9d, 0x01, 0x00, 0x00, 0xcd, + 0x24, 0x01, 0x00, 0x0e, 0x92, 0x08, 0xf2, 0xc2, 0x64, 0x08, 0x00, 0x41, 0x9d, 0x01, 0x00, 0x00, 0x04, 0xa4, 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, - 0x0e, 0xba, 0xc8, 0x0a, 0xc7, 0x0a, 0xc7, 0x0b, - 0xa5, 0xf0, 0x58, 0xba, 0xc8, 0x08, 0xc7, 0x08, - 0xc7, 0x09, 0xa5, 0xf0, 0x39, 0xc7, 0x08, 0xc7, - 0x0b, 0x99, 0xc7, 0x0a, 0x9c, 0xd6, 0xcb, 0xef, - 0xa8, 0xf1, 0x2b, 0xcb, 0xce, 0x46, 0xd1, 0xc7, - 0x08, 0xc7, 0x09, 0xbb, 0x9d, 0xac, 0xf0, 0x0d, - 0xcd, 0x41, 0xe4, 0x01, 0x00, 0x00, 0xc7, 0x07, - 0x24, 0x01, 0x00, 0xd1, 0x64, 0x08, 0x00, 0x41, - 0x9d, 0x01, 0x00, 0x00, 0xcd, 0x24, 0x01, 0x00, - 0x0e, 0x92, 0x08, 0xf2, 0xc2, 0x64, 0x08, 0x00, - 0x41, 0x9d, 0x01, 0x00, 0x00, 0x04, 0xa4, 0x01, - 0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, 0x92, 0x0a, - 0xf2, 0xa3, 0x5d, 0x09, 0x00, 0xf4, 0x0e, 0x29, - 0x0c, 0x43, 0x02, 0x01, 0xb6, 0x05, 0x02, 0x01, - 0x02, 0x02, 0x00, 0x00, 0x00, 0x10, 0x03, 0x9e, - 0x06, 0x00, 0x01, 0x00, 0xca, 0x07, 0x00, 0x01, - 0x00, 0xae, 0x07, 0x00, 0x00, 0x00, 0xc6, 0xcf, - 0xd8, 0x8f, 0xdc, 0xba, 0xa7, 0xf0, 0x06, 0xd7, - 0x93, 0x00, 0xf2, 0xf5, 0xcb, 0x28, 0x0c, 0x43, - 0x02, 0x01, 0xbe, 0x05, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x07, 0x00, 0x1e, 0x00, 0xec, 0x03, 0x00, - 0x1a, 0x9a, 0x04, 0x20, 0x00, 0xd4, 0x04, 0x3d, - 0x00, 0xc0, 0x04, 0x33, 0x00, 0xc2, 0x04, 0x34, - 0x00, 0xae, 0x04, 0x2a, 0x00, 0xb0, 0x04, 0x2b, - 0x00, 0x64, 0x00, 0x00, 0x41, 0x9d, 0x01, 0x00, - 0x00, 0xe4, 0x24, 0x01, 0x00, 0x0e, 0xe5, 0xe4, - 0xf5, 0xe6, 0x9b, 0x5e, 0x04, 0x00, 0xc6, 0x5e, - 0x05, 0x00, 0xba, 0x5e, 0x06, 0x00, 0x29, 0x0c, - 0x43, 0x02, 0x01, 0xc0, 0x05, 0x02, 0x01, 0x02, - 0x05, 0x00, 0x11, 0x00, 0x80, 0x01, 0x03, 0xcc, - 0x07, 0x00, 0x01, 0x00, 0xce, 0x07, 0x00, 0x01, - 0x00, 0xb0, 0x07, 0x00, 0x00, 0x00, 0xaa, 0x04, - 0x28, 0x00, 0xac, 0x04, 0x29, 0x00, 0x92, 0x04, - 0x1c, 0x00, 0x94, 0x04, 0x1d, 0x00, 0xbc, 0x05, - 0x71, 0x00, 0x98, 0x04, 0x1f, 0x00, 0x9a, 0x04, - 0x20, 0x00, 0xa6, 0x04, 0x26, 0x00, 0xb6, 0x05, - 0x6e, 0x00, 0x9c, 0x04, 0x21, 0x00, 0xa0, 0x04, - 0x23, 0x00, 0x86, 0x04, 0x16, 0x00, 0xa4, 0x04, - 0x25, 0x00, 0x9e, 0x04, 0x22, 0x00, 0xbe, 0x05, - 0x72, 0x00, 0xe0, 0x04, 0x43, 0x00, 0xba, 0x05, - 0x70, 0x00, 0xd7, 0x11, 0xf1, 0x03, 0x0e, 0xc6, - 0xeb, 0xef, 0xe8, 0xe5, 0xef, 0xea, 0xd8, 0x5e, - 0x04, 0x00, 0x5d, 0x05, 0x00, 0x5e, 0x06, 0x00, - 0x5d, 0x07, 0x00, 0xf0, 0x22, 0x5d, 0x06, 0x00, - 0x5d, 0x08, 0x00, 0x04, 0xe8, 0x01, 0x00, 0x00, - 0x5d, 0x09, 0x00, 0x5d, 0x06, 0x00, 0xef, 0x9d, - 0xf6, 0x9c, 0x5f, 0x06, 0x00, 0x5d, 0x0a, 0x00, - 0x9c, 0x5e, 0x06, 0x00, 0xf2, 0x36, 0x5d, 0x0b, - 0x00, 0xf0, 0x20, 0x5d, 0x0c, 0x00, 0xc3, 0xe8, - 0x03, 0x9a, 0xcf, 0x5d, 0x06, 0x00, 0xcb, 0x41, - 0xe9, 0x01, 0x00, 0x00, 0xc0, 0x24, 0x01, 0x00, - 0x04, 0xe8, 0x01, 0x00, 0x00, 0x9c, 0x9c, 0x5e, - 0x06, 0x00, 0x5d, 0x06, 0x00, 0xef, 0x5e, 0x09, - 0x00, 0x5d, 0x06, 0x00, 0x5d, 0x0d, 0x00, 0x9c, - 0x5e, 0x06, 0x00, 0x5d, 0x0e, 0x00, 0xf4, 0x0e, - 0x5d, 0x0f, 0x00, 0xf4, 0x0e, 0xba, 0x5e, 0x10, - 0x00, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xc2, 0x05, - 0x01, 0x01, 0x01, 0x03, 0x00, 0x04, 0x02, 0x86, - 0x01, 0x02, 0xd4, 0x07, 0x00, 0x01, 0x00, 0x8c, - 0x06, 0x00, 0x00, 0x00, 0xc4, 0x02, 0x01, 0x00, - 0xba, 0x05, 0x70, 0x00, 0xb8, 0x05, 0x6f, 0x00, - 0xc4, 0x05, 0x75, 0x00, 0x07, 0x02, 0x30, 0x07, - 0x02, 0x39, 0xe3, 0x41, 0xeb, 0x01, 0x00, 0x00, - 0xd7, 0x24, 0x01, 0x00, 0xcf, 0xe4, 0x11, 0xba, - 0xad, 0xf0, 0x14, 0xcb, 0x04, 0xec, 0x01, 0x00, - 0x00, 0xab, 0xf0, 0x06, 0xcb, 0xe9, 0xbb, 0xe8, - 0x29, 0xe6, 0xcb, 0xf5, 0x0e, 0x29, 0x11, 0xbb, - 0xad, 0xf0, 0x24, 0xe5, 0xcb, 0x9c, 0xe9, 0xcb, - 0x04, 0xed, 0x01, 0x00, 0x00, 0xab, 0xf0, 0x04, - 0xbc, 0xe8, 0x29, 0xcb, 0x04, 0xee, 0x01, 0x00, - 0x00, 0xab, 0xf0, 0x04, 0xbd, 0xe8, 0x29, 0xe6, - 0xe5, 0xf5, 0x0e, 0xba, 0xe8, 0x29, 0x11, 0xbc, - 0xad, 0xf0, 0x26, 0xe5, 0xcb, 0x9c, 0xe9, 0xcb, - 0x04, 0xef, 0x01, 0x00, 0x00, 0xab, 0x11, 0xf1, - 0x0e, 0x0e, 0xcb, 0xc4, 0x00, 0xa8, 0x11, 0xf0, - 0x06, 0x0e, 0xcb, 0xc4, 0x01, 0xa6, 0x95, 0xf0, - 0x17, 0xe6, 0xe5, 0xf5, 0x0e, 0xba, 0xe8, 0x29, - 0x11, 0xbd, 0xad, 0xf0, 0x0b, 0xe5, 0xcb, 0x9c, - 0xe9, 0xe6, 0xe5, 0xf5, 0x0e, 0xba, 0xe8, 0x29, - 0x0c, 0x43, 0x02, 0x01, 0xc4, 0x05, 0x01, 0x01, - 0x01, 0x05, 0x00, 0x0e, 0x00, 0xb6, 0x01, 0x02, - 0x62, 0x00, 0x01, 0x00, 0xe0, 0x07, 0x00, 0x00, - 0x00, 0xb6, 0x04, 0x2e, 0x00, 0xd4, 0x04, 0x3d, - 0x00, 0xe2, 0x04, 0x44, 0x00, 0xb4, 0x05, 0x6d, - 0x00, 0xb2, 0x04, 0x2c, 0x00, 0xbc, 0x05, 0x71, - 0x00, 0xaa, 0x04, 0x28, 0x00, 0xee, 0x03, 0x01, - 0x1a, 0xbc, 0x04, 0x31, 0x00, 0xee, 0x05, 0x8a, - 0x01, 0x00, 0xb4, 0x04, 0x2d, 0x00, 0xe8, 0x04, - 0x47, 0x00, 0xac, 0x04, 0x29, 0x00, 0xe0, 0x04, - 0x43, 0x00, 0xe3, 0xf0, 0x11, 0xe4, 0xd7, 0xf5, - 0xbb, 0xad, 0xf0, 0x05, 0xe5, 0xd7, 0xf5, 0x0e, - 0x09, 0xe7, 0xf3, 0x80, 0x00, 0xe6, 0xd7, 0x46, - 0xd3, 0xf0, 0x5a, 0xcb, 0x5e, 0x04, 0x00, 0xcb, - 0xd7, 0xf5, 0x11, 0xb9, 0xad, 0xf0, 0x09, 0x5d, - 0x05, 0x00, 0x5d, 0x06, 0x00, 0xf5, 0x29, 0x11, - 0xc2, 0xfe, 0xad, 0xf0, 0x07, 0x5d, 0x05, 0x00, - 0x07, 0xf5, 0x29, 0x11, 0xc2, 0xfd, 0xad, 0xf0, - 0x2b, 0x64, 0x07, 0x00, 0x41, 0x7f, 0x01, 0x00, - 0x00, 0x64, 0x07, 0x00, 0x40, 0x80, 0x01, 0x00, - 0x00, 0x07, 0x24, 0x02, 0x00, 0x0e, 0x64, 0x07, - 0x00, 0x41, 0x81, 0x01, 0x00, 0x00, 0x5d, 0x08, - 0x00, 0x07, 0x24, 0x02, 0x00, 0x0e, 0x5d, 0x09, - 0x00, 0xf4, 0x29, 0x0e, 0x5d, 0x04, 0x00, 0x5e, - 0x0a, 0x00, 0xf2, 0x20, 0xe4, 0xd7, 0xf5, 0xbb, - 0xad, 0xf0, 0x14, 0xd7, 0x04, 0xe8, 0x01, 0x00, - 0x00, 0xa8, 0xf0, 0x0b, 0xe5, 0xd7, 0xf5, 0x0e, - 0xe5, 0x5e, 0x0a, 0x00, 0xf2, 0x06, 0x5d, 0x0b, - 0x00, 0xf4, 0x0e, 0x5d, 0x0c, 0x00, 0xba, 0xa5, - 0xf0, 0x04, 0xba, 0xf2, 0x14, 0x5d, 0x0c, 0x00, - 0x5d, 0x06, 0x00, 0xef, 0xa7, 0xf0, 0x07, 0x5d, - 0x06, 0x00, 0xef, 0xf2, 0x04, 0x5d, 0x0c, 0x00, - 0x5e, 0x0c, 0x00, 0x5d, 0x0d, 0x00, 0xf4, 0x29, - 0x0c, 0x43, 0x02, 0x01, 0xc6, 0x05, 0x02, 0x01, - 0x02, 0x05, 0x00, 0x02, 0x01, 0x70, 0x03, 0x92, - 0x06, 0x00, 0x01, 0x00, 0xe2, 0x07, 0x00, 0x01, - 0x00, 0xf6, 0x06, 0x00, 0x00, 0x00, 0xf4, 0x03, - 0x0d, 0x00, 0xcc, 0x02, 0x0b, 0x00, 0x07, 0x02, - 0x30, 0xe3, 0xd7, 0xf5, 0x95, 0xf0, 0x0a, 0xd7, - 0x41, 0x3b, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, - 0xd7, 0xba, 0xab, 0xf0, 0x15, 0xbb, 0xd7, 0x9a, - 0xba, 0xa5, 0xf0, 0x09, 0x04, 0xf2, 0x01, 0x00, - 0x00, 0xcf, 0xf2, 0x4c, 0xc4, 0x00, 0xcf, 0xf2, - 0x47, 0xd8, 0xc2, 0x10, 0xab, 0xf0, 0x37, 0xd7, - 0xe4, 0x41, 0xe2, 0x01, 0x00, 0x00, 0xd7, 0x24, - 0x01, 0x00, 0xad, 0xf0, 0x29, 0xd7, 0xba, 0xa5, - 0xf0, 0x0c, 0xd7, 0x8b, 0xdb, 0x04, 0xf3, 0x01, - 0x00, 0x00, 0xcf, 0xf2, 0x03, 0xc6, 0xcf, 0xcb, - 0x04, 0xf4, 0x01, 0x00, 0x00, 0xd7, 0x41, 0x3b, - 0x00, 0x00, 0x00, 0xc2, 0x10, 0x24, 0x01, 0x00, - 0x9c, 0x9c, 0xcf, 0xf2, 0x0b, 0xd7, 0x41, 0x3b, - 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0xcf, 0xcb, - 0x28, 0x0c, 0x43, 0x02, 0x01, 0xc8, 0x05, 0x02, - 0x01, 0x02, 0x05, 0x00, 0x00, 0x00, 0x40, 0x03, - 0x92, 0x06, 0x00, 0x01, 0x00, 0xe2, 0x07, 0x00, - 0x01, 0x00, 0xf6, 0x06, 0x00, 0x00, 0x00, 0xd8, - 0xc2, 0x10, 0xab, 0xf0, 0x29, 0xd7, 0xba, 0xa5, - 0xf0, 0x0c, 0xd7, 0x8b, 0xdb, 0x04, 0xf3, 0x01, - 0x00, 0x00, 0xcf, 0xf2, 0x03, 0xc6, 0xcf, 0xcb, - 0x04, 0xf4, 0x01, 0x00, 0x00, 0xd7, 0x41, 0x3b, - 0x00, 0x00, 0x00, 0xc2, 0x10, 0x24, 0x01, 0x00, - 0x9c, 0x9c, 0xcf, 0xf2, 0x0b, 0xd7, 0x41, 0x3b, - 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0xcf, 0xcb, - 0x04, 0xa0, 0x01, 0x00, 0x00, 0x9c, 0x28, 0x0c, - 0x43, 0x02, 0x01, 0x00, 0x04, 0x18, 0x04, 0x06, - 0x19, 0x12, 0x0e, 0xea, 0x01, 0x1c, 0xea, 0x07, - 0x00, 0x01, 0x00, 0x8a, 0x04, 0x00, 0x01, 0x40, - 0x0a, 0xec, 0x07, 0x00, 0x01, 0x40, 0x07, 0xee, - 0x07, 0x00, 0x01, 0x40, 0x0d, 0xf0, 0x07, 0x00, - 0x00, 0x00, 0x8c, 0x01, 0x00, 0x01, 0x00, 0xf2, - 0x07, 0x00, 0x02, 0x40, 0x15, 0xf4, 0x07, 0x00, - 0x03, 0x40, 0x09, 0xf6, 0x07, 0x00, 0x04, 0x40, - 0x0c, 0xf8, 0x07, 0x00, 0x05, 0x40, 0x02, 0xfa, - 0x07, 0x00, 0x06, 0x40, 0x04, 0x72, 0x00, 0x07, - 0x40, 0x05, 0xfc, 0x07, 0x00, 0x08, 0x40, 0x00, - 0xfe, 0x07, 0x00, 0x09, 0x40, 0x0f, 0x80, 0x08, - 0x00, 0x0a, 0x40, 0x0e, 0x82, 0x08, 0x00, 0x0b, - 0x40, 0x03, 0x84, 0x08, 0x00, 0x0c, 0x40, 0x01, - 0x86, 0x08, 0x00, 0x0d, 0x40, 0x0b, 0x88, 0x08, - 0x00, 0x0e, 0x40, 0x06, 0x8a, 0x08, 0x00, 0x0f, - 0x40, 0x08, 0x8c, 0x08, 0x00, 0x10, 0x40, 0x10, - 0x8e, 0x08, 0x00, 0x11, 0x40, 0x13, 0x90, 0x08, - 0x00, 0x12, 0x40, 0x14, 0x92, 0x08, 0x00, 0x13, - 0x40, 0x11, 0x94, 0x08, 0x00, 0x14, 0x40, 0x12, - 0x96, 0x08, 0x00, 0x15, 0x40, 0x16, 0x98, 0x08, - 0x00, 0x16, 0x40, 0x17, 0x9a, 0x08, 0x00, 0x17, - 0x40, 0x18, 0xf8, 0x03, 0x0f, 0x00, 0xce, 0x02, - 0x0c, 0x00, 0xbc, 0x02, 0x00, 0x00, 0xc6, 0x05, - 0x76, 0x00, 0x8e, 0x04, 0x1a, 0x00, 0xc8, 0x05, - 0x77, 0x00, 0xc4, 0x02, 0x01, 0x00, 0xd0, 0x02, - 0x07, 0x00, 0xd8, 0x02, 0x08, 0x00, 0xc6, 0x02, - 0x03, 0x00, 0xc2, 0x02, 0x02, 0x00, 0xf8, 0x02, - 0x04, 0x00, 0xbe, 0x02, 0x06, 0x00, 0xe2, 0x02, - 0x05, 0x00, 0xfe, 0x03, 0x12, 0x00, 0x82, 0x04, - 0x14, 0x00, 0xcc, 0x02, 0x0b, 0x00, 0xc0, 0x04, - 0x33, 0x00, 0x0c, 0x43, 0x02, 0x01, 0x8c, 0x01, - 0x02, 0x00, 0x02, 0x01, 0x00, 0x01, 0x00, 0x0e, - 0x02, 0x9c, 0x08, 0x00, 0x01, 0x00, 0x9e, 0x08, - 0x00, 0x01, 0x00, 0xf8, 0x03, 0x00, 0x02, 0xd7, - 0xfa, 0xf0, 0x03, 0xd8, 0x28, 0xd7, 0xf9, 0xf0, - 0x03, 0xe3, 0x28, 0xd7, 0x28, 0x0c, 0x43, 0x02, - 0x01, 0x82, 0x08, 0x01, 0x00, 0x01, 0x04, 0x00, - 0x01, 0x00, 0x54, 0x01, 0xf6, 0x06, 0x00, 0x01, - 0x00, 0xce, 0x02, 0x01, 0x02, 0xd7, 0x41, 0x8e, - 0x01, 0x00, 0x00, 0x04, 0xc6, 0x01, 0x00, 0x00, - 0x24, 0x01, 0x00, 0xf0, 0x0b, 0xe3, 0x41, 0x10, - 0x02, 0x00, 0x00, 0xd7, 0x25, 0x01, 0x00, 0xe3, - 0x41, 0x10, 0x02, 0x00, 0x00, 0xd7, 0x24, 0x01, - 0x00, 0x41, 0xbf, 0x01, 0x00, 0x00, 0xbb, 0xb9, - 0x24, 0x02, 0x00, 0x41, 0x11, 0x02, 0x00, 0x00, - 0x04, 0x12, 0x02, 0x00, 0x00, 0x04, 0xc7, 0x01, - 0x00, 0x00, 0x24, 0x02, 0x00, 0xdb, 0x04, 0xc6, - 0x01, 0x00, 0x00, 0x41, 0x64, 0x00, 0x00, 0x00, - 0xd7, 0x04, 0xc6, 0x01, 0x00, 0x00, 0x25, 0x02, - 0x00, 0x0c, 0x43, 0x02, 0x01, 0x84, 0x08, 0x01, - 0x00, 0x01, 0x04, 0x00, 0x01, 0x00, 0x0d, 0x01, + 0x0e, 0x92, 0x0a, 0xf2, 0xa3, 0x5d, 0x09, 0x00, + 0xf4, 0x0e, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xb6, + 0x05, 0x02, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, + 0x10, 0x03, 0x9e, 0x06, 0x00, 0x01, 0x00, 0xca, + 0x07, 0x00, 0x01, 0x00, 0xae, 0x07, 0x00, 0x00, + 0x00, 0xc6, 0xcf, 0xd8, 0x8f, 0xdc, 0xba, 0xa7, + 0xf0, 0x06, 0xd7, 0x93, 0x00, 0xf2, 0xf5, 0xcb, + 0x28, 0x0c, 0x43, 0x02, 0x01, 0xbe, 0x05, 0x00, + 0x00, 0x00, 0x03, 0x00, 0x07, 0x00, 0x1e, 0x00, + 0xec, 0x03, 0x00, 0x1a, 0x9a, 0x04, 0x20, 0x00, + 0xd4, 0x04, 0x3d, 0x00, 0xc0, 0x04, 0x33, 0x00, + 0xc2, 0x04, 0x34, 0x00, 0xae, 0x04, 0x2a, 0x00, + 0xb0, 0x04, 0x2b, 0x00, 0x64, 0x00, 0x00, 0x41, + 0x9d, 0x01, 0x00, 0x00, 0xe4, 0x24, 0x01, 0x00, + 0x0e, 0xe5, 0xe4, 0xf5, 0xe6, 0x9b, 0x5e, 0x04, + 0x00, 0xc6, 0x5e, 0x05, 0x00, 0xba, 0x5e, 0x06, + 0x00, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xc0, 0x05, + 0x02, 0x01, 0x02, 0x05, 0x00, 0x11, 0x00, 0x80, + 0x01, 0x03, 0xcc, 0x07, 0x00, 0x01, 0x00, 0xce, + 0x07, 0x00, 0x01, 0x00, 0xb0, 0x07, 0x00, 0x00, + 0x00, 0xaa, 0x04, 0x28, 0x00, 0xac, 0x04, 0x29, + 0x00, 0x92, 0x04, 0x1c, 0x00, 0x94, 0x04, 0x1d, + 0x00, 0xbc, 0x05, 0x71, 0x00, 0x98, 0x04, 0x1f, + 0x00, 0x9a, 0x04, 0x20, 0x00, 0xa6, 0x04, 0x26, + 0x00, 0xb6, 0x05, 0x6e, 0x00, 0x9c, 0x04, 0x21, + 0x00, 0xa0, 0x04, 0x23, 0x00, 0x86, 0x04, 0x16, + 0x00, 0xa4, 0x04, 0x25, 0x00, 0x9e, 0x04, 0x22, + 0x00, 0xbe, 0x05, 0x72, 0x00, 0xe0, 0x04, 0x43, + 0x00, 0xba, 0x05, 0x70, 0x00, 0xd7, 0x11, 0xf1, + 0x03, 0x0e, 0xc6, 0xeb, 0xef, 0xe8, 0xe5, 0xef, + 0xea, 0xd8, 0x5e, 0x04, 0x00, 0x5d, 0x05, 0x00, + 0x5e, 0x06, 0x00, 0x5d, 0x07, 0x00, 0xf0, 0x22, + 0x5d, 0x06, 0x00, 0x5d, 0x08, 0x00, 0x04, 0xe8, + 0x01, 0x00, 0x00, 0x5d, 0x09, 0x00, 0x5d, 0x06, + 0x00, 0xef, 0x9d, 0xf6, 0x9c, 0x5f, 0x06, 0x00, + 0x5d, 0x0a, 0x00, 0x9c, 0x5e, 0x06, 0x00, 0xf2, + 0x36, 0x5d, 0x0b, 0x00, 0xf0, 0x20, 0x5d, 0x0c, + 0x00, 0xc3, 0xe8, 0x03, 0x9a, 0xcf, 0x5d, 0x06, + 0x00, 0xcb, 0x41, 0xe9, 0x01, 0x00, 0x00, 0xc0, + 0x24, 0x01, 0x00, 0x04, 0xe8, 0x01, 0x00, 0x00, + 0x9c, 0x9c, 0x5e, 0x06, 0x00, 0x5d, 0x06, 0x00, + 0xef, 0x5e, 0x09, 0x00, 0x5d, 0x06, 0x00, 0x5d, + 0x0d, 0x00, 0x9c, 0x5e, 0x06, 0x00, 0x5d, 0x0e, + 0x00, 0xf4, 0x0e, 0x5d, 0x0f, 0x00, 0xf4, 0x0e, + 0xba, 0x5e, 0x10, 0x00, 0x29, 0x0c, 0x43, 0x02, + 0x01, 0xc2, 0x05, 0x01, 0x01, 0x01, 0x03, 0x00, + 0x04, 0x02, 0x86, 0x01, 0x02, 0xd4, 0x07, 0x00, + 0x01, 0x00, 0x8c, 0x06, 0x00, 0x00, 0x00, 0xc4, + 0x02, 0x01, 0x00, 0xba, 0x05, 0x70, 0x00, 0xb8, + 0x05, 0x6f, 0x00, 0xc4, 0x05, 0x75, 0x00, 0x07, + 0x02, 0x30, 0x07, 0x02, 0x39, 0xe3, 0x41, 0xeb, + 0x01, 0x00, 0x00, 0xd7, 0x24, 0x01, 0x00, 0xcf, + 0xe4, 0x11, 0xba, 0xad, 0xf0, 0x14, 0xcb, 0x04, + 0xec, 0x01, 0x00, 0x00, 0xab, 0xf0, 0x06, 0xcb, + 0xe9, 0xbb, 0xe8, 0x29, 0xe6, 0xcb, 0xf5, 0x0e, + 0x29, 0x11, 0xbb, 0xad, 0xf0, 0x24, 0xe5, 0xcb, + 0x9c, 0xe9, 0xcb, 0x04, 0xed, 0x01, 0x00, 0x00, + 0xab, 0xf0, 0x04, 0xbc, 0xe8, 0x29, 0xcb, 0x04, + 0xee, 0x01, 0x00, 0x00, 0xab, 0xf0, 0x04, 0xbd, + 0xe8, 0x29, 0xe6, 0xe5, 0xf5, 0x0e, 0xba, 0xe8, + 0x29, 0x11, 0xbc, 0xad, 0xf0, 0x26, 0xe5, 0xcb, + 0x9c, 0xe9, 0xcb, 0x04, 0xef, 0x01, 0x00, 0x00, + 0xab, 0x11, 0xf1, 0x0e, 0x0e, 0xcb, 0xc4, 0x00, + 0xa8, 0x11, 0xf0, 0x06, 0x0e, 0xcb, 0xc4, 0x01, + 0xa6, 0x95, 0xf0, 0x17, 0xe6, 0xe5, 0xf5, 0x0e, + 0xba, 0xe8, 0x29, 0x11, 0xbd, 0xad, 0xf0, 0x0b, + 0xe5, 0xcb, 0x9c, 0xe9, 0xe6, 0xe5, 0xf5, 0x0e, + 0xba, 0xe8, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xc4, + 0x05, 0x01, 0x01, 0x01, 0x05, 0x00, 0x0e, 0x00, + 0xb6, 0x01, 0x02, 0x62, 0x00, 0x01, 0x00, 0xe0, + 0x07, 0x00, 0x00, 0x00, 0xb6, 0x04, 0x2e, 0x00, + 0xd4, 0x04, 0x3d, 0x00, 0xe2, 0x04, 0x44, 0x00, + 0xb4, 0x05, 0x6d, 0x00, 0xb2, 0x04, 0x2c, 0x00, + 0xbc, 0x05, 0x71, 0x00, 0xaa, 0x04, 0x28, 0x00, + 0xee, 0x03, 0x01, 0x1a, 0xbc, 0x04, 0x31, 0x00, + 0xee, 0x05, 0x8a, 0x01, 0x00, 0xb4, 0x04, 0x2d, + 0x00, 0xe8, 0x04, 0x47, 0x00, 0xac, 0x04, 0x29, + 0x00, 0xe0, 0x04, 0x43, 0x00, 0xe3, 0xf0, 0x11, + 0xe4, 0xd7, 0xf5, 0xbb, 0xad, 0xf0, 0x05, 0xe5, + 0xd7, 0xf5, 0x0e, 0x09, 0xe7, 0xf3, 0x80, 0x00, + 0xe6, 0xd7, 0x46, 0xd3, 0xf0, 0x5a, 0xcb, 0x5e, + 0x04, 0x00, 0xcb, 0xd7, 0xf5, 0x11, 0xb9, 0xad, + 0xf0, 0x09, 0x5d, 0x05, 0x00, 0x5d, 0x06, 0x00, + 0xf5, 0x29, 0x11, 0xc2, 0xfe, 0xad, 0xf0, 0x07, + 0x5d, 0x05, 0x00, 0x07, 0xf5, 0x29, 0x11, 0xc2, + 0xfd, 0xad, 0xf0, 0x2b, 0x64, 0x07, 0x00, 0x41, + 0x7f, 0x01, 0x00, 0x00, 0x64, 0x07, 0x00, 0x40, + 0x80, 0x01, 0x00, 0x00, 0x07, 0x24, 0x02, 0x00, + 0x0e, 0x64, 0x07, 0x00, 0x41, 0x81, 0x01, 0x00, + 0x00, 0x5d, 0x08, 0x00, 0x07, 0x24, 0x02, 0x00, + 0x0e, 0x5d, 0x09, 0x00, 0xf4, 0x29, 0x0e, 0x5d, + 0x04, 0x00, 0x5e, 0x0a, 0x00, 0xf2, 0x20, 0xe4, + 0xd7, 0xf5, 0xbb, 0xad, 0xf0, 0x14, 0xd7, 0x04, + 0xe8, 0x01, 0x00, 0x00, 0xa8, 0xf0, 0x0b, 0xe5, + 0xd7, 0xf5, 0x0e, 0xe5, 0x5e, 0x0a, 0x00, 0xf2, + 0x06, 0x5d, 0x0b, 0x00, 0xf4, 0x0e, 0x5d, 0x0c, + 0x00, 0xba, 0xa5, 0xf0, 0x04, 0xba, 0xf2, 0x14, + 0x5d, 0x0c, 0x00, 0x5d, 0x06, 0x00, 0xef, 0xa7, + 0xf0, 0x07, 0x5d, 0x06, 0x00, 0xef, 0xf2, 0x04, + 0x5d, 0x0c, 0x00, 0x5e, 0x0c, 0x00, 0x5d, 0x0d, + 0x00, 0xf4, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xc6, + 0x05, 0x02, 0x01, 0x02, 0x05, 0x00, 0x02, 0x01, + 0x70, 0x03, 0x92, 0x06, 0x00, 0x01, 0x00, 0xe2, + 0x07, 0x00, 0x01, 0x00, 0xf6, 0x06, 0x00, 0x00, + 0x00, 0xf4, 0x03, 0x0d, 0x00, 0xcc, 0x02, 0x0b, + 0x00, 0x07, 0x02, 0x30, 0xe3, 0xd7, 0xf5, 0x95, + 0xf0, 0x0a, 0xd7, 0x41, 0x3b, 0x00, 0x00, 0x00, + 0x25, 0x00, 0x00, 0xd7, 0xba, 0xab, 0xf0, 0x15, + 0xbb, 0xd7, 0x9a, 0xba, 0xa5, 0xf0, 0x09, 0x04, + 0xf2, 0x01, 0x00, 0x00, 0xcf, 0xf2, 0x4c, 0xc4, + 0x00, 0xcf, 0xf2, 0x47, 0xd8, 0xc2, 0x10, 0xab, + 0xf0, 0x37, 0xd7, 0xe4, 0x41, 0xe2, 0x01, 0x00, + 0x00, 0xd7, 0x24, 0x01, 0x00, 0xad, 0xf0, 0x29, + 0xd7, 0xba, 0xa5, 0xf0, 0x0c, 0xd7, 0x8b, 0xdb, + 0x04, 0xf3, 0x01, 0x00, 0x00, 0xcf, 0xf2, 0x03, + 0xc6, 0xcf, 0xcb, 0x04, 0xf4, 0x01, 0x00, 0x00, + 0xd7, 0x41, 0x3b, 0x00, 0x00, 0x00, 0xc2, 0x10, + 0x24, 0x01, 0x00, 0x9c, 0x9c, 0xcf, 0xf2, 0x0b, + 0xd7, 0x41, 0x3b, 0x00, 0x00, 0x00, 0x24, 0x00, + 0x00, 0xcf, 0xcb, 0x28, 0x0c, 0x43, 0x02, 0x01, + 0xc8, 0x05, 0x02, 0x01, 0x02, 0x05, 0x00, 0x00, + 0x00, 0x40, 0x03, 0x92, 0x06, 0x00, 0x01, 0x00, + 0xe2, 0x07, 0x00, 0x01, 0x00, 0xf6, 0x06, 0x00, + 0x00, 0x00, 0xd8, 0xc2, 0x10, 0xab, 0xf0, 0x29, + 0xd7, 0xba, 0xa5, 0xf0, 0x0c, 0xd7, 0x8b, 0xdb, + 0x04, 0xf3, 0x01, 0x00, 0x00, 0xcf, 0xf2, 0x03, + 0xc6, 0xcf, 0xcb, 0x04, 0xf4, 0x01, 0x00, 0x00, + 0xd7, 0x41, 0x3b, 0x00, 0x00, 0x00, 0xc2, 0x10, + 0x24, 0x01, 0x00, 0x9c, 0x9c, 0xcf, 0xf2, 0x0b, + 0xd7, 0x41, 0x3b, 0x00, 0x00, 0x00, 0x24, 0x00, + 0x00, 0xcf, 0xcb, 0x04, 0xa0, 0x01, 0x00, 0x00, + 0x9c, 0x28, 0x0c, 0x43, 0x02, 0x01, 0x00, 0x04, + 0x18, 0x04, 0x06, 0x19, 0x12, 0x0e, 0xea, 0x01, + 0x1c, 0xea, 0x07, 0x00, 0x01, 0x00, 0x8a, 0x04, + 0x00, 0x01, 0x40, 0x0a, 0xec, 0x07, 0x00, 0x01, + 0x40, 0x07, 0xee, 0x07, 0x00, 0x01, 0x40, 0x0d, + 0xf0, 0x07, 0x00, 0x00, 0x00, 0x8c, 0x01, 0x00, + 0x01, 0x00, 0xf2, 0x07, 0x00, 0x02, 0x40, 0x15, + 0xf4, 0x07, 0x00, 0x03, 0x40, 0x09, 0xf6, 0x07, + 0x00, 0x04, 0x40, 0x0c, 0xf8, 0x07, 0x00, 0x05, + 0x40, 0x02, 0xfa, 0x07, 0x00, 0x06, 0x40, 0x04, + 0x72, 0x00, 0x07, 0x40, 0x05, 0xfc, 0x07, 0x00, + 0x08, 0x40, 0x00, 0xfe, 0x07, 0x00, 0x09, 0x40, + 0x0f, 0x80, 0x08, 0x00, 0x0a, 0x40, 0x0e, 0x82, + 0x08, 0x00, 0x0b, 0x40, 0x03, 0x84, 0x08, 0x00, + 0x0c, 0x40, 0x01, 0x86, 0x08, 0x00, 0x0d, 0x40, + 0x0b, 0x88, 0x08, 0x00, 0x0e, 0x40, 0x06, 0x8a, + 0x08, 0x00, 0x0f, 0x40, 0x08, 0x8c, 0x08, 0x00, + 0x10, 0x40, 0x10, 0x8e, 0x08, 0x00, 0x11, 0x40, + 0x13, 0x90, 0x08, 0x00, 0x12, 0x40, 0x14, 0x92, + 0x08, 0x00, 0x13, 0x40, 0x11, 0x94, 0x08, 0x00, + 0x14, 0x40, 0x12, 0x96, 0x08, 0x00, 0x15, 0x40, + 0x16, 0x98, 0x08, 0x00, 0x16, 0x40, 0x17, 0x9a, + 0x08, 0x00, 0x17, 0x40, 0x18, 0xf8, 0x03, 0x0f, + 0x00, 0xce, 0x02, 0x0c, 0x00, 0xbc, 0x02, 0x00, + 0x00, 0xc6, 0x05, 0x76, 0x00, 0x8e, 0x04, 0x1a, + 0x00, 0xc8, 0x05, 0x77, 0x00, 0xc4, 0x02, 0x01, + 0x00, 0xd0, 0x02, 0x07, 0x00, 0xd8, 0x02, 0x08, + 0x00, 0xc6, 0x02, 0x03, 0x00, 0xc2, 0x02, 0x02, + 0x00, 0xf8, 0x02, 0x04, 0x00, 0xbe, 0x02, 0x06, + 0x00, 0xe2, 0x02, 0x05, 0x00, 0xfe, 0x03, 0x12, + 0x00, 0x82, 0x04, 0x14, 0x00, 0xcc, 0x02, 0x0b, + 0x00, 0xc0, 0x04, 0x33, 0x00, 0x0c, 0x43, 0x02, + 0x01, 0x8c, 0x01, 0x02, 0x00, 0x02, 0x01, 0x00, + 0x01, 0x00, 0x0e, 0x02, 0x9c, 0x08, 0x00, 0x01, + 0x00, 0x9e, 0x08, 0x00, 0x01, 0x00, 0xf8, 0x03, + 0x00, 0x02, 0xd7, 0xfa, 0xf0, 0x03, 0xd8, 0x28, + 0xd7, 0xf9, 0xf0, 0x03, 0xe3, 0x28, 0xd7, 0x28, + 0x0c, 0x43, 0x02, 0x01, 0x82, 0x08, 0x01, 0x00, + 0x01, 0x04, 0x00, 0x01, 0x00, 0x54, 0x01, 0xf6, + 0x06, 0x00, 0x01, 0x00, 0xce, 0x02, 0x01, 0x02, + 0xd7, 0x41, 0x8e, 0x01, 0x00, 0x00, 0x04, 0xc6, + 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, 0xf0, 0x0b, + 0xe3, 0x41, 0x10, 0x02, 0x00, 0x00, 0xd7, 0x25, + 0x01, 0x00, 0xe3, 0x41, 0x10, 0x02, 0x00, 0x00, + 0xd7, 0x24, 0x01, 0x00, 0x41, 0xbf, 0x01, 0x00, + 0x00, 0xbb, 0xb9, 0x24, 0x02, 0x00, 0x41, 0x11, + 0x02, 0x00, 0x00, 0x04, 0x12, 0x02, 0x00, 0x00, + 0x04, 0xc7, 0x01, 0x00, 0x00, 0x24, 0x02, 0x00, + 0xdb, 0x04, 0xc6, 0x01, 0x00, 0x00, 0x41, 0x64, + 0x00, 0x00, 0x00, 0xd7, 0x04, 0xc6, 0x01, 0x00, + 0x00, 0x25, 0x02, 0x00, 0x0c, 0x43, 0x02, 0x01, + 0x84, 0x08, 0x01, 0x00, 0x01, 0x04, 0x00, 0x01, + 0x00, 0x0d, 0x01, 0xf6, 0x06, 0x00, 0x01, 0x00, + 0xfc, 0x07, 0x08, 0x00, 0xe3, 0x41, 0xb2, 0x01, + 0x00, 0x00, 0xc6, 0xd7, 0x9c, 0x24, 0x01, 0x00, + 0x29, 0x0c, 0x43, 0x02, 0x01, 0x86, 0x08, 0x01, + 0x00, 0x01, 0x04, 0x00, 0x01, 0x00, 0x0c, 0x01, 0xf6, 0x06, 0x00, 0x01, 0x00, 0xfc, 0x07, 0x08, - 0x00, 0xe3, 0x41, 0xb2, 0x01, 0x00, 0x00, 0xc6, - 0xd7, 0x9c, 0x24, 0x01, 0x00, 0x29, 0x0c, 0x43, - 0x02, 0x01, 0x86, 0x08, 0x01, 0x00, 0x01, 0x04, - 0x00, 0x01, 0x00, 0x0c, 0x01, 0xf6, 0x06, 0x00, - 0x01, 0x00, 0xfc, 0x07, 0x08, 0x00, 0xe3, 0xe3, - 0xef, 0xbb, 0x9d, 0x72, 0x13, 0x46, 0xd7, 0x9c, - 0x48, 0x29, 0x0c, 0x43, 0x02, 0x01, 0x88, 0x08, - 0x01, 0x00, 0x01, 0x04, 0x00, 0x01, 0x00, 0x1f, - 0x01, 0xa6, 0x08, 0x00, 0x01, 0x00, 0xbc, 0x02, - 0x02, 0x02, 0xe3, 0x40, 0x3f, 0x00, 0x00, 0x00, - 0x40, 0x3b, 0x00, 0x00, 0x00, 0x41, 0x14, 0x02, - 0x00, 0x00, 0xd7, 0x24, 0x01, 0x00, 0x41, 0xbf, - 0x01, 0x00, 0x00, 0xc2, 0x08, 0xb9, 0x25, 0x02, - 0x00, 0x0c, 0x43, 0x02, 0x01, 0x8a, 0x08, 0x02, - 0x13, 0x02, 0x09, 0x00, 0x1a, 0x02, 0xdc, 0x0b, - 0x15, 0x92, 0x06, 0x00, 0x01, 0x00, 0xa8, 0x04, - 0x00, 0x01, 0x00, 0xc0, 0x06, 0x00, 0x00, 0x00, - 0xaa, 0x08, 0x00, 0x01, 0x00, 0x86, 0x06, 0x00, - 0x02, 0x00, 0xac, 0x08, 0x00, 0x03, 0x00, 0x62, - 0x00, 0x04, 0x00, 0xae, 0x08, 0x00, 0x05, 0x00, - 0xb0, 0x08, 0x00, 0x06, 0x00, 0xb2, 0x08, 0x00, - 0x07, 0x00, 0xb4, 0x08, 0x00, 0x08, 0x00, 0xb6, - 0x08, 0x00, 0x09, 0x00, 0xb8, 0x08, 0x00, 0x0a, - 0x00, 0xba, 0x08, 0x00, 0x0b, 0x00, 0xbc, 0x08, - 0x00, 0x0c, 0x00, 0xbe, 0x08, 0x00, 0x0d, 0x00, - 0xc0, 0x08, 0x00, 0x0e, 0x00, 0xa0, 0x06, 0x00, - 0x0f, 0x00, 0xb2, 0x06, 0x00, 0x10, 0x00, 0xc2, - 0x08, 0x00, 0x11, 0x00, 0xc4, 0x08, 0x00, 0x12, - 0x00, 0x84, 0x08, 0x0c, 0x00, 0xc6, 0x05, 0x03, - 0x02, 0x8e, 0x04, 0x04, 0x02, 0xc8, 0x05, 0x05, - 0x02, 0xf8, 0x07, 0x05, 0x00, 0x82, 0x08, 0x0b, - 0x00, 0xc4, 0x02, 0x06, 0x02, 0xfa, 0x07, 0x06, - 0x00, 0x72, 0x07, 0x00, 0xfc, 0x07, 0x08, 0x00, - 0x88, 0x08, 0x0e, 0x00, 0xd0, 0x02, 0x07, 0x02, - 0xce, 0x02, 0x01, 0x02, 0xd8, 0x02, 0x08, 0x02, - 0xc6, 0x02, 0x09, 0x02, 0xc2, 0x02, 0x0a, 0x02, - 0xf8, 0x02, 0x0b, 0x02, 0xbe, 0x02, 0x0c, 0x02, - 0xe2, 0x02, 0x0d, 0x02, 0xec, 0x07, 0x02, 0x01, - 0x8a, 0x08, 0x0f, 0x00, 0xf4, 0x07, 0x03, 0x00, - 0x8a, 0x04, 0x01, 0x01, 0xbc, 0x02, 0x02, 0x02, - 0x86, 0x08, 0x0d, 0x00, 0xf6, 0x07, 0x04, 0x00, - 0x07, 0x32, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x41, - 0x2d, 0x5a, 0x5f, 0x24, 0x5d, 0x5b, 0x30, 0x2d, - 0x39, 0x61, 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x5f, - 0x24, 0x5d, 0x2a, 0x07, 0xaa, 0x01, 0x00, 0x00, - 0x01, 0x00, 0x4d, 0x00, 0x00, 0x00, 0x09, 0x06, - 0x00, 0x00, 0x00, 0x05, 0x08, 0xf5, 0xff, 0xff, - 0xff, 0x0c, 0x00, 0x06, 0x16, 0x04, 0x00, 0x24, - 0x00, 0x24, 0x00, 0x41, 0x00, 0x5a, 0x00, 0x5f, - 0x00, 0x5f, 0x00, 0x61, 0x00, 0x7a, 0x00, 0x1d, - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0x7f, 0x01, 0x00, 0x00, 0x00, - 0x16, 0x05, 0x00, 0x24, 0x00, 0x24, 0x00, 0x30, - 0x00, 0x39, 0x00, 0x41, 0x00, 0x5a, 0x00, 0x5f, - 0x00, 0x5f, 0x00, 0x61, 0x00, 0x7a, 0x00, 0x0b, - 0x0d, 0x00, 0x0b, 0xd7, 0x96, 0xc9, 0x06, 0x11, - 0x04, 0x49, 0x00, 0x00, 0x00, 0xad, 0xf1, 0x0a, - 0x11, 0x04, 0x4b, 0x00, 0x00, 0x00, 0xad, 0xf0, - 0x06, 0xe3, 0xd7, 0xf5, 0x0e, 0x29, 0x11, 0x04, - 0x4a, 0x00, 0x00, 0x00, 0xad, 0xf0, 0x11, 0xe3, - 0xe4, 0xd7, 0xe5, 0xf0, 0x05, 0xc2, 0x10, 0xf2, - 0x03, 0xc2, 0x0a, 0xf6, 0xf5, 0x0e, 0x29, 0x11, - 0x04, 0x96, 0x00, 0x00, 0x00, 0xad, 0xf0, 0x11, - 0xe3, 0xe6, 0xd7, 0xe5, 0xf0, 0x05, 0xc2, 0x10, - 0xf2, 0x03, 0xc2, 0x0a, 0xf6, 0xf5, 0x0e, 0x29, - 0x11, 0x04, 0x4c, 0x00, 0x00, 0x00, 0xad, 0xf0, - 0x26, 0xd7, 0xef, 0x5d, 0x04, 0x00, 0xa7, 0xf0, - 0x15, 0xd7, 0x41, 0x9f, 0x01, 0x00, 0x00, 0xba, - 0x5d, 0x04, 0x00, 0x24, 0x02, 0x00, 0x04, 0x23, - 0x02, 0x00, 0x00, 0x9c, 0xdb, 0xe3, 0x5d, 0x05, - 0x00, 0xd7, 0xf5, 0xf5, 0x0e, 0x29, 0x11, 0x04, - 0x4e, 0x00, 0x00, 0x00, 0xad, 0xf0, 0x0a, 0xe3, - 0x5d, 0x06, 0x00, 0xd7, 0xf5, 0xf5, 0x0e, 0x29, - 0x11, 0x04, 0x4d, 0x00, 0x00, 0x00, 0xad, 0xf1, - 0x0d, 0x11, 0x04, 0x1b, 0x00, 0x00, 0x00, 0xad, - 0x68, 0x35, 0x05, 0x00, 0x00, 0xd7, 0xf9, 0xf0, - 0x06, 0xe3, 0xd7, 0xf5, 0x0e, 0x29, 0x5d, 0x07, - 0x00, 0x41, 0xc5, 0x01, 0x00, 0x00, 0xd7, 0x24, - 0x01, 0x00, 0xd3, 0xba, 0xa8, 0xf0, 0x18, 0xe3, - 0x04, 0x24, 0x02, 0x00, 0x00, 0x41, 0x64, 0x00, - 0x00, 0x00, 0xcb, 0x04, 0xc9, 0x01, 0x00, 0x00, - 0x24, 0x02, 0x00, 0xf5, 0x0e, 0x29, 0x5d, 0x08, - 0x00, 0x41, 0xc5, 0x01, 0x00, 0x00, 0xd7, 0x24, - 0x01, 0x00, 0xd3, 0xba, 0xa8, 0xf0, 0x2c, 0xe3, - 0x04, 0x24, 0x02, 0x00, 0x00, 0x41, 0x64, 0x00, - 0x00, 0x00, 0x5d, 0x07, 0x00, 0xef, 0x04, 0xc9, + 0x00, 0xe3, 0xe3, 0xef, 0xbb, 0x9d, 0x72, 0x13, + 0x46, 0xd7, 0x9c, 0x48, 0x29, 0x0c, 0x43, 0x02, + 0x01, 0x88, 0x08, 0x01, 0x00, 0x01, 0x04, 0x00, + 0x01, 0x00, 0x1f, 0x01, 0xa6, 0x08, 0x00, 0x01, + 0x00, 0xbc, 0x02, 0x02, 0x02, 0xe3, 0x40, 0x3f, + 0x00, 0x00, 0x00, 0x40, 0x3b, 0x00, 0x00, 0x00, + 0x41, 0x14, 0x02, 0x00, 0x00, 0xd7, 0x24, 0x01, + 0x00, 0x41, 0xbf, 0x01, 0x00, 0x00, 0xc2, 0x08, + 0xb9, 0x25, 0x02, 0x00, 0x0c, 0x43, 0x02, 0x01, + 0x8a, 0x08, 0x02, 0x13, 0x02, 0x09, 0x00, 0x1a, + 0x02, 0xdc, 0x0b, 0x15, 0x92, 0x06, 0x00, 0x01, + 0x00, 0xa8, 0x04, 0x00, 0x01, 0x00, 0xc0, 0x06, + 0x00, 0x00, 0x00, 0xaa, 0x08, 0x00, 0x01, 0x00, + 0x86, 0x06, 0x00, 0x02, 0x00, 0xac, 0x08, 0x00, + 0x03, 0x00, 0x62, 0x00, 0x04, 0x00, 0xae, 0x08, + 0x00, 0x05, 0x00, 0xb0, 0x08, 0x00, 0x06, 0x00, + 0xb2, 0x08, 0x00, 0x07, 0x00, 0xb4, 0x08, 0x00, + 0x08, 0x00, 0xb6, 0x08, 0x00, 0x09, 0x00, 0xb8, + 0x08, 0x00, 0x0a, 0x00, 0xba, 0x08, 0x00, 0x0b, + 0x00, 0xbc, 0x08, 0x00, 0x0c, 0x00, 0xbe, 0x08, + 0x00, 0x0d, 0x00, 0xc0, 0x08, 0x00, 0x0e, 0x00, + 0xa0, 0x06, 0x00, 0x0f, 0x00, 0xb2, 0x06, 0x00, + 0x10, 0x00, 0xc2, 0x08, 0x00, 0x11, 0x00, 0xc4, + 0x08, 0x00, 0x12, 0x00, 0x84, 0x08, 0x0c, 0x00, + 0xc6, 0x05, 0x03, 0x02, 0x8e, 0x04, 0x04, 0x02, + 0xc8, 0x05, 0x05, 0x02, 0xf8, 0x07, 0x05, 0x00, + 0x82, 0x08, 0x0b, 0x00, 0xc4, 0x02, 0x06, 0x02, + 0xfa, 0x07, 0x06, 0x00, 0x72, 0x07, 0x00, 0xfc, + 0x07, 0x08, 0x00, 0x88, 0x08, 0x0e, 0x00, 0xd0, + 0x02, 0x07, 0x02, 0xce, 0x02, 0x01, 0x02, 0xd8, + 0x02, 0x08, 0x02, 0xc6, 0x02, 0x09, 0x02, 0xc2, + 0x02, 0x0a, 0x02, 0xf8, 0x02, 0x0b, 0x02, 0xbe, + 0x02, 0x0c, 0x02, 0xe2, 0x02, 0x0d, 0x02, 0xec, + 0x07, 0x02, 0x01, 0x8a, 0x08, 0x0f, 0x00, 0xf4, + 0x07, 0x03, 0x00, 0x8a, 0x04, 0x01, 0x01, 0xbc, + 0x02, 0x02, 0x02, 0x86, 0x08, 0x0d, 0x00, 0xf6, + 0x07, 0x04, 0x00, 0x07, 0x32, 0x5e, 0x5b, 0x61, + 0x2d, 0x7a, 0x41, 0x2d, 0x5a, 0x5f, 0x24, 0x5d, + 0x5b, 0x30, 0x2d, 0x39, 0x61, 0x2d, 0x7a, 0x41, + 0x2d, 0x5a, 0x5f, 0x24, 0x5d, 0x2a, 0x07, 0x9a, + 0x01, 0x00, 0x00, 0x01, 0x00, 0x45, 0x00, 0x00, + 0x00, 0x0e, 0x06, 0x00, 0x00, 0x00, 0x06, 0x0d, + 0xf5, 0xff, 0xff, 0xff, 0x13, 0x00, 0x09, 0x24, + 0x04, 0x00, 0x24, 0x00, 0x24, 0x00, 0x41, 0x00, + 0x5a, 0x00, 0x5f, 0x00, 0x5f, 0x00, 0x61, 0x00, + 0x7a, 0x00, 0x0f, 0x1c, 0x00, 0x00, 0x00, 0x24, + 0x05, 0x00, 0x24, 0x00, 0x24, 0x00, 0x30, 0x00, + 0x39, 0x00, 0x41, 0x00, 0x5a, 0x00, 0x5f, 0x00, + 0x5f, 0x00, 0x61, 0x00, 0x7a, 0x00, 0x0d, 0xdf, + 0xff, 0xff, 0xff, 0x14, 0x00, 0x10, 0xd7, 0x96, + 0xc9, 0x06, 0x11, 0x04, 0x49, 0x00, 0x00, 0x00, + 0xad, 0xf1, 0x0a, 0x11, 0x04, 0x4b, 0x00, 0x00, + 0x00, 0xad, 0xf0, 0x06, 0xe3, 0xd7, 0xf5, 0x0e, + 0x29, 0x11, 0x04, 0x4a, 0x00, 0x00, 0x00, 0xad, + 0xf0, 0x11, 0xe3, 0xe4, 0xd7, 0xe5, 0xf0, 0x05, + 0xc2, 0x10, 0xf2, 0x03, 0xc2, 0x0a, 0xf6, 0xf5, + 0x0e, 0x29, 0x11, 0x04, 0x96, 0x00, 0x00, 0x00, + 0xad, 0xf0, 0x11, 0xe3, 0xe6, 0xd7, 0xe5, 0xf0, + 0x05, 0xc2, 0x10, 0xf2, 0x03, 0xc2, 0x0a, 0xf6, + 0xf5, 0x0e, 0x29, 0x11, 0x04, 0x4c, 0x00, 0x00, + 0x00, 0xad, 0xf0, 0x26, 0xd7, 0xef, 0x5d, 0x04, + 0x00, 0xa7, 0xf0, 0x15, 0xd7, 0x41, 0x9f, 0x01, + 0x00, 0x00, 0xba, 0x5d, 0x04, 0x00, 0x24, 0x02, + 0x00, 0x04, 0x23, 0x02, 0x00, 0x00, 0x9c, 0xdb, + 0xe3, 0x5d, 0x05, 0x00, 0xd7, 0xf5, 0xf5, 0x0e, + 0x29, 0x11, 0x04, 0x4e, 0x00, 0x00, 0x00, 0xad, + 0xf0, 0x0a, 0xe3, 0x5d, 0x06, 0x00, 0xd7, 0xf5, + 0xf5, 0x0e, 0x29, 0x11, 0x04, 0x4d, 0x00, 0x00, + 0x00, 0xad, 0xf1, 0x0d, 0x11, 0x04, 0x1b, 0x00, + 0x00, 0x00, 0xad, 0x68, 0x35, 0x05, 0x00, 0x00, + 0xd7, 0xf9, 0xf0, 0x06, 0xe3, 0xd7, 0xf5, 0x0e, + 0x29, 0x5d, 0x07, 0x00, 0x41, 0xc5, 0x01, 0x00, + 0x00, 0xd7, 0x24, 0x01, 0x00, 0xd3, 0xba, 0xa8, + 0xf0, 0x18, 0xe3, 0x04, 0x24, 0x02, 0x00, 0x00, + 0x41, 0x64, 0x00, 0x00, 0x00, 0xcb, 0x04, 0xc9, 0x01, 0x00, 0x00, 0x24, 0x02, 0x00, 0xf5, 0x0e, - 0x5d, 0x07, 0x00, 0x41, 0xb2, 0x01, 0x00, 0x00, - 0x5d, 0x08, 0x00, 0xcb, 0x46, 0x24, 0x01, 0x00, - 0x0e, 0x29, 0x5d, 0x09, 0x00, 0xef, 0xc8, 0x0c, - 0x5d, 0x0a, 0x00, 0xd7, 0xf5, 0xc8, 0x0d, 0x5d, - 0x08, 0x00, 0x41, 0xb2, 0x01, 0x00, 0x00, 0xd7, - 0x24, 0x01, 0x00, 0x0e, 0xd7, 0x5d, 0x0b, 0x00, - 0xa9, 0xf0, 0x28, 0xe3, 0x04, 0x25, 0x02, 0x00, - 0x00, 0x41, 0x64, 0x00, 0x00, 0x00, 0x5d, 0x0c, - 0x00, 0x41, 0x10, 0x02, 0x00, 0x00, 0xd7, 0x41, - 0x26, 0x02, 0x00, 0x00, 0x24, 0x00, 0x00, 0x24, - 0x01, 0x00, 0x24, 0x01, 0x00, 0xf5, 0x0e, 0xf3, - 0xad, 0x01, 0xd7, 0x5d, 0x0d, 0x00, 0xa9, 0xf0, - 0x10, 0xe3, 0xd7, 0x41, 0x3b, 0x00, 0x00, 0x00, - 0x24, 0x00, 0x00, 0xf5, 0x0e, 0xf3, 0x97, 0x01, - 0xd7, 0x5d, 0x0e, 0x00, 0xa9, 0x11, 0xf1, 0x10, - 0x0e, 0xd7, 0x5d, 0x0f, 0x00, 0xa9, 0x11, 0xf1, - 0x07, 0x0e, 0xd7, 0x5d, 0x10, 0x00, 0xa9, 0xf0, - 0x21, 0xe3, 0x04, 0xed, 0x01, 0x00, 0x00, 0x41, - 0x64, 0x00, 0x00, 0x00, 0xc7, 0x0d, 0x04, 0x27, - 0x02, 0x00, 0x00, 0xd7, 0x04, 0xc9, 0x01, 0x00, - 0x00, 0x24, 0x04, 0x00, 0xf5, 0x0e, 0xf3, 0x5e, - 0x01, 0xd7, 0x5d, 0x06, 0x00, 0xa9, 0xf0, 0x2c, - 0xe3, 0x04, 0xed, 0x01, 0x00, 0x00, 0x41, 0x64, - 0x00, 0x00, 0x00, 0xc7, 0x0d, 0x04, 0x27, 0x02, - 0x00, 0x00, 0x5d, 0x05, 0x00, 0xd7, 0xf5, 0x04, + 0x29, 0x5d, 0x08, 0x00, 0x41, 0xc5, 0x01, 0x00, + 0x00, 0xd7, 0x24, 0x01, 0x00, 0xd3, 0xba, 0xa8, + 0xf0, 0x2c, 0xe3, 0x04, 0x24, 0x02, 0x00, 0x00, + 0x41, 0x64, 0x00, 0x00, 0x00, 0x5d, 0x07, 0x00, + 0xef, 0x04, 0xc9, 0x01, 0x00, 0x00, 0x24, 0x02, + 0x00, 0xf5, 0x0e, 0x5d, 0x07, 0x00, 0x41, 0xb2, + 0x01, 0x00, 0x00, 0x5d, 0x08, 0x00, 0xcb, 0x46, + 0x24, 0x01, 0x00, 0x0e, 0x29, 0x5d, 0x09, 0x00, + 0xef, 0xc8, 0x0c, 0x5d, 0x0a, 0x00, 0xd7, 0xf5, + 0xc8, 0x0d, 0x5d, 0x08, 0x00, 0x41, 0xb2, 0x01, + 0x00, 0x00, 0xd7, 0x24, 0x01, 0x00, 0x0e, 0xd7, + 0x5d, 0x0b, 0x00, 0xa9, 0xf0, 0x28, 0xe3, 0x04, + 0x25, 0x02, 0x00, 0x00, 0x41, 0x64, 0x00, 0x00, + 0x00, 0x5d, 0x0c, 0x00, 0x41, 0x10, 0x02, 0x00, + 0x00, 0xd7, 0x41, 0x26, 0x02, 0x00, 0x00, 0x24, + 0x00, 0x00, 0x24, 0x01, 0x00, 0x24, 0x01, 0x00, + 0xf5, 0x0e, 0xf3, 0xad, 0x01, 0xd7, 0x5d, 0x0d, + 0x00, 0xa9, 0xf0, 0x10, 0xe3, 0xd7, 0x41, 0x3b, + 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0xf5, 0x0e, + 0xf3, 0x97, 0x01, 0xd7, 0x5d, 0x0e, 0x00, 0xa9, + 0x11, 0xf1, 0x10, 0x0e, 0xd7, 0x5d, 0x0f, 0x00, + 0xa9, 0x11, 0xf1, 0x07, 0x0e, 0xd7, 0x5d, 0x10, + 0x00, 0xa9, 0xf0, 0x21, 0xe3, 0x04, 0xed, 0x01, + 0x00, 0x00, 0x41, 0x64, 0x00, 0x00, 0x00, 0xc7, + 0x0d, 0x04, 0x27, 0x02, 0x00, 0x00, 0xd7, 0x04, 0xc9, 0x01, 0x00, 0x00, 0x24, 0x04, 0x00, 0xf5, - 0x0e, 0xd7, 0xef, 0xc8, 0x0f, 0xbb, 0xc8, 0x08, - 0xf3, 0x2c, 0x01, 0x5d, 0x11, 0x00, 0x41, 0x28, - 0x02, 0x00, 0x00, 0xd7, 0x24, 0x01, 0x00, 0xf0, - 0x0f, 0xe3, 0x04, 0xed, 0x01, 0x00, 0x00, 0xf5, - 0x0e, 0xbb, 0xc8, 0x07, 0xf3, 0x10, 0x01, 0xc7, - 0x0d, 0x41, 0x8e, 0x01, 0x00, 0x00, 0x04, 0x9f, - 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0xf0, 0x2d, - 0xd7, 0x5d, 0x12, 0x00, 0x40, 0x48, 0x00, 0x00, - 0x00, 0xa9, 0xf0, 0x21, 0xe3, 0xc6, 0x41, 0x64, - 0x00, 0x00, 0x00, 0xc7, 0x0d, 0x04, 0xdf, 0x01, - 0x00, 0x00, 0xd7, 0xef, 0x04, 0x29, 0x02, 0x00, - 0x00, 0x24, 0x04, 0x00, 0xf5, 0x0e, 0xbb, 0xc8, - 0x07, 0xf3, 0xd3, 0x00, 0xc7, 0x06, 0x04, 0x1b, - 0x00, 0x00, 0x00, 0xad, 0xf0, 0x32, 0xd7, 0x40, - 0x3a, 0x00, 0x00, 0x00, 0xf0, 0x1f, 0xe3, 0x04, - 0x2a, 0x02, 0x00, 0x00, 0x41, 0x64, 0x00, 0x00, - 0x00, 0xd7, 0x40, 0x3a, 0x00, 0x00, 0x00, 0x04, - 0xc9, 0x01, 0x00, 0x00, 0x24, 0x02, 0x00, 0xf5, - 0x0e, 0xf3, 0xa3, 0x00, 0xe3, 0x04, 0x2b, 0x02, - 0x00, 0x00, 0xf5, 0x0e, 0xf3, 0x98, 0x00, 0xd7, - 0x40, 0x40, 0x00, 0x00, 0x00, 0x11, 0xf0, 0x0d, - 0x0e, 0xd7, 0x40, 0x40, 0x00, 0x00, 0x00, 0x40, - 0x3a, 0x00, 0x00, 0x00, 0x11, 0xf1, 0x07, 0x0e, - 0x04, 0x9e, 0x00, 0x00, 0x00, 0xc8, 0x0e, 0xc7, - 0x0d, 0x04, 0x9e, 0x00, 0x00, 0x00, 0xae, 0xf0, - 0x1d, 0xe3, 0xc6, 0x41, 0x64, 0x00, 0x00, 0x00, - 0xc7, 0x0e, 0x04, 0x2c, 0x02, 0x00, 0x00, 0xc7, - 0x0d, 0x04, 0x2d, 0x02, 0x00, 0x00, 0x24, 0x04, - 0x00, 0xf5, 0x0e, 0xf2, 0x4a, 0xd7, 0x40, 0x48, - 0x00, 0x00, 0x00, 0xf9, 0xf0, 0x1a, 0xe3, 0x04, - 0xed, 0x01, 0x00, 0x00, 0x41, 0x64, 0x00, 0x00, - 0x00, 0xc7, 0x0e, 0x04, 0x2e, 0x02, 0x00, 0x00, - 0x24, 0x02, 0x00, 0xf5, 0x0e, 0xf2, 0x28, 0xc7, - 0x0e, 0x04, 0x9e, 0x00, 0x00, 0x00, 0xae, 0xf0, - 0x16, 0xe3, 0xc6, 0x41, 0x64, 0x00, 0x00, 0x00, - 0xc7, 0x0e, 0x04, 0x2f, 0x02, 0x00, 0x00, 0x24, - 0x02, 0x00, 0xf5, 0x0e, 0xf2, 0x09, 0xe3, 0x04, - 0x30, 0x02, 0x00, 0x00, 0xf5, 0x0e, 0x04, 0x31, - 0x02, 0x00, 0x00, 0xc8, 0x0a, 0x07, 0xc8, 0x04, - 0xba, 0xcf, 0xba, 0xd0, 0xba, 0xd2, 0xc7, 0x07, - 0x68, 0xcb, 0x00, 0x00, 0x00, 0x04, 0xc9, 0x01, - 0x00, 0x00, 0xc8, 0x0a, 0xd7, 0xef, 0xc8, 0x0f, - 0xd8, 0x5d, 0x13, 0x00, 0xa7, 0xf0, 0x12, 0xc7, - 0x0f, 0xf0, 0x0e, 0xe3, 0x04, 0x23, 0x02, 0x00, - 0x00, 0xf5, 0x0e, 0xe3, 0xc7, 0x0a, 0xf5, 0x29, - 0xba, 0xd1, 0xcd, 0xc7, 0x0f, 0xa5, 0x68, 0x89, - 0x00, 0x00, 0x00, 0x92, 0x03, 0xcd, 0xd7, 0xaa, - 0xf0, 0x0e, 0x5d, 0x14, 0x00, 0xd7, 0xcd, 0x46, - 0xd8, 0xbb, 0x9c, 0xf6, 0x0e, 0xf2, 0x43, 0xcd, - 0xc8, 0x10, 0xcd, 0xbb, 0x9c, 0xc7, 0x0f, 0xa5, - 0xf0, 0x0d, 0xcd, 0xbb, 0x9c, 0xd7, 0xaa, 0x95, - 0xf0, 0x05, 0x92, 0x02, 0xf2, 0xed, 0xcd, 0xc7, - 0x10, 0xa7, 0xf0, 0x1e, 0xe3, 0x04, 0x32, 0x02, - 0x00, 0x00, 0x41, 0x64, 0x00, 0x00, 0x00, 0xcd, - 0xc7, 0x10, 0x9d, 0xbb, 0x9c, 0x04, 0x33, 0x02, - 0x00, 0x00, 0x24, 0x02, 0x00, 0xf5, 0x0e, 0xf2, - 0x09, 0xe3, 0x04, 0x34, 0x02, 0x00, 0x00, 0xf5, - 0x0e, 0xce, 0x5d, 0x15, 0x00, 0xa8, 0xf0, 0x24, - 0xc7, 0x0f, 0xce, 0x9d, 0xbf, 0xa7, 0xf0, 0x1c, - 0xe3, 0x04, 0x35, 0x02, 0x00, 0x00, 0x41, 0x64, - 0x00, 0x00, 0x00, 0xc7, 0x0f, 0xce, 0x9d, 0x04, - 0x36, 0x02, 0x00, 0x00, 0x24, 0x02, 0x00, 0xf5, - 0x0e, 0xf2, 0x06, 0x92, 0x02, 0xf3, 0x74, 0xff, - 0xbb, 0xc8, 0x08, 0xcd, 0xc7, 0x0f, 0xae, 0xf0, - 0x0c, 0xc7, 0x0f, 0xc3, 0xe8, 0x03, 0xa7, 0xf0, - 0x04, 0xbb, 0xc8, 0x09, 0xc7, 0x09, 0x95, 0xf0, - 0x24, 0x5d, 0x16, 0x00, 0xf0, 0x0f, 0x5d, 0x17, - 0x00, 0x41, 0xd4, 0x01, 0x00, 0x00, 0xd7, 0x24, - 0x01, 0x00, 0xf2, 0x0d, 0x5d, 0x17, 0x00, 0x41, - 0x31, 0x00, 0x00, 0x00, 0xd7, 0x24, 0x01, 0x00, - 0xc9, 0x04, 0xef, 0xcf, 0xc7, 0x08, 0xf0, 0x1e, - 0xcc, 0xcb, 0xa5, 0xf0, 0x19, 0xc7, 0x04, 0xcc, - 0x46, 0x8c, 0xd5, 0xcd, 0xba, 0xa0, 0xae, 0x11, - 0xf1, 0x06, 0x0e, 0xcd, 0xc7, 0x0f, 0xa8, 0xf1, - 0x05, 0x92, 0x01, 0xf2, 0xe4, 0xcc, 0xcb, 0xa5, - 0x68, 0x5a, 0x01, 0x00, 0x00, 0xc7, 0x0a, 0x95, - 0xf0, 0x12, 0x5d, 0x18, 0x00, 0x04, 0x2f, 0x02, - 0x00, 0x00, 0xf5, 0x0e, 0x04, 0x31, 0x02, 0x00, - 0x00, 0xc8, 0x0a, 0xd8, 0x5d, 0x13, 0x00, 0xa7, - 0xf0, 0x13, 0xcc, 0xcb, 0xa5, 0xf0, 0x0e, 0xe3, - 0x04, 0x23, 0x02, 0x00, 0x00, 0xf5, 0x0e, 0xe3, - 0xc7, 0x0a, 0xf5, 0x29, 0xcc, 0xd1, 0xcd, 0xcb, - 0xa5, 0x68, 0x21, 0x01, 0x00, 0x00, 0xc7, 0x04, - 0xcd, 0x46, 0xc8, 0x05, 0x5d, 0x17, 0x00, 0x41, - 0x6e, 0x00, 0x00, 0x00, 0xd7, 0xc7, 0x05, 0x24, - 0x02, 0x00, 0xc9, 0x11, 0x95, 0x69, 0x00, 0x01, - 0x00, 0x00, 0xc7, 0x11, 0x40, 0x43, 0x00, 0x00, - 0x00, 0x95, 0xf0, 0x1e, 0xe3, 0x04, 0xed, 0x01, - 0x00, 0x00, 0x41, 0x64, 0x00, 0x00, 0x00, 0x5d, - 0x06, 0x00, 0xc7, 0x05, 0xf5, 0x04, 0xc9, 0x01, + 0x0e, 0xf3, 0x5e, 0x01, 0xd7, 0x5d, 0x06, 0x00, + 0xa9, 0xf0, 0x2c, 0xe3, 0x04, 0xed, 0x01, 0x00, + 0x00, 0x41, 0x64, 0x00, 0x00, 0x00, 0xc7, 0x0d, + 0x04, 0x27, 0x02, 0x00, 0x00, 0x5d, 0x05, 0x00, + 0xd7, 0xf5, 0x04, 0xc9, 0x01, 0x00, 0x00, 0x24, + 0x04, 0x00, 0xf5, 0x0e, 0xd7, 0xef, 0xc8, 0x0f, + 0xbb, 0xc8, 0x08, 0xf3, 0x2c, 0x01, 0x5d, 0x11, + 0x00, 0x41, 0x28, 0x02, 0x00, 0x00, 0xd7, 0x24, + 0x01, 0x00, 0xf0, 0x0f, 0xe3, 0x04, 0xed, 0x01, + 0x00, 0x00, 0xf5, 0x0e, 0xbb, 0xc8, 0x07, 0xf3, + 0x10, 0x01, 0xc7, 0x0d, 0x41, 0x8e, 0x01, 0x00, + 0x00, 0x04, 0x9f, 0x00, 0x00, 0x00, 0x24, 0x01, + 0x00, 0xf0, 0x2d, 0xd7, 0x5d, 0x12, 0x00, 0x40, + 0x48, 0x00, 0x00, 0x00, 0xa9, 0xf0, 0x21, 0xe3, + 0xc6, 0x41, 0x64, 0x00, 0x00, 0x00, 0xc7, 0x0d, + 0x04, 0xdf, 0x01, 0x00, 0x00, 0xd7, 0xef, 0x04, + 0x29, 0x02, 0x00, 0x00, 0x24, 0x04, 0x00, 0xf5, + 0x0e, 0xbb, 0xc8, 0x07, 0xf3, 0xd3, 0x00, 0xc7, + 0x06, 0x04, 0x1b, 0x00, 0x00, 0x00, 0xad, 0xf0, + 0x32, 0xd7, 0x40, 0x3a, 0x00, 0x00, 0x00, 0xf0, + 0x1f, 0xe3, 0x04, 0x2a, 0x02, 0x00, 0x00, 0x41, + 0x64, 0x00, 0x00, 0x00, 0xd7, 0x40, 0x3a, 0x00, + 0x00, 0x00, 0x04, 0xc9, 0x01, 0x00, 0x00, 0x24, + 0x02, 0x00, 0xf5, 0x0e, 0xf3, 0xa3, 0x00, 0xe3, + 0x04, 0x2b, 0x02, 0x00, 0x00, 0xf5, 0x0e, 0xf3, + 0x98, 0x00, 0xd7, 0x40, 0x40, 0x00, 0x00, 0x00, + 0x11, 0xf0, 0x0d, 0x0e, 0xd7, 0x40, 0x40, 0x00, + 0x00, 0x00, 0x40, 0x3a, 0x00, 0x00, 0x00, 0x11, + 0xf1, 0x07, 0x0e, 0x04, 0x9e, 0x00, 0x00, 0x00, + 0xc8, 0x0e, 0xc7, 0x0d, 0x04, 0x9e, 0x00, 0x00, + 0x00, 0xae, 0xf0, 0x1d, 0xe3, 0xc6, 0x41, 0x64, + 0x00, 0x00, 0x00, 0xc7, 0x0e, 0x04, 0x2c, 0x02, + 0x00, 0x00, 0xc7, 0x0d, 0x04, 0x2d, 0x02, 0x00, + 0x00, 0x24, 0x04, 0x00, 0xf5, 0x0e, 0xf2, 0x4a, + 0xd7, 0x40, 0x48, 0x00, 0x00, 0x00, 0xf9, 0xf0, + 0x1a, 0xe3, 0x04, 0xed, 0x01, 0x00, 0x00, 0x41, + 0x64, 0x00, 0x00, 0x00, 0xc7, 0x0e, 0x04, 0x2e, + 0x02, 0x00, 0x00, 0x24, 0x02, 0x00, 0xf5, 0x0e, + 0xf2, 0x28, 0xc7, 0x0e, 0x04, 0x9e, 0x00, 0x00, + 0x00, 0xae, 0xf0, 0x16, 0xe3, 0xc6, 0x41, 0x64, + 0x00, 0x00, 0x00, 0xc7, 0x0e, 0x04, 0x2f, 0x02, 0x00, 0x00, 0x24, 0x02, 0x00, 0xf5, 0x0e, 0xf2, - 0x2e, 0xc7, 0x05, 0x8c, 0xc7, 0x05, 0xba, 0xa0, - 0xad, 0x11, 0xf1, 0x11, 0x0e, 0xc7, 0x05, 0x41, - 0xcb, 0x01, 0x00, 0x00, 0xc4, 0x00, 0xc4, 0x01, - 0x34, 0x24, 0x01, 0x00, 0xf0, 0x08, 0xe3, 0xc7, - 0x05, 0xf5, 0x0e, 0xf2, 0x0a, 0xe3, 0x5d, 0x05, - 0x00, 0xc7, 0x05, 0xf5, 0xf5, 0x0e, 0xe3, 0x04, - 0x37, 0x02, 0x00, 0x00, 0xf5, 0x0e, 0x04, 0x44, - 0x00, 0x00, 0x00, 0xc7, 0x11, 0xaa, 0xf0, 0x12, - 0x5d, 0x14, 0x00, 0xc7, 0x11, 0x40, 0x44, 0x00, - 0x00, 0x00, 0xd8, 0xbb, 0x9c, 0xf6, 0x0e, 0xf2, - 0x5c, 0x26, 0x00, 0x00, 0xc8, 0x12, 0xc7, 0x11, - 0x40, 0x45, 0x00, 0x00, 0x00, 0xf0, 0x11, 0xc7, - 0x12, 0x41, 0xb2, 0x01, 0x00, 0x00, 0x04, 0x38, - 0x02, 0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, 0xc7, - 0x11, 0x40, 0x46, 0x00, 0x00, 0x00, 0xf0, 0x11, - 0xc7, 0x12, 0x41, 0xb2, 0x01, 0x00, 0x00, 0x04, - 0x39, 0x02, 0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, - 0xe3, 0x04, 0xed, 0x01, 0x00, 0x00, 0x41, 0x64, - 0x00, 0x00, 0x00, 0xc7, 0x12, 0x41, 0x63, 0x00, - 0x00, 0x00, 0x04, 0xca, 0x01, 0x00, 0x00, 0x24, - 0x01, 0x00, 0x04, 0xc9, 0x01, 0x00, 0x00, 0x24, - 0x02, 0x00, 0xf5, 0x0e, 0x92, 0x03, 0xce, 0x5d, - 0x19, 0x00, 0xa7, 0xf0, 0x22, 0xcb, 0xce, 0x9d, - 0xbf, 0xa7, 0xf0, 0x1b, 0xe3, 0x04, 0x35, 0x02, - 0x00, 0x00, 0x41, 0x64, 0x00, 0x00, 0x00, 0xcb, - 0xce, 0x9d, 0x04, 0x3a, 0x02, 0x00, 0x00, 0x24, + 0x09, 0xe3, 0x04, 0x30, 0x02, 0x00, 0x00, 0xf5, + 0x0e, 0x04, 0x31, 0x02, 0x00, 0x00, 0xc8, 0x0a, + 0x07, 0xc8, 0x04, 0xba, 0xcf, 0xba, 0xd0, 0xba, + 0xd2, 0xc7, 0x07, 0x68, 0xcb, 0x00, 0x00, 0x00, + 0x04, 0xc9, 0x01, 0x00, 0x00, 0xc8, 0x0a, 0xd7, + 0xef, 0xc8, 0x0f, 0xd8, 0x5d, 0x13, 0x00, 0xa7, + 0xf0, 0x12, 0xc7, 0x0f, 0xf0, 0x0e, 0xe3, 0x04, + 0x23, 0x02, 0x00, 0x00, 0xf5, 0x0e, 0xe3, 0xc7, + 0x0a, 0xf5, 0x29, 0xba, 0xd1, 0xcd, 0xc7, 0x0f, + 0xa5, 0x68, 0x89, 0x00, 0x00, 0x00, 0x92, 0x03, + 0xcd, 0xd7, 0xaa, 0xf0, 0x0e, 0x5d, 0x14, 0x00, + 0xd7, 0xcd, 0x46, 0xd8, 0xbb, 0x9c, 0xf6, 0x0e, + 0xf2, 0x43, 0xcd, 0xc8, 0x10, 0xcd, 0xbb, 0x9c, + 0xc7, 0x0f, 0xa5, 0xf0, 0x0d, 0xcd, 0xbb, 0x9c, + 0xd7, 0xaa, 0x95, 0xf0, 0x05, 0x92, 0x02, 0xf2, + 0xed, 0xcd, 0xc7, 0x10, 0xa7, 0xf0, 0x1e, 0xe3, + 0x04, 0x32, 0x02, 0x00, 0x00, 0x41, 0x64, 0x00, + 0x00, 0x00, 0xcd, 0xc7, 0x10, 0x9d, 0xbb, 0x9c, + 0x04, 0x33, 0x02, 0x00, 0x00, 0x24, 0x02, 0x00, + 0xf5, 0x0e, 0xf2, 0x09, 0xe3, 0x04, 0x34, 0x02, + 0x00, 0x00, 0xf5, 0x0e, 0xce, 0x5d, 0x15, 0x00, + 0xa8, 0xf0, 0x24, 0xc7, 0x0f, 0xce, 0x9d, 0xbf, + 0xa7, 0xf0, 0x1c, 0xe3, 0x04, 0x35, 0x02, 0x00, + 0x00, 0x41, 0x64, 0x00, 0x00, 0x00, 0xc7, 0x0f, + 0xce, 0x9d, 0x04, 0x36, 0x02, 0x00, 0x00, 0x24, 0x02, 0x00, 0xf5, 0x0e, 0xf2, 0x06, 0x92, 0x02, - 0xf3, 0xdd, 0xfe, 0xc7, 0x0a, 0xf0, 0x06, 0xe3, - 0xc7, 0x0a, 0xf5, 0x0e, 0x5d, 0x08, 0x00, 0x41, - 0x3b, 0x02, 0x00, 0x00, 0xd7, 0x24, 0x01, 0x00, - 0x0e, 0x5d, 0x07, 0x00, 0x41, 0xc5, 0x01, 0x00, - 0x00, 0xd7, 0x24, 0x01, 0x00, 0xd5, 0xba, 0xa7, - 0xf0, 0x35, 0x5d, 0x09, 0x00, 0xc7, 0x0c, 0x1b, - 0x11, 0xaf, 0xf1, 0x04, 0x1b, 0x71, 0x1b, 0x1b, - 0x04, 0x3c, 0x02, 0x00, 0x00, 0x41, 0x64, 0x00, - 0x00, 0x00, 0xcd, 0x04, 0x3d, 0x02, 0x00, 0x00, - 0x5d, 0x09, 0x00, 0xc7, 0x0c, 0x46, 0x24, 0x03, - 0x00, 0x1b, 0x71, 0x1b, 0x48, 0x29, 0xe3, 0x5d, - 0x06, 0x00, 0xd7, 0xf5, 0xf5, 0x0e, 0x29, 0x0c, - 0x43, 0x02, 0x01, 0x8c, 0x08, 0x02, 0x01, 0x02, - 0x03, 0x00, 0x05, 0x00, 0x3d, 0x03, 0xf6, 0x06, - 0x00, 0x01, 0x00, 0xb8, 0x06, 0x00, 0x01, 0x00, - 0xfc, 0x08, 0x00, 0x00, 0x00, 0xee, 0x07, 0x03, - 0x01, 0x80, 0x08, 0x0a, 0x00, 0xfe, 0x07, 0x09, - 0x00, 0xfe, 0x03, 0x0e, 0x02, 0x82, 0x04, 0x0f, - 0x02, 0xe3, 0xf0, 0x30, 0xe4, 0xd8, 0xae, 0xf0, - 0x13, 0xe5, 0x41, 0xb2, 0x01, 0x00, 0x00, 0xe6, - 0x40, 0x9e, 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, - 0x0e, 0xd8, 0xe8, 0xd8, 0xf0, 0x16, 0xe6, 0x5d, - 0x04, 0x00, 0xd8, 0x46, 0x46, 0xd3, 0xf0, 0x0c, - 0xe5, 0x41, 0xb2, 0x01, 0x00, 0x00, 0xcb, 0x24, - 0x01, 0x00, 0x0e, 0xe5, 0x41, 0xb2, 0x01, 0x00, - 0x00, 0xd7, 0x24, 0x01, 0x00, 0x29, 0x0c, 0x43, - 0x02, 0x01, 0x8e, 0x08, 0x01, 0x00, 0x01, 0x03, - 0x00, 0x01, 0x02, 0x2c, 0x01, 0xf6, 0x06, 0x00, - 0x01, 0x00, 0x8c, 0x08, 0x10, 0x00, 0x07, 0x02, - 0x30, 0x07, 0x02, 0x39, 0xd7, 0xba, 0x46, 0xc4, - 0x00, 0xa8, 0xf0, 0x14, 0xd7, 0xba, 0x46, 0xc4, - 0x01, 0xa6, 0xf0, 0x0c, 0xe3, 0xd7, 0x04, 0x4a, - 0x00, 0x00, 0x00, 0xf6, 0x0e, 0xf2, 0x0a, 0xe3, - 0xd7, 0x04, 0x3f, 0x02, 0x00, 0x00, 0xf6, 0x0e, - 0xe3, 0x04, 0x27, 0x02, 0x00, 0x00, 0xf5, 0x29, - 0x0c, 0x43, 0x02, 0x01, 0x90, 0x08, 0x01, 0x04, - 0x01, 0x05, 0x00, 0x03, 0x14, 0xa1, 0x04, 0x05, - 0xf6, 0x06, 0x00, 0x01, 0x00, 0xb8, 0x06, 0x00, - 0x00, 0x00, 0x80, 0x09, 0x00, 0x01, 0x00, 0xa0, - 0x06, 0x00, 0x02, 0x00, 0xbc, 0x07, 0x00, 0x03, - 0x00, 0xee, 0x07, 0x03, 0x01, 0x8c, 0x08, 0x10, - 0x00, 0x92, 0x08, 0x13, 0x00, 0x07, 0x20, 0x5e, - 0x22, 0x28, 0x5b, 0x5e, 0x5c, 0x5c, 0x22, 0x5d, - 0x7c, 0x5c, 0x5c, 0x2e, 0x29, 0x2a, 0x22, 0x07, - 0x98, 0x01, 0x00, 0x00, 0x02, 0x01, 0x44, 0x00, - 0x00, 0x00, 0x09, 0x06, 0x00, 0x00, 0x00, 0x05, - 0x08, 0xf5, 0xff, 0xff, 0xff, 0x0c, 0x00, 0x06, - 0x01, 0x22, 0x0e, 0x01, 0x01, 0x0a, 0x27, 0x00, - 0x00, 0x00, 0x1a, 0x0c, 0x01, 0x0a, 0x14, 0x00, - 0x00, 0x00, 0x16, 0x03, 0x00, 0x00, 0x00, 0x21, - 0x00, 0x23, 0x00, 0x5b, 0x00, 0x5d, 0x00, 0xff, - 0xff, 0x08, 0x03, 0x00, 0x00, 0x00, 0x01, 0x5c, - 0x04, 0x0d, 0x01, 0x1b, 0x08, 0xd4, 0xff, 0xff, - 0xff, 0x01, 0x22, 0x0d, 0x00, 0x0b, 0x07, 0x20, + 0xf3, 0x74, 0xff, 0xbb, 0xc8, 0x08, 0xcd, 0xc7, + 0x0f, 0xae, 0xf0, 0x0c, 0xc7, 0x0f, 0xc3, 0xe8, + 0x03, 0xa7, 0xf0, 0x04, 0xbb, 0xc8, 0x09, 0xc7, + 0x09, 0x95, 0xf0, 0x24, 0x5d, 0x16, 0x00, 0xf0, + 0x0f, 0x5d, 0x17, 0x00, 0x41, 0xd4, 0x01, 0x00, + 0x00, 0xd7, 0x24, 0x01, 0x00, 0xf2, 0x0d, 0x5d, + 0x17, 0x00, 0x41, 0x31, 0x00, 0x00, 0x00, 0xd7, + 0x24, 0x01, 0x00, 0xc9, 0x04, 0xef, 0xcf, 0xc7, + 0x08, 0xf0, 0x1e, 0xcc, 0xcb, 0xa5, 0xf0, 0x19, + 0xc7, 0x04, 0xcc, 0x46, 0x8c, 0xd5, 0xcd, 0xba, + 0xa0, 0xae, 0x11, 0xf1, 0x06, 0x0e, 0xcd, 0xc7, + 0x0f, 0xa8, 0xf1, 0x05, 0x92, 0x01, 0xf2, 0xe4, + 0xcc, 0xcb, 0xa5, 0x68, 0x5a, 0x01, 0x00, 0x00, + 0xc7, 0x0a, 0x95, 0xf0, 0x12, 0x5d, 0x18, 0x00, + 0x04, 0x2f, 0x02, 0x00, 0x00, 0xf5, 0x0e, 0x04, + 0x31, 0x02, 0x00, 0x00, 0xc8, 0x0a, 0xd8, 0x5d, + 0x13, 0x00, 0xa7, 0xf0, 0x13, 0xcc, 0xcb, 0xa5, + 0xf0, 0x0e, 0xe3, 0x04, 0x23, 0x02, 0x00, 0x00, + 0xf5, 0x0e, 0xe3, 0xc7, 0x0a, 0xf5, 0x29, 0xcc, + 0xd1, 0xcd, 0xcb, 0xa5, 0x68, 0x21, 0x01, 0x00, + 0x00, 0xc7, 0x04, 0xcd, 0x46, 0xc8, 0x05, 0x5d, + 0x17, 0x00, 0x41, 0x6e, 0x00, 0x00, 0x00, 0xd7, + 0xc7, 0x05, 0x24, 0x02, 0x00, 0xc9, 0x11, 0x95, + 0x69, 0x00, 0x01, 0x00, 0x00, 0xc7, 0x11, 0x40, + 0x43, 0x00, 0x00, 0x00, 0x95, 0xf0, 0x1e, 0xe3, + 0x04, 0xed, 0x01, 0x00, 0x00, 0x41, 0x64, 0x00, + 0x00, 0x00, 0x5d, 0x06, 0x00, 0xc7, 0x05, 0xf5, + 0x04, 0xc9, 0x01, 0x00, 0x00, 0x24, 0x02, 0x00, + 0xf5, 0x0e, 0xf2, 0x2e, 0xc7, 0x05, 0x8c, 0xc7, + 0x05, 0xba, 0xa0, 0xad, 0x11, 0xf1, 0x11, 0x0e, + 0xc7, 0x05, 0x41, 0xcb, 0x01, 0x00, 0x00, 0xc4, + 0x00, 0xc4, 0x01, 0x34, 0x24, 0x01, 0x00, 0xf0, + 0x08, 0xe3, 0xc7, 0x05, 0xf5, 0x0e, 0xf2, 0x0a, + 0xe3, 0x5d, 0x05, 0x00, 0xc7, 0x05, 0xf5, 0xf5, + 0x0e, 0xe3, 0x04, 0x37, 0x02, 0x00, 0x00, 0xf5, + 0x0e, 0x04, 0x44, 0x00, 0x00, 0x00, 0xc7, 0x11, + 0xaa, 0xf0, 0x12, 0x5d, 0x14, 0x00, 0xc7, 0x11, + 0x40, 0x44, 0x00, 0x00, 0x00, 0xd8, 0xbb, 0x9c, + 0xf6, 0x0e, 0xf2, 0x5c, 0x26, 0x00, 0x00, 0xc8, + 0x12, 0xc7, 0x11, 0x40, 0x45, 0x00, 0x00, 0x00, + 0xf0, 0x11, 0xc7, 0x12, 0x41, 0xb2, 0x01, 0x00, + 0x00, 0x04, 0x38, 0x02, 0x00, 0x00, 0x24, 0x01, + 0x00, 0x0e, 0xc7, 0x11, 0x40, 0x46, 0x00, 0x00, + 0x00, 0xf0, 0x11, 0xc7, 0x12, 0x41, 0xb2, 0x01, + 0x00, 0x00, 0x04, 0x39, 0x02, 0x00, 0x00, 0x24, + 0x01, 0x00, 0x0e, 0xe3, 0x04, 0xed, 0x01, 0x00, + 0x00, 0x41, 0x64, 0x00, 0x00, 0x00, 0xc7, 0x12, + 0x41, 0x63, 0x00, 0x00, 0x00, 0x04, 0xca, 0x01, + 0x00, 0x00, 0x24, 0x01, 0x00, 0x04, 0xc9, 0x01, + 0x00, 0x00, 0x24, 0x02, 0x00, 0xf5, 0x0e, 0x92, + 0x03, 0xce, 0x5d, 0x19, 0x00, 0xa7, 0xf0, 0x22, + 0xcb, 0xce, 0x9d, 0xbf, 0xa7, 0xf0, 0x1b, 0xe3, + 0x04, 0x35, 0x02, 0x00, 0x00, 0x41, 0x64, 0x00, + 0x00, 0x00, 0xcb, 0xce, 0x9d, 0x04, 0x3a, 0x02, + 0x00, 0x00, 0x24, 0x02, 0x00, 0xf5, 0x0e, 0xf2, + 0x06, 0x92, 0x02, 0xf3, 0xdd, 0xfe, 0xc7, 0x0a, + 0xf0, 0x06, 0xe3, 0xc7, 0x0a, 0xf5, 0x0e, 0x5d, + 0x08, 0x00, 0x41, 0x3b, 0x02, 0x00, 0x00, 0xd7, + 0x24, 0x01, 0x00, 0x0e, 0x5d, 0x07, 0x00, 0x41, + 0xc5, 0x01, 0x00, 0x00, 0xd7, 0x24, 0x01, 0x00, + 0xd5, 0xba, 0xa7, 0xf0, 0x35, 0x5d, 0x09, 0x00, + 0xc7, 0x0c, 0x1b, 0x11, 0xaf, 0xf1, 0x04, 0x1b, + 0x71, 0x1b, 0x1b, 0x04, 0x3c, 0x02, 0x00, 0x00, + 0x41, 0x64, 0x00, 0x00, 0x00, 0xcd, 0x04, 0x3d, + 0x02, 0x00, 0x00, 0x5d, 0x09, 0x00, 0xc7, 0x0c, + 0x46, 0x24, 0x03, 0x00, 0x1b, 0x71, 0x1b, 0x48, + 0x29, 0xe3, 0x5d, 0x06, 0x00, 0xd7, 0xf5, 0xf5, + 0x0e, 0x29, 0x0c, 0x43, 0x02, 0x01, 0x8c, 0x08, + 0x02, 0x01, 0x02, 0x03, 0x00, 0x05, 0x00, 0x3d, + 0x03, 0xf6, 0x06, 0x00, 0x01, 0x00, 0xb8, 0x06, + 0x00, 0x01, 0x00, 0xfc, 0x08, 0x00, 0x00, 0x00, + 0xee, 0x07, 0x03, 0x01, 0x80, 0x08, 0x0a, 0x00, + 0xfe, 0x07, 0x09, 0x00, 0xfe, 0x03, 0x0e, 0x02, + 0x82, 0x04, 0x0f, 0x02, 0xe3, 0xf0, 0x30, 0xe4, + 0xd8, 0xae, 0xf0, 0x13, 0xe5, 0x41, 0xb2, 0x01, + 0x00, 0x00, 0xe6, 0x40, 0x9e, 0x01, 0x00, 0x00, + 0x24, 0x01, 0x00, 0x0e, 0xd8, 0xe8, 0xd8, 0xf0, + 0x16, 0xe6, 0x5d, 0x04, 0x00, 0xd8, 0x46, 0x46, + 0xd3, 0xf0, 0x0c, 0xe5, 0x41, 0xb2, 0x01, 0x00, + 0x00, 0xcb, 0x24, 0x01, 0x00, 0x0e, 0xe5, 0x41, + 0xb2, 0x01, 0x00, 0x00, 0xd7, 0x24, 0x01, 0x00, + 0x29, 0x0c, 0x43, 0x02, 0x01, 0x8e, 0x08, 0x01, + 0x00, 0x01, 0x03, 0x00, 0x01, 0x02, 0x2c, 0x01, + 0xf6, 0x06, 0x00, 0x01, 0x00, 0x8c, 0x08, 0x10, + 0x00, 0x07, 0x02, 0x30, 0x07, 0x02, 0x39, 0xd7, + 0xba, 0x46, 0xc4, 0x00, 0xa8, 0xf0, 0x14, 0xd7, + 0xba, 0x46, 0xc4, 0x01, 0xa6, 0xf0, 0x0c, 0xe3, + 0xd7, 0x04, 0x4a, 0x00, 0x00, 0x00, 0xf6, 0x0e, + 0xf2, 0x0a, 0xe3, 0xd7, 0x04, 0x3f, 0x02, 0x00, + 0x00, 0xf6, 0x0e, 0xe3, 0x04, 0x27, 0x02, 0x00, + 0x00, 0xf5, 0x29, 0x0c, 0x43, 0x02, 0x01, 0x90, + 0x08, 0x01, 0x04, 0x01, 0x05, 0x00, 0x03, 0x14, + 0xa1, 0x04, 0x05, 0xf6, 0x06, 0x00, 0x01, 0x00, + 0xb8, 0x06, 0x00, 0x00, 0x00, 0x80, 0x09, 0x00, + 0x01, 0x00, 0xa0, 0x06, 0x00, 0x02, 0x00, 0xbc, + 0x07, 0x00, 0x03, 0x00, 0xee, 0x07, 0x03, 0x01, + 0x8c, 0x08, 0x10, 0x00, 0x92, 0x08, 0x13, 0x00, + 0x07, 0x20, 0x5e, 0x22, 0x28, 0x5b, 0x5e, 0x5c, + 0x5c, 0x22, 0x5d, 0x7c, 0x5c, 0x5c, 0x2e, 0x29, + 0x2a, 0x22, 0x07, 0xa2, 0x01, 0x00, 0x00, 0x02, + 0x01, 0x49, 0x00, 0x00, 0x00, 0x0e, 0x06, 0x00, + 0x00, 0x00, 0x06, 0x0d, 0xf5, 0xff, 0xff, 0xff, + 0x13, 0x00, 0x09, 0x01, 0x22, 0x00, 0x0f, 0x2d, + 0x00, 0x00, 0x00, 0x2a, 0x00, 0x15, 0x01, 0x01, + 0x13, 0x01, 0x0f, 0x14, 0x00, 0x00, 0x00, 0x24, + 0x03, 0x00, 0x00, 0x00, 0x21, 0x00, 0x23, 0x00, + 0x5b, 0x00, 0x5d, 0x00, 0xff, 0xff, 0x0d, 0x04, + 0x00, 0x00, 0x00, 0x01, 0x5c, 0x00, 0x05, 0x14, + 0x01, 0x2b, 0x00, 0x0d, 0xce, 0xff, 0xff, 0xff, + 0x01, 0x22, 0x00, 0x14, 0x00, 0x10, 0x07, 0x20, 0x5e, 0x27, 0x28, 0x5b, 0x5e, 0x5c, 0x5c, 0x27, 0x5d, 0x7c, 0x5c, 0x5c, 0x2e, 0x29, 0x2a, 0x27, - 0x07, 0x98, 0x01, 0x00, 0x00, 0x02, 0x01, 0x44, - 0x00, 0x00, 0x00, 0x09, 0x06, 0x00, 0x00, 0x00, - 0x05, 0x08, 0xf5, 0xff, 0xff, 0xff, 0x0c, 0x00, - 0x06, 0x01, 0x27, 0x0e, 0x01, 0x01, 0x0a, 0x27, - 0x00, 0x00, 0x00, 0x1a, 0x0c, 0x01, 0x0a, 0x14, - 0x00, 0x00, 0x00, 0x16, 0x03, 0x00, 0x00, 0x00, - 0x26, 0x00, 0x28, 0x00, 0x5b, 0x00, 0x5d, 0x00, - 0xff, 0xff, 0x08, 0x03, 0x00, 0x00, 0x00, 0x01, - 0x5c, 0x04, 0x0d, 0x01, 0x1b, 0x08, 0xd4, 0xff, - 0xff, 0xff, 0x01, 0x27, 0x0d, 0x00, 0x0b, 0x07, - 0x16, 0x5e, 0x5c, 0x3c, 0x5b, 0x5e, 0x5c, 0x3e, - 0x5d, 0x2b, 0x5c, 0x3e, 0x07, 0x74, 0x00, 0x00, - 0x01, 0x00, 0x32, 0x00, 0x00, 0x00, 0x09, 0x06, - 0x00, 0x00, 0x00, 0x05, 0x08, 0xf5, 0xff, 0xff, - 0xff, 0x0c, 0x00, 0x06, 0x01, 0x3c, 0x1d, 0x0c, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, - 0xff, 0xff, 0x7f, 0x01, 0x00, 0x00, 0x00, 0x16, - 0x02, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x3f, 0x00, - 0xff, 0xff, 0x0b, 0x01, 0x3e, 0x0d, 0x00, 0x0b, - 0x07, 0x16, 0x5e, 0x5c, 0x5b, 0x5b, 0x5e, 0x5c, - 0x5d, 0x5d, 0x2b, 0x5c, 0x5d, 0x07, 0x74, 0x00, - 0x00, 0x01, 0x00, 0x32, 0x00, 0x00, 0x00, 0x09, - 0x06, 0x00, 0x00, 0x00, 0x05, 0x08, 0xf5, 0xff, - 0xff, 0xff, 0x0c, 0x00, 0x06, 0x01, 0x5b, 0x1d, - 0x0c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0x7f, 0x01, 0x00, 0x00, 0x00, - 0x16, 0x02, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x5e, - 0x00, 0xff, 0xff, 0x0b, 0x01, 0x5d, 0x0d, 0x00, - 0x0b, 0x07, 0x02, 0x30, 0x07, 0x02, 0x31, 0x07, - 0x02, 0x32, 0x07, 0x02, 0x33, 0x07, 0x02, 0x34, - 0x07, 0x02, 0x35, 0x07, 0x02, 0x36, 0x07, 0x02, - 0x37, 0x07, 0x02, 0x38, 0x07, 0x02, 0x39, 0x07, - 0x56, 0x5e, 0x5b, 0x30, 0x2d, 0x39, 0x61, 0x2d, - 0x7a, 0x5f, 0x5d, 0x2b, 0x5b, 0x2e, 0x5d, 0x3f, - 0x5b, 0x30, 0x2d, 0x39, 0x61, 0x2d, 0x7a, 0x5f, - 0x5d, 0x2a, 0x5b, 0x65, 0x45, 0x70, 0x50, 0x5d, - 0x3f, 0x5b, 0x2b, 0x2d, 0x5d, 0x3f, 0x5b, 0x30, - 0x2d, 0x39, 0x5d, 0x2a, 0x07, 0x9e, 0x03, 0x00, - 0x00, 0x01, 0x00, 0xc7, 0x00, 0x00, 0x00, 0x09, - 0x06, 0x00, 0x00, 0x00, 0x05, 0x08, 0xf5, 0xff, - 0xff, 0xff, 0x0c, 0x00, 0x06, 0x1d, 0x10, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xff, 0x7f, 0x01, 0x00, 0x00, 0x00, 0x16, 0x03, - 0x00, 0x30, 0x00, 0x39, 0x00, 0x5f, 0x00, 0x5f, - 0x00, 0x61, 0x00, 0x7a, 0x00, 0x0b, 0x1d, 0x08, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x16, - 0x01, 0x00, 0x2e, 0x00, 0x2e, 0x00, 0x0b, 0x1d, - 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0x7f, 0x01, 0x00, 0x00, 0x00, - 0x16, 0x03, 0x00, 0x30, 0x00, 0x39, 0x00, 0x5f, - 0x00, 0x5f, 0x00, 0x61, 0x00, 0x7a, 0x00, 0x0b, - 0x1d, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x16, 0x04, 0x00, 0x45, 0x00, 0x45, 0x00, - 0x50, 0x00, 0x50, 0x00, 0x65, 0x00, 0x65, 0x00, - 0x70, 0x00, 0x70, 0x00, 0x0b, 0x1d, 0x0c, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x16, 0x02, - 0x00, 0x2b, 0x00, 0x2b, 0x00, 0x2d, 0x00, 0x2d, - 0x00, 0x0b, 0x1d, 0x08, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x7f, 0x01, - 0x00, 0x00, 0x00, 0x16, 0x01, 0x00, 0x30, 0x00, - 0x39, 0x00, 0x0b, 0x0d, 0x00, 0x0b, 0xe3, 0x95, - 0xf0, 0x05, 0xe4, 0xd7, 0xf5, 0x29, 0xd7, 0xef, - 0xba, 0xa7, 0x68, 0x13, 0x02, 0x00, 0x00, 0x04, - 0x9e, 0x01, 0x00, 0x00, 0xcf, 0xd7, 0xd0, 0xba, - 0xd1, 0x07, 0xd2, 0xd7, 0xba, 0x46, 0x11, 0x04, - 0xc7, 0x01, 0x00, 0x00, 0xad, 0xf0, 0x19, 0x04, - 0x4c, 0x00, 0x00, 0x00, 0xcf, 0xd7, 0x41, 0xcb, - 0x01, 0x00, 0x00, 0xc4, 0x00, 0xc4, 0x01, 0x34, - 0x24, 0x01, 0x00, 0xd2, 0xf3, 0xb3, 0x01, 0x11, - 0x04, 0xc6, 0x01, 0x00, 0x00, 0xad, 0xf0, 0x19, - 0x04, 0x4c, 0x00, 0x00, 0x00, 0xcf, 0xd7, 0x41, - 0xcb, 0x01, 0x00, 0x00, 0xc4, 0x02, 0xc4, 0x03, - 0x34, 0x24, 0x01, 0x00, 0xd2, 0xf3, 0x92, 0x01, - 0x11, 0x04, 0xca, 0x01, 0x00, 0x00, 0xad, 0xf0, - 0x0a, 0x04, 0x41, 0x02, 0x00, 0x00, 0xcf, 0xf3, - 0x80, 0x01, 0x11, 0x04, 0x32, 0x02, 0x00, 0x00, - 0xad, 0xf0, 0x1e, 0xd7, 0x41, 0xcb, 0x01, 0x00, - 0x00, 0xc4, 0x04, 0xc4, 0x05, 0x34, 0x24, 0x01, - 0x00, 0xd6, 0x68, 0x65, 0x01, 0x00, 0x00, 0x04, - 0x42, 0x02, 0x00, 0x00, 0xcf, 0xf3, 0x5a, 0x01, - 0x11, 0x04, 0xed, 0x01, 0x00, 0x00, 0xad, 0xf0, - 0x1b, 0xd7, 0x41, 0xcb, 0x01, 0x00, 0x00, 0xc4, - 0x06, 0xc4, 0x07, 0x34, 0x24, 0x01, 0x00, 0xd6, - 0xf0, 0x2e, 0x04, 0x42, 0x02, 0x00, 0x00, 0xcf, - 0xf3, 0x37, 0x01, 0x11, 0x04, 0xc9, 0x01, 0x00, - 0x00, 0xad, 0xf1, 0x1c, 0x11, 0x04, 0x31, 0x02, - 0x00, 0x00, 0xad, 0xf1, 0x13, 0x11, 0x04, 0x43, - 0x02, 0x00, 0x00, 0xad, 0xf1, 0x0a, 0x11, 0x04, - 0xe8, 0x01, 0x00, 0x00, 0xad, 0xf0, 0x0c, 0x04, - 0x44, 0x02, 0x00, 0x00, 0xcf, 0xbb, 0xd1, 0xf3, - 0x08, 0x01, 0x11, 0x04, 0xbe, 0x01, 0x00, 0x00, - 0xad, 0xf0, 0x0a, 0x04, 0x42, 0x02, 0x00, 0x00, - 0xcf, 0xf3, 0xf6, 0x00, 0x11, 0xc4, 0x08, 0xad, - 0xf1, 0x37, 0x11, 0xc4, 0x09, 0xad, 0xf1, 0x31, - 0x11, 0xc4, 0x0a, 0xad, 0xf1, 0x2b, 0x11, 0xc4, - 0x0b, 0xad, 0xf1, 0x25, 0x11, 0xc4, 0x0c, 0xad, - 0xf1, 0x1f, 0x11, 0xc4, 0x0d, 0xad, 0xf1, 0x19, - 0x11, 0xc4, 0x0e, 0xad, 0xf1, 0x13, 0x11, 0xc4, - 0x0f, 0xad, 0xf1, 0x0d, 0x11, 0xc4, 0x10, 0xad, - 0xf1, 0x07, 0x11, 0xc4, 0x11, 0xad, 0xf0, 0x19, - 0x04, 0x4a, 0x00, 0x00, 0x00, 0xcf, 0xd7, 0x41, - 0xcb, 0x01, 0x00, 0x00, 0xc4, 0x12, 0xc4, 0x13, - 0x34, 0x24, 0x01, 0x00, 0xd2, 0xf3, 0xa2, 0x00, - 0x11, 0x04, 0xf3, 0x01, 0x00, 0x00, 0xad, 0xf0, - 0x06, 0xbb, 0xd1, 0xf3, 0x94, 0x00, 0xe5, 0xd7, - 0xf5, 0xf0, 0x06, 0xd7, 0xef, 0xbb, 0x9d, 0xd1, - 0xd7, 0x41, 0xd3, 0x01, 0x00, 0x00, 0x04, 0xa8, - 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0xf0, 0x09, - 0x04, 0x45, 0x02, 0x00, 0x00, 0xcf, 0xf2, 0x71, - 0xd7, 0x41, 0xd3, 0x01, 0x00, 0x00, 0x04, 0xa4, - 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0xf0, 0x09, - 0x04, 0x4e, 0x00, 0x00, 0x00, 0xcf, 0xf2, 0x59, - 0xd7, 0x04, 0xfc, 0x00, 0x00, 0x00, 0xad, 0x11, - 0xf1, 0x09, 0x0e, 0xd7, 0x04, 0x46, 0x02, 0x00, - 0x00, 0xad, 0xf0, 0x09, 0x04, 0x47, 0x02, 0x00, - 0x00, 0xcf, 0xf2, 0x3d, 0xd7, 0x04, 0x03, 0x00, - 0x00, 0x00, 0xad, 0x11, 0xf1, 0x09, 0x0e, 0xd7, - 0x04, 0x02, 0x00, 0x00, 0x00, 0xad, 0xf0, 0x09, - 0x04, 0x4b, 0x00, 0x00, 0x00, 0xcf, 0xf2, 0x21, - 0xd7, 0x04, 0x01, 0x00, 0x00, 0x00, 0xad, 0xf0, - 0x09, 0x04, 0x01, 0x00, 0x00, 0x00, 0xcf, 0xf2, - 0x10, 0xd7, 0x04, 0x49, 0x00, 0x00, 0x00, 0xad, - 0xf0, 0x07, 0x04, 0x49, 0x00, 0x00, 0x00, 0xcf, - 0x0e, 0xce, 0xf0, 0x06, 0xce, 0xba, 0x46, 0xef, - 0xd1, 0xcd, 0xba, 0xa7, 0xf0, 0x0d, 0xd7, 0x41, - 0xbf, 0x01, 0x00, 0x00, 0xba, 0xcd, 0x24, 0x02, - 0x00, 0xd0, 0xe4, 0xcc, 0xcb, 0xf6, 0x0e, 0xd7, - 0x41, 0xbf, 0x01, 0x00, 0x00, 0xcc, 0xef, 0x24, - 0x01, 0x00, 0xdb, 0xf3, 0xea, 0xfd, 0x29, 0x0c, - 0x43, 0x02, 0x01, 0x92, 0x08, 0x01, 0x01, 0x01, - 0x03, 0x00, 0x00, 0x00, 0x19, 0x02, 0xf6, 0x06, - 0x00, 0x01, 0x00, 0x8c, 0x06, 0x00, 0x00, 0x00, - 0xd7, 0xd7, 0xef, 0xbb, 0x9d, 0x46, 0xd3, 0x04, - 0xed, 0x01, 0x00, 0x00, 0xad, 0x11, 0xf1, 0x09, - 0x0e, 0xcb, 0x04, 0x30, 0x02, 0x00, 0x00, 0xad, - 0x28, 0x0c, 0x43, 0x02, 0x01, 0x94, 0x08, 0x01, - 0x04, 0x01, 0x06, 0x00, 0x03, 0x00, 0x6e, 0x05, - 0x86, 0x06, 0x00, 0x01, 0x00, 0x90, 0x09, 0x00, - 0x00, 0x00, 0x92, 0x09, 0x00, 0x01, 0x00, 0x94, - 0x09, 0x00, 0x02, 0x00, 0xf6, 0x06, 0x00, 0x03, - 0x00, 0xfc, 0x07, 0x08, 0x00, 0x92, 0x08, 0x13, - 0x00, 0x94, 0x08, 0x14, 0x00, 0xe3, 0xd7, 0x46, - 0xef, 0xcf, 0xe3, 0xd7, 0xbb, 0x9c, 0x46, 0x04, - 0x37, 0x02, 0x00, 0x00, 0xad, 0xf0, 0x0e, 0xd7, - 0xbc, 0x9c, 0xdb, 0xcb, 0xbc, 0xe3, 0xd7, 0x46, - 0xef, 0x9c, 0x9c, 0xcf, 0xcb, 0xd0, 0xe4, 0xe3, - 0xd7, 0x46, 0xf5, 0xf0, 0x41, 0xbb, 0xd1, 0xd7, - 0x8e, 0xdf, 0xe3, 0xef, 0xa5, 0xf0, 0x37, 0xcd, - 0x93, 0x01, 0xe3, 0xd7, 0x46, 0xd6, 0x04, 0xc9, - 0x01, 0x00, 0x00, 0xad, 0x11, 0xf1, 0x09, 0x0e, - 0xce, 0x04, 0x31, 0x02, 0x00, 0x00, 0xad, 0xf1, - 0x1d, 0xf2, 0x0e, 0x11, 0x7e, 0x81, 0x00, 0x0e, - 0xdb, 0x81, 0x00, 0x0e, 0xcf, 0x83, 0xf2, 0x06, - 0xe5, 0xd7, 0xf5, 0xf2, 0xef, 0x0e, 0xcb, 0x93, - 0x01, 0xbc, 0xd1, 0xf2, 0xc3, 0xd7, 0xcc, 0x26, - 0x02, 0x00, 0x28, 0x0c, 0x43, 0x02, 0x01, 0x96, - 0x08, 0x02, 0x02, 0x02, 0x03, 0x00, 0x05, 0x00, - 0x67, 0x04, 0x86, 0x06, 0x00, 0x01, 0x00, 0x96, - 0x09, 0x00, 0x01, 0x00, 0xba, 0x08, 0x00, 0x00, - 0x00, 0xf6, 0x06, 0x00, 0x01, 0x00, 0xfc, 0x07, - 0x08, 0x00, 0x8c, 0x08, 0x10, 0x00, 0x8e, 0x08, - 0x11, 0x00, 0x90, 0x08, 0x12, 0x00, 0x92, 0x08, - 0x13, 0x00, 0xc6, 0xcf, 0xd7, 0xd8, 0xa6, 0xf0, - 0x60, 0xe3, 0xd7, 0x90, 0xdb, 0x46, 0xd4, 0x04, - 0xc9, 0x01, 0x00, 0x00, 0xad, 0x11, 0xf1, 0x09, - 0x0e, 0xcc, 0x04, 0x31, 0x02, 0x00, 0x00, 0xad, - 0xf0, 0x11, 0xcb, 0xef, 0xbb, 0xa7, 0xf0, 0x27, - 0xe4, 0x04, 0xe8, 0x01, 0x00, 0x00, 0xf5, 0x0e, - 0xf2, 0x1d, 0xe4, 0xcb, 0xf5, 0x0e, 0xe3, 0xd7, - 0x46, 0x04, 0x37, 0x02, 0x00, 0x00, 0xad, 0xf0, - 0x0e, 0xe5, 0xcc, 0xf5, 0x0e, 0xd7, 0x8e, 0xdb, - 0xe3, 0xd7, 0x90, 0xdb, 0x46, 0xd0, 0xe6, 0xcc, - 0xf5, 0x0e, 0x5d, 0x04, 0x00, 0xcc, 0xf5, 0xf0, - 0x08, 0x04, 0xe8, 0x01, 0x00, 0x00, 0xf2, 0x06, - 0x04, 0x4c, 0x02, 0x00, 0x00, 0xcf, 0xf2, 0x9d, - 0x29, 0x0c, 0x43, 0x02, 0x01, 0x98, 0x08, 0x02, - 0x00, 0x02, 0x04, 0x00, 0x01, 0x00, 0x1a, 0x02, - 0xf6, 0x06, 0x00, 0x01, 0x00, 0xca, 0x07, 0x00, - 0x01, 0x00, 0x8c, 0x08, 0x10, 0x00, 0xd8, 0xba, - 0xa7, 0xf0, 0x12, 0xd7, 0x04, 0xe8, 0x01, 0x00, - 0x00, 0x41, 0x4d, 0x02, 0x00, 0x00, 0xd8, 0x24, - 0x01, 0x00, 0x9c, 0xdb, 0xe3, 0xd7, 0xf5, 0x29, - 0x0c, 0x43, 0x02, 0x01, 0x9a, 0x08, 0x02, 0x0c, - 0x02, 0x07, 0x00, 0x0b, 0x00, 0xe7, 0x04, 0x0e, - 0x9c, 0x09, 0x00, 0x01, 0x00, 0x86, 0x02, 0x00, - 0x01, 0x00, 0x9e, 0x09, 0x00, 0x00, 0x00, 0x96, - 0x09, 0x00, 0x01, 0x00, 0x92, 0x09, 0x00, 0x02, - 0x00, 0xba, 0x08, 0x00, 0x03, 0x00, 0xa0, 0x09, - 0x00, 0x04, 0x00, 0x86, 0x06, 0x00, 0x05, 0x00, - 0x90, 0x09, 0x00, 0x06, 0x00, 0xac, 0x08, 0x00, - 0x07, 0x00, 0xb4, 0x07, 0x00, 0x08, 0x00, 0xa2, - 0x09, 0x00, 0x09, 0x00, 0xf4, 0x05, 0x00, 0x0a, - 0x00, 0xa4, 0x09, 0x00, 0x0b, 0x00, 0xf2, 0x07, - 0x02, 0x00, 0x94, 0x08, 0x14, 0x00, 0x96, 0x08, - 0x15, 0x00, 0xfc, 0x07, 0x08, 0x00, 0x8e, 0x08, - 0x11, 0x00, 0x90, 0x08, 0x12, 0x00, 0x92, 0x08, - 0x13, 0x00, 0xcc, 0x02, 0x10, 0x02, 0x8c, 0x08, - 0x10, 0x00, 0x98, 0x08, 0x16, 0x00, 0x9a, 0x08, - 0x17, 0x00, 0xe3, 0xd7, 0x9d, 0xbc, 0x9d, 0xcf, - 0x06, 0x11, 0xf8, 0xf1, 0x0d, 0x7e, 0x81, 0x00, - 0x0e, 0xd0, 0x81, 0x00, 0x0e, 0xd1, 0x83, 0xf2, - 0x07, 0x0e, 0xe4, 0xd8, 0xf5, 0xf2, 0xef, 0xcd, - 0xcb, 0xa6, 0xf0, 0x0c, 0xe5, 0xd8, 0xcc, 0xf6, - 0x0e, 0xcc, 0xcd, 0x26, 0x02, 0x00, 0x28, 0xe6, - 0xd8, 0xbb, 0x9c, 0x46, 0x04, 0x37, 0x02, 0x00, - 0x00, 0xad, 0xf0, 0x0d, 0x5d, 0x04, 0x00, 0xe6, - 0xd8, 0x46, 0xf5, 0x0e, 0xd8, 0xbc, 0x9c, 0xdc, - 0x5d, 0x05, 0x00, 0xe6, 0xd8, 0x46, 0xf5, 0x0e, - 0x5d, 0x06, 0x00, 0xe6, 0xd8, 0x46, 0xf5, 0x95, - 0xf0, 0x07, 0xd8, 0xcd, 0x26, 0x02, 0x00, 0x28, - 0xd7, 0xbc, 0x9c, 0xdb, 0xcb, 0xbc, 0x9d, 0xcf, - 0xc6, 0xd2, 0xd8, 0xbb, 0x9c, 0xc8, 0x04, 0xe6, - 0xd8, 0x46, 0x41, 0x53, 0x02, 0x00, 0x00, 0x04, - 0xed, 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, 0x68, - 0x8d, 0x01, 0x00, 0x00, 0xba, 0xc8, 0x07, 0x26, - 0x00, 0x00, 0xc8, 0x0a, 0xc7, 0x04, 0xc8, 0x05, - 0xc7, 0x05, 0xcc, 0xa5, 0xf0, 0x51, 0xe6, 0xc7, - 0x05, 0x46, 0xba, 0x46, 0x04, 0xbe, 0x01, 0x00, - 0x00, 0xad, 0x11, 0xf1, 0x0e, 0x0e, 0xe6, 0xc7, - 0x05, 0xbb, 0x9c, 0x46, 0x04, 0x37, 0x02, 0x00, - 0x00, 0xad, 0xf1, 0x33, 0xf2, 0x10, 0x11, 0x7e, - 0x81, 0x00, 0x0e, 0xc8, 0x05, 0x81, 0x00, 0x0e, - 0xc8, 0x06, 0x83, 0xf2, 0x07, 0xe4, 0xc7, 0x05, - 0xf5, 0xf2, 0xec, 0x0e, 0xc7, 0x0a, 0xc7, 0x07, - 0x90, 0xc8, 0x07, 0x1b, 0x11, 0xaf, 0xf1, 0x04, - 0x1b, 0x71, 0x1b, 0x1b, 0xc7, 0x06, 0x1b, 0x71, - 0x1b, 0x48, 0x92, 0x05, 0xf2, 0xab, 0x5d, 0x07, - 0x00, 0x41, 0xa5, 0x01, 0x00, 0x00, 0xcb, 0xbd, - 0x9a, 0xc7, 0x0a, 0xef, 0xc2, 0x10, 0x24, 0x03, - 0x00, 0xc8, 0x09, 0xc7, 0x09, 0xbb, 0xa7, 0xf0, - 0x73, 0x26, 0x00, 0x00, 0xc8, 0x0b, 0xba, 0xc8, - 0x08, 0xba, 0xc8, 0x07, 0xc7, 0x07, 0xc7, 0x0a, - 0xef, 0xa5, 0xf0, 0x3b, 0xc7, 0x0b, 0xc7, 0x08, - 0x1b, 0x11, 0xaf, 0xf1, 0x04, 0x1b, 0x71, 0x1b, - 0x1b, 0x5d, 0x07, 0x00, 0x41, 0xe1, 0x01, 0x00, - 0x00, 0xc7, 0x0b, 0xc7, 0x08, 0x46, 0x11, 0xf1, - 0x03, 0x0e, 0xba, 0xc7, 0x0a, 0xc7, 0x07, 0x46, - 0xbc, 0x9c, 0x24, 0x02, 0x00, 0x1b, 0x71, 0x1b, - 0x48, 0xc7, 0x08, 0xbb, 0x9c, 0xc7, 0x09, 0x9b, - 0xc8, 0x08, 0x92, 0x07, 0xf2, 0xbf, 0xba, 0xc8, - 0x06, 0xba, 0xc8, 0x08, 0xc7, 0x08, 0xc7, 0x09, - 0xa5, 0xf0, 0x0f, 0xc7, 0x06, 0xc7, 0x0b, 0xc7, - 0x08, 0x46, 0x9c, 0xc8, 0x06, 0x92, 0x08, 0xf2, - 0xec, 0xc7, 0x06, 0xcb, 0xa6, 0xf1, 0x05, 0x91, - 0x09, 0xf2, 0x89, 0xc7, 0x09, 0xbb, 0xa7, 0x68, - 0x95, 0x00, 0x00, 0x00, 0xba, 0xc8, 0x06, 0xc7, - 0x09, 0xbb, 0x9d, 0xc8, 0x08, 0xc7, 0x04, 0xc8, - 0x05, 0xc7, 0x05, 0xcc, 0xa5, 0xf0, 0x7b, 0xe6, - 0xc7, 0x05, 0x46, 0xba, 0x46, 0x04, 0xbe, 0x01, - 0x00, 0x00, 0xad, 0x11, 0xf1, 0x0e, 0x0e, 0xe6, - 0xc7, 0x05, 0xbb, 0x9c, 0x46, 0x04, 0x37, 0x02, - 0x00, 0x00, 0xad, 0xf1, 0x5d, 0xc7, 0x06, 0xce, - 0xef, 0x9c, 0xc8, 0x06, 0x5d, 0x08, 0x00, 0xce, - 0xf5, 0x0e, 0x04, 0x43, 0x02, 0x00, 0x00, 0xd2, - 0xc7, 0x08, 0xc7, 0x09, 0xbb, 0x9d, 0xad, 0xf0, - 0x11, 0x5d, 0x09, 0x00, 0x04, 0xa4, 0x01, 0x00, - 0x00, 0xd7, 0xf6, 0x0e, 0xba, 0xc8, 0x08, 0xf2, - 0x23, 0x5d, 0x09, 0x00, 0xc6, 0xc7, 0x0b, 0xc7, - 0x08, 0x90, 0xc8, 0x08, 0x46, 0xc7, 0x06, 0x9d, - 0xf6, 0x0e, 0xf2, 0x10, 0x11, 0x7e, 0x81, 0x00, - 0x0e, 0xc8, 0x05, 0x81, 0x00, 0x0e, 0xc8, 0x06, - 0x83, 0xf2, 0x0a, 0x5d, 0x0a, 0x00, 0xd7, 0xc7, - 0x05, 0xf6, 0xf2, 0xe9, 0x0e, 0x92, 0x05, 0xf2, - 0x81, 0xc7, 0x05, 0xc8, 0x04, 0xc7, 0x04, 0xc8, - 0x05, 0xc7, 0x05, 0xcc, 0xa5, 0xf0, 0x37, 0x5d, - 0x08, 0x00, 0xce, 0xf5, 0x0e, 0x04, 0x43, 0x02, - 0x00, 0x00, 0xd2, 0x5d, 0x09, 0x00, 0x04, 0xa4, - 0x01, 0x00, 0x00, 0xd7, 0xf6, 0x0e, 0xf2, 0x10, - 0x11, 0x7e, 0x81, 0x00, 0x0e, 0xc8, 0x05, 0x81, - 0x00, 0x0e, 0xc8, 0x06, 0x83, 0xf2, 0x0a, 0x5d, - 0x0a, 0x00, 0xd7, 0xc7, 0x05, 0xf6, 0xf2, 0xe9, - 0x0e, 0x92, 0x05, 0xf2, 0xc5, 0x5d, 0x09, 0x00, - 0x04, 0xa4, 0x01, 0x00, 0x00, 0xd7, 0xbc, 0x9d, - 0xdf, 0xf6, 0x0e, 0x5d, 0x05, 0x00, 0xe6, 0xcc, - 0x46, 0xf5, 0x0e, 0xcc, 0xe3, 0x26, 0x02, 0x00, - 0x28, 0xc5, 0x00, 0xd0, 0xc5, 0x01, 0xc8, 0x0b, - 0xc5, 0x02, 0xc8, 0x0c, 0xc5, 0x03, 0xc8, 0x0d, - 0xc5, 0x04, 0xc8, 0x0e, 0xc5, 0x05, 0xc8, 0x0f, - 0xc5, 0x06, 0xc8, 0x10, 0xc5, 0x07, 0xc8, 0x11, - 0xc5, 0x08, 0xc8, 0x12, 0xc5, 0x09, 0xc8, 0x13, - 0xc5, 0x0a, 0xc8, 0x14, 0xc5, 0x0b, 0xc8, 0x15, - 0xc5, 0x0c, 0xc8, 0x16, 0xc5, 0x0d, 0xc8, 0x17, - 0x0b, 0xcf, 0xd8, 0x96, 0x04, 0x4d, 0x00, 0x00, - 0x00, 0xad, 0xf0, 0x1c, 0xd8, 0x07, 0xae, 0xf0, - 0x17, 0xd8, 0xd3, 0x40, 0x54, 0x02, 0x00, 0x00, - 0xdc, 0xcb, 0x40, 0x55, 0x02, 0x00, 0x00, 0xdd, - 0xcb, 0x40, 0xff, 0x00, 0x00, 0x00, 0xde, 0xd8, - 0x96, 0x04, 0x4b, 0x00, 0x00, 0x00, 0xae, 0xf0, - 0x03, 0x09, 0xdc, 0xcc, 0xd9, 0xbc, 0xf6, 0xdd, - 0xcc, 0xda, 0x0a, 0xf6, 0xde, 0xcc, 0xcb, 0x40, - 0xf9, 0x01, 0x00, 0x00, 0x5d, 0x10, 0x00, 0x41, - 0xa5, 0x01, 0x00, 0x00, 0x5d, 0x11, 0x00, 0xc2, - 0x50, 0x24, 0x02, 0x00, 0xf6, 0xd1, 0xcc, 0xcb, - 0x40, 0xfa, 0x01, 0x00, 0x00, 0xc2, 0x64, 0xf6, - 0xd2, 0xcc, 0xcb, 0x40, 0xfb, 0x01, 0x00, 0x00, - 0xce, 0xc2, 0x0a, 0x9c, 0xf6, 0xc8, 0x04, 0xcc, - 0xcb, 0x40, 0xfc, 0x01, 0x00, 0x00, 0xc2, 0x4e, - 0xf6, 0xc8, 0x05, 0x0b, 0x26, 0x01, 0x00, 0xc8, - 0x06, 0x26, 0x00, 0x00, 0xc8, 0x07, 0x26, 0x00, - 0x00, 0xc8, 0x08, 0x26, 0x00, 0x00, 0xc8, 0x09, - 0x04, 0x9e, 0x01, 0x00, 0x00, 0xc8, 0x0a, 0xc7, - 0x0f, 0xd7, 0xba, 0xf6, 0x0e, 0xc7, 0x17, 0xba, - 0xba, 0xf6, 0x0e, 0xc7, 0x10, 0xc6, 0xf5, 0x0e, - 0xc7, 0x09, 0x41, 0x63, 0x00, 0x00, 0x00, 0xc6, - 0x25, 0x01, 0x00, 0x0c, 0x43, 0x02, 0x01, 0xcc, - 0x05, 0x01, 0x00, 0x01, 0x07, 0x00, 0x05, 0x00, - 0x3c, 0x01, 0xea, 0x07, 0x00, 0x01, 0x00, 0xec, - 0x03, 0x00, 0x1a, 0xca, 0x05, 0x78, 0x00, 0x8c, - 0x04, 0x19, 0x00, 0x88, 0x04, 0x17, 0x00, 0x8a, - 0x04, 0x18, 0x00, 0x64, 0x00, 0x00, 0x41, 0x9d, - 0x01, 0x00, 0x00, 0xe4, 0x41, 0x56, 0x02, 0x00, - 0x00, 0xd7, 0x0b, 0xe5, 0x4b, 0x55, 0x02, 0x00, - 0x00, 0xe6, 0x4b, 0xff, 0x00, 0x00, 0x00, 0x5d, - 0x04, 0x00, 0x4b, 0x54, 0x02, 0x00, 0x00, 0x24, - 0x02, 0x00, 0x24, 0x01, 0x00, 0x0e, 0x64, 0x00, - 0x00, 0x41, 0x9d, 0x01, 0x00, 0x00, 0x04, 0xa4, - 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, 0x29, 0x0c, - 0x43, 0x02, 0x01, 0xce, 0x05, 0x01, 0x05, 0x01, - 0x06, 0x00, 0x03, 0x00, 0xb4, 0x01, 0x06, 0x92, - 0x06, 0x00, 0x01, 0x00, 0xde, 0x06, 0x00, 0x00, - 0x00, 0xaa, 0x04, 0x00, 0x01, 0x00, 0xae, 0x09, - 0x00, 0x02, 0x00, 0xe0, 0x07, 0x00, 0x03, 0x00, - 0xb0, 0x09, 0x00, 0x04, 0x00, 0xd0, 0x05, 0x7b, - 0x00, 0xd8, 0x05, 0x7f, 0x00, 0xec, 0x03, 0x00, - 0x1a, 0xd7, 0x04, 0x59, 0x02, 0x00, 0x00, 0xad, - 0xf0, 0x06, 0xe3, 0xf4, 0x0e, 0x0a, 0x28, 0xd7, - 0xba, 0x46, 0x04, 0xc3, 0x01, 0x00, 0x00, 0xae, - 0xf0, 0x0e, 0xd7, 0xba, 0x46, 0x04, 0xbe, 0x01, - 0x00, 0x00, 0xae, 0xf0, 0x03, 0x09, 0x28, 0xbb, - 0xcf, 0xcb, 0xd7, 0xef, 0xa5, 0xf0, 0x10, 0xd7, - 0xcb, 0x46, 0x04, 0xe8, 0x01, 0x00, 0x00, 0xae, - 0xf0, 0x05, 0x92, 0x00, 0xf2, 0xec, 0xd7, 0x41, - 0x9f, 0x01, 0x00, 0x00, 0xbb, 0xcb, 0x24, 0x02, - 0x00, 0xd0, 0xba, 0xd1, 0xe4, 0x7d, 0xf2, 0x21, - 0xc8, 0x04, 0xc7, 0x04, 0x41, 0xd3, 0x01, 0x00, - 0x00, 0xcc, 0x24, 0x01, 0x00, 0xf0, 0x12, 0xe4, - 0xc7, 0x04, 0x46, 0xd2, 0x92, 0x02, 0xc7, 0x04, - 0xcc, 0xad, 0xf0, 0x05, 0xba, 0xd1, 0xf2, 0x05, - 0x80, 0xf0, 0xde, 0x0e, 0x0e, 0xce, 0xf0, 0x1d, - 0xcd, 0xbc, 0xa5, 0xf0, 0x18, 0xce, 0xd7, 0x41, - 0x9f, 0x01, 0x00, 0x00, 0xcb, 0x24, 0x01, 0x00, - 0x41, 0x5a, 0x02, 0x00, 0x00, 0x24, 0x00, 0x00, - 0xf5, 0x0e, 0xf2, 0x20, 0x64, 0x02, 0x00, 0x41, - 0x9d, 0x01, 0x00, 0x00, 0x04, 0x5b, 0x02, 0x00, - 0x00, 0x41, 0x64, 0x00, 0x00, 0x00, 0xcc, 0x04, - 0xa4, 0x01, 0x00, 0x00, 0x24, 0x02, 0x00, 0x24, - 0x01, 0x00, 0x0e, 0x0a, 0x28, 0x0c, 0x43, 0x02, - 0x01, 0xd0, 0x05, 0x00, 0x01, 0x00, 0x07, 0x00, - 0x09, 0x01, 0xdc, 0x01, 0x01, 0xb8, 0x09, 0x00, - 0x00, 0x00, 0xec, 0x03, 0x00, 0x1a, 0x8e, 0x04, - 0x1a, 0x00, 0x86, 0x04, 0x16, 0x00, 0x90, 0x04, - 0x1b, 0x00, 0x8c, 0x04, 0x19, 0x00, 0x8a, 0x04, - 0x18, 0x00, 0x88, 0x04, 0x17, 0x00, 0x82, 0x04, - 0x14, 0x00, 0x80, 0x04, 0x13, 0x00, 0x0c, 0x42, - 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, - 0x00, 0x00, 0x0f, 0x01, 0xc0, 0x06, 0x00, 0x01, - 0x00, 0xd7, 0xf0, 0x07, 0x04, 0x87, 0x00, 0x00, - 0x00, 0x28, 0x04, 0xe8, 0x01, 0x00, 0x00, 0x28, - 0xc5, 0x00, 0x4c, 0x5c, 0x02, 0x00, 0x00, 0xcf, - 0x64, 0x00, 0x00, 0x41, 0x9d, 0x01, 0x00, 0x00, - 0x04, 0x5d, 0x02, 0x00, 0x00, 0x04, 0x5e, 0x02, - 0x00, 0x00, 0x9c, 0xcb, 0xe4, 0xf5, 0x9c, 0x04, - 0x5f, 0x02, 0x00, 0x00, 0x9c, 0x04, 0x60, 0x02, - 0x00, 0x00, 0x9c, 0xcb, 0xe4, 0x95, 0xf5, 0x9c, - 0x04, 0x61, 0x02, 0x00, 0x00, 0x9c, 0x04, 0x62, - 0x02, 0x00, 0x00, 0x9c, 0xcb, 0xe5, 0xf5, 0x9c, - 0x04, 0x63, 0x02, 0x00, 0x00, 0x9c, 0x04, 0x64, - 0x02, 0x00, 0x00, 0x9c, 0xcb, 0xe6, 0xf5, 0x9c, - 0x04, 0x65, 0x02, 0x00, 0x00, 0x9c, 0x04, 0x66, - 0x02, 0x00, 0x00, 0x41, 0x64, 0x00, 0x00, 0x00, - 0x5d, 0x04, 0x00, 0x04, 0x67, 0x02, 0x00, 0x00, - 0x24, 0x02, 0x00, 0x9c, 0x04, 0x68, 0x02, 0x00, - 0x00, 0x9c, 0xcb, 0x5d, 0x05, 0x00, 0xf5, 0x9c, - 0x04, 0x69, 0x02, 0x00, 0x00, 0x9c, 0x04, 0x6a, - 0x02, 0x00, 0x00, 0x9c, 0xcb, 0x5d, 0x06, 0x00, - 0xf5, 0x9c, 0x04, 0x6b, 0x02, 0x00, 0x00, 0x9c, - 0x04, 0x6c, 0x02, 0x00, 0x00, 0x9c, 0xcb, 0x5d, - 0x07, 0x00, 0x5d, 0x08, 0x00, 0x40, 0x6d, 0x02, - 0x00, 0x00, 0xab, 0xf5, 0x9c, 0x04, 0x6e, 0x02, - 0x00, 0x00, 0x9c, 0x04, 0x6f, 0x02, 0x00, 0x00, - 0x9c, 0xcb, 0x5d, 0x07, 0x00, 0x5d, 0x08, 0x00, - 0x40, 0x70, 0x02, 0x00, 0x00, 0xab, 0xf5, 0x9c, - 0x04, 0x71, 0x02, 0x00, 0x00, 0x9c, 0x04, 0x72, - 0x02, 0x00, 0x00, 0x9c, 0x04, 0x73, 0x02, 0x00, - 0x00, 0x9c, 0x04, 0x74, 0x02, 0x00, 0x00, 0x9c, + 0x07, 0xa2, 0x01, 0x00, 0x00, 0x02, 0x01, 0x49, + 0x00, 0x00, 0x00, 0x0e, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x0d, 0xf5, 0xff, 0xff, 0xff, 0x13, 0x00, + 0x09, 0x01, 0x27, 0x00, 0x0f, 0x2d, 0x00, 0x00, + 0x00, 0x2a, 0x00, 0x15, 0x01, 0x01, 0x13, 0x01, + 0x0f, 0x14, 0x00, 0x00, 0x00, 0x24, 0x03, 0x00, + 0x00, 0x00, 0x26, 0x00, 0x28, 0x00, 0x5b, 0x00, + 0x5d, 0x00, 0xff, 0xff, 0x0d, 0x04, 0x00, 0x00, + 0x00, 0x01, 0x5c, 0x00, 0x05, 0x14, 0x01, 0x2b, + 0x00, 0x0d, 0xce, 0xff, 0xff, 0xff, 0x01, 0x27, + 0x00, 0x14, 0x00, 0x10, 0x07, 0x16, 0x5e, 0x5c, + 0x3c, 0x5b, 0x5e, 0x5c, 0x3e, 0x5d, 0x2b, 0x5c, + 0x3e, 0x07, 0x5e, 0x00, 0x00, 0x01, 0x00, 0x27, + 0x00, 0x00, 0x00, 0x0e, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x0d, 0xf5, 0xff, 0xff, 0xff, 0x13, 0x00, + 0x09, 0x01, 0x3c, 0x00, 0x24, 0x02, 0x00, 0x00, + 0x00, 0x3d, 0x00, 0x3f, 0x00, 0xff, 0xff, 0x0e, + 0xf0, 0xff, 0xff, 0xff, 0x01, 0x3e, 0x00, 0x14, + 0x00, 0x10, 0x07, 0x16, 0x5e, 0x5c, 0x5b, 0x5b, + 0x5e, 0x5c, 0x5d, 0x5d, 0x2b, 0x5c, 0x5d, 0x07, + 0x5e, 0x00, 0x00, 0x01, 0x00, 0x27, 0x00, 0x00, + 0x00, 0x0e, 0x06, 0x00, 0x00, 0x00, 0x06, 0x0d, + 0xf5, 0xff, 0xff, 0xff, 0x13, 0x00, 0x09, 0x01, + 0x5b, 0x00, 0x24, 0x02, 0x00, 0x00, 0x00, 0x5c, + 0x00, 0x5e, 0x00, 0xff, 0xff, 0x0e, 0xf0, 0xff, + 0xff, 0xff, 0x01, 0x5d, 0x00, 0x14, 0x00, 0x10, + 0x07, 0x02, 0x30, 0x07, 0x02, 0x31, 0x07, 0x02, + 0x32, 0x07, 0x02, 0x33, 0x07, 0x02, 0x34, 0x07, + 0x02, 0x35, 0x07, 0x02, 0x36, 0x07, 0x02, 0x37, + 0x07, 0x02, 0x38, 0x07, 0x02, 0x39, 0x07, 0x56, + 0x5e, 0x5b, 0x30, 0x2d, 0x39, 0x61, 0x2d, 0x7a, + 0x5f, 0x5d, 0x2b, 0x5b, 0x2e, 0x5d, 0x3f, 0x5b, + 0x30, 0x2d, 0x39, 0x61, 0x2d, 0x7a, 0x5f, 0x5d, + 0x2a, 0x5b, 0x65, 0x45, 0x70, 0x50, 0x5d, 0x3f, + 0x5b, 0x2b, 0x2d, 0x5d, 0x3f, 0x5b, 0x30, 0x2d, + 0x39, 0x5d, 0x2a, 0x07, 0x96, 0x02, 0x00, 0x00, + 0x01, 0x00, 0x83, 0x00, 0x00, 0x00, 0x0e, 0x06, + 0x00, 0x00, 0x00, 0x06, 0x0d, 0xf5, 0xff, 0xff, + 0xff, 0x13, 0x00, 0x09, 0x24, 0x03, 0x00, 0x30, + 0x00, 0x39, 0x00, 0x5f, 0x00, 0x5f, 0x00, 0x61, + 0x00, 0x7a, 0x00, 0x0e, 0xec, 0xff, 0xff, 0xff, + 0x0f, 0x07, 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, + 0x2e, 0x00, 0x2e, 0x00, 0x0f, 0x14, 0x00, 0x00, + 0x00, 0x24, 0x03, 0x00, 0x30, 0x00, 0x39, 0x00, + 0x5f, 0x00, 0x5f, 0x00, 0x61, 0x00, 0x7a, 0x00, + 0x0d, 0xe7, 0xff, 0xff, 0xff, 0x0f, 0x13, 0x00, + 0x00, 0x00, 0x24, 0x04, 0x00, 0x45, 0x00, 0x45, + 0x00, 0x50, 0x00, 0x50, 0x00, 0x65, 0x00, 0x65, + 0x00, 0x70, 0x00, 0x70, 0x00, 0x0f, 0x0b, 0x00, + 0x00, 0x00, 0x24, 0x02, 0x00, 0x2b, 0x00, 0x2b, + 0x00, 0x2d, 0x00, 0x2d, 0x00, 0x0f, 0x0c, 0x00, + 0x00, 0x00, 0x24, 0x01, 0x00, 0x30, 0x00, 0x39, + 0x00, 0x0d, 0xef, 0xff, 0xff, 0xff, 0x14, 0x00, + 0x10, 0xe3, 0x95, 0xf0, 0x05, 0xe4, 0xd7, 0xf5, + 0x29, 0xd7, 0xef, 0xba, 0xa7, 0x68, 0x13, 0x02, + 0x00, 0x00, 0x04, 0x9e, 0x01, 0x00, 0x00, 0xcf, + 0xd7, 0xd0, 0xba, 0xd1, 0x07, 0xd2, 0xd7, 0xba, + 0x46, 0x11, 0x04, 0xc7, 0x01, 0x00, 0x00, 0xad, + 0xf0, 0x19, 0x04, 0x4c, 0x00, 0x00, 0x00, 0xcf, + 0xd7, 0x41, 0xcb, 0x01, 0x00, 0x00, 0xc4, 0x00, + 0xc4, 0x01, 0x34, 0x24, 0x01, 0x00, 0xd2, 0xf3, + 0xb3, 0x01, 0x11, 0x04, 0xc6, 0x01, 0x00, 0x00, + 0xad, 0xf0, 0x19, 0x04, 0x4c, 0x00, 0x00, 0x00, + 0xcf, 0xd7, 0x41, 0xcb, 0x01, 0x00, 0x00, 0xc4, + 0x02, 0xc4, 0x03, 0x34, 0x24, 0x01, 0x00, 0xd2, + 0xf3, 0x92, 0x01, 0x11, 0x04, 0xca, 0x01, 0x00, + 0x00, 0xad, 0xf0, 0x0a, 0x04, 0x41, 0x02, 0x00, + 0x00, 0xcf, 0xf3, 0x80, 0x01, 0x11, 0x04, 0x32, + 0x02, 0x00, 0x00, 0xad, 0xf0, 0x1e, 0xd7, 0x41, + 0xcb, 0x01, 0x00, 0x00, 0xc4, 0x04, 0xc4, 0x05, + 0x34, 0x24, 0x01, 0x00, 0xd6, 0x68, 0x65, 0x01, + 0x00, 0x00, 0x04, 0x42, 0x02, 0x00, 0x00, 0xcf, + 0xf3, 0x5a, 0x01, 0x11, 0x04, 0xed, 0x01, 0x00, + 0x00, 0xad, 0xf0, 0x1b, 0xd7, 0x41, 0xcb, 0x01, + 0x00, 0x00, 0xc4, 0x06, 0xc4, 0x07, 0x34, 0x24, + 0x01, 0x00, 0xd6, 0xf0, 0x2e, 0x04, 0x42, 0x02, + 0x00, 0x00, 0xcf, 0xf3, 0x37, 0x01, 0x11, 0x04, + 0xc9, 0x01, 0x00, 0x00, 0xad, 0xf1, 0x1c, 0x11, + 0x04, 0x31, 0x02, 0x00, 0x00, 0xad, 0xf1, 0x13, + 0x11, 0x04, 0x43, 0x02, 0x00, 0x00, 0xad, 0xf1, + 0x0a, 0x11, 0x04, 0xe8, 0x01, 0x00, 0x00, 0xad, + 0xf0, 0x0c, 0x04, 0x44, 0x02, 0x00, 0x00, 0xcf, + 0xbb, 0xd1, 0xf3, 0x08, 0x01, 0x11, 0x04, 0xbe, + 0x01, 0x00, 0x00, 0xad, 0xf0, 0x0a, 0x04, 0x42, + 0x02, 0x00, 0x00, 0xcf, 0xf3, 0xf6, 0x00, 0x11, + 0xc4, 0x08, 0xad, 0xf1, 0x37, 0x11, 0xc4, 0x09, + 0xad, 0xf1, 0x31, 0x11, 0xc4, 0x0a, 0xad, 0xf1, + 0x2b, 0x11, 0xc4, 0x0b, 0xad, 0xf1, 0x25, 0x11, + 0xc4, 0x0c, 0xad, 0xf1, 0x1f, 0x11, 0xc4, 0x0d, + 0xad, 0xf1, 0x19, 0x11, 0xc4, 0x0e, 0xad, 0xf1, + 0x13, 0x11, 0xc4, 0x0f, 0xad, 0xf1, 0x0d, 0x11, + 0xc4, 0x10, 0xad, 0xf1, 0x07, 0x11, 0xc4, 0x11, + 0xad, 0xf0, 0x19, 0x04, 0x4a, 0x00, 0x00, 0x00, + 0xcf, 0xd7, 0x41, 0xcb, 0x01, 0x00, 0x00, 0xc4, + 0x12, 0xc4, 0x13, 0x34, 0x24, 0x01, 0x00, 0xd2, + 0xf3, 0xa2, 0x00, 0x11, 0x04, 0xf3, 0x01, 0x00, + 0x00, 0xad, 0xf0, 0x06, 0xbb, 0xd1, 0xf3, 0x94, + 0x00, 0xe5, 0xd7, 0xf5, 0xf0, 0x06, 0xd7, 0xef, + 0xbb, 0x9d, 0xd1, 0xd7, 0x41, 0xd3, 0x01, 0x00, + 0x00, 0x04, 0xa8, 0x00, 0x00, 0x00, 0x24, 0x01, + 0x00, 0xf0, 0x09, 0x04, 0x45, 0x02, 0x00, 0x00, + 0xcf, 0xf2, 0x71, 0xd7, 0x41, 0xd3, 0x01, 0x00, + 0x00, 0x04, 0xa4, 0x00, 0x00, 0x00, 0x24, 0x01, + 0x00, 0xf0, 0x09, 0x04, 0x4e, 0x00, 0x00, 0x00, + 0xcf, 0xf2, 0x59, 0xd7, 0x04, 0xfc, 0x00, 0x00, + 0x00, 0xad, 0x11, 0xf1, 0x09, 0x0e, 0xd7, 0x04, + 0x46, 0x02, 0x00, 0x00, 0xad, 0xf0, 0x09, 0x04, + 0x47, 0x02, 0x00, 0x00, 0xcf, 0xf2, 0x3d, 0xd7, + 0x04, 0x03, 0x00, 0x00, 0x00, 0xad, 0x11, 0xf1, + 0x09, 0x0e, 0xd7, 0x04, 0x02, 0x00, 0x00, 0x00, + 0xad, 0xf0, 0x09, 0x04, 0x4b, 0x00, 0x00, 0x00, + 0xcf, 0xf2, 0x21, 0xd7, 0x04, 0x01, 0x00, 0x00, + 0x00, 0xad, 0xf0, 0x09, 0x04, 0x01, 0x00, 0x00, + 0x00, 0xcf, 0xf2, 0x10, 0xd7, 0x04, 0x49, 0x00, + 0x00, 0x00, 0xad, 0xf0, 0x07, 0x04, 0x49, 0x00, + 0x00, 0x00, 0xcf, 0x0e, 0xce, 0xf0, 0x06, 0xce, + 0xba, 0x46, 0xef, 0xd1, 0xcd, 0xba, 0xa7, 0xf0, + 0x0d, 0xd7, 0x41, 0xbf, 0x01, 0x00, 0x00, 0xba, + 0xcd, 0x24, 0x02, 0x00, 0xd0, 0xe4, 0xcc, 0xcb, + 0xf6, 0x0e, 0xd7, 0x41, 0xbf, 0x01, 0x00, 0x00, + 0xcc, 0xef, 0x24, 0x01, 0x00, 0xdb, 0xf3, 0xea, + 0xfd, 0x29, 0x0c, 0x43, 0x02, 0x01, 0x92, 0x08, + 0x01, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x19, + 0x02, 0xf6, 0x06, 0x00, 0x01, 0x00, 0x8c, 0x06, + 0x00, 0x00, 0x00, 0xd7, 0xd7, 0xef, 0xbb, 0x9d, + 0x46, 0xd3, 0x04, 0xed, 0x01, 0x00, 0x00, 0xad, + 0x11, 0xf1, 0x09, 0x0e, 0xcb, 0x04, 0x30, 0x02, + 0x00, 0x00, 0xad, 0x28, 0x0c, 0x43, 0x02, 0x01, + 0x94, 0x08, 0x01, 0x04, 0x01, 0x06, 0x00, 0x03, + 0x00, 0x6e, 0x05, 0x86, 0x06, 0x00, 0x01, 0x00, + 0x90, 0x09, 0x00, 0x00, 0x00, 0x92, 0x09, 0x00, + 0x01, 0x00, 0x94, 0x09, 0x00, 0x02, 0x00, 0xf6, + 0x06, 0x00, 0x03, 0x00, 0xfc, 0x07, 0x08, 0x00, + 0x92, 0x08, 0x13, 0x00, 0x94, 0x08, 0x14, 0x00, + 0xe3, 0xd7, 0x46, 0xef, 0xcf, 0xe3, 0xd7, 0xbb, + 0x9c, 0x46, 0x04, 0x37, 0x02, 0x00, 0x00, 0xad, + 0xf0, 0x0e, 0xd7, 0xbc, 0x9c, 0xdb, 0xcb, 0xbc, + 0xe3, 0xd7, 0x46, 0xef, 0x9c, 0x9c, 0xcf, 0xcb, + 0xd0, 0xe4, 0xe3, 0xd7, 0x46, 0xf5, 0xf0, 0x41, + 0xbb, 0xd1, 0xd7, 0x8e, 0xdf, 0xe3, 0xef, 0xa5, + 0xf0, 0x37, 0xcd, 0x93, 0x01, 0xe3, 0xd7, 0x46, + 0xd6, 0x04, 0xc9, 0x01, 0x00, 0x00, 0xad, 0x11, + 0xf1, 0x09, 0x0e, 0xce, 0x04, 0x31, 0x02, 0x00, + 0x00, 0xad, 0xf1, 0x1d, 0xf2, 0x0e, 0x11, 0x7e, + 0x81, 0x00, 0x0e, 0xdb, 0x81, 0x00, 0x0e, 0xcf, + 0x83, 0xf2, 0x06, 0xe5, 0xd7, 0xf5, 0xf2, 0xef, + 0x0e, 0xcb, 0x93, 0x01, 0xbc, 0xd1, 0xf2, 0xc3, + 0xd7, 0xcc, 0x26, 0x02, 0x00, 0x28, 0x0c, 0x43, + 0x02, 0x01, 0x96, 0x08, 0x02, 0x02, 0x02, 0x03, + 0x00, 0x05, 0x00, 0x67, 0x04, 0x86, 0x06, 0x00, + 0x01, 0x00, 0x96, 0x09, 0x00, 0x01, 0x00, 0xba, + 0x08, 0x00, 0x00, 0x00, 0xf6, 0x06, 0x00, 0x01, + 0x00, 0xfc, 0x07, 0x08, 0x00, 0x8c, 0x08, 0x10, + 0x00, 0x8e, 0x08, 0x11, 0x00, 0x90, 0x08, 0x12, + 0x00, 0x92, 0x08, 0x13, 0x00, 0xc6, 0xcf, 0xd7, + 0xd8, 0xa6, 0xf0, 0x60, 0xe3, 0xd7, 0x90, 0xdb, + 0x46, 0xd4, 0x04, 0xc9, 0x01, 0x00, 0x00, 0xad, + 0x11, 0xf1, 0x09, 0x0e, 0xcc, 0x04, 0x31, 0x02, + 0x00, 0x00, 0xad, 0xf0, 0x11, 0xcb, 0xef, 0xbb, + 0xa7, 0xf0, 0x27, 0xe4, 0x04, 0xe8, 0x01, 0x00, + 0x00, 0xf5, 0x0e, 0xf2, 0x1d, 0xe4, 0xcb, 0xf5, + 0x0e, 0xe3, 0xd7, 0x46, 0x04, 0x37, 0x02, 0x00, + 0x00, 0xad, 0xf0, 0x0e, 0xe5, 0xcc, 0xf5, 0x0e, + 0xd7, 0x8e, 0xdb, 0xe3, 0xd7, 0x90, 0xdb, 0x46, + 0xd0, 0xe6, 0xcc, 0xf5, 0x0e, 0x5d, 0x04, 0x00, + 0xcc, 0xf5, 0xf0, 0x08, 0x04, 0xe8, 0x01, 0x00, + 0x00, 0xf2, 0x06, 0x04, 0x4c, 0x02, 0x00, 0x00, + 0xcf, 0xf2, 0x9d, 0x29, 0x0c, 0x43, 0x02, 0x01, + 0x98, 0x08, 0x02, 0x00, 0x02, 0x04, 0x00, 0x01, + 0x00, 0x1a, 0x02, 0xf6, 0x06, 0x00, 0x01, 0x00, + 0xca, 0x07, 0x00, 0x01, 0x00, 0x8c, 0x08, 0x10, + 0x00, 0xd8, 0xba, 0xa7, 0xf0, 0x12, 0xd7, 0x04, + 0xe8, 0x01, 0x00, 0x00, 0x41, 0x4d, 0x02, 0x00, + 0x00, 0xd8, 0x24, 0x01, 0x00, 0x9c, 0xdb, 0xe3, + 0xd7, 0xf5, 0x29, 0x0c, 0x43, 0x02, 0x01, 0x9a, + 0x08, 0x02, 0x0c, 0x02, 0x07, 0x00, 0x0b, 0x00, + 0xeb, 0x04, 0x0e, 0x9c, 0x09, 0x00, 0x01, 0x00, + 0x86, 0x02, 0x00, 0x01, 0x00, 0x9e, 0x09, 0x00, + 0x00, 0x00, 0x96, 0x09, 0x00, 0x01, 0x00, 0x92, + 0x09, 0x00, 0x02, 0x00, 0xba, 0x08, 0x00, 0x03, + 0x00, 0xa0, 0x09, 0x00, 0x04, 0x00, 0x86, 0x06, + 0x00, 0x05, 0x00, 0x90, 0x09, 0x00, 0x06, 0x00, + 0xac, 0x08, 0x00, 0x07, 0x00, 0xb4, 0x07, 0x00, + 0x08, 0x00, 0xa2, 0x09, 0x00, 0x09, 0x00, 0xf4, + 0x05, 0x00, 0x0a, 0x00, 0xa4, 0x09, 0x00, 0x0b, + 0x00, 0xf2, 0x07, 0x02, 0x00, 0x94, 0x08, 0x14, + 0x00, 0x96, 0x08, 0x15, 0x00, 0xfc, 0x07, 0x08, + 0x00, 0x8e, 0x08, 0x11, 0x00, 0x90, 0x08, 0x12, + 0x00, 0x92, 0x08, 0x13, 0x00, 0xcc, 0x02, 0x10, + 0x02, 0x8c, 0x08, 0x10, 0x00, 0x98, 0x08, 0x16, + 0x00, 0x9a, 0x08, 0x17, 0x00, 0xe3, 0xd7, 0x9d, + 0xbc, 0x9d, 0xcf, 0x06, 0x11, 0xf8, 0xf1, 0x0d, + 0x7e, 0x81, 0x00, 0x0e, 0xd0, 0x81, 0x00, 0x0e, + 0xd1, 0x83, 0xf2, 0x07, 0x0e, 0xe4, 0xd8, 0xf5, + 0xf2, 0xef, 0xcd, 0xcb, 0xa6, 0xf0, 0x0c, 0xe5, + 0xd8, 0xcc, 0xf6, 0x0e, 0xcc, 0xcd, 0x26, 0x02, + 0x00, 0x28, 0xe6, 0xd8, 0xbb, 0x9c, 0x46, 0x04, + 0x37, 0x02, 0x00, 0x00, 0xad, 0xf0, 0x0d, 0x5d, + 0x04, 0x00, 0xe6, 0xd8, 0x46, 0xf5, 0x0e, 0xd8, + 0xbc, 0x9c, 0xdc, 0x5d, 0x05, 0x00, 0xe6, 0xd8, + 0x46, 0xf5, 0x0e, 0x5d, 0x06, 0x00, 0xe6, 0xd8, + 0x46, 0xf5, 0x95, 0xf0, 0x07, 0xd8, 0xcd, 0x26, + 0x02, 0x00, 0x28, 0xd7, 0xbc, 0x9c, 0xdb, 0xcb, + 0xbc, 0x9d, 0xcf, 0xc6, 0xd2, 0xd8, 0xbb, 0x9c, + 0xc8, 0x04, 0xe6, 0xd8, 0x46, 0x41, 0x53, 0x02, + 0x00, 0x00, 0x04, 0xed, 0x01, 0x00, 0x00, 0x24, + 0x01, 0x00, 0x68, 0x91, 0x01, 0x00, 0x00, 0xba, + 0xc8, 0x07, 0x26, 0x00, 0x00, 0xc8, 0x0a, 0xc7, + 0x04, 0xc8, 0x05, 0xc7, 0x05, 0xcc, 0xa5, 0xf0, + 0x51, 0xe6, 0xc7, 0x05, 0x46, 0xba, 0x46, 0x04, + 0xbe, 0x01, 0x00, 0x00, 0xad, 0x11, 0xf1, 0x0e, + 0x0e, 0xe6, 0xc7, 0x05, 0xbb, 0x9c, 0x46, 0x04, + 0x37, 0x02, 0x00, 0x00, 0xad, 0xf1, 0x33, 0xf2, + 0x10, 0x11, 0x7e, 0x81, 0x00, 0x0e, 0xc8, 0x05, + 0x81, 0x00, 0x0e, 0xc8, 0x06, 0x83, 0xf2, 0x07, + 0xe4, 0xc7, 0x05, 0xf5, 0xf2, 0xec, 0x0e, 0xc7, + 0x0a, 0xc7, 0x07, 0x90, 0xc8, 0x07, 0x1b, 0x11, + 0xaf, 0xf1, 0x04, 0x1b, 0x71, 0x1b, 0x1b, 0xc7, + 0x06, 0x1b, 0x71, 0x1b, 0x48, 0x92, 0x05, 0xf2, + 0xab, 0x5d, 0x07, 0x00, 0x41, 0xa5, 0x01, 0x00, + 0x00, 0xcb, 0xbd, 0x9a, 0xc7, 0x0a, 0xef, 0xc2, + 0x10, 0x24, 0x03, 0x00, 0xc8, 0x09, 0xc7, 0x09, + 0xbb, 0xa7, 0xf0, 0x73, 0x26, 0x00, 0x00, 0xc8, + 0x0b, 0xba, 0xc8, 0x08, 0xba, 0xc8, 0x07, 0xc7, + 0x07, 0xc7, 0x0a, 0xef, 0xa5, 0xf0, 0x3b, 0xc7, + 0x0b, 0xc7, 0x08, 0x1b, 0x11, 0xaf, 0xf1, 0x04, + 0x1b, 0x71, 0x1b, 0x1b, 0x5d, 0x07, 0x00, 0x41, + 0xe1, 0x01, 0x00, 0x00, 0xc7, 0x0b, 0xc7, 0x08, + 0x46, 0x11, 0xf1, 0x03, 0x0e, 0xba, 0xc7, 0x0a, + 0xc7, 0x07, 0x46, 0xbc, 0x9c, 0x24, 0x02, 0x00, + 0x1b, 0x71, 0x1b, 0x48, 0xc7, 0x08, 0xbb, 0x9c, + 0xc7, 0x09, 0x9b, 0xc8, 0x08, 0x92, 0x07, 0xf2, + 0xbf, 0xba, 0xc8, 0x06, 0xba, 0xc8, 0x08, 0xc7, + 0x08, 0xc7, 0x09, 0xa5, 0xf0, 0x0f, 0xc7, 0x06, + 0xc7, 0x0b, 0xc7, 0x08, 0x46, 0x9c, 0xc8, 0x06, + 0x92, 0x08, 0xf2, 0xec, 0xc7, 0x06, 0xcb, 0xa6, + 0xf1, 0x05, 0x91, 0x09, 0xf2, 0x89, 0xc7, 0x09, + 0xbb, 0xa7, 0x68, 0x99, 0x00, 0x00, 0x00, 0xba, + 0xc8, 0x06, 0xc7, 0x09, 0xbb, 0x9d, 0xc8, 0x08, + 0xc7, 0x04, 0xc8, 0x05, 0xc7, 0x05, 0xcc, 0xa5, + 0x68, 0x7f, 0x00, 0x00, 0x00, 0xe6, 0xc7, 0x05, + 0x46, 0xba, 0x46, 0x04, 0xbe, 0x01, 0x00, 0x00, + 0xad, 0x11, 0xf1, 0x0e, 0x0e, 0xe6, 0xc7, 0x05, + 0xbb, 0x9c, 0x46, 0x04, 0x37, 0x02, 0x00, 0x00, + 0xad, 0xf1, 0x5e, 0xc7, 0x06, 0xce, 0xef, 0x9c, + 0xc8, 0x06, 0x5d, 0x08, 0x00, 0xce, 0xf5, 0x0e, + 0x04, 0x43, 0x02, 0x00, 0x00, 0xd2, 0xc7, 0x08, + 0xc7, 0x09, 0xbb, 0x9d, 0xad, 0xf0, 0x11, 0x5d, + 0x09, 0x00, 0x04, 0xa4, 0x01, 0x00, 0x00, 0xd7, + 0xf6, 0x0e, 0xba, 0xc8, 0x08, 0xf2, 0x23, 0x5d, + 0x09, 0x00, 0xc6, 0xc7, 0x0b, 0xc7, 0x08, 0x90, + 0xc8, 0x08, 0x46, 0xc7, 0x06, 0x9d, 0xf6, 0x0e, + 0xf2, 0x10, 0x11, 0x7e, 0x81, 0x00, 0x0e, 0xc8, + 0x05, 0x81, 0x00, 0x0e, 0xc8, 0x06, 0x83, 0xf2, + 0x0a, 0x5d, 0x0a, 0x00, 0xd7, 0xc7, 0x05, 0xf6, + 0xf2, 0xe9, 0x0e, 0x92, 0x05, 0xf3, 0x7e, 0xff, + 0xc7, 0x05, 0xc8, 0x04, 0xc7, 0x04, 0xc8, 0x05, + 0xc7, 0x05, 0xcc, 0xa5, 0xf0, 0x37, 0x5d, 0x08, + 0x00, 0xce, 0xf5, 0x0e, 0x04, 0x43, 0x02, 0x00, + 0x00, 0xd2, 0x5d, 0x09, 0x00, 0x04, 0xa4, 0x01, + 0x00, 0x00, 0xd7, 0xf6, 0x0e, 0xf2, 0x10, 0x11, + 0x7e, 0x81, 0x00, 0x0e, 0xc8, 0x05, 0x81, 0x00, + 0x0e, 0xc8, 0x06, 0x83, 0xf2, 0x0a, 0x5d, 0x0a, + 0x00, 0xd7, 0xc7, 0x05, 0xf6, 0xf2, 0xe9, 0x0e, + 0x92, 0x05, 0xf2, 0xc5, 0x5d, 0x09, 0x00, 0x04, + 0xa4, 0x01, 0x00, 0x00, 0xd7, 0xbc, 0x9d, 0xdf, + 0xf6, 0x0e, 0x5d, 0x05, 0x00, 0xe6, 0xcc, 0x46, + 0xf5, 0x0e, 0xcc, 0xe3, 0x26, 0x02, 0x00, 0x28, + 0xc5, 0x00, 0xd0, 0xc5, 0x01, 0xc8, 0x0b, 0xc5, + 0x02, 0xc8, 0x0c, 0xc5, 0x03, 0xc8, 0x0d, 0xc5, + 0x04, 0xc8, 0x0e, 0xc5, 0x05, 0xc8, 0x0f, 0xc5, + 0x06, 0xc8, 0x10, 0xc5, 0x07, 0xc8, 0x11, 0xc5, + 0x08, 0xc8, 0x12, 0xc5, 0x09, 0xc8, 0x13, 0xc5, + 0x0a, 0xc8, 0x14, 0xc5, 0x0b, 0xc8, 0x15, 0xc5, + 0x0c, 0xc8, 0x16, 0xc5, 0x0d, 0xc8, 0x17, 0x0b, + 0xcf, 0xd8, 0x96, 0x04, 0x4d, 0x00, 0x00, 0x00, + 0xad, 0xf0, 0x1c, 0xd8, 0x07, 0xae, 0xf0, 0x17, + 0xd8, 0xd3, 0x40, 0x54, 0x02, 0x00, 0x00, 0xdc, + 0xcb, 0x40, 0x55, 0x02, 0x00, 0x00, 0xdd, 0xcb, + 0x40, 0xff, 0x00, 0x00, 0x00, 0xde, 0xd8, 0x96, + 0x04, 0x4b, 0x00, 0x00, 0x00, 0xae, 0xf0, 0x03, + 0x09, 0xdc, 0xcc, 0xd9, 0xbc, 0xf6, 0xdd, 0xcc, + 0xda, 0x0a, 0xf6, 0xde, 0xcc, 0xcb, 0x40, 0xf9, + 0x01, 0x00, 0x00, 0x5d, 0x10, 0x00, 0x41, 0xa5, + 0x01, 0x00, 0x00, 0x5d, 0x11, 0x00, 0xc2, 0x50, + 0x24, 0x02, 0x00, 0xf6, 0xd1, 0xcc, 0xcb, 0x40, + 0xfa, 0x01, 0x00, 0x00, 0xc2, 0x64, 0xf6, 0xd2, + 0xcc, 0xcb, 0x40, 0xfb, 0x01, 0x00, 0x00, 0xce, + 0xc2, 0x0a, 0x9c, 0xf6, 0xc8, 0x04, 0xcc, 0xcb, + 0x40, 0xfc, 0x01, 0x00, 0x00, 0xc2, 0x4e, 0xf6, + 0xc8, 0x05, 0x0b, 0x26, 0x01, 0x00, 0xc8, 0x06, + 0x26, 0x00, 0x00, 0xc8, 0x07, 0x26, 0x00, 0x00, + 0xc8, 0x08, 0x26, 0x00, 0x00, 0xc8, 0x09, 0x04, + 0x9e, 0x01, 0x00, 0x00, 0xc8, 0x0a, 0xc7, 0x0f, + 0xd7, 0xba, 0xf6, 0x0e, 0xc7, 0x17, 0xba, 0xba, + 0xf6, 0x0e, 0xc7, 0x10, 0xc6, 0xf5, 0x0e, 0xc7, + 0x09, 0x41, 0x63, 0x00, 0x00, 0x00, 0xc6, 0x25, + 0x01, 0x00, 0x0c, 0x43, 0x02, 0x01, 0xcc, 0x05, + 0x01, 0x00, 0x01, 0x07, 0x00, 0x05, 0x00, 0x3c, + 0x01, 0xea, 0x07, 0x00, 0x01, 0x00, 0xec, 0x03, + 0x00, 0x1a, 0xca, 0x05, 0x78, 0x00, 0x8c, 0x04, + 0x19, 0x00, 0x88, 0x04, 0x17, 0x00, 0x8a, 0x04, + 0x18, 0x00, 0x64, 0x00, 0x00, 0x41, 0x9d, 0x01, + 0x00, 0x00, 0xe4, 0x41, 0x56, 0x02, 0x00, 0x00, + 0xd7, 0x0b, 0xe5, 0x4b, 0x55, 0x02, 0x00, 0x00, + 0xe6, 0x4b, 0xff, 0x00, 0x00, 0x00, 0x5d, 0x04, + 0x00, 0x4b, 0x54, 0x02, 0x00, 0x00, 0x24, 0x02, + 0x00, 0x24, 0x01, 0x00, 0x0e, 0x64, 0x00, 0x00, + 0x41, 0x9d, 0x01, 0x00, 0x00, 0x04, 0xa4, 0x01, + 0x00, 0x00, 0x24, 0x01, 0x00, 0x29, 0x0c, 0x43, + 0x02, 0x01, 0xce, 0x05, 0x01, 0x05, 0x01, 0x06, + 0x00, 0x03, 0x00, 0xb4, 0x01, 0x06, 0x92, 0x06, + 0x00, 0x01, 0x00, 0xde, 0x06, 0x00, 0x00, 0x00, + 0xaa, 0x04, 0x00, 0x01, 0x00, 0xae, 0x09, 0x00, + 0x02, 0x00, 0xe0, 0x07, 0x00, 0x03, 0x00, 0xb0, + 0x09, 0x00, 0x04, 0x00, 0xd0, 0x05, 0x7b, 0x00, + 0xd8, 0x05, 0x7f, 0x00, 0xec, 0x03, 0x00, 0x1a, + 0xd7, 0x04, 0x59, 0x02, 0x00, 0x00, 0xad, 0xf0, + 0x06, 0xe3, 0xf4, 0x0e, 0x0a, 0x28, 0xd7, 0xba, + 0x46, 0x04, 0xc3, 0x01, 0x00, 0x00, 0xae, 0xf0, + 0x0e, 0xd7, 0xba, 0x46, 0x04, 0xbe, 0x01, 0x00, + 0x00, 0xae, 0xf0, 0x03, 0x09, 0x28, 0xbb, 0xcf, + 0xcb, 0xd7, 0xef, 0xa5, 0xf0, 0x10, 0xd7, 0xcb, + 0x46, 0x04, 0xe8, 0x01, 0x00, 0x00, 0xae, 0xf0, + 0x05, 0x92, 0x00, 0xf2, 0xec, 0xd7, 0x41, 0x9f, + 0x01, 0x00, 0x00, 0xbb, 0xcb, 0x24, 0x02, 0x00, + 0xd0, 0xba, 0xd1, 0xe4, 0x7d, 0xf2, 0x21, 0xc8, + 0x04, 0xc7, 0x04, 0x41, 0xd3, 0x01, 0x00, 0x00, + 0xcc, 0x24, 0x01, 0x00, 0xf0, 0x12, 0xe4, 0xc7, + 0x04, 0x46, 0xd2, 0x92, 0x02, 0xc7, 0x04, 0xcc, + 0xad, 0xf0, 0x05, 0xba, 0xd1, 0xf2, 0x05, 0x80, + 0xf0, 0xde, 0x0e, 0x0e, 0xce, 0xf0, 0x1d, 0xcd, + 0xbc, 0xa5, 0xf0, 0x18, 0xce, 0xd7, 0x41, 0x9f, + 0x01, 0x00, 0x00, 0xcb, 0x24, 0x01, 0x00, 0x41, + 0x5a, 0x02, 0x00, 0x00, 0x24, 0x00, 0x00, 0xf5, + 0x0e, 0xf2, 0x20, 0x64, 0x02, 0x00, 0x41, 0x9d, + 0x01, 0x00, 0x00, 0x04, 0x5b, 0x02, 0x00, 0x00, + 0x41, 0x64, 0x00, 0x00, 0x00, 0xcc, 0x04, 0xa4, + 0x01, 0x00, 0x00, 0x24, 0x02, 0x00, 0x24, 0x01, + 0x00, 0x0e, 0x0a, 0x28, 0x0c, 0x43, 0x02, 0x01, + 0xd0, 0x05, 0x00, 0x01, 0x00, 0x07, 0x00, 0x09, + 0x01, 0xdc, 0x01, 0x01, 0xb8, 0x09, 0x00, 0x00, + 0x00, 0xec, 0x03, 0x00, 0x1a, 0x8e, 0x04, 0x1a, + 0x00, 0x86, 0x04, 0x16, 0x00, 0x90, 0x04, 0x1b, + 0x00, 0x8c, 0x04, 0x19, 0x00, 0x8a, 0x04, 0x18, + 0x00, 0x88, 0x04, 0x17, 0x00, 0x82, 0x04, 0x14, + 0x00, 0x80, 0x04, 0x13, 0x00, 0x0c, 0x42, 0x02, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, + 0x00, 0x0f, 0x01, 0xc0, 0x06, 0x00, 0x01, 0x00, + 0xd7, 0xf0, 0x07, 0x04, 0x87, 0x00, 0x00, 0x00, + 0x28, 0x04, 0xe8, 0x01, 0x00, 0x00, 0x28, 0xc5, + 0x00, 0x4c, 0x5c, 0x02, 0x00, 0x00, 0xcf, 0x64, + 0x00, 0x00, 0x41, 0x9d, 0x01, 0x00, 0x00, 0x04, + 0x5d, 0x02, 0x00, 0x00, 0x04, 0x5e, 0x02, 0x00, + 0x00, 0x9c, 0xcb, 0xe4, 0xf5, 0x9c, 0x04, 0x5f, + 0x02, 0x00, 0x00, 0x9c, 0x04, 0x60, 0x02, 0x00, + 0x00, 0x9c, 0xcb, 0xe4, 0x95, 0xf5, 0x9c, 0x04, + 0x61, 0x02, 0x00, 0x00, 0x9c, 0x04, 0x62, 0x02, + 0x00, 0x00, 0x9c, 0xcb, 0xe5, 0xf5, 0x9c, 0x04, + 0x63, 0x02, 0x00, 0x00, 0x9c, 0x04, 0x64, 0x02, + 0x00, 0x00, 0x9c, 0xcb, 0xe6, 0xf5, 0x9c, 0x04, + 0x65, 0x02, 0x00, 0x00, 0x9c, 0x04, 0x66, 0x02, + 0x00, 0x00, 0x41, 0x64, 0x00, 0x00, 0x00, 0x5d, + 0x04, 0x00, 0x04, 0x67, 0x02, 0x00, 0x00, 0x24, + 0x02, 0x00, 0x9c, 0x04, 0x68, 0x02, 0x00, 0x00, + 0x9c, 0xcb, 0x5d, 0x05, 0x00, 0xf5, 0x9c, 0x04, + 0x69, 0x02, 0x00, 0x00, 0x9c, 0x04, 0x6a, 0x02, + 0x00, 0x00, 0x9c, 0xcb, 0x5d, 0x06, 0x00, 0xf5, + 0x9c, 0x04, 0x6b, 0x02, 0x00, 0x00, 0x9c, 0x04, + 0x6c, 0x02, 0x00, 0x00, 0x9c, 0xcb, 0x5d, 0x07, + 0x00, 0x5d, 0x08, 0x00, 0x40, 0x6d, 0x02, 0x00, + 0x00, 0xab, 0xf5, 0x9c, 0x04, 0x6e, 0x02, 0x00, + 0x00, 0x9c, 0x04, 0x6f, 0x02, 0x00, 0x00, 0x9c, + 0xcb, 0x5d, 0x07, 0x00, 0x5d, 0x08, 0x00, 0x40, + 0x70, 0x02, 0x00, 0x00, 0xab, 0xf5, 0x9c, 0x04, + 0x71, 0x02, 0x00, 0x00, 0x9c, 0x04, 0x72, 0x02, + 0x00, 0x00, 0x9c, 0x04, 0x73, 0x02, 0x00, 0x00, + 0x9c, 0x04, 0x74, 0x02, 0x00, 0x00, 0x9c, 0x24, + 0x01, 0x00, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xd2, + 0x05, 0x01, 0x01, 0x01, 0x07, 0x00, 0x01, 0x00, + 0x5f, 0x02, 0xf6, 0x06, 0x00, 0x01, 0x00, 0xea, + 0x09, 0x04, 0x00, 0x03, 0xec, 0x03, 0x00, 0x1a, + 0xd7, 0x41, 0x76, 0x02, 0x00, 0x00, 0x04, 0xbe, + 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, 0xd7, 0x41, + 0x76, 0x02, 0x00, 0x00, 0x04, 0xca, 0x01, 0x00, + 0x00, 0x24, 0x01, 0x00, 0xa6, 0xf0, 0x09, 0xd7, + 0x04, 0x77, 0x02, 0x00, 0x00, 0x9c, 0xdb, 0x6b, + 0x13, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x41, + 0x78, 0x02, 0x00, 0x00, 0xd7, 0x24, 0x01, 0x00, + 0x0e, 0x0e, 0x29, 0xcf, 0x6b, 0x21, 0x00, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x41, 0x9d, 0x01, 0x00, + 0x00, 0xc6, 0x41, 0x64, 0x00, 0x00, 0x00, 0xcb, + 0x04, 0xa4, 0x01, 0x00, 0x00, 0x24, 0x02, 0x00, + 0x24, 0x01, 0x00, 0x0e, 0x0e, 0x29, 0x30, 0x0c, + 0x43, 0x02, 0x01, 0xd4, 0x05, 0x01, 0x00, 0x01, + 0x03, 0x00, 0x02, 0x00, 0x10, 0x01, 0xea, 0x09, + 0x00, 0x01, 0x00, 0xee, 0x05, 0x8a, 0x01, 0x00, + 0xec, 0x03, 0x00, 0x1a, 0xe3, 0xf4, 0x0e, 0x64, + 0x01, 0x00, 0x41, 0x6a, 0x01, 0x00, 0x00, 0xd7, 0x24, 0x01, 0x00, 0x29, 0x0c, 0x43, 0x02, 0x01, - 0xd2, 0x05, 0x01, 0x01, 0x01, 0x07, 0x00, 0x01, - 0x00, 0x5f, 0x02, 0xf6, 0x06, 0x00, 0x01, 0x00, - 0xea, 0x09, 0x04, 0x00, 0x03, 0xec, 0x03, 0x00, - 0x1a, 0xd7, 0x41, 0x76, 0x02, 0x00, 0x00, 0x04, - 0xbe, 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, 0xd7, - 0x41, 0x76, 0x02, 0x00, 0x00, 0x04, 0xca, 0x01, - 0x00, 0x00, 0x24, 0x01, 0x00, 0xa6, 0xf0, 0x09, - 0xd7, 0x04, 0x77, 0x02, 0x00, 0x00, 0x9c, 0xdb, - 0x6b, 0x13, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, - 0x41, 0x78, 0x02, 0x00, 0x00, 0xd7, 0x24, 0x01, - 0x00, 0x0e, 0x0e, 0x29, 0xcf, 0x6b, 0x21, 0x00, - 0x00, 0x00, 0x64, 0x00, 0x00, 0x41, 0x9d, 0x01, - 0x00, 0x00, 0xc6, 0x41, 0x64, 0x00, 0x00, 0x00, - 0xcb, 0x04, 0xa4, 0x01, 0x00, 0x00, 0x24, 0x02, - 0x00, 0x24, 0x01, 0x00, 0x0e, 0x0e, 0x29, 0x30, - 0x0c, 0x43, 0x02, 0x01, 0xd4, 0x05, 0x01, 0x00, - 0x01, 0x03, 0x00, 0x02, 0x00, 0x10, 0x01, 0xea, - 0x09, 0x00, 0x01, 0x00, 0xee, 0x05, 0x8a, 0x01, - 0x00, 0xec, 0x03, 0x00, 0x1a, 0xe3, 0xf4, 0x0e, - 0x64, 0x01, 0x00, 0x41, 0x6a, 0x01, 0x00, 0x00, - 0xd7, 0x24, 0x01, 0x00, 0x29, 0x0c, 0x43, 0x02, - 0x01, 0xd6, 0x05, 0x02, 0x00, 0x02, 0x03, 0x00, - 0x00, 0x00, 0x14, 0x02, 0xf6, 0x06, 0x00, 0x01, - 0x00, 0x9e, 0x08, 0x00, 0x01, 0x00, 0xd7, 0xf0, - 0x10, 0x04, 0x79, 0x02, 0x00, 0x00, 0x41, 0x8e, - 0x01, 0x00, 0x00, 0xd7, 0x24, 0x01, 0x00, 0x28, - 0xd8, 0x28, 0x0c, 0x42, 0x02, 0x01, 0x00, 0x01, - 0x00, 0x01, 0x03, 0x00, 0x02, 0x00, 0x06, 0x01, + 0xd6, 0x05, 0x02, 0x00, 0x02, 0x03, 0x00, 0x00, + 0x00, 0x14, 0x02, 0xf6, 0x06, 0x00, 0x01, 0x00, + 0x9e, 0x08, 0x00, 0x01, 0x00, 0xd7, 0xf0, 0x10, + 0x04, 0x79, 0x02, 0x00, 0x00, 0x41, 0x8e, 0x01, + 0x00, 0x00, 0xd7, 0x24, 0x01, 0x00, 0x28, 0xd8, + 0x28, 0x0c, 0x42, 0x02, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x03, 0x00, 0x02, 0x00, 0x06, 0x01, 0xf6, + 0x06, 0x00, 0x01, 0x00, 0xd6, 0x05, 0x7e, 0x00, + 0x8e, 0x04, 0x1a, 0x00, 0xe3, 0xd7, 0x0a, 0xf6, + 0xe8, 0x29, 0x0c, 0x42, 0x02, 0x01, 0x00, 0x01, + 0x00, 0x01, 0x03, 0x00, 0x02, 0x00, 0x07, 0x01, 0xf6, 0x06, 0x00, 0x01, 0x00, 0xd6, 0x05, 0x7e, 0x00, 0x8e, 0x04, 0x1a, 0x00, 0xe3, 0xd7, 0x0a, - 0xf6, 0xe8, 0x29, 0x0c, 0x42, 0x02, 0x01, 0x00, - 0x01, 0x00, 0x01, 0x03, 0x00, 0x02, 0x00, 0x07, - 0x01, 0xf6, 0x06, 0x00, 0x01, 0x00, 0xd6, 0x05, - 0x7e, 0x00, 0x8e, 0x04, 0x1a, 0x00, 0xe3, 0xd7, - 0x0a, 0xf6, 0x95, 0xe8, 0x29, 0x0c, 0x42, 0x02, - 0x01, 0x00, 0x01, 0x00, 0x01, 0x03, 0x00, 0x02, - 0x00, 0x07, 0x01, 0xf6, 0x06, 0x00, 0x01, 0x00, - 0xd6, 0x05, 0x7e, 0x00, 0x86, 0x04, 0x16, 0x00, - 0xe3, 0xd7, 0xe4, 0x95, 0xf6, 0xe8, 0x29, 0x0c, - 0x42, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, 0x03, - 0x00, 0x02, 0x00, 0x07, 0x01, 0xf6, 0x06, 0x00, - 0x01, 0x00, 0xd6, 0x05, 0x7e, 0x00, 0x90, 0x04, - 0x1b, 0x00, 0xe3, 0xd7, 0xe4, 0x95, 0xf6, 0xe8, - 0x29, 0x0c, 0x42, 0x02, 0x01, 0x00, 0x01, 0x00, - 0x01, 0x02, 0x00, 0x01, 0x00, 0x09, 0x01, 0xf6, - 0x06, 0x00, 0x01, 0x00, 0x8c, 0x04, 0x19, 0x00, - 0xd7, 0x8c, 0x11, 0xf1, 0x03, 0x0e, 0xbc, 0xe7, - 0x29, 0x0c, 0x42, 0x02, 0x01, 0x00, 0x01, 0x00, - 0x01, 0x03, 0x00, 0x02, 0x00, 0x07, 0x01, 0xf6, - 0x06, 0x00, 0x01, 0x00, 0xd6, 0x05, 0x7e, 0x00, - 0x8a, 0x04, 0x18, 0x00, 0xe3, 0xd7, 0xe4, 0x95, - 0xf6, 0xe8, 0x29, 0x0c, 0x42, 0x02, 0x01, 0x00, - 0x01, 0x00, 0x01, 0x03, 0x00, 0x02, 0x00, 0x07, - 0x01, 0xf6, 0x06, 0x00, 0x01, 0x00, 0xd6, 0x05, - 0x7e, 0x00, 0x88, 0x04, 0x17, 0x00, 0xe3, 0xd7, - 0xe4, 0x95, 0xf6, 0xe8, 0x29, 0x0c, 0x42, 0x02, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, - 0x00, 0x08, 0x00, 0x80, 0x04, 0x13, 0x00, 0x82, - 0x04, 0x14, 0x00, 0xe3, 0x40, 0x6d, 0x02, 0x00, - 0x00, 0xe8, 0x29, 0x0c, 0x42, 0x02, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x08, - 0x00, 0x80, 0x04, 0x13, 0x00, 0x82, 0x04, 0x14, - 0x00, 0xe3, 0x40, 0x70, 0x02, 0x00, 0x00, 0xe8, - 0x29, 0x0c, 0x42, 0x02, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x01, 0x00, 0x11, 0x00, 0xec, - 0x03, 0x00, 0x1a, 0x64, 0x00, 0x00, 0x41, 0x9d, - 0x01, 0x00, 0x00, 0x04, 0x7a, 0x02, 0x00, 0x00, - 0x24, 0x01, 0x00, 0x29, 0x0c, 0x42, 0x02, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, - 0x04, 0x00, 0xd4, 0x05, 0x7d, 0x00, 0xe3, 0xba, - 0xf5, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xda, 0x05, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x14, - 0x00, 0xec, 0x03, 0x00, 0x1a, 0xdc, 0x05, 0x81, - 0x01, 0x00, 0x64, 0x00, 0x00, 0x41, 0x9d, 0x01, - 0x00, 0x00, 0x04, 0x7b, 0x02, 0x00, 0x00, 0x24, - 0x01, 0x00, 0x0e, 0xe4, 0xf4, 0x29, 0x0c, 0x43, - 0x02, 0x01, 0xdc, 0x05, 0x00, 0x00, 0x00, 0x04, - 0x00, 0x04, 0x00, 0x0c, 0x00, 0xc0, 0x05, 0x73, - 0x00, 0xb6, 0x05, 0x6e, 0x00, 0xa8, 0x04, 0x27, - 0x00, 0xde, 0x05, 0x82, 0x01, 0x00, 0xe3, 0xe4, - 0x04, 0x7c, 0x02, 0x00, 0x00, 0xe5, 0xf6, 0xe6, - 0xf6, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xde, 0x05, - 0x01, 0x00, 0x01, 0x02, 0x00, 0x02, 0x00, 0x0a, - 0x01, 0xfa, 0x09, 0x00, 0x01, 0x00, 0xe0, 0x05, - 0x83, 0x01, 0x00, 0xdc, 0x05, 0x81, 0x01, 0x00, - 0xe3, 0xd7, 0xf5, 0x95, 0xf0, 0x04, 0xe4, 0xf4, - 0x0e, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xe0, 0x05, - 0x01, 0x01, 0x01, 0x02, 0x00, 0x06, 0x00, 0x3a, - 0x02, 0xfa, 0x09, 0x00, 0x01, 0x00, 0xd2, 0x06, - 0x00, 0x00, 0x00, 0xa6, 0x04, 0x26, 0x00, 0xce, - 0x05, 0x7a, 0x00, 0xea, 0x05, 0x88, 0x01, 0x00, - 0x98, 0x04, 0x1f, 0x00, 0xa8, 0x04, 0x27, 0x00, - 0xe2, 0x05, 0x84, 0x01, 0x00, 0xd7, 0x95, 0xf0, - 0x03, 0x09, 0x28, 0xe3, 0xf0, 0x0d, 0xe3, 0x04, - 0xa4, 0x01, 0x00, 0x00, 0x9c, 0xd7, 0x9c, 0xdb, - 0xf2, 0x08, 0xe4, 0xd7, 0xf5, 0xf0, 0x03, 0x09, - 0x28, 0xe5, 0xd7, 0xf5, 0xd3, 0xba, 0x46, 0xea, - 0xcb, 0xbb, 0x46, 0x5e, 0x04, 0x00, 0xe6, 0xf0, - 0x05, 0xd7, 0xe7, 0x09, 0x28, 0xc6, 0xe7, 0x5d, - 0x05, 0x00, 0xd7, 0xf5, 0x0e, 0x0a, 0x28, 0x0c, - 0x43, 0x02, 0x01, 0xe2, 0x05, 0x01, 0x01, 0x01, - 0x06, 0x00, 0x06, 0x00, 0x4a, 0x02, 0xfa, 0x09, - 0x00, 0x01, 0x00, 0xfc, 0x09, 0x00, 0x00, 0x00, - 0x90, 0x04, 0x1b, 0x00, 0xee, 0x03, 0x01, 0x1a, - 0xa2, 0x04, 0x24, 0x00, 0xec, 0x03, 0x00, 0x1a, - 0xe4, 0x05, 0x85, 0x01, 0x00, 0xe6, 0x05, 0x86, - 0x01, 0x00, 0xe3, 0xf0, 0x09, 0x04, 0x7f, 0x02, - 0x00, 0x00, 0xd7, 0x9c, 0xdb, 0x64, 0x01, 0x00, - 0x41, 0x80, 0x02, 0x00, 0x00, 0x24, 0x00, 0x00, - 0xe9, 0x38, 0xce, 0x00, 0x00, 0x00, 0x41, 0x18, - 0x00, 0x00, 0x00, 0x64, 0x03, 0x00, 0x40, 0x81, - 0x02, 0x00, 0x00, 0xd7, 0x0b, 0x0a, 0x4b, 0x82, - 0x02, 0x00, 0x00, 0x0a, 0x4b, 0x8f, 0x00, 0x00, - 0x00, 0x24, 0x03, 0x00, 0xd3, 0x41, 0x89, 0x00, - 0x00, 0x00, 0x5d, 0x04, 0x00, 0x5d, 0x05, 0x00, - 0x24, 0x02, 0x00, 0x29, 0x0c, 0x43, 0x02, 0x01, - 0xe4, 0x05, 0x01, 0x00, 0x01, 0x02, 0x00, 0x06, - 0x00, 0x27, 0x01, 0xfc, 0x09, 0x00, 0x01, 0x00, - 0xee, 0x03, 0x01, 0x1a, 0xa2, 0x04, 0x24, 0x00, - 0xa4, 0x04, 0x25, 0x00, 0xcc, 0x05, 0x79, 0x00, - 0xf2, 0x03, 0x00, 0x01, 0xe8, 0x05, 0x87, 0x01, - 0x00, 0xd7, 0x40, 0x44, 0x00, 0x00, 0x00, 0xdb, - 0x64, 0x00, 0x00, 0x41, 0x80, 0x02, 0x00, 0x00, - 0x24, 0x00, 0x00, 0xe4, 0x9d, 0xe9, 0xe6, 0xd7, - 0xf5, 0x0e, 0x5d, 0x04, 0x00, 0xd7, 0x42, 0x8b, - 0x01, 0x00, 0x00, 0x5d, 0x05, 0x00, 0xf4, 0x29, - 0x0c, 0x43, 0x02, 0x01, 0xe6, 0x05, 0x01, 0x00, - 0x01, 0x04, 0x00, 0x06, 0x00, 0xa1, 0x01, 0x01, - 0x6e, 0x00, 0x01, 0x00, 0x88, 0x04, 0x17, 0x00, - 0xec, 0x03, 0x00, 0x1a, 0xfe, 0x03, 0x12, 0x00, - 0x82, 0x04, 0x14, 0x00, 0xc0, 0x02, 0x09, 0x00, - 0xe8, 0x05, 0x87, 0x01, 0x00, 0xe3, 0xf0, 0x15, - 0x64, 0x01, 0x00, 0x41, 0x9d, 0x01, 0x00, 0x00, - 0xe5, 0xe6, 0x40, 0x37, 0x00, 0x00, 0x00, 0x46, - 0x24, 0x01, 0x00, 0x0e, 0xd7, 0x5d, 0x04, 0x00, - 0xa9, 0xf0, 0x3b, 0x64, 0x01, 0x00, 0x41, 0x9d, - 0x01, 0x00, 0x00, 0xd7, 0x24, 0x01, 0x00, 0x0e, - 0x64, 0x01, 0x00, 0x41, 0x9d, 0x01, 0x00, 0x00, - 0x04, 0xa4, 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, - 0x0e, 0xd7, 0x40, 0x39, 0x00, 0x00, 0x00, 0xf0, - 0x44, 0x64, 0x01, 0x00, 0x41, 0x9d, 0x01, 0x00, - 0x00, 0xd7, 0x40, 0x39, 0x00, 0x00, 0x00, 0x24, - 0x01, 0x00, 0x0e, 0xf2, 0x30, 0x64, 0x01, 0x00, - 0x41, 0x9d, 0x01, 0x00, 0x00, 0x04, 0x83, 0x02, - 0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, 0x64, 0x01, - 0x00, 0x41, 0x9d, 0x01, 0x00, 0x00, 0xd7, 0x24, - 0x01, 0x00, 0x0e, 0x64, 0x01, 0x00, 0x41, 0x9d, - 0x01, 0x00, 0x00, 0x04, 0xa4, 0x01, 0x00, 0x00, - 0x24, 0x01, 0x00, 0x0e, 0xe3, 0xf0, 0x13, 0x64, + 0xf6, 0x95, 0xe8, 0x29, 0x0c, 0x42, 0x02, 0x01, + 0x00, 0x01, 0x00, 0x01, 0x03, 0x00, 0x02, 0x00, + 0x07, 0x01, 0xf6, 0x06, 0x00, 0x01, 0x00, 0xd6, + 0x05, 0x7e, 0x00, 0x86, 0x04, 0x16, 0x00, 0xe3, + 0xd7, 0xe4, 0x95, 0xf6, 0xe8, 0x29, 0x0c, 0x42, + 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, 0x03, 0x00, + 0x02, 0x00, 0x07, 0x01, 0xf6, 0x06, 0x00, 0x01, + 0x00, 0xd6, 0x05, 0x7e, 0x00, 0x90, 0x04, 0x1b, + 0x00, 0xe3, 0xd7, 0xe4, 0x95, 0xf6, 0xe8, 0x29, + 0x0c, 0x42, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, + 0x02, 0x00, 0x01, 0x00, 0x09, 0x01, 0xf6, 0x06, + 0x00, 0x01, 0x00, 0x8c, 0x04, 0x19, 0x00, 0xd7, + 0x8c, 0x11, 0xf1, 0x03, 0x0e, 0xbc, 0xe7, 0x29, + 0x0c, 0x42, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, + 0x03, 0x00, 0x02, 0x00, 0x07, 0x01, 0xf6, 0x06, + 0x00, 0x01, 0x00, 0xd6, 0x05, 0x7e, 0x00, 0x8a, + 0x04, 0x18, 0x00, 0xe3, 0xd7, 0xe4, 0x95, 0xf6, + 0xe8, 0x29, 0x0c, 0x42, 0x02, 0x01, 0x00, 0x01, + 0x00, 0x01, 0x03, 0x00, 0x02, 0x00, 0x07, 0x01, + 0xf6, 0x06, 0x00, 0x01, 0x00, 0xd6, 0x05, 0x7e, + 0x00, 0x88, 0x04, 0x17, 0x00, 0xe3, 0xd7, 0xe4, + 0x95, 0xf6, 0xe8, 0x29, 0x0c, 0x42, 0x02, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, + 0x08, 0x00, 0x80, 0x04, 0x13, 0x00, 0x82, 0x04, + 0x14, 0x00, 0xe3, 0x40, 0x6d, 0x02, 0x00, 0x00, + 0xe8, 0x29, 0x0c, 0x42, 0x02, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x08, 0x00, + 0x80, 0x04, 0x13, 0x00, 0x82, 0x04, 0x14, 0x00, + 0xe3, 0x40, 0x70, 0x02, 0x00, 0x00, 0xe8, 0x29, + 0x0c, 0x42, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x01, 0x00, 0x11, 0x00, 0xec, 0x03, + 0x00, 0x1a, 0x64, 0x00, 0x00, 0x41, 0x9d, 0x01, + 0x00, 0x00, 0x04, 0x7a, 0x02, 0x00, 0x00, 0x24, + 0x01, 0x00, 0x29, 0x0c, 0x42, 0x02, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04, + 0x00, 0xd4, 0x05, 0x7d, 0x00, 0xe3, 0xba, 0xf5, + 0x29, 0x0c, 0x43, 0x02, 0x01, 0xda, 0x05, 0x00, + 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x14, 0x00, + 0xec, 0x03, 0x00, 0x1a, 0xdc, 0x05, 0x81, 0x01, + 0x00, 0x64, 0x00, 0x00, 0x41, 0x9d, 0x01, 0x00, + 0x00, 0x04, 0x7b, 0x02, 0x00, 0x00, 0x24, 0x01, + 0x00, 0x0e, 0xe4, 0xf4, 0x29, 0x0c, 0x43, 0x02, + 0x01, 0xdc, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x0c, 0x00, 0xc0, 0x05, 0x73, 0x00, + 0xb6, 0x05, 0x6e, 0x00, 0xa8, 0x04, 0x27, 0x00, + 0xde, 0x05, 0x82, 0x01, 0x00, 0xe3, 0xe4, 0x04, + 0x7c, 0x02, 0x00, 0x00, 0xe5, 0xf6, 0xe6, 0xf6, + 0x29, 0x0c, 0x43, 0x02, 0x01, 0xde, 0x05, 0x01, + 0x00, 0x01, 0x02, 0x00, 0x02, 0x00, 0x0a, 0x01, + 0xfa, 0x09, 0x00, 0x01, 0x00, 0xe0, 0x05, 0x83, + 0x01, 0x00, 0xdc, 0x05, 0x81, 0x01, 0x00, 0xe3, + 0xd7, 0xf5, 0x95, 0xf0, 0x04, 0xe4, 0xf4, 0x0e, + 0x29, 0x0c, 0x43, 0x02, 0x01, 0xe0, 0x05, 0x01, + 0x01, 0x01, 0x02, 0x00, 0x06, 0x00, 0x3a, 0x02, + 0xfa, 0x09, 0x00, 0x01, 0x00, 0xd2, 0x06, 0x00, + 0x00, 0x00, 0xa6, 0x04, 0x26, 0x00, 0xce, 0x05, + 0x7a, 0x00, 0xea, 0x05, 0x88, 0x01, 0x00, 0x98, + 0x04, 0x1f, 0x00, 0xa8, 0x04, 0x27, 0x00, 0xe2, + 0x05, 0x84, 0x01, 0x00, 0xd7, 0x95, 0xf0, 0x03, + 0x09, 0x28, 0xe3, 0xf0, 0x0d, 0xe3, 0x04, 0xa4, + 0x01, 0x00, 0x00, 0x9c, 0xd7, 0x9c, 0xdb, 0xf2, + 0x08, 0xe4, 0xd7, 0xf5, 0xf0, 0x03, 0x09, 0x28, + 0xe5, 0xd7, 0xf5, 0xd3, 0xba, 0x46, 0xea, 0xcb, + 0xbb, 0x46, 0x5e, 0x04, 0x00, 0xe6, 0xf0, 0x05, + 0xd7, 0xe7, 0x09, 0x28, 0xc6, 0xe7, 0x5d, 0x05, + 0x00, 0xd7, 0xf5, 0x0e, 0x0a, 0x28, 0x0c, 0x43, + 0x02, 0x01, 0xe2, 0x05, 0x01, 0x01, 0x01, 0x06, + 0x00, 0x06, 0x00, 0x4a, 0x02, 0xfa, 0x09, 0x00, + 0x01, 0x00, 0xfc, 0x09, 0x00, 0x00, 0x00, 0x90, + 0x04, 0x1b, 0x00, 0xee, 0x03, 0x01, 0x1a, 0xa2, + 0x04, 0x24, 0x00, 0xec, 0x03, 0x00, 0x1a, 0xe4, + 0x05, 0x85, 0x01, 0x00, 0xe6, 0x05, 0x86, 0x01, + 0x00, 0xe3, 0xf0, 0x09, 0x04, 0x7f, 0x02, 0x00, + 0x00, 0xd7, 0x9c, 0xdb, 0x64, 0x01, 0x00, 0x41, + 0x80, 0x02, 0x00, 0x00, 0x24, 0x00, 0x00, 0xe9, + 0x38, 0xce, 0x00, 0x00, 0x00, 0x41, 0x18, 0x00, + 0x00, 0x00, 0x64, 0x03, 0x00, 0x40, 0x81, 0x02, + 0x00, 0x00, 0xd7, 0x0b, 0x0a, 0x4b, 0x82, 0x02, + 0x00, 0x00, 0x0a, 0x4b, 0x8f, 0x00, 0x00, 0x00, + 0x24, 0x03, 0x00, 0xd3, 0x41, 0x89, 0x00, 0x00, + 0x00, 0x5d, 0x04, 0x00, 0x5d, 0x05, 0x00, 0x24, + 0x02, 0x00, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xe4, + 0x05, 0x01, 0x00, 0x01, 0x02, 0x00, 0x06, 0x00, + 0x27, 0x01, 0xfc, 0x09, 0x00, 0x01, 0x00, 0xee, + 0x03, 0x01, 0x1a, 0xa2, 0x04, 0x24, 0x00, 0xa4, + 0x04, 0x25, 0x00, 0xcc, 0x05, 0x79, 0x00, 0xf2, + 0x03, 0x00, 0x01, 0xe8, 0x05, 0x87, 0x01, 0x00, + 0xd7, 0x40, 0x44, 0x00, 0x00, 0x00, 0xdb, 0x64, + 0x00, 0x00, 0x41, 0x80, 0x02, 0x00, 0x00, 0x24, + 0x00, 0x00, 0xe4, 0x9d, 0xe9, 0xe6, 0xd7, 0xf5, + 0x0e, 0x5d, 0x04, 0x00, 0xd7, 0x42, 0x8b, 0x01, + 0x00, 0x00, 0x5d, 0x05, 0x00, 0xf4, 0x29, 0x0c, + 0x43, 0x02, 0x01, 0xe6, 0x05, 0x01, 0x00, 0x01, + 0x04, 0x00, 0x06, 0x00, 0xa1, 0x01, 0x01, 0x6e, + 0x00, 0x01, 0x00, 0x88, 0x04, 0x17, 0x00, 0xec, + 0x03, 0x00, 0x1a, 0xfe, 0x03, 0x12, 0x00, 0x82, + 0x04, 0x14, 0x00, 0xc0, 0x02, 0x09, 0x00, 0xe8, + 0x05, 0x87, 0x01, 0x00, 0xe3, 0xf0, 0x15, 0x64, 0x01, 0x00, 0x41, 0x9d, 0x01, 0x00, 0x00, 0xe5, - 0x40, 0x9e, 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, - 0x0e, 0x5d, 0x05, 0x00, 0xf4, 0x29, 0x0c, 0x43, - 0x02, 0x01, 0xe8, 0x05, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x03, 0x00, 0x11, 0x00, 0xa8, 0x04, 0x27, - 0x00, 0xec, 0x03, 0x00, 0x1a, 0xdc, 0x05, 0x81, - 0x01, 0x00, 0xba, 0xe7, 0x64, 0x01, 0x00, 0x41, - 0x84, 0x02, 0x00, 0x00, 0x24, 0x00, 0x00, 0x0e, - 0xe5, 0xf4, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xea, - 0x05, 0x01, 0x17, 0x01, 0x04, 0x0f, 0x03, 0x0a, - 0x84, 0x04, 0x18, 0x9e, 0x06, 0x00, 0x01, 0x40, - 0x06, 0x86, 0x06, 0x00, 0x00, 0x40, 0x04, 0x8c, - 0x06, 0x00, 0x01, 0x40, 0x08, 0xb2, 0x06, 0x00, - 0x02, 0x40, 0x0a, 0xc0, 0x06, 0x00, 0x03, 0x40, - 0x05, 0xb8, 0x06, 0x00, 0x04, 0x40, 0x02, 0x8a, - 0x0a, 0x00, 0x05, 0x40, 0x00, 0xa8, 0x04, 0x00, - 0x06, 0x00, 0x8c, 0x0a, 0x00, 0x07, 0x00, 0x8e, - 0x0a, 0x00, 0x08, 0x40, 0x09, 0x9a, 0x07, 0x00, - 0x09, 0x40, 0x0e, 0x90, 0x0a, 0x00, 0x0a, 0x40, - 0x03, 0x92, 0x0a, 0x00, 0x0b, 0x40, 0x01, 0x94, - 0x0a, 0x00, 0x0c, 0x40, 0x07, 0x96, 0x0a, 0x00, - 0x0d, 0x00, 0x98, 0x0a, 0x00, 0x0e, 0x00, 0x9a, - 0x0a, 0x00, 0x0f, 0x00, 0x9c, 0x0a, 0x00, 0x10, - 0x00, 0x9e, 0x0a, 0x00, 0x11, 0x00, 0xa0, 0x0a, - 0x00, 0x12, 0x40, 0x0b, 0xa2, 0x0a, 0x00, 0x13, - 0x40, 0x0c, 0xa4, 0x0a, 0x00, 0x14, 0x40, 0x0d, - 0xa6, 0x0a, 0x00, 0x15, 0x00, 0xa8, 0x0a, 0x00, - 0x16, 0x00, 0xd0, 0x04, 0x3b, 0x00, 0xd8, 0x04, - 0x3f, 0x00, 0xce, 0x04, 0x3a, 0x00, 0x0c, 0x43, - 0x02, 0x01, 0x90, 0x0a, 0x01, 0x00, 0x01, 0x02, - 0x00, 0x01, 0x00, 0x05, 0x01, 0x8c, 0x06, 0x00, - 0x01, 0x00, 0x8a, 0x0a, 0x05, 0x00, 0xe3, 0xd7, - 0x9c, 0xe7, 0x29, 0x0c, 0x43, 0x02, 0x01, 0x92, - 0x0a, 0x01, 0x00, 0x01, 0x04, 0x00, 0x01, 0x00, - 0x0d, 0x01, 0x8c, 0x06, 0x00, 0x01, 0x00, 0x8a, - 0x0a, 0x05, 0x00, 0xe3, 0x41, 0x9f, 0x01, 0x00, - 0x00, 0xe3, 0xef, 0xbb, 0x9d, 0x25, 0x01, 0x00, - 0x0c, 0x43, 0x02, 0x01, 0x94, 0x0a, 0x01, 0x00, - 0x01, 0x05, 0x00, 0x02, 0x00, 0x14, 0x01, 0x8c, - 0x06, 0x00, 0x01, 0x00, 0x92, 0x0a, 0x0b, 0x00, - 0x8a, 0x0a, 0x05, 0x00, 0xe3, 0xf4, 0xdb, 0xe4, - 0x41, 0x9f, 0x01, 0x00, 0x00, 0xba, 0xe4, 0xef, - 0xbb, 0x9d, 0x24, 0x02, 0x00, 0xe8, 0xd7, 0x28, - 0x0c, 0x43, 0x02, 0x01, 0x96, 0x0a, 0x00, 0x00, - 0x00, 0x03, 0x00, 0x06, 0x00, 0x49, 0x00, 0xb8, - 0x06, 0x04, 0x00, 0x90, 0x0a, 0x0a, 0x00, 0x86, - 0x06, 0x00, 0x00, 0xc0, 0x06, 0x03, 0x00, 0x9e, - 0x06, 0x00, 0x01, 0x94, 0x0a, 0x0c, 0x00, 0x04, - 0x95, 0x02, 0x00, 0x00, 0xe7, 0xe4, 0x04, 0xca, - 0x01, 0x00, 0x00, 0xf5, 0x0e, 0xe5, 0x8e, 0xe9, - 0xe5, 0xe6, 0xbb, 0x9d, 0xa5, 0xf0, 0x31, 0x5d, - 0x04, 0x00, 0xe5, 0x46, 0x04, 0x87, 0x00, 0x00, - 0x00, 0xab, 0xf0, 0x1f, 0x5d, 0x04, 0x00, 0xe5, - 0xbb, 0x9c, 0x46, 0x04, 0xca, 0x01, 0x00, 0x00, - 0xab, 0xf0, 0x10, 0xe5, 0xbc, 0x9c, 0xe9, 0x5d, - 0x05, 0x00, 0x04, 0xca, 0x01, 0x00, 0x00, 0xf5, - 0x0e, 0x29, 0xe5, 0x8e, 0xe9, 0xf2, 0xca, 0x29, - 0x0c, 0x43, 0x02, 0x01, 0x98, 0x0a, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x04, 0x00, 0x1f, 0x00, 0xb8, - 0x06, 0x04, 0x00, 0x86, 0x06, 0x00, 0x00, 0xc0, - 0x06, 0x03, 0x00, 0x9e, 0x06, 0x00, 0x01, 0x04, - 0x95, 0x02, 0x00, 0x00, 0xe7, 0xe4, 0x8e, 0xe8, - 0xe4, 0xe5, 0xa5, 0xf0, 0x11, 0xe6, 0xe4, 0x46, - 0x04, 0xa4, 0x01, 0x00, 0x00, 0xab, 0xf1, 0x06, - 0xe4, 0x8e, 0xe8, 0xf2, 0xec, 0x29, 0x0c, 0x43, - 0x02, 0x01, 0x9a, 0x0a, 0x01, 0x00, 0x01, 0x03, - 0x00, 0x07, 0x00, 0x4c, 0x01, 0xac, 0x0a, 0x00, - 0x01, 0x00, 0xb8, 0x06, 0x04, 0x00, 0x90, 0x0a, - 0x0a, 0x00, 0x86, 0x06, 0x00, 0x00, 0xc0, 0x06, - 0x03, 0x00, 0x9e, 0x06, 0x00, 0x01, 0x8c, 0x06, - 0x01, 0x00, 0x94, 0x0a, 0x0c, 0x00, 0x04, 0x4c, - 0x00, 0x00, 0x00, 0xe7, 0xe4, 0xd7, 0xf5, 0x0e, - 0xe5, 0xe6, 0xa5, 0xf0, 0x3d, 0x5d, 0x04, 0x00, - 0xe5, 0x90, 0xe9, 0x46, 0x5f, 0x05, 0x00, 0x04, - 0xa4, 0x01, 0x00, 0x00, 0xab, 0xf0, 0x09, 0x04, - 0x37, 0x00, 0x00, 0x00, 0xe7, 0xf2, 0xe2, 0x5d, - 0x05, 0x00, 0x04, 0xc3, 0x01, 0x00, 0x00, 0xab, - 0xf0, 0x0b, 0xe5, 0xe6, 0xa8, 0xf1, 0x13, 0xe5, - 0x8e, 0xe9, 0xf2, 0xcd, 0x5d, 0x05, 0x00, 0xd7, - 0xab, 0xf0, 0xc6, 0x5d, 0x06, 0x00, 0xf4, 0x0e, - 0x29, 0x29, 0x0c, 0x43, 0x02, 0x01, 0x9c, 0x0a, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x09, 0x00, 0xc4, - 0x01, 0x00, 0xb8, 0x06, 0x04, 0x00, 0x90, 0x0a, - 0x0a, 0x00, 0x86, 0x06, 0x00, 0x00, 0xc0, 0x06, - 0x03, 0x00, 0x9e, 0x06, 0x00, 0x01, 0x8c, 0x06, - 0x01, 0x00, 0x92, 0x0a, 0x0b, 0x00, 0x94, 0x0a, - 0x0c, 0x00, 0xd0, 0x04, 0x00, 0x02, 0x04, 0x41, + 0xe6, 0x40, 0x37, 0x00, 0x00, 0x00, 0x46, 0x24, + 0x01, 0x00, 0x0e, 0xd7, 0x5d, 0x04, 0x00, 0xa9, + 0xf0, 0x3b, 0x64, 0x01, 0x00, 0x41, 0x9d, 0x01, + 0x00, 0x00, 0xd7, 0x24, 0x01, 0x00, 0x0e, 0x64, + 0x01, 0x00, 0x41, 0x9d, 0x01, 0x00, 0x00, 0x04, + 0xa4, 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, + 0xd7, 0x40, 0x39, 0x00, 0x00, 0x00, 0xf0, 0x44, + 0x64, 0x01, 0x00, 0x41, 0x9d, 0x01, 0x00, 0x00, + 0xd7, 0x40, 0x39, 0x00, 0x00, 0x00, 0x24, 0x01, + 0x00, 0x0e, 0xf2, 0x30, 0x64, 0x01, 0x00, 0x41, + 0x9d, 0x01, 0x00, 0x00, 0x04, 0x83, 0x02, 0x00, + 0x00, 0x24, 0x01, 0x00, 0x0e, 0x64, 0x01, 0x00, + 0x41, 0x9d, 0x01, 0x00, 0x00, 0xd7, 0x24, 0x01, + 0x00, 0x0e, 0x64, 0x01, 0x00, 0x41, 0x9d, 0x01, + 0x00, 0x00, 0x04, 0xa4, 0x01, 0x00, 0x00, 0x24, + 0x01, 0x00, 0x0e, 0xe3, 0xf0, 0x13, 0x64, 0x01, + 0x00, 0x41, 0x9d, 0x01, 0x00, 0x00, 0xe5, 0x40, + 0x9e, 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, + 0x5d, 0x05, 0x00, 0xf4, 0x29, 0x0c, 0x43, 0x02, + 0x01, 0xe8, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x03, 0x00, 0x11, 0x00, 0xa8, 0x04, 0x27, 0x00, + 0xec, 0x03, 0x00, 0x1a, 0xdc, 0x05, 0x81, 0x01, + 0x00, 0xba, 0xe7, 0x64, 0x01, 0x00, 0x41, 0x84, + 0x02, 0x00, 0x00, 0x24, 0x00, 0x00, 0x0e, 0xe5, + 0xf4, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xea, 0x05, + 0x01, 0x17, 0x01, 0x04, 0x0f, 0x03, 0x0a, 0x84, + 0x04, 0x18, 0x9e, 0x06, 0x00, 0x01, 0x40, 0x06, + 0x86, 0x06, 0x00, 0x00, 0x40, 0x04, 0x8c, 0x06, + 0x00, 0x01, 0x40, 0x08, 0xb2, 0x06, 0x00, 0x02, + 0x40, 0x0a, 0xc0, 0x06, 0x00, 0x03, 0x40, 0x05, + 0xb8, 0x06, 0x00, 0x04, 0x40, 0x02, 0x8a, 0x0a, + 0x00, 0x05, 0x40, 0x00, 0xa8, 0x04, 0x00, 0x06, + 0x00, 0x8c, 0x0a, 0x00, 0x07, 0x00, 0x8e, 0x0a, + 0x00, 0x08, 0x40, 0x09, 0x9a, 0x07, 0x00, 0x09, + 0x40, 0x0e, 0x90, 0x0a, 0x00, 0x0a, 0x40, 0x03, + 0x92, 0x0a, 0x00, 0x0b, 0x40, 0x01, 0x94, 0x0a, + 0x00, 0x0c, 0x40, 0x07, 0x96, 0x0a, 0x00, 0x0d, + 0x00, 0x98, 0x0a, 0x00, 0x0e, 0x00, 0x9a, 0x0a, + 0x00, 0x0f, 0x00, 0x9c, 0x0a, 0x00, 0x10, 0x00, + 0x9e, 0x0a, 0x00, 0x11, 0x00, 0xa0, 0x0a, 0x00, + 0x12, 0x40, 0x0b, 0xa2, 0x0a, 0x00, 0x13, 0x40, + 0x0c, 0xa4, 0x0a, 0x00, 0x14, 0x40, 0x0d, 0xa6, + 0x0a, 0x00, 0x15, 0x00, 0xa8, 0x0a, 0x00, 0x16, + 0x00, 0xd0, 0x04, 0x3b, 0x00, 0xd8, 0x04, 0x3f, + 0x00, 0xce, 0x04, 0x3a, 0x00, 0x0c, 0x43, 0x02, + 0x01, 0x90, 0x0a, 0x01, 0x00, 0x01, 0x02, 0x00, + 0x01, 0x00, 0x05, 0x01, 0x8c, 0x06, 0x00, 0x01, + 0x00, 0x8a, 0x0a, 0x05, 0x00, 0xe3, 0xd7, 0x9c, + 0xe7, 0x29, 0x0c, 0x43, 0x02, 0x01, 0x92, 0x0a, + 0x01, 0x00, 0x01, 0x04, 0x00, 0x01, 0x00, 0x0d, + 0x01, 0x8c, 0x06, 0x00, 0x01, 0x00, 0x8a, 0x0a, + 0x05, 0x00, 0xe3, 0x41, 0x9f, 0x01, 0x00, 0x00, + 0xe3, 0xef, 0xbb, 0x9d, 0x25, 0x01, 0x00, 0x0c, + 0x43, 0x02, 0x01, 0x94, 0x0a, 0x01, 0x00, 0x01, + 0x05, 0x00, 0x02, 0x00, 0x14, 0x01, 0x8c, 0x06, + 0x00, 0x01, 0x00, 0x92, 0x0a, 0x0b, 0x00, 0x8a, + 0x0a, 0x05, 0x00, 0xe3, 0xf4, 0xdb, 0xe4, 0x41, + 0x9f, 0x01, 0x00, 0x00, 0xba, 0xe4, 0xef, 0xbb, + 0x9d, 0x24, 0x02, 0x00, 0xe8, 0xd7, 0x28, 0x0c, + 0x43, 0x02, 0x01, 0x96, 0x0a, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x06, 0x00, 0x49, 0x00, 0xb8, 0x06, + 0x04, 0x00, 0x90, 0x0a, 0x0a, 0x00, 0x86, 0x06, + 0x00, 0x00, 0xc0, 0x06, 0x03, 0x00, 0x9e, 0x06, + 0x00, 0x01, 0x94, 0x0a, 0x0c, 0x00, 0x04, 0x95, 0x02, 0x00, 0x00, 0xe7, 0xe4, 0x04, 0xca, 0x01, - 0x00, 0x00, 0xf5, 0x0e, 0xe5, 0xe6, 0xa5, 0x68, - 0xb1, 0x00, 0x00, 0x00, 0x5d, 0x04, 0x00, 0xe5, + 0x00, 0x00, 0xf5, 0x0e, 0xe5, 0x8e, 0xe9, 0xe5, + 0xe6, 0xbb, 0x9d, 0xa5, 0xf0, 0x31, 0x5d, 0x04, + 0x00, 0xe5, 0x46, 0x04, 0x87, 0x00, 0x00, 0x00, + 0xab, 0xf0, 0x1f, 0x5d, 0x04, 0x00, 0xe5, 0xbb, + 0x9c, 0x46, 0x04, 0xca, 0x01, 0x00, 0x00, 0xab, + 0xf0, 0x10, 0xe5, 0xbc, 0x9c, 0xe9, 0x5d, 0x05, + 0x00, 0x04, 0xca, 0x01, 0x00, 0x00, 0xf5, 0x0e, + 0x29, 0xe5, 0x8e, 0xe9, 0xf2, 0xca, 0x29, 0x0c, + 0x43, 0x02, 0x01, 0x98, 0x0a, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x04, 0x00, 0x1f, 0x00, 0xb8, 0x06, + 0x04, 0x00, 0x86, 0x06, 0x00, 0x00, 0xc0, 0x06, + 0x03, 0x00, 0x9e, 0x06, 0x00, 0x01, 0x04, 0x95, + 0x02, 0x00, 0x00, 0xe7, 0xe4, 0x8e, 0xe8, 0xe4, + 0xe5, 0xa5, 0xf0, 0x11, 0xe6, 0xe4, 0x46, 0x04, + 0xa4, 0x01, 0x00, 0x00, 0xab, 0xf1, 0x06, 0xe4, + 0x8e, 0xe8, 0xf2, 0xec, 0x29, 0x0c, 0x43, 0x02, + 0x01, 0x9a, 0x0a, 0x01, 0x00, 0x01, 0x03, 0x00, + 0x07, 0x00, 0x4c, 0x01, 0xac, 0x0a, 0x00, 0x01, + 0x00, 0xb8, 0x06, 0x04, 0x00, 0x90, 0x0a, 0x0a, + 0x00, 0x86, 0x06, 0x00, 0x00, 0xc0, 0x06, 0x03, + 0x00, 0x9e, 0x06, 0x00, 0x01, 0x8c, 0x06, 0x01, + 0x00, 0x94, 0x0a, 0x0c, 0x00, 0x04, 0x4c, 0x00, + 0x00, 0x00, 0xe7, 0xe4, 0xd7, 0xf5, 0x0e, 0xe5, + 0xe6, 0xa5, 0xf0, 0x3d, 0x5d, 0x04, 0x00, 0xe5, 0x90, 0xe9, 0x46, 0x5f, 0x05, 0x00, 0x04, 0xa4, 0x01, 0x00, 0x00, 0xab, 0xf0, 0x09, 0x04, 0x37, - 0x00, 0x00, 0x00, 0xe7, 0xf2, 0xdf, 0x5d, 0x05, + 0x00, 0x00, 0x00, 0xe7, 0xf2, 0xe2, 0x5d, 0x05, 0x00, 0x04, 0xc3, 0x01, 0x00, 0x00, 0xab, 0xf0, - 0x0b, 0xe5, 0xe6, 0xa5, 0xf0, 0xcf, 0xe5, 0x8e, - 0xe9, 0xf2, 0xca, 0x5d, 0x06, 0x00, 0xf4, 0x04, - 0xed, 0x01, 0x00, 0x00, 0xab, 0xf0, 0x13, 0x5d, - 0x05, 0x00, 0x04, 0xc9, 0x01, 0x00, 0x00, 0xab, - 0xf0, 0xb3, 0x5d, 0x07, 0x00, 0xf4, 0x0e, 0xf2, - 0xac, 0x5d, 0x05, 0x00, 0x04, 0xed, 0x01, 0x00, - 0x00, 0xab, 0xf0, 0x2e, 0xe4, 0x04, 0xed, 0x01, - 0x00, 0x00, 0xf5, 0x0e, 0x5d, 0x04, 0x00, 0xe5, - 0x46, 0x04, 0xed, 0x01, 0x00, 0x00, 0xab, 0x11, - 0xf1, 0x0d, 0x0e, 0x5d, 0x04, 0x00, 0xe5, 0x46, - 0x04, 0xc9, 0x01, 0x00, 0x00, 0xab, 0x68, 0x7d, - 0xff, 0xff, 0xff, 0xe5, 0x8e, 0xe9, 0xf3, 0x75, - 0xff, 0x5d, 0x05, 0x00, 0x04, 0xca, 0x01, 0x00, - 0x00, 0xab, 0x68, 0x69, 0xff, 0xff, 0xff, 0x5d, - 0x07, 0x00, 0xf4, 0x0e, 0xe5, 0xe6, 0xa5, 0xf0, - 0x11, 0x5d, 0x08, 0x00, 0x5d, 0x04, 0x00, 0xe5, - 0x46, 0xf5, 0xf0, 0x06, 0xe5, 0x8e, 0xe9, 0xf2, - 0xec, 0x29, 0x0c, 0x43, 0x02, 0x01, 0x9e, 0x0a, - 0x00, 0x00, 0x00, 0x03, 0x00, 0x05, 0x00, 0x41, - 0x00, 0xb8, 0x06, 0x04, 0x00, 0x86, 0x06, 0x00, - 0x00, 0xc0, 0x06, 0x03, 0x00, 0xd0, 0x04, 0x00, - 0x02, 0x9e, 0x06, 0x00, 0x01, 0x04, 0x4a, 0x00, - 0x00, 0x00, 0xe7, 0xe4, 0xe5, 0xa5, 0xf0, 0x36, - 0xe6, 0x5d, 0x04, 0x00, 0xe4, 0x46, 0xf5, 0x11, - 0xf1, 0x25, 0x0e, 0x5d, 0x04, 0x00, 0xe4, 0x46, - 0x04, 0xbe, 0x01, 0x00, 0x00, 0xab, 0xf0, 0x1e, - 0xe4, 0xe5, 0xbb, 0x9d, 0xab, 0x11, 0xf1, 0x0f, - 0x0e, 0x5d, 0x04, 0x00, 0xe4, 0xbb, 0x9c, 0x46, - 0x04, 0xbe, 0x01, 0x00, 0x00, 0xac, 0xf0, 0x06, - 0xe4, 0x8e, 0xe8, 0xf2, 0xc7, 0x29, 0x0c, 0x43, - 0x02, 0x01, 0xa6, 0x0a, 0x00, 0x03, 0x00, 0x04, - 0x00, 0x0a, 0x00, 0x95, 0x02, 0x03, 0xf6, 0x06, - 0x00, 0x00, 0x00, 0x90, 0x09, 0x00, 0x01, 0x00, - 0xae, 0x0a, 0x00, 0x02, 0x00, 0x8e, 0x0a, 0x08, + 0x0b, 0xe5, 0xe6, 0xa8, 0xf1, 0x13, 0xe5, 0x8e, + 0xe9, 0xf2, 0xcd, 0x5d, 0x05, 0x00, 0xd7, 0xab, + 0xf0, 0xc6, 0x5d, 0x06, 0x00, 0xf4, 0x0e, 0x29, + 0x29, 0x0c, 0x43, 0x02, 0x01, 0x9c, 0x0a, 0x00, + 0x00, 0x00, 0x03, 0x00, 0x09, 0x00, 0xc4, 0x01, + 0x00, 0xb8, 0x06, 0x04, 0x00, 0x90, 0x0a, 0x0a, 0x00, 0x86, 0x06, 0x00, 0x00, 0xc0, 0x06, 0x03, - 0x00, 0xd0, 0x04, 0x00, 0x02, 0x9e, 0x06, 0x00, - 0x01, 0xb2, 0x06, 0x02, 0x00, 0xa0, 0x0a, 0x12, - 0x00, 0xb8, 0x06, 0x04, 0x00, 0xa2, 0x0a, 0x13, - 0x00, 0xa4, 0x0a, 0x14, 0x00, 0xbb, 0xe7, 0xe4, - 0xe5, 0xa5, 0xf0, 0x0f, 0xe6, 0x5d, 0x04, 0x00, - 0xe4, 0x46, 0xf5, 0xf0, 0x06, 0xe4, 0x8e, 0xe8, - 0xf2, 0xee, 0x5d, 0x04, 0x00, 0x41, 0x9f, 0x01, - 0x00, 0x00, 0x5d, 0x05, 0x00, 0xe4, 0x24, 0x02, - 0x00, 0xcf, 0x04, 0x98, 0x02, 0x00, 0x00, 0xcb, - 0x9c, 0x04, 0x98, 0x02, 0x00, 0x00, 0x9c, 0xd0, - 0x5d, 0x06, 0x00, 0x41, 0xc5, 0x01, 0x00, 0x00, - 0xcc, 0x24, 0x01, 0x00, 0xba, 0xa8, 0xf0, 0x7c, - 0x04, 0x47, 0x02, 0x00, 0x00, 0x5e, 0x07, 0x00, - 0xcb, 0x04, 0x03, 0x00, 0x00, 0x00, 0xad, 0x11, - 0xf1, 0x09, 0x0e, 0xcb, 0x04, 0x02, 0x00, 0x00, - 0x00, 0xad, 0xf0, 0x0b, 0x04, 0x4b, 0x00, 0x00, - 0x00, 0x5e, 0x07, 0x00, 0xf2, 0x43, 0xcb, 0x04, - 0x03, 0x00, 0x00, 0x00, 0xad, 0x11, 0xf1, 0x09, - 0x0e, 0xcb, 0x04, 0x02, 0x00, 0x00, 0x00, 0xad, - 0xf0, 0x0b, 0x04, 0x4b, 0x00, 0x00, 0x00, 0x5e, - 0x07, 0x00, 0xf2, 0x25, 0xcb, 0x04, 0x01, 0x00, - 0x00, 0x00, 0xad, 0xf0, 0x0b, 0x04, 0x01, 0x00, - 0x00, 0x00, 0x5e, 0x07, 0x00, 0xf2, 0x12, 0xcb, - 0x04, 0x49, 0x00, 0x00, 0x00, 0xad, 0xf0, 0x09, - 0x04, 0x49, 0x00, 0x00, 0x00, 0x5e, 0x07, 0x00, - 0x5d, 0x08, 0x00, 0x41, 0xc5, 0x01, 0x00, 0x00, - 0xcc, 0x24, 0x01, 0x00, 0xba, 0xa8, 0xf0, 0x03, - 0xba, 0xe7, 0x29, 0xe4, 0xd1, 0xcd, 0xe5, 0xa5, - 0xf0, 0x12, 0x5d, 0x04, 0x00, 0xcd, 0x46, 0x04, - 0xe8, 0x01, 0x00, 0x00, 0xab, 0xf0, 0x05, 0x92, - 0x02, 0xf2, 0xeb, 0xcd, 0xe5, 0xa5, 0xf0, 0x17, - 0x5d, 0x04, 0x00, 0xcd, 0x46, 0x04, 0xdf, 0x01, - 0x00, 0x00, 0xab, 0xf0, 0x0a, 0x04, 0x1b, 0x00, - 0x00, 0x00, 0x5e, 0x07, 0x00, 0x29, 0x5d, 0x09, - 0x00, 0x41, 0xc5, 0x01, 0x00, 0x00, 0xcc, 0x24, - 0x01, 0x00, 0xba, 0xa8, 0xf0, 0x0a, 0x04, 0x18, - 0x02, 0x00, 0x00, 0x5e, 0x07, 0x00, 0x29, 0x04, - 0x99, 0x02, 0x00, 0x00, 0x5e, 0x07, 0x00, 0xba, - 0xe7, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xa8, 0x0a, - 0x02, 0x00, 0x02, 0x03, 0x00, 0x02, 0x00, 0x2b, - 0x02, 0x86, 0x02, 0x00, 0x01, 0x00, 0xb4, 0x0a, - 0x00, 0x01, 0x00, 0x9a, 0x07, 0x09, 0x00, 0xb8, - 0x06, 0x04, 0x00, 0xe3, 0xef, 0xd7, 0xa5, 0xf0, - 0x12, 0xe3, 0x41, 0xb2, 0x01, 0x00, 0x00, 0x04, - 0x16, 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, - 0xf2, 0xea, 0xe3, 0xef, 0xd8, 0xa5, 0xf0, 0x0e, - 0xe3, 0x41, 0xb2, 0x01, 0x00, 0x00, 0xe4, 0x24, - 0x01, 0x00, 0x0e, 0xf2, 0xee, 0x29, 0xc5, 0x00, - 0xc8, 0x0a, 0xc5, 0x01, 0xc8, 0x0b, 0xc5, 0x02, - 0xc8, 0x0c, 0xc5, 0x03, 0xc8, 0x0d, 0xc5, 0x04, - 0xc8, 0x0e, 0xc5, 0x05, 0xc8, 0x0f, 0xc5, 0x06, - 0xc8, 0x10, 0xc5, 0x07, 0xc8, 0x11, 0xc5, 0x08, - 0xc8, 0x15, 0xc5, 0x09, 0xc8, 0x16, 0xd7, 0xef, - 0xd2, 0xc6, 0xc8, 0x05, 0xba, 0xc8, 0x06, 0xbb, - 0xc8, 0x08, 0x26, 0x00, 0x00, 0xc8, 0x09, 0x04, - 0x98, 0x02, 0x00, 0x00, 0x04, 0x9b, 0x02, 0x00, - 0x00, 0x9c, 0x04, 0x9c, 0x02, 0x00, 0x00, 0x9c, - 0x04, 0x9d, 0x02, 0x00, 0x00, 0x9c, 0x04, 0x9e, - 0x02, 0x00, 0x00, 0x9c, 0x04, 0x9f, 0x02, 0x00, - 0x00, 0x9c, 0x04, 0xa0, 0x02, 0x00, 0x00, 0x9c, - 0x04, 0xa1, 0x02, 0x00, 0x00, 0x9c, 0x04, 0xa2, - 0x02, 0x00, 0x00, 0x9c, 0x04, 0xa3, 0x02, 0x00, - 0x00, 0x9c, 0xc8, 0x12, 0x04, 0xa4, 0x02, 0x00, - 0x00, 0xc8, 0x13, 0x04, 0xa5, 0x02, 0x00, 0x00, - 0xc8, 0x14, 0xba, 0xcf, 0xcb, 0xce, 0xa5, 0x68, - 0x6a, 0x01, 0x00, 0x00, 0x07, 0xc8, 0x04, 0xcb, - 0xd1, 0xd7, 0xcb, 0x90, 0xcf, 0x46, 0xd4, 0x11, - 0x04, 0xe8, 0x01, 0x00, 0x00, 0xad, 0xf1, 0x1c, - 0x11, 0x04, 0xa6, 0x02, 0x00, 0x00, 0xad, 0xf1, - 0x13, 0x11, 0x04, 0xa7, 0x02, 0x00, 0x00, 0xad, - 0xf1, 0x0a, 0x11, 0x04, 0xa4, 0x01, 0x00, 0x00, - 0xad, 0xf0, 0x04, 0x0e, 0xf2, 0xc7, 0x11, 0x04, - 0xa8, 0x02, 0x00, 0x00, 0xad, 0xf1, 0x0a, 0x11, - 0x04, 0xf3, 0x01, 0x00, 0x00, 0xad, 0xf0, 0x18, - 0xcb, 0xce, 0xa5, 0xf0, 0x0d, 0xd7, 0xcb, 0x46, - 0xcc, 0xab, 0xf0, 0x06, 0x92, 0x00, 0x0e, 0xf2, - 0xa4, 0xbb, 0xc8, 0x08, 0x0e, 0xf2, 0x9e, 0x11, - 0x04, 0xca, 0x01, 0x00, 0x00, 0xad, 0xf0, 0x44, - 0xcb, 0xce, 0xa5, 0xf0, 0x13, 0xd7, 0xcb, 0x46, - 0x04, 0x87, 0x00, 0x00, 0x00, 0xab, 0xf0, 0x08, - 0xc7, 0x0d, 0xf4, 0x0e, 0xf3, 0xdc, 0x00, 0xcb, + 0x00, 0x9e, 0x06, 0x00, 0x01, 0x8c, 0x06, 0x01, + 0x00, 0x92, 0x0a, 0x0b, 0x00, 0x94, 0x0a, 0x0c, + 0x00, 0xd0, 0x04, 0x00, 0x02, 0x04, 0x41, 0x02, + 0x00, 0x00, 0xe7, 0xe4, 0x04, 0xca, 0x01, 0x00, + 0x00, 0xf5, 0x0e, 0xe5, 0xe6, 0xa5, 0x68, 0xb1, + 0x00, 0x00, 0x00, 0x5d, 0x04, 0x00, 0xe5, 0x90, + 0xe9, 0x46, 0x5f, 0x05, 0x00, 0x04, 0xa4, 0x01, + 0x00, 0x00, 0xab, 0xf0, 0x09, 0x04, 0x37, 0x00, + 0x00, 0x00, 0xe7, 0xf2, 0xdf, 0x5d, 0x05, 0x00, + 0x04, 0xc3, 0x01, 0x00, 0x00, 0xab, 0xf0, 0x0b, + 0xe5, 0xe6, 0xa5, 0xf0, 0xcf, 0xe5, 0x8e, 0xe9, + 0xf2, 0xca, 0x5d, 0x06, 0x00, 0xf4, 0x04, 0xed, + 0x01, 0x00, 0x00, 0xab, 0xf0, 0x13, 0x5d, 0x05, + 0x00, 0x04, 0xc9, 0x01, 0x00, 0x00, 0xab, 0xf0, + 0xb3, 0x5d, 0x07, 0x00, 0xf4, 0x0e, 0xf2, 0xac, + 0x5d, 0x05, 0x00, 0x04, 0xed, 0x01, 0x00, 0x00, + 0xab, 0xf0, 0x2e, 0xe4, 0x04, 0xed, 0x01, 0x00, + 0x00, 0xf5, 0x0e, 0x5d, 0x04, 0x00, 0xe5, 0x46, + 0x04, 0xed, 0x01, 0x00, 0x00, 0xab, 0x11, 0xf1, + 0x0d, 0x0e, 0x5d, 0x04, 0x00, 0xe5, 0x46, 0x04, + 0xc9, 0x01, 0x00, 0x00, 0xab, 0x68, 0x7d, 0xff, + 0xff, 0xff, 0xe5, 0x8e, 0xe9, 0xf3, 0x75, 0xff, + 0x5d, 0x05, 0x00, 0x04, 0xca, 0x01, 0x00, 0x00, + 0xab, 0x68, 0x69, 0xff, 0xff, 0xff, 0x5d, 0x07, + 0x00, 0xf4, 0x0e, 0xe5, 0xe6, 0xa5, 0xf0, 0x11, + 0x5d, 0x08, 0x00, 0x5d, 0x04, 0x00, 0xe5, 0x46, + 0xf5, 0xf0, 0x06, 0xe5, 0x8e, 0xe9, 0xf2, 0xec, + 0x29, 0x0c, 0x43, 0x02, 0x01, 0x9e, 0x0a, 0x00, + 0x00, 0x00, 0x03, 0x00, 0x05, 0x00, 0x41, 0x00, + 0xb8, 0x06, 0x04, 0x00, 0x86, 0x06, 0x00, 0x00, + 0xc0, 0x06, 0x03, 0x00, 0xd0, 0x04, 0x00, 0x02, + 0x9e, 0x06, 0x00, 0x01, 0x04, 0x4a, 0x00, 0x00, + 0x00, 0xe7, 0xe4, 0xe5, 0xa5, 0xf0, 0x36, 0xe6, + 0x5d, 0x04, 0x00, 0xe4, 0x46, 0xf5, 0x11, 0xf1, + 0x25, 0x0e, 0x5d, 0x04, 0x00, 0xe4, 0x46, 0x04, + 0xbe, 0x01, 0x00, 0x00, 0xab, 0xf0, 0x1e, 0xe4, + 0xe5, 0xbb, 0x9d, 0xab, 0x11, 0xf1, 0x0f, 0x0e, + 0x5d, 0x04, 0x00, 0xe4, 0xbb, 0x9c, 0x46, 0x04, + 0xbe, 0x01, 0x00, 0x00, 0xac, 0xf0, 0x06, 0xe4, + 0x8e, 0xe8, 0xf2, 0xc7, 0x29, 0x0c, 0x43, 0x02, + 0x01, 0xa6, 0x0a, 0x00, 0x03, 0x00, 0x04, 0x00, + 0x0a, 0x00, 0x95, 0x02, 0x03, 0xf6, 0x06, 0x00, + 0x00, 0x00, 0x90, 0x09, 0x00, 0x01, 0x00, 0xae, + 0x0a, 0x00, 0x02, 0x00, 0x8e, 0x0a, 0x08, 0x00, + 0x86, 0x06, 0x00, 0x00, 0xc0, 0x06, 0x03, 0x00, + 0xd0, 0x04, 0x00, 0x02, 0x9e, 0x06, 0x00, 0x01, + 0xb2, 0x06, 0x02, 0x00, 0xa0, 0x0a, 0x12, 0x00, + 0xb8, 0x06, 0x04, 0x00, 0xa2, 0x0a, 0x13, 0x00, + 0xa4, 0x0a, 0x14, 0x00, 0xbb, 0xe7, 0xe4, 0xe5, + 0xa5, 0xf0, 0x0f, 0xe6, 0x5d, 0x04, 0x00, 0xe4, + 0x46, 0xf5, 0xf0, 0x06, 0xe4, 0x8e, 0xe8, 0xf2, + 0xee, 0x5d, 0x04, 0x00, 0x41, 0x9f, 0x01, 0x00, + 0x00, 0x5d, 0x05, 0x00, 0xe4, 0x24, 0x02, 0x00, + 0xcf, 0x04, 0x98, 0x02, 0x00, 0x00, 0xcb, 0x9c, + 0x04, 0x98, 0x02, 0x00, 0x00, 0x9c, 0xd0, 0x5d, + 0x06, 0x00, 0x41, 0xc5, 0x01, 0x00, 0x00, 0xcc, + 0x24, 0x01, 0x00, 0xba, 0xa8, 0xf0, 0x7c, 0x04, + 0x47, 0x02, 0x00, 0x00, 0x5e, 0x07, 0x00, 0xcb, + 0x04, 0x03, 0x00, 0x00, 0x00, 0xad, 0x11, 0xf1, + 0x09, 0x0e, 0xcb, 0x04, 0x02, 0x00, 0x00, 0x00, + 0xad, 0xf0, 0x0b, 0x04, 0x4b, 0x00, 0x00, 0x00, + 0x5e, 0x07, 0x00, 0xf2, 0x43, 0xcb, 0x04, 0x03, + 0x00, 0x00, 0x00, 0xad, 0x11, 0xf1, 0x09, 0x0e, + 0xcb, 0x04, 0x02, 0x00, 0x00, 0x00, 0xad, 0xf0, + 0x0b, 0x04, 0x4b, 0x00, 0x00, 0x00, 0x5e, 0x07, + 0x00, 0xf2, 0x25, 0xcb, 0x04, 0x01, 0x00, 0x00, + 0x00, 0xad, 0xf0, 0x0b, 0x04, 0x01, 0x00, 0x00, + 0x00, 0x5e, 0x07, 0x00, 0xf2, 0x12, 0xcb, 0x04, + 0x49, 0x00, 0x00, 0x00, 0xad, 0xf0, 0x09, 0x04, + 0x49, 0x00, 0x00, 0x00, 0x5e, 0x07, 0x00, 0x5d, + 0x08, 0x00, 0x41, 0xc5, 0x01, 0x00, 0x00, 0xcc, + 0x24, 0x01, 0x00, 0xba, 0xa8, 0xf0, 0x03, 0xba, + 0xe7, 0x29, 0xe4, 0xd1, 0xcd, 0xe5, 0xa5, 0xf0, + 0x12, 0x5d, 0x04, 0x00, 0xcd, 0x46, 0x04, 0xe8, + 0x01, 0x00, 0x00, 0xab, 0xf0, 0x05, 0x92, 0x02, + 0xf2, 0xeb, 0xcd, 0xe5, 0xa5, 0xf0, 0x17, 0x5d, + 0x04, 0x00, 0xcd, 0x46, 0x04, 0xdf, 0x01, 0x00, + 0x00, 0xab, 0xf0, 0x0a, 0x04, 0x1b, 0x00, 0x00, + 0x00, 0x5e, 0x07, 0x00, 0x29, 0x5d, 0x09, 0x00, + 0x41, 0xc5, 0x01, 0x00, 0x00, 0xcc, 0x24, 0x01, + 0x00, 0xba, 0xa8, 0xf0, 0x0a, 0x04, 0x18, 0x02, + 0x00, 0x00, 0x5e, 0x07, 0x00, 0x29, 0x04, 0x99, + 0x02, 0x00, 0x00, 0x5e, 0x07, 0x00, 0xba, 0xe7, + 0x29, 0x0c, 0x43, 0x02, 0x01, 0xa8, 0x0a, 0x02, + 0x00, 0x02, 0x03, 0x00, 0x02, 0x00, 0x2b, 0x02, + 0x86, 0x02, 0x00, 0x01, 0x00, 0xb4, 0x0a, 0x00, + 0x01, 0x00, 0x9a, 0x07, 0x09, 0x00, 0xb8, 0x06, + 0x04, 0x00, 0xe3, 0xef, 0xd7, 0xa5, 0xf0, 0x12, + 0xe3, 0x41, 0xb2, 0x01, 0x00, 0x00, 0x04, 0x16, + 0x00, 0x00, 0x00, 0x24, 0x01, 0x00, 0x0e, 0xf2, + 0xea, 0xe3, 0xef, 0xd8, 0xa5, 0xf0, 0x0e, 0xe3, + 0x41, 0xb2, 0x01, 0x00, 0x00, 0xe4, 0x24, 0x01, + 0x00, 0x0e, 0xf2, 0xee, 0x29, 0xc5, 0x00, 0xc8, + 0x0a, 0xc5, 0x01, 0xc8, 0x0b, 0xc5, 0x02, 0xc8, + 0x0c, 0xc5, 0x03, 0xc8, 0x0d, 0xc5, 0x04, 0xc8, + 0x0e, 0xc5, 0x05, 0xc8, 0x0f, 0xc5, 0x06, 0xc8, + 0x10, 0xc5, 0x07, 0xc8, 0x11, 0xc5, 0x08, 0xc8, + 0x15, 0xc5, 0x09, 0xc8, 0x16, 0xd7, 0xef, 0xd2, + 0xc6, 0xc8, 0x05, 0xba, 0xc8, 0x06, 0xbb, 0xc8, + 0x08, 0x26, 0x00, 0x00, 0xc8, 0x09, 0x04, 0x98, + 0x02, 0x00, 0x00, 0x04, 0x9b, 0x02, 0x00, 0x00, + 0x9c, 0x04, 0x9c, 0x02, 0x00, 0x00, 0x9c, 0x04, + 0x9d, 0x02, 0x00, 0x00, 0x9c, 0x04, 0x9e, 0x02, + 0x00, 0x00, 0x9c, 0x04, 0x9f, 0x02, 0x00, 0x00, + 0x9c, 0x04, 0xa0, 0x02, 0x00, 0x00, 0x9c, 0x04, + 0xa1, 0x02, 0x00, 0x00, 0x9c, 0x04, 0xa2, 0x02, + 0x00, 0x00, 0x9c, 0x04, 0xa3, 0x02, 0x00, 0x00, + 0x9c, 0xc8, 0x12, 0x04, 0xa4, 0x02, 0x00, 0x00, + 0xc8, 0x13, 0x04, 0xa5, 0x02, 0x00, 0x00, 0xc8, + 0x14, 0xba, 0xcf, 0xcb, 0xce, 0xa5, 0x68, 0x6a, + 0x01, 0x00, 0x00, 0x07, 0xc8, 0x04, 0xcb, 0xd1, + 0xd7, 0xcb, 0x90, 0xcf, 0x46, 0xd4, 0x11, 0x04, + 0xe8, 0x01, 0x00, 0x00, 0xad, 0xf1, 0x1c, 0x11, + 0x04, 0xa6, 0x02, 0x00, 0x00, 0xad, 0xf1, 0x13, + 0x11, 0x04, 0xa7, 0x02, 0x00, 0x00, 0xad, 0xf1, + 0x0a, 0x11, 0x04, 0xa4, 0x01, 0x00, 0x00, 0xad, + 0xf0, 0x04, 0x0e, 0xf2, 0xc7, 0x11, 0x04, 0xa8, + 0x02, 0x00, 0x00, 0xad, 0xf1, 0x0a, 0x11, 0x04, + 0xf3, 0x01, 0x00, 0x00, 0xad, 0xf0, 0x18, 0xcb, + 0xce, 0xa5, 0xf0, 0x0d, 0xd7, 0xcb, 0x46, 0xcc, + 0xab, 0xf0, 0x06, 0x92, 0x00, 0x0e, 0xf2, 0xa4, + 0xbb, 0xc8, 0x08, 0x0e, 0xf2, 0x9e, 0x11, 0x04, + 0xca, 0x01, 0x00, 0x00, 0xad, 0xf0, 0x44, 0xcb, 0xce, 0xa5, 0xf0, 0x13, 0xd7, 0xcb, 0x46, 0x04, - 0xca, 0x01, 0x00, 0x00, 0xab, 0xf0, 0x08, 0xc7, - 0x0e, 0xf4, 0x0e, 0xf3, 0xc5, 0x00, 0xc7, 0x08, - 0xf0, 0x0b, 0xc7, 0x10, 0xf4, 0x0e, 0xba, 0xc8, - 0x08, 0xf3, 0xb7, 0x00, 0xbb, 0xc8, 0x08, 0x0e, - 0xf3, 0x53, 0xff, 0x11, 0x04, 0xc6, 0x01, 0x00, - 0x00, 0xad, 0xf1, 0x13, 0x11, 0x04, 0xc7, 0x01, - 0x00, 0x00, 0xad, 0xf1, 0x0a, 0x11, 0x04, 0xc8, - 0x01, 0x00, 0x00, 0xad, 0xf0, 0x0c, 0xc7, 0x0f, - 0xcc, 0xf5, 0x0e, 0xba, 0xc8, 0x08, 0xf3, 0x8a, - 0x00, 0x11, 0x04, 0xdf, 0x01, 0x00, 0x00, 0xad, - 0xf1, 0x13, 0x11, 0x04, 0xed, 0x01, 0x00, 0x00, - 0xad, 0xf1, 0x0a, 0x11, 0x04, 0x30, 0x02, 0x00, - 0x00, 0xad, 0xf0, 0x0f, 0xbb, 0xc8, 0x08, 0x92, - 0x06, 0xc7, 0x0a, 0xcc, 0xf5, 0x0e, 0x0e, 0xf3, - 0x04, 0xff, 0x11, 0x04, 0xe0, 0x01, 0x00, 0x00, - 0xad, 0xf1, 0x13, 0x11, 0x04, 0xc9, 0x01, 0x00, - 0x00, 0xad, 0xf1, 0x0a, 0x11, 0x04, 0x31, 0x02, - 0x00, 0x00, 0xad, 0xf0, 0x25, 0xba, 0xc8, 0x08, - 0xc7, 0x06, 0xba, 0xa7, 0xf0, 0x13, 0xe4, 0xc7, - 0x0b, 0xf4, 0xcc, 0xf6, 0xf0, 0x0b, 0x91, 0x06, - 0xc7, 0x0c, 0xf4, 0x0e, 0x0e, 0xf3, 0xce, 0xfe, - 0x04, 0x37, 0x00, 0x00, 0x00, 0xc8, 0x04, 0xf2, - 0x21, 0xe5, 0xcc, 0xf5, 0xf0, 0x0a, 0xc7, 0x11, - 0xf4, 0x0e, 0xba, 0xc8, 0x08, 0xf2, 0x13, 0xe3, - 0xcc, 0xf5, 0xf0, 0x07, 0xc7, 0x15, 0xf4, 0x0e, - 0xf2, 0x08, 0xbb, 0xc8, 0x08, 0x0e, 0xf3, 0xa5, - 0xfe, 0x0e, 0xc7, 0x04, 0x68, 0x9f, 0xfe, 0xff, - 0xff, 0xc7, 0x16, 0xcd, 0xcb, 0xf6, 0x0e, 0xf3, - 0x94, 0xfe, 0xc7, 0x16, 0xce, 0xce, 0xf6, 0x0e, - 0xc7, 0x05, 0xc7, 0x06, 0xc7, 0x09, 0x26, 0x03, - 0x00, 0x28, 0x0c, 0x43, 0x02, 0x01, 0xec, 0x05, - 0x01, 0x02, 0x01, 0x04, 0x00, 0x02, 0x00, 0x9d, - 0x01, 0x03, 0xf6, 0x06, 0x00, 0x01, 0x00, 0xd2, - 0x0a, 0x00, 0x00, 0x00, 0xd4, 0x0a, 0x00, 0x01, - 0x00, 0xec, 0x03, 0x00, 0x1a, 0xee, 0x03, 0x01, - 0x1a, 0x64, 0x00, 0x00, 0x41, 0xab, 0x02, 0x00, - 0x00, 0x04, 0xac, 0x02, 0x00, 0x00, 0x24, 0x01, - 0x00, 0xd3, 0xf0, 0x16, 0xcb, 0xba, 0x46, 0x04, - 0xca, 0x01, 0x00, 0x00, 0xad, 0xf0, 0x0b, 0xcb, - 0x04, 0xca, 0x01, 0x00, 0x00, 0x9c, 0xd7, 0x9c, - 0x28, 0x64, 0x00, 0x00, 0x41, 0xab, 0x02, 0x00, - 0x00, 0x04, 0xad, 0x02, 0x00, 0x00, 0x24, 0x01, - 0x00, 0xd0, 0x64, 0x01, 0x00, 0x40, 0xae, 0x02, - 0x00, 0x00, 0x04, 0xaf, 0x02, 0x00, 0x00, 0xad, - 0xf0, 0x0c, 0xcc, 0xf0, 0x09, 0xcc, 0x04, 0xb0, - 0x02, 0x00, 0x00, 0x9c, 0xcf, 0x64, 0x01, 0x00, - 0x41, 0xb1, 0x02, 0x00, 0x00, 0xcb, 0x04, 0xca, - 0x01, 0x00, 0x00, 0x9c, 0x24, 0x01, 0x00, 0xbb, - 0x46, 0xba, 0xad, 0xf0, 0x0b, 0xcb, 0x04, 0xca, - 0x01, 0x00, 0x00, 0x9c, 0xd7, 0x9c, 0x28, 0xcc, - 0x11, 0xf1, 0x1b, 0x0e, 0x64, 0x00, 0x00, 0x41, - 0xab, 0x02, 0x00, 0x00, 0x04, 0xb2, 0x02, 0x00, - 0x00, 0x24, 0x01, 0x00, 0x11, 0xf1, 0x07, 0x0e, - 0x04, 0xbe, 0x01, 0x00, 0x00, 0x04, 0xb3, 0x02, - 0x00, 0x00, 0x9c, 0xd7, 0x9c, 0x28, 0x0c, 0x43, - 0x02, 0x01, 0xee, 0x05, 0x00, 0x03, 0x00, 0x05, - 0x00, 0x03, 0x00, 0x67, 0x03, 0xf6, 0x06, 0x00, - 0x00, 0x00, 0xe8, 0x0a, 0x00, 0x01, 0x00, 0xea, - 0x09, 0x05, 0x00, 0x03, 0x92, 0x04, 0x1c, 0x00, - 0xec, 0x03, 0x00, 0x1a, 0xec, 0x05, 0x89, 0x01, - 0x00, 0xe3, 0x41, 0xbf, 0x01, 0x00, 0x00, 0xc3, - 0x18, 0xfc, 0x24, 0x01, 0x00, 0x41, 0x63, 0x00, - 0x00, 0x00, 0x04, 0xa4, 0x01, 0x00, 0x00, 0x24, - 0x01, 0x00, 0x41, 0x5a, 0x02, 0x00, 0x00, 0x24, - 0x00, 0x00, 0xd3, 0xf0, 0x43, 0x6b, 0x38, 0x00, - 0x00, 0x00, 0x64, 0x01, 0x00, 0x41, 0xb5, 0x02, - 0x00, 0x00, 0xe5, 0x04, 0xb6, 0x02, 0x00, 0x00, - 0xf5, 0x04, 0x48, 0x02, 0x00, 0x00, 0x24, 0x02, - 0x00, 0xd4, 0x41, 0x9d, 0x01, 0x00, 0x00, 0xcb, - 0x04, 0xa4, 0x01, 0x00, 0x00, 0x9c, 0x24, 0x01, - 0x00, 0x0e, 0xcc, 0x41, 0xb7, 0x02, 0x00, 0x00, - 0x24, 0x00, 0x00, 0x0e, 0x0e, 0x29, 0xd1, 0x6b, - 0x06, 0x00, 0x00, 0x00, 0x0e, 0x29, 0x30, 0x29, - 0x0c, 0x43, 0x02, 0x01, 0xf0, 0x05, 0x00, 0x01, - 0x00, 0x04, 0x00, 0x04, 0x00, 0x2f, 0x01, 0x92, - 0x06, 0x00, 0x00, 0x00, 0xec, 0x03, 0x00, 0x1a, - 0xec, 0x05, 0x89, 0x01, 0x00, 0x92, 0x04, 0x1c, - 0x00, 0x94, 0x04, 0x1d, 0x00, 0x64, 0x00, 0x00, - 0x41, 0xb8, 0x02, 0x00, 0x00, 0xe4, 0x04, 0xb6, - 0x02, 0x00, 0x00, 0xf5, 0x24, 0x01, 0x00, 0xd3, - 0xf0, 0x1a, 0xcb, 0x41, 0x5a, 0x02, 0x00, 0x00, - 0x24, 0x00, 0x00, 0x41, 0x65, 0x00, 0x00, 0x00, - 0x04, 0xa4, 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, - 0xed, 0xef, 0xea, 0x29, 0x0c, 0x43, 0x02, 0x01, - 0xf2, 0x05, 0x00, 0x02, 0x00, 0x04, 0x00, 0x04, - 0x02, 0x51, 0x02, 0xbc, 0x07, 0x00, 0x00, 0x00, - 0xf6, 0x06, 0x00, 0x01, 0x00, 0xec, 0x03, 0x00, - 0x1a, 0x80, 0x04, 0x13, 0x00, 0x82, 0x04, 0x14, - 0x00, 0x88, 0x04, 0x17, 0x00, 0x07, 0x16, 0x28, - 0x5c, 0x64, 0x2b, 0x29, 0x3b, 0x28, 0x5c, 0x64, - 0x2b, 0x29, 0x07, 0xa8, 0x01, 0x00, 0x00, 0x03, - 0x00, 0x4c, 0x00, 0x00, 0x00, 0x09, 0x06, 0x00, - 0x00, 0x00, 0x05, 0x08, 0xf5, 0xff, 0xff, 0xff, - 0x0c, 0x00, 0x0c, 0x01, 0x1d, 0x08, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, - 0x7f, 0x01, 0x00, 0x00, 0x00, 0x16, 0x01, 0x00, - 0x30, 0x00, 0x39, 0x00, 0x0b, 0x0d, 0x01, 0x01, - 0x3b, 0x0c, 0x02, 0x1d, 0x08, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x7f, - 0x01, 0x00, 0x00, 0x00, 0x16, 0x01, 0x00, 0x30, - 0x00, 0x39, 0x00, 0x0b, 0x0d, 0x02, 0x0d, 0x00, - 0x0b, 0x64, 0x00, 0x00, 0x41, 0xab, 0x02, 0x00, - 0x00, 0x04, 0xb9, 0x02, 0x00, 0x00, 0x24, 0x01, - 0x00, 0xd4, 0xf0, 0x21, 0xcc, 0x41, 0xcb, 0x01, - 0x00, 0x00, 0xc4, 0x00, 0xc4, 0x01, 0x34, 0x24, - 0x01, 0x00, 0xd3, 0xf0, 0x10, 0xcb, 0xbc, 0x46, - 0x8c, 0xba, 0xae, 0xf0, 0x08, 0xe4, 0x40, 0x70, - 0x02, 0x00, 0x00, 0xe9, 0x64, 0x00, 0x00, 0x41, - 0xab, 0x02, 0x00, 0x00, 0x04, 0xba, 0x02, 0x00, - 0x00, 0x24, 0x01, 0x00, 0xd4, 0xf0, 0x0b, 0xcc, - 0xba, 0x46, 0x8c, 0xba, 0xae, 0xf0, 0x03, 0x09, - 0xea, 0x29, 0xc5, 0x00, 0xc8, 0x35, 0xc5, 0x01, - 0xc8, 0x36, 0xc5, 0x02, 0xc8, 0x37, 0xc5, 0x03, - 0xc8, 0x38, 0xc5, 0x04, 0xc8, 0x39, 0xc5, 0x05, - 0xc8, 0x3a, 0xc5, 0x06, 0xc8, 0x3b, 0xc5, 0x07, - 0xc8, 0x3c, 0xc5, 0x08, 0xc8, 0x3d, 0xc5, 0x09, - 0xc8, 0x3e, 0xc5, 0x0a, 0xc8, 0x3f, 0xc5, 0x0b, - 0xc8, 0x40, 0xc5, 0x0c, 0xc8, 0x41, 0xc5, 0x0d, - 0xc8, 0x42, 0xc5, 0x0e, 0xc8, 0x43, 0xc5, 0x0f, - 0xc8, 0x44, 0xc5, 0x10, 0xc8, 0x45, 0xc5, 0x11, - 0xc8, 0x46, 0xc5, 0x12, 0xc8, 0x47, 0xc5, 0x13, - 0xc8, 0x48, 0xc5, 0x14, 0xc8, 0x49, 0xc5, 0x15, - 0xc8, 0x4a, 0xc5, 0x16, 0xc8, 0x4b, 0xc5, 0x17, - 0xc8, 0x4c, 0xc5, 0x18, 0xc8, 0x4d, 0xc5, 0x19, - 0xc8, 0x4e, 0xc5, 0x1a, 0xc8, 0x4f, 0xc5, 0x1b, - 0xc8, 0x50, 0xc5, 0x1c, 0xc8, 0x51, 0xc5, 0x1d, - 0xc8, 0x52, 0xc5, 0x1e, 0xc8, 0x53, 0xc5, 0x1f, - 0xc8, 0x54, 0xc5, 0x20, 0xc8, 0x55, 0xc5, 0x21, - 0xc8, 0x56, 0xc5, 0x22, 0xc8, 0x57, 0xc5, 0x23, - 0xc8, 0x58, 0xc5, 0x24, 0xc8, 0x59, 0xc5, 0x25, - 0xc8, 0x5a, 0xc5, 0x26, 0xc8, 0x5b, 0xc5, 0x27, - 0xc8, 0x5c, 0xc5, 0x28, 0xc8, 0x5d, 0xc5, 0x29, - 0xc8, 0x5e, 0xc5, 0x2a, 0xc8, 0x5f, 0xc5, 0x2b, - 0xc8, 0x60, 0xc5, 0x2c, 0xc8, 0x61, 0xc5, 0x2d, - 0xc8, 0x62, 0xc5, 0x2e, 0xc8, 0x63, 0xc5, 0x2f, - 0xc8, 0x64, 0xc5, 0x30, 0xc8, 0x65, 0xc5, 0x31, - 0xc8, 0x66, 0xc5, 0x32, 0xc8, 0x67, 0xc5, 0x33, - 0xc8, 0x68, 0xc5, 0x34, 0xc8, 0x69, 0xc5, 0x35, - 0xc8, 0x6a, 0xc5, 0x36, 0xc8, 0x6b, 0xc5, 0x37, - 0xc8, 0x6c, 0xc5, 0x38, 0xc8, 0x6e, 0xc5, 0x39, - 0xc8, 0x72, 0xc5, 0x3a, 0xc8, 0x73, 0xc5, 0x3b, - 0xc8, 0x74, 0xc5, 0x3c, 0xc8, 0x75, 0xc5, 0x3d, - 0xc8, 0x76, 0xc5, 0x3e, 0xc8, 0x77, 0xc5, 0x40, - 0xc8, 0x79, 0xc5, 0x41, 0xc8, 0x7a, 0xc5, 0x42, - 0xc8, 0x7b, 0xc5, 0x43, 0xc8, 0x7c, 0xc5, 0x44, - 0xc8, 0x7d, 0xc5, 0x45, 0xc8, 0x7e, 0xc5, 0x51, - 0xc8, 0x80, 0xc5, 0x52, 0xc8, 0x81, 0xc5, 0x53, - 0xc8, 0x82, 0xc5, 0x54, 0xc8, 0x83, 0xc5, 0x55, - 0xc8, 0x84, 0xc5, 0x56, 0xc8, 0x85, 0xc5, 0x57, - 0xc8, 0x86, 0xc5, 0x58, 0xc8, 0x87, 0xc5, 0x59, - 0xc8, 0x88, 0xc5, 0x5a, 0xc8, 0x89, 0xc5, 0x5b, - 0xc8, 0x8a, 0xc5, 0x5c, 0xc8, 0x8b, 0xc5, 0x5d, - 0xc8, 0x8c, 0xd7, 0x64, 0x02, 0x00, 0x42, 0xf8, - 0x00, 0x00, 0x00, 0xd7, 0x64, 0x01, 0x00, 0x42, - 0xf7, 0x00, 0x00, 0x00, 0xd7, 0x64, 0x00, 0x00, - 0x42, 0xf6, 0x00, 0x00, 0x00, 0xd7, 0x40, 0x9e, - 0x00, 0x00, 0x00, 0xcf, 0xd7, 0x40, 0xa2, 0x00, - 0x00, 0x00, 0xd0, 0xd7, 0x40, 0xa1, 0x00, 0x00, - 0x00, 0xd1, 0xd7, 0x40, 0xa3, 0x00, 0x00, 0x00, - 0xd2, 0xd7, 0x40, 0xbc, 0x00, 0x00, 0x00, 0xc8, - 0x04, 0xd7, 0x40, 0xb1, 0x00, 0x00, 0x00, 0xc8, - 0x05, 0xd7, 0x40, 0x9f, 0x00, 0x00, 0x00, 0xc8, - 0x06, 0xd7, 0x40, 0xa8, 0x00, 0x00, 0x00, 0xc8, - 0x07, 0xd7, 0x40, 0xac, 0x00, 0x00, 0x00, 0xc8, - 0x08, 0xd7, 0x40, 0xa0, 0x00, 0x00, 0x00, 0xc8, - 0x09, 0xd7, 0x40, 0xa4, 0x00, 0x00, 0x00, 0xc8, - 0x0a, 0xd7, 0x40, 0xa6, 0x00, 0x00, 0x00, 0xc8, - 0x0b, 0xd7, 0x40, 0xa7, 0x00, 0x00, 0x00, 0xc8, - 0x0c, 0xd7, 0x40, 0xfa, 0x00, 0x00, 0x00, 0xc8, - 0x0d, 0xd7, 0x40, 0xfb, 0x00, 0x00, 0x00, 0xc8, - 0x0e, 0xd7, 0x40, 0xfc, 0x00, 0x00, 0x00, 0xc8, - 0x0f, 0xd7, 0x40, 0xfd, 0x00, 0x00, 0x00, 0xc8, - 0x10, 0x04, 0xbb, 0x02, 0x00, 0x00, 0x04, 0xbc, - 0x02, 0x00, 0x00, 0x04, 0xbd, 0x02, 0x00, 0x00, - 0x04, 0xbe, 0x02, 0x00, 0x00, 0x04, 0xbf, 0x02, - 0x00, 0x00, 0x04, 0xc0, 0x02, 0x00, 0x00, 0x04, - 0xc1, 0x02, 0x00, 0x00, 0x04, 0xc2, 0x02, 0x00, - 0x00, 0x04, 0xc3, 0x02, 0x00, 0x00, 0x04, 0xc4, - 0x02, 0x00, 0x00, 0x04, 0xc5, 0x02, 0x00, 0x00, - 0x04, 0xc6, 0x02, 0x00, 0x00, 0x04, 0xc7, 0x02, - 0x00, 0x00, 0x04, 0x06, 0x00, 0x00, 0x00, 0x04, - 0xc8, 0x02, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, - 0x00, 0x04, 0xc9, 0x02, 0x00, 0x00, 0x04, 0xca, - 0x02, 0x00, 0x00, 0x04, 0xcb, 0x02, 0x00, 0x00, - 0x04, 0xcc, 0x02, 0x00, 0x00, 0x04, 0xcd, 0x02, - 0x00, 0x00, 0x26, 0x15, 0x00, 0xc8, 0x11, 0x0b, - 0x04, 0xce, 0x02, 0x00, 0x00, 0x4b, 0x9e, 0x01, - 0x00, 0x00, 0x04, 0xcf, 0x02, 0x00, 0x00, 0x4b, - 0xd0, 0x02, 0x00, 0x00, 0x04, 0xd1, 0x02, 0x00, - 0x00, 0x4b, 0xd2, 0x02, 0x00, 0x00, 0x04, 0xd3, - 0x02, 0x00, 0x00, 0x4b, 0xd4, 0x02, 0x00, 0x00, - 0x04, 0xd5, 0x02, 0x00, 0x00, 0x4b, 0xd6, 0x02, - 0x00, 0x00, 0x04, 0xd7, 0x02, 0x00, 0x00, 0x4b, - 0xd8, 0x02, 0x00, 0x00, 0x04, 0xd9, 0x02, 0x00, - 0x00, 0x4b, 0xda, 0x02, 0x00, 0x00, 0x04, 0xdb, - 0x02, 0x00, 0x00, 0x4b, 0xdc, 0x02, 0x00, 0x00, - 0x04, 0xdd, 0x02, 0x00, 0x00, 0x4b, 0xde, 0x02, - 0x00, 0x00, 0x04, 0xdf, 0x02, 0x00, 0x00, 0x4b, - 0xe0, 0x02, 0x00, 0x00, 0x04, 0xdf, 0x02, 0x00, - 0x00, 0x4b, 0xe1, 0x02, 0x00, 0x00, 0x04, 0xe2, - 0x02, 0x00, 0x00, 0x4b, 0xe3, 0x02, 0x00, 0x00, - 0x04, 0xe4, 0x02, 0x00, 0x00, 0x4b, 0xe5, 0x02, - 0x00, 0x00, 0x04, 0xe6, 0x02, 0x00, 0x00, 0x4b, - 0xe7, 0x02, 0x00, 0x00, 0x04, 0xe8, 0x02, 0x00, - 0x00, 0x4b, 0xe9, 0x02, 0x00, 0x00, 0x04, 0xea, - 0x02, 0x00, 0x00, 0x4b, 0xeb, 0x02, 0x00, 0x00, - 0x04, 0xec, 0x02, 0x00, 0x00, 0x4b, 0xed, 0x02, - 0x00, 0x00, 0x04, 0xee, 0x02, 0x00, 0x00, 0x4b, - 0xef, 0x02, 0x00, 0x00, 0xc8, 0x12, 0x0b, 0x0b, - 0x04, 0xdc, 0x02, 0x00, 0x00, 0x4b, 0x42, 0x02, - 0x00, 0x00, 0x04, 0xef, 0x02, 0x00, 0x00, 0x4b, - 0x4b, 0x00, 0x00, 0x00, 0x04, 0xde, 0x02, 0x00, - 0x00, 0x4b, 0x95, 0x02, 0x00, 0x00, 0x04, 0xda, - 0x02, 0x00, 0x00, 0x4b, 0x45, 0x02, 0x00, 0x00, - 0x04, 0xe5, 0x02, 0x00, 0x00, 0x4b, 0x16, 0x00, - 0x00, 0x00, 0x04, 0xe3, 0x02, 0x00, 0x00, 0x4b, - 0x37, 0x00, 0x00, 0x00, 0x04, 0xe7, 0x02, 0x00, - 0x00, 0x4b, 0x1b, 0x00, 0x00, 0x00, 0x04, 0xe5, - 0x02, 0x00, 0x00, 0x4b, 0x99, 0x02, 0x00, 0x00, - 0x04, 0xef, 0x02, 0x00, 0x00, 0x4b, 0x47, 0x02, - 0x00, 0x00, 0x04, 0xef, 0x02, 0x00, 0x00, 0x4b, - 0x01, 0x00, 0x00, 0x00, 0x04, 0xd4, 0x02, 0x00, - 0x00, 0x4b, 0x4a, 0x00, 0x00, 0x00, 0x04, 0xde, - 0x02, 0x00, 0x00, 0x4b, 0x44, 0x02, 0x00, 0x00, - 0x04, 0xde, 0x02, 0x00, 0x00, 0x4b, 0x3f, 0x02, - 0x00, 0x00, 0x04, 0xdc, 0x02, 0x00, 0x00, 0x4b, - 0x41, 0x02, 0x00, 0x00, 0x04, 0xed, 0x02, 0x00, - 0x00, 0x4b, 0x4c, 0x00, 0x00, 0x00, 0x04, 0xef, - 0x02, 0x00, 0x00, 0x4b, 0x4e, 0x00, 0x00, 0x00, - 0x04, 0xeb, 0x02, 0x00, 0x00, 0x4b, 0x18, 0x02, - 0x00, 0x00, 0x04, 0xef, 0x02, 0x00, 0x00, 0x4b, - 0x49, 0x00, 0x00, 0x00, 0x4b, 0x6d, 0x02, 0x00, - 0x00, 0x0b, 0x04, 0xdc, 0x02, 0x00, 0x00, 0x4b, - 0x42, 0x02, 0x00, 0x00, 0x04, 0xeb, 0x02, 0x00, - 0x00, 0x4b, 0x4b, 0x00, 0x00, 0x00, 0x04, 0xe1, - 0x02, 0x00, 0x00, 0x4b, 0x95, 0x02, 0x00, 0x00, - 0x04, 0xda, 0x02, 0x00, 0x00, 0x4b, 0x45, 0x02, - 0x00, 0x00, 0x04, 0xd0, 0x02, 0x00, 0x00, 0x4b, - 0x16, 0x00, 0x00, 0x00, 0x04, 0xd2, 0x02, 0x00, - 0x00, 0x4b, 0x37, 0x00, 0x00, 0x00, 0x04, 0xe7, - 0x02, 0x00, 0x00, 0x4b, 0x1b, 0x00, 0x00, 0x00, - 0x04, 0xd0, 0x02, 0x00, 0x00, 0x4b, 0x99, 0x02, - 0x00, 0x00, 0x04, 0xeb, 0x02, 0x00, 0x00, 0x4b, - 0x47, 0x02, 0x00, 0x00, 0x04, 0xeb, 0x02, 0x00, - 0x00, 0x4b, 0x01, 0x00, 0x00, 0x00, 0x04, 0xd4, - 0x02, 0x00, 0x00, 0x4b, 0x4a, 0x00, 0x00, 0x00, - 0x04, 0xd0, 0x02, 0x00, 0x00, 0x4b, 0x44, 0x02, - 0x00, 0x00, 0x04, 0xd0, 0x02, 0x00, 0x00, 0x4b, - 0x3f, 0x02, 0x00, 0x00, 0x04, 0xdc, 0x02, 0x00, - 0x00, 0x4b, 0x41, 0x02, 0x00, 0x00, 0x04, 0xed, - 0x02, 0x00, 0x00, 0x4b, 0x4c, 0x00, 0x00, 0x00, - 0x04, 0xe1, 0x02, 0x00, 0x00, 0x4b, 0x4e, 0x00, - 0x00, 0x00, 0x04, 0xeb, 0x02, 0x00, 0x00, 0x4b, - 0x18, 0x02, 0x00, 0x00, 0x04, 0xeb, 0x02, 0x00, - 0x00, 0x4b, 0x49, 0x00, 0x00, 0x00, 0x4b, 0x70, - 0x02, 0x00, 0x00, 0xc9, 0x13, 0x40, 0x6d, 0x02, - 0x00, 0x00, 0xc8, 0x14, 0x0a, 0xc8, 0x15, 0x09, - 0xc8, 0x16, 0x0a, 0xc8, 0x17, 0x09, 0xc8, 0x18, - 0xbc, 0xc8, 0x19, 0x09, 0xc8, 0x1a, 0x09, 0xc8, - 0x1b, 0x26, 0x00, 0x00, 0xc8, 0x1c, 0xc6, 0xc8, - 0x1e, 0xc6, 0xc8, 0x1f, 0xc6, 0xc8, 0x20, 0xba, - 0xc8, 0x21, 0x04, 0xf0, 0x02, 0x00, 0x00, 0xc8, - 0x22, 0x04, 0xf1, 0x02, 0x00, 0x00, 0xc8, 0x23, - 0xba, 0xc8, 0x25, 0xc6, 0xc8, 0x26, 0xba, 0xc8, - 0x27, 0xc6, 0xc8, 0x28, 0xba, 0xc8, 0x29, 0xc6, - 0xc8, 0x2a, 0xba, 0xc8, 0x2b, 0x09, 0xc8, 0x2e, - 0xba, 0xc8, 0x2f, 0xba, 0xc8, 0x30, 0xba, 0xc8, - 0x34, 0x0b, 0xc7, 0x48, 0x4b, 0xf2, 0x02, 0x00, - 0x00, 0xc7, 0x4b, 0x4b, 0xf3, 0x02, 0x00, 0x00, - 0xc7, 0x66, 0x4b, 0xf4, 0x02, 0x00, 0x00, 0xc7, - 0x5a, 0x4b, 0xf5, 0x02, 0x00, 0x00, 0xc7, 0x49, - 0x4b, 0xf6, 0x02, 0x00, 0x00, 0xc7, 0x4a, 0x4b, - 0xf7, 0x02, 0x00, 0x00, 0xc7, 0x46, 0x4b, 0xf8, - 0x02, 0x00, 0x00, 0xc7, 0x5b, 0x4b, 0xf9, 0x02, - 0x00, 0x00, 0xc7, 0x6c, 0x4b, 0xa6, 0x02, 0x00, - 0x00, 0xc7, 0x51, 0x4b, 0xa4, 0x01, 0x00, 0x00, - 0xc7, 0x61, 0x4b, 0xfa, 0x02, 0x00, 0x00, 0xc7, - 0x50, 0x4b, 0xfb, 0x02, 0x00, 0x00, 0xc7, 0x51, - 0x4b, 0xa7, 0x02, 0x00, 0x00, 0xc7, 0x54, 0x4b, - 0xfc, 0x02, 0x00, 0x00, 0xc7, 0x53, 0x4b, 0xfd, - 0x02, 0x00, 0x00, 0xc7, 0x45, 0x4b, 0xfe, 0x02, - 0x00, 0x00, 0xc7, 0x47, 0x4b, 0xff, 0x02, 0x00, - 0x00, 0xc7, 0x47, 0x4b, 0x00, 0x03, 0x00, 0x00, - 0xc7, 0x5c, 0x4b, 0x01, 0x03, 0x00, 0x00, 0xc7, - 0x64, 0x4b, 0x02, 0x03, 0x00, 0x00, 0xc7, 0x67, - 0x4b, 0x03, 0x03, 0x00, 0x00, 0xc7, 0x65, 0x4b, - 0x04, 0x03, 0x00, 0x00, 0xc7, 0x53, 0x4b, 0x05, - 0x03, 0x00, 0x00, 0xc7, 0x54, 0x4b, 0x06, 0x03, - 0x00, 0x00, 0xc7, 0x4a, 0x4b, 0x07, 0x03, 0x00, - 0x00, 0xc7, 0x4b, 0x4b, 0x08, 0x03, 0x00, 0x00, - 0xc7, 0x4e, 0x4b, 0x09, 0x03, 0x00, 0x00, 0xc7, - 0x4f, 0x4b, 0x0a, 0x03, 0x00, 0x00, 0xc7, 0x4e, - 0x4b, 0x0b, 0x03, 0x00, 0x00, 0xc7, 0x4f, 0x4b, - 0x0c, 0x03, 0x00, 0x00, 0xc7, 0x48, 0x4b, 0x0d, - 0x03, 0x00, 0x00, 0xc7, 0x59, 0x4b, 0x0e, 0x03, - 0x00, 0x00, 0xc7, 0x49, 0x4b, 0x0f, 0x03, 0x00, - 0x00, 0xc7, 0x56, 0x4b, 0x10, 0x03, 0x00, 0x00, - 0xc7, 0x57, 0x4b, 0x11, 0x03, 0x00, 0x00, 0xc7, - 0x53, 0x4b, 0x12, 0x03, 0x00, 0x00, 0xc7, 0x54, - 0x4b, 0x13, 0x03, 0x00, 0x00, 0xc7, 0x4a, 0x4b, - 0x14, 0x03, 0x00, 0x00, 0xc7, 0x4b, 0x4b, 0x15, - 0x03, 0x00, 0x00, 0xc7, 0x49, 0x4b, 0x16, 0x03, - 0x00, 0x00, 0xc7, 0x48, 0x4b, 0x17, 0x03, 0x00, - 0x00, 0xc7, 0x64, 0x4b, 0x18, 0x03, 0x00, 0x00, - 0xc7, 0x4f, 0x4b, 0x19, 0x03, 0x00, 0x00, 0xc7, - 0x63, 0x4b, 0x1a, 0x03, 0x00, 0x00, 0xc7, 0x4e, - 0x4b, 0x1b, 0x03, 0x00, 0x00, 0xc7, 0x62, 0x4b, - 0x1c, 0x03, 0x00, 0x00, 0xc7, 0x5f, 0x4b, 0x1d, - 0x03, 0x00, 0x00, 0xc7, 0x5d, 0x4b, 0x1e, 0x03, - 0x00, 0x00, 0xc7, 0x5e, 0x4b, 0x1f, 0x03, 0x00, - 0x00, 0xc7, 0x5b, 0x4b, 0x20, 0x03, 0x00, 0x00, - 0xc8, 0x6d, 0x0b, 0xc9, 0x78, 0xc5, 0x3f, 0x42, - 0x56, 0x02, 0x00, 0x00, 0xcb, 0x41, 0x68, 0x00, - 0x00, 0x00, 0x0b, 0xc7, 0x7b, 0x4b, 0x68, 0x01, - 0x00, 0x00, 0xc7, 0x7c, 0x4b, 0x69, 0x01, 0x00, - 0x00, 0xc5, 0x46, 0x4c, 0x21, 0x03, 0x00, 0x00, - 0x4b, 0x21, 0x03, 0x00, 0x00, 0xc5, 0x47, 0x4c, - 0x22, 0x03, 0x00, 0x00, 0x4b, 0x22, 0x03, 0x00, - 0x00, 0xc5, 0x48, 0x4c, 0x23, 0x03, 0x00, 0x00, - 0x4b, 0x23, 0x03, 0x00, 0x00, 0xc5, 0x49, 0x4c, - 0x24, 0x03, 0x00, 0x00, 0x4b, 0x24, 0x03, 0x00, - 0x00, 0xc5, 0x4a, 0x4c, 0x55, 0x02, 0x00, 0x00, - 0x4b, 0x55, 0x02, 0x00, 0x00, 0xc5, 0x4b, 0x4c, - 0x25, 0x03, 0x00, 0x00, 0x4b, 0x25, 0x03, 0x00, - 0x00, 0xc5, 0x4c, 0x4c, 0x3e, 0x02, 0x00, 0x00, - 0x4b, 0x3e, 0x02, 0x00, 0x00, 0xc5, 0x4d, 0x4c, - 0x6d, 0x02, 0x00, 0x00, 0x4b, 0x6d, 0x02, 0x00, - 0x00, 0xc5, 0x4e, 0x4c, 0x70, 0x02, 0x00, 0x00, - 0x4b, 0x70, 0x02, 0x00, 0x00, 0xc5, 0x4f, 0x4c, - 0xb0, 0x01, 0x00, 0x00, 0x4b, 0xb0, 0x01, 0x00, - 0x00, 0xc5, 0x50, 0x4c, 0x26, 0x03, 0x00, 0x00, - 0x4b, 0x26, 0x03, 0x00, 0x00, 0x07, 0x24, 0x02, - 0x00, 0xc8, 0x7f, 0xc7, 0x8c, 0xf4, 0x0e, 0xc7, - 0x8b, 0xf4, 0x0e, 0xc7, 0x35, 0xf4, 0x0e, 0xc7, - 0x80, 0xf4, 0x29, 0x08, 0xf0, 0x02, 0x29, 0xc5, - 0x00, 0x38, 0x95, 0x00, 0x00, 0x00, 0xf5, 0x0e, - 0x06, 0x2f, + 0x87, 0x00, 0x00, 0x00, 0xab, 0xf0, 0x08, 0xc7, + 0x0d, 0xf4, 0x0e, 0xf3, 0xdc, 0x00, 0xcb, 0xce, + 0xa5, 0xf0, 0x13, 0xd7, 0xcb, 0x46, 0x04, 0xca, + 0x01, 0x00, 0x00, 0xab, 0xf0, 0x08, 0xc7, 0x0e, + 0xf4, 0x0e, 0xf3, 0xc5, 0x00, 0xc7, 0x08, 0xf0, + 0x0b, 0xc7, 0x10, 0xf4, 0x0e, 0xba, 0xc8, 0x08, + 0xf3, 0xb7, 0x00, 0xbb, 0xc8, 0x08, 0x0e, 0xf3, + 0x53, 0xff, 0x11, 0x04, 0xc6, 0x01, 0x00, 0x00, + 0xad, 0xf1, 0x13, 0x11, 0x04, 0xc7, 0x01, 0x00, + 0x00, 0xad, 0xf1, 0x0a, 0x11, 0x04, 0xc8, 0x01, + 0x00, 0x00, 0xad, 0xf0, 0x0c, 0xc7, 0x0f, 0xcc, + 0xf5, 0x0e, 0xba, 0xc8, 0x08, 0xf3, 0x8a, 0x00, + 0x11, 0x04, 0xdf, 0x01, 0x00, 0x00, 0xad, 0xf1, + 0x13, 0x11, 0x04, 0xed, 0x01, 0x00, 0x00, 0xad, + 0xf1, 0x0a, 0x11, 0x04, 0x30, 0x02, 0x00, 0x00, + 0xad, 0xf0, 0x0f, 0xbb, 0xc8, 0x08, 0x92, 0x06, + 0xc7, 0x0a, 0xcc, 0xf5, 0x0e, 0x0e, 0xf3, 0x04, + 0xff, 0x11, 0x04, 0xe0, 0x01, 0x00, 0x00, 0xad, + 0xf1, 0x13, 0x11, 0x04, 0xc9, 0x01, 0x00, 0x00, + 0xad, 0xf1, 0x0a, 0x11, 0x04, 0x31, 0x02, 0x00, + 0x00, 0xad, 0xf0, 0x25, 0xba, 0xc8, 0x08, 0xc7, + 0x06, 0xba, 0xa7, 0xf0, 0x13, 0xe4, 0xc7, 0x0b, + 0xf4, 0xcc, 0xf6, 0xf0, 0x0b, 0x91, 0x06, 0xc7, + 0x0c, 0xf4, 0x0e, 0x0e, 0xf3, 0xce, 0xfe, 0x04, + 0x37, 0x00, 0x00, 0x00, 0xc8, 0x04, 0xf2, 0x21, + 0xe5, 0xcc, 0xf5, 0xf0, 0x0a, 0xc7, 0x11, 0xf4, + 0x0e, 0xba, 0xc8, 0x08, 0xf2, 0x13, 0xe3, 0xcc, + 0xf5, 0xf0, 0x07, 0xc7, 0x15, 0xf4, 0x0e, 0xf2, + 0x08, 0xbb, 0xc8, 0x08, 0x0e, 0xf3, 0xa5, 0xfe, + 0x0e, 0xc7, 0x04, 0x68, 0x9f, 0xfe, 0xff, 0xff, + 0xc7, 0x16, 0xcd, 0xcb, 0xf6, 0x0e, 0xf3, 0x94, + 0xfe, 0xc7, 0x16, 0xce, 0xce, 0xf6, 0x0e, 0xc7, + 0x05, 0xc7, 0x06, 0xc7, 0x09, 0x26, 0x03, 0x00, + 0x28, 0x0c, 0x43, 0x02, 0x01, 0xec, 0x05, 0x01, + 0x02, 0x01, 0x04, 0x00, 0x02, 0x00, 0x9d, 0x01, + 0x03, 0xf6, 0x06, 0x00, 0x01, 0x00, 0xd2, 0x0a, + 0x00, 0x00, 0x00, 0xd4, 0x0a, 0x00, 0x01, 0x00, + 0xec, 0x03, 0x00, 0x1a, 0xee, 0x03, 0x01, 0x1a, + 0x64, 0x00, 0x00, 0x41, 0xab, 0x02, 0x00, 0x00, + 0x04, 0xac, 0x02, 0x00, 0x00, 0x24, 0x01, 0x00, + 0xd3, 0xf0, 0x16, 0xcb, 0xba, 0x46, 0x04, 0xca, + 0x01, 0x00, 0x00, 0xad, 0xf0, 0x0b, 0xcb, 0x04, + 0xca, 0x01, 0x00, 0x00, 0x9c, 0xd7, 0x9c, 0x28, + 0x64, 0x00, 0x00, 0x41, 0xab, 0x02, 0x00, 0x00, + 0x04, 0xad, 0x02, 0x00, 0x00, 0x24, 0x01, 0x00, + 0xd0, 0x64, 0x01, 0x00, 0x40, 0xae, 0x02, 0x00, + 0x00, 0x04, 0xaf, 0x02, 0x00, 0x00, 0xad, 0xf0, + 0x0c, 0xcc, 0xf0, 0x09, 0xcc, 0x04, 0xb0, 0x02, + 0x00, 0x00, 0x9c, 0xcf, 0x64, 0x01, 0x00, 0x41, + 0xb1, 0x02, 0x00, 0x00, 0xcb, 0x04, 0xca, 0x01, + 0x00, 0x00, 0x9c, 0x24, 0x01, 0x00, 0xbb, 0x46, + 0xba, 0xad, 0xf0, 0x0b, 0xcb, 0x04, 0xca, 0x01, + 0x00, 0x00, 0x9c, 0xd7, 0x9c, 0x28, 0xcc, 0x11, + 0xf1, 0x1b, 0x0e, 0x64, 0x00, 0x00, 0x41, 0xab, + 0x02, 0x00, 0x00, 0x04, 0xb2, 0x02, 0x00, 0x00, + 0x24, 0x01, 0x00, 0x11, 0xf1, 0x07, 0x0e, 0x04, + 0xbe, 0x01, 0x00, 0x00, 0x04, 0xb3, 0x02, 0x00, + 0x00, 0x9c, 0xd7, 0x9c, 0x28, 0x0c, 0x43, 0x02, + 0x01, 0xee, 0x05, 0x00, 0x03, 0x00, 0x05, 0x00, + 0x03, 0x00, 0x67, 0x03, 0xf6, 0x06, 0x00, 0x00, + 0x00, 0xe8, 0x0a, 0x00, 0x01, 0x00, 0xea, 0x09, + 0x05, 0x00, 0x03, 0x92, 0x04, 0x1c, 0x00, 0xec, + 0x03, 0x00, 0x1a, 0xec, 0x05, 0x89, 0x01, 0x00, + 0xe3, 0x41, 0xbf, 0x01, 0x00, 0x00, 0xc3, 0x18, + 0xfc, 0x24, 0x01, 0x00, 0x41, 0x63, 0x00, 0x00, + 0x00, 0x04, 0xa4, 0x01, 0x00, 0x00, 0x24, 0x01, + 0x00, 0x41, 0x5a, 0x02, 0x00, 0x00, 0x24, 0x00, + 0x00, 0xd3, 0xf0, 0x43, 0x6b, 0x38, 0x00, 0x00, + 0x00, 0x64, 0x01, 0x00, 0x41, 0xb5, 0x02, 0x00, + 0x00, 0xe5, 0x04, 0xb6, 0x02, 0x00, 0x00, 0xf5, + 0x04, 0x48, 0x02, 0x00, 0x00, 0x24, 0x02, 0x00, + 0xd4, 0x41, 0x9d, 0x01, 0x00, 0x00, 0xcb, 0x04, + 0xa4, 0x01, 0x00, 0x00, 0x9c, 0x24, 0x01, 0x00, + 0x0e, 0xcc, 0x41, 0xb7, 0x02, 0x00, 0x00, 0x24, + 0x00, 0x00, 0x0e, 0x0e, 0x29, 0xd1, 0x6b, 0x06, + 0x00, 0x00, 0x00, 0x0e, 0x29, 0x30, 0x29, 0x0c, + 0x43, 0x02, 0x01, 0xf0, 0x05, 0x00, 0x01, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x2f, 0x01, 0x92, 0x06, + 0x00, 0x00, 0x00, 0xec, 0x03, 0x00, 0x1a, 0xec, + 0x05, 0x89, 0x01, 0x00, 0x92, 0x04, 0x1c, 0x00, + 0x94, 0x04, 0x1d, 0x00, 0x64, 0x00, 0x00, 0x41, + 0xb8, 0x02, 0x00, 0x00, 0xe4, 0x04, 0xb6, 0x02, + 0x00, 0x00, 0xf5, 0x24, 0x01, 0x00, 0xd3, 0xf0, + 0x1a, 0xcb, 0x41, 0x5a, 0x02, 0x00, 0x00, 0x24, + 0x00, 0x00, 0x41, 0x65, 0x00, 0x00, 0x00, 0x04, + 0xa4, 0x01, 0x00, 0x00, 0x24, 0x01, 0x00, 0xed, + 0xef, 0xea, 0x29, 0x0c, 0x43, 0x02, 0x01, 0xf2, + 0x05, 0x00, 0x02, 0x00, 0x04, 0x00, 0x04, 0x02, + 0x51, 0x02, 0xbc, 0x07, 0x00, 0x00, 0x00, 0xf6, + 0x06, 0x00, 0x01, 0x00, 0xec, 0x03, 0x00, 0x1a, + 0x80, 0x04, 0x13, 0x00, 0x82, 0x04, 0x14, 0x00, + 0x88, 0x04, 0x17, 0x00, 0x07, 0x16, 0x28, 0x5c, + 0x64, 0x2b, 0x29, 0x3b, 0x28, 0x5c, 0x64, 0x2b, + 0x29, 0x07, 0x76, 0x00, 0x00, 0x03, 0x00, 0x33, + 0x00, 0x00, 0x00, 0x0e, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x0d, 0xf5, 0xff, 0xff, 0xff, 0x13, 0x00, + 0x13, 0x01, 0x24, 0x01, 0x00, 0x30, 0x00, 0x39, + 0x00, 0x0e, 0xf4, 0xff, 0xff, 0xff, 0x14, 0x01, + 0x01, 0x3b, 0x00, 0x13, 0x02, 0x24, 0x01, 0x00, + 0x30, 0x00, 0x39, 0x00, 0x0e, 0xf4, 0xff, 0xff, + 0xff, 0x14, 0x02, 0x14, 0x00, 0x10, 0x64, 0x00, + 0x00, 0x41, 0xab, 0x02, 0x00, 0x00, 0x04, 0xb9, + 0x02, 0x00, 0x00, 0x24, 0x01, 0x00, 0xd4, 0xf0, + 0x21, 0xcc, 0x41, 0xcb, 0x01, 0x00, 0x00, 0xc4, + 0x00, 0xc4, 0x01, 0x34, 0x24, 0x01, 0x00, 0xd3, + 0xf0, 0x10, 0xcb, 0xbc, 0x46, 0x8c, 0xba, 0xae, + 0xf0, 0x08, 0xe4, 0x40, 0x70, 0x02, 0x00, 0x00, + 0xe9, 0x64, 0x00, 0x00, 0x41, 0xab, 0x02, 0x00, + 0x00, 0x04, 0xba, 0x02, 0x00, 0x00, 0x24, 0x01, + 0x00, 0xd4, 0xf0, 0x0b, 0xcc, 0xba, 0x46, 0x8c, + 0xba, 0xae, 0xf0, 0x03, 0x09, 0xea, 0x29, 0xc5, + 0x00, 0xc8, 0x35, 0xc5, 0x01, 0xc8, 0x36, 0xc5, + 0x02, 0xc8, 0x37, 0xc5, 0x03, 0xc8, 0x38, 0xc5, + 0x04, 0xc8, 0x39, 0xc5, 0x05, 0xc8, 0x3a, 0xc5, + 0x06, 0xc8, 0x3b, 0xc5, 0x07, 0xc8, 0x3c, 0xc5, + 0x08, 0xc8, 0x3d, 0xc5, 0x09, 0xc8, 0x3e, 0xc5, + 0x0a, 0xc8, 0x3f, 0xc5, 0x0b, 0xc8, 0x40, 0xc5, + 0x0c, 0xc8, 0x41, 0xc5, 0x0d, 0xc8, 0x42, 0xc5, + 0x0e, 0xc8, 0x43, 0xc5, 0x0f, 0xc8, 0x44, 0xc5, + 0x10, 0xc8, 0x45, 0xc5, 0x11, 0xc8, 0x46, 0xc5, + 0x12, 0xc8, 0x47, 0xc5, 0x13, 0xc8, 0x48, 0xc5, + 0x14, 0xc8, 0x49, 0xc5, 0x15, 0xc8, 0x4a, 0xc5, + 0x16, 0xc8, 0x4b, 0xc5, 0x17, 0xc8, 0x4c, 0xc5, + 0x18, 0xc8, 0x4d, 0xc5, 0x19, 0xc8, 0x4e, 0xc5, + 0x1a, 0xc8, 0x4f, 0xc5, 0x1b, 0xc8, 0x50, 0xc5, + 0x1c, 0xc8, 0x51, 0xc5, 0x1d, 0xc8, 0x52, 0xc5, + 0x1e, 0xc8, 0x53, 0xc5, 0x1f, 0xc8, 0x54, 0xc5, + 0x20, 0xc8, 0x55, 0xc5, 0x21, 0xc8, 0x56, 0xc5, + 0x22, 0xc8, 0x57, 0xc5, 0x23, 0xc8, 0x58, 0xc5, + 0x24, 0xc8, 0x59, 0xc5, 0x25, 0xc8, 0x5a, 0xc5, + 0x26, 0xc8, 0x5b, 0xc5, 0x27, 0xc8, 0x5c, 0xc5, + 0x28, 0xc8, 0x5d, 0xc5, 0x29, 0xc8, 0x5e, 0xc5, + 0x2a, 0xc8, 0x5f, 0xc5, 0x2b, 0xc8, 0x60, 0xc5, + 0x2c, 0xc8, 0x61, 0xc5, 0x2d, 0xc8, 0x62, 0xc5, + 0x2e, 0xc8, 0x63, 0xc5, 0x2f, 0xc8, 0x64, 0xc5, + 0x30, 0xc8, 0x65, 0xc5, 0x31, 0xc8, 0x66, 0xc5, + 0x32, 0xc8, 0x67, 0xc5, 0x33, 0xc8, 0x68, 0xc5, + 0x34, 0xc8, 0x69, 0xc5, 0x35, 0xc8, 0x6a, 0xc5, + 0x36, 0xc8, 0x6b, 0xc5, 0x37, 0xc8, 0x6c, 0xc5, + 0x38, 0xc8, 0x6e, 0xc5, 0x39, 0xc8, 0x72, 0xc5, + 0x3a, 0xc8, 0x73, 0xc5, 0x3b, 0xc8, 0x74, 0xc5, + 0x3c, 0xc8, 0x75, 0xc5, 0x3d, 0xc8, 0x76, 0xc5, + 0x3e, 0xc8, 0x77, 0xc5, 0x40, 0xc8, 0x79, 0xc5, + 0x41, 0xc8, 0x7a, 0xc5, 0x42, 0xc8, 0x7b, 0xc5, + 0x43, 0xc8, 0x7c, 0xc5, 0x44, 0xc8, 0x7d, 0xc5, + 0x45, 0xc8, 0x7e, 0xc5, 0x51, 0xc8, 0x80, 0xc5, + 0x52, 0xc8, 0x81, 0xc5, 0x53, 0xc8, 0x82, 0xc5, + 0x54, 0xc8, 0x83, 0xc5, 0x55, 0xc8, 0x84, 0xc5, + 0x56, 0xc8, 0x85, 0xc5, 0x57, 0xc8, 0x86, 0xc5, + 0x58, 0xc8, 0x87, 0xc5, 0x59, 0xc8, 0x88, 0xc5, + 0x5a, 0xc8, 0x89, 0xc5, 0x5b, 0xc8, 0x8a, 0xc5, + 0x5c, 0xc8, 0x8b, 0xc5, 0x5d, 0xc8, 0x8c, 0xd7, + 0x64, 0x02, 0x00, 0x42, 0xf8, 0x00, 0x00, 0x00, + 0xd7, 0x64, 0x01, 0x00, 0x42, 0xf7, 0x00, 0x00, + 0x00, 0xd7, 0x64, 0x00, 0x00, 0x42, 0xf6, 0x00, + 0x00, 0x00, 0xd7, 0x40, 0x9e, 0x00, 0x00, 0x00, + 0xcf, 0xd7, 0x40, 0xa2, 0x00, 0x00, 0x00, 0xd0, + 0xd7, 0x40, 0xa1, 0x00, 0x00, 0x00, 0xd1, 0xd7, + 0x40, 0xa3, 0x00, 0x00, 0x00, 0xd2, 0xd7, 0x40, + 0xbc, 0x00, 0x00, 0x00, 0xc8, 0x04, 0xd7, 0x40, + 0xb1, 0x00, 0x00, 0x00, 0xc8, 0x05, 0xd7, 0x40, + 0x9f, 0x00, 0x00, 0x00, 0xc8, 0x06, 0xd7, 0x40, + 0xa8, 0x00, 0x00, 0x00, 0xc8, 0x07, 0xd7, 0x40, + 0xac, 0x00, 0x00, 0x00, 0xc8, 0x08, 0xd7, 0x40, + 0xa0, 0x00, 0x00, 0x00, 0xc8, 0x09, 0xd7, 0x40, + 0xa4, 0x00, 0x00, 0x00, 0xc8, 0x0a, 0xd7, 0x40, + 0xa6, 0x00, 0x00, 0x00, 0xc8, 0x0b, 0xd7, 0x40, + 0xa7, 0x00, 0x00, 0x00, 0xc8, 0x0c, 0xd7, 0x40, + 0xfa, 0x00, 0x00, 0x00, 0xc8, 0x0d, 0xd7, 0x40, + 0xfb, 0x00, 0x00, 0x00, 0xc8, 0x0e, 0xd7, 0x40, + 0xfc, 0x00, 0x00, 0x00, 0xc8, 0x0f, 0xd7, 0x40, + 0xfd, 0x00, 0x00, 0x00, 0xc8, 0x10, 0x04, 0xbb, + 0x02, 0x00, 0x00, 0x04, 0xbc, 0x02, 0x00, 0x00, + 0x04, 0xbd, 0x02, 0x00, 0x00, 0x04, 0xbe, 0x02, + 0x00, 0x00, 0x04, 0xbf, 0x02, 0x00, 0x00, 0x04, + 0xc0, 0x02, 0x00, 0x00, 0x04, 0xc1, 0x02, 0x00, + 0x00, 0x04, 0xc2, 0x02, 0x00, 0x00, 0x04, 0xc3, + 0x02, 0x00, 0x00, 0x04, 0xc4, 0x02, 0x00, 0x00, + 0x04, 0xc5, 0x02, 0x00, 0x00, 0x04, 0xc6, 0x02, + 0x00, 0x00, 0x04, 0xc7, 0x02, 0x00, 0x00, 0x04, + 0x06, 0x00, 0x00, 0x00, 0x04, 0xc8, 0x02, 0x00, + 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x04, 0xc9, + 0x02, 0x00, 0x00, 0x04, 0xca, 0x02, 0x00, 0x00, + 0x04, 0xcb, 0x02, 0x00, 0x00, 0x04, 0xcc, 0x02, + 0x00, 0x00, 0x04, 0xcd, 0x02, 0x00, 0x00, 0x26, + 0x15, 0x00, 0xc8, 0x11, 0x0b, 0x04, 0xce, 0x02, + 0x00, 0x00, 0x4b, 0x9e, 0x01, 0x00, 0x00, 0x04, + 0xcf, 0x02, 0x00, 0x00, 0x4b, 0xd0, 0x02, 0x00, + 0x00, 0x04, 0xd1, 0x02, 0x00, 0x00, 0x4b, 0xd2, + 0x02, 0x00, 0x00, 0x04, 0xd3, 0x02, 0x00, 0x00, + 0x4b, 0xd4, 0x02, 0x00, 0x00, 0x04, 0xd5, 0x02, + 0x00, 0x00, 0x4b, 0xd6, 0x02, 0x00, 0x00, 0x04, + 0xd7, 0x02, 0x00, 0x00, 0x4b, 0xd8, 0x02, 0x00, + 0x00, 0x04, 0xd9, 0x02, 0x00, 0x00, 0x4b, 0xda, + 0x02, 0x00, 0x00, 0x04, 0xdb, 0x02, 0x00, 0x00, + 0x4b, 0xdc, 0x02, 0x00, 0x00, 0x04, 0xdd, 0x02, + 0x00, 0x00, 0x4b, 0xde, 0x02, 0x00, 0x00, 0x04, + 0xdf, 0x02, 0x00, 0x00, 0x4b, 0xe0, 0x02, 0x00, + 0x00, 0x04, 0xdf, 0x02, 0x00, 0x00, 0x4b, 0xe1, + 0x02, 0x00, 0x00, 0x04, 0xe2, 0x02, 0x00, 0x00, + 0x4b, 0xe3, 0x02, 0x00, 0x00, 0x04, 0xe4, 0x02, + 0x00, 0x00, 0x4b, 0xe5, 0x02, 0x00, 0x00, 0x04, + 0xe6, 0x02, 0x00, 0x00, 0x4b, 0xe7, 0x02, 0x00, + 0x00, 0x04, 0xe8, 0x02, 0x00, 0x00, 0x4b, 0xe9, + 0x02, 0x00, 0x00, 0x04, 0xea, 0x02, 0x00, 0x00, + 0x4b, 0xeb, 0x02, 0x00, 0x00, 0x04, 0xec, 0x02, + 0x00, 0x00, 0x4b, 0xed, 0x02, 0x00, 0x00, 0x04, + 0xee, 0x02, 0x00, 0x00, 0x4b, 0xef, 0x02, 0x00, + 0x00, 0xc8, 0x12, 0x0b, 0x0b, 0x04, 0xdc, 0x02, + 0x00, 0x00, 0x4b, 0x42, 0x02, 0x00, 0x00, 0x04, + 0xef, 0x02, 0x00, 0x00, 0x4b, 0x4b, 0x00, 0x00, + 0x00, 0x04, 0xde, 0x02, 0x00, 0x00, 0x4b, 0x95, + 0x02, 0x00, 0x00, 0x04, 0xda, 0x02, 0x00, 0x00, + 0x4b, 0x45, 0x02, 0x00, 0x00, 0x04, 0xe5, 0x02, + 0x00, 0x00, 0x4b, 0x16, 0x00, 0x00, 0x00, 0x04, + 0xe3, 0x02, 0x00, 0x00, 0x4b, 0x37, 0x00, 0x00, + 0x00, 0x04, 0xe7, 0x02, 0x00, 0x00, 0x4b, 0x1b, + 0x00, 0x00, 0x00, 0x04, 0xe5, 0x02, 0x00, 0x00, + 0x4b, 0x99, 0x02, 0x00, 0x00, 0x04, 0xef, 0x02, + 0x00, 0x00, 0x4b, 0x47, 0x02, 0x00, 0x00, 0x04, + 0xef, 0x02, 0x00, 0x00, 0x4b, 0x01, 0x00, 0x00, + 0x00, 0x04, 0xd4, 0x02, 0x00, 0x00, 0x4b, 0x4a, + 0x00, 0x00, 0x00, 0x04, 0xde, 0x02, 0x00, 0x00, + 0x4b, 0x44, 0x02, 0x00, 0x00, 0x04, 0xde, 0x02, + 0x00, 0x00, 0x4b, 0x3f, 0x02, 0x00, 0x00, 0x04, + 0xdc, 0x02, 0x00, 0x00, 0x4b, 0x41, 0x02, 0x00, + 0x00, 0x04, 0xed, 0x02, 0x00, 0x00, 0x4b, 0x4c, + 0x00, 0x00, 0x00, 0x04, 0xef, 0x02, 0x00, 0x00, + 0x4b, 0x4e, 0x00, 0x00, 0x00, 0x04, 0xeb, 0x02, + 0x00, 0x00, 0x4b, 0x18, 0x02, 0x00, 0x00, 0x04, + 0xef, 0x02, 0x00, 0x00, 0x4b, 0x49, 0x00, 0x00, + 0x00, 0x4b, 0x6d, 0x02, 0x00, 0x00, 0x0b, 0x04, + 0xdc, 0x02, 0x00, 0x00, 0x4b, 0x42, 0x02, 0x00, + 0x00, 0x04, 0xeb, 0x02, 0x00, 0x00, 0x4b, 0x4b, + 0x00, 0x00, 0x00, 0x04, 0xe1, 0x02, 0x00, 0x00, + 0x4b, 0x95, 0x02, 0x00, 0x00, 0x04, 0xda, 0x02, + 0x00, 0x00, 0x4b, 0x45, 0x02, 0x00, 0x00, 0x04, + 0xd0, 0x02, 0x00, 0x00, 0x4b, 0x16, 0x00, 0x00, + 0x00, 0x04, 0xd2, 0x02, 0x00, 0x00, 0x4b, 0x37, + 0x00, 0x00, 0x00, 0x04, 0xe7, 0x02, 0x00, 0x00, + 0x4b, 0x1b, 0x00, 0x00, 0x00, 0x04, 0xd0, 0x02, + 0x00, 0x00, 0x4b, 0x99, 0x02, 0x00, 0x00, 0x04, + 0xeb, 0x02, 0x00, 0x00, 0x4b, 0x47, 0x02, 0x00, + 0x00, 0x04, 0xeb, 0x02, 0x00, 0x00, 0x4b, 0x01, + 0x00, 0x00, 0x00, 0x04, 0xd4, 0x02, 0x00, 0x00, + 0x4b, 0x4a, 0x00, 0x00, 0x00, 0x04, 0xd0, 0x02, + 0x00, 0x00, 0x4b, 0x44, 0x02, 0x00, 0x00, 0x04, + 0xd0, 0x02, 0x00, 0x00, 0x4b, 0x3f, 0x02, 0x00, + 0x00, 0x04, 0xdc, 0x02, 0x00, 0x00, 0x4b, 0x41, + 0x02, 0x00, 0x00, 0x04, 0xed, 0x02, 0x00, 0x00, + 0x4b, 0x4c, 0x00, 0x00, 0x00, 0x04, 0xe1, 0x02, + 0x00, 0x00, 0x4b, 0x4e, 0x00, 0x00, 0x00, 0x04, + 0xeb, 0x02, 0x00, 0x00, 0x4b, 0x18, 0x02, 0x00, + 0x00, 0x04, 0xeb, 0x02, 0x00, 0x00, 0x4b, 0x49, + 0x00, 0x00, 0x00, 0x4b, 0x70, 0x02, 0x00, 0x00, + 0xc9, 0x13, 0x40, 0x6d, 0x02, 0x00, 0x00, 0xc8, + 0x14, 0x0a, 0xc8, 0x15, 0x09, 0xc8, 0x16, 0x0a, + 0xc8, 0x17, 0x09, 0xc8, 0x18, 0xbc, 0xc8, 0x19, + 0x09, 0xc8, 0x1a, 0x09, 0xc8, 0x1b, 0x26, 0x00, + 0x00, 0xc8, 0x1c, 0xc6, 0xc8, 0x1e, 0xc6, 0xc8, + 0x1f, 0xc6, 0xc8, 0x20, 0xba, 0xc8, 0x21, 0x04, + 0xf0, 0x02, 0x00, 0x00, 0xc8, 0x22, 0x04, 0xf1, + 0x02, 0x00, 0x00, 0xc8, 0x23, 0xba, 0xc8, 0x25, + 0xc6, 0xc8, 0x26, 0xba, 0xc8, 0x27, 0xc6, 0xc8, + 0x28, 0xba, 0xc8, 0x29, 0xc6, 0xc8, 0x2a, 0xba, + 0xc8, 0x2b, 0x09, 0xc8, 0x2e, 0xba, 0xc8, 0x2f, + 0xba, 0xc8, 0x30, 0xba, 0xc8, 0x34, 0x0b, 0xc7, + 0x48, 0x4b, 0xf2, 0x02, 0x00, 0x00, 0xc7, 0x4b, + 0x4b, 0xf3, 0x02, 0x00, 0x00, 0xc7, 0x66, 0x4b, + 0xf4, 0x02, 0x00, 0x00, 0xc7, 0x5a, 0x4b, 0xf5, + 0x02, 0x00, 0x00, 0xc7, 0x49, 0x4b, 0xf6, 0x02, + 0x00, 0x00, 0xc7, 0x4a, 0x4b, 0xf7, 0x02, 0x00, + 0x00, 0xc7, 0x46, 0x4b, 0xf8, 0x02, 0x00, 0x00, + 0xc7, 0x5b, 0x4b, 0xf9, 0x02, 0x00, 0x00, 0xc7, + 0x6c, 0x4b, 0xa6, 0x02, 0x00, 0x00, 0xc7, 0x51, + 0x4b, 0xa4, 0x01, 0x00, 0x00, 0xc7, 0x61, 0x4b, + 0xfa, 0x02, 0x00, 0x00, 0xc7, 0x50, 0x4b, 0xfb, + 0x02, 0x00, 0x00, 0xc7, 0x51, 0x4b, 0xa7, 0x02, + 0x00, 0x00, 0xc7, 0x54, 0x4b, 0xfc, 0x02, 0x00, + 0x00, 0xc7, 0x53, 0x4b, 0xfd, 0x02, 0x00, 0x00, + 0xc7, 0x45, 0x4b, 0xfe, 0x02, 0x00, 0x00, 0xc7, + 0x47, 0x4b, 0xff, 0x02, 0x00, 0x00, 0xc7, 0x47, + 0x4b, 0x00, 0x03, 0x00, 0x00, 0xc7, 0x5c, 0x4b, + 0x01, 0x03, 0x00, 0x00, 0xc7, 0x64, 0x4b, 0x02, + 0x03, 0x00, 0x00, 0xc7, 0x67, 0x4b, 0x03, 0x03, + 0x00, 0x00, 0xc7, 0x65, 0x4b, 0x04, 0x03, 0x00, + 0x00, 0xc7, 0x53, 0x4b, 0x05, 0x03, 0x00, 0x00, + 0xc7, 0x54, 0x4b, 0x06, 0x03, 0x00, 0x00, 0xc7, + 0x4a, 0x4b, 0x07, 0x03, 0x00, 0x00, 0xc7, 0x4b, + 0x4b, 0x08, 0x03, 0x00, 0x00, 0xc7, 0x4e, 0x4b, + 0x09, 0x03, 0x00, 0x00, 0xc7, 0x4f, 0x4b, 0x0a, + 0x03, 0x00, 0x00, 0xc7, 0x4e, 0x4b, 0x0b, 0x03, + 0x00, 0x00, 0xc7, 0x4f, 0x4b, 0x0c, 0x03, 0x00, + 0x00, 0xc7, 0x48, 0x4b, 0x0d, 0x03, 0x00, 0x00, + 0xc7, 0x59, 0x4b, 0x0e, 0x03, 0x00, 0x00, 0xc7, + 0x49, 0x4b, 0x0f, 0x03, 0x00, 0x00, 0xc7, 0x56, + 0x4b, 0x10, 0x03, 0x00, 0x00, 0xc7, 0x57, 0x4b, + 0x11, 0x03, 0x00, 0x00, 0xc7, 0x53, 0x4b, 0x12, + 0x03, 0x00, 0x00, 0xc7, 0x54, 0x4b, 0x13, 0x03, + 0x00, 0x00, 0xc7, 0x4a, 0x4b, 0x14, 0x03, 0x00, + 0x00, 0xc7, 0x4b, 0x4b, 0x15, 0x03, 0x00, 0x00, + 0xc7, 0x49, 0x4b, 0x16, 0x03, 0x00, 0x00, 0xc7, + 0x48, 0x4b, 0x17, 0x03, 0x00, 0x00, 0xc7, 0x64, + 0x4b, 0x18, 0x03, 0x00, 0x00, 0xc7, 0x4f, 0x4b, + 0x19, 0x03, 0x00, 0x00, 0xc7, 0x63, 0x4b, 0x1a, + 0x03, 0x00, 0x00, 0xc7, 0x4e, 0x4b, 0x1b, 0x03, + 0x00, 0x00, 0xc7, 0x62, 0x4b, 0x1c, 0x03, 0x00, + 0x00, 0xc7, 0x5f, 0x4b, 0x1d, 0x03, 0x00, 0x00, + 0xc7, 0x5d, 0x4b, 0x1e, 0x03, 0x00, 0x00, 0xc7, + 0x5e, 0x4b, 0x1f, 0x03, 0x00, 0x00, 0xc7, 0x5b, + 0x4b, 0x20, 0x03, 0x00, 0x00, 0xc8, 0x6d, 0x0b, + 0xc9, 0x78, 0xc5, 0x3f, 0x42, 0x56, 0x02, 0x00, + 0x00, 0xcb, 0x41, 0x68, 0x00, 0x00, 0x00, 0x0b, + 0xc7, 0x7b, 0x4b, 0x68, 0x01, 0x00, 0x00, 0xc7, + 0x7c, 0x4b, 0x69, 0x01, 0x00, 0x00, 0xc5, 0x46, + 0x4c, 0x21, 0x03, 0x00, 0x00, 0x4b, 0x21, 0x03, + 0x00, 0x00, 0xc5, 0x47, 0x4c, 0x22, 0x03, 0x00, + 0x00, 0x4b, 0x22, 0x03, 0x00, 0x00, 0xc5, 0x48, + 0x4c, 0x23, 0x03, 0x00, 0x00, 0x4b, 0x23, 0x03, + 0x00, 0x00, 0xc5, 0x49, 0x4c, 0x24, 0x03, 0x00, + 0x00, 0x4b, 0x24, 0x03, 0x00, 0x00, 0xc5, 0x4a, + 0x4c, 0x55, 0x02, 0x00, 0x00, 0x4b, 0x55, 0x02, + 0x00, 0x00, 0xc5, 0x4b, 0x4c, 0x25, 0x03, 0x00, + 0x00, 0x4b, 0x25, 0x03, 0x00, 0x00, 0xc5, 0x4c, + 0x4c, 0x3e, 0x02, 0x00, 0x00, 0x4b, 0x3e, 0x02, + 0x00, 0x00, 0xc5, 0x4d, 0x4c, 0x6d, 0x02, 0x00, + 0x00, 0x4b, 0x6d, 0x02, 0x00, 0x00, 0xc5, 0x4e, + 0x4c, 0x70, 0x02, 0x00, 0x00, 0x4b, 0x70, 0x02, + 0x00, 0x00, 0xc5, 0x4f, 0x4c, 0xb0, 0x01, 0x00, + 0x00, 0x4b, 0xb0, 0x01, 0x00, 0x00, 0xc5, 0x50, + 0x4c, 0x26, 0x03, 0x00, 0x00, 0x4b, 0x26, 0x03, + 0x00, 0x00, 0x07, 0x24, 0x02, 0x00, 0xc8, 0x7f, + 0xc7, 0x8c, 0xf4, 0x0e, 0xc7, 0x8b, 0xf4, 0x0e, + 0xc7, 0x35, 0xf4, 0x0e, 0xc7, 0x80, 0xf4, 0x29, + 0x08, 0xf0, 0x02, 0x29, 0xc5, 0x00, 0x38, 0x95, + 0x00, 0x00, 0x00, 0xf5, 0x0e, 0x06, 0x2f, }; diff --git a/deps/quickjs/gen/standalone.c b/deps/quickjs/gen/standalone.c index 2a10690..97b0007 100644 --- a/deps/quickjs/gen/standalone.c +++ b/deps/quickjs/gen/standalone.c @@ -5,7 +5,7 @@ const uint32_t qjsc_standalone_size = 2512; const uint8_t qjsc_standalone[2512] = { - 0x1a, 0x64, 0x80, 0xb9, 0x26, 0x4c, 0x01, 0x1a, + 0x1b, 0x64, 0x80, 0xb9, 0x26, 0x4c, 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, diff --git a/deps/quickjs/gen/test_fib.c b/deps/quickjs/gen/test_fib.c index 4959e2b..5063e72 100644 --- a/deps/quickjs/gen/test_fib.c +++ b/deps/quickjs/gen/test_fib.c @@ -2,10 +2,10 @@ #include "quickjs-libc.h" -const uint32_t qjsc_test_fib_size = 300; +const uint32_t qjsc_test_fib_size = 302; -const uint8_t qjsc_test_fib[300] = { - 0x1a, 0x68, 0x46, 0x85, 0x68, 0x0e, 0x01, 0x28, +const uint8_t qjsc_test_fib[302] = { + 0x1b, 0xf0, 0xec, 0x8a, 0x13, 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, @@ -40,9 +40,9 @@ const uint8_t qjsc_test_fib[300] = { 0x00, 0x00, 0x41, 0xfd, 0x00, 0x00, 0x00, 0x04, 0xff, 0x00, 0x00, 0x00, 0x64, 0x02, 0x00, 0xc2, 0x0a, 0xf5, 0x24, 0x02, 0x00, 0x0e, 0x06, 0x2f, - 0xe4, 0x03, 0x01, 0x01, 0x0e, 0x41, 0x3c, 0x00, - 0x3a, 0x06, 0x3b, 0x34, 0x10, 0x30, 0x0f, 0x34, - 0x10, 0x2a, 0x20, 0x00, + 0xe4, 0x03, 0x01, 0x01, 0x10, 0x19, 0x1c, 0x2a, + 0x20, 0xa8, 0x10, 0x81, 0x4b, 0x34, 0x10, 0x30, + 0x0f, 0x34, 0x10, 0x1b, 0x20, 0x00, }; static JSContext *JS_NewCustomContext(JSRuntime *rt) diff --git a/deps/quickjs/libregexp-opcode.h b/deps/quickjs/libregexp-opcode.h index 5c1714a..b3d7b6f 100644 --- a/deps/quickjs/libregexp-opcode.h +++ b/deps/quickjs/libregexp-opcode.h @@ -25,34 +25,49 @@ #ifdef DEF DEF(invalid, 1) /* never used */ -DEF(char8, 2) /* 7 bits in fact */ -DEF(char16, 3) +DEF(char, 3) +DEF(char_i, 3) DEF(char32, 5) +DEF(char32_i, 5) DEF(dot, 1) DEF(any, 1) /* same as dot but match any character including line terminator */ +DEF(space, 1) +DEF(not_space, 1) /* must come after */ DEF(line_start, 1) +DEF(line_start_m, 1) DEF(line_end, 1) +DEF(line_end_m, 1) DEF(goto, 5) DEF(split_goto_first, 5) DEF(split_next_first, 5) DEF(match, 1) +DEF(lookahead_match, 1) +DEF(negative_lookahead_match, 1) /* must come after */ 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(loop, 6) /* decrement the top the stack and goto if != 0 */ +DEF(loop_split_goto_first, 10) /* loop and then split */ +DEF(loop_split_next_first, 10) +DEF(loop_check_adv_split_goto_first, 10) /* loop and then check advance and split */ +DEF(loop_check_adv_split_next_first, 10) +DEF(set_i32, 6) /* store the immediate value to a register */ DEF(word_boundary, 1) +DEF(word_boundary_i, 1) DEF(not_word_boundary, 1) -DEF(back_reference, 2) -DEF(backward_back_reference, 2) /* must come after back_reference */ +DEF(not_word_boundary_i, 1) +DEF(back_reference, 2) /* variable length */ +DEF(back_reference_i, 2) /* must come after */ +DEF(backward_back_reference, 2) /* must come after */ +DEF(backward_back_reference_i, 2) /* must come after */ DEF(range, 3) /* variable length */ +DEF(range_i, 3) /* variable length */ DEF(range32, 3) /* variable length */ +DEF(range32_i, 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(negative_lookahead, 5) /* must come after */ +DEF(set_char_pos, 2) /* store the character position to a register */ +DEF(check_advance, 2) /* check that the register is different from the character position */ DEF(prev, 1) /* go to the previous char */ -DEF(simple_greedy_quant, 17) #endif /* DEF */ diff --git a/deps/quickjs/libregexp.c b/deps/quickjs/libregexp.c index ec558a4..1492512 100644 --- a/deps/quickjs/libregexp.c +++ b/deps/quickjs/libregexp.c @@ -30,14 +30,25 @@ #include "cutils.h" #include "libregexp.h" +#include "libunicode.h" -#if defined(__sun) -#include -#endif +/* ASCII identifier tables, used by lre_js_is_ident_first/next in libregexp.h + and by quickjs.c. */ +uint32_t const lre_id_start_table_ascii[4] = { + /* $ A-Z _ a-z */ + 0x00000000, 0x00000010, 0x87FFFFFE, 0x07FFFFFE +}; + +uint32_t const lre_id_continue_table_ascii[4] = { + /* $ 0-9 A-Z _ a-z */ + 0x00000000, 0x03FF0010, 0x87FFFFFE, 0x07FFFFFE +}; /* TODO: - + - remove REOP_char_i and REOP_range_i by precomputing the case folding. + - add specific opcodes for simple unicode property tests so that the + generated bytecode is smaller. - Add a lock step execution mode (=linear time execution guaranteed) when the regular expression is "simple" i.e. no backreference nor complicated lookahead. The opcodes are designed for this execution @@ -47,6 +58,8 @@ #if defined(TEST) #define DUMP_REOP #endif +//#define DUMP_REOP +//#define DUMP_EXEC typedef enum { #define DEF(id, size) REOP_ ## id, @@ -56,7 +69,8 @@ typedef enum { } REOPCodeEnum; #define CAPTURE_COUNT_MAX 255 -#define STACK_SIZE_MAX 255 +#define REGISTER_COUNT_MAX 255 +#define GROUP_NAME_SCOPE_MAX 255 /* must be large enough to have a negligible runtime cost and small enough to call the interrupt callback often. */ #define INTERRUPT_COUNTER_INIT 10000 @@ -67,7 +81,6 @@ typedef enum { #define TMP_BUF_SIZE 128 -// invariant: is_unicode ^ unicode_sets (or neither, but not both) typedef struct { DynBuf byte_code; const uint8_t *buf_ptr; @@ -75,9 +88,11 @@ typedef struct { const uint8_t *buf_start; int re_flags; bool is_unicode; - bool unicode_sets; + bool unicode_sets; /* if set, is_unicode is also set */ bool ignore_case; + bool multi_line; bool dotall; + uint8_t group_name_scope; int capture_count; int total_capture_count; /* -1 = not computed yet */ int has_named_captures; /* -1 = don't know, 0 = no, 1 = yes */ @@ -106,10 +121,10 @@ static const REOpCode reopcode_info[REOP_COUNT] = { #undef DEF }; -#define RE_HEADER_FLAGS 0 -#define RE_HEADER_CAPTURE_COUNT 2 -#define RE_HEADER_STACK_SIZE 3 -#define RE_HEADER_BYTECODE_LEN 4 +#define RE_HEADER_FLAGS 0 +#define RE_HEADER_CAPTURE_COUNT 2 +#define RE_HEADER_REGISTER_COUNT 3 +#define RE_HEADER_BYTECODE_LEN 4 #define RE_HEADER_LEN 8 @@ -127,6 +142,270 @@ static int dbuf_insert(DynBuf *s, int pos, int len) return 0; } +typedef struct REString { + struct REString *next; + uint32_t hash; + uint32_t len; + uint32_t buf[]; +} REString; + +typedef struct { + /* the string list is the union of 'char_range' and of the strings + in hash_table[]. The strings in hash_table[] have a length != + 1. */ + CharRange cr; + uint32_t n_strings; + uint32_t hash_size; + int hash_bits; + REString **hash_table; +} REStringList; + +static uint32_t re_string_hash(int len, const uint32_t *buf) +{ + int i; + uint32_t h; + h = 1; + for(i = 0; i < len; i++) + h = h * 263 + buf[i]; + return hash32(h); +} + +static void re_string_list_init(REParseState *s1, REStringList *s) +{ + cr_init(&s->cr, s1->opaque, lre_realloc); + s->n_strings = 0; + s->hash_size = 0; + s->hash_bits = 0; + s->hash_table = NULL; +} + +static void re_string_list_free(REStringList *s) +{ + REString *p, *p_next; + int i; + for(i = 0; i < s->hash_size; i++) { + for(p = s->hash_table[i]; p != NULL; p = p_next) { + p_next = p->next; + lre_realloc(s->cr.mem_opaque, p, 0); + } + } + lre_realloc(s->cr.mem_opaque, s->hash_table, 0); + + cr_free(&s->cr); +} + +#ifdef DUMP_REOP +static void lre_print_char(int c, bool is_range) +{ + if (c == '\'' || c == '\\' || + (is_range && (c == '-' || c == ']'))) { + printf("\\%c", c); + } else if (c >= ' ' && c <= 126) { + printf("%c", c); + } else { + printf("\\u{%04x}", c); + } +} + +static __maybe_unused void re_string_list_dump(const char *str, const REStringList *s) +{ + REString *p; + const CharRange *cr; + int i, j, k; + + printf("%s:\n", str); + printf(" ranges: ["); + cr = &s->cr; + for(i = 0; i < cr->len; i += 2) { + lre_print_char(cr->points[i], true); + if (cr->points[i] != cr->points[i + 1] - 1) { + printf("-"); + lre_print_char(cr->points[i + 1] - 1, true); + } + } + printf("]\n"); + + j = 0; + for(i = 0; i < s->hash_size; i++) { + for(p = s->hash_table[i]; p != NULL; p = p->next) { + printf(" %d/%d: '", j, s->n_strings); + for(k = 0; k < p->len; k++) { + lre_print_char(p->buf[k], false); + } + printf("'\n"); + j++; + } + } +} +#endif /* DUMP_REOP */ + +/* 'buf' is NULL if 'len' is zero: the empty string is a valid member of a + string set, e.g. /[\q{}]/v */ +static int re_string_find2(REStringList *s, int len, const uint32_t *buf, + uint32_t h0, bool add_flag) +{ + uint32_t h = 0; /* avoid warning */ + REString *p; + if (s->n_strings != 0) { + h = h0 >> (32 - s->hash_bits); + for(p = s->hash_table[h]; p != NULL; p = p->next) { + if (p->hash == h0 && p->len == len && + (len == 0 || + !memcmp(p->buf, buf, len * sizeof(buf[0])))) { + return 1; + } + } + } + /* not found */ + if (!add_flag) + return 0; + /* increase the size of the hash table if needed */ + if (unlikely((s->n_strings + 1) > s->hash_size)) { + REString **new_hash_table, *p_next; + int new_hash_bits, i; + uint32_t new_hash_size; + new_hash_bits = max_int(s->hash_bits + 1, 4); + new_hash_size = 1 << new_hash_bits; + new_hash_table = lre_realloc(s->cr.mem_opaque, NULL, + sizeof(new_hash_table[0]) * new_hash_size); + if (!new_hash_table) + return -1; + memset(new_hash_table, 0, sizeof(new_hash_table[0]) * new_hash_size); + for(i = 0; i < s->hash_size; i++) { + for(p = s->hash_table[i]; p != NULL; p = p_next) { + p_next = p->next; + h = p->hash >> (32 - new_hash_bits); + p->next = new_hash_table[h]; + new_hash_table[h] = p; + } + } + lre_realloc(s->cr.mem_opaque, s->hash_table, 0); + s->hash_bits = new_hash_bits; + s->hash_size = new_hash_size; + s->hash_table = new_hash_table; + h = h0 >> (32 - s->hash_bits); + } + + p = lre_realloc(s->cr.mem_opaque, NULL, sizeof(REString) + len * sizeof(buf[0])); + if (!p) + return -1; + p->next = s->hash_table[h]; + s->hash_table[h] = p; + s->n_strings++; + p->hash = h0; + p->len = len; + if (len != 0) + memcpy(p->buf, buf, sizeof(buf[0]) * len); + return 1; +} + +static int re_string_find(REStringList *s, int len, const uint32_t *buf, + bool add_flag) +{ + uint32_t h0; + h0 = re_string_hash(len, buf); + return re_string_find2(s, len, buf, h0, add_flag); +} + +/* return -1 if memory error, 0 if OK */ +static int re_string_add(REStringList *s, int len, const uint32_t *buf) +{ + if (len == 1) { + return cr_union_interval(&s->cr, buf[0], buf[0]); + } + if (re_string_find(s, len, buf, true) < 0) + return -1; + return 0; +} + +/* a = a op b */ +static int re_string_list_op(REStringList *a, REStringList *b, int op) +{ + int i, ret; + REString *p, **pp; + + if (cr_op1(&a->cr, b->cr.points, b->cr.len, op)) + return -1; + + switch(op) { + case CR_OP_UNION: + if (b->n_strings != 0) { + for(i = 0; i < b->hash_size; i++) { + for(p = b->hash_table[i]; p != NULL; p = p->next) { + if (re_string_find2(a, p->len, p->buf, p->hash, true) < 0) + return -1; + } + } + } + break; + case CR_OP_INTER: + case CR_OP_SUB: + for(i = 0; i < a->hash_size; i++) { + pp = &a->hash_table[i]; + for(;;) { + p = *pp; + if (p == NULL) + break; + ret = re_string_find2(b, p->len, p->buf, p->hash, false); + if (op == CR_OP_SUB) + ret = !ret; + if (!ret) { + /* remove it */ + *pp = p->next; + a->n_strings--; + lre_realloc(a->cr.mem_opaque, p, 0); + } else { + /* keep it */ + pp = &p->next; + } + } + } + break; + default: + abort(); + } + return 0; +} + +static int re_string_list_canonicalize(REParseState *s1, + REStringList *s, bool is_unicode) +{ + if (cr_regexp_canonicalize(&s->cr, is_unicode)) + return -1; + if (s->n_strings != 0) { + REStringList a_s, *a = &a_s; + int i, j; + REString *p; + + /* XXX: simplify */ + re_string_list_init(s1, a); + + a->n_strings = s->n_strings; + a->hash_size = s->hash_size; + a->hash_bits = s->hash_bits; + a->hash_table = s->hash_table; + + s->n_strings = 0; + s->hash_size = 0; + s->hash_bits = 0; + s->hash_table = NULL; + + for(i = 0; i < a->hash_size; i++) { + for(p = a->hash_table[i]; p != NULL; p = p->next) { + for(j = 0; j < p->len; j++) { + p->buf[j] = lre_canonicalize(p->buf[j], is_unicode); + } + if (re_string_add(s, p->len, p->buf)) { + re_string_list_free(a); + return -1; + } + } + } + re_string_list_free(a); + } + return 0; +} + static const uint16_t char_range_d[] = { 1, 0x0030, 0x0039 + 1, @@ -150,32 +429,6 @@ static const uint16_t char_range_s[] = { 0xFEFF, 0xFEFF + 1, }; -bool lre_is_space(int c) -{ - int i, n, low, high; - n = (countof(char_range_s) - 1) / 2; - for(i = 0; i < n; i++) { - low = char_range_s[2 * i + 1]; - if (c < low) - return false; - high = char_range_s[2 * i + 2]; - if (c < high) - return true; - } - return false; -} - -uint32_t const lre_id_start_table_ascii[4] = { - /* $ A-Z _ a-z */ - 0x00000000, 0x00000010, 0x87FFFFFE, 0x07FFFFFE -}; - -uint32_t const lre_id_continue_table_ascii[4] = { - /* $ 0-9 A-Z _ a-z */ - 0x00000000, 0x03FF0010, 0x87FFFFFE, 0x07FFFFFE -}; - - static const uint16_t char_range_w[] = { 4, 0x0030, 0x0039 + 1, @@ -195,13 +448,13 @@ typedef enum { CHAR_RANGE_W, } CharRangeEnum; -static const uint16_t *char_range_table[] = { +static const uint16_t * const char_range_table[] = { char_range_d, char_range_s, char_range_w, }; -static int cr_init_char_range(REParseState *s, CharRange *cr, uint32_t c) +static int cr_init_char_range(REParseState *s, REStringList *cr, uint32_t c) { bool invert; const uint16_t *c_pt; @@ -210,18 +463,18 @@ static int cr_init_char_range(REParseState *s, CharRange *cr, uint32_t c) invert = c & 1; c_pt = char_range_table[c >> 1]; len = *c_pt++; - cr_init(cr, s->opaque, lre_realloc); + re_string_list_init(s, cr); for(i = 0; i < len * 2; i++) { - if (cr_add_point(cr, c_pt[i])) + if (cr_add_point(&cr->cr, c_pt[i])) goto fail; } if (invert) { - if (cr_invert(cr)) + if (cr_invert(&cr->cr)) goto fail; } return 0; fail: - cr_free(cr); + re_string_list_free(cr); return -1; } @@ -230,15 +483,15 @@ static __maybe_unused void lre_dump_bytecode(const uint8_t *buf, int buf_len) { int pos, len, opcode, bc_len, re_flags, i; - uint32_t val; + uint32_t val, val2; assert(buf_len >= RE_HEADER_LEN); re_flags = lre_get_flags(buf); bc_len = get_u32(buf + RE_HEADER_BYTECODE_LEN); assert(bc_len + RE_HEADER_LEN <= buf_len); - printf("flags: 0x%x capture_count=%d stack_size=%d\n", - re_flags, buf[RE_HEADER_CAPTURE_COUNT], buf[RE_HEADER_STACK_SIZE]); + printf("flags: 0x%x capture_count=%d reg_count=%d\n", + re_flags, buf[RE_HEADER_CAPTURE_COUNT], buf[RE_HEADER_REGISTER_COUNT]); if (re_flags & LRE_FLAG_NAMED_GROUPS) { const char *p; p = (char *)buf + RE_HEADER_LEN + bc_len; @@ -247,7 +500,7 @@ static __maybe_unused void lre_dump_bytecode(const uint8_t *buf, if (i != 1) printf(","); printf("<%s>", p); - p += strlen(p) + 1; + p += strlen(p) + LRE_GROUP_NAME_TRAILER_LEN; } printf("\n"); assert(p == (char *)(buf + buf_len)); @@ -270,15 +523,17 @@ static __maybe_unused void lre_dump_bytecode(const uint8_t *buf, } printf("%s", reopcode_info[opcode].name); switch(opcode) { - case REOP_char8: - val = get_u8(buf + pos + 1); - goto printchar; - case REOP_char16: + case REOP_char: + case REOP_char_i: val = get_u16(buf + pos + 1); - goto printchar; + if (val >= ' ' && val <= 126) + printf(" '%c'", val); + else + printf(" 0x%04x", val); + break; case REOP_char32: + case REOP_char32_i: val = get_u32(buf + pos + 1); - printchar: if (val >= ' ' && val <= 126) printf(" '%c'", val); else @@ -287,34 +542,65 @@ static __maybe_unused void lre_dump_bytecode(const uint8_t *buf, case REOP_goto: case REOP_split_goto_first: case REOP_split_next_first: - case REOP_loop: case REOP_lookahead: case REOP_negative_lookahead: val = get_u32(buf + pos + 1); val += (pos + 5); printf(" %u", val); break; - case REOP_simple_greedy_quant: - printf(" %u %u %u %u", - get_u32(buf + pos + 1) + (pos + 17), - get_u32(buf + pos + 1 + 4), - get_u32(buf + pos + 1 + 8), - get_u32(buf + pos + 1 + 12)); + case REOP_loop: + val2 = buf[pos + 1]; + val = get_u32(buf + pos + 2); + val += (pos + 6); + printf(" r%u, %u", val2, val); + break; + case REOP_loop_split_goto_first: + case REOP_loop_split_next_first: + case REOP_loop_check_adv_split_goto_first: + case REOP_loop_check_adv_split_next_first: + { + uint32_t limit; + val2 = buf[pos + 1]; + limit = get_u32(buf + pos + 2); + val = get_u32(buf + pos + 6); + val += (pos + 10); + printf(" r%u, %u, %u", val2, limit, val); + } break; case REOP_save_start: case REOP_save_end: + printf(" %u", buf[pos + 1]); + break; case REOP_back_reference: + case REOP_back_reference_i: case REOP_backward_back_reference: - printf(" %u", buf[pos + 1]); + case REOP_backward_back_reference_i: + { + int n, i; + n = buf[pos + 1]; + len += n; + for(i = 0; i < n; i++) { + if (i != 0) + printf(","); + printf(" %u", buf[pos + 2 + i]); + } + } break; case REOP_save_reset: printf(" %u %u", buf[pos + 1], buf[pos + 2]); break; - case REOP_push_i32: - val = get_u32(buf + pos + 1); - printf(" %d", val); + case REOP_set_i32: + val = buf[pos + 1]; + val2 = get_u32(buf + pos + 2); + printf(" r%u, %d", val, val2); + break; + case REOP_set_char_pos: + case REOP_check_advance: + val = buf[pos + 1]; + printf(" r%u", val); break; case REOP_range: + case REOP_range_i: { int n, i; n = get_u16(buf + pos + 1); @@ -326,6 +612,7 @@ static __maybe_unused void lre_dump_bytecode(const uint8_t *buf, } break; case REOP_range32: + case REOP_range32_i: { int n, i; n = get_u16(buf + pos + 1); @@ -369,6 +656,27 @@ static int re_emit_goto(REParseState *s, int op, uint32_t val) return pos; } +static int re_emit_goto_u8(REParseState *s, int op, uint32_t arg, uint32_t val) +{ + int pos; + dbuf_putc(&s->byte_code, op); + dbuf_putc(&s->byte_code, arg); + pos = s->byte_code.size; + dbuf_put_u32(&s->byte_code, val - (pos + 4)); + return pos; +} + +static int re_emit_goto_u8_u32(REParseState *s, int op, uint32_t arg0, uint32_t arg1, uint32_t val) +{ + int pos; + dbuf_putc(&s->byte_code, op); + dbuf_putc(&s->byte_code, arg0); + dbuf_put_u32(&s->byte_code, arg1); + pos = s->byte_code.size; + dbuf_put_u32(&s->byte_code, val - (pos + 4)); + return pos; +} + static void re_emit_op_u8(REParseState *s, int op, uint32_t val) { dbuf_putc(&s->byte_code, op); @@ -381,7 +689,7 @@ static void re_emit_op_u16(REParseState *s, int op, uint32_t val) dbuf_put_u16(&s->byte_code, val); } -static int JS_PRINTF_FORMAT_ATTR(2, 3) re_parse_error(REParseState *s, const char *fmt, ...) +static int JS_PRINTF_FORMAT_ATTR(2, 3) re_parse_error(REParseState *s, JS_PRINTF_FORMAT const char *fmt, ...) { va_list ap; va_start(ap, fmt); @@ -395,13 +703,6 @@ static int re_parse_out_of_memory(REParseState *s) return re_parse_error(s, "out of memory"); } -static int lre_check_size(REParseState *s) -{ - if (s->byte_code.size < 64*1024*1024) - return 0; - return re_parse_out_of_memory(s); -} - /* If allow_overflow is false, return -1 in case of overflow. Otherwise return INT32_MAX. */ static int parse_digits(const uint8_t **pp, bool allow_overflow) @@ -477,9 +778,21 @@ int lre_parse_escape(const uint8_t **pp, int allow_utf16) c = '\v'; break; case 'x': + { + int h0, h1; + + h0 = from_hex(*p++); + if (h0 < 0) + return -1; + h1 = from_hex(*p++); + if (h1 < 0) + return -1; + c = (h0 << 4) | h1; + } + break; case 'u': { - int h, n, i; + int h, i; uint32_t c1; if (*p == '{' && allow_utf16) { @@ -497,14 +810,8 @@ int lre_parse_escape(const uint8_t **pp, int allow_utf16) } p++; } else { - if (c == 'x') { - n = 2; - } else { - n = 4; - } - c = 0; - for(i = 0; i < n; i++) { + for(i = 0; i < 4; i++) { h = from_hex(*p++); if (h < 0) { return -1; @@ -570,8 +877,16 @@ static bool is_unicode_char(int c) (c == '_')); } -static int parse_unicode_property(REParseState *s, CharRange *cr, - const uint8_t **pp, bool is_inv) +/* XXX: memory error test */ +static void seq_prop_cb(void *opaque, const uint32_t *seq, int seq_len) +{ + REStringList *sl = opaque; + re_string_add(sl, seq_len, seq); +} + +static int parse_unicode_property(REParseState *s, REStringList *cr, + const uint8_t **pp, bool is_inv, + bool allow_sequence_prop) { const uint8_t *p; char name[64], value[64]; @@ -611,51 +926,76 @@ static int parse_unicode_property(REParseState *s, CharRange *cr, } else if (!strcmp(name, "Script_Extensions") || !strcmp(name, "scx")) { script_ext = true; do_script: - cr_init(cr, s->opaque, lre_realloc); - ret = unicode_script(cr, value, script_ext); + re_string_list_init(s, cr); + ret = unicode_script(&cr->cr, value, script_ext); if (ret) { - cr_free(cr); + re_string_list_free(cr); if (ret == -2) return re_parse_error(s, "unknown unicode script"); else goto out_of_memory; } } else if (!strcmp(name, "General_Category") || !strcmp(name, "gc")) { - cr_init(cr, s->opaque, lre_realloc); - ret = unicode_general_category(cr, value); + re_string_list_init(s, cr); + ret = unicode_general_category(&cr->cr, value); if (ret) { - cr_free(cr); + re_string_list_free(cr); if (ret == -2) return re_parse_error(s, "unknown unicode general category"); else goto out_of_memory; } } else if (value[0] == '\0') { - cr_init(cr, s->opaque, lre_realloc); - ret = unicode_general_category(cr, name); + re_string_list_init(s, cr); + ret = unicode_general_category(&cr->cr, name); if (ret == -1) { - cr_free(cr); + re_string_list_free(cr); goto out_of_memory; } if (ret < 0) { - ret = unicode_prop(cr, name); - if (ret) { - cr_free(cr); - if (ret == -2) - goto unknown_property_name; - else - goto out_of_memory; + ret = unicode_prop(&cr->cr, name); + if (ret == -1) { + re_string_list_free(cr); + goto out_of_memory; } } + if (ret < 0 && !is_inv && allow_sequence_prop) { + CharRange cr_tmp; + cr_init(&cr_tmp, s->opaque, lre_realloc); + ret = unicode_sequence_prop(name, seq_prop_cb, cr, &cr_tmp); + cr_free(&cr_tmp); + if (ret == -1) { + re_string_list_free(cr); + goto out_of_memory; + } + } + if (ret < 0) + goto unknown_property_name; } else { unknown_property_name: return re_parse_error(s, "unknown unicode property name"); } + /* the ordering of case folding and inversion differs with + unicode_sets. 'unicode_sets' ordering is more consistent */ + /* XXX: the spec seems incorrect, we do it as the other engines + seem to do it. */ + if (s->ignore_case && s->unicode_sets) { + if (re_string_list_canonicalize(s, cr, s->is_unicode)) { + re_string_list_free(cr); + goto out_of_memory; + } + } if (is_inv) { - if (cr_invert(cr)) { - cr_free(cr); - return -1; + if (cr_invert(&cr->cr)) { + re_string_list_free(cr); + goto out_of_memory; + } + } + if (s->ignore_case && !s->unicode_sets) { + if (re_string_list_canonicalize(s, cr, s->is_unicode)) { + re_string_list_free(cr); + goto out_of_memory; } } *pp = p; @@ -664,13 +1004,64 @@ static int parse_unicode_property(REParseState *s, CharRange *cr, return re_parse_out_of_memory(s); } +static int get_class_atom(REParseState *s, REStringList *cr, + const uint8_t **pp, bool inclass); + +static int parse_class_string_disjunction(REParseState *s, REStringList *cr, + const uint8_t **pp) +{ + const uint8_t *p; + DynBuf str; + int c; + + p = *pp; + if (*p != '{') + return re_parse_error(s, "expecting '{' after \\q"); + + dbuf_init2(&str, s->opaque, lre_realloc); + re_string_list_init(s, cr); + + p++; + for(;;) { + str.size = 0; + while (*p != '}' && *p != '|') { + c = get_class_atom(s, NULL, &p, false); + if (c < 0) + goto fail; + if (dbuf_put_u32(&str, c)) { + re_parse_out_of_memory(s); + goto fail; + } + } + if (re_string_add(cr, str.size / 4, (uint32_t *)str.buf)) { + re_parse_out_of_memory(s); + goto fail; + } + if (*p == '}') + break; + p++; + } + if (s->ignore_case) { + if (re_string_list_canonicalize(s, cr, true)) + goto fail; + } + p++; /* skip the '}' */ + dbuf_free(&str); + *pp = p; + return 0; + fail: + dbuf_free(&str); + re_string_list_free(cr); + return -1; +} + /* return -1 if error otherwise the character or a class range - (CLASS_RANGE_BASE). In case of class range, 'cr' is + (CLASS_RANGE_BASE) if cr != NULL. In case of class range, 'cr' is initialized. Otherwise, it is ignored. */ -static int get_class_atom(REParseState *s, CharRange *cr, +static int get_class_atom(REParseState *s, REStringList *cr, const uint8_t **pp, bool inclass) { - const uint8_t *p, *p_next; + const uint8_t *p; uint32_t c; int ret; @@ -702,9 +1093,11 @@ static int get_class_atom(REParseState *s, CharRange *cr, case 'W': c = CHAR_RANGE_W; class_range: + if (!cr) + goto default_escape; if (cr_init_char_range(s, cr, c)) return -1; - c = CLASS_RANGE_BASE; + c += CLASS_RANGE_BASE; break; case 'c': c = *p; @@ -722,28 +1115,52 @@ static int get_class_atom(REParseState *s, CharRange *cr, c = '\\'; } break; + case '-': + if (!inclass && s->is_unicode) + goto invalid_escape; + break; + case '^': + case '$': + case '\\': + case '.': + case '*': + case '+': + case '?': + case '(': + case ')': + case '[': + case ']': + case '{': + case '}': + case '|': + case '/': + /* always valid to escape these characters */ + break; case 'p': case 'P': - if (s->is_unicode) { - if (parse_unicode_property(s, cr, &p, (c == 'P'))) + if (s->is_unicode && cr) { + if (parse_unicode_property(s, cr, &p, (c == 'P'), s->unicode_sets)) + return -1; + c = CLASS_RANGE_BASE; + break; + } + goto default_escape; + case 'q': + if (s->unicode_sets && cr && inclass) { + if (parse_class_string_disjunction(s, cr, &p)) return -1; c = CLASS_RANGE_BASE; break; } - /* fall thru */ + goto default_escape; default: + default_escape: p--; ret = lre_parse_escape(&p, s->is_unicode * 2); if (ret >= 0) { c = ret; } else { - if (ret == -2 && *p != '\0' && strchr("^$\\.*+?()[]{}|/", *p)) { - /* always valid to escape these characters */ - goto normal_char; - } else if (s->is_unicode) { - // special case: allowed inside [] but not outside - if (ret == -2 && *p == '-' && inclass) - goto normal_char; + if (s->is_unicode) { invalid_escape: return re_parse_error(s, "invalid escape sequence in regular expression"); } else { @@ -760,20 +1177,59 @@ static int get_class_atom(REParseState *s, CharRange *cr, return re_parse_error(s, "unexpected end"); } /* fall thru */ + goto normal_char; + + case '&': + case '!': + case '#': + case '$': + case '%': + case '*': + case '+': + case ',': + case '.': + case ':': + case ';': + case '<': + case '=': + case '>': + case '?': + case '@': + case '^': + case '`': + case '~': + if (s->unicode_sets && p[1] == c) { + /* forbidden double characters */ + return re_parse_error(s, "invalid class set operation in regular expression"); + } + goto normal_char; + + case '(': + case ')': + case '[': + case ']': + case '{': + case '}': + case '/': + case '-': + case '|': + if (s->unicode_sets) { + /* invalid characters in unicode sets */ + return re_parse_error(s, "invalid character in class in regular expression"); + } + goto normal_char; + default: normal_char: - p++; - if (c >= 0x80) { - c = utf8_decode(p - 1, &p_next); - if (p_next == p) - return re_parse_error(s, "invalid UTF-8 sequence"); - p = p_next; - if (c > 0xFFFF && !s->is_unicode) { - // TODO(chqrlie): should handle non BMP-1 code points in - // the calling function and no require the source string - // to be CESU-8 encoded if not s->is_unicode + /* normal char */ + if (c >= 128) { + c = utf8_decode_len(p, UTF8_CHAR_LEN_MAX, &p); + if ((unsigned)c > 0xffff && !s->is_unicode) { + /* XXX: should handle non BMP-1 code points */ return re_parse_error(s, "malformed unicode char"); } + } else { + p++; } break; } @@ -790,8 +1246,6 @@ static int re_emit_range(REParseState *s, const CharRange *cr) if (len >= 65535) return re_parse_error(s, "too many ranges"); if (len == 0) { - /* not sure it can really happen. Emit a match that is always - false */ re_emit_op_u32(s, REOP_char32, -1); } else { high = cr->points[cr->len - 1]; @@ -800,7 +1254,7 @@ static int re_emit_range(REParseState *s, const CharRange *cr) if (high <= 0xffff) { /* can use 16 bit ranges with the conversion that 0xffff = infinity */ - re_emit_op_u16(s, REOP_range, len); + re_emit_op_u16(s, s->ignore_case ? REOP_range_i : REOP_range, len); for(i = 0; i < cr->len; i += 2) { dbuf_put_u16(&s->byte_code, cr->points[i]); high = cr->points[i + 1] - 1; @@ -809,7 +1263,7 @@ static int re_emit_range(REParseState *s, const CharRange *cr) dbuf_put_u16(&s->byte_code, high); } } else { - re_emit_op_u16(s, REOP_range32, len); + re_emit_op_u16(s, s->ignore_case ? REOP_range32_i : REOP_range32, len); for(i = 0; i < cr->len; i += 2) { dbuf_put_u32(&s->byte_code, cr->points[i]); dbuf_put_u32(&s->byte_code, cr->points[i + 1] - 1); @@ -819,254 +1273,419 @@ static int re_emit_range(REParseState *s, const CharRange *cr) return 0; } -// s->unicode turns patterns like []] into syntax errors -// s->unicode_sets turns more patterns into errors, like [a-] or [[] -static int re_parse_char_class(REParseState *s, const uint8_t **pp) +static int re_string_cmp_len(const void *a, const void *b, void *arg) +{ + REString *p1 = *(REString **)a; + REString *p2 = *(REString **)b; + return (p1->len < p2->len) - (p1->len > p2->len); +} + +static void re_emit_char(REParseState *s, int c) +{ + if (c <= 0xffff) + re_emit_op_u16(s, s->ignore_case ? REOP_char_i : REOP_char, c); + else + re_emit_op_u32(s, s->ignore_case ? REOP_char32_i : REOP_char32, c); +} + +static int re_emit_string_list(REParseState *s, const REStringList *sl) +{ + REString **tab, *p; + int i, j, split_pos, last_match_pos, n; + bool has_empty_string, is_last; + + // re_string_list_dump("sl", sl); + if (sl->n_strings == 0) { + /* simple case: only characters */ + if (re_emit_range(s, &sl->cr)) + return -1; + } else { + /* at least one string list is present : match the longest ones first */ + /* XXX: add a new op_switch opcode to compile as a trie */ + tab = lre_realloc(s->opaque, NULL, sizeof(tab[0]) * sl->n_strings); + if (!tab) { + re_parse_out_of_memory(s); + return -1; + } + has_empty_string = false; + n = 0; + for(i = 0; i < sl->hash_size; i++) { + for(p = sl->hash_table[i]; p != NULL; p = p->next) { + if (p->len == 0) { + has_empty_string = true; + } else { + tab[n++] = p; + } + } + } + assert(n <= sl->n_strings); + + rqsort(tab, n, sizeof(tab[0]), re_string_cmp_len, NULL); + + last_match_pos = -1; + for(i = 0; i < n; i++) { + p = tab[i]; + is_last = !has_empty_string && sl->cr.len == 0 && i == (n - 1); + if (!is_last) + split_pos = re_emit_op_u32(s, REOP_split_next_first, 0); + else + split_pos = 0; + for(j = 0; j < p->len; j++) { + re_emit_char(s, p->buf[j]); + } + if (!is_last) { + last_match_pos = re_emit_op_u32(s, REOP_goto, last_match_pos); + /* the positions to patch are only valid if all the byte code + could be emitted */ + if (dbuf_error(&s->byte_code)) + goto out_of_memory; + put_u32(s->byte_code.buf + split_pos, s->byte_code.size - (split_pos + 4)); + } + } + + if (sl->cr.len != 0) { + /* char range */ + is_last = !has_empty_string; + if (!is_last) + split_pos = re_emit_op_u32(s, REOP_split_next_first, 0); + else + split_pos = 0; /* not used */ + if (re_emit_range(s, &sl->cr)) + goto fail; + if (!is_last) { + if (dbuf_error(&s->byte_code)) + goto out_of_memory; + put_u32(s->byte_code.buf + split_pos, s->byte_code.size - (split_pos + 4)); + } + } + + /* patch the 'goto match' */ + if (dbuf_error(&s->byte_code)) + goto out_of_memory; + while (last_match_pos != -1) { + int next_pos = get_u32(s->byte_code.buf + last_match_pos); + put_u32(s->byte_code.buf + last_match_pos, s->byte_code.size - (last_match_pos + 4)); + last_match_pos = next_pos; + } + + lre_realloc(s->opaque, tab, 0); + } + return 0; + out_of_memory: + re_parse_out_of_memory(s); + fail: + lre_realloc(s->opaque, tab, 0); + return -1; +} + +static int re_parse_nested_class(REParseState *s, REStringList *cr, const uint8_t **pp); + +static int re_parse_class_set_operand(REParseState *s, REStringList *cr, const uint8_t **pp) +{ + int c1; + const uint8_t *p = *pp; + + if (*p == '[') { + if (re_parse_nested_class(s, cr, pp)) + return -1; + } else { + c1 = get_class_atom(s, cr, pp, true); + if (c1 < 0) + return -1; + if (c1 < CLASS_RANGE_BASE) { + /* create a range with a single character */ + re_string_list_init(s, cr); + if (s->ignore_case) + c1 = lre_canonicalize(c1, s->is_unicode); + if (cr_union_interval(&cr->cr, c1, c1)) { + re_string_list_free(cr); + return -1; + } + } + } + return 0; +} + +static int re_parse_nested_class(REParseState *s, REStringList *cr, const uint8_t **pp) { const uint8_t *p; uint32_t c1, c2; - CharRange cr_s, *cr = &cr_s; - CharRange cr1_s, *cr1 = &cr1_s; - bool invert; + int ret; + REStringList cr1_s, *cr1 = &cr1_s; + bool invert, is_first; - cr_init(cr, s->opaque, lre_realloc); + if (lre_check_stack_overflow(s->opaque, 0)) + return re_parse_error(s, "stack overflow"); + + re_string_list_init(s, cr); p = *pp; p++; /* skip '[' */ - if (s->unicode_sets) { - static const char verboten[] = - "()[{}/-|" "\0" - "&&!!##$$%%**++,,..::;;<<==>>??@@``~~" "\0" - "^^^_^^"; - const char *s = verboten; - int n = 1; - do { - // not memcmp because some implementations compare word instead - // of byte at a time and will happily read past end of input - if (!strncmp(s, (const char *)p, n)) - if (p[n] == ']') - goto invalid_class_range; - s += n; - if (!*s) { - s++; - n++; - } - } while (n < 4); - } - invert = false; if (*p == '^') { p++; invert = true; } - + + /* handle unions */ + is_first = true; for(;;) { if (*p == ']') break; - c1 = get_class_atom(s, cr1, &p, true); - if ((int)c1 < 0) - goto fail; - if (*p == '-' && p[1] == ']' && s->unicode_sets) { - if (c1 >= CLASS_RANGE_BASE) - cr_free(cr1); - goto invalid_class_range; - } - if (*p == '-' && p[1] != ']') { - const uint8_t *p0 = p + 1; - if (c1 >= CLASS_RANGE_BASE) { - if (s->is_unicode) { - cr_free(cr1); - goto invalid_class_range; - } - /* Annex B: match '-' character */ - goto class_atom; - } - c2 = get_class_atom(s, cr1, &p0, true); - if ((int)c2 < 0) + if (*p == '[' && s->unicode_sets) { + if (re_parse_nested_class(s, cr1, &p)) goto fail; - if (c2 >= CLASS_RANGE_BASE) { - cr_free(cr1); - if (s->is_unicode) { - goto invalid_class_range; - } - /* Annex B: match '-' character */ - goto class_atom; - } - p = p0; - if (c2 < c1) { - invalid_class_range: - re_parse_error(s, "invalid class range"); - goto fail; - } - if (cr_union_interval(cr, c1, c2)) - goto memory_error; + goto class_union; } else { - class_atom: - if (c1 >= CLASS_RANGE_BASE) { - int ret; - ret = cr_union1(cr, cr1->points, cr1->len); - cr_free(cr1); - if (ret) - goto memory_error; + c1 = get_class_atom(s, cr1, &p, true); + if ((int)c1 < 0) + goto fail; + if (*p == '-' && p[1] != ']') { + const uint8_t *p0 = p + 1; + if (p[1] == '-' && s->unicode_sets && is_first) + goto class_atom; /* first character class followed by '--' */ + if (c1 >= CLASS_RANGE_BASE) { + if (s->is_unicode) { + re_string_list_free(cr1); + goto invalid_class_range; + } + /* Annex B: match '-' character */ + goto class_atom; + } + c2 = get_class_atom(s, cr1, &p0, true); + if ((int)c2 < 0) + goto fail; + if (c2 >= CLASS_RANGE_BASE) { + re_string_list_free(cr1); + if (s->is_unicode) { + goto invalid_class_range; + } + /* Annex B: match '-' character */ + goto class_atom; + } + p = p0; + if (c2 < c1) { + invalid_class_range: + re_parse_error(s, "invalid class range"); + goto fail; + } + if (s->ignore_case) { + CharRange cr2_s, *cr2 = &cr2_s; + cr_init(cr2, s->opaque, lre_realloc); + if (cr_add_interval(cr2, c1, c2 + 1) || + cr_regexp_canonicalize(cr2, s->is_unicode) || + cr_op1(&cr->cr, cr2->points, cr2->len, CR_OP_UNION)) { + cr_free(cr2); + goto memory_error; + } + cr_free(cr2); + } else { + if (cr_union_interval(&cr->cr, c1, c2)) + goto memory_error; + } + is_first = false; /* union operation */ } else { - if (cr_union_interval(cr, c1, c1)) - goto memory_error; + class_atom: + if (c1 >= CLASS_RANGE_BASE) { + class_union: + ret = re_string_list_op(cr, cr1, CR_OP_UNION); + re_string_list_free(cr1); + if (ret) + goto memory_error; + } else { + if (s->ignore_case) + c1 = lre_canonicalize(c1, s->is_unicode); + if (cr_union_interval(&cr->cr, c1, c1)) + goto memory_error; + } } } + if (s->unicode_sets && is_first) { + if (*p == '&' && p[1] == '&' && p[2] != '&') { + /* handle '&&' */ + for(;;) { + if (*p == ']') { + break; + } else if (*p == '&' && p[1] == '&' && p[2] != '&') { + p += 2; + } else { + goto invalid_operation; + } + if (re_parse_class_set_operand(s, cr1, &p)) + goto fail; + ret = re_string_list_op(cr, cr1, CR_OP_INTER); + re_string_list_free(cr1); + if (ret) + goto memory_error; + } + } else if (*p == '-' && p[1] == '-') { + /* handle '--' */ + for(;;) { + if (*p == ']') { + break; + } else if (*p == '-' && p[1] == '-') { + p += 2; + } else { + invalid_operation: + re_parse_error(s, "invalid operation in regular expression"); + goto fail; + } + if (re_parse_class_set_operand(s, cr1, &p)) + goto fail; + ret = re_string_list_op(cr, cr1, CR_OP_SUB); + re_string_list_free(cr1); + if (ret) + goto memory_error; + } + } + } + is_first = false; } - if (s->ignore_case) { - if (cr_regexp_canonicalize(cr, s->is_unicode)) - goto memory_error; - } + + p++; /* skip ']' */ + *pp = p; if (invert) { - if (cr_invert(cr)) + /* XXX: add may_contain_string syntax check to be fully + compliant. The test here accepts more input than the + spec. */ + if (cr->n_strings != 0) { + re_parse_error(s, "negated character class with strings in regular expression debugger eval code"); + goto fail; + } + if (cr_invert(&cr->cr)) goto memory_error; } - if (re_emit_range(s, cr)) - goto fail; - cr_free(cr); - p++; /* skip ']' */ - *pp = p; return 0; memory_error: re_parse_out_of_memory(s); fail: - cr_free(cr); + re_string_list_free(cr); + return -1; +} + +static int re_parse_char_class(REParseState *s, const uint8_t **pp) +{ + REStringList cr_s, *cr = &cr_s; + + if (re_parse_nested_class(s, cr, pp)) + return -1; + if (re_emit_string_list(s, cr)) + goto fail; + re_string_list_free(cr); + return 0; + fail: + re_string_list_free(cr); return -1; } -/* Return: - - true if the opcodes may not advance the char pointer - - false if the opcodes always advance the char pointer +/* need_check_adv: false if the opcodes always advance the char pointer + need_capture_init: true if all the captures in the atom are not set */ -static bool re_need_check_advance(const uint8_t *bc_buf, int bc_buf_len) +static bool re_need_check_adv_and_capture_init(bool *pneed_capture_init, + const uint8_t *bc_buf, int bc_buf_len) { int pos, opcode, len; uint32_t val; - bool ret; + bool need_check_adv, need_capture_init; - ret = true; + need_check_adv = true; + need_capture_init = false; pos = 0; - while (pos < bc_buf_len) { opcode = bc_buf[pos]; len = reopcode_info[opcode].size; switch(opcode) { case REOP_range: + case REOP_range_i: val = get_u16(bc_buf + pos + 1); len += val * 4; - goto simple_char; + need_check_adv = false; + break; case REOP_range32: + case REOP_range32_i: val = get_u16(bc_buf + pos + 1); len += val * 8; - goto simple_char; + need_check_adv = false; + break; + case REOP_char: + case REOP_char_i: case REOP_char32: - case REOP_char16: - case REOP_char8: + case REOP_char32_i: case REOP_dot: case REOP_any: - simple_char: - ret = false; + case REOP_space: + case REOP_not_space: + need_check_adv = false; break; case REOP_line_start: + case REOP_line_start_m: case REOP_line_end: - case REOP_push_i32: - case REOP_push_char_pos: - case REOP_drop: + case REOP_line_end_m: + case REOP_set_i32: + case REOP_set_char_pos: case REOP_word_boundary: + case REOP_word_boundary_i: case REOP_not_word_boundary: + case REOP_not_word_boundary_i: case REOP_prev: /* no effect */ break; case REOP_save_start: case REOP_save_end: case REOP_save_reset: + break; case REOP_back_reference: + case REOP_back_reference_i: case REOP_backward_back_reference: + case REOP_backward_back_reference_i: + val = bc_buf[pos + 1]; + len += val; + need_capture_init = true; break; default: - /* safe behvior: we cannot predict the outcome */ - return true; + /* safe behavior: we cannot predict the outcome */ + need_capture_init = true; + goto done; } pos += len; } - return ret; -} - -/* return -1 if a simple quantifier cannot be used. Otherwise return - the number of characters in the atom. */ -static int re_is_simple_quantifier(const uint8_t *bc_buf, int bc_buf_len) -{ - int pos, opcode, len, count; - uint32_t val; - - count = 0; - pos = 0; - while (pos < bc_buf_len) { - opcode = bc_buf[pos]; - len = reopcode_info[opcode].size; - switch(opcode) { - case REOP_range: - val = get_u16(bc_buf + pos + 1); - len += val * 4; - goto simple_char; - case REOP_range32: - val = get_u16(bc_buf + pos + 1); - len += val * 8; - goto simple_char; - case REOP_char32: - case REOP_char16: - case REOP_char8: - case REOP_dot: - case REOP_any: - simple_char: - count++; - break; - case REOP_line_start: - case REOP_line_end: - case REOP_word_boundary: - case REOP_not_word_boundary: - break; - default: - return -1; - } - pos += len; - } - return count; + done: + *pneed_capture_init = need_capture_init; + return need_check_adv; } /* '*pp' is the first char after '<' */ static int re_parse_group_name(char *buf, int buf_size, const uint8_t **pp) { - const uint8_t *p, *p_next; + const uint8_t *p, *p1; uint32_t c, d; char *q; p = *pp; q = buf; for(;;) { - c = *p++; + c = *p; if (c == '\\') { + p++; if (*p != 'u') return -1; c = lre_parse_escape(&p, 2); // accept surrogate pairs - if ((int)c < 0) - return -1; } else if (c == '>') { break; - } else if (c >= 0x80) { - c = utf8_decode(p - 1, &p_next); - if (p_next == p) - return -1; - p = p_next; + } else if (c >= 128) { + c = utf8_decode_len(p, UTF8_CHAR_LEN_MAX, &p); if (is_hi_surrogate(c)) { - d = utf8_decode(p, &p_next); + d = utf8_decode_len(p, UTF8_CHAR_LEN_MAX, &p1); if (is_lo_surrogate(d)) { c = from_surrogate(c, d); - p = p_next; + p = p1; } } + } else { + p++; } + if (c > 0x10FFFF) + return -1; if (q == buf) { if (!lre_js_is_ident_first(c)) return -1; @@ -1076,7 +1695,7 @@ static int re_parse_group_name(char *buf, int buf_size, const uint8_t **pp) } if ((q - buf + UTF8_CHAR_LEN_MAX + 1) > buf_size) return -1; - if (c < 0x80) { + if (c < 128) { *q++ = c; } else { q += utf8_encode((uint8_t*)q, c); @@ -1085,21 +1704,22 @@ static int re_parse_group_name(char *buf, int buf_size, const uint8_t **pp) if (q == buf) return -1; *q = '\0'; + p++; *pp = p; return 0; } /* if capture_name = NULL: return the number of captures + 1. - Otherwise, return the capture index corresponding to capture_name - or -1 if none */ + Otherwise, return the number of matching capture groups */ static int re_parse_captures(REParseState *s, int *phas_named_captures, - const char *capture_name) + const char *capture_name, bool emit_group_index) { const uint8_t *p; - int capture_index; + int capture_index, n; char name[TMP_BUF_SIZE]; capture_index = 1; + n = 0; *phas_named_captures = 0; for (p = s->buf_start; p < s->buf_end; p++) { switch (*p) { @@ -1111,8 +1731,11 @@ static int re_parse_captures(REParseState *s, int *phas_named_captures, if (capture_name) { p += 3; if (re_parse_group_name(name, sizeof(name), &p) == 0) { - if (!strcmp(name, capture_name)) - return capture_index; + if (!strcmp(name, capture_name)) { + if (emit_group_index) + dbuf_putc(&s->byte_code, capture_index); + n++; + } } } capture_index++; @@ -1137,17 +1760,18 @@ static int re_parse_captures(REParseState *s, int *phas_named_captures, } } done: - if (capture_name) - return -1; - else + if (capture_name) { + return n; + } else { return capture_index; + } } static int re_count_captures(REParseState *s) { if (s->total_capture_count < 0) { s->total_capture_count = re_parse_captures(s, &s->has_named_captures, - NULL); + NULL, false); } return s->total_capture_count; } @@ -1159,38 +1783,104 @@ static bool re_has_named_captures(REParseState *s) return s->has_named_captures; } -static int find_group_name(REParseState *s, const char *name) +static int find_group_name(REParseState *s, const char *name, bool emit_group_index) +{ + const char *p, *buf_end; + size_t len, name_len; + int capture_index, n; + + p = (char *)s->group_names.buf; + if (!p) + return 0; + buf_end = (char *)s->group_names.buf + s->group_names.size; + name_len = strlen(name); + capture_index = 1; + n = 0; + while (p < buf_end) { + len = strlen(p); + if (len == name_len && memcmp(name, p, name_len) == 0) { + if (emit_group_index) + dbuf_putc(&s->byte_code, capture_index); + n++; + } + p += len + LRE_GROUP_NAME_TRAILER_LEN; + capture_index++; + } + return n; +} + +static bool is_duplicate_group_name(REParseState *s, const char *name, int scope) { const char *p, *buf_end; size_t len, name_len; - int capture_index; - + int scope1; + p = (char *)s->group_names.buf; - if (!p) return -1; + if (!p) + return 0; buf_end = (char *)s->group_names.buf + s->group_names.size; name_len = strlen(name); - capture_index = 1; while (p < buf_end) { len = strlen(p); - if (len == name_len && memcmp(name, p, name_len) == 0) - return capture_index; - p += len + 1; - capture_index++; + if (len == name_len && memcmp(name, p, name_len) == 0) { + scope1 = (uint8_t)p[len + 1]; + if (scope == scope1) + return true; + } + p += len + LRE_GROUP_NAME_TRAILER_LEN; } - return -1; + return false; } static int re_parse_disjunction(REParseState *s, bool is_backward_dir); +static int re_parse_modifiers(REParseState *s, const uint8_t **pp) +{ + const uint8_t *p = *pp; + int mask = 0; + int val; + + for(;;) { + if (*p == 'i') { + val = LRE_FLAG_IGNORECASE; + } else if (*p == 'm') { + val = LRE_FLAG_MULTILINE; + } else if (*p == 's') { + val = LRE_FLAG_DOTALL; + } else { + break; + } + if (mask & val) + return re_parse_error(s, "duplicate modifier: '%c'", *p); + mask |= val; + p++; + } + *pp = p; + return mask; +} + +static bool update_modifier(bool val, int add_mask, int remove_mask, + int mask) +{ + if (add_mask & mask) + val = true; + if (remove_mask & mask) + val = false; + return val; +} + static int re_parse_term(REParseState *s, bool is_backward_dir) { const uint8_t *p; int c, last_atom_start, quant_min, quant_max, last_capture_count; - bool greedy, add_zero_advance_check, is_neg, is_backward_lookahead; - CharRange cr_s, *cr = &cr_s; + bool greedy, is_neg, is_backward_lookahead; + REStringList cr_s, *cr = &cr_s; + + /* after a failed allocation the byte code is incomplete and 'buf' may + still be NULL: stop before computing positions inside it */ + if (dbuf_error(&s->byte_code)) + return re_parse_out_of_memory(s); - if (lre_check_size(s)) - return -1; last_atom_start = -1; last_capture_count = 0; p = s->buf_ptr; @@ -1198,11 +1888,11 @@ static int re_parse_term(REParseState *s, bool is_backward_dir) switch(c) { case '^': p++; - re_emit_op(s, REOP_line_start); + re_emit_op(s, s->multi_line ? REOP_line_start_m : REOP_line_start); break; case '$': p++; - re_emit_op(s, REOP_line_end); + re_emit_op(s, s->multi_line ? REOP_line_end_m : REOP_line_end); break; case '.': p++; @@ -1252,6 +1942,44 @@ static int re_parse_term(REParseState *s, bool is_backward_dir) p = s->buf_ptr; if (re_parse_expect(s, &p, ')')) return -1; + } else if (p[2] == 'i' || p[2] == 'm' || p[2] == 's' || p[2] == '-') { + bool saved_ignore_case, saved_multi_line, saved_dotall; + int add_mask, remove_mask; + p += 2; + remove_mask = 0; + add_mask = re_parse_modifiers(s, &p); + if (add_mask < 0) + return -1; + if (*p == '-') { + p++; + remove_mask = re_parse_modifiers(s, &p); + if (remove_mask < 0) + return -1; + } + if ((add_mask == 0 && remove_mask == 0) || + (add_mask & remove_mask) != 0) { + return re_parse_error(s, "invalid modifiers"); + } + if (re_parse_expect(s, &p, ':')) + return -1; + saved_ignore_case = s->ignore_case; + saved_multi_line = s->multi_line; + saved_dotall = s->dotall; + s->ignore_case = update_modifier(s->ignore_case, add_mask, remove_mask, LRE_FLAG_IGNORECASE); + s->multi_line = update_modifier(s->multi_line, add_mask, remove_mask, LRE_FLAG_MULTILINE); + s->dotall = update_modifier(s->dotall, add_mask, remove_mask, LRE_FLAG_DOTALL); + + last_atom_start = s->byte_code.size; + last_capture_count = s->capture_count; + s->buf_ptr = p; + if (re_parse_disjunction(s, is_backward_dir)) + return -1; + p = s->buf_ptr; + if (re_parse_expect(s, &p, ')')) + return -1; + s->ignore_case = saved_ignore_case; + s->multi_line = saved_multi_line; + s->dotall = saved_dotall; } else if ((p[2] == '=' || p[2] == '!')) { is_neg = (p[2] == '!'); is_backward_lookahead = false; @@ -1278,10 +2006,10 @@ static int re_parse_term(REParseState *s, bool is_backward_dir) p = s->buf_ptr; if (re_parse_expect(s, &p, ')')) return -1; - re_emit_op(s, REOP_match); + re_emit_op(s, REOP_lookahead_match + is_neg); /* jump after the 'match' after the lookahead is successful */ if (dbuf_error(&s->byte_code)) - return -1; + return re_parse_out_of_memory(s); put_u32(s->byte_code.buf + pos, s->byte_code.size - (pos + 4)); } else if (p[2] == '<') { p += 3; @@ -1289,12 +2017,16 @@ static int re_parse_term(REParseState *s, bool is_backward_dir) &p)) { return re_parse_error(s, "invalid group name"); } - if (find_group_name(s, s->u.tmp_buf) > 0) { + /* poor's man method to test duplicate group + names. */ + /* XXX: this method does not catch all the errors*/ + if (is_duplicate_group_name(s, s->u.tmp_buf, s->group_name_scope)) { return re_parse_error(s, "duplicate group name"); } /* group name with a trailing zero */ dbuf_put(&s->group_names, (uint8_t *)s->u.tmp_buf, strlen(s->u.tmp_buf) + 1); + dbuf_putc(&s->group_names, s->group_name_scope); s->has_named_captures = 1; goto parse_capture; } else { @@ -1305,6 +2037,7 @@ static int re_parse_term(REParseState *s, bool is_backward_dir) p++; /* capture without group name */ dbuf_putc(&s->group_names, 0); + dbuf_putc(&s->group_names, 0); parse_capture: if (s->capture_count >= CAPTURE_COUNT_MAX) return re_parse_error(s, "too many captures"); @@ -1330,14 +2063,19 @@ static int re_parse_term(REParseState *s, bool is_backward_dir) switch(p[1]) { case 'b': case 'B': - re_emit_op(s, REOP_word_boundary + (p[1] != 'b')); + if (p[1] != 'b') { + re_emit_op(s, s->ignore_case && s->is_unicode ? REOP_not_word_boundary_i : REOP_not_word_boundary); + } else { + re_emit_op(s, s->ignore_case && s->is_unicode ? REOP_word_boundary_i : REOP_word_boundary); + } p += 2; break; case 'k': { const uint8_t *p1; - int dummy_res; - + int dummy_res, n; + bool is_forward; + p1 = p; if (p1[2] != '<') { /* annex B: we tolerate invalid group names in non @@ -1356,21 +2094,33 @@ static int re_parse_term(REParseState *s, bool is_backward_dir) else goto parse_class_atom; } - c = find_group_name(s, s->u.tmp_buf); - if (c < 0) { + is_forward = false; + n = find_group_name(s, s->u.tmp_buf, false); + if (n == 0) { /* no capture name parsed before, try to look after (inefficient, but hopefully not common */ - c = re_parse_captures(s, &dummy_res, s->u.tmp_buf); - if (c < 0) { + n = re_parse_captures(s, &dummy_res, s->u.tmp_buf, false); + if (n == 0) { if (s->is_unicode || re_has_named_captures(s)) return re_parse_error(s, "group name not defined"); else goto parse_class_atom; } + is_forward = true; + } + last_atom_start = s->byte_code.size; + last_capture_count = s->capture_count; + + /* emit back references to all the captures indexes matching the group name */ + re_emit_op_u8(s, REOP_back_reference + 2 * is_backward_dir + s->ignore_case, n); + if (is_forward) { + re_parse_captures(s, &dummy_res, s->u.tmp_buf, true); + } else { + find_group_name(s, s->u.tmp_buf, true); } p = p1; } - goto emit_back_reference; + break; case '0': p += 2; c = 0; @@ -1416,10 +2166,11 @@ static int re_parse_term(REParseState *s, bool is_backward_dir) } return re_parse_error(s, "back reference out of range in regular expression"); } - emit_back_reference: last_atom_start = s->byte_code.size; last_capture_count = s->capture_count; - re_emit_op_u8(s, REOP_back_reference + is_backward_dir, c); + + re_emit_op_u8(s, REOP_back_reference + 2 * is_backward_dir + s->ignore_case, 1); + dbuf_putc(&s->byte_code, c); } break; default: @@ -1452,21 +2203,22 @@ static int re_parse_term(REParseState *s, bool is_backward_dir) if (is_backward_dir) re_emit_op(s, REOP_prev); if (c >= CLASS_RANGE_BASE) { - int ret; - /* Note: canonicalization is not needed */ - ret = re_emit_range(s, cr); - cr_free(cr); + int ret = 0; + /* optimize the common 'space' tests */ + if (c == (CLASS_RANGE_BASE + CHAR_RANGE_s)) { + re_emit_op(s, REOP_space); + } else if (c == (CLASS_RANGE_BASE + CHAR_RANGE_S)) { + re_emit_op(s, REOP_not_space); + } else { + ret = re_emit_string_list(s, cr); + } + re_string_list_free(cr); if (ret) return -1; } else { if (s->ignore_case) c = lre_canonicalize(c, s->is_unicode); - if (c <= 0x7f) - re_emit_op_u8(s, REOP_char8, c); - else if (c <= 0xffff) - re_emit_op_u16(s, REOP_char16, c); - else - re_emit_op_u32(s, REOP_char32, c); + re_emit_char(s, c); } if (is_backward_dir) re_emit_op(s, REOP_prev); @@ -1534,52 +2286,39 @@ static int re_parse_term(REParseState *s, bool is_backward_dir) if (last_atom_start < 0) { return re_parse_error(s, "nothing to repeat"); } - if (greedy) { + { + bool need_capture_init, add_zero_advance_check; int len, pos; - - if (quant_max > 0) { - /* specific optimization for simple quantifiers */ - if (dbuf_error(&s->byte_code)) + + /* the spec tells that if there is no advance when + running the atom after the first quant_min times, + then there is no match. We remove this test when we + are sure the atom always advances the position. */ + add_zero_advance_check = + re_need_check_adv_and_capture_init(&need_capture_init, + s->byte_code.buf + last_atom_start, + s->byte_code.size - last_atom_start); + + /* general case: need to reset the capture at each + iteration. We don't do it if there are no captures + in the atom or if we are sure all captures are + initialized in the atom. If quant_min = 0, we still + need to reset once the captures in case the atom + does not match. */ + if (need_capture_init && last_capture_count != s->capture_count) { + if (dbuf_insert(&s->byte_code, last_atom_start, 3)) goto out_of_memory; - len = re_is_simple_quantifier(s->byte_code.buf + last_atom_start, - s->byte_code.size - last_atom_start); - if (len > 0) { - re_emit_op(s, REOP_match); - - if (dbuf_insert(&s->byte_code, last_atom_start, 17)) - goto out_of_memory; - pos = last_atom_start; - s->byte_code.buf[pos++] = REOP_simple_greedy_quant; - put_u32(&s->byte_code.buf[pos], - s->byte_code.size - last_atom_start - 17); - pos += 4; - put_u32(&s->byte_code.buf[pos], quant_min); - pos += 4; - put_u32(&s->byte_code.buf[pos], quant_max); - pos += 4; - put_u32(&s->byte_code.buf[pos], len); - pos += 4; - goto done; - } + int pos = last_atom_start; + s->byte_code.buf[pos++] = REOP_save_reset; + s->byte_code.buf[pos++] = last_capture_count; + s->byte_code.buf[pos++] = s->capture_count - 1; } - if (dbuf_error(&s->byte_code)) - goto out_of_memory; - } - /* the spec tells that if there is no advance when - running the atom after the first quant_min times, - then there is no match. We remove this test when we - are sure the atom always advances the position. */ - add_zero_advance_check = re_need_check_advance(s->byte_code.buf + last_atom_start, - s->byte_code.size - last_atom_start); - - { - int len, pos; len = s->byte_code.size - last_atom_start; if (quant_min == 0) { /* need to reset the capture in case the atom is not executed */ - if (last_capture_count != s->capture_count) { + if (!need_capture_init && last_capture_count != s->capture_count) { if (dbuf_insert(&s->byte_code, last_atom_start, 3)) goto out_of_memory; s->byte_code.buf[last_atom_start++] = REOP_save_reset; @@ -1590,76 +2329,63 @@ static int re_parse_term(REParseState *s, bool is_backward_dir) s->byte_code.size = last_atom_start; } else if (quant_max == 1 || quant_max == INT32_MAX) { bool has_goto = (quant_max == INT32_MAX); - if (dbuf_insert(&s->byte_code, last_atom_start, 5 + add_zero_advance_check)) + if (dbuf_insert(&s->byte_code, last_atom_start, 5 + add_zero_advance_check * 2)) goto out_of_memory; s->byte_code.buf[last_atom_start] = REOP_split_goto_first + greedy; put_u32(s->byte_code.buf + last_atom_start + 1, - len + 5 * has_goto + add_zero_advance_check * 2); + len + 5 * has_goto + add_zero_advance_check * 2 * 2); if (add_zero_advance_check) { - s->byte_code.buf[last_atom_start + 1 + 4] = REOP_push_char_pos; - re_emit_op(s, REOP_check_advance); + s->byte_code.buf[last_atom_start + 1 + 4] = REOP_set_char_pos; + s->byte_code.buf[last_atom_start + 1 + 4 + 1] = 0; + re_emit_op_u8(s, REOP_check_advance, 0); } if (has_goto) re_emit_goto(s, REOP_goto, last_atom_start); } else { - if (dbuf_insert(&s->byte_code, last_atom_start, 10 + add_zero_advance_check)) + if (dbuf_insert(&s->byte_code, last_atom_start, 11 + add_zero_advance_check * 2)) goto out_of_memory; pos = last_atom_start; - s->byte_code.buf[pos++] = REOP_push_i32; - put_u32(s->byte_code.buf + pos, quant_max); - pos += 4; s->byte_code.buf[pos++] = REOP_split_goto_first + greedy; - put_u32(s->byte_code.buf + pos, len + 5 + add_zero_advance_check * 2); + put_u32(s->byte_code.buf + pos, 6 + add_zero_advance_check * 2 + len + 10); + pos += 4; + + s->byte_code.buf[pos++] = REOP_set_i32; + s->byte_code.buf[pos++] = 0; + put_u32(s->byte_code.buf + pos, quant_max); pos += 4; + last_atom_start = pos; if (add_zero_advance_check) { - s->byte_code.buf[pos++] = REOP_push_char_pos; - re_emit_op(s, REOP_check_advance); + s->byte_code.buf[pos++] = REOP_set_char_pos; + s->byte_code.buf[pos++] = 0; } - re_emit_goto(s, REOP_loop, last_atom_start + 5); - re_emit_op(s, REOP_drop); + re_emit_goto_u8_u32(s, (add_zero_advance_check ? REOP_loop_check_adv_split_next_first : REOP_loop_split_next_first) - greedy, 0, quant_max, last_atom_start); } } else if (quant_min == 1 && quant_max == INT32_MAX && !add_zero_advance_check) { re_emit_goto(s, REOP_split_next_first - greedy, last_atom_start); } else { - if (quant_min == 1) { - /* nothing to add */ - } else { - if (dbuf_insert(&s->byte_code, last_atom_start, 5)) - goto out_of_memory; - s->byte_code.buf[last_atom_start] = REOP_push_i32; - put_u32(s->byte_code.buf + last_atom_start + 1, - quant_min); - last_atom_start += 5; - re_emit_goto(s, REOP_loop, last_atom_start); - re_emit_op(s, REOP_drop); + if (quant_min == quant_max) + add_zero_advance_check = false; + if (dbuf_insert(&s->byte_code, last_atom_start, 6 + add_zero_advance_check * 2)) + goto out_of_memory; + /* Note: we assume the string length is < INT32_MAX */ + pos = last_atom_start; + s->byte_code.buf[pos++] = REOP_set_i32; + s->byte_code.buf[pos++] = 0; + put_u32(s->byte_code.buf + pos, quant_max); + pos += 4; + last_atom_start = pos; + if (add_zero_advance_check) { + s->byte_code.buf[pos++] = REOP_set_char_pos; + s->byte_code.buf[pos++] = 0; } - if (quant_max == INT32_MAX) { - pos = s->byte_code.size; - re_emit_op_u32(s, REOP_split_goto_first + greedy, - len + 5 + add_zero_advance_check * 2); - if (add_zero_advance_check) - re_emit_op(s, REOP_push_char_pos); - /* copy the atom */ - dbuf_put_self(&s->byte_code, last_atom_start, len); - if (add_zero_advance_check) - re_emit_op(s, REOP_check_advance); - re_emit_goto(s, REOP_goto, pos); - } else if (quant_max > quant_min) { - re_emit_op_u32(s, REOP_push_i32, quant_max - quant_min); - pos = s->byte_code.size; - re_emit_op_u32(s, REOP_split_goto_first + greedy, - len + 5 + add_zero_advance_check * 2); - if (add_zero_advance_check) - re_emit_op(s, REOP_push_char_pos); - /* copy the atom */ - dbuf_put_self(&s->byte_code, last_atom_start, len); - if (add_zero_advance_check) - re_emit_op(s, REOP_check_advance); - re_emit_goto(s, REOP_loop, pos); - re_emit_op(s, REOP_drop); + if (quant_min == quant_max) { + /* a simple loop is enough */ + re_emit_goto_u8(s, REOP_loop, 0, last_atom_start); + } else { + re_emit_goto_u8_u32(s, (add_zero_advance_check ? REOP_loop_check_adv_split_next_first : REOP_loop_split_next_first) - greedy, 0, quant_max - quant_min, last_atom_start); } } last_atom_start = -1; @@ -1669,7 +2395,6 @@ static int re_parse_term(REParseState *s, bool is_backward_dir) break; } } - done: s->buf_ptr = p; return 0; out_of_memory: @@ -1682,8 +2407,6 @@ static int re_parse_alternative(REParseState *s, bool is_backward_dir) int ret; size_t start, term_start, end, term_size; - if (lre_check_size(s)) - return -1; start = s->byte_code.size; for(;;) { p = s->buf_ptr; @@ -1701,7 +2424,7 @@ static int re_parse_alternative(REParseState *s, bool is_backward_dir) end = s->byte_code.size; term_size = end - term_start; if (dbuf_claim(&s->byte_code, term_size)) - return -1; + return re_parse_out_of_memory(s); memmove(s->byte_code.buf + start + term_size, s->byte_code.buf + start, end - start); @@ -1718,8 +2441,7 @@ static int re_parse_disjunction(REParseState *s, bool is_backward_dir) if (lre_check_stack_overflow(s->opaque, 0)) return re_parse_error(s, "stack overflow"); - if (lre_check_size(s)) - return -1; + start = s->byte_code.size; if (re_parse_alternative(s, is_backward_dir)) return -1; @@ -1737,18 +2459,27 @@ static int re_parse_disjunction(REParseState *s, bool is_backward_dir) pos = re_emit_op_u32(s, REOP_goto, 0); + if (re_has_named_captures(s) && s->group_name_scope == GROUP_NAME_SCOPE_MAX) + return re_parse_error(s, "too many named groups"); + + s->group_name_scope++; + if (re_parse_alternative(s, is_backward_dir)) return -1; - /* patch the goto */ + /* patch the goto ('pos' is only valid if the placeholder for the + offset could be emitted) */ + if (dbuf_error(&s->byte_code)) + return re_parse_out_of_memory(s); len = s->byte_code.size - (pos + 4); put_u32(s->byte_code.buf + pos, len); } return 0; } -/* the control flow is recursive so the analysis can be linear */ -static int lre_compute_stack_size(const uint8_t *bc_buf, int bc_buf_len) +/* Allocate the registers as a stack. The control flow is recursive so + the analysis can be linear. */ +static int compute_register_count(uint8_t *bc_buf, int bc_buf_len) { int stack_size, stack_size_max, pos, opcode, len; uint32_t val; @@ -1764,34 +2495,64 @@ static int lre_compute_stack_size(const uint8_t *bc_buf, int bc_buf_len) assert(opcode < REOP_COUNT); assert((pos + len) <= bc_buf_len); switch(opcode) { - case REOP_push_i32: - case REOP_push_char_pos: + case REOP_set_i32: + case REOP_set_char_pos: + bc_buf[pos + 1] = stack_size; stack_size++; if (stack_size > stack_size_max) { - if (stack_size > STACK_SIZE_MAX) + if (stack_size > REGISTER_COUNT_MAX) return -1; stack_size_max = stack_size; } break; - case REOP_drop: case REOP_check_advance: + case REOP_loop: + case REOP_loop_split_goto_first: + case REOP_loop_split_next_first: assert(stack_size > 0); stack_size--; + bc_buf[pos + 1] = stack_size; + break; + case REOP_loop_check_adv_split_goto_first: + case REOP_loop_check_adv_split_next_first: + assert(stack_size >= 2); + stack_size -= 2; + bc_buf[pos + 1] = stack_size; break; case REOP_range: + case REOP_range_i: val = get_u16(bc_buf + pos + 1); len += val * 4; break; case REOP_range32: + case REOP_range32_i: val = get_u16(bc_buf + pos + 1); len += val * 8; break; + case REOP_back_reference: + case REOP_back_reference_i: + case REOP_backward_back_reference: + case REOP_backward_back_reference_i: + val = bc_buf[pos + 1]; + len += val; + break; } pos += len; } return stack_size_max; } +static void *lre_bytecode_realloc(void *opaque, void *ptr, size_t size) +{ + if (size > (INT32_MAX / 2)) { + /* the bytecode cannot be larger than 2G. Leave some slack to + avoid some overflows. */ + return NULL; + } else { + return lre_realloc(opaque, ptr, size); + } +} + /* 'buf' must be a zero terminated UTF-8 string of length buf_len. Return NULL if error and allocate an error message in *perror_msg, otherwise the compiled bytecode and its length in plen. @@ -1801,7 +2562,7 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size, void *opaque) { REParseState s_s, *s = &s_s; - int stack_size; + int register_count; bool is_sticky; memset(s, 0, sizeof(*s)); @@ -1810,16 +2571,17 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size, s->buf_end = s->buf_ptr + buf_len; s->buf_start = s->buf_ptr; s->re_flags = re_flags; - s->is_unicode = ((re_flags & LRE_FLAG_UNICODE) != 0); + s->is_unicode = ((re_flags & (LRE_FLAG_UNICODE | LRE_FLAG_UNICODE_SETS)) != 0); is_sticky = ((re_flags & LRE_FLAG_STICKY) != 0); s->ignore_case = ((re_flags & LRE_FLAG_IGNORECASE) != 0); + s->multi_line = ((re_flags & LRE_FLAG_MULTILINE) != 0); s->dotall = ((re_flags & LRE_FLAG_DOTALL) != 0); s->unicode_sets = ((re_flags & LRE_FLAG_UNICODE_SETS) != 0); s->capture_count = 1; s->total_capture_count = -1; s->has_named_captures = -1; - dbuf_init2(&s->byte_code, opaque, lre_realloc); + dbuf_init2(&s->byte_code, opaque, lre_bytecode_realloc); dbuf_init2(&s->group_names, opaque, lre_realloc); dbuf_put_u16(&s->byte_code, re_flags); /* first element is the flags */ @@ -1861,22 +2623,25 @@ uint8_t *lre_compile(int *plen, char *error_msg, int error_msg_size, goto error; } - stack_size = lre_compute_stack_size(s->byte_code.buf, s->byte_code.size); - if (stack_size < 0) { + register_count = compute_register_count(s->byte_code.buf, s->byte_code.size); + if (register_count < 0) { re_parse_error(s, "too many imbricated quantifiers"); goto error; } s->byte_code.buf[RE_HEADER_CAPTURE_COUNT] = s->capture_count; - s->byte_code.buf[RE_HEADER_STACK_SIZE] = stack_size; + s->byte_code.buf[RE_HEADER_REGISTER_COUNT] = register_count; put_u32(s->byte_code.buf + RE_HEADER_BYTECODE_LEN, s->byte_code.size - RE_HEADER_LEN); /* add the named groups if needed */ - if (s->group_names.size > (s->capture_count - 1)) { - dbuf_put(&s->byte_code, s->group_names.buf, s->group_names.size); + if (s->group_names.size > (s->capture_count - 1) * LRE_GROUP_NAME_TRAILER_LEN) { + if (dbuf_put(&s->byte_code, s->group_names.buf, s->group_names.size)) { + re_parse_out_of_memory(s); + goto error; + } put_u16(s->byte_code.buf + RE_HEADER_FLAGS, - LRE_FLAG_NAMED_GROUPS | lre_get_flags(s->byte_code.buf)); + lre_get_flags(s->byte_code.buf) | LRE_FLAG_NAMED_GROUPS); } dbuf_free(&s->group_names); @@ -1894,14 +2659,6 @@ static bool is_line_terminator(uint32_t c) return (c == '\n' || c == '\r' || c == CP_LS || c == CP_PS); } -static bool is_word_char(uint32_t c) -{ - return ((c >= '0' && c <= '9') || - (c >= 'a' && c <= 'z') || - (c >= 'A' && c <= 'Z') || - (c == '_')); -} - #define GET_CHAR(c, cptr, cbuf_end, cbuf_type) \ do { \ if (cbuf_type == 0) { \ @@ -1910,11 +2667,11 @@ static bool is_word_char(uint32_t c) const uint16_t *_p = (const uint16_t *)cptr; \ const uint16_t *_end = (const uint16_t *)cbuf_end; \ c = *_p++; \ - if (is_hi_surrogate(c)) \ - if (cbuf_type == 2) \ - if (_p < _end) \ - if (is_lo_surrogate(*_p)) \ - c = from_surrogate(c, *_p++); \ + if (is_hi_surrogate(c) && cbuf_type == 2) { \ + if (_p < _end && is_lo_surrogate(*_p)) { \ + c = from_surrogate(c, *_p++); \ + } \ + } \ cptr = (const void *)_p; \ } \ } while (0) @@ -1927,11 +2684,11 @@ static bool is_word_char(uint32_t c) const uint16_t *_p = (const uint16_t *)cptr; \ const uint16_t *_end = (const uint16_t *)cbuf_end; \ c = *_p++; \ - if (is_hi_surrogate(c)) \ - if (cbuf_type == 2) \ - if (_p < _end) \ - if (is_lo_surrogate(*_p)) \ - c = from_surrogate(c, *_p); \ + if (is_hi_surrogate(c) && cbuf_type == 2) { \ + if (_p < _end && is_lo_surrogate(*_p)) { \ + c = from_surrogate(c, *_p); \ + } \ + } \ } \ } while (0) @@ -1943,11 +2700,11 @@ static bool is_word_char(uint32_t c) const uint16_t *_p = (const uint16_t *)cptr - 1; \ const uint16_t *_start = (const uint16_t *)cbuf_start; \ c = *_p; \ - if (is_lo_surrogate(c)) \ - if (cbuf_type == 2) \ - if (_p > _start) \ - if (is_hi_surrogate(_p[-1])) \ - c = from_surrogate(*--_p, c); \ + if (is_lo_surrogate(c) && cbuf_type == 2) { \ + if (_p > _start && is_hi_surrogate(_p[-1])) { \ + c = from_surrogate(*--_p, c); \ + } \ + } \ } \ } while (0) @@ -1960,11 +2717,11 @@ static bool is_word_char(uint32_t c) const uint16_t *_p = (const uint16_t *)cptr - 1; \ const uint16_t *_start = (const uint16_t *)cbuf_start; \ c = *_p; \ - if (is_lo_surrogate(c)) \ - if (cbuf_type == 2) \ - if (_p > _start) \ - if (is_hi_surrogate(_p[-1])) \ - c = from_surrogate(*--_p, c); \ + if (is_lo_surrogate(c) && cbuf_type == 2) { \ + if (_p > _start && is_hi_surrogate(_p[-1])) { \ + c = from_surrogate(*--_p, c); \ + } \ + } \ cptr = (const void *)_p; \ } \ } while (0) @@ -1976,32 +2733,35 @@ static bool is_word_char(uint32_t c) } else { \ const uint16_t *_p = (const uint16_t *)cptr - 1; \ const uint16_t *_start = (const uint16_t *)cbuf_start; \ - if (is_lo_surrogate(*_p)) \ - if (cbuf_type == 2) \ - if (_p > _start) \ - if (is_hi_surrogate(_p[-1])) \ - _p--; \ + if (is_lo_surrogate(*_p) && cbuf_type == 2) { \ + if (_p > _start && is_hi_surrogate(_p[-1])) { \ + --_p; \ + } \ + } \ cptr = (const void *)_p; \ } \ } while (0) -typedef uintptr_t StackInt; - typedef enum { RE_EXEC_STATE_SPLIT, RE_EXEC_STATE_LOOKAHEAD, RE_EXEC_STATE_NEGATIVE_LOOKAHEAD, - RE_EXEC_STATE_GREEDY_QUANT, } REExecStateEnum; -typedef struct REExecState { - REExecStateEnum type : 8; - uint8_t stack_len; - size_t count; /* only used for RE_EXEC_STATE_GREEDY_QUANT */ - const uint8_t *cptr; - const uint8_t *pc; - void *buf[]; -} REExecState; +#if INTPTR_MAX >= INT64_MAX +#define BP_TYPE_BITS 3 +#else +#define BP_TYPE_BITS 2 +#endif + +typedef union { + uint8_t *ptr; + intptr_t val; /* for bp, the low BP_SHIFT bits store REExecStateEnum */ + struct { + uintptr_t val : sizeof(uintptr_t) * 8 - BP_TYPE_BITS; + uintptr_t type : BP_TYPE_BITS; + } bp; +} StackElem; typedef struct { const uint8_t *cbuf; @@ -2009,57 +2769,15 @@ typedef struct { /* 0 = 8 bit chars, 1 = 16 bit chars, 2 = 16 bit chars, UTF-16 */ int cbuf_type; int capture_count; - int stack_size_max; - bool multi_line; - bool ignore_case; bool is_unicode; int interrupt_counter; void *opaque; /* used for stack overflow check */ - size_t state_size; - uint8_t *state_stack; - size_t state_stack_size; - size_t state_stack_len; + StackElem *stack_buf; + size_t stack_size; + StackElem static_stack_buf[32]; /* static stack to avoid allocation in most cases */ } REExecContext; -static int push_state(REExecContext *s, - uint8_t **capture, - StackInt *stack, size_t stack_len, - const uint8_t *pc, const uint8_t *cptr, - REExecStateEnum type, size_t count) -{ - REExecState *rs; - uint8_t *new_stack; - size_t new_size, i, n; - StackInt *stack_buf; - - if (unlikely((s->state_stack_len + 1) > s->state_stack_size)) { - /* reallocate the stack */ - new_size = s->state_stack_size * 3 / 2; - if (new_size < 8) - new_size = 8; - new_stack = lre_realloc(s->opaque, s->state_stack, new_size * s->state_size); - if (!new_stack) - return -1; - s->state_stack_size = new_size; - s->state_stack = new_stack; - } - rs = (REExecState *)(s->state_stack + s->state_stack_len * s->state_size); - s->state_stack_len++; - rs->type = type; - rs->count = count; - rs->stack_len = stack_len; - rs->cptr = cptr; - rs->pc = pc; - n = 2 * s->capture_count; - for(i = 0; i < n; i++) - rs->buf[i] = capture[i]; - stack_buf = (StackInt *)(rs->buf + n); - for(i = 0; i < stack_len; i++) - stack_buf[i] = stack[i]; - return 0; -} - static int lre_poll_timeout(REExecContext *s) { if (unlikely(--s->interrupt_counter <= 0)) { @@ -2070,111 +2788,196 @@ static int lre_poll_timeout(REExecContext *s) return 0; } +static no_inline int stack_realloc(REExecContext *s, size_t n) +{ + StackElem *new_stack; + size_t new_size; + new_size = s->stack_size * 3 / 2; + if (new_size < n) + new_size = n; + if (s->stack_buf == s->static_stack_buf) { + new_stack = lre_realloc(s->opaque, NULL, new_size * sizeof(StackElem)); + if (!new_stack) + return -1; + /* XXX: could use correct size */ + memcpy(new_stack, s->stack_buf, s->stack_size * sizeof(StackElem)); + } else { + new_stack = lre_realloc(s->opaque, s->stack_buf, new_size * sizeof(StackElem)); + if (!new_stack) + return -1; + } + s->stack_size = new_size; + s->stack_buf = new_stack; + return 0; +} + /* return 1 if match, 0 if not match or < 0 if error. */ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, - StackInt *stack, int stack_len, - const uint8_t *pc, const uint8_t *cptr, - bool no_recurse) + const uint8_t *pc, const uint8_t *cptr) { - int opcode, ret; + int opcode; int cbuf_type; - uint32_t val, c; + uint32_t val, c, idx; const uint8_t *cbuf_end; - + StackElem *sp, *bp, *stack_end; +#ifdef DUMP_EXEC + const uint8_t *pc_start = pc; /* TEST */ +#endif cbuf_type = s->cbuf_type; cbuf_end = s->cbuf_end; + sp = s->stack_buf; + bp = s->stack_buf; + stack_end = s->stack_buf + s->stack_size; + +#define CHECK_STACK_SPACE(n) \ + if (unlikely((stack_end - sp) < (n))) { \ + size_t saved_sp = sp - s->stack_buf; \ + size_t saved_bp = bp - s->stack_buf; \ + if (stack_realloc(s, sp - s->stack_buf + (n))) \ + return LRE_RET_MEMORY_ERROR; \ + stack_end = s->stack_buf + s->stack_size; \ + sp = s->stack_buf + saved_sp; \ + bp = s->stack_buf + saved_bp; \ + } + + /* XXX: could test if the value was saved to reduce the stack size + but slower */ +#define SAVE_CAPTURE(idx, value) \ + { \ + CHECK_STACK_SPACE(2); \ + sp[0].val = idx; \ + sp[1].ptr = capture[idx]; \ + sp += 2; \ + capture[idx] = (value); \ + } + + /* avoid saving the previous value if already saved */ +#define SAVE_CAPTURE_CHECK(idx, value) \ + { \ + StackElem *sp1; \ + sp1 = sp; \ + for(;;) { \ + if (sp1 > bp) { \ + if (sp1[-2].val == idx) \ + break; \ + sp1 -= 2; \ + } else { \ + CHECK_STACK_SPACE(2); \ + sp[0].val = idx; \ + sp[1].ptr = capture[idx]; \ + sp += 2; \ + break; \ + } \ + } \ + capture[idx] = (value); \ + } + + +#ifdef DUMP_EXEC + printf("%5s %5s %5s %5s %s\n", "PC", "CP", "BP", "SP", "OPCODE"); +#endif for(;;) { - // printf("top=%p: pc=%d\n", th_list.top, (int)(pc - (bc_buf + RE_HEADER_LEN))); opcode = *pc++; +#ifdef DUMP_EXEC + printf("%5ld %5ld %5ld %5ld %s\n", + pc - 1 - pc_start, + cbuf_type == 0 ? cptr - s->cbuf : (cptr - s->cbuf) / 2, + bp - s->stack_buf, + sp - s->stack_buf, + reopcode_info[opcode].name); +#endif switch(opcode) { case REOP_match: - { - REExecState *rs; - if (no_recurse) - return (intptr_t)cptr; - ret = 1; - goto recurse; - no_match: - if (no_recurse) + return 1; + no_match: + for(;;) { + REExecStateEnum type; + if (bp == s->stack_buf) return 0; - ret = 0; - recurse: + /* undo the modifications to capture[] */ + while (sp > bp) { + capture[sp[-2].val] = sp[-1].ptr; + sp -= 2; + } + + pc = sp[-3].ptr; + cptr = sp[-2].ptr; + type = sp[-1].bp.type; + bp = s->stack_buf + sp[-1].bp.val; + sp -= 3; + if (type != RE_EXEC_STATE_LOOKAHEAD) + break; + } + if (lre_poll_timeout(s)) + return LRE_RET_TIMEOUT; + break; + case REOP_lookahead_match: + /* pop all the saved states until reaching the start of + the lookahead and keep the updated captures and + variables and the corresponding undo info. */ + { + StackElem *sp1, *sp_top, *next_sp; + REExecStateEnum type; + + sp_top = sp; for(;;) { - if (lre_poll_timeout(s)) - return LRE_RET_TIMEOUT; - if (s->state_stack_len == 0) - return ret; - rs = (REExecState *)(s->state_stack + - (s->state_stack_len - 1) * s->state_size); - if (rs->type == RE_EXEC_STATE_SPLIT) { - if (!ret) { - pop_state: - memcpy(capture, rs->buf, - sizeof(capture[0]) * 2 * s->capture_count); - pop_state1: - pc = rs->pc; - cptr = rs->cptr; - stack_len = rs->stack_len; - memcpy(stack, rs->buf + 2 * s->capture_count, - stack_len * sizeof(stack[0])); - s->state_stack_len--; - break; - } - } else if (rs->type == RE_EXEC_STATE_GREEDY_QUANT) { - if (!ret) { - uint32_t char_count, i; - memcpy(capture, rs->buf, - sizeof(capture[0]) * 2 * s->capture_count); - stack_len = rs->stack_len; - memcpy(stack, rs->buf + 2 * s->capture_count, - stack_len * sizeof(stack[0])); - pc = rs->pc; - cptr = rs->cptr; - /* go backward */ - char_count = get_u32(pc + 12); - for(i = 0; i < char_count; i++) { - PREV_CHAR(cptr, s->cbuf, cbuf_type); - } - pc = (pc + 16) + (int)get_u32(pc); - rs->cptr = cptr; - rs->count--; - if (rs->count == 0) { - s->state_stack_len--; - } - break; - } - } else { - ret = ((rs->type == RE_EXEC_STATE_LOOKAHEAD && ret) || - (rs->type == RE_EXEC_STATE_NEGATIVE_LOOKAHEAD && !ret)); - if (ret) { - /* keep the capture in case of positive lookahead */ - if (rs->type == RE_EXEC_STATE_LOOKAHEAD) - goto pop_state1; - else - goto pop_state; - } + sp1 = sp; + sp = bp; + pc = sp[-3].ptr; + cptr = sp[-2].ptr; + type = sp[-1].bp.type; + bp = s->stack_buf + sp[-1].bp.val; + sp[-1].ptr = (void *)sp1; /* save the next value for the copy step */ + sp -= 3; + if (type == RE_EXEC_STATE_LOOKAHEAD) + break; + } + if (sp != s->stack_buf) { + /* keep the undo info if there is a saved state */ + sp1 = sp; + while (sp1 < sp_top) { + next_sp = (void *)sp1[2].ptr; + sp1 += 3; + while (sp1 < next_sp) + *sp++ = *sp1++; } - s->state_stack_len--; } } break; + case REOP_negative_lookahead_match: + /* pop all the saved states until reaching start of the negative lookahead */ + for(;;) { + REExecStateEnum type; + type = bp[-1].bp.type; + /* undo the modifications to capture[] */ + while (sp > bp) { + capture[sp[-2].val] = sp[-1].ptr; + sp -= 2; + } + pc = sp[-3].ptr; + cptr = sp[-2].ptr; + type = sp[-1].bp.type; + bp = s->stack_buf + sp[-1].bp.val; + sp -= 3; + if (type == RE_EXEC_STATE_NEGATIVE_LOOKAHEAD) + break; + } + goto no_match; case REOP_char32: + case REOP_char32_i: val = get_u32(pc); pc += 4; goto test_char; - case REOP_char16: + case REOP_char: + case REOP_char_i: val = get_u16(pc); pc += 2; - goto test_char; - case REOP_char8: - val = get_u8(pc); - pc += 1; test_char: if (cptr >= cbuf_end) goto no_match; GET_CHAR(c, cptr, cbuf_end, cbuf_type); - if (s->ignore_case) { + if (opcode == REOP_char_i || opcode == REOP_char32_i) { c = lre_canonicalize(c, s->is_unicode); } if (val != c) @@ -2193,24 +2996,27 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, pc1 = pc; pc = pc + (int)val; } - ret = push_state(s, capture, stack, stack_len, - pc1, cptr, RE_EXEC_STATE_SPLIT, 0); - if (ret < 0) - return LRE_RET_MEMORY_ERROR; - break; + CHECK_STACK_SPACE(3); + sp[0].ptr = (uint8_t *)pc1; + sp[1].ptr = (uint8_t *)cptr; + sp[2].bp.val = bp - s->stack_buf; + sp[2].bp.type = RE_EXEC_STATE_SPLIT; + sp += 3; + bp = sp; } + break; case REOP_lookahead: case REOP_negative_lookahead: val = get_u32(pc); pc += 4; - ret = push_state(s, capture, stack, stack_len, - pc + (int)val, cptr, - RE_EXEC_STATE_LOOKAHEAD + opcode - REOP_lookahead, - 0); - if (ret < 0) - return LRE_RET_MEMORY_ERROR; + CHECK_STACK_SPACE(3); + sp[0].ptr = (uint8_t *)(pc + (int)val); + sp[1].ptr = (uint8_t *)cptr; + sp[2].bp.val = bp - s->stack_buf; + sp[2].bp.type = RE_EXEC_STATE_LOOKAHEAD + opcode - REOP_lookahead; + sp += 3; + bp = sp; break; - case REOP_goto: val = get_u32(pc); pc += 4 + (int)val; @@ -2218,18 +3024,20 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, return LRE_RET_TIMEOUT; break; case REOP_line_start: + case REOP_line_start_m: if (cptr == s->cbuf) break; - if (!s->multi_line) + if (opcode == REOP_line_start) goto no_match; PEEK_PREV_CHAR(c, cptr, s->cbuf, cbuf_type); if (!is_line_terminator(c)) goto no_match; break; case REOP_line_end: + case REOP_line_end_m: if (cptr == cbuf_end) break; - if (!s->multi_line) + if (opcode == REOP_line_end) goto no_match; PEEK_CHAR(c, cptr, cbuf_end, cbuf_type); if (!is_line_terminator(c)) @@ -2247,12 +3055,27 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, goto no_match; GET_CHAR(c, cptr, cbuf_end, cbuf_type); break; + case REOP_space: + if (cptr == cbuf_end) + goto no_match; + GET_CHAR(c, cptr, cbuf_end, cbuf_type); + if (!lre_is_space(c)) + goto no_match; + break; + case REOP_not_space: + if (cptr == cbuf_end) + goto no_match; + GET_CHAR(c, cptr, cbuf_end, cbuf_type); + if (lre_is_space(c)) + goto no_match; + break; case REOP_save_start: case REOP_save_end: val = *pc++; - if (val >= s->capture_count) + if (val >= (uint32_t)s->capture_count) return LRE_RET_BYTECODE_ERROR; - capture[2 * val + opcode - REOP_save_start] = (uint8_t *)cptr; + idx = 2 * val + opcode - REOP_save_start; + SAVE_CAPTURE(idx, (uint8_t *)cptr); break; case REOP_save_reset: { @@ -2260,106 +3083,194 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, val = pc[0]; val2 = pc[1]; pc += 2; - if (val2 >= s->capture_count) + if (val2 >= (uint32_t)s->capture_count) return LRE_RET_BYTECODE_ERROR; + CHECK_STACK_SPACE(2 * (val2 - val + 1)); while (val <= val2) { - capture[2 * val] = NULL; - capture[2 * val + 1] = NULL; + idx = 2 * val; + SAVE_CAPTURE(idx, NULL); + idx = 2 * val + 1; + SAVE_CAPTURE(idx, NULL); val++; } } break; - case REOP_push_i32: - val = get_u32(pc); - pc += 4; - stack[stack_len++] = val; - break; - case REOP_drop: - stack_len--; + case REOP_set_i32: + idx = 2 * s->capture_count + pc[0]; + val = get_u32(pc + 1); + pc += 5; + SAVE_CAPTURE_CHECK(idx, (void *)(uintptr_t)val); break; case REOP_loop: - val = get_u32(pc); - pc += 4; - if (--stack[stack_len - 1] != 0) { - pc += (int)val; - if (lre_poll_timeout(s)) - return LRE_RET_TIMEOUT; + { + uint32_t val2; + idx = 2 * s->capture_count + pc[0]; + val = get_u32(pc + 1); + pc += 5; + + val2 = (uintptr_t)capture[idx] - 1; + SAVE_CAPTURE_CHECK(idx, (void *)(uintptr_t)val2); + if (val2 != 0) { + pc += (int)val; + if (lre_poll_timeout(s)) + return LRE_RET_TIMEOUT; + } + } + break; + case REOP_loop_split_goto_first: + case REOP_loop_split_next_first: + case REOP_loop_check_adv_split_goto_first: + case REOP_loop_check_adv_split_next_first: + { + const uint8_t *pc1; + uint32_t val2, limit; + idx = 2 * s->capture_count + pc[0]; + limit = get_u32(pc + 1); + val = get_u32(pc + 5); + pc += 9; + + /* decrement the counter */ + val2 = (uintptr_t)capture[idx] - 1; + SAVE_CAPTURE_CHECK(idx, (void *)(uintptr_t)val2); + + if (val2 > limit) { + /* normal loop if counter > limit */ + pc += (int)val; + if (lre_poll_timeout(s)) + return LRE_RET_TIMEOUT; + } else { + /* check advance */ + if ((opcode == REOP_loop_check_adv_split_goto_first || + opcode == REOP_loop_check_adv_split_next_first) && + capture[idx + 1] == cptr && + val2 != limit) { + goto no_match; + } + + /* otherwise conditional split */ + if (val2 != 0) { + if (opcode == REOP_loop_split_next_first || + opcode == REOP_loop_check_adv_split_next_first) { + pc1 = pc + (int)val; + } else { + pc1 = pc; + pc = pc + (int)val; + } + CHECK_STACK_SPACE(3); + sp[0].ptr = (uint8_t *)pc1; + sp[1].ptr = (uint8_t *)cptr; + sp[2].bp.val = bp - s->stack_buf; + sp[2].bp.type = RE_EXEC_STATE_SPLIT; + sp += 3; + bp = sp; + } + } } break; - case REOP_push_char_pos: - stack[stack_len++] = (uintptr_t)cptr; + case REOP_set_char_pos: + idx = 2 * s->capture_count + pc[0]; + pc++; + SAVE_CAPTURE_CHECK(idx, (uint8_t *)cptr); break; case REOP_check_advance: - if (stack[--stack_len] == (uintptr_t)cptr) + idx = 2 * s->capture_count + pc[0]; + pc++; + if (capture[idx] == cptr) goto no_match; break; case REOP_word_boundary: + case REOP_word_boundary_i: case REOP_not_word_boundary: + case REOP_not_word_boundary_i: { bool v1, v2; + int ignore_case = (opcode == REOP_word_boundary_i || opcode == REOP_not_word_boundary_i); + bool is_boundary = (opcode == REOP_word_boundary || opcode == REOP_word_boundary_i); /* char before */ if (cptr == s->cbuf) { v1 = false; } else { PEEK_PREV_CHAR(c, cptr, s->cbuf, cbuf_type); - v1 = is_word_char(c); + if (c < 256) { + v1 = (lre_is_word_byte(c) != 0); + } else { + v1 = ignore_case && (c == 0x017f || c == 0x212a); + } } /* current char */ if (cptr >= cbuf_end) { v2 = false; } else { PEEK_CHAR(c, cptr, cbuf_end, cbuf_type); - v2 = is_word_char(c); + if (c < 256) { + v2 = (lre_is_word_byte(c) != 0); + } else { + v2 = ignore_case && (c == 0x017f || c == 0x212a); + } } - if (v1 ^ v2 ^ (REOP_not_word_boundary - opcode)) + if (v1 ^ v2 ^ is_boundary) goto no_match; } break; case REOP_back_reference: + case REOP_back_reference_i: case REOP_backward_back_reference: + case REOP_backward_back_reference_i: { const uint8_t *cptr1, *cptr1_end, *cptr1_start; + const uint8_t *pc1; uint32_t c1, c2; + int i, n; - val = *pc++; - if (val >= s->capture_count) - goto no_match; - cptr1_start = capture[2 * val]; - cptr1_end = capture[2 * val + 1]; - if (!cptr1_start || !cptr1_end) - break; - if (opcode == REOP_back_reference) { - cptr1 = cptr1_start; - while (cptr1 < cptr1_end) { - if (cptr >= cbuf_end) - goto no_match; - GET_CHAR(c1, cptr1, cptr1_end, cbuf_type); - GET_CHAR(c2, cptr, cbuf_end, cbuf_type); - if (s->ignore_case) { - c1 = lre_canonicalize(c1, s->is_unicode); - c2 = lre_canonicalize(c2, s->is_unicode); - } - if (c1 != c2) - goto no_match; - } - } else { - cptr1 = cptr1_end; - while (cptr1 > cptr1_start) { - if (cptr == s->cbuf) - goto no_match; - GET_PREV_CHAR(c1, cptr1, cptr1_start, cbuf_type); - GET_PREV_CHAR(c2, cptr, s->cbuf, cbuf_type); - if (s->ignore_case) { - c1 = lre_canonicalize(c1, s->is_unicode); - c2 = lre_canonicalize(c2, s->is_unicode); + n = *pc++; + pc1 = pc; + pc += n; + + for(i = 0; i < n; i++) { + val = pc1[i]; + if (val >= s->capture_count) + goto no_match; + cptr1_start = capture[2 * val]; + cptr1_end = capture[2 * val + 1]; + /* test the first not empty capture */ + if (cptr1_start && cptr1_end) { + if (opcode == REOP_back_reference || + opcode == REOP_back_reference_i) { + cptr1 = cptr1_start; + while (cptr1 < cptr1_end) { + if (cptr >= cbuf_end) + goto no_match; + GET_CHAR(c1, cptr1, cptr1_end, cbuf_type); + GET_CHAR(c2, cptr, cbuf_end, cbuf_type); + if (opcode == REOP_back_reference_i) { + c1 = lre_canonicalize(c1, s->is_unicode); + c2 = lre_canonicalize(c2, s->is_unicode); + } + if (c1 != c2) + goto no_match; + } + } else { + cptr1 = cptr1_end; + while (cptr1 > cptr1_start) { + if (cptr == s->cbuf) + goto no_match; + GET_PREV_CHAR(c1, cptr1, cptr1_start, cbuf_type); + GET_PREV_CHAR(c2, cptr, s->cbuf, cbuf_type); + if (opcode == REOP_backward_back_reference_i) { + c1 = lre_canonicalize(c1, s->is_unicode); + c2 = lre_canonicalize(c2, s->is_unicode); + } + if (c1 != c2) + goto no_match; + } } - if (c1 != c2) - goto no_match; + break; } } } break; case REOP_range: + case REOP_range_i: { int n; uint32_t low, high, idx_min, idx_max, idx; @@ -2369,7 +3280,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, if (cptr >= cbuf_end) goto no_match; GET_CHAR(c, cptr, cbuf_end, cbuf_type); - if (s->ignore_case) { + if (opcode == REOP_range_i) { c = lre_canonicalize(c, s->is_unicode); } idx_min = 0; @@ -2400,6 +3311,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, } break; case REOP_range32: + case REOP_range32_i: { int n; uint32_t low, high, idx_min, idx_max, idx; @@ -2409,7 +3321,7 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, if (cptr >= cbuf_end) goto no_match; GET_CHAR(c, cptr, cbuf_end, cbuf_type); - if (s->ignore_case) { + if (opcode == REOP_range32_i) { c = lre_canonicalize(c, s->is_unicode); } idx_min = 0; @@ -2442,50 +3354,10 @@ static intptr_t lre_exec_backtrack(REExecContext *s, uint8_t **capture, goto no_match; PREV_CHAR(cptr, s->cbuf, cbuf_type); break; - case REOP_simple_greedy_quant: - { - uint32_t next_pos, quant_min, quant_max; - size_t q; - intptr_t res; - const uint8_t *pc1; - - next_pos = get_u32(pc); - quant_min = get_u32(pc + 4); - quant_max = get_u32(pc + 8); - pc += 16; - pc1 = pc; - pc += (int)next_pos; - - q = 0; - for(;;) { - if (lre_poll_timeout(s)) - return LRE_RET_TIMEOUT; - res = lre_exec_backtrack(s, capture, stack, stack_len, - pc1, cptr, true); - if (res == LRE_RET_MEMORY_ERROR || - res == LRE_RET_TIMEOUT) - return res; - if (!res) - break; - cptr = (uint8_t *)res; - q++; - if (q >= quant_max && quant_max != INT32_MAX) - break; - } - if (q < quant_min) - goto no_match; - if (q > quant_min) { - /* will examine all matches down to quant_min */ - ret = push_state(s, capture, stack, stack_len, - pc1 - 16, cptr, - RE_EXEC_STATE_GREEDY_QUANT, - q - quant_min); - if (ret < 0) - return LRE_RET_MEMORY_ERROR; - } - } - break; default: +#ifdef DUMP_EXEC + printf("unknown opcode pc=%ld\n", pc - 1 - pc_start); +#endif abort(); } } @@ -2499,15 +3371,12 @@ int lre_exec(uint8_t **capture, int cbuf_type, void *opaque) { REExecContext s_s, *s = &s_s; - int re_flags, i, alloca_size, ret; - StackInt *stack_buf; + int re_flags, i, ret; + const uint8_t *cptr; re_flags = lre_get_flags(bc_buf); - s->multi_line = (re_flags & LRE_FLAG_MULTILINE) != 0; - s->ignore_case = (re_flags & LRE_FLAG_IGNORECASE) != 0; - s->is_unicode = (re_flags & LRE_FLAG_UNICODE) != 0; + s->is_unicode = (re_flags & (LRE_FLAG_UNICODE | LRE_FLAG_UNICODE_SETS)) != 0; s->capture_count = bc_buf[RE_HEADER_CAPTURE_COUNT]; - s->stack_size_max = bc_buf[RE_HEADER_STACK_SIZE]; s->cbuf = cbuf; s->cbuf_end = cbuf + (clen << cbuf_type); s->cbuf_type = cbuf_type; @@ -2516,23 +3385,47 @@ int lre_exec(uint8_t **capture, s->interrupt_counter = INTERRUPT_COUNTER_INIT; s->opaque = opaque; - s->state_size = sizeof(REExecState) + - s->capture_count * sizeof(capture[0]) * 2 + - s->stack_size_max * sizeof(stack_buf[0]); - s->state_stack = NULL; - s->state_stack_len = 0; - s->state_stack_size = 0; + s->stack_buf = s->static_stack_buf; + s->stack_size = countof(s->static_stack_buf); for(i = 0; i < s->capture_count * 2; i++) capture[i] = NULL; - alloca_size = s->stack_size_max * sizeof(stack_buf[0]); - stack_buf = alloca(alloca_size); - ret = lre_exec_backtrack(s, capture, stack_buf, 0, bc_buf + RE_HEADER_LEN, - cbuf + (cindex << cbuf_type), false); - lre_realloc(s->opaque, s->state_stack, 0); + + cptr = cbuf + (cindex << cbuf_type); + if (0 < cindex && cindex < clen && s->cbuf_type == 2) { + const uint16_t *p = (const uint16_t *)cptr; + if (is_lo_surrogate(*p) && is_hi_surrogate(p[-1])) { + cptr = (const uint8_t *)(p - 1); + } + } + + ret = lre_exec_backtrack(s, capture, bc_buf + RE_HEADER_LEN, cptr); + + if (s->stack_buf != s->static_stack_buf) + lre_realloc(s->opaque, s->stack_buf, 0); return ret; } +int lre_get_alloc_count(const uint8_t *bc_buf) +{ + return bc_buf[RE_HEADER_CAPTURE_COUNT] * 2 + + bc_buf[RE_HEADER_REGISTER_COUNT]; +} + +/* Structurally validate serialized regexp bytecode (e.g. from JS_ReadObject) + before it is executed: a present header and a body length that fits within + the buffer. Returns 0 on success, -1 if the bytecode is malformed. */ +int lre_check_bytecode(const uint8_t *bc_buf, int bc_buf_len) +{ + uint32_t re_bytecode_len; + if (bc_buf_len < RE_HEADER_LEN) + return -1; + re_bytecode_len = get_u32(bc_buf + RE_HEADER_BYTECODE_LEN); + if (re_bytecode_len > (uint32_t)(bc_buf_len - RE_HEADER_LEN)) + return -1; + return 0; +} + int lre_get_capture_count(const uint8_t *bc_buf) { return bc_buf[RE_HEADER_CAPTURE_COUNT]; @@ -2571,13 +3464,13 @@ int main(int argc, char **argv) int len, flags, ret, i; uint8_t *bc; char error_msg[64]; - uint8_t *capture[CAPTURE_COUNT_MAX * 2]; + uint8_t *capture; const char *input; int input_len, capture_count; if (argc < 4) { printf("usage: %s regexp flags input\n", argv[0]); - exit(1); + return 1; } flags = atoi(argv[2]); bc = lre_compile(&len, error_msg, sizeof(error_msg), argv[1], @@ -2590,6 +3483,7 @@ int main(int argc, char **argv) input = argv[3]; input_len = strlen(input); + capture = malloc(sizeof(capture[0]) * lre_get_alloc_count(bc)); ret = lre_exec(capture, bc, (uint8_t *)input, 0, input_len, 0, NULL); printf("ret=%d\n", ret); if (ret == 1) { @@ -2605,6 +3499,7 @@ int main(int argc, char **argv) printf("\n"); } } + free(capture); return 0; } #endif diff --git a/deps/quickjs/libregexp.h b/deps/quickjs/libregexp.h index 7d24c11..44eded3 100644 --- a/deps/quickjs/libregexp.h +++ b/deps/quickjs/libregexp.h @@ -47,9 +47,14 @@ extern "C" { #define LRE_RET_TIMEOUT (-2) #define LRE_RET_BYTECODE_ERROR (-3) +/* trailer length after the group name including the trailing '\0' */ +#define LRE_GROUP_NAME_TRAILER_LEN 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_alloc_count(const uint8_t *bc_buf); +int lre_check_bytecode(const uint8_t *bc_buf, int bc_buf_len); 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); @@ -58,7 +63,7 @@ int lre_exec(uint8_t **capture, int cbuf_type, void *opaque); int lre_parse_escape(const uint8_t **pp, int allow_utf16); -bool lre_is_space(int c); +/* lre_is_space() is provided as an inline in libunicode.h */ /* must be provided by the user */ bool lre_check_stack_overflow(void *opaque, size_t alloca_size); diff --git a/deps/quickjs/libunicode-table.h b/deps/quickjs/libunicode-table.h index c75e9e3..63967a0 100644 --- a/deps/quickjs/libunicode-table.h +++ b/deps/quickjs/libunicode-table.h @@ -1,6 +1,48 @@ /* Compressed unicode tables */ /* Automatically generated file - do not edit */ +/* +UNICODE LICENSE V3 + +COPYRIGHT AND PERMISSION NOTICE + +Copyright © 1991-2026 Unicode, Inc. + +NOTICE TO USER: Carefully read the following legal agreement. BY +DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING DATA FILES, AND/OR +SOFTWARE, YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE +TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT +DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of data files and any associated documentation (the "Data Files") or +software and any associated documentation (the "Software") to deal in the +Data Files or Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, and/or sell +copies of the Data Files or Software, and to permit persons to whom the +Data Files or Software are furnished to do so, provided that either (a) +this copyright and permission notice appear with all copies of the Data +Files or Software, or (b) this copyright and permission notice appear in +associated Documentation. + +THE DATA FILES AND SOFTWARE ARE 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 OF +THIRD PARTY RIGHTS. + +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE +BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, +OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA +FILES OR SOFTWARE. + +Except as contained in this notice, the name of a copyright holder shall +not be used in advertising or otherwise to promote the sale, use or other +dealings in these Data Files or Software without prior written +authorization of the copyright holder. +*/ + #include static const uint32_t case_conv_table1[378] = { @@ -4473,6 +4515,10 @@ typedef enum { UNICODE_PROP_Changes_When_Titlecased1, UNICODE_PROP_Changes_When_Casefolded1, UNICODE_PROP_Changes_When_NFKC_Casefolded1, + UNICODE_PROP_Basic_Emoji1, + UNICODE_PROP_Basic_Emoji2, + UNICODE_PROP_RGI_Emoji_Flag_Sequence, + UNICODE_PROP_Emoji_Keycap_Sequence, UNICODE_PROP_ASCII_Hex_Digit, UNICODE_PROP_Bidi_Control, UNICODE_PROP_Dash, @@ -4595,6 +4641,89 @@ static const char unicode_prop_name_table[] = "XID_Start,XIDS" "\0" ; +/* RGI emoji sequence support */ +static const uint8_t unicode_prop_Basic_Emoji1_table[144] = { + 0x60, 0x23, 0x19, 0x81, 0x40, 0xcc, 0x1a, 0x01, + 0x80, 0x42, 0x08, 0x81, 0x94, 0x81, 0xb1, 0x8b, + 0xaa, 0x80, 0x92, 0x80, 0x8c, 0x07, 0x81, 0x90, + 0x0c, 0x0f, 0x04, 0x80, 0x94, 0x06, 0x08, 0x03, + 0x01, 0x06, 0x03, 0x81, 0x9b, 0x80, 0xa2, 0x00, + 0x03, 0x10, 0x80, 0xbc, 0x82, 0x97, 0x80, 0x8d, + 0x80, 0x43, 0x5a, 0x81, 0xb2, 0x03, 0x80, 0x61, + 0xc4, 0xad, 0x80, 0x40, 0xc9, 0x80, 0x40, 0xbd, + 0x01, 0x89, 0xe5, 0x80, 0x97, 0x80, 0x93, 0x01, + 0x20, 0x82, 0x94, 0x81, 0x40, 0xad, 0xa0, 0x8b, + 0x88, 0x80, 0xc5, 0x80, 0x95, 0x8b, 0xaa, 0x1c, + 0x8b, 0x90, 0x10, 0x82, 0xc6, 0x00, 0x80, 0x40, + 0xba, 0x81, 0xbe, 0x8c, 0x18, 0x97, 0x91, 0x80, + 0x99, 0x81, 0x8c, 0x80, 0xd5, 0xd4, 0xaf, 0xc5, + 0x28, 0x12, 0x0b, 0x13, 0x8a, 0x0e, 0x88, 0x40, + 0xe2, 0x8b, 0x18, 0x41, 0x1a, 0xae, 0x80, 0x89, + 0x80, 0x40, 0xb8, 0xef, 0x8c, 0x82, 0x8a, 0x82, + 0xb8, 0x00, 0x83, 0x8f, 0x81, 0x8b, 0x83, 0x89, +}; + +static const uint8_t unicode_prop_Basic_Emoji2_table[183] = { + 0x40, 0xa8, 0x03, 0x80, 0x5f, 0x8c, 0x80, 0x8b, + 0x80, 0x40, 0xd7, 0x80, 0x95, 0x80, 0xd9, 0x85, + 0x8e, 0x81, 0x41, 0x7c, 0x80, 0x40, 0xa5, 0x80, + 0x9c, 0x10, 0x0c, 0x82, 0x40, 0xc6, 0x80, 0x40, + 0xe6, 0x81, 0x89, 0x80, 0x88, 0x80, 0xb9, 0x0a, + 0x84, 0x88, 0x01, 0x05, 0x03, 0x01, 0x00, 0x09, + 0x02, 0x02, 0x0f, 0x14, 0x00, 0x80, 0x9b, 0x09, + 0x00, 0x08, 0x80, 0x91, 0x01, 0x80, 0x92, 0x00, + 0x18, 0x00, 0x0a, 0x05, 0x07, 0x81, 0x95, 0x05, + 0x00, 0x00, 0x80, 0x94, 0x05, 0x09, 0x01, 0x17, + 0x04, 0x09, 0x08, 0x01, 0x00, 0x00, 0x05, 0x02, + 0x80, 0x90, 0x81, 0x8e, 0x01, 0x80, 0x9a, 0x81, + 0xbb, 0x80, 0x41, 0x91, 0x81, 0x41, 0xce, 0x82, + 0x45, 0x27, 0x80, 0x8b, 0x80, 0x42, 0x58, 0x00, + 0x80, 0x61, 0xbe, 0xd5, 0x81, 0x8b, 0x81, 0x40, + 0x81, 0x80, 0xb3, 0x80, 0x40, 0xe8, 0x01, 0x88, + 0x88, 0x80, 0xc5, 0x80, 0x97, 0x08, 0x11, 0x81, + 0xaa, 0x1c, 0x8b, 0x92, 0x00, 0x00, 0x80, 0xc6, + 0x00, 0x80, 0x40, 0xba, 0x80, 0xca, 0x81, 0xa3, + 0x09, 0x86, 0x8c, 0x01, 0x19, 0x80, 0x93, 0x01, + 0x07, 0x81, 0x88, 0x04, 0x82, 0x8b, 0x17, 0x11, + 0x00, 0x03, 0x05, 0x02, 0x05, 0x80, 0x40, 0xcf, + 0x00, 0x82, 0x8f, 0x2a, 0x05, 0x01, 0x80, +}; + +static const uint8_t unicode_prop_RGI_Emoji_Modifier_Sequence_table[72] = { + 0x60, 0x26, 0x1c, 0x80, 0x40, 0xda, 0x80, 0x8f, + 0x83, 0x61, 0xcc, 0x76, 0x80, 0xbb, 0x11, 0x01, + 0x82, 0xf4, 0x09, 0x8a, 0x94, 0x18, 0x8d, 0x10, + 0x1a, 0x02, 0x30, 0x00, 0x97, 0x80, 0x40, 0xc8, + 0x0b, 0x80, 0x94, 0x03, 0x81, 0x40, 0xad, 0x12, + 0x84, 0xd2, 0x80, 0x8f, 0x82, 0x88, 0x80, 0x8a, + 0x80, 0x42, 0x3e, 0x01, 0x07, 0x3d, 0x80, 0x88, + 0x89, 0x0a, 0xb7, 0x80, 0xbc, 0x08, 0x08, 0x80, + 0x90, 0x10, 0x8c, 0x40, 0xe4, 0x82, 0xa9, 0x88, +}; + +static const uint8_t unicode_prop_RGI_Emoji_Flag_Sequence_table[128] = { + 0x0c, 0x00, 0x09, 0x00, 0x04, 0x01, 0x02, 0x06, + 0x03, 0x03, 0x01, 0x02, 0x01, 0x03, 0x07, 0x0d, + 0x18, 0x00, 0x09, 0x00, 0x00, 0x89, 0x08, 0x00, + 0x00, 0x81, 0x88, 0x83, 0x8c, 0x10, 0x00, 0x01, + 0x07, 0x08, 0x29, 0x10, 0x28, 0x00, 0x80, 0x8a, + 0x00, 0x0a, 0x00, 0x0e, 0x15, 0x18, 0x83, 0x89, + 0x06, 0x00, 0x81, 0x8d, 0x00, 0x12, 0x08, 0x00, + 0x03, 0x00, 0x24, 0x00, 0x05, 0x21, 0x00, 0x00, + 0x29, 0x90, 0x00, 0x02, 0x00, 0x08, 0x09, 0x00, + 0x08, 0x18, 0x8b, 0x80, 0x8c, 0x02, 0x19, 0x1a, + 0x11, 0x00, 0x00, 0x80, 0x9c, 0x80, 0x88, 0x02, + 0x00, 0x00, 0x02, 0x20, 0x88, 0x0a, 0x00, 0x03, + 0x01, 0x02, 0x05, 0x08, 0x00, 0x01, 0x09, 0x20, + 0x21, 0x18, 0x22, 0x00, 0x00, 0x00, 0x00, 0x18, + 0x28, 0x89, 0x80, 0x8b, 0x80, 0x90, 0x80, 0x92, + 0x80, 0x8d, 0x05, 0x80, 0x8a, 0x80, 0x88, 0x80, +}; + +static const uint8_t unicode_prop_Emoji_Keycap_Sequence_table[4] = { + 0xa2, 0x05, 0x04, 0x89, +}; + static const uint8_t * const unicode_prop_table[] = { unicode_prop_Hyphen_table, unicode_prop_Other_Math_table, @@ -4612,6 +4741,10 @@ static const uint8_t * const unicode_prop_table[] = { unicode_prop_Changes_When_Titlecased1_table, unicode_prop_Changes_When_Casefolded1_table, unicode_prop_Changes_When_NFKC_Casefolded1_table, + unicode_prop_Basic_Emoji1_table, + unicode_prop_Basic_Emoji2_table, + unicode_prop_RGI_Emoji_Flag_Sequence_table, + unicode_prop_Emoji_Keycap_Sequence_table, unicode_prop_ASCII_Hex_Digit_table, unicode_prop_Bidi_Control_table, unicode_prop_Dash_table, @@ -4667,6 +4800,10 @@ static const uint16_t unicode_prop_len_table[] = { countof(unicode_prop_Changes_When_Titlecased1_table), countof(unicode_prop_Changes_When_Casefolded1_table), countof(unicode_prop_Changes_When_NFKC_Casefolded1_table), + countof(unicode_prop_Basic_Emoji1_table), + countof(unicode_prop_Basic_Emoji2_table), + countof(unicode_prop_RGI_Emoji_Flag_Sequence_table), + countof(unicode_prop_Emoji_Keycap_Sequence_table), countof(unicode_prop_ASCII_Hex_Digit_table), countof(unicode_prop_Bidi_Control_table), countof(unicode_prop_Dash_table), @@ -4705,3 +4842,332 @@ static const uint16_t unicode_prop_len_table[] = { countof(unicode_prop_Case_Ignorable_table), }; +/* RGI emoji sequence-property tables */ +typedef enum { + UNICODE_SEQUENCE_PROP_Basic_Emoji, + UNICODE_SEQUENCE_PROP_Emoji_Keycap_Sequence, + UNICODE_SEQUENCE_PROP_RGI_Emoji_Modifier_Sequence, + UNICODE_SEQUENCE_PROP_RGI_Emoji_Flag_Sequence, + UNICODE_SEQUENCE_PROP_RGI_Emoji_Tag_Sequence, + UNICODE_SEQUENCE_PROP_RGI_Emoji_ZWJ_Sequence, + UNICODE_SEQUENCE_PROP_RGI_Emoji, + UNICODE_SEQUENCE_PROP_COUNT, +} UnicodeSequencePropertyEnum; + +static const char unicode_sequence_prop_name_table[] = + "Basic_Emoji" "\0" + "Emoji_Keycap_Sequence" "\0" + "RGI_Emoji_Modifier_Sequence" "\0" + "RGI_Emoji_Flag_Sequence" "\0" + "RGI_Emoji_Tag_Sequence" "\0" + "RGI_Emoji_ZWJ_Sequence" "\0" + "RGI_Emoji" "\0" +; + +static const uint8_t unicode_rgi_emoji_tag_sequence[18] = { + 0x67, 0x62, 0x65, 0x6e, 0x67, 0x00, 0x67, 0x62, + 0x73, 0x63, 0x74, 0x00, 0x67, 0x62, 0x77, 0x6c, + 0x73, 0x00, +}; + +static const uint8_t unicode_rgi_emoji_zwj_sequence[2392] = { + 0x02, 0xb8, 0x19, 0x40, 0x86, 0x02, 0xd1, 0x39, + 0xb0, 0x19, 0x02, 0x26, 0x39, 0x42, 0x86, 0x02, + 0xb4, 0x36, 0x42, 0x86, 0x03, 0x68, 0x54, 0x64, + 0x87, 0x68, 0x54, 0x02, 0xdc, 0x39, 0x42, 0x86, + 0x02, 0xd1, 0x39, 0x73, 0x13, 0x02, 0x39, 0x39, + 0x40, 0x86, 0x02, 0x69, 0x34, 0xbd, 0x19, 0x03, + 0xb6, 0x36, 0x40, 0x86, 0xa1, 0x87, 0x03, 0x68, + 0x74, 0x1d, 0x19, 0x68, 0x74, 0x03, 0x68, 0x34, + 0xbd, 0x19, 0xa1, 0x87, 0x02, 0xf1, 0x7a, 0xf2, + 0x7a, 0x02, 0xca, 0x33, 0x42, 0x86, 0x02, 0x69, + 0x34, 0xb0, 0x19, 0x04, 0x68, 0x14, 0x68, 0x14, + 0x67, 0x14, 0x66, 0x14, 0x02, 0xf9, 0x26, 0x42, + 0x86, 0x03, 0x69, 0x74, 0x1d, 0x19, 0x69, 0x74, + 0x03, 0xd1, 0x19, 0xbc, 0x19, 0xa1, 0x87, 0x02, + 0x3c, 0x19, 0x40, 0x86, 0x02, 0x68, 0x34, 0xeb, + 0x13, 0x02, 0xc3, 0x33, 0xa1, 0x87, 0x02, 0x70, + 0x34, 0x40, 0x86, 0x02, 0xd4, 0x39, 0x42, 0x86, + 0x02, 0xcf, 0x39, 0x42, 0x86, 0x03, 0xd1, 0x79, + 0xef, 0x1a, 0xd1, 0x79, 0x03, 0x68, 0x74, 0xef, + 0x1a, 0x68, 0x74, 0x03, 0x69, 0x74, 0xef, 0x1a, + 0x69, 0x74, 0x02, 0x47, 0x36, 0x40, 0x86, 0x03, + 0x68, 0x74, 0x30, 0x14, 0x68, 0x74, 0x02, 0x39, + 0x39, 0x42, 0x86, 0x04, 0xd1, 0x79, 0x64, 0x87, + 0x8b, 0x14, 0xd1, 0x79, 0x03, 0x69, 0x74, 0x30, + 0x14, 0x69, 0x74, 0x02, 0xd1, 0x39, 0x95, 0x86, + 0x02, 0x68, 0x34, 0x93, 0x13, 0x02, 0x69, 0x34, + 0xed, 0x13, 0x02, 0xda, 0x39, 0x40, 0x86, 0x03, + 0x69, 0x34, 0xaf, 0x19, 0xa1, 0x87, 0x02, 0xd1, + 0x39, 0x93, 0x13, 0x03, 0xce, 0x39, 0x42, 0x86, + 0xa1, 0x87, 0x03, 0xd1, 0x79, 0x64, 0x87, 0xd1, + 0x79, 0x03, 0xc3, 0x33, 0x42, 0x86, 0xa1, 0x87, + 0x03, 0x69, 0x74, 0x1d, 0x19, 0x68, 0x74, 0x02, + 0x69, 0x34, 0x92, 0x16, 0x02, 0xd1, 0x39, 0x96, + 0x86, 0x04, 0x69, 0x14, 0x64, 0x87, 0x8b, 0x14, + 0x68, 0x14, 0x02, 0x47, 0x36, 0x42, 0x86, 0x02, + 0x68, 0x34, 0x7c, 0x13, 0x02, 0x86, 0x34, 0x42, + 0x86, 0x02, 0xd1, 0x39, 0x7c, 0x13, 0x02, 0x69, + 0x14, 0xa4, 0x13, 0x02, 0xda, 0x39, 0x42, 0x86, + 0x02, 0x37, 0x39, 0x40, 0x86, 0x02, 0xd1, 0x39, + 0x08, 0x87, 0x04, 0x68, 0x54, 0x64, 0x87, 0x8b, + 0x14, 0x68, 0x54, 0x02, 0x4d, 0x36, 0x40, 0x86, + 0x02, 0x68, 0x34, 0x2c, 0x15, 0x02, 0x69, 0x34, + 0xaf, 0x19, 0x02, 0x6e, 0x34, 0x40, 0x86, 0x02, + 0xcd, 0x39, 0x42, 0x86, 0x02, 0xd1, 0x39, 0x2c, + 0x15, 0x02, 0x6f, 0x14, 0x40, 0x86, 0x03, 0xd1, + 0x39, 0xbc, 0x19, 0xa1, 0x87, 0x02, 0x68, 0x34, + 0xa8, 0x13, 0x02, 0x69, 0x34, 0x73, 0x13, 0x04, + 0x69, 0x54, 0x64, 0x87, 0x8b, 0x14, 0x68, 0x54, + 0x02, 0x71, 0x34, 0x42, 0x86, 0x02, 0x45, 0x36, + 0x40, 0x86, 0x02, 0xd1, 0x39, 0xa8, 0x13, 0x03, + 0x69, 0x54, 0x64, 0x87, 0x68, 0x54, 0x03, 0x69, + 0x54, 0x64, 0x87, 0x69, 0x54, 0x03, 0xce, 0x39, + 0x40, 0x86, 0xa1, 0x87, 0x02, 0xd8, 0x39, 0x40, + 0x86, 0x03, 0xc3, 0x33, 0x40, 0x86, 0xa1, 0x87, + 0x02, 0x4d, 0x36, 0x42, 0x86, 0x02, 0xd1, 0x19, + 0x92, 0x16, 0x02, 0xd1, 0x39, 0xeb, 0x13, 0x02, + 0x68, 0x34, 0xbc, 0x14, 0x02, 0xd1, 0x39, 0xbc, + 0x14, 0x02, 0x3d, 0x39, 0x40, 0x86, 0x02, 0xb8, + 0x39, 0x42, 0x86, 0x02, 0xa3, 0x36, 0x40, 0x86, + 0x02, 0x75, 0x35, 0x40, 0x86, 0x02, 0xd8, 0x39, + 0x42, 0x86, 0x02, 0x69, 0x34, 0x93, 0x13, 0x02, + 0x35, 0x39, 0x40, 0x86, 0x02, 0x4b, 0x36, 0x40, + 0x86, 0x02, 0x3d, 0x39, 0x42, 0x86, 0x02, 0x38, + 0x39, 0x42, 0x86, 0x02, 0xa3, 0x36, 0x42, 0x86, + 0x03, 0x69, 0x14, 0x67, 0x14, 0x67, 0x14, 0x02, + 0xb6, 0x36, 0x40, 0x86, 0x02, 0x69, 0x34, 0x7c, + 0x13, 0x02, 0x75, 0x35, 0x42, 0x86, 0x02, 0xcc, + 0x93, 0x40, 0x86, 0x02, 0x6f, 0x34, 0x42, 0x86, + 0x02, 0xcc, 0x33, 0x40, 0x86, 0x03, 0xd1, 0x39, + 0xbd, 0x19, 0xa1, 0x87, 0x02, 0x87, 0x34, 0x40, + 0x86, 0x02, 0x82, 0x34, 0x40, 0x86, 0x02, 0x69, + 0x14, 0x3e, 0x13, 0x02, 0xd6, 0x39, 0x40, 0x86, + 0x02, 0x68, 0x14, 0xbd, 0x19, 0x02, 0x4b, 0x36, + 0x42, 0x86, 0x02, 0x46, 0x36, 0x42, 0x86, 0x02, + 0x69, 0x34, 0x2c, 0x15, 0x03, 0xb6, 0x36, 0x42, + 0x86, 0xa1, 0x87, 0x02, 0xc4, 0x33, 0x40, 0x86, + 0x02, 0x26, 0x19, 0x40, 0x86, 0x02, 0x69, 0x14, + 0xb0, 0x19, 0x02, 0xde, 0x19, 0x42, 0x86, 0x02, + 0x69, 0x34, 0xa8, 0x13, 0x02, 0xcc, 0x33, 0x42, + 0x86, 0x02, 0x82, 0x34, 0x42, 0x86, 0x02, 0xd1, + 0x19, 0x93, 0x13, 0x02, 0x81, 0x14, 0x42, 0x86, + 0x03, 0xd1, 0x79, 0x30, 0x14, 0xd1, 0x79, 0x02, + 0x68, 0x34, 0xbb, 0x14, 0x02, 0x69, 0x34, 0x95, + 0x86, 0x02, 0xd1, 0x39, 0xbb, 0x14, 0x02, 0x69, + 0x34, 0xeb, 0x13, 0x02, 0xd1, 0x39, 0x84, 0x13, + 0x02, 0x69, 0x34, 0xbc, 0x14, 0x04, 0x69, 0x54, + 0x64, 0x87, 0x8b, 0x14, 0x69, 0x54, 0x02, 0x26, + 0x39, 0x40, 0x86, 0x02, 0xb4, 0x36, 0x40, 0x86, + 0x02, 0x47, 0x16, 0x42, 0x86, 0x02, 0xdc, 0x39, + 0x40, 0x86, 0x02, 0xca, 0x33, 0x40, 0x86, 0x02, + 0xf9, 0x26, 0x40, 0x86, 0x02, 0x69, 0x34, 0x08, + 0x87, 0x03, 0x69, 0x14, 0x69, 0x14, 0x66, 0x14, + 0x03, 0xd1, 0x59, 0x1d, 0x19, 0xd1, 0x59, 0x02, + 0xd4, 0x39, 0x40, 0x86, 0x02, 0xcf, 0x39, 0x40, + 0x86, 0x02, 0x68, 0x34, 0xa4, 0x13, 0x02, 0xd1, + 0x39, 0xa4, 0x13, 0x02, 0xd1, 0x19, 0xa8, 0x13, + 0x02, 0xd7, 0x39, 0x42, 0x86, 0x03, 0x69, 0x34, + 0xbc, 0x19, 0xa1, 0x87, 0x02, 0x68, 0x14, 0xb0, + 0x19, 0x02, 0x3c, 0x39, 0x42, 0x86, 0x02, 0x68, + 0x14, 0x73, 0x13, 0x04, 0x69, 0x14, 0x69, 0x14, + 0x66, 0x14, 0x66, 0x14, 0x03, 0x68, 0x34, 0xaf, + 0x19, 0xa1, 0x87, 0x02, 0x68, 0x34, 0x80, 0x16, + 0x02, 0x73, 0x34, 0x42, 0x86, 0x02, 0xd1, 0x39, + 0x80, 0x16, 0x02, 0x68, 0x34, 0xb0, 0x19, 0x02, + 0x86, 0x34, 0x40, 0x86, 0x02, 0x38, 0x19, 0x42, + 0x86, 0x02, 0x69, 0x34, 0xbb, 0x14, 0x02, 0xb5, + 0x36, 0x42, 0x86, 0x02, 0xcd, 0x39, 0x40, 0x86, + 0x02, 0x68, 0x34, 0x27, 0x15, 0x02, 0x68, 0x34, + 0x95, 0x86, 0x03, 0x68, 0x14, 0x68, 0x14, 0x66, + 0x14, 0x02, 0x71, 0x34, 0x40, 0x86, 0x02, 0xd1, + 0x39, 0x27, 0x15, 0x02, 0x2e, 0x16, 0xa8, 0x14, + 0x02, 0xc3, 0x33, 0x42, 0x86, 0x02, 0x69, 0x14, + 0x66, 0x14, 0x02, 0x68, 0x34, 0x96, 0x86, 0x02, + 0xd1, 0x39, 0x70, 0x1a, 0x03, 0x69, 0x14, 0x64, + 0x87, 0x68, 0x14, 0x02, 0x69, 0x34, 0xa4, 0x13, + 0x02, 0xb8, 0x39, 0x40, 0x86, 0x02, 0x68, 0x34, + 0x3e, 0x13, 0x03, 0xd1, 0x19, 0xaf, 0x19, 0xa1, + 0x87, 0x02, 0xd1, 0x39, 0x3e, 0x13, 0x02, 0x68, + 0x34, 0xbd, 0x19, 0x02, 0xd1, 0x19, 0xbb, 0x14, + 0x02, 0xd1, 0x19, 0x95, 0x86, 0x02, 0xdb, 0x39, + 0x42, 0x86, 0x02, 0x38, 0x39, 0x40, 0x86, 0x02, + 0x69, 0x34, 0x80, 0x16, 0x02, 0x69, 0x14, 0xeb, + 0x13, 0x04, 0x68, 0x14, 0x69, 0x14, 0x67, 0x14, + 0x67, 0x14, 0x02, 0x6f, 0x34, 0x40, 0x86, 0x02, + 0x77, 0x34, 0x42, 0x86, 0x02, 0x46, 0x36, 0x40, + 0x86, 0x02, 0x68, 0x34, 0x92, 0x16, 0x02, 0x4e, + 0x36, 0x42, 0x86, 0x03, 0x69, 0x14, 0xbd, 0x19, + 0xa1, 0x87, 0x02, 0xde, 0x19, 0x40, 0x86, 0x02, + 0x69, 0x34, 0x27, 0x15, 0x03, 0xc3, 0x13, 0x40, + 0x86, 0xa1, 0x87, 0x02, 0x81, 0x14, 0x40, 0x86, + 0x03, 0xd1, 0x39, 0xaf, 0x19, 0xa1, 0x87, 0x02, + 0x68, 0x34, 0xbc, 0x19, 0x02, 0xd1, 0x19, 0x80, + 0x16, 0x02, 0xd9, 0x39, 0x42, 0x86, 0x02, 0xd1, + 0x39, 0xbc, 0x19, 0x02, 0xdc, 0x19, 0x42, 0x86, + 0x02, 0x68, 0x34, 0x73, 0x13, 0x02, 0x69, 0x34, + 0x3e, 0x13, 0x02, 0x47, 0x16, 0x40, 0x86, 0x02, + 0xd1, 0x39, 0xbd, 0x19, 0x02, 0x3e, 0x39, 0x42, + 0x86, 0x02, 0x69, 0x14, 0x95, 0x86, 0x02, 0x68, + 0x14, 0x96, 0x86, 0x03, 0x69, 0x34, 0xbd, 0x19, + 0xa1, 0x87, 0x02, 0xd7, 0x39, 0x40, 0x86, 0x02, + 0x45, 0x16, 0x42, 0x86, 0x02, 0x68, 0x34, 0xed, + 0x13, 0x03, 0x68, 0x34, 0xbc, 0x19, 0xa1, 0x87, + 0x02, 0xd1, 0x39, 0xed, 0x13, 0x02, 0x3c, 0x39, + 0x40, 0x86, 0x02, 0xd1, 0x19, 0x70, 0x1a, 0x02, + 0xd1, 0x39, 0x92, 0x16, 0x02, 0x73, 0x34, 0x40, + 0x86, 0x02, 0x38, 0x19, 0x40, 0x86, 0x02, 0xb5, + 0x36, 0x40, 0x86, 0x02, 0x68, 0x34, 0xaf, 0x19, + 0x02, 0xd1, 0x39, 0xaf, 0x19, 0x02, 0x69, 0x34, + 0xbc, 0x19, 0x02, 0xb6, 0x16, 0x42, 0x86, 0x02, + 0x26, 0x14, 0x25, 0x15, 0x02, 0xc3, 0x33, 0x40, + 0x86, 0x02, 0xdd, 0x39, 0x42, 0x86, 0x02, 0xcb, + 0x93, 0x42, 0x86, 0x02, 0xcb, 0x33, 0x42, 0x86, + 0x02, 0x81, 0x34, 0x42, 0x86, 0x02, 0xce, 0x39, + 0xa1, 0x87, 0x02, 0xdb, 0x39, 0x40, 0x86, 0x02, + 0x68, 0x34, 0x08, 0x87, 0x02, 0xd1, 0x19, 0xb0, + 0x19, 0x02, 0x77, 0x34, 0x40, 0x86, 0x02, 0x4e, + 0x36, 0x40, 0x86, 0x02, 0xce, 0x39, 0x42, 0x86, + 0x02, 0x4e, 0x16, 0x42, 0x86, 0x02, 0xd9, 0x39, + 0x40, 0x86, 0x02, 0xdc, 0x19, 0x40, 0x86, 0x02, + 0x3e, 0x39, 0x40, 0x86, 0x02, 0xb9, 0x39, 0x42, + 0x86, 0x02, 0xda, 0x19, 0x42, 0x86, 0x02, 0x42, + 0x16, 0x94, 0x81, 0x02, 0x45, 0x16, 0x40, 0x86, + 0x02, 0x69, 0x14, 0xbd, 0x19, 0x02, 0x70, 0x34, + 0x42, 0x86, 0x02, 0xce, 0x19, 0xa1, 0x87, 0x02, + 0xc3, 0x13, 0x42, 0x86, 0x02, 0x68, 0x14, 0x08, + 0x87, 0x02, 0xd1, 0x19, 0x7c, 0x13, 0x02, 0x68, + 0x14, 0x92, 0x16, 0x02, 0xb6, 0x16, 0x40, 0x86, + 0x02, 0x37, 0x39, 0x42, 0x86, 0x03, 0xce, 0x19, + 0x42, 0x86, 0xa1, 0x87, 0x03, 0x68, 0x14, 0x67, + 0x14, 0x67, 0x14, 0x02, 0xdd, 0x39, 0x40, 0x86, + 0x02, 0xcf, 0x19, 0x42, 0x86, 0x02, 0xd1, 0x19, + 0x2c, 0x15, 0x02, 0x4b, 0x13, 0xe9, 0x17, 0x02, + 0x68, 0x14, 0x67, 0x14, 0x02, 0xcb, 0x93, 0x40, + 0x86, 0x02, 0x6e, 0x34, 0x42, 0x86, 0x02, 0xcb, + 0x33, 0x40, 0x86, 0x02, 0x81, 0x34, 0x40, 0x86, + 0x02, 0xb6, 0x36, 0xa1, 0x87, 0x02, 0x45, 0x36, + 0x42, 0x86, 0x02, 0xb4, 0x16, 0x42, 0x86, 0x02, + 0x69, 0x14, 0x73, 0x13, 0x04, 0x69, 0x14, 0x69, + 0x14, 0x67, 0x14, 0x66, 0x14, 0x02, 0x35, 0x39, + 0x42, 0x86, 0x02, 0x68, 0x14, 0x93, 0x13, 0x02, + 0xb6, 0x36, 0x42, 0x86, 0x03, 0x68, 0x14, 0x69, + 0x14, 0x66, 0x14, 0x02, 0xce, 0x39, 0x40, 0x86, + 0x02, 0x4e, 0x16, 0x40, 0x86, 0x02, 0x87, 0x34, + 0x42, 0x86, 0x02, 0x86, 0x14, 0x42, 0x86, 0x02, + 0xd6, 0x39, 0x42, 0x86, 0x02, 0xc4, 0x33, 0x42, + 0x86, 0x02, 0x69, 0x34, 0x96, 0x86, 0x02, 0xb9, + 0x39, 0x40, 0x86, 0x02, 0x68, 0x14, 0xa8, 0x13, + 0x02, 0xd1, 0x19, 0x84, 0x13, 0x02, 0xda, 0x19, + 0x40, 0x86, 0x02, 0xd8, 0x19, 0x42, 0x86, 0x02, + 0xc3, 0x13, 0x40, 0x86, 0x02, 0xb9, 0x19, 0x42, + 0x86, 0x02, 0x3d, 0x19, 0x42, 0x86, 0x02, 0xcf, + 0x19, 0x40, 0x86, 0x04, 0x68, 0x14, 0x68, 0x14, + 0x67, 0x14, 0x67, 0x14, 0x03, 0xd1, 0x19, 0xd1, + 0x19, 0xd2, 0x19, 0x02, 0x68, 0x14, 0xbb, 0x14, + 0x02, 0x3b, 0x14, 0x44, 0x87, 0x02, 0xd1, 0x19, + 0x27, 0x15, 0x02, 0xb4, 0x16, 0x40, 0x86, 0x02, + 0xcd, 0x19, 0x42, 0x86, 0x02, 0xd3, 0x86, 0xa5, + 0x14, 0x02, 0x70, 0x14, 0x42, 0x86, 0x03, 0xb6, + 0x16, 0x42, 0x86, 0xa1, 0x87, 0x04, 0x69, 0x14, + 0x64, 0x87, 0x8b, 0x14, 0x69, 0x14, 0x02, 0x36, + 0x16, 0x2b, 0x93, 0x02, 0x68, 0x14, 0x80, 0x16, + 0x02, 0x86, 0x14, 0x40, 0x86, 0x02, 0x08, 0x14, + 0x1b, 0x0b, 0x02, 0xd1, 0x19, 0xbc, 0x19, 0x02, + 0xca, 0x13, 0x42, 0x86, 0x02, 0x41, 0x94, 0xe8, + 0x95, 0x02, 0xd8, 0x19, 0x40, 0x86, 0x02, 0xb9, + 0x19, 0x40, 0x86, 0x02, 0xd1, 0x19, 0xed, 0x13, + 0x02, 0xf9, 0x86, 0x42, 0x86, 0x03, 0xd1, 0x19, + 0xbd, 0x19, 0xa1, 0x87, 0x02, 0x3d, 0x19, 0x40, + 0x86, 0x02, 0xd6, 0x19, 0x42, 0x86, 0x03, 0x69, + 0x14, 0x66, 0x14, 0x66, 0x14, 0x02, 0xd1, 0x19, + 0xaf, 0x19, 0x03, 0x69, 0x14, 0x69, 0x14, 0x67, + 0x14, 0x02, 0xcd, 0x19, 0x40, 0x86, 0x02, 0x70, + 0x14, 0x40, 0x86, 0x03, 0x68, 0x14, 0xbc, 0x19, + 0xa1, 0x87, 0x02, 0x6e, 0x14, 0x42, 0x86, 0x02, + 0x69, 0x14, 0x92, 0x16, 0x03, 0x68, 0x14, 0x68, + 0x14, 0x67, 0x14, 0x02, 0x69, 0x14, 0x67, 0x14, + 0x02, 0x75, 0x95, 0x42, 0x86, 0x03, 0x69, 0x14, + 0x64, 0x87, 0x69, 0x14, 0x02, 0xd1, 0x19, 0xbc, + 0x14, 0x02, 0xdf, 0x19, 0x42, 0x86, 0x02, 0xca, + 0x13, 0x40, 0x86, 0x02, 0x82, 0x14, 0x42, 0x86, + 0x02, 0x69, 0x14, 0x93, 0x13, 0x02, 0x68, 0x14, + 0x7c, 0x13, 0x02, 0xf9, 0x86, 0x40, 0x86, 0x02, + 0xd6, 0x19, 0x40, 0x86, 0x02, 0x68, 0x14, 0x2c, + 0x15, 0x02, 0x69, 0x14, 0xa8, 0x13, 0x02, 0xd4, + 0x19, 0x42, 0x86, 0x04, 0x68, 0x14, 0x69, 0x14, + 0x66, 0x14, 0x66, 0x14, 0x02, 0x77, 0x14, 0x42, + 0x86, 0x02, 0x39, 0x19, 0x42, 0x86, 0x02, 0xd1, + 0x19, 0xa4, 0x13, 0x02, 0x6e, 0x14, 0x40, 0x86, + 0x03, 0xd1, 0x19, 0xd2, 0x19, 0xd2, 0x19, 0x02, + 0x69, 0x14, 0xbb, 0x14, 0x02, 0xd1, 0x19, 0x96, + 0x86, 0x02, 0x75, 0x95, 0x40, 0x86, 0x04, 0x68, + 0x14, 0x64, 0x87, 0x8b, 0x14, 0x68, 0x14, 0x02, + 0xd1, 0x19, 0x3e, 0x13, 0x02, 0xdf, 0x19, 0x40, + 0x86, 0x02, 0x82, 0x14, 0x40, 0x86, 0x02, 0x44, + 0x13, 0xeb, 0x17, 0x02, 0xdd, 0x19, 0x42, 0x86, + 0x03, 0x68, 0x14, 0xaf, 0x19, 0xa1, 0x87, 0x02, + 0x69, 0x14, 0x80, 0x16, 0x02, 0xa3, 0x16, 0x42, + 0x86, 0x02, 0x69, 0x14, 0x96, 0x86, 0x02, 0x46, + 0x16, 0x42, 0x86, 0x02, 0xb6, 0x16, 0xa1, 0x87, + 0x02, 0x68, 0x14, 0x27, 0x15, 0x02, 0x26, 0x14, + 0x1b, 0x0b, 0x02, 0xd4, 0x19, 0x40, 0x86, 0x02, + 0x77, 0x14, 0x40, 0x86, 0x02, 0x39, 0x19, 0x40, + 0x86, 0x02, 0x37, 0x19, 0x42, 0x86, 0x03, 0x69, + 0x14, 0x67, 0x14, 0x66, 0x14, 0x03, 0xc3, 0x13, + 0x42, 0x86, 0xa1, 0x87, 0x02, 0x68, 0x14, 0xbc, + 0x19, 0x02, 0xd1, 0x19, 0xeb, 0x13, 0x04, 0x69, + 0x14, 0x69, 0x14, 0x67, 0x14, 0x67, 0x14, 0x02, + 0xd1, 0x19, 0x08, 0x87, 0x02, 0x68, 0x14, 0xed, + 0x13, 0x03, 0x69, 0x14, 0xbc, 0x19, 0xa1, 0x87, + 0x02, 0xdd, 0x19, 0x40, 0x86, 0x02, 0xc3, 0x13, + 0xa1, 0x87, 0x03, 0x68, 0x14, 0x66, 0x14, 0x66, + 0x14, 0x03, 0x68, 0x14, 0x69, 0x14, 0x67, 0x14, + 0x02, 0xa3, 0x16, 0x40, 0x86, 0x02, 0xdb, 0x19, + 0x42, 0x86, 0x02, 0x68, 0x14, 0xaf, 0x19, 0x02, + 0x46, 0x16, 0x40, 0x86, 0x02, 0x35, 0x16, 0xab, + 0x14, 0x02, 0x68, 0x14, 0x95, 0x86, 0x02, 0x42, + 0x16, 0x95, 0x81, 0x02, 0xc4, 0x13, 0x42, 0x86, + 0x02, 0x15, 0x14, 0xba, 0x19, 0x03, 0xd1, 0x19, + 0x1d, 0x19, 0xd1, 0x19, 0x02, 0x69, 0x14, 0x08, + 0x87, 0x02, 0x69, 0x14, 0x7c, 0x13, 0x02, 0x37, + 0x19, 0x40, 0x86, 0x02, 0x73, 0x14, 0x42, 0x86, + 0x02, 0x69, 0x14, 0x2c, 0x15, 0x02, 0xb5, 0x16, + 0x42, 0x86, 0x02, 0x35, 0x19, 0x42, 0x86, 0x04, + 0x68, 0x14, 0x69, 0x14, 0x67, 0x14, 0x66, 0x14, + 0x02, 0x64, 0x87, 0x25, 0x15, 0x02, 0x64, 0x87, + 0x79, 0x1a, 0x02, 0x68, 0x14, 0xbc, 0x14, 0x03, + 0xce, 0x19, 0x40, 0x86, 0xa1, 0x87, 0x02, 0x87, + 0x14, 0x42, 0x86, 0x02, 0x4d, 0x16, 0x42, 0x86, + 0x04, 0x68, 0x14, 0x68, 0x14, 0x66, 0x14, 0x66, + 0x14, 0x02, 0xdb, 0x19, 0x40, 0x86, 0x02, 0xd9, + 0x19, 0x42, 0x86, 0x02, 0xc4, 0x13, 0x40, 0x86, + 0x02, 0xd1, 0x19, 0xbd, 0x19, 0x02, 0x68, 0x14, + 0xa4, 0x13, 0x02, 0x3e, 0x19, 0x42, 0x86, 0x02, + 0xf3, 0x93, 0xa7, 0x86, 0x03, 0x69, 0x14, 0xaf, + 0x19, 0xa1, 0x87, 0x02, 0xf3, 0x93, 0x08, 0x13, + 0x02, 0xd1, 0x19, 0xd2, 0x19, 0x02, 0x73, 0x14, + 0x40, 0x86, 0x02, 0xb5, 0x16, 0x40, 0x86, 0x02, + 0x35, 0x19, 0x40, 0x86, 0x02, 0x69, 0x14, 0x27, + 0x15, 0x02, 0xce, 0x19, 0x42, 0x86, 0x02, 0x71, + 0x14, 0x42, 0x86, 0x02, 0xd1, 0x19, 0x73, 0x13, + 0x02, 0x68, 0x14, 0x3e, 0x13, 0x02, 0xf4, 0x13, + 0x20, 0x86, 0x02, 0x87, 0x14, 0x40, 0x86, 0x03, + 0xb6, 0x16, 0x40, 0x86, 0xa1, 0x87, 0x02, 0x4d, + 0x16, 0x40, 0x86, 0x02, 0x69, 0x14, 0xbc, 0x19, + 0x02, 0x4b, 0x16, 0x42, 0x86, 0x02, 0xd9, 0x19, + 0x40, 0x86, 0x02, 0x3e, 0x19, 0x40, 0x86, 0x02, + 0x69, 0x14, 0xed, 0x13, 0x02, 0xd7, 0x19, 0x42, + 0x86, 0x02, 0xb8, 0x19, 0x42, 0x86, 0x03, 0x68, + 0x14, 0x67, 0x14, 0x66, 0x14, 0x02, 0x3c, 0x19, + 0x42, 0x86, 0x02, 0x68, 0x14, 0x66, 0x14, 0x03, + 0x68, 0x14, 0x64, 0x87, 0x68, 0x14, 0x02, 0x69, + 0x14, 0xaf, 0x19, 0x02, 0xce, 0x19, 0x40, 0x86, + 0x02, 0x71, 0x14, 0x40, 0x86, 0x02, 0x68, 0x14, + 0xeb, 0x13, 0x03, 0x68, 0x14, 0xbd, 0x19, 0xa1, + 0x87, 0x02, 0x6f, 0x14, 0x42, 0x86, 0x04, 0xd1, + 0x19, 0xd1, 0x19, 0xd2, 0x19, 0xd2, 0x19, 0x02, + 0x69, 0x14, 0xbc, 0x14, 0x02, 0xcc, 0x93, 0x42, + 0x86, 0x02, 0x4b, 0x16, 0x40, 0x86, 0x02, 0x26, + 0x19, 0x42, 0x86, 0x02, 0xd7, 0x19, 0x40, 0x86, +}; diff --git a/deps/quickjs/libunicode.c b/deps/quickjs/libunicode.c index 09a76a7..ecba971 100644 --- a/deps/quickjs/libunicode.c +++ b/deps/quickjs/libunicode.c @@ -492,6 +492,9 @@ int cr_op(CharRange *cr, const uint32_t *a_pt, int a_len, case CR_OP_XOR: is_in = (a_idx & 1) ^ (b_idx & 1); break; + case CR_OP_SUB: + is_in = (a_idx & 1) & ((b_idx & 1) ^ 1); + break; default: abort(); } @@ -504,14 +507,14 @@ int cr_op(CharRange *cr, const uint32_t *a_pt, int a_len, return 0; } -int cr_union1(CharRange *cr, const uint32_t *b_pt, int b_len) +int cr_op1(CharRange *cr, const uint32_t *b_pt, int b_len, int op) { CharRange a = *cr; int ret; cr->len = 0; cr->size = 0; cr->points = NULL; - ret = cr_op(cr, a.points, a.len, b_pt, b_len, CR_OP_UNION); + ret = cr_op(cr, a.points, a.len, b_pt, b_len, op); cr_free(&a); return ret; } @@ -552,6 +555,101 @@ bool lre_is_white_space(uint32_t c) sizeof(unicode_prop_White_Space_index) / 3); } +/*---- lre codepoint categorizing functions ----*/ + +#define S UNICODE_C_SPACE +#define D UNICODE_C_DIGIT +#define X UNICODE_C_XDIGIT +#define U UNICODE_C_UPPER +#define L UNICODE_C_LOWER +#define _ UNICODE_C_UNDER +#define d UNICODE_C_DOLLAR + +uint8_t const lre_ctype_bits[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, S, S, S, S, S, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + S, 0, 0, 0, d, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + X|D, X|D, X|D, X|D, X|D, X|D, X|D, X|D, + X|D, X|D, 0, 0, 0, 0, 0, 0, + + 0, X|U, X|U, X|U, X|U, X|U, X|U, U, + U, U, U, U, U, U, U, U, + U, U, U, U, U, U, U, U, + U, U, U, 0, 0, 0, 0, _, + + 0, X|L, X|L, X|L, X|L, X|L, X|L, L, + L, L, L, L, L, L, L, L, + L, L, L, L, L, L, L, L, + L, L, L, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + S, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +#undef S +#undef D +#undef X +#undef U +#undef L +#undef _ +#undef d + +/* code point ranges for Zs,Zl or Zp property */ +static const uint16_t char_range_space[] = { + 10, + 0x0009, 0x000D + 1, + 0x0020, 0x0020 + 1, + 0x00A0, 0x00A0 + 1, + 0x1680, 0x1680 + 1, + 0x2000, 0x200A + 1, + /* 2028;LINE SEPARATOR;Zl;0;WS;;;;;N;;;;; */ + /* 2029;PARAGRAPH SEPARATOR;Zp;0;B;;;;;N;;;;; */ + 0x2028, 0x2029 + 1, + 0x202F, 0x202F + 1, + 0x205F, 0x205F + 1, + 0x3000, 0x3000 + 1, + /* FEFF;ZERO WIDTH NO-BREAK SPACE;Cf;0;BN;;;;;N;BYTE ORDER MARK;;;; */ + 0xFEFF, 0xFEFF + 1, +}; + +int lre_is_space_non_ascii(uint32_t c) +{ + size_t i, n; + + n = countof(char_range_space); + for(i = 5; i < n; i += 2) { + uint32_t low = char_range_space[i]; + uint32_t high = char_range_space[i + 1]; + if (c < low) + return false; + if (c < high) + return true; + } + return false; +} + + #define UNICODE_DECOMP_LEN_MAX 18 typedef enum { @@ -1062,11 +1160,17 @@ int unicode_script(CharRange *cr, CharRange cr2_s = { 0 }, *cr2 = &cr2_s; bool is_common; - script_idx = unicode_find_name(unicode_script_name_table, script_name); - if (script_idx < 0) - return -2; - /* Note: we remove the "Unknown" Script */ - script_idx += UNICODE_SCRIPT_Unknown + 1; + if (!strcmp(script_name, "Unknown") || !strcmp(script_name, "Zzzz")) { + /* "Unknown" (ISO 15924 code "Zzzz") is excluded from the name table; + it matches every character outside any script. */ + script_idx = UNICODE_SCRIPT_Unknown; + } else { + script_idx = unicode_find_name(unicode_script_name_table, script_name); + if (script_idx < 0) + return -2; + /* Note: the name table excludes the "Unknown" Script */ + script_idx += UNICODE_SCRIPT_Unknown + 1; + } is_common = (script_idx == UNICODE_SCRIPT_Common || script_idx == UNICODE_SCRIPT_Inherited); @@ -1101,13 +1205,22 @@ int unicode_script(CharRange *cr, else v = *p++; c1 = c + n + 1; - if (v == script_idx) { + /* only script-bearing ranges (type != 0); for Unknown, match every + such range and invert afterwards */ + if (type != 0 && + (v == script_idx || script_idx == UNICODE_SCRIPT_Unknown)) { if (cr_add_interval(cr1, c, c1)) goto fail; } c = c1; } + if (script_idx == UNICODE_SCRIPT_Unknown) { + /* Unknown is all the characters outside scripts */ + if (cr_invert(cr1)) + goto fail; + } + if (is_ext) { /* add the script extensions */ p = unicode_script_ext_table; @@ -1586,6 +1699,216 @@ int unicode_general_category(CharRange *cr, const char *gc_name) /* 'cr' must be initialized and empty. Return 0 if OK, -1 if error, -2 if not found */ +/* Unicode "properties of strings" (e.g. \p{RGI_Emoji}) used by the v flag; + expands a string property into a list of code-point sequences via the + callback. Returns -2 if the property name is unknown. */ +#define SEQ_MAX_LEN 16 + +static int unicode_sequence_prop1(int seq_prop_idx, UnicodeSequencePropCB *cb, void *opaque, + CharRange *cr) +{ + int i, c, j; + uint32_t seq[SEQ_MAX_LEN]; + + switch(seq_prop_idx) { + case UNICODE_SEQUENCE_PROP_Basic_Emoji: + if (unicode_prop1(cr, UNICODE_PROP_Basic_Emoji1) < 0) + return -1; + for(i = 0; i < cr->len; i += 2) { + for(c = cr->points[i]; c < cr->points[i + 1]; c++) { + seq[0] = c; + cb(opaque, seq, 1); + } + } + + cr->len = 0; + + if (unicode_prop1(cr, UNICODE_PROP_Basic_Emoji2) < 0) + return -1; + for(i = 0; i < cr->len; i += 2) { + for(c = cr->points[i]; c < cr->points[i + 1]; c++) { + seq[0] = c; + seq[1] = 0xfe0f; + cb(opaque, seq, 2); + } + } + + break; + case UNICODE_SEQUENCE_PROP_RGI_Emoji_Modifier_Sequence: + if (unicode_prop1(cr, UNICODE_PROP_Emoji_Modifier_Base) < 0) + return -1; + for(i = 0; i < cr->len; i += 2) { + for(c = cr->points[i]; c < cr->points[i + 1]; c++) { + for(j = 0; j < 5; j++) { + seq[0] = c; + seq[1] = 0x1f3fb + j; + cb(opaque, seq, 2); + } + } + } + break; + case UNICODE_SEQUENCE_PROP_RGI_Emoji_Flag_Sequence: + if (unicode_prop1(cr, UNICODE_PROP_RGI_Emoji_Flag_Sequence) < 0) + return -1; + for(i = 0; i < cr->len; i += 2) { + for(c = cr->points[i]; c < cr->points[i + 1]; c++) { + int c0, c1; + c0 = c / 26; + c1 = c % 26; + seq[0] = 0x1F1E6 + c0; + seq[1] = 0x1F1E6 + c1; + cb(opaque, seq, 2); + } + } + break; + case UNICODE_SEQUENCE_PROP_RGI_Emoji_ZWJ_Sequence: + { + int len, code, pres, k, mod, mod_count, mod_pos[2], hc_pos, n_mod, n_hc, mod1; + int mod_idx, hc_idx, i0, i1; + const uint8_t *tab = unicode_rgi_emoji_zwj_sequence; + + for(i = 0; i < countof(unicode_rgi_emoji_zwj_sequence);) { + len = tab[i++]; + k = 0; + mod = 0; + mod_count = 0; + hc_pos = -1; + for(j = 0; j < len; j++) { + code = tab[i++]; + code |= tab[i++] << 8; + pres = code >> 15; + mod1 = (code >> 13) & 3; + code &= 0x1fff; + if (code < 0x1000) { + c = code + 0x2000; + } else { + c = 0x1f000 + (code - 0x1000); + } + if (c == 0x1f9b0) + hc_pos = k; + seq[k++] = c; + if (mod1 != 0) { + assert(mod_count < 2); + mod = mod1; + mod_pos[mod_count++] = k; + seq[k++] = 0; /* will be filled later */ + } + if (pres) { + seq[k++] = 0xfe0f; + } + if (j < len - 1) { + seq[k++] = 0x200d; + } + } + + /* genrate all the variants */ + switch(mod) { + case 1: + n_mod = 5; + break; + case 2: + n_mod = 25; + break; + case 3: + n_mod = 20; + break; + default: + n_mod = 1; + break; + } + if (hc_pos >= 0) + n_hc = 4; + else + n_hc = 1; + for(hc_idx = 0; hc_idx < n_hc; hc_idx++) { + for(mod_idx = 0; mod_idx < n_mod; mod_idx++) { + if (hc_pos >= 0) + seq[hc_pos] = 0x1f9b0 + hc_idx; + + switch(mod) { + case 1: + seq[mod_pos[0]] = 0x1f3fb + mod_idx; + break; + case 2: + case 3: + i0 = mod_idx / 5; + i1 = mod_idx % 5; + /* avoid identical values */ + if (mod == 3 && i0 >= i1) + i0++; + seq[mod_pos[0]] = 0x1f3fb + i0; + seq[mod_pos[1]] = 0x1f3fb + i1; + break; + default: + break; + } +#if 0 + for(j = 0; j < k; j++) + printf(" %04x", seq[j]); + printf("\n"); +#endif + cb(opaque, seq, k); + } + } + } + } + break; + case UNICODE_SEQUENCE_PROP_RGI_Emoji_Tag_Sequence: + { + for(i = 0; i < countof(unicode_rgi_emoji_tag_sequence);) { + j = 0; + seq[j++] = 0x1F3F4; + for(;;) { + c = unicode_rgi_emoji_tag_sequence[i++]; + if (c == 0x00) + break; + seq[j++] = 0xe0000 + c; + } + seq[j++] = 0xe007f; + cb(opaque, seq, j); + } + } + break; + case UNICODE_SEQUENCE_PROP_Emoji_Keycap_Sequence: + if (unicode_prop1(cr, UNICODE_PROP_Emoji_Keycap_Sequence) < 0) + return -1; + for(i = 0; i < cr->len; i += 2) { + for(c = cr->points[i]; c < cr->points[i + 1]; c++) { + seq[0] = c; + seq[1] = 0xfe0f; + seq[2] = 0x20e3; + cb(opaque, seq, 3); + } + } + break; + case UNICODE_SEQUENCE_PROP_RGI_Emoji: + /* all prevous sequences */ + for(i = UNICODE_SEQUENCE_PROP_Basic_Emoji; i <= UNICODE_SEQUENCE_PROP_RGI_Emoji_ZWJ_Sequence; i++) { + int ret; + ret = unicode_sequence_prop1(i, cb, opaque, cr); + if (ret < 0) + return ret; + cr->len = 0; + } + break; + default: + return -2; + } + return 0; +} + +/* build a unicode sequence property */ +/* return -2 if not found, -1 if other error. 'cr' is used as temporary memory. */ +int unicode_sequence_prop(const char *prop_name, UnicodeSequencePropCB *cb, void *opaque, + CharRange *cr) +{ + int seq_prop_idx; + seq_prop_idx = unicode_find_name(unicode_sequence_prop_name_table, prop_name); + if (seq_prop_idx < 0) + return -2; + return unicode_sequence_prop1(seq_prop_idx, cb, opaque, cr); +} + int unicode_prop(CharRange *cr, const char *prop_name) { int prop_idx, ret; diff --git a/deps/quickjs/libunicode.h b/deps/quickjs/libunicode.h index 8e6f2a0..66c0b38 100644 --- a/deps/quickjs/libunicode.h +++ b/deps/quickjs/libunicode.h @@ -60,6 +60,7 @@ typedef enum { CR_OP_UNION, CR_OP_INTER, CR_OP_XOR, + CR_OP_SUB, } CharRangeOpEnum; void cr_init(CharRange *cr, void *mem_opaque, void *(*realloc_func)(void *opaque, void *ptr, size_t size)); @@ -88,14 +89,14 @@ static inline int cr_add_interval(CharRange *cr, uint32_t c1, uint32_t c2) return 0; } -int cr_union1(CharRange *cr, const uint32_t *b_pt, int b_len); +int cr_op1(CharRange *cr, const uint32_t *b_pt, int b_len, int op); 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); + return cr_op1(cr, b_pt, 2, CR_OP_UNION); } int cr_op(CharRange *cr, const uint32_t *a_pt, int a_len, @@ -119,6 +120,51 @@ int unicode_script(CharRange *cr, int unicode_general_category(CharRange *cr, const char *gc_name); int unicode_prop(CharRange *cr, const char *prop_name); +typedef void UnicodeSequencePropCB(void *opaque, const uint32_t *buf, int len); +int unicode_sequence_prop(const char *prop_name, UnicodeSequencePropCB *cb, void *opaque, + CharRange *cr); + +/* Code point type categories (ASCII fast path table) */ +enum { + UNICODE_C_SPACE = (1 << 0), + UNICODE_C_DIGIT = (1 << 1), + UNICODE_C_UPPER = (1 << 2), + UNICODE_C_LOWER = (1 << 3), + UNICODE_C_UNDER = (1 << 4), + UNICODE_C_DOLLAR = (1 << 5), + UNICODE_C_XDIGIT = (1 << 6), +}; +extern uint8_t const lre_ctype_bits[256]; + +static inline int lre_is_space_byte(uint8_t c) { + return lre_ctype_bits[c] & UNICODE_C_SPACE; +} + +static inline int lre_is_id_start_byte(uint8_t c) { + return lre_ctype_bits[c] & (UNICODE_C_UPPER | UNICODE_C_LOWER | + UNICODE_C_UNDER | UNICODE_C_DOLLAR); +} + +static inline int lre_is_id_continue_byte(uint8_t c) { + return lre_ctype_bits[c] & (UNICODE_C_UPPER | UNICODE_C_LOWER | + UNICODE_C_UNDER | UNICODE_C_DOLLAR | + UNICODE_C_DIGIT); +} + +static inline int lre_is_word_byte(uint8_t c) { + return lre_ctype_bits[c] & (UNICODE_C_UPPER | UNICODE_C_LOWER | + UNICODE_C_UNDER | UNICODE_C_DIGIT); +} + +int lre_is_space_non_ascii(uint32_t c); + +static inline int lre_is_space(uint32_t c) { + if (c < 256) + return lre_is_space_byte(c); + else + return lre_is_space_non_ascii(c); +} + #ifdef __cplusplus } /* extern "C" { */ #endif diff --git a/deps/quickjs/lre-test.c b/deps/quickjs/lre-test.c index 3285db9..6f57188 100644 --- a/deps/quickjs/lre-test.c +++ b/deps/quickjs/lre-test.c @@ -6,6 +6,12 @@ #include #include "libregexp.h" +// If >= 0, the next 'alloc_countdown' allocations succeed and the one after +// that fails. Used to inject out-of-memory conditions in the compiler. +// When alloc_fail_persist is true, every subsequent allocation fails too. +static int alloc_countdown = -1; +static bool alloc_fail_persist; + bool lre_check_stack_overflow(void *opaque, size_t alloca_size) { return false; @@ -22,6 +28,14 @@ void *lre_realloc(void *opaque, void *ptr, size_t size) free(ptr); return NULL; } + if (alloc_countdown >= 0) { + if (alloc_countdown == 0) { + if (!alloc_fail_persist) + alloc_countdown = -1; + return NULL; + } + alloc_countdown--; + } return realloc(ptr, size); } @@ -33,11 +47,11 @@ static void oob_save_index(void) uint8_t bc[] = { 0x00, 0x00, // RE_HEADER_FLAGS = 0 0x01, // RE_HEADER_CAPTURE_COUNT = 1 - 0x00, // RE_HEADER_STACK_SIZE = 0 + 0x00, // RE_HEADER_REGISTER_COUNT = 0 0x04, 0x00, 0x00, 0x00, // RE_HEADER_BYTECODE_LEN = 4 (little-endian) - 0x05, // REOP_any - 0x0C, 0x64, // REOP_save_start, index=100 - 0x0B, // REOP_match + 0x06, // REOP_any + 0x13, 0x64, // REOP_save_start, index=100 + 0x10, // REOP_match }; uint8_t *capture[2] = {NULL, NULL}; @@ -45,8 +59,54 @@ static void oob_save_index(void) assert(ret < 0); } +static void oom_no_oob_write(void) +{ + static const struct { + const char *prefix; + const char *suffix; + int flags; + } templates[] = { + { "", "|b", 0 }, + { "", "*b", 0 }, + { "", "{2,4}b", 0 }, + { "(", "|b)", 0 }, + { "(?:", "|b){2,7}c", 0 }, + { "(?=", "|b)c", 0 }, + { "(?<=", "|b)c", 0 }, + { "[\\q{", "|bc}]", LRE_FLAG_UNICODE_SETS }, + }; + char pattern[128], error_msg[128]; + size_t i, prefix_len; + int k, n, len, persist; + uint8_t *bc; + + for (i = 0; i < sizeof(templates) / sizeof(templates[0]); i++) { + prefix_len = strlen(templates[i].prefix); + for (k = 0; k < 64; k++) { + memcpy(pattern, templates[i].prefix, prefix_len); + memset(pattern + prefix_len, 'a', k); + strcpy(pattern + prefix_len + k, templates[i].suffix); + for (n = 0; n < 128; n++) { + for (persist = 0; persist < 2; persist++) { + alloc_fail_persist = persist; + alloc_countdown = n; + error_msg[0] = '\0'; + bc = lre_compile(&len, error_msg, sizeof(error_msg), + pattern, strlen(pattern), + templates[i].flags, NULL); + alloc_countdown = -1; + // Failure must always come with an error message. + assert(bc || error_msg[0] != '\0'); + lre_realloc(NULL, bc, 0); + } + } + } + } +} + int main(void) { oob_save_index(); + oom_no_oob_write(); return 0; } diff --git a/deps/quickjs/meson.build b/deps/quickjs/meson.build index b7b1638..2a85267 100644 --- a/deps/quickjs/meson.build +++ b/deps/quickjs/meson.build @@ -1,10 +1,12 @@ project( 'quickjs-ng', 'c', - version: '0.15.1', + version: '0.16.0', default_options: [ 'c_std=gnu11,c11', 'warning_level=3', + 'buildtype=release', + 'b_ndebug=if-release', ], license: 'MIT', license_files: 'LICENSE', diff --git a/deps/quickjs/qjs.c b/deps/quickjs/qjs.c index bdf8d2d..9653391 100644 --- a/deps/quickjs/qjs.c +++ b/deps/quickjs/qjs.c @@ -45,16 +45,23 @@ extern const uint32_t qjsc_repl_size; extern const uint8_t qjsc_standalone[]; extern const uint32_t qjsc_standalone_size; +#if defined(EMSCRIPTEN) || defined(__wasi__) +// Standalone executables (the --compile option and detecting/running an +// executable with appended bytecode) can't work in these environments. +#define emscripten_or_wasi 1 +#else +#define emscripten_or_wasi 0 +#endif + +static int qjs__argc; +static char **qjs__argv; + // 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"); @@ -386,13 +393,15 @@ void help(int exit_status) " --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" + "-D --dump-flags flags for dumping debug data (see DUMP_* defines)\n", + JS_GetVersion()); + if (!emscripten_or_wasi) + printf("-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"); + printf(" --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()); + "-q --quit just instantiate the interpreter and quit\n"); exit(exit_status); } @@ -400,18 +409,18 @@ 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; + JSValue ret = JS_UNDEFINED; 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; + char *expr = NULL; + char *dump_flags_str = NULL; int interactive = 0; int dump_memory = 0; int dump_flags = 0; @@ -429,8 +438,8 @@ int main(int argc, char **argv) qjs__argv = argv; /* check if this is a standalone executable */ - - if (!js_exepath(exebuf, &exebuf_size) && is_standalone(exebuf)) { + if (!emscripten_or_wasi && + !js_exepath(exebuf, &exebuf_size) && is_standalone(exebuf)) { standalone = 1; goto start; } @@ -549,7 +558,8 @@ int main(int argc, char **argv) stack_size = parse_limit(optarg); break; } - if (opt == 'c' || !strcmp(longopt, "compile")) { + if (!emscripten_or_wasi && + (opt == 'c' || !strcmp(longopt, "compile"))) { if (!optarg) { if (optind >= argc) { fprintf(stderr, "qjs: missing file for -c\n"); @@ -560,7 +570,7 @@ int main(int argc, char **argv) compile_file = optarg; break; } - if (opt == 'o' || !strcmp(longopt, "out")) { + if (!emscripten_or_wasi && (opt == 'o' || !strcmp(longopt, "out"))) { if (!optarg) { if (optind >= argc) { fprintf(stderr, "qjs: missing file for -o\n"); @@ -571,7 +581,7 @@ int main(int argc, char **argv) out = optarg; break; } - if (!strcmp(longopt, "exe")) { + if (!emscripten_or_wasi && !strcmp(longopt, "exe")) { if (!optarg) { if (optind >= argc) { fprintf(stderr, "qjs: missing file for --exe\n"); @@ -591,7 +601,7 @@ int main(int argc, char **argv) } } - if (compile_file && !out) + if (!emscripten_or_wasi && compile_file && !out) help(1); start: diff --git a/deps/quickjs/qjs.man b/deps/quickjs/qjs.man new file mode 100644 index 0000000..5672a52 --- /dev/null +++ b/deps/quickjs/qjs.man @@ -0,0 +1,90 @@ +.TH QJS 1 "2026-07-22" +.SH NAME +qjs - QuickJS-NG JavaScript interpreter + +.SH SYNOPSIS +.SY qjs +.RI [ OPTION ].\|.\|.\& +.RI [ FILE " [" ARGUMENT ].\|.\|.] +.YS + +.SH DESCRIPTION +QuickJS-NG is a small and embeddable JavaScript engine. +It aims to support the latest ECMAScript specification. +.PP +The \fBqjs\fR executable runs the JavaScript interpreter. +It includes a simple standard library and REPL. + +.SH OPTIONS +.TP +.B \-c\fR,\fP \-\-compile +Compile \fIFILE\fR into a standalone executable, bundling the interpreter and the script. + +.TP +.B \-C\fR,\fP \-\-script +Load \fIFILE\fR as a classic JavaScript script. +By default, \fBqjs\fR will try to detect if \fIFILE\fR is a JS script or an ES module. + +.TP +.B \-d\fR,\fP \-\-dump +Dump memory usage statistics. + +.TP +\fB\-D \fIFLAGS\fR, \fB\-\-dump-flags\fR=\fIFLAGS\fR +Specify debug dump flags. +These can also be set through the \fBQJS_DUMP_FLAGS\fR environment variable. + +.TP +\fB\-e\fR \fIEXPR\fR, \fB\-\-eval\fR \fIEXPR\fR +Evaluate \fIEXPR\fR and exit. + +.TP +.B \-h\fR,\fP \-\-help +Print a help message and exit. + +.TP +.B \-i\fR,\fP \-\-interactive +Enter interactive mode. This is the default if no \fIFILE\fR is provided. + +.TP +\fB\-I\fR \fIIFILE\fR, \fB\-\-include\fR \fIIFILE\fR +Include an additional file. + +.TP +.BI \-\-memory\-limit " N" +Limit memory usage to \fIN\fR Kbytes. + +.TP +.B \-m\fR,\fP \-\-module +Load \fIFILE\fR as an ECMAScript module. +By default, \fBqjs\fR will try to detect if \fIFILE\fR is a JS script or an ES module. + +.TP +\fB\-\-o\fR \fIOUTPUT\fR, \fB\-\-out\fR \fIOUTPUT\fR +Output file name when creating a standalone executable with \fB\-c\fR. + +.TP +.BI \-\-stack\-size " N" +Limit the stack size to \fIN\fR Kbytes. + +.TP +.B \-\-std +Make \fI'std'\fR, \fI'os'\fR and \fI'bjson'\fR available to the script. + +.TP +.B \-T\fR,\fP \-\-trace +Trace memory allocation. + +.TP +.B \-v\fR,\fP \-\-version +Print version string and exit. + +.TP +.B \-q\fR,\fP \-\-quit +Instantiate the interpreter and immediately exit. + +.SH SEE ALSO +.SS "Man pages" +.BR qjsc (1) +.SS "Online documentation" +Detailed documentation about the project can be found at: https://quickjs-ng.github.io/quickjs/ diff --git a/deps/quickjs/qjsc.man b/deps/quickjs/qjsc.man new file mode 100644 index 0000000..1b61a1e --- /dev/null +++ b/deps/quickjs/qjsc.man @@ -0,0 +1,78 @@ +.TH QJSC 1 "2026-07-22" +.SH NAME +qjsc - QuickJS-NG bytecode compiler + +.SH SYNOPSIS +.SY qjsc +.RI [ OPTION ].\|.\|.\& +.RI [ FILE ].\|.\|. +.YS + +.SH DESCRIPTION +QuickJS-NG is a small and embeddable JavaScript engine. +It aims to support the latest ECMAScript specification. +.PP +The \fBqjsc\fR 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. + +.SH OPTIONS +.TP +.B \-b +Output raw bytecode instead of C code. + +.TP +.B \-C +Compile as classic JavaScript script. +By default, \fBqjsc\fR will try to detect if each \fIFILE\fR is a JS script or an ES module. + +.TP +.BI \-D " MODULE_NAME" +Compile a dynamically loaded module or worker. + +.TP +.B \-e +Output \fBmain()\fR and bytecode in a C file. + +.TP +.B \-m +Compile as ECMAScript module. +By default, \fBqjsc\fR will try to detect if each \fIFILE\fR is a JS script or an ES module. + +.TP +\fB\-M\fR \fIMODULE_NAME\fR[,\fICNAME\fR] +Add initialization code for an external C module. + +.TP +.BI \-n " SCRIPT_NAME" +Set the script name (as used in stack traces). + +.TP +.BI \-N " CNAME" +Set the C name of the generated data. + +.TP +.BI \-o " OUTPUT" +Set the output filename. + +.TP +.BI \-p " PREFIX" +Add a prefix to generated C names. + +.TP +.B \-P +Do not add default system modules. + +.TP +.B \-s +Strip the source code. Specify this option twice to also strip debug info. + +.TP +.BI \-S " N" +Set the maximum stack size to \fIN\fR bytes (default is 1 048 576). + +.SH SEE ALSO +.SS "Man pages" +.BR qjs (1) +.SS "Online documentation" +Detailed documentation about the project can be found at: https://quickjs-ng.github.io/quickjs/ diff --git a/deps/quickjs/quickjs-libc.c b/deps/quickjs/quickjs-libc.c index 6926733..772b912 100644 --- a/deps/quickjs/quickjs-libc.c +++ b/deps/quickjs/quickjs-libc.c @@ -528,8 +528,12 @@ static int get_bool_option(JSContext *ctx, bool *pbool, return 0; } -static void free_buf(JSRuntime *rt, void *opaque, void *ptr) { - js_free_rt(rt, ptr); +// js_realloc_array_buffer to avoid a name conflict with +// js_array_buffer_realloc from quickjs.c in the amalgamation build +static void *js_realloc_array_buffer(JSRuntime *rt, void *opaque, void *ptr, + size_t size) +{ + return js_realloc_rt(rt, ptr, size); } /* load a file as a UTF-8 encoded string or Uint8Array */ @@ -558,7 +562,8 @@ static JSValue js_std_loadFile(JSContext *ctx, JSValueConst this_val, if (!buf) return JS_NULL; if (binary) { - ret = JS_NewUint8Array(ctx, buf, buf_len, free_buf, NULL, false); + ret = JS_NewUint8Array(ctx, buf, buf_len, js_realloc_array_buffer, + NULL, false); } else { ret = JS_NewStringLen(ctx, (char *)buf, buf_len); js_free(ctx, buf); @@ -829,13 +834,6 @@ int js_module_check_attributes(JSContext *ctx, void *opaque, return ret; } -// js_free_array_buffer to avoid a name conflict with js_array_buffer_free -// from quickjs.c in the amalgamation build -static void js_free_array_buffer(JSRuntime *rt, void *opaque, void *ptr) -{ - js_free_rt(rt, ptr); -} - enum { JS_IMPORT_TYPE_JS, JS_IMPORT_TYPE_JSON, @@ -892,7 +890,9 @@ JSModuleDef *js_module_load(JSContext *ctx, const char *module_name, type = js_module_import_type(ctx, attributes); if (type < 0) return NULL; - if (type != JS_IMPORT_TYPE_BYTES) + /* the .json suffix only selects the JSON type when no type attribute + was given, so that e.g. 'with { type: "text" }' is honored */ + if (type == JS_IMPORT_TYPE_JS) if (js__has_suffix(module_name, ".json")) type = JS_IMPORT_TYPE_JSON; buf = (char *)load_file(ctx, &buf_len, module_name); @@ -914,7 +914,8 @@ JSModuleDef *js_module_load(JSContext *ctx, const char *module_name, break; case JS_IMPORT_TYPE_BYTES: val = JS_NewUint8Array(ctx, (uint8_t *)buf, buf_len, - js_free_array_buffer, NULL, /*is_shared*/false); + js_realloc_array_buffer, NULL, + /*is_shared*/false); if (!JS_IsException(val)) { JSValue abuf = JS_GetTypedArrayBuffer(ctx, val, NULL, NULL, NULL); JS_SetImmutableArrayBuffer(abuf, /*immutable*/true); diff --git a/deps/quickjs/quickjs.c b/deps/quickjs/quickjs.c index 11caae0..53ef173 100644 --- a/deps/quickjs/quickjs.c +++ b/deps/quickjs/quickjs.c @@ -256,6 +256,63 @@ typedef struct JSMallocState { void *opaque; /* user opaque */ } JSMallocState; +/* Small-block "arena" allocator. + js_{malloc,free,realloc,calloc}_rt serve allocations up to ~512 + bytes from size-classed 4KB arenas carved out of the underlying + JSMallocFunctions allocator, so the backing allocator (system malloc, + mimalloc, ...) sees roughly one request per arena refill instead of one per + object. */ + +#define JS_ARENA_ALIGN 8 +#define JS_ARENA_SIZE 4096 +#define JS_ARENA_BLOCK_SIZE_COUNT 31 +#define JS_ARENA_MAX_SMALL_SIZE 512 +#define JS_ARENA_FREE_NIL 0xffff + +#if defined(__SANITIZE_ADDRESS__) || defined(FORCE_GC_AT_MALLOC) +/* Route every allocation through the backing malloc so each block is seen + individually: ASan can then poison a freed block, and a GC-stress build + (FORCE_GC_AT_MALLOC) exposes prematurely-freed objects instead of the pool + silently recycling them. */ +#define JS_ARENA_LARGE_BLOCKS_ONLY 1 +#else +#define JS_ARENA_LARGE_BLOCKS_ONLY 0 +#endif + +/* 8-byte header preceding every user allocation. It carries the allocator + bookkeeping (block_idx/free_next + block_size_idx) and, the + GC/refcount fields (gc_obj_type/mark/ref_count) that would otherwise sit in + the object body. The 8-byte size keeps user_data JS_ARENA_ALIGN-aligned. */ +typedef struct JSMallocBlockHeader { + union { + uint16_t block_idx; /* JS_ARENA_FREE_NIL => large or zero-size block */ + uint16_t free_next; /* next free block index while on a free list */ + } u; + uint8_t block_size_idx; + /* GC/refcount header merged into the allocator header: + the object body keeps only JSGCObjectHeader.link (no ref_count/flags). */ + uint8_t gc_obj_type : 7; /* JSGCObjectTypeEnum for GC objects */ + uint8_t mark : 1; /* used by the cycle collector */ + int ref_count; + _Alignas(JS_ARENA_ALIGN) uint8_t user_data[]; +} JSMallocBlockHeader; + +typedef struct JSArena { + struct list_head free_link; /* in free_arena_list[idx] while not full */ + struct list_head link; /* in arena_list[idx] for the whole lifetime */ + uint8_t block_size_idx; + uint16_t n_used_blocks; + uint16_t n_blocks; + uint16_t first_free_block; /* JS_ARENA_FREE_NIL if none */ + _Alignas(JS_ARENA_ALIGN) uint8_t blocks[]; +} JSArena; + +typedef struct JSArenaState { + struct list_head arena_list[JS_ARENA_BLOCK_SIZE_COUNT]; + struct list_head free_arena_list[JS_ARENA_BLOCK_SIZE_COUNT]; + _Alignas(JS_ARENA_ALIGN) uint8_t zero_size_block[sizeof(JSMallocBlockHeader)]; +} JSArenaState; + typedef struct JSRuntimeFinalizerState { struct JSRuntimeFinalizerState *next; JSRuntimeFinalizer *finalizer; @@ -270,6 +327,7 @@ typedef struct JSValueLink { struct JSRuntime { JSMallocFunctions mf; JSMallocState malloc_state; + JSArenaState arena_state; const char *rt_info; int atom_hash_size; /* power of two */ @@ -377,9 +435,16 @@ typedef struct JSStackFrame { uint16_t var_ref_count; /* number of var refs */ uint16_t arg_count; bool is_strict_mode; + bool is_constructor; /* true if invoked as a constructor (new) */ /* only used in generators. Current stack pointer value. NULL if the function is running. */ JSValue *cur_sp; + /* only set for coroutine frames (async function / generator / + async generator): the GC object owning this heap-allocated frame, + NULL for ordinary C-stack frames. Lets a var_ref capturing one of + the coroutine's locals keep the (suspended) coroutine reachable by + the cycle collector. */ + struct JSGCObjectHeader *cur_gc_obj; } JSStackFrame; typedef enum { @@ -395,26 +460,31 @@ typedef enum { reference count that can reference other GC objects. JS Objects are a particular type of GC object. */ struct JSGCObjectHeader { - int ref_count; /* must come first, 32-bit */ - JSGCObjectTypeEnum gc_obj_type : 4; - uint8_t mark : 1; /* used by the GC */ - uint8_t dummy0 : 3; - uint8_t dummy1; /* not used by the GC */ - uint16_t dummy2; /* not used by the GC */ + /* ref_count/gc_obj_type/mark live in the allocator block header (js_rc(p), + the 8 bytes before every allocation); only the GC list link remains in + the object body. */ struct list_head link; }; typedef struct JSVarRef { - union { - JSGCObjectHeader header; /* must come first */ - struct { - int __gc_ref_count; /* corresponds to header.ref_count */ - uint8_t __gc_mark; /* corresponds to header.mark/gc_obj_type */ - uint8_t is_detached; - uint8_t is_lexical; /* only used with global variables */ - uint8_t is_const; /* only used with global variables */ - }; - }; + JSGCObjectHeader header; /* {link}; must come first so &p->header == p */ + uint8_t is_detached; + uint8_t is_lexical; /* only used with global variables */ + uint8_t is_const; /* only used with global variables */ + /* Set at creation for an open var_ref that captures a local of a + coroutine (async function / generator / async generator): such a + var_ref holds a counted reference to that coroutine's GC object and + is itself a GC object, so the cycle collector can see the closure -> + var_ref -> coroutine edge and keep the suspended coroutine (hence the + captured variable it points into) alive. The coroutine is recovered + as stack_frame->cur_gc_obj (valid while open). This is a *snapshot* of + cur_gc_obj != NULL taken at creation, NOT rederived at read time: + cur_gc_obj transitions NULL -> owner (it is set only after a + generator's initial resume), so var_refs created during the prologue + (e.g. mapped `arguments`) must stay non-coro even though cur_gc_obj is + later set. Cleared when the var_ref is detached; the ref is released on + detach/free. */ + uint8_t is_coro; JSValue *pvalue; /* pointer to the value, either on the stack or to 'value' */ union { @@ -426,9 +496,17 @@ typedef struct JSVarRef { }; } JSVarRef; -typedef struct JSRefCountHeader { - int ref_count; -} JSRefCountHeader; +/* Accessors for the reference count and GC mark/type. These fields live in the + arena block header (the 8 bytes before every allocation, reached via + js_rc()), not in the object body. The macros yield lvalues, and the argument + is always the object/header pointer (whose address equals the GC header's, + since the header is the first member). */ +static inline JSMallocBlockHeader *js_rc(const void *p) { + return (JSMallocBlockHeader *)((uint8_t *)(uintptr_t)p - offsetof(JSMallocBlockHeader, user_data)); +} +#define JS_REF_COUNT(p) (js_rc(p)->ref_count) +#define JS_GC_TYPE(p) (js_rc(p)->gc_obj_type) +#define JS_GC_MARK(p) (js_rc(p)->mark) /* bigint */ typedef int32_t js_slimb_t; @@ -447,7 +525,6 @@ typedef uint64_t js_dlimb_t; typedef struct JSBigInt { - JSRefCountHeader header; /* must come first, 32-bit */ uint32_t len; /* number of limbs, >= 1 */ js_limb_t tab[]; /* two's complement representation, always normalized so that 'len' is the minimum @@ -525,6 +602,7 @@ struct JSContext { double time_origin; uint64_t random_state; + uint32_t hash_seed; /* when the counter reaches zero, JSRutime.interrupt_handler is called */ int interrupt_counter; @@ -616,7 +694,6 @@ typedef enum { #define JS_ATOM_HASH_MASK ((1 << 28) - 1) struct JSString { - JSRefCountHeader header; /* must come first, 32-bit */ uint32_t len : 31; uint32_t is_wide_char : 1; /* 0 = 8 bits, 1 = 16 bits characters */ /* for JS_ATOM_TYPE_SYMBOL: hash = 0, atom_type = 3, @@ -638,7 +715,6 @@ typedef struct JSStringSlice { } JSStringSlice; struct JSStringRope { - JSRefCountHeader header; /* must come first, 32-bit */ uint32_t len; uint8_t is_wide_char; /* 0 = 8 bits, 1 = 16 bits characters */ uint8_t depth; /* max depth of the rope tree */ @@ -828,6 +904,7 @@ typedef enum JSIteratorKindEnum { } JSIteratorKindEnum; typedef enum JSIteratorHelperKindEnum { + JS_ITERATOR_HELPER_KIND_CHUNKS, JS_ITERATOR_HELPER_KIND_DROP, JS_ITERATOR_HELPER_KIND_EVERY, JS_ITERATOR_HELPER_KIND_FILTER, @@ -837,6 +914,7 @@ typedef enum JSIteratorHelperKindEnum { JS_ITERATOR_HELPER_KIND_MAP, JS_ITERATOR_HELPER_KIND_SOME, JS_ITERATOR_HELPER_KIND_TAKE, + JS_ITERATOR_HELPER_KIND_WINDOWS, } JSIteratorHelperKindEnum; typedef struct JSForInIterator { @@ -867,7 +945,7 @@ typedef struct JSArrayBuffer { uint8_t *data; /* NULL if detached */ struct list_head array_list; void *opaque; - JSFreeArrayBufferDataFunc *free_func; + JSReallocArrayBufferDataFunc *realloc_func; } JSArrayBuffer; typedef struct JSTypedArray { @@ -940,7 +1018,6 @@ typedef enum { } JSModuleStatus; struct JSModuleDef { - JSRefCountHeader header; /* must come first, 32-bit */ JSAtom module_name; struct list_head link; @@ -960,6 +1037,11 @@ struct JSModuleDef { int import_entries_count; int import_entries_size; + /* import attributes the module was requested with, JS_UNDEFINED if + none; the same module name can be loaded with different attributes + (e.g. as both a JS module and a text module) */ + JSValue attributes; + JSValue module_ns; JSValue func_obj; /* only used for JS modules */ JSModuleInitFunc *init_func; /* only used for C modules */ @@ -1037,28 +1119,23 @@ struct JSShape { int deleted_prop_count; JSShape *shape_hash_next; /* in JSRuntime.shape_hash[h] list */ JSObject *proto; - JSShapeProperty prop[]; /* prop_size elements */ + uint32_t hash_table[]; /* prop_hash_mask + 1 elements, then prop[prop_size] */ }; struct JSObject { - union { - JSGCObjectHeader header; - struct { - int __gc_ref_count; /* corresponds to header.ref_count */ - uint8_t __gc_mark : 7; /* corresponds to header.mark/gc_obj_type */ - uint8_t is_prototype : 1; /* object may be used as prototype */ - - uint8_t extensible : 1; - uint8_t free_mark : 1; /* only used when freeing objects with cycles */ - uint8_t is_exotic : 1; /* true if object has exotic property handlers */ - uint8_t fast_array : 1; /* true if u.array is used for get/put (for JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS, JS_CLASS_MAPPED_ARGUMENTS and typed arrays) */ - uint8_t is_constructor : 1; /* true if object is a constructor function */ - uint8_t is_uncatchable_error : 1; /* if true, error is not catchable */ - uint8_t tmp_mark : 1; /* used in JS_WriteObjectRec() */ - uint8_t is_HTMLDDA : 1; /* specific annex B IsHtmlDDA behavior */ - uint16_t class_id; /* see JS_CLASS_x */ - }; - }; + /* ref_count/gc_obj_type/mark live in the allocator block header; the object + body keeps only the GC list link plus the object's own flags. */ + JSGCObjectHeader header; /* {link}; must come first so &p->header == p */ + uint8_t is_prototype : 1; /* object may be used as prototype */ + uint8_t extensible : 1; + uint8_t free_mark : 1; /* only used when freeing objects with cycles */ + uint8_t is_exotic : 1; /* true if object has exotic property handlers */ + uint8_t fast_array : 1; /* true if u.array is used for get/put (for JS_CLASS_ARRAY, JS_CLASS_ARGUMENTS, JS_CLASS_MAPPED_ARGUMENTS and typed arrays) */ + uint8_t is_constructor : 1; /* true if object is a constructor function */ + uint8_t is_uncatchable_error : 1; /* if true, error is not catchable */ + uint8_t tmp_mark : 1; /* used in JS_WriteObjectRec() */ + uint8_t is_HTMLDDA : 1; /* specific annex B IsHtmlDDA behavior */ + uint16_t class_id; /* see JS_CLASS_x */ /* byte offsets: 16/24 */ JSShape *shape; /* prototype and property names + flag */ JSProperty *prop; /* array of properties */ @@ -1135,6 +1212,7 @@ typedef struct JSCallSiteData { JSValue func; JSValue func_name; bool native; + bool constructor; int line_num; int col_num; } JSCallSiteData; @@ -1315,6 +1393,7 @@ static JSValue js_error_constructor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv, int magic); static JSValue js_object_defineProperty(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic); +static uint64_t xorshift64star(uint64_t *pstate); typedef enum JSStrictEqModeEnum { JS_EQ_STRICT, @@ -1354,9 +1433,10 @@ static JSValue js_array_buffer_constructor3(JSContext *ctx, uint64_t len, uint64_t *max_len, JSClassID class_id, uint8_t *buf, - JSFreeArrayBufferDataFunc *free_func, + JSReallocArrayBufferDataFunc *realloc_func, void *opaque, bool alloc_flag); -static void js_array_buffer_free(JSRuntime *rt, void *opaque, void *ptr); +static void *js_array_buffer_realloc(JSRuntime *rt, void *opaque, void *ptr, + size_t size); static JSArrayBuffer *js_get_array_buffer(JSContext *ctx, JSValueConst obj); static bool array_buffer_is_resizable(const JSArrayBuffer *abuf); static JSValue js_typed_array_constructor(JSContext *ctx, @@ -1391,12 +1471,16 @@ static JSValue JS_EvalInternal(JSContext *ctx, JSValueConst this_obj, const char *input, size_t input_len, const char *filename, int line, int flags, int scope_idx); static void js_free_module_def(JSContext *ctx, JSModuleDef *m); +static int js_module_attributes_equal(JSContext *ctx, JSValueConst attr1, + JSValueConst attr2); static void js_mark_module_def(JSRuntime *rt, JSModuleDef *m, JS_MarkFunc *mark_func); static JSValue js_import_meta(JSContext *ctx); static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier, JSValueConst options); static void free_var_ref(JSRuntime *rt, JSVarRef *var_ref); +static void js_async_function_free(JSRuntime *rt, JSAsyncFunctionData *s); +static void js_release_coro(JSRuntime *rt, JSGCObjectHeader *coro); static JSValue js_new_promise_capability(JSContext *ctx, JSValue *resolving_funcs, JSValueConst ctor); @@ -1545,6 +1629,21 @@ static JSValue js_number(double d) return js_float64(d); } +/* If v is a number (int or float64), store it as a double and return true. + Used by the interpreter arithmetic fast paths to handle mixed int/float + operands inline instead of falling back to the slow path. */ +static inline bool js_arith_to_float64(JSValue v, double *pd) +{ + uint32_t tag = JS_VALUE_GET_TAG(v); + if (JS_TAG_IS_FLOAT64(tag)) + *pd = JS_VALUE_GET_FLOAT64(v); + else if (tag == JS_TAG_INT) + *pd = JS_VALUE_GET_INT(v); + else + return false; + return true; +} + static JSValue __JS_NewShortBigInt(JSContext *ctx, int32_t d) { (void)&ctx; @@ -1564,8 +1663,8 @@ static JSValue js_bool(bool v) static JSValue js_dup(JSValueConst v) { if (JS_VALUE_HAS_REF_COUNT(v)) { - JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); - p->ref_count++; + void *p = JS_VALUE_GET_PTR(v); + JS_REF_COUNT(p)++; } return unsafe_unconst(v); } @@ -1606,6 +1705,279 @@ static size_t js_malloc_usable_size_unknown(const void *ptr) return 0; } +/* max overhead for size >= 64: 12.5% */ +static const uint16_t arena_block_sizes[JS_ARENA_BLOCK_SIZE_COUNT] = { + 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 128, + 144, 160, 176, 192, 208, 224, 240, 256, + 288, 320, 352, 384, 416, 448, 480, 512, +}; + +static int arena_get_size_index(size_t size) +{ + if (size <= 16) + return 0; + else if (size <= 128) + return (size + 7) / 8 - 2; + else if (size <= 256) + return (size + 15) / 16 + 6; + else if (size <= 512) + return (size + 31) / 32 + 14; + else + return JS_ARENA_BLOCK_SIZE_COUNT; +} + +static inline JSMallocBlockHeader *arena_zero_block(JSRuntime *rt) +{ + return (JSMallocBlockHeader *)rt->arena_state.zero_size_block; +} + +static void js_arena_init(JSRuntime *rt) +{ + JSArenaState *s = &rt->arena_state; + int i; + arena_zero_block(rt)->u.block_idx = JS_ARENA_FREE_NIL; + for (i = 0; i < JS_ARENA_BLOCK_SIZE_COUNT; i++) { + init_list_head(&s->arena_list[i]); + init_list_head(&s->free_arena_list[i]); + } +} + +static inline void *arena_get_block(JSArena *ar, unsigned int idx, + unsigned int block_size) +{ + return ar->blocks + (size_t)idx * block_size; +} + +static no_inline JSArena *arena_new(JSRuntime *rt, int block_size_idx) +{ + JSMallocBlockHeader *b; + JSArena *ar; + int n_blocks, block_size, i; + + block_size = arena_block_sizes[block_size_idx]; + n_blocks = (JS_ARENA_SIZE - sizeof(JSArena)) / block_size; + ar = rt->mf.js_malloc(rt->malloc_state.opaque, + sizeof(JSArena) + (size_t)n_blocks * block_size); + if (!ar) + return NULL; + ar->block_size_idx = block_size_idx; + ar->n_blocks = n_blocks; + ar->n_used_blocks = 0; + ar->first_free_block = 0; + for (i = 0; i < n_blocks - 1; i++) { + b = arena_get_block(ar, i, block_size); + b->u.free_next = i + 1; + b->block_size_idx = block_size_idx; + } + b = arena_get_block(ar, n_blocks - 1, block_size); + b->u.free_next = JS_ARENA_FREE_NIL; + b->block_size_idx = block_size_idx; + list_add(&ar->link, &rt->arena_state.arena_list[block_size_idx]); + list_add(&ar->free_link, &rt->arena_state.free_arena_list[block_size_idx]); + return ar; +} + +static no_inline void *arena_malloc_large(JSRuntime *rt, size_t size) +{ + JSMallocBlockHeader *b; + b = rt->mf.js_malloc(rt->malloc_state.opaque, + sizeof(JSMallocBlockHeader) + size); + if (!b) + return NULL; + b->u.block_idx = JS_ARENA_FREE_NIL; + b->block_size_idx = 0xff; /* fail safe */ + return b->user_data; +} + +static no_inline void *arena_calloc_large(JSRuntime *rt, size_t size) +{ + JSMallocBlockHeader *b; + b = rt->mf.js_calloc(rt->malloc_state.opaque, 1, + sizeof(JSMallocBlockHeader) + size); + if (!b) + return NULL; + b->u.block_idx = JS_ARENA_FREE_NIL; + b->block_size_idx = 0xff; /* fail safe */ + return b->user_data; +} + +static void *js_arena_malloc(JSRuntime *rt, size_t size) +{ + size_t total_size; + + if (unlikely(size == 0)) + return arena_zero_block(rt)->user_data; + total_size = ((size + JS_ARENA_ALIGN - 1) & ~(size_t)(JS_ARENA_ALIGN - 1)) + + sizeof(JSMallocBlockHeader); + if (!JS_ARENA_LARGE_BLOCKS_ONLY && total_size <= JS_ARENA_MAX_SMALL_SIZE) { + int block_size_idx; + unsigned int block_idx, block_size; + JSMallocBlockHeader *b; + JSArena *ar; + struct list_head *el, *head; + + block_size_idx = arena_get_size_index(total_size); + block_size = arena_block_sizes[block_size_idx]; + head = &rt->arena_state.free_arena_list[block_size_idx]; + el = head->next; + if (unlikely(el == head)) { + ar = arena_new(rt, block_size_idx); + if (!ar) + return NULL; + } else { + ar = list_entry(el, JSArena, free_link); + } + block_idx = ar->first_free_block; + b = arena_get_block(ar, block_idx, block_size); + ar->first_free_block = b->u.free_next; + b->u.block_idx = block_idx; + ar->n_used_blocks++; + if (unlikely(ar->n_used_blocks == ar->n_blocks)) + list_del(&ar->free_link); + return b->user_data; + } else { + return arena_malloc_large(rt, size); + } +} + +static void js_arena_free(JSRuntime *rt, void *ptr) +{ + JSMallocBlockHeader *b; + + if (!ptr) + return; + b = container_of(ptr, JSMallocBlockHeader, user_data); + if (unlikely(b->u.block_idx == JS_ARENA_FREE_NIL)) { + /* large or zero-size block */ + if (b == arena_zero_block(rt)) { + /* nothing to do */ + } else { + rt->mf.js_free(rt->malloc_state.opaque, b); + } + } else { + unsigned int block_idx = b->u.block_idx; + unsigned int block_size_idx = b->block_size_idx; + unsigned int block_size = arena_block_sizes[block_size_idx]; + JSArena *ar = (JSArena *)((uint8_t *)b - + (size_t)block_size * block_idx - + sizeof(JSArena)); + b->u.free_next = ar->first_free_block; + ar->first_free_block = block_idx; + if (unlikely(ar->n_used_blocks == ar->n_blocks)) + list_add(&ar->free_link, + &rt->arena_state.free_arena_list[block_size_idx]); + ar->n_used_blocks--; + if (unlikely(ar->n_used_blocks == 0)) { + list_del(&ar->link); + list_del(&ar->free_link); + rt->mf.js_free(rt->malloc_state.opaque, ar); + } + } +} + +static size_t js_arena_usable_size(JSRuntime *rt, const void *ptr) +{ + const JSMallocBlockHeader *b; + + if (!ptr) + return 0; + b = container_of(ptr, JSMallocBlockHeader, user_data); + if (b->u.block_idx == JS_ARENA_FREE_NIL) { + if (b == arena_zero_block(rt)) { + return 0; + } else { + size_t size = rt->mf.js_malloc_usable_size(b); + if (size != 0) + size -= sizeof(JSMallocBlockHeader); + return size; + } + } else { + return arena_block_sizes[b->block_size_idx] - sizeof(JSMallocBlockHeader); + } +} + +static void *js_arena_realloc(JSRuntime *rt, void *ptr, size_t size) +{ + JSMallocBlockHeader *b; + + /* js_realloc_rt already handles ptr == NULL and size == 0 */ + b = container_of(ptr, JSMallocBlockHeader, user_data); + if (b->u.block_idx == JS_ARENA_FREE_NIL) { + if (b == arena_zero_block(rt)) { + return js_arena_malloc(rt, size); + } else { + JSMallocBlockHeader *nb; + nb = rt->mf.js_realloc(rt->malloc_state.opaque, b, + sizeof(JSMallocBlockHeader) + size); + if (!nb) + return NULL; + nb->u.block_idx = JS_ARENA_FREE_NIL; + nb->block_size_idx = 0xff; + return nb->user_data; + } + } else { + unsigned int block_size = arena_block_sizes[b->block_size_idx]; + size_t total_size, old_usable; + void *new_ptr; + + total_size = ((size + JS_ARENA_ALIGN - 1) & ~(size_t)(JS_ARENA_ALIGN - 1)) + + sizeof(JSMallocBlockHeader); + if (total_size <= block_size) + return ptr; /* still fits the current size class */ + new_ptr = js_arena_malloc(rt, size); + if (!new_ptr) + return NULL; + { + /* carry the merged GC/refcount fields to the relocated block */ + JSMallocBlockHeader *nb = container_of(new_ptr, JSMallocBlockHeader, user_data); + nb->gc_obj_type = b->gc_obj_type; + nb->mark = b->mark; + nb->ref_count = b->ref_count; + } + old_usable = block_size - sizeof(JSMallocBlockHeader); + if (size > old_usable) + size = old_usable; + memcpy(new_ptr, ptr, size); + js_arena_free(rt, ptr); + return new_ptr; + } +} + +static void *js_arena_calloc(JSRuntime *rt, size_t count, size_t size) +{ + size_t n = count * size; /* overflow already checked by js_calloc_rt */ + size_t total_size = ((n + JS_ARENA_ALIGN - 1) & ~(size_t)(JS_ARENA_ALIGN - 1)) + + sizeof(JSMallocBlockHeader); + if (!JS_ARENA_LARGE_BLOCKS_ONLY && total_size <= JS_ARENA_MAX_SMALL_SIZE) { + /* Small blocks are carved from recycled (dirty) arena memory, so they + must be zeroed explicitly. */ + void *ptr = js_arena_malloc(rt, n); + if (unlikely(!ptr)) + return NULL; + return memset(ptr, 0, n); + } + /* Large blocks come straight from the backing allocator, so let js_calloc + do the zeroing. */ + return arena_calloc_large(rt, n); +} + +/* free any arenas still mapped at runtime teardown (normally none: empty + arenas are released eagerly as their last block is freed) */ +static void js_arena_free_all(JSRuntime *rt) +{ + JSArenaState *s = &rt->arena_state; + struct list_head *el, *el1; + int i; + for (i = 0; i < JS_ARENA_BLOCK_SIZE_COUNT; i++) { + list_for_each_safe(el, el1, &s->arena_list[i]) { + JSArena *ar = list_entry(el, JSArena, link); + rt->mf.js_free(rt->malloc_state.opaque, ar); + } + init_list_head(&s->arena_list[i]); + init_list_head(&s->free_arena_list[i]); + } +} + void *js_calloc_rt(JSRuntime *rt, size_t count, size_t size) { void *ptr; @@ -1623,12 +1995,12 @@ void *js_calloc_rt(JSRuntime *rt, size_t count, size_t size) if (unlikely(s->malloc_size + (count * size) > s->malloc_limit - 1)) return NULL; - ptr = rt->mf.js_calloc(s->opaque, count, size); + ptr = js_arena_calloc(rt, count, size); if (!ptr) return NULL; s->malloc_count++; - s->malloc_size += rt->mf.js_malloc_usable_size(ptr) + MALLOC_OVERHEAD; + s->malloc_size += js_arena_usable_size(rt, ptr) + MALLOC_OVERHEAD; return ptr; } @@ -1646,12 +2018,12 @@ void *js_malloc_rt(JSRuntime *rt, size_t size) if (unlikely(s->malloc_size + size > s->malloc_limit - 1)) return NULL; - ptr = rt->mf.js_malloc(s->opaque, size); + ptr = js_arena_malloc(rt, size); if (!ptr) return NULL; s->malloc_count++; - s->malloc_size += rt->mf.js_malloc_usable_size(ptr) + MALLOC_OVERHEAD; + s->malloc_size += js_arena_usable_size(rt, ptr) + MALLOC_OVERHEAD; return ptr; } @@ -1663,14 +2035,14 @@ void js_free_rt(JSRuntime *rt, void *ptr) return; s = &rt->malloc_state; - size_t free_size = rt->mf.js_malloc_usable_size(ptr) + MALLOC_OVERHEAD; + size_t free_size = js_arena_usable_size(rt, ptr) + MALLOC_OVERHEAD; if (unlikely(free_size > s->malloc_size)) { printf("js_free_rt: malloc_size underflow: freeing %zu but only %zu tracked\n", free_size, s->malloc_size); abort(); } s->malloc_count--; s->malloc_size -= free_size; - rt->mf.js_free(s->opaque, ptr); + js_arena_free(rt, ptr); } void *js_realloc_rt(JSRuntime *rt, void *ptr, size_t size) @@ -1687,23 +2059,23 @@ void *js_realloc_rt(JSRuntime *rt, void *ptr, size_t size) js_free_rt(rt, ptr); return NULL; } - old_size = rt->mf.js_malloc_usable_size(ptr); + old_size = js_arena_usable_size(rt, ptr); s = &rt->malloc_state; /* When malloc_limit is 0 (unlimited), malloc_limit - 1 will be SIZE_MAX. */ if (s->malloc_size + size - old_size > s->malloc_limit - 1) return NULL; - ptr = rt->mf.js_realloc(s->opaque, ptr, size); + ptr = js_arena_realloc(rt, ptr, size); if (!ptr) return NULL; - s->malloc_size += rt->mf.js_malloc_usable_size(ptr) - old_size; + s->malloc_size += js_arena_usable_size(rt, ptr) - old_size; return ptr; } size_t js_malloc_usable_size_rt(JSRuntime *rt, const void *ptr) { - return rt->mf.js_malloc_usable_size(ptr); + return js_arena_usable_size(rt, ptr); } /** @@ -1771,22 +2143,6 @@ void *js_realloc(JSContext *ctx, void *ptr, size_t size) return ret; } -/* store extra allocated size in *pslack if successful */ -void *js_realloc2(JSContext *ctx, void *ptr, size_t size, size_t *pslack) -{ - void *ret; - ret = js_realloc_rt(ctx->rt, ptr, size); - if (unlikely(!ret && size != 0)) { - JS_ThrowOutOfMemory(ctx); - return NULL; - } - if (pslack) { - size_t new_size = js_malloc_usable_size_rt(ctx->rt, ret); - *pslack = (new_size > size) ? new_size - size : 0; - } - return ret; -} - size_t js_malloc_usable_size(JSContext *ctx, const void *ptr) { return js_malloc_usable_size_rt(ctx->rt, ptr); @@ -1813,14 +2169,13 @@ static no_inline int js_realloc_array(JSContext *ctx, void **parray, int elem_size, int *psize, int req_size) { int new_size; - size_t slack; void *new_array; /* XXX: potential arithmetic overflow */ new_size = max_int(req_size, *psize * 3 / 2); - new_array = js_realloc2(ctx, *parray, new_size * elem_size, &slack); + assert(elem_size > 0 && new_size > 0); + new_array = js_realloc(ctx, *parray, (size_t)new_size * (size_t)elem_size); if (!new_array) return -1; - new_size += slack / elem_size; *psize = new_size; *parray = new_array; return 0; @@ -1863,7 +2218,7 @@ typedef struct JSClassShortDef { static JSClassShortDef const js_std_class_def[] = { { JS_ATOM_Object, NULL, NULL }, /* JS_CLASS_OBJECT */ { JS_ATOM_Array, js_array_finalizer, js_array_mark }, /* JS_CLASS_ARRAY */ - { JS_ATOM_Error, NULL, NULL }, /* JS_CLASS_ERROR */ + { JS_ATOM_Error, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_ERROR */ { JS_ATOM_Number, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_NUMBER */ { JS_ATOM_String, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_STRING */ { JS_ATOM_Boolean, js_object_data_finalizer, js_object_data_mark }, /* JS_CLASS_BOOLEAN */ @@ -1977,6 +2332,7 @@ JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque) ms.malloc_count++; ms.malloc_size += rt->mf.js_malloc_usable_size(rt) + MALLOC_OVERHEAD; rt->malloc_state = ms; + js_arena_init(rt); rt->malloc_gc_threshold = 256 * 1024; init_list_head(&rt->context_list); @@ -2223,7 +2579,7 @@ static JSString *js_alloc_string_rt(JSRuntime *rt, int max_len, int is_wide_char str = js_malloc_rt(rt, sizeof(JSString) + (max_len << is_wide_char) + 1 - is_wide_char); if (unlikely(!str)) return NULL; - str->header.ref_count = 1; + JS_REF_COUNT(str) = 1; str->is_wide_char = is_wide_char; str->len = max_len; str->kind = JS_STRING_KIND_NORMAL; @@ -2252,7 +2608,7 @@ static inline void js_free_string0(JSRuntime *rt, JSString *str); /* same as JS_FreeValueRT() but faster */ static inline void js_free_string(JSRuntime *rt, JSString *str) { - if (--str->header.ref_count <= 0) + if (--JS_REF_COUNT(str) <= 0) js_free_string0(rt, str); } @@ -2315,14 +2671,14 @@ void JS_FreeRuntime(JSRuntime *rt) referenced externally */ list_for_each(el, &rt->gc_obj_list) { p = list_entry(el, JSGCObjectHeader, link); - p->mark = 0; + JS_GC_MARK(p) = 0; } gc_decref(rt); header_done = false; list_for_each(el, &rt->gc_obj_list) { p = list_entry(el, JSGCObjectHeader, link); - if (p->ref_count != 0) { + if (JS_REF_COUNT(p) != 0) { if (!header_done) { printf("Object leaks:\n"); JS_DumpObjectHeader(rt); @@ -2336,7 +2692,7 @@ void JS_FreeRuntime(JSRuntime *rt) count = 0; list_for_each(el, &rt->gc_obj_list) { p = list_entry(el, JSGCObjectHeader, link); - if (p->ref_count == 0) { + if (JS_REF_COUNT(p) == 0) { count++; } } @@ -2364,7 +2720,7 @@ void JS_FreeRuntime(JSRuntime *rt) for(i = 0; i < rt->atom_size; i++) { JSAtomStruct *p = rt->atom_array[i]; if (!atom_is_free(p) /* && p->str*/) { - if (i >= JS_ATOM_END || p->header.ref_count != 1) { + if (i >= JS_ATOM_END || JS_REF_COUNT(p) != 1) { if (!header_done) { header_done = true; if (rt->rt_info) { @@ -2378,7 +2734,7 @@ void JS_FreeRuntime(JSRuntime *rt) if (rt->rt_info) { printf(" "); } else { - printf(" %6u %6u ", i, p->header.ref_count); + printf(" %6u %6u ", i, JS_REF_COUNT(p)); } switch (p->atom_type) { case JS_ATOM_TYPE_STRING: @@ -2402,7 +2758,7 @@ void JS_FreeRuntime(JSRuntime *rt) break; } if (rt->rt_info) { - printf(":%u", p->header.ref_count); + printf(":%u", JS_REF_COUNT(p)); } else { printf("\n"); } @@ -2442,11 +2798,11 @@ void JS_FreeRuntime(JSRuntime *rt) if (rt->rt_info) { printf(" "); } else { - printf(" %6u ", str->header.ref_count); + printf(" %6u ", JS_REF_COUNT(str)); } JS_DumpString(rt, str); if (rt->rt_info) { - printf(":%u", str->header.ref_count); + printf(":%u", JS_REF_COUNT(str)); } else { printf("\n"); } @@ -2482,6 +2838,8 @@ void JS_FreeRuntime(JSRuntime *rt) leak &= check_dump_flag(rt, JS_ABORT_ON_LEAKS); + js_arena_free_all(rt); + { JSMallocState *ms = &rt->malloc_state; rt->mf.js_free(ms->opaque, rt); @@ -2499,7 +2857,7 @@ JSContext *JS_NewContextRaw(JSRuntime *rt) ctx = js_mallocz_rt(rt, sizeof(JSContext)); if (!ctx) return NULL; - ctx->header.ref_count = 1; + JS_REF_COUNT(ctx) = 1; add_gc_object(rt, &ctx->header, JS_GC_OBJ_TYPE_JS_CONTEXT); ctx->class_proto = js_malloc_rt(rt, sizeof(ctx->class_proto[0]) * @@ -2522,6 +2880,12 @@ JSContext *JS_NewContextRaw(JSRuntime *rt) ctx->error_prepare_stack = JS_UNDEFINED; ctx->error_stack_trace_limit = js_int32(10); init_list_head(&ctx->loaded_modules); + // TODO(bnoordhuis) use getrandom() etc. + ctx->random_state = js__gettimeofday_us(); + // the state must be non zero + if (ctx->random_state == 0) + ctx->random_state = 1; + ctx->hash_seed = xorshift64star(&ctx->random_state); if (JS_AddIntrinsicBasicObjects(ctx)) { JS_FreeContext(ctx); @@ -2613,7 +2977,7 @@ static void js_free_modules(JSContext *ctx, JSFreeModuleEnum flag) JSContext *JS_DupContext(JSContext *ctx) { - ctx->header.ref_count++; + JS_REF_COUNT(ctx)++; return ctx; } @@ -2678,9 +3042,9 @@ void JS_FreeContext(JSContext *ctx) JSRuntime *rt = ctx->rt; int i; - if (--ctx->header.ref_count > 0) + if (--JS_REF_COUNT(ctx) > 0) return; - assert(ctx->header.ref_count == 0); + assert(JS_REF_COUNT(ctx) == 0); #ifdef ENABLE_DUMPS // JS_DUMP_ATOMS if (check_dump_flag(rt, JS_DUMP_ATOMS)) @@ -2863,7 +3227,7 @@ static inline uint32_t hash_string8(const uint8_t *str, size_t len, uint32_t h) for(i = 0; i < len; i++) h = h * 263 + str[i]; - return h; + return h ^ hash32(len); } static inline uint32_t hash_string16(const uint16_t *str, @@ -2873,7 +3237,7 @@ static inline uint32_t hash_string16(const uint16_t *str, for(i = 0; i < len; i++) h = h * 263 + str[i]; - return h; + return h ^ hash32(len); } static uint32_t hash_string(JSString *str, uint32_t h) @@ -2904,8 +3268,8 @@ static __maybe_unused void JS_DumpString(JSRuntime *rt, JSString *p) printf(""); return; } - if (p->header.ref_count != 1) - printf("%d", p->header.ref_count); + if (JS_REF_COUNT(p) != 1) + printf("%d", JS_REF_COUNT(p)); if (p->is_wide_char) putchar('L'); sep = '\"'; @@ -3027,7 +3391,7 @@ JSAtom JS_DupAtomRT(JSRuntime *rt, JSAtom v) if (!__JS_AtomIsConst(v)) { p = rt->atom_array[v]; - p->header.ref_count++; + JS_REF_COUNT(p)++; } return v; } @@ -3040,7 +3404,7 @@ JSAtom JS_DupAtom(JSContext *ctx, JSAtom v) if (!__JS_AtomIsConst(v)) { rt = ctx->rt; p = rt->atom_array[v]; - p->header.ref_count++; + JS_REF_COUNT(p)++; } return v; } @@ -3106,7 +3470,7 @@ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type) i = js_get_atom_index(rt, str); /* reduce string refcount and increase atom's unless constant */ if (__JS_AtomIsConst(i)) - str->header.ref_count--; + JS_REF_COUNT(str)--; return i; } /* try and locate an already registered atom */ @@ -3122,7 +3486,7 @@ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type) p->len == len && js_string_memcmp(p, str, len) == 0) { if (!__JS_AtomIsConst(i)) - p->header.ref_count++; + JS_REF_COUNT(p)++; goto done; } i = p->hash_next; @@ -3149,7 +3513,6 @@ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type) new_size = max_int(711, rt->atom_size * 3 / 2); if (new_size > JS_ATOM_MAX) goto fail; - /* XXX: should use realloc2 to use slack space */ new_array = js_realloc_rt(rt, rt->atom_array, sizeof(*new_array) * new_size); if (!new_array) goto fail; @@ -3162,7 +3525,7 @@ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type) js_free_rt(rt, new_array); goto fail; } - p->header.ref_count = 1; /* not refcounted */ + JS_REF_COUNT(p) = 1; /* not refcounted */ p->atom_type = JS_ATOM_TYPE_SYMBOL; #ifdef ENABLE_DUMPS // JS_DUMP_LEAKS list_add_tail(&p->link, &rt->string_list); @@ -3194,7 +3557,7 @@ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type) 1 - str->is_wide_char); if (unlikely(!p)) goto fail; - p->header.ref_count = 1; + JS_REF_COUNT(p) = 1; p->is_wide_char = str->is_wide_char; p->len = str->len; p->kind = JS_STRING_KIND_NORMAL; @@ -3209,7 +3572,7 @@ static JSAtom __JS_NewAtom(JSRuntime *rt, JSString *str, int atom_type) p = js_malloc_rt(rt, sizeof(JSAtomStruct)); /* empty wide string */ if (!p) return JS_ATOM_NULL; - p->header.ref_count = 1; + JS_REF_COUNT(p) = 1; p->is_wide_char = 1; /* Hack to represent NULL as a JSString */ p->len = 0; p->kind = JS_STRING_KIND_NORMAL; @@ -3281,7 +3644,7 @@ static JSAtom __JS_FindAtom(JSRuntime *rt, const char *str, size_t len, p->is_wide_char == 0 && memcmp(str8(p), str, len) == 0) { if (!__JS_AtomIsConst(i)) - p->header.ref_count++; + JS_REF_COUNT(p)++; return i; } i = p->hash_next; @@ -3334,7 +3697,7 @@ static void __JS_FreeAtom(JSRuntime *rt, uint32_t i) JSAtomStruct *p; p = rt->atom_array[i]; - if (--p->header.ref_count > 0) + if (--JS_REF_COUNT(p) > 0) return; JS_FreeAtomStruct(rt, p); } @@ -3967,7 +4330,7 @@ static JSValue js_sub_string(JSContext *ctx, JSString *p, int start, int end) slice = (void *)&q[1]; slice->parent = p; slice->start = start << p->is_wide_char; // chars -> bytes - p->header.ref_count++; + JS_REF_COUNT(p)++; return JS_MKPTR(JS_TAG_STRING, q); } if (p->is_wide_char) { @@ -4049,16 +4412,14 @@ static int string_buffer_set_error(StringBuffer *s) static no_inline int string_buffer_widen(StringBuffer *s, int size) { JSString *str; - size_t slack; int i; if (s->error_status) return -1; - str = js_realloc2(s->ctx, s->str, sizeof(JSString) + (size << 1), &slack); + str = js_realloc(s->ctx, s->str, sizeof(JSString) + (size << 1)); if (!str) return string_buffer_set_error(s); - size += slack >> 1; for(i = s->len; i-- > 0;) { str16(str)[i] = str8(str)[i]; } @@ -4072,7 +4433,7 @@ static no_inline int string_buffer_realloc(StringBuffer *s, int new_len, int c) { JSString *new_str; int new_size; - size_t new_size_bytes, slack; + size_t new_size_bytes; if (s->error_status) return -1; @@ -4086,10 +4447,9 @@ static no_inline int string_buffer_realloc(StringBuffer *s, int new_len, int c) return string_buffer_widen(s, new_size); } new_size_bytes = sizeof(JSString) + (new_size << s->is_wide_char) + 1 - s->is_wide_char; - new_str = js_realloc2(s->ctx, s->str, new_size_bytes, &slack); + new_str = js_realloc(s->ctx, s->str, new_size_bytes); if (!new_str) return string_buffer_set_error(s); - new_size = min_int(new_size + (slack >> s->is_wide_char), JS_STRING_LEN_MAX); s->size = new_size; s->str = new_str; return 0; @@ -4877,7 +5237,7 @@ static JSValue js_new_string_rope(JSContext *ctx, JSValue op1, JSValue op2) r = js_malloc(ctx, sizeof(*r)); if (!r) goto fail; - r->header.ref_count = 1; + JS_REF_COUNT(r) = 1; r->len = len; r->is_wide_char = is_wide_char; r->depth = depth + 1; @@ -5036,7 +5396,7 @@ static JSValue js_linearize_string_rope(JSContext *ctx, JSValueConst rope) if (string_buffer_concat_value(b, rope)) goto fail; ret = string_buffer_end(b); - if (r->header.ref_count > 1) { + if (JS_REF_COUNT(r) > 1) { /* update the rope so that it won't need to be linearized again */ JS_FreeValue(ctx, r->left); JS_FreeValue(ctx, r->right); @@ -5101,7 +5461,7 @@ static JSValue JS_ConcatString2(JSContext *ctx, JSValue op1, JSValue op2) if (p2->len == 0) { goto ret_op1; } - if (p1->header.ref_count == 1 && p1->is_wide_char == p2->is_wide_char + if (JS_REF_COUNT(p1) == 1 && p1->is_wide_char == p2->is_wide_char && js_malloc_usable_size(ctx, p1) >= sizeof(*p1) + ((p1->len + p2->len) << p2->is_wide_char) + 1 - p1->is_wide_char) { /* Concatenate in place in available space at the end of p1 */ if (p1->is_wide_char) { @@ -5209,17 +5569,26 @@ static inline size_t get_shape_size(size_t hash_size, size_t prop_size) static inline JSShape *get_shape_from_alloc(void *sh_alloc, size_t hash_size) { - return (JSShape *)(void *)((uint32_t *)sh_alloc + hash_size); + (void)hash_size; + return (JSShape *)sh_alloc; /* shape sits at the allocation start */ } +/* one-past-the-end of the hash bucket array; buckets are addressed as + prop_hash_end(sh)[-h - 1] for h in [0, prop_hash_mask], in BOTH layouts. */ static inline uint32_t *prop_hash_end(JSShape *sh) { - return (uint32_t *)sh; + return sh->hash_table + sh->prop_hash_mask + 1; +} + +/* the JSShapeProperty array */ +static inline JSShapeProperty *get_shape_prop(JSShape *sh) +{ + return (JSShapeProperty *)(void *)(sh->hash_table + sh->prop_hash_mask + 1); } static inline void *get_alloc_from_shape(JSShape *sh) { - return prop_hash_end(sh) - ((intptr_t)sh->prop_hash_mask + 1); + return sh; /* shape sits at the allocation start */ } static int init_shape_hash(JSRuntime *rt) @@ -5315,14 +5684,16 @@ static inline JSShape *js_new_shape_nohash(JSContext *ctx, JSObject *proto, if (!sh_alloc) return NULL; sh = get_shape_from_alloc(sh_alloc, hash_size); - sh->header.ref_count = 1; + JS_REF_COUNT(sh) = 1; add_gc_object(rt, &sh->header, JS_GC_OBJ_TYPE_SHAPE); if (proto) js_dup(JS_MKPTR(JS_TAG_OBJECT, proto)); sh->proto = proto; + /* prop_hash_mask must be set before prop_hash_end(sh) is used, as the hash + location depends on it in the merged-header layout. */ + sh->prop_hash_mask = hash_size - 1; memset(prop_hash_end(sh) - hash_size, 0, sizeof(prop_hash_end(sh)[0]) * hash_size); - sh->prop_hash_mask = hash_size - 1; sh->prop_size = prop_size; sh->prop_count = 0; sh->deleted_prop_count = 0; @@ -5411,13 +5782,13 @@ static JSShape *js_clone_shape(JSContext *ctx, JSShape *sh1) sh_alloc1 = get_alloc_from_shape(sh1); memcpy(sh_alloc, sh_alloc1, size); sh = get_shape_from_alloc(sh_alloc, hash_size); - sh->header.ref_count = 1; + JS_REF_COUNT(sh) = 1; add_gc_object(ctx->rt, &sh->header, JS_GC_OBJ_TYPE_SHAPE); sh->is_hashed = false; if (sh->proto) { js_dup(JS_MKPTR(JS_TAG_OBJECT, sh->proto)); } - for(i = 0, pr = sh->prop; i < sh->prop_count; i++, pr++) { + for(i = 0, pr = get_shape_prop(sh); i < sh->prop_count; i++, pr++) { JS_DupAtom(ctx, pr->atom); } return sh; @@ -5425,7 +5796,7 @@ static JSShape *js_clone_shape(JSContext *ctx, JSShape *sh1) static JSShape *js_dup_shape(JSShape *sh) { - sh->header.ref_count++; + JS_REF_COUNT(sh)++; return sh; } @@ -5434,13 +5805,13 @@ static void js_free_shape0(JSRuntime *rt, JSShape *sh) uint32_t i; JSShapeProperty *pr; - assert(sh->header.ref_count == 0); + assert(JS_REF_COUNT(sh) == 0); if (sh->is_hashed) js_shape_hash_unlink(rt, sh); if (sh->proto != NULL) { JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_OBJECT, sh->proto)); } - pr = sh->prop; + pr = get_shape_prop(sh); for(i = 0; i < sh->prop_count; i++) { JS_FreeAtomRT(rt, pr->atom); pr++; @@ -5451,7 +5822,7 @@ static void js_free_shape0(JSRuntime *rt, JSShape *sh) static void js_free_shape(JSRuntime *rt, JSShape *sh) { - if (unlikely(--sh->header.ref_count <= 0)) { + if (unlikely(--JS_REF_COUNT(sh) <= 0)) { js_free_shape0(rt, sh); } } @@ -5495,15 +5866,22 @@ static no_inline int resize_properties(JSContext *ctx, JSShape **psh, return -1; sh = get_shape_from_alloc(sh_alloc, new_hash_size); list_del(&old_sh->header.link); - /* copy all the fields and the properties */ - memcpy(sh, old_sh, - sizeof(JSShape) + sizeof(sh->prop[0]) * old_sh->prop_count); + /* copy the shape header, then the properties. Their location relative + to the struct differs by layout, so copy via get_shape_prop(). */ + memcpy(sh, old_sh, sizeof(JSShape)); list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list); + /* the GC/refcount fields live in the block header, not the struct, so + the memcpy above did not carry them: transfer them explicitly */ + JS_REF_COUNT(sh) = JS_REF_COUNT(old_sh); + JS_GC_TYPE(sh) = JS_GC_TYPE(old_sh); + JS_GC_MARK(sh) = JS_GC_MARK(old_sh); new_hash_mask = new_hash_size - 1; sh->prop_hash_mask = new_hash_mask; + memcpy(get_shape_prop(sh), get_shape_prop(old_sh), + sizeof(JSShapeProperty) * old_sh->prop_count); memset(prop_hash_end(sh) - new_hash_size, 0, sizeof(prop_hash_end(sh)[0]) * new_hash_size); - for(i = 0, pr = sh->prop; i < sh->prop_count; i++, pr++) { + for(i = 0, pr = get_shape_prop(sh); i < sh->prop_count; i++, pr++) { if (pr->atom != JS_ATOM_NULL) { h = ((uintptr_t)pr->atom & new_hash_mask); pr->hash_next = prop_hash_end(sh)[-h - 1]; @@ -5560,13 +5938,21 @@ static int compact_properties(JSContext *ctx, JSObject *p) list_del(&old_sh->header.link); memcpy(sh, old_sh, sizeof(JSShape)); list_add_tail(&sh->header.link, &ctx->rt->gc_obj_list); - + /* the GC/refcount fields live in the block header, not the struct, so the + memcpy above did not carry them: transfer them explicitly */ + JS_REF_COUNT(sh) = JS_REF_COUNT(old_sh); + JS_GC_TYPE(sh) = JS_GC_TYPE(old_sh); + JS_GC_MARK(sh) = JS_GC_MARK(old_sh); + + /* set the new hash mask before prop_hash_end()/get_shape_prop() are used, + as their locations depend on it in the merged-header layout */ + sh->prop_hash_mask = new_hash_mask; memset(prop_hash_end(sh) - new_hash_size, 0, sizeof(prop_hash_end(sh)[0]) * new_hash_size); j = 0; - old_pr = old_sh->prop; - pr = sh->prop; + old_pr = get_shape_prop(old_sh); + pr = get_shape_prop(sh); prop = p->prop; for(i = 0; i < sh->prop_count; i++) { if (old_pr->atom != JS_ATOM_NULL) { @@ -5628,7 +6014,7 @@ static int add_shape_property(JSContext *ctx, JSShape **psh, } /* Initialize the new shape property. The object property at p->prop[sh->prop_count] is uninitialized */ - prop = sh->prop; + prop = get_shape_prop(sh); pr = &prop[sh->prop_count++]; pr->atom = JS_DupAtom(ctx, atom); pr->flags = prop_flags; @@ -5678,12 +6064,12 @@ static JSShape *find_hashed_shape_prop(JSRuntime *rt, JSShape *sh, sh1->proto == sh->proto && sh1->prop_count == ((n = sh->prop_count) + 1)) { for(i = 0; i < n; i++) { - if (unlikely(sh1->prop[i].atom != sh->prop[i].atom) || - unlikely(sh1->prop[i].flags != sh->prop[i].flags)) + if (unlikely(get_shape_prop(sh1)[i].atom != get_shape_prop(sh)[i].atom) || + unlikely(get_shape_prop(sh1)[i].flags != get_shape_prop(sh)[i].flags)) goto next; } - if (unlikely(sh1->prop[n].atom != atom) || - unlikely(sh1->prop[n].flags != prop_flags)) + if (unlikely(get_shape_prop(sh1)[n].atom != atom) || + unlikely(get_shape_prop(sh1)[n].flags != prop_flags)) goto next; return sh1; } @@ -5699,11 +6085,11 @@ static __maybe_unused void JS_DumpShape(JSRuntime *rt, int i, JSShape *sh) /* XXX: should output readable class prototype */ printf("%5d %3d%c %14p %5d %5d", i, - sh->header.ref_count, " *"[sh->is_hashed], + JS_REF_COUNT(sh), " *"[sh->is_hashed], (void *)sh->proto, sh->prop_size, sh->prop_count); for(j = 0; j < sh->prop_count; j++) { printf(" %s", JS_AtomGetStrRT(rt, atom_buf, sizeof(atom_buf), - sh->prop[j].atom)); + get_shape_prop(sh)[j].atom)); } printf("\n"); } @@ -5727,7 +6113,7 @@ static __maybe_unused void JS_DumpShapes(JSRuntime *rt) /* dump non-hashed shapes */ list_for_each(el, &rt->gc_obj_list) { gp = list_entry(el, JSGCObjectHeader, link); - if (gp->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT) { + if (JS_GC_TYPE(gp) == JS_GC_OBJ_TYPE_JS_OBJECT) { p = (JSObject *)gp; if (!p->shape->is_hashed) { JS_DumpShape(rt, -1, p->shape); @@ -5767,7 +6153,7 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas js_free(ctx, p); fail: if (props) { - JSShapeProperty *prs = sh->prop; + JSShapeProperty *prs = get_shape_prop(sh); for(i = 0; i < sh->prop_count; i++) { free_property(ctx->rt, &props[i], prs->flags); prs++; @@ -5829,6 +6215,7 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas p->u.array.u.ptr = NULL; p->u.array.count = 0; break; + case JS_CLASS_ERROR: case JS_CLASS_NUMBER: case JS_CLASS_STRING: case JS_CLASS_BOOLEAN: @@ -5848,7 +6235,7 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx, JSShape *sh, JSClassID clas } break; } - p->header.ref_count = 1; + JS_REF_COUNT(p) = 1; add_gc_object(ctx->rt, &p->header, JS_GC_OBJ_TYPE_JS_OBJECT); if (props) { for(i = 0; i < sh->prop_count; i++) @@ -5955,7 +6342,7 @@ JSValue JS_NewObjectFrom(JSContext *ctx, int count, const JSAtom *props, p = JS_VALUE_GET_OBJ(obj); sh = p->shape; assert(sh->is_hashed); - assert(sh->header.ref_count == 1); + assert(JS_REF_COUNT(sh) == 1); js_shape_hash_unlink(rt, sh); if (resize_properties(ctx, &sh, p, count)) { js_shape_hash_link(rt, sh); @@ -5965,7 +6352,7 @@ JSValue JS_NewObjectFrom(JSContext *ctx, int count, const JSAtom *props, p->shape = sh; for (i = 0; i < count; i++) { atom = props[i]; - pr = &sh->prop[i]; + pr = &get_shape_prop(sh)[i]; sh->hash = shape_hash(shape_hash(sh->hash, atom), JS_PROP_C_W_E); h = atom & sh->prop_hash_mask; hash = &prop_hash_end(sh)[-h - 1]; @@ -6257,6 +6644,7 @@ static JSValue js_call_c_function_data(JSContext *ctx, JSValueConst func_obj, rt->current_stack_frame = sf; // TODO(bnoordhuis) switch realms like js_call_c_function does sf->is_strict_mode = false; + sf->is_constructor = (flags & JS_CALL_FLAG_CONSTRUCTOR) != 0; sf->cur_func = unsafe_unconst(func_obj); sf->arg_count = argc; ret = s->func(ctx, this_val, argc, arg_buf, s->magic, vc(s->data)); @@ -6382,6 +6770,7 @@ static JSValue js_call_c_closure(JSContext *ctx, JSValueConst func_obj, rt->current_stack_frame = sf; // TODO(bnoordhuis) switch realms like js_call_c_function does sf->is_strict_mode = false; + sf->is_constructor = (flags & JS_CALL_FLAG_CONSTRUCTOR) != 0; sf->cur_func = unsafe_unconst(func_obj); sf->arg_count = argc; ret = s->func(ctx, this_val, argc, arg_buf, s->magic, s->opaque); @@ -6452,7 +6841,7 @@ static inline JSShapeProperty *find_own_property1(JSObject *p, JSAtom atom) sh = p->shape; h = (uintptr_t)atom & sh->prop_hash_mask; h = prop_hash_end(sh)[-h - 1]; - prop = sh->prop; + prop = get_shape_prop(sh); while (h) { pr = &prop[h - 1]; if (likely(pr->atom == atom)) { @@ -6473,7 +6862,7 @@ static inline JSShapeProperty *find_own_property(JSProperty **ppr, sh = p->shape; h = (uintptr_t)atom & sh->prop_hash_mask; h = prop_hash_end(sh)[-h - 1]; - prop = sh->prop; + prop = get_shape_prop(sh); while (h) { pr = &prop[h - 1]; if (likely(pr->atom == atom)) { @@ -6487,11 +6876,28 @@ static inline JSShapeProperty *find_own_property(JSProperty **ppr, return NULL; } +/* Release a counted reference an open var_ref held on the coroutine + (async function / generator / async generator) owning the frame it + points into. */ +static void js_release_coro(JSRuntime *rt, JSGCObjectHeader *coro) +{ + switch (JS_GC_TYPE(coro)) { + case JS_GC_OBJ_TYPE_ASYNC_FUNCTION: + js_async_function_free(rt, (JSAsyncFunctionData *)coro); + break; + case JS_GC_OBJ_TYPE_JS_OBJECT: /* generator / async generator */ + JS_FreeValueRT(rt, JS_MKPTR(JS_TAG_OBJECT, (JSObject *)coro)); + break; + default: + abort(); + } +} + static void free_var_ref(JSRuntime *rt, JSVarRef *var_ref) { if (var_ref) { - assert(var_ref->header.ref_count > 0); - if (--var_ref->header.ref_count == 0) { + assert(JS_REF_COUNT(var_ref) > 0); + if (--JS_REF_COUNT(var_ref) == 0) { if (var_ref->is_detached) { JS_FreeValueRT(rt, var_ref->value); remove_gc_object(&var_ref->header); @@ -6499,6 +6905,12 @@ static void free_var_ref(JSRuntime *rt, JSVarRef *var_ref) JSStackFrame *sf = var_ref->stack_frame; assert(sf->var_refs[var_ref->var_ref_idx] == var_ref); sf->var_refs[var_ref->var_ref_idx] = NULL; + /* an open coroutine var_ref is itself a GC object and holds + a counted ref to its coroutine (sf->cur_gc_obj) */ + if (var_ref->is_coro) { + js_release_coro(rt, sf->cur_gc_obj); + remove_gc_object(&var_ref->header); + } } js_free_rt(rt, var_ref); } @@ -6597,7 +7009,10 @@ static void js_bytecode_function_mark(JSRuntime *rt, JSValueConst val, if (var_refs) { for(i = 0; i < b->closure_var_count; i++) { JSVarRef *var_ref = var_refs[i]; - if (var_ref && var_ref->is_detached) { + /* Detached var_refs are GC objects; open var_refs are GC + objects only when they capture a coroutine local (see + get_var_ref). Only those may be marked. */ + if (var_ref && (var_ref->is_detached || var_ref->is_coro)) { mark_func(rt, &var_ref->header); } } @@ -6662,7 +7077,7 @@ static void free_object(JSRuntime *rt, JSObject *p) freeing cycles */ /* free all the fields */ sh = p->shape; - pr = sh->prop; + pr = get_shape_prop(sh); for(i = 0; i < sh->prop_count; i++) { free_property(rt, &p->prop[i], pr->flags); pr++; @@ -6691,7 +7106,7 @@ static void free_object(JSRuntime *rt, JSObject *p) p->u.func.home_object = NULL; remove_gc_object(&p->header); - if (rt->gc_phase == JS_GC_PHASE_REMOVE_CYCLES && p->header.ref_count != 0) { + if (rt->gc_phase == JS_GC_PHASE_REMOVE_CYCLES && JS_REF_COUNT(p) != 0) { list_add_tail(&p->header.link, &rt->gc_zero_ref_count_list); } else { js_free_rt(rt, p); @@ -6700,7 +7115,7 @@ static void free_object(JSRuntime *rt, JSObject *p) static void free_gc_object(JSRuntime *rt, JSGCObjectHeader *gp) { - switch(gp->gc_obj_type) { + switch(JS_GC_TYPE(gp)) { case JS_GC_OBJ_TYPE_JS_OBJECT: free_object(rt, (JSObject *)gp); break; @@ -6723,7 +7138,7 @@ static void free_zero_refcount(JSRuntime *rt) if (el == &rt->gc_zero_ref_count_list) break; p = list_entry(el, JSGCObjectHeader, link); - assert(p->ref_count == 0); + assert(JS_REF_COUNT(p) == 0); free_gc_object(rt, p); } rt->gc_phase = JS_GC_PHASE_NONE; @@ -6799,8 +7214,8 @@ static void js_free_value_rt(JSRuntime *rt, JSValue v) void JS_FreeValueRT(JSRuntime *rt, JSValue v) { if (JS_VALUE_HAS_REF_COUNT(v)) { - JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v); - if (--p->ref_count <= 0) { + void *p = JS_VALUE_GET_PTR(v); + if (--JS_REF_COUNT(p) <= 0) { js_free_value_rt(rt, v); } } @@ -6816,8 +7231,8 @@ void JS_FreeValue(JSContext *ctx, JSValue v) static void add_gc_object(JSRuntime *rt, JSGCObjectHeader *h, JSGCObjectTypeEnum type) { - h->mark = 0; - h->gc_obj_type = type; + JS_GC_MARK(h) = 0; + JS_GC_TYPE(h) = type; list_add_tail(&h->link, &rt->gc_obj_list); } @@ -6859,7 +7274,7 @@ static void mark_weak_map_value(JSRuntime *rt, JSWeakRefRecord *first_weak_ref, static void mark_children(JSRuntime *rt, JSGCObjectHeader *gp, JS_MarkFunc *mark_func) { - switch(gp->gc_obj_type) { + switch(JS_GC_TYPE(gp)) { case JS_GC_OBJ_TYPE_JS_OBJECT: { JSObject *p = (JSObject *)gp; @@ -6869,7 +7284,7 @@ static void mark_children(JSRuntime *rt, JSGCObjectHeader *gp, sh = p->shape; mark_func(rt, &sh->header); /* mark all the fields */ - prs = sh->prop; + prs = get_shape_prop(sh); for(i = 0; i < sh->prop_count; i++) { JSProperty *pr = &p->prop[i]; if (prs->atom != JS_ATOM_NULL) { @@ -6880,7 +7295,8 @@ static void mark_children(JSRuntime *rt, JSGCObjectHeader *gp, if (pr->u.getset.setter) mark_func(rt, &pr->u.getset.setter->header); } else if ((prs->flags & JS_PROP_TMASK) == JS_PROP_VARREF) { - if (pr->u.var_ref->is_detached) { + if (pr->u.var_ref->is_detached || + pr->u.var_ref->is_coro) { /* Note: the tag does not matter provided it is a GC object */ mark_func(rt, &pr->u.var_ref->header); @@ -6922,9 +7338,17 @@ static void mark_children(JSRuntime *rt, JSGCObjectHeader *gp, case JS_GC_OBJ_TYPE_VAR_REF: { JSVarRef *var_ref = (JSVarRef *)gp; - /* only detached variable referenced are taken into account */ - assert(var_ref->is_detached); - JS_MarkValue(rt, *var_ref->pvalue, mark_func); + if (var_ref->is_detached) { + /* the var_ref owns its value */ + JS_MarkValue(rt, *var_ref->pvalue, mark_func); + } else { + /* open var_ref: the value lives in the coroutine's frame + and is marked by the coroutine itself; only keep that + coroutine reachable. (Open var_refs are GC objects only + when they capture a coroutine local.) */ + assert(var_ref->is_coro); + mark_func(rt, var_ref->stack_frame->cur_gc_obj); + } } break; case JS_GC_OBJ_TYPE_ASYNC_FUNCTION: @@ -6957,9 +7381,9 @@ static void mark_children(JSRuntime *rt, JSGCObjectHeader *gp, static void gc_decref_child(JSRuntime *rt, JSGCObjectHeader *p) { - assert(p->ref_count > 0); - p->ref_count--; - if (p->ref_count == 0 && p->mark == 1) { + assert(JS_REF_COUNT(p) > 0); + JS_REF_COUNT(p)--; + if (JS_REF_COUNT(p) == 0 && JS_GC_MARK(p) == 1) { list_del(&p->link); list_add_tail(&p->link, &rt->tmp_obj_list); } @@ -6977,10 +7401,10 @@ static void gc_decref(JSRuntime *rt) tmp_obj_list */ list_for_each_safe(el, el1, &rt->gc_obj_list) { p = list_entry(el, JSGCObjectHeader, link); - assert(p->mark == 0); + assert(JS_GC_MARK(p) == 0); mark_children(rt, p, gc_decref_child); - p->mark = 1; - if (p->ref_count == 0) { + JS_GC_MARK(p) = 1; + if (JS_REF_COUNT(p) == 0) { list_del(&p->link); list_add_tail(&p->link, &rt->tmp_obj_list); } @@ -6989,19 +7413,19 @@ static void gc_decref(JSRuntime *rt) static void gc_scan_incref_child(JSRuntime *rt, JSGCObjectHeader *p) { - p->ref_count++; - if (p->ref_count == 1) { + JS_REF_COUNT(p)++; + if (JS_REF_COUNT(p) == 1) { /* ref_count was 0: remove from tmp_obj_list and add at the end of gc_obj_list */ list_del(&p->link); list_add_tail(&p->link, &rt->gc_obj_list); - p->mark = 0; /* reset the mark for the next GC call */ + JS_GC_MARK(p) = 0; /* reset the mark for the next GC call */ } } static void gc_scan_incref_child2(JSRuntime *rt, JSGCObjectHeader *p) { - p->ref_count++; + JS_REF_COUNT(p)++; } static void gc_scan(JSRuntime *rt) @@ -7012,8 +7436,8 @@ static void gc_scan(JSRuntime *rt) /* keep the objects with a refcount > 0 and their children. */ list_for_each(el, &rt->gc_obj_list) { p = list_entry(el, JSGCObjectHeader, link); - assert(p->ref_count > 0); - p->mark = 0; /* reset the mark for the next GC call */ + assert(JS_REF_COUNT(p) > 0); + JS_GC_MARK(p) = 0; /* reset the mark for the next GC call */ mark_children(rt, p, gc_scan_incref_child); } @@ -7042,7 +7466,7 @@ static void gc_free_cycles(JSRuntime *rt) /* Only need to free the GC object associated with JS values. The rest will be automatically removed because they must be referenced by them. */ - switch(p->gc_obj_type) { + switch(JS_GC_TYPE(p)) { case JS_GC_OBJ_TYPE_JS_OBJECT: case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE: #ifdef ENABLE_DUMPS // JS_DUMP_GC_FREE @@ -7067,8 +7491,8 @@ static void gc_free_cycles(JSRuntime *rt) list_for_each_safe(el, el1, &rt->gc_zero_ref_count_list) { p = list_entry(el, JSGCObjectHeader, link); - assert(p->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT || - p->gc_obj_type == JS_GC_OBJ_TYPE_FUNCTION_BYTECODE); + assert(JS_GC_TYPE(p) == JS_GC_OBJ_TYPE_JS_OBJECT || + JS_GC_TYPE(p) == JS_GC_OBJ_TYPE_FUNCTION_BYTECODE); js_free_rt(rt, p); } @@ -7118,7 +7542,7 @@ static void compute_value_size(JSValue val, JSMemoryUsage_helper *hp); static void compute_jsstring_size(JSString *str, JSMemoryUsage_helper *hp) { if (!str->atom_type) { /* atoms are handled separately */ - double s_ref_count = str->header.ref_count; + double s_ref_count = JS_REF_COUNT(str); hp->str_count += 1 / s_ref_count; hp->str_size += ((sizeof(*str) + (str->len << str->is_wide_char) + 1 - str->is_wide_char) / s_ref_count); @@ -7240,10 +7664,10 @@ void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s) JSShapeProperty *prs; /* XXX: could count the other GC object types too */ - if (gp->gc_obj_type == JS_GC_OBJ_TYPE_FUNCTION_BYTECODE) { + if (JS_GC_TYPE(gp) == JS_GC_OBJ_TYPE_FUNCTION_BYTECODE) { compute_bytecode_size((JSFunctionBytecode *)gp, hp); continue; - } else if (gp->gc_obj_type != JS_GC_OBJ_TYPE_JS_OBJECT) { + } else if (JS_GC_TYPE(gp) != JS_GC_OBJ_TYPE_JS_OBJECT) { continue; } p = (JSObject *)gp; @@ -7253,7 +7677,7 @@ void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s) s->memory_used_count++; s->prop_size += sh->prop_size * sizeof(*p->prop); s->prop_count += sh->prop_count; - prs = sh->prop; + prs = get_shape_prop(sh); for(i = 0; i < sh->prop_count; i++) { JSProperty *pr = &p->prop[i]; if (prs->atom != JS_ATOM_NULL && !(prs->flags & JS_PROP_TMASK)) { @@ -7286,6 +7710,7 @@ void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s) } } break; + case JS_CLASS_ERROR: /* u.object_data */ case JS_CLASS_NUMBER: /* u.object_data */ case JS_CLASS_STRING: /* u.object_data */ case JS_CLASS_BOOLEAN: /* u.object_data */ @@ -7307,7 +7732,7 @@ void JS_ComputeMemoryUsage(JSRuntime *rt, JSMemoryUsage *s) s->js_func_size += b->closure_var_count * sizeof(*var_refs); for (i = 0; i < b->closure_var_count; i++) { if (var_refs[i]) { - double ref_count = var_refs[i]->header.ref_count; + double ref_count = JS_REF_COUNT(var_refs[i]); s->memory_used_count += 1 / ref_count; s->js_func_size += sizeof(*var_refs[i]) / ref_count; /* handle non object closed values */ @@ -7501,7 +7926,7 @@ void JS_DumpMemoryUsage(FILE *fp, const JSMemoryUsage *s, JSRuntime *rt) list_for_each(el, &rt->gc_obj_list) { JSGCObjectHeader *gp = list_entry(el, JSGCObjectHeader, link); JSObject *p; - if (gp->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT) { + if (JS_GC_TYPE(gp) == JS_GC_OBJ_TYPE_JS_OBJECT) { p = (JSObject *)gp; obj_classes[min_uint32(p->class_id, JS_CLASS_INIT_COUNT)]++; } @@ -7749,7 +8174,23 @@ static bool can_add_backtrace(JSValueConst obj) if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) return false; p = JS_VALUE_GET_OBJ(obj); - if (p->class_id != JS_CLASS_ERROR && p->class_id != JS_CLASS_DOM_EXCEPTION) + if (p->class_id != JS_CLASS_DOM_EXCEPTION) + return false; + if (find_own_property1(p, JS_ATOM_stack)) + return false; + return true; +} + +/* Note: it is important that no exception is returned by this function */ +static bool can_store_error_stack(JSValueConst obj) +{ + JSObject *p; + if (JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) + return false; + p = JS_VALUE_GET_OBJ(obj); + if (p->class_id != JS_CLASS_ERROR) + return false; + if (!JS_IsUndefined(p->u.object_data)) return false; if (find_own_property1(p, JS_ATOM_stack)) return false; @@ -7918,10 +8359,8 @@ static void build_backtrace(JSContext *ctx, JSValueConst error_val, JSValue v = js_new_callsite(ctx, &csd[j]); if (JS_IsException(v)) break; - if (JS_DefinePropertyValueUint32(ctx, stack, j, v, JS_PROP_C_W_E) < 0) { - JS_FreeValue(ctx, v); + if (JS_DefinePropertyValueUint32(ctx, stack, j, v, JS_PROP_C_W_E) < 0) break; - } } } // Clear the csd's we didn't use in case of error. @@ -7952,7 +8391,18 @@ static void build_backtrace(JSContext *ctx, JSValueConst error_val, if (JS_IsUndefined(ctx->error_back_trace)) ctx->error_back_trace = js_dup(stack); - if (has_filter_func || can_add_backtrace(error_obj)) { + if (has_filter_func) { + /* Error.captureStackTrace(target, ...): install an own data property + on the (possibly non-Error) target, shadowing the accessor */ + JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_stack, stack, + JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + } else if (can_store_error_stack(error_obj)) { + /* genuine Error instance: store as the [[ErrorData]] stack value */ + p = JS_VALUE_GET_OBJ(error_obj); + JS_FreeValue(ctx, p->u.object_data); + p->u.object_data = stack; + } else if (can_add_backtrace(error_obj)) { + /* DOMException and the like keep an own "stack" data property */ JS_DefinePropertyValue(ctx, error_obj, JS_ATOM_stack, stack, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); } else { @@ -8838,8 +9288,10 @@ static JSValue JS_ThrowTypeErrorPrivateNotFound(JSContext *ctx, JSAtom atom) atom); } -/* Private fields can be added even on non extensible objects or - Proxies */ +/* Per the nonextensible-applies-to-private proposal, private fields cannot + be added to non-extensible objects. Note that a Proxy's JSObject stays + extensible (its trap reflects the target), so private fields can still be + stamped onto Proxies. */ static int JS_DefinePrivateField(JSContext *ctx, JSValueConst obj, JSValue name, JSValue val) { @@ -8859,6 +9311,10 @@ static int JS_DefinePrivateField(JSContext *ctx, JSValueConst obj, } prop = js_symbol_to_atom(ctx, name); p = JS_VALUE_GET_OBJ(obj); + if (unlikely(!p->extensible)) { + JS_ThrowTypeError(ctx, "object is not extensible"); + goto fail; + } prs = find_own_property(&pr, p, prop); if (prs) { JS_ThrowTypeErrorAtom(ctx, "private class field '%s' already exists", @@ -8962,6 +9418,11 @@ static int JS_AddBrand(JSContext *ctx, JSValueConst obj, JSValueConst home_obj) if (JS_IsObject(obj)) { p1 = JS_VALUE_GET_OBJ(obj); + if (unlikely(!p1->extensible)) { + JS_FreeAtom(ctx, brand_atom); + JS_ThrowTypeError(ctx, "object is not extensible"); + return -1; + } prs = find_own_property(&pr, p1, brand_atom); if (unlikely(prs)) { JS_FreeAtom(ctx, brand_atom); @@ -9093,7 +9554,7 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx, exotic_count = 0; tab_exotic = NULL; sh = p->shape; - for(i = 0, prs = sh->prop; i < sh->prop_count; i++, prs++) { + for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) { atom = prs->atom; if (atom != JS_ATOM_NULL) { is_enumerable = ((prs->flags & JS_PROP_ENUMERABLE) != 0); @@ -9180,7 +9641,7 @@ static int __exception JS_GetOwnPropertyNamesInternal(JSContext *ctx, num_sorted = true; sh = p->shape; - for(i = 0, prs = sh->prop; i < sh->prop_count; i++, prs++) { + for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) { atom = prs->atom; if (atom != JS_ATOM_NULL) { is_enumerable = ((prs->flags & JS_PROP_ENUMERABLE) != 0); @@ -9334,20 +9795,12 @@ static int JS_GetOwnPropertyInternal2(JSContext *ctx, JSPropertyDescriptor *desc if (desc) { desc->flags = JS_PROP_WRITABLE | JS_PROP_ENUMERABLE | JS_PROP_CONFIGURABLE; - if (is_typed_array(p->class_id) && typed_array_is_immutable(p)) { - desc->flags &= ~JS_PROP_WRITABLE; - desc->flags &= ~JS_PROP_CONFIGURABLE; - } desc->getter = JS_UNDEFINED; desc->setter = JS_UNDEFINED; desc->value = JS_GetPropertyUint32(ctx, JS_MKPTR(JS_TAG_OBJECT, p), idx); } else if (flags_only) { *pflags = JS_PROP_WRITABLE | JS_PROP_ENUMERABLE | JS_PROP_CONFIGURABLE; - if (is_typed_array(p->class_id) && typed_array_is_immutable(p)) { - *pflags &= ~JS_PROP_WRITABLE; - *pflags &= ~JS_PROP_CONFIGURABLE; - } } return true; } @@ -9734,7 +10187,7 @@ static JSProperty *add_property(JSContext *ctx, p->shape = js_dup_shape(new_sh); js_free_shape(ctx->rt, sh); return &p->prop[new_sh->prop_count - 1]; - } else if (sh->header.ref_count != 1) { + } else if (JS_REF_COUNT(sh) != 1) { /* if the shape is shared, clone it */ new_sh = js_clone_shape(ctx, sh); if (!new_sh) @@ -9746,7 +10199,7 @@ static JSProperty *add_property(JSContext *ctx, p->shape = new_sh; } } - assert(p->shape->header.ref_count == 1); + assert(JS_REF_COUNT(p->shape) == 1); if (add_shape_property(ctx, &p->shape, p, prop, prop_flags)) return NULL; return &p->prop[p->shape->prop_count - 1]; @@ -9814,7 +10267,7 @@ static int delete_property(JSContext *ctx, JSObject *p, JSAtom atom) sh = p->shape; h1 = atom & sh->prop_hash_mask; h = prop_hash_end(sh)[-h1 - 1]; - prop = sh->prop; + prop = get_shape_prop(sh); lpr = NULL; lpr_idx = 0; /* prevent warning */ while (h != 0) { @@ -9825,13 +10278,13 @@ static int delete_property(JSContext *ctx, JSObject *p, JSAtom atom) return false; /* realloc the shape if needed */ if (lpr) - lpr_idx = lpr - sh->prop; + lpr_idx = lpr - get_shape_prop(sh); if (js_shape_prepare_update(ctx, p, &pr)) return -1; sh = p->shape; /* remove property */ if (lpr) { - lpr = &sh->prop[lpr_idx]; + lpr = &get_shape_prop(sh)[lpr_idx]; lpr->hash_next = pr->hash_next; } else { prop_hash_end(sh)[-h1 - 1] = pr->hash_next; @@ -9920,7 +10373,7 @@ static int set_array_length(JSContext *ctx, JSObject *p, JSValue val, if (ret) return -1; /* JS_ToArrayLengthFree() must be done before the read-only test */ - if (unlikely(!(p->shape->prop[0].flags & JS_PROP_WRITABLE))) + if (unlikely(!(get_shape_prop(p->shape)[0].flags & JS_PROP_WRITABLE))) return JS_ThrowTypeErrorReadOnly(ctx, flags, JS_ATOM_length); if (likely(p->fast_array)) { @@ -9964,7 +10417,7 @@ static int set_array_length(JSContext *ctx, JSObject *p, JSValue val, passes in case one of the property is not configurable */ cur_len = len; - for(i = 0, pr = sh->prop; i < sh->prop_count; + for(i = 0, pr = get_shape_prop(sh); i < sh->prop_count; i++, pr++) { if (pr->atom != JS_ATOM_NULL && JS_AtomIsArrayIndex(ctx, &idx, pr->atom)) { @@ -9975,7 +10428,7 @@ static int set_array_length(JSContext *ctx, JSObject *p, JSValue val, } } - for(i = 0, pr = sh->prop; i < sh->prop_count; + for(i = 0, pr = get_shape_prop(sh); i < sh->prop_count; i++, pr++) { if (pr->atom != JS_ATOM_NULL && JS_AtomIsArrayIndex(ctx, &idx, pr->atom)) { @@ -9984,7 +10437,7 @@ static int set_array_length(JSContext *ctx, JSObject *p, JSValue val, delete_property(ctx, p, pr->atom); /* WARNING: the shape may have been modified */ sh = p->shape; - pr = &sh->prop[i]; + pr = &get_shape_prop(sh)[i]; } } } @@ -10004,7 +10457,6 @@ static int set_array_length(JSContext *ctx, JSObject *p, JSValue val, static int expand_fast_array(JSContext *ctx, JSObject *p, uint32_t new_len) { uint32_t old_size, new_size; - size_t slack; JSValue *new_array_prop; if (unlikely(new_len > (uint32_t)INT32_MAX)) { @@ -10019,10 +10471,9 @@ static int expand_fast_array(JSContext *ctx, JSObject *p, uint32_t new_len) return -1; } new_size = max_uint32(new_len, new_size); - new_array_prop = js_realloc2(ctx, p->u.array.u.values, sizeof(JSValue) * new_size, &slack); + new_array_prop = js_realloc(ctx, p->u.array.u.values, sizeof(JSValue) * new_size); if (!new_array_prop) return -1; - new_size += slack / sizeof(*new_array_prop); p->u.array.u.values = new_array_prop; p->u.array.u1.size = new_size; return 0; @@ -10042,7 +10493,7 @@ static int add_fast_array_element(JSContext *ctx, JSObject *p, if (likely(JS_VALUE_GET_TAG(p->prop[0].u.value) == JS_TAG_INT)) { array_len = JS_VALUE_GET_INT(p->prop[0].u.value); if (new_len > array_len) { - if (unlikely(!(p->shape->prop->flags & JS_PROP_WRITABLE))) { + if (unlikely(!(get_shape_prop(p->shape)->flags & JS_PROP_WRITABLE))) { JS_FreeValue(ctx, val); return JS_ThrowTypeErrorReadOnly(ctx, flags, JS_ATOM_length); } @@ -10184,17 +10635,28 @@ static int JS_SetPropertyInternal2(JSContext *ctx, JSValueConst obj, JSAtom prop if (ret < 0) goto fail; typed_array_oob: - // per spec: evaluate value for side effects - if (p1->class_id == JS_CLASS_BIG_INT64_ARRAY || - p1->class_id == JS_CLASS_BIG_UINT64_ARRAY) { - int64_t v; - if (JS_ToBigInt64Free(ctx, &v, val)) - return -1; + /* [[Set]] (10.4.5.5): an out-of-bounds or non-canonical + integer index only coerces the value (step i, via + TypedArraySetElement) when the receiver is the typed + array itself. With any other receiver the invalid + index is dropped (step ii) without evaluating the + value. p is the receiver object (NULL for a primitive + receiver), p1 is the typed array. */ + if (p == p1) { + // evaluate value for side effects + if (p1->class_id == JS_CLASS_BIG_INT64_ARRAY || + p1->class_id == JS_CLASS_BIG_UINT64_ARRAY) { + int64_t v; + if (JS_ToBigInt64Free(ctx, &v, val)) + return -1; + } else { + val = JS_ToNumberFree(ctx, val); + JS_FreeValue(ctx, val); + if (JS_IsException(val)) + return -1; + } } else { - val = JS_ToNumberFree(ctx, val); JS_FreeValue(ctx, val); - if (JS_IsException(val)) - return -1; } return true; } @@ -10615,7 +11077,7 @@ static int JS_CreateProperty(JSContext *ctx, JSObject *p, plen = &p->prop[0]; JS_ToUint32(ctx, &len, plen->u.value); if ((idx + 1) > len) { - pslen = p->shape->prop; + pslen = get_shape_prop(p->shape); if (unlikely(!(pslen->flags & JS_PROP_WRITABLE))) return JS_ThrowTypeErrorReadOnly(ctx, flags, JS_ATOM_length); /* XXX: should update the length after defining @@ -10723,9 +11185,9 @@ static int js_shape_prepare_update(JSContext *ctx, JSObject *p, sh = p->shape; if (sh->is_hashed) { - if (sh->header.ref_count != 1) { + if (JS_REF_COUNT(sh) != 1) { if (pprs) - idx = *pprs - sh->prop; + idx = *pprs - get_shape_prop(sh); /* clone the shape (the resulting one is no longer hashed) */ sh = js_clone_shape(ctx, sh); if (!sh) @@ -10733,7 +11195,7 @@ static int js_shape_prepare_update(JSContext *ctx, JSObject *p, js_free_shape(ctx->rt, p->shape); p->shape = sh; if (pprs) - *pprs = &sh->prop[idx]; + *pprs = &get_shape_prop(sh)[idx]; } else { js_shape_hash_unlink(ctx->rt, sh); sh->is_hashed = false; @@ -10923,7 +11385,7 @@ int JS_DefineProperty(JSContext *ctx, JSValueConst this_obj, property is read-only. */ if ((flags & (JS_PROP_HAS_WRITABLE | JS_PROP_WRITABLE)) == JS_PROP_HAS_WRITABLE) { - prs = p->shape->prop; + prs = get_shape_prop(p->shape); if (js_update_property_flags(ctx, p, &prs, prs->flags & ~JS_PROP_WRITABLE)) return -1; @@ -12210,7 +12672,7 @@ static JSBigInt *js_bigint_new(JSContext *ctx, int len) r = js_malloc(ctx, sizeof(JSBigInt) + len * sizeof(js_limb_t)); if (!r) return NULL; - r->header.ref_count = 1; + JS_REF_COUNT(r) = 1; r->len = len; return r; } @@ -12218,7 +12680,8 @@ static JSBigInt *js_bigint_new(JSContext *ctx, int len) static JSBigInt *js_bigint_set_si(JSBigIntBuf *buf, js_slimb_t a) { JSBigInt *r = (JSBigInt *)buf->big_int_buf; - r->header.ref_count = 0; /* fail safe */ + /* r points into a stack JSBigIntBuf, not an arena block, so it has no + block-header ref_count slot; this temp is never refcounted/freed. */ r->len = 1; r->tab[0] = a; return r; @@ -12227,7 +12690,7 @@ static JSBigInt *js_bigint_set_si(JSBigIntBuf *buf, js_slimb_t a) static JSBigInt *js_bigint_set_si64(JSBigIntBuf *buf, int64_t a) { JSBigInt *r = (JSBigInt *)buf->big_int_buf; - r->header.ref_count = 0; /* fail safe */ + /* stack JSBigIntBuf: no block-header ref_count slot (see js_bigint_set_si) */ if (a >= INT32_MIN && a <= INT32_MAX) { r->len = 1; r->tab[0] = a; @@ -12328,7 +12791,7 @@ static JSBigInt *js_bigint_normalize1(JSContext *ctx, JSBigInt *a, int l) { js_limb_t v; - assert(a->header.ref_count == 1); + assert(JS_REF_COUNT(a) == 1); while (l > 1) { v = a->tab[l - 1]; if ((v != 0 && v != -1) || @@ -14330,10 +14793,10 @@ static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p) sh = p->shape; /* the shape can be NULL while freeing an object */ printf("%14p %4d ", (void *)p, - p->header.ref_count); + JS_REF_COUNT(p)); if (sh) { printf("%3d%c %14p ", - sh->header.ref_count, + JS_REF_COUNT(sh), " *"[sh->is_hashed], (void *)sh->proto); } else { @@ -14377,7 +14840,7 @@ static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p) if (sh) { printf("{ "); - for(i = 0, prs = sh->prop; i < sh->prop_count; i++, prs++) { + for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) { if (prs->atom != JS_ATOM_NULL) { pr = &p->prop[i]; if (!is_first) @@ -14424,13 +14887,13 @@ static __maybe_unused void JS_DumpObject(JSRuntime *rt, JSObject *p) static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p) { - if (p->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT) { + if (JS_GC_TYPE(p) == JS_GC_OBJ_TYPE_JS_OBJECT) { JS_DumpObject(rt, (JSObject *)p); } else { printf("%14p %4d ", (void *)p, - p->ref_count); - switch(p->gc_obj_type) { + JS_REF_COUNT(p)); + switch(JS_GC_TYPE(p)) { case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE: printf("[function bytecode]"); break; @@ -14447,7 +14910,7 @@ static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p) printf("[js_context]"); break; default: - printf("[unknown %d]", p->gc_obj_type); + printf("[unknown %d]", JS_GC_TYPE(p)); break; } printf("\n"); @@ -15324,6 +15787,11 @@ static no_inline __exception int js_binary_logic_slow(JSContext *ctx, JSBigInt *p1, *p2, *r; JSBigIntBuf buf1, buf2; slow_big_int: + /* buf2 is zero-initialized here (after the label, so it also runs on + the goto slow_big_int paths) to silence a -Wmaybe-uninitialized + false positive: GCC cannot prove buf2 is initialized through the + inlined js_bigint_get_si_sat() -> js_bigint_sign() read below. */ + memset(&buf2, 0, sizeof(buf2)); if (JS_VALUE_GET_TAG(op1) == JS_TAG_SHORT_BIG_INT) p1 = js_bigint_set_short(&buf1, op1); else @@ -16230,8 +16698,12 @@ static void js_mapped_arguments_mark(JSRuntime *rt, JSValueConst val, int i; if (var_refs) { for(i = 0; i < p->u.array.count; i++) { - if (var_refs[i] && var_refs[i]->is_detached) - mark_func(rt, &var_refs[i]->header); + /* mapped arguments hold a counted ref to each var_ref; the + ones that are GC objects (detached, or open capturing a + coroutine local) must be marked, like the other holders */ + JSVarRef *vr = var_refs[i]; + if (vr && (vr->is_detached || vr->is_coro)) + mark_func(rt, &vr->header); } } } @@ -16358,7 +16830,7 @@ static JSValue build_for_in_iterator(JSContext *ctx, JSValue obj) JSShapeProperty *prs; /* check that there are no enumerable normal fields */ sh = p->shape; - for(i = 0, prs = sh->prop; i < sh->prop_count; i++, prs++) { + for(i = 0, prs = get_shape_prop(sh); i < sh->prop_count; i++, prs++) { if (prs->flags & JS_PROP_ENUMERABLE) goto normal_case; } @@ -16450,7 +16922,7 @@ static __exception int js_for_in_next(JSContext *ctx, JSValue *sp) JSShapeProperty *prs; if (it->idx >= sh->prop_count) goto done; - prs = &sh->prop[it->idx]; + prs = &get_shape_prop(sh)[it->idx]; prop = prs->atom; it->idx++; if (prop == JS_ATOM_NULL || !(prs->flags & JS_PROP_ENUMERABLE)) @@ -16785,6 +17257,16 @@ static __exception int js_iterator_get_value_done(JSContext *ctx, JSValue *sp) JS_FreeValue(ctx, obj); sp[-1] = value; sp[0] = js_bool(done); + if (done) { + /* Iterator exhausted via {done:true}: drop the iterator object (stack + layout at the for-await `next` call is iter_obj,next,catch_offset,result + so iter_obj is sp[-4]) so the trailing OP_iterator_close skips calling + return(). Mirrors js_for_of_next, which nulls the iterator on done. + Per spec AsyncIteratorClose must NOT run on normal completion. This op + is emitted only by the for-await-of loop, so the layout is fixed. */ + JS_FreeValue(ctx, sp[-4]); + sp[-4] = JS_UNDEFINED; + } return 0; } @@ -17017,8 +17499,9 @@ static JSVarRef *js_create_var_ref(JSContext *ctx, bool is_gc_object) var_ref = js_malloc(ctx, sizeof(JSVarRef)); if (!var_ref) return NULL; - var_ref->header.ref_count = 1; + JS_REF_COUNT(var_ref) = 1; var_ref->is_detached = true; + var_ref->is_coro = false; var_ref->value = JS_UNDEFINED; var_ref->pvalue = &var_ref->value; if (is_gc_object) @@ -17053,7 +17536,7 @@ static JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf, int var_idx, var_ref = sf->var_refs[var_ref_idx]; if (var_ref) { /* reference to the already created local variable */ - var_ref->header.ref_count++; + JS_REF_COUNT(var_ref)++; return var_ref; } @@ -17061,7 +17544,7 @@ static JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf, int var_idx, var_ref = js_malloc(ctx, sizeof(JSVarRef)); if (!var_ref) return NULL; - var_ref->header.ref_count = 1; + JS_REF_COUNT(var_ref) = 1; var_ref->is_detached = false; var_ref->is_lexical = false; var_ref->is_const = false; @@ -17069,6 +17552,19 @@ static JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf, int var_idx, var_ref->stack_frame = sf; sf->var_refs[var_ref_idx] = var_ref; var_ref->pvalue = pvalue; + /* If this local belongs to a coroutine (async function, generator or + async generator), keep the coroutine reachable for as long as a + closure references the variable: make the open var_ref a GC object + holding a counted reference to the coroutine (sf->cur_gc_obj). + Otherwise (ordinary C-stack frame, cur_gc_obj == NULL) the running + function is a GC root and no extra bookkeeping is needed. Snapshot + the decision in is_coro now (cur_gc_obj may become non-NULL later); + the coroutine itself is recovered via stack_frame->cur_gc_obj. */ + var_ref->is_coro = (sf->cur_gc_obj != NULL); + if (sf->cur_gc_obj) { + JS_REF_COUNT(sf->cur_gc_obj)++; + add_gc_object(ctx->rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF); + } return var_ref; } else { /* Variable is not captured (e.g., from eval closures on uncaptured vars). @@ -17076,8 +17572,9 @@ static JSVarRef *get_var_ref(JSContext *ctx, JSStackFrame *sf, int var_idx, var_ref = js_malloc(ctx, sizeof(JSVarRef)); if (!var_ref) return NULL; - var_ref->header.ref_count = 1; + JS_REF_COUNT(var_ref) = 1; var_ref->is_detached = true; + var_ref->is_coro = false; var_ref->value = js_dup(*pvalue); var_ref->pvalue = &var_ref->value; add_gc_object(ctx->rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF); @@ -17118,7 +17615,7 @@ static JSValue js_closure2(JSContext *ctx, JSValue func_obj, case JS_CLOSURE_REF: case JS_CLOSURE_GLOBAL_REF: var_ref = cur_var_refs[cv->var_idx]; - var_ref->header.ref_count++; + JS_REF_COUNT(var_ref)++; break; default: abort(); @@ -17313,11 +17810,27 @@ static int js_op_define_class(JSContext *ctx, JSValue *sp, static void close_var_ref(JSRuntime *rt, JSVarRef *var_ref) { + JSGCObjectHeader *coro; + /* Already closed. This can happen during reentrant coroutine teardown: + closing one var_ref can drop the coroutine's refcount to zero and + re-enter close_var_refs on the same frame. Once detached, the union + holds 'value' rather than stack_frame, so we must not touch it. */ + if (var_ref->is_detached) + return; + /* Read the coroutine (if any) before js_dup() overwrites the union + member that aliases stack_frame with 'value'. */ + coro = var_ref->is_coro ? var_ref->stack_frame->cur_gc_obj : NULL; var_ref->value = js_dup(*var_ref->pvalue); var_ref->pvalue = &var_ref->value; /* the reference is no longer to a local variable */ var_ref->is_detached = true; - add_gc_object(rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF); + var_ref->is_coro = false; + /* an open coroutine var_ref is already a GC object and holds a + reference to its coroutine; drop it now that it is detached. */ + if (coro) + js_release_coro(rt, coro); + else + add_gc_object(rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF); } static void close_var_refs(JSRuntime *rt, JSStackFrame *sf) @@ -17376,6 +17889,7 @@ static JSValue js_call_c_function(JSContext *ctx, JSValueConst func_obj, ctx = p->u.cfunc.realm; /* change the current realm */ sf->is_strict_mode = false; + sf->is_constructor = (flags & JS_CALL_FLAG_CONSTRUCTOR) != 0; sf->cur_func = unsafe_unconst(func_obj); sf->arg_count = argc; arg_buf = argv; @@ -17536,14 +18050,7 @@ static void print_func_name(JSFunctionBytecode *b); static bool needs_backtrace(JSValue exc) { - JSObject *p; - - if (JS_VALUE_GET_TAG(exc) != JS_TAG_OBJECT) - return false; - p = JS_VALUE_GET_OBJ(exc); - if (p->class_id != JS_CLASS_ERROR) - return false; - return !find_own_property1(p, JS_ATOM_stack); + return can_store_error_stack(exc) || can_add_backtrace(exc); } /* argv[] is modified if (flags & JS_CALL_FLAG_COPY_ARGV) = 0. */ @@ -17641,6 +18148,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, return JS_ThrowStackOverflow(caller_ctx); sf->is_strict_mode = b->is_strict_mode; + sf->is_constructor = (flags & JS_CALL_FLAG_CONSTRUCTOR) != 0; arg_buf = (JSValue *)argv; sf->arg_count = argc; sf->cur_func = unsafe_unconst(func_obj); @@ -17668,6 +18176,8 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, sf->var_ref_count = b->var_ref_count; for(i = 0; i < b->var_ref_count; i++) sf->var_refs[i] = NULL; + /* ordinary C-stack frame: not owned by a coroutine GC object */ + sf->cur_gc_obj = NULL; sp = stack_buf; pc = b->byte_code_buf; /* sf->cur_pc must we set to pc before any recursive calls to JS_CallInternal. */ @@ -18633,7 +19143,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, goto exception; if (opcode == OP_make_var_ref_ref) { var_ref = var_refs[idx]; - var_ref->header.ref_count++; + JS_REF_COUNT(var_ref)++; } else { var_ref = get_var_ref(ctx, sf, idx, opcode == OP_make_arg_ref); if (!var_ref) @@ -19369,6 +19879,26 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, { JSValue val; + /* fast path: regular/typed array element by int index */ + if (likely(JS_VALUE_GET_TAG(sp[-2]) == JS_TAG_OBJECT && + JS_VALUE_GET_TAG(sp[-1]) == JS_TAG_INT)) { + JSObject *p = JS_VALUE_GET_OBJ(sp[-2]); + uint32_t idx = JS_VALUE_GET_INT(sp[-1]); + if (likely(p->class_id == JS_CLASS_ARRAY && + idx < p->u.array.count)) { + val = js_dup(p->u.array.u.values[idx]); + JS_FreeValue(ctx, sp[-2]); + sp[-2] = val; + sp--; + BREAK; + } + if (js_get_fast_array_element(ctx, p, idx, &val)) { + JS_FreeValue(ctx, sp[-2]); + sp[-2] = val; + sp--; + BREAK; + } + } sf->cur_pc = pc; val = JS_GetPropertyValue(ctx, sp[-2], sp[-1]); JS_FreeValue(ctx, sp[-2]); @@ -19383,6 +19913,21 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, { JSValue val; + /* fast path: regular/typed array element by int index */ + if (likely(JS_VALUE_GET_TAG(sp[-2]) == JS_TAG_OBJECT && + JS_VALUE_GET_TAG(sp[-1]) == JS_TAG_INT)) { + JSObject *p = JS_VALUE_GET_OBJ(sp[-2]); + uint32_t idx = JS_VALUE_GET_INT(sp[-1]); + if (likely(p->class_id == JS_CLASS_ARRAY && + idx < p->u.array.count)) { + sp[-1] = js_dup(p->u.array.u.values[idx]); + BREAK; + } + if (js_get_fast_array_element(ctx, p, idx, &val)) { + sp[-1] = val; + BREAK; + } + } sf->cur_pc = pc; val = JS_GetPropertyValue(ctx, sp[-2], sp[-1]); sp[-1] = val; @@ -19594,7 +20139,19 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, JS_VALUE_GET_FLOAT64(op2)); JS_X87_FPCW_RESTORE(fpcw); sp--; + } else if (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(op1)) || + JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(op2))) { + /* mixed int/float; the BOTH_FLOAT fast path above is unchanged */ + double d1, d2; + if (!js_arith_to_float64(op1, &d1) || + !js_arith_to_float64(op2, &d2)) + goto add_slow_case; + JS_X87_FPCW_SAVE_AND_ADJUST(fpcw); + sp[-2] = js_float64(d1 + d2); + JS_X87_FPCW_RESTORE(fpcw); + sp--; } else { + add_slow_case: sf->cur_pc = pc; if (js_add_slow(ctx, sp)) goto exception; @@ -19664,6 +20221,17 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, JS_VALUE_GET_FLOAT64(op2)); JS_X87_FPCW_RESTORE(fpcw); sp--; + } else if (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(op1)) || + JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(op2))) { + /* mixed int/float; the BOTH_FLOAT fast path above is unchanged */ + double d1, d2; + if (!js_arith_to_float64(op1, &d1) || + !js_arith_to_float64(op2, &d2)) + goto binary_arith_slow; + JS_X87_FPCW_SAVE_AND_ADJUST(fpcw); + sp[-2] = js_float64(d1 - d2); + JS_X87_FPCW_RESTORE(fpcw); + sp--; } else { goto binary_arith_slow; } @@ -19699,6 +20267,17 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, mul_fp_res: sp[-2] = js_float64(d); sp--; + } else if (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(op1)) || + JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(op2))) { + /* mixed int/float; the BOTH_FLOAT fast path above is unchanged */ + double d1, d2; + if (!js_arith_to_float64(op1, &d1) || + !js_arith_to_float64(op2, &d2)) + goto binary_arith_slow; + JS_X87_FPCW_SAVE_AND_ADJUST(fpcw); + d = d1 * d2; + JS_X87_FPCW_RESTORE(fpcw); + goto mul_fp_res; } else { goto binary_arith_slow; } @@ -19715,6 +20294,23 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, v2 = JS_VALUE_GET_INT(op2); sp[-2] = js_number((double)v1 / (double)v2); sp--; + } else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) { + JS_X87_FPCW_SAVE_AND_ADJUST(fpcw); + sp[-2] = js_number(JS_VALUE_GET_FLOAT64(op1) / + JS_VALUE_GET_FLOAT64(op2)); + JS_X87_FPCW_RESTORE(fpcw); + sp--; + } else if (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(op1)) || + JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(op2))) { + /* mixed int/float; the BOTH_FLOAT fast path above is unchanged */ + double d1, d2; + if (!js_arith_to_float64(op1, &d1) || + !js_arith_to_float64(op2, &d2)) + goto binary_arith_slow; + JS_X87_FPCW_SAVE_AND_ADJUST(fpcw); + sp[-2] = js_number(d1 / d2); + JS_X87_FPCW_RESTORE(fpcw); + sp--; } else { goto binary_arith_slow; } @@ -20562,6 +21158,7 @@ static __exception int async_func_init(JSContext *ctx, JSAsyncFunctionState *s, p = JS_VALUE_GET_OBJ(func_obj); b = p->u.func.function_bytecode; sf->is_strict_mode = b->is_strict_mode; + sf->is_constructor = false; sf->cur_pc = b->byte_code_buf; arg_buf_len = max_int(b->arg_count, argc); local_count = arg_buf_len + b->var_count + b->stack_size; @@ -20576,6 +21173,8 @@ static __exception int async_func_init(JSContext *ctx, JSAsyncFunctionState *s, sf->arg_count = arg_buf_len; sf->var_buf = sf->arg_buf + arg_buf_len; sf->cur_sp = sf->var_buf + b->var_count; + /* set by the caller once the owning coroutine GC object exists */ + sf->cur_gc_obj = NULL; sf->var_refs = (JSVarRef **)(sf->cur_sp + b->stack_size); sf->var_ref_count = b->var_ref_count; for(i = 0; i < b->var_ref_count; i++) @@ -20813,6 +21412,10 @@ static JSValue js_call_generator_function(JSContext *ctx, JSValueConst func_obj, if (JS_IsException(obj)) goto fail; JS_SetOpaqueInternal(obj, s); + /* the body only starts running on the first next(); root captured + locals against the generator object from now on (the initial resume + above only reaches OP_initial_yield, before any user code) */ + s->func_state.frame.cur_gc_obj = &JS_VALUE_GET_OBJ(obj)->header; return obj; fail: free_generator_stack_rt(ctx->rt, s); @@ -20841,7 +21444,7 @@ static void js_async_function_free0(JSRuntime *rt, JSAsyncFunctionData *s) static void js_async_function_free(JSRuntime *rt, JSAsyncFunctionData *s) { - if (--s->header.ref_count == 0) { + if (--JS_REF_COUNT(s) == 0) { js_async_function_free0(rt, s); } } @@ -20880,10 +21483,12 @@ static int js_async_function_resolve_create(JSContext *ctx, if (JS_IsException(resolving_funcs[i])) { if (i == 1) JS_FreeValue(ctx, resolving_funcs[0]); + resolving_funcs[0] = JS_UNDEFINED; + resolving_funcs[1] = JS_UNDEFINED; return -1; } p = JS_VALUE_GET_OBJ(resolving_funcs[i]); - s->header.ref_count++; + JS_REF_COUNT(s)++; p->u.async_function_data = s; } return 0; @@ -20995,7 +21600,7 @@ static JSValue js_async_function_call(JSContext *ctx, JSValueConst func_obj, s = js_mallocz(ctx, sizeof(*s)); if (!s) return JS_EXCEPTION; - s->header.ref_count = 1; + JS_REF_COUNT(s) = 1; add_gc_object(ctx->rt, &s->header, JS_GC_OBJ_TYPE_ASYNC_FUNCTION); s->is_active = false; s->resolving_funcs[0] = JS_UNDEFINED; @@ -21012,6 +21617,9 @@ static JSValue js_async_function_call(JSContext *ctx, JSValueConst func_obj, return JS_EXCEPTION; } s->is_active = true; + /* the body runs immediately (up to the first await), so the frame must + already know its owning coroutine to root captured locals */ + s->func_state.frame.cur_gc_obj = &s->header; if (!js_async_function_resume(ctx, s)) goto fail; @@ -21119,6 +21727,8 @@ static int js_async_generator_resolve_function_create(JSContext *ctx, if (JS_IsException(func)) { if (i == 1) JS_FreeValue(ctx, resolving_funcs[0]); + resolving_funcs[0] = JS_UNDEFINED; + resolving_funcs[1] = JS_UNDEFINED; return -1; } resolving_funcs[i] = func; @@ -21458,6 +22068,9 @@ static JSValue js_async_generator_function_call(JSContext *ctx, if (JS_IsException(obj)) goto fail; s->generator = JS_VALUE_GET_OBJ(obj); + /* root captured locals against the async generator object (the initial + resume above only reaches OP_initial_yield, before any user code) */ + s->func_state.frame.cur_gc_obj = &s->generator->header; JS_SetOpaqueInternal(obj, s); return obj; fail: @@ -21584,6 +22197,7 @@ typedef struct BlockEnv { int label_finally; /* -1 if none */ int scope_level; uint8_t has_iterator : 1; + uint8_t is_async_iterator : 1; uint8_t is_regular_stmt : 1; // i.e. not a loop statement uint8_t has_using : 1; /* scope has using declarations needing disposal */ int using_scope_level; /* scope level for OP_dispose_scope (-1 if none) */ @@ -21959,8 +22573,18 @@ int JS_PRINTF_FORMAT_ATTR(2, 3) js_parse_error(JSParseState *s, JS_PRINTF_FORMAT backtrace_flags = 0; if (s->cur_func && s->cur_func->backtrace_barrier) backtrace_flags = JS_BACKTRACE_FLAG_SINGLE_LEVEL; + /* s->col_num is not advanced during token scanning, so derive the column + as the 1-based offset of the token from the start of its line. */ + int err_col_num = s->token.col_num; + if (s->token.ptr && s->token.ptr >= s->buf_start) { + const uint8_t *line_start = s->token.ptr; + while (line_start > s->buf_start && + line_start[-1] != '\n' && line_start[-1] != '\r') + line_start--; + err_col_num = (int)(s->token.ptr - line_start) + 1; + } build_backtrace(ctx, ctx->rt->current_exception, JS_UNDEFINED, s->filename, - s->line_num, s->col_num, backtrace_flags); + s->token.line_num, err_col_num, backtrace_flags); return -1; } @@ -23733,21 +24357,19 @@ static int push_scope(JSParseState *s) { /* XXX: should check for scope overflow */ if ((fd->scope_count + 1) > fd->scope_size) { int new_size; - size_t slack; JSVarScope *new_buf; /* XXX: potential arithmetic overflow */ new_size = max_int(fd->scope_count + 1, fd->scope_size * 3 / 2); if (fd->scopes == fd->def_scope_array) { - new_buf = js_realloc2(s->ctx, NULL, new_size * sizeof(*fd->scopes), &slack); + new_buf = js_realloc(s->ctx, NULL, new_size * sizeof(*fd->scopes)); if (!new_buf) return -1; memcpy(new_buf, fd->scopes, fd->scope_count * sizeof(*fd->scopes)); } else { - new_buf = js_realloc2(s->ctx, fd->scopes, new_size * sizeof(*fd->scopes), &slack); + new_buf = js_realloc(s->ctx, fd->scopes, new_size * sizeof(*fd->scopes)); if (!new_buf) return -1; } - new_size += slack / sizeof(*new_buf); fd->scopes = new_buf; fd->scope_size = new_size; } @@ -26318,6 +26940,11 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, goto var_error; if (js_define_var(s, var_name, tok)) goto var_error; + if (export_flag) { + if (!add_export_entry(s, s->cur_func->module, var_name, var_name, + JS_EXPORT_TYPE_LOCAL)) + goto var_error; + } opcode = OP_scope_get_var; scope = s->cur_func->scope_level; } else { @@ -26561,6 +27188,14 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) case TOK_IDENT: { JSAtom name; + int identifier_line_num = s->token.line_num; + const uint8_t *identifier_line_start = s->token.ptr; + while (identifier_line_start > s->buf_start && + identifier_line_start[-1] != '\n' && + identifier_line_start[-1] != '\r') + identifier_line_start--; + int identifier_col_num = + (int)(s->token.ptr - identifier_line_start) + 1; if (s->token.u.ident.is_reserved) { return js_parse_error_reserved_identifier(s); } @@ -26598,6 +27233,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags) return -1; } do_get_var: + emit_source_loc_at(s, identifier_line_num, identifier_col_num); emit_op(s, OP_scope_get_var); emit_u32(s, name); emit_u16(s, s->cur_func->scope_level); @@ -27925,6 +28561,7 @@ static void push_break_entry(JSFunctionDef *fd, BlockEnv *be, be->label_finally = -1; be->scope_level = fd->scope_level; be->has_iterator = false; + be->is_async_iterator = false; be->is_regular_stmt = false; be->has_using = false; be->using_scope_level = -1; @@ -27937,6 +28574,45 @@ static void pop_break_entry(JSFunctionDef *fd) fd->top_break = be->prev; } +static void emit_iterator_close(JSParseState *s, bool is_async, + bool preserve_completion) +{ + int label_no_return, label_done; + + if (!is_async) { + emit_op(s, OP_iterator_close); + return; + } + + if (preserve_completion) { + /* iter_obj next completion -> completion iter_obj */ + emit_op(s, OP_nip); + emit_op(s, OP_swap); + } else { + /* iter_obj next catch_offset -> iter_obj */ + emit_op(s, OP_drop); + emit_op(s, OP_drop); + } + emit_op(s, OP_dup); + emit_op(s, OP_is_undefined); + label_done = emit_goto(s, OP_if_true, -1); + emit_op(s, OP_get_field2); + emit_atom(s, JS_ATOM_return); + /* completion? iter_obj return_func */ + emit_op(s, OP_dup); + emit_op(s, OP_is_undefined_or_null); + label_no_return = emit_goto(s, OP_if_true, -1); + emit_op(s, OP_call_method); + emit_u16(s, 0); + emit_op(s, OP_await); + emit_op(s, OP_check_object); + emit_goto(s, OP_goto, label_done); + emit_label(s, label_no_return); + emit_op(s, OP_drop); + emit_label(s, label_done); + emit_op(s, OP_drop); +} + static __exception int emit_break(JSParseState *s, JSAtom name, int is_cont) { BlockEnv *top; @@ -27963,7 +28639,7 @@ static __exception int emit_break(JSParseState *s, JSAtom name, int is_cont) } i = 0; if (top->has_iterator) { - emit_op(s, OP_iterator_close); + emit_iterator_close(s, top->is_async_iterator, false); i += 3; } for(; i < top->drop_count; i++) @@ -28024,25 +28700,8 @@ static void emit_return(JSParseState *s, bool hasval) emit_op(s, OP_nip_catch); /* stack: iter_obj next ret_val */ if (top->has_iterator) { - if (s->cur_func->func_kind == JS_FUNC_ASYNC_GENERATOR) { - int label_next, label_next2; - emit_op(s, OP_nip); /* next */ - emit_op(s, OP_swap); - emit_op(s, OP_get_field2); - emit_atom(s, JS_ATOM_return); - /* stack: iter_obj return_func */ - emit_op(s, OP_dup); - emit_op(s, OP_is_undefined_or_null); - label_next = emit_goto(s, OP_if_true, -1); - emit_op(s, OP_call_method); - emit_u16(s, 0); - emit_op(s, OP_check_object); - emit_op(s, OP_await); - label_next2 = emit_goto(s, OP_goto, -1); - emit_label(s, label_next); - emit_op(s, OP_drop); - emit_label(s, label_next2); - emit_op(s, OP_drop); + if (top->is_async_iterator) { + emit_iterator_close(s, true, true); } else { emit_op(s, OP_rot3r); emit_op(s, OP_undefined); /* dummy catch offset */ @@ -28591,6 +29250,7 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name, that a yield in the expression does not try to close a not-yet-created iterator */ break_entry.has_iterator = true; + break_entry.is_async_iterator = is_async; break_entry.drop_count += 2; if (is_async) emit_op(s, OP_for_await_of_start); @@ -28699,7 +29359,7 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name, if (is_for_of) { /* close and drop enum_rec */ emit_source_loc_at(s, source_line_num, source_col_num); - emit_op(s, OP_iterator_close); + emit_iterator_close(s, is_async, false); } else { emit_op(s, OP_drop); } @@ -29639,7 +30299,7 @@ static JSModuleDef *js_new_module_def(JSContext *ctx, JSAtom name) JS_FreeAtom(ctx, name); return NULL; } - m->header.ref_count = 1; + JS_REF_COUNT(m) = 1; m->module_name = name; m->module_ns = JS_UNDEFINED; m->func_obj = JS_UNDEFINED; @@ -29649,6 +30309,7 @@ static JSModuleDef *js_new_module_def(JSContext *ctx, JSAtom name) m->resolving_funcs[0] = JS_UNDEFINED; m->resolving_funcs[1] = JS_UNDEFINED; m->private_value = JS_UNDEFINED; + m->attributes = JS_UNDEFINED; list_add_tail(&m->link, &ctx->loaded_modules); return m; } @@ -29679,6 +30340,7 @@ static void js_mark_module_def(JSRuntime *rt, JSModuleDef *m, JS_MarkValue(rt, m->resolving_funcs[0], mark_func); JS_MarkValue(rt, m->resolving_funcs[1], mark_func); JS_MarkValue(rt, m->private_value, mark_func); + JS_MarkValue(rt, m->attributes, mark_func); } static void js_free_module_def(JSContext *ctx, JSModuleDef *m) @@ -29720,6 +30382,7 @@ static void js_free_module_def(JSContext *ctx, JSModuleDef *m) JS_FreeValue(ctx, m->resolving_funcs[0]); JS_FreeValue(ctx, m->resolving_funcs[1]); JS_FreeValue(ctx, m->private_value); + JS_FreeValue(ctx, m->attributes); list_del(&m->link); js_free(ctx, m); } @@ -29727,16 +30390,22 @@ static void js_free_module_def(JSContext *ctx, JSModuleDef *m) #ifndef QJS_DISABLE_PARSER static int add_req_module_entry(JSContext *ctx, JSModuleDef *m, - JSAtom module_name) + JSAtom module_name, JSValueConst attributes) { JSReqModuleEntry *rme; - int i; + int i, eq; - /* no need to add the module request if it is already present */ + /* no need to add the module request if an equivalent one (same + specifier and same import attributes) is already present */ for(i = 0; i < m->req_module_entries_count; i++) { rme = &m->req_module_entries[i]; - if (rme->module_name == module_name) - return i; + if (rme->module_name == module_name) { + eq = js_module_attributes_equal(ctx, rme->attributes, attributes); + if (eq < 0) + return -1; + if (eq) + return i; + } } if (js_resize_array(ctx, (void **)&m->req_module_entries, @@ -29747,7 +30416,7 @@ static int add_req_module_entry(JSContext *ctx, JSModuleDef *m, rme = &m->req_module_entries[m->req_module_entries_count++]; rme->module_name = JS_DupAtom(ctx, module_name); rme->module = NULL; - rme->attributes = JS_UNDEFINED; + rme->attributes = js_dup(attributes); return i; } @@ -29982,12 +30651,101 @@ static char *js_default_module_normalize_name(JSContext *ctx, return filename; } -static JSModuleDef *js_find_loaded_module(JSContext *ctx, JSAtom name) +/* Two sets of import attributes are equal if they have the same + key/value pairs; absent attributes are equivalent to an empty set + (ModuleRequestsEqual). Returns 1, 0 or -1 in case of exception. */ +static int js_module_attributes_equal(JSContext *ctx, JSValueConst attr1, + JSValueConst attr2) +{ + JSPropertyEnum *tab = NULL; + uint32_t len = 0, len2 = 0, i; + JSValue v1, v2; + JSAtom a1, a2; + int res; + + if (JS_IsObject(attr1)) { + if (JS_GetOwnPropertyNames(ctx, &tab, &len, attr1, + JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY) < 0) + return -1; + } + if (JS_IsObject(attr2)) { + JSPropertyEnum *tab2 = NULL; + if (JS_GetOwnPropertyNames(ctx, &tab2, &len2, attr2, + JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY) < 0) { + res = -1; + goto done; + } + js_free_prop_enum(ctx, tab2, len2); + } + res = 0; + if (len != len2) + goto done; + for (i = 0; i < len; i++) { + v1 = JS_GetProperty(ctx, attr1, tab[i].atom); + if (JS_IsException(v1)) { + res = -1; + goto done; + } + v2 = JS_GetProperty(ctx, attr2, tab[i].atom); + if (JS_IsException(v2)) { + JS_FreeValue(ctx, v1); + res = -1; + goto done; + } + if (JS_IsUndefined(v2)) { + /* attribute values are strings, undefined means the key is + not present */ + JS_FreeValue(ctx, v1); + goto done; + } + a1 = JS_ValueToAtom(ctx, v1); + a2 = JS_ValueToAtom(ctx, v2); + JS_FreeValue(ctx, v1); + JS_FreeValue(ctx, v2); + if (a1 == JS_ATOM_NULL || a2 == JS_ATOM_NULL) { + JS_FreeAtom(ctx, a1); + JS_FreeAtom(ctx, a2); + res = -1; + goto done; + } + res = (a1 == a2); + JS_FreeAtom(ctx, a1); + JS_FreeAtom(ctx, a2); + if (!res) + goto done; + } + res = 1; +done: + js_free_prop_enum(ctx, tab, len); + return res; +} + +static JSModuleDef *js_find_loaded_module(JSContext *ctx, JSAtom name, + JSValueConst attributes) { struct list_head *el; JSModuleDef *m; + int eq; /* first look at the loaded modules */ + list_for_each(el, &ctx->loaded_modules) { + m = list_entry(el, JSModuleDef, link); + if (m->module_name == name) { + eq = js_module_attributes_equal(ctx, m->attributes, attributes); + if (eq < 0) + return NULL; /* exception */ + if (eq) + return m; + } + } + return NULL; +} + +static JSModuleDef *js_find_loaded_module_by_name(JSContext *ctx, JSAtom name) +{ + struct list_head *el; + JSModuleDef *m; + list_for_each(el, &ctx->loaded_modules) { m = list_entry(el, JSModuleDef, link); if (m->module_name == name) @@ -30028,12 +30786,17 @@ static JSModuleDef *js_host_resolve_imported_module(JSContext *ctx, } /* first look at the loaded modules */ - m = js_find_loaded_module(ctx, module_name); + m = js_find_loaded_module(ctx, module_name, attributes); if (m) { js_free(ctx, cname); JS_FreeAtom(ctx, module_name); return m; } + if (JS_HasException(ctx)) { + js_free(ctx, cname); + JS_FreeAtom(ctx, module_name); + return NULL; + } JS_FreeAtom(ctx, module_name); @@ -30052,6 +30815,11 @@ static JSModuleDef *js_host_resolve_imported_module(JSContext *ctx, } else { m = rt->u.module_loader_func(ctx, cname, rt->module_loader_opaque); } + /* remember the attributes the module was requested with so that + js_find_loaded_module() can tell apart e.g. a text module and a + JS module with the same name */ + if (m && JS_IsObject(attributes) && JS_IsUndefined(m->attributes)) + m->attributes = js_dup(attributes); js_free(ctx, cname); return m; } @@ -30224,6 +30992,62 @@ static JSResolveResultEnum js_resolve_export(JSContext *ctx, return ret; } +static JSVarRef *js_get_local_export_var_ref1(JSContext *ctx, JSModuleDef *m, + JSExportEntry *me, + JSResolveState *s) +{ + JSVarRef *var_ref = me->u.local.var_ref; + int i; + + if (!var_ref) { + JSObject *p = JS_VALUE_GET_OBJ(m->func_obj); + var_ref = p->u.func.var_refs[me->u.local.var_idx]; + } + if (var_ref) + return var_ref; + /* the slot is a re-exported import whose source is not linked yet: follow + the import alias, guarding against re-export cycles like js_resolve_export1 */ + for(i = 0; i < m->import_entries_count; i++) { + JSImportEntry *mi = &m->import_entries[i]; + JSModuleDef *m1, *res_m; + JSExportEntry *res_me; + + if (mi->var_idx != me->u.local.var_idx) + continue; + if (find_resolve_entry(s, m, mi->import_name) >= 0) + return NULL; + if (add_resolve_entry(ctx, s, m, mi->import_name) < 0) + return NULL; + m1 = m->req_module_entries[mi->req_module_idx].module; + if (js_resolve_export1(ctx, &res_m, &res_me, m1, mi->import_name, s) == + JS_RESOLVE_RES_FOUND && + res_me->local_name != JS_ATOM__star_) + return js_get_local_export_var_ref1(ctx, res_m, res_me, s); + break; + } + return NULL; +} + +/* var_ref of a local export. For a re-exported import the slot is NULL until + the source is linked, so follow the import alias; returns NULL if + unresolvable (e.g. a re-export cycle with no concrete binding). */ +static JSVarRef *js_get_local_export_var_ref(JSContext *ctx, JSModuleDef *m, + JSExportEntry *me) +{ + JSResolveState ss, *s = &ss; + JSVarRef *var_ref; + int i; + + s->array = NULL; + s->size = 0; + s->count = 0; + var_ref = js_get_local_export_var_ref1(ctx, m, me, s); + for(i = 0; i < s->count; i++) + JS_FreeAtom(ctx, s->array[i].name); + js_free(ctx, s->array); + return var_ref; +} + static void js_resolve_export_throw_error(JSContext *ctx, JSResolveResultEnum res, JSModuleDef *m, JSAtom export_name) @@ -30414,7 +31238,17 @@ static JSValue js_build_module_ns(JSContext *ctx, JSModuleDef *m) } if (res != JS_RESOLVE_RES_FOUND) { if (res != JS_RESOLVE_RES_AMBIGUOUS) { - js_resolve_export_throw_error(ctx, res, m, en->export_name); + /* for a re-export the binding is missing from the target + module, not from m; report the target and the looked-up name */ + JSExportEntry *me = find_export_entry(ctx, m, en->export_name); + if (me && me->export_type == JS_EXPORT_TYPE_INDIRECT && + me->local_name != JS_ATOM__star_) { + JSModuleDef *m1 = + m->req_module_entries[me->u.req_module_idx].module; + js_resolve_export_throw_error(ctx, res, m1, me->local_name); + } else { + js_resolve_export_throw_error(ctx, res, m, en->export_name); + } goto fail; } en->export_type = EXPORTED_NAME_AMBIGUOUS; @@ -30424,13 +31258,9 @@ static JSValue js_build_module_ns(JSContext *ctx, JSModuleDef *m) en->u.module = res_m->req_module_entries[res_me->u.req_module_idx].module; } else { en->export_type = EXPORTED_NAME_NORMAL; - if (res_me->u.local.var_ref) { - en->u.var_ref = res_me->u.local.var_ref; - } else { - JSObject *p1 = JS_VALUE_GET_OBJ(res_m->func_obj); - p1 = JS_VALUE_GET_OBJ(res_m->func_obj); - en->u.var_ref = p1->u.func.var_refs[res_me->u.local.var_idx]; - } + /* follow the import alias when the slot is NULL (cyclic + re-export of an imported binding) */ + en->u.var_ref = js_get_local_export_var_ref(ctx, res_m, res_me); } } } @@ -30455,7 +31285,7 @@ static JSValue js_build_module_ns(JSContext *ctx, JSModuleDef *m) JS_PROP_VARREF); if (!pr) goto fail; - var_ref->header.ref_count++; + JS_REF_COUNT(var_ref)++; pr->u.var_ref = var_ref; } break; @@ -30546,13 +31376,14 @@ static JSVarRef *js_create_module_var(JSContext *ctx, bool is_lexical) var_ref = js_malloc(ctx, sizeof(JSVarRef)); if (!var_ref) return NULL; - var_ref->header.ref_count = 1; + JS_REF_COUNT(var_ref) = 1; if (is_lexical) var_ref->value = JS_UNINITIALIZED; else var_ref->value = JS_UNDEFINED; var_ref->pvalue = &var_ref->value; var_ref->is_detached = true; + var_ref->is_coro = false; add_gc_object(ctx->rt, &var_ref->header, JS_GC_OBJ_TYPE_VAR_REF); return var_ref; } @@ -30576,7 +31407,7 @@ static int js_create_module_bytecode_function(JSContext *ctx, JSModuleDef *m) p = JS_VALUE_GET_OBJ(func_obj); p->u.func.function_bytecode = b; - b->header.ref_count++; + JS_REF_COUNT(b)++; p->u.func.home_object = NULL; p->u.func.var_refs = NULL; if (b->closure_var_count) { @@ -30723,7 +31554,10 @@ static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m, m1 = m->req_module_entries[me->u.req_module_idx].module; ret = js_resolve_export(ctx, &res_m, &res_me, m1, me->local_name); if (ret != JS_RESOLVE_RES_FOUND) { - js_resolve_export_throw_error(ctx, ret, m, me->export_name); + /* the binding is missing from the re-exported module m1, not + from the re-exporting module m; report m1 and the name being + looked up there, matching the direct-import diagnostic */ + js_resolve_export_throw_error(ctx, ret, m1, me->local_name); goto fail; } } @@ -30771,7 +31605,6 @@ static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m, JSResolveResultEnum ret; JSExportEntry *res_me; JSModuleDef *res_m; - JSObject *p1; ret = js_resolve_export(ctx, &res_m, &res_me, m1, mi->import_name); @@ -30798,12 +31631,19 @@ static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m, module_trace(ctx, "namespace from\n"); } else { - var_ref = res_me->u.local.var_ref; + /* follow the import alias when the slot is NULL (cyclic + re-export of an imported binding) */ + var_ref = js_get_local_export_var_ref(ctx, res_m, res_me); if (!var_ref) { - p1 = JS_VALUE_GET_OBJ(res_m->func_obj); - var_ref = p1->u.func.var_refs[res_me->u.local.var_idx]; + char buf2[ATOM_GET_STR_BUF_SIZE]; + char buf3[ATOM_GET_STR_BUF_SIZE]; + JS_ThrowSyntaxError(ctx, + "circular import: binding '%s' is not resolvable in module '%s'", + JS_AtomGetStr(ctx, buf2, sizeof(buf2), mi->import_name), + JS_AtomGetStr(ctx, buf3, sizeof(buf3), res_m->module_name)); + goto fail; } - var_ref->header.ref_count++; + JS_REF_COUNT(var_ref)++; var_refs[mi->var_idx] = var_ref; module_trace(ctx, "local export (var_ref=%p)\n", (void *)var_ref); @@ -30818,7 +31658,7 @@ static int js_inner_module_linking(JSContext *ctx, JSModuleDef *m, JSExportEntry *me = &m->export_entries[i]; if (me->export_type == JS_EXPORT_TYPE_LOCAL) { var_ref = var_refs[me->u.local.var_idx]; - var_ref->header.ref_count++; + JS_REF_COUNT(var_ref)++; me->u.local.var_ref = var_ref; } } @@ -30942,7 +31782,7 @@ static JSValue js_import_meta(JSContext *ctx) /* XXX: inefficient, need to add a module or script pointer in JSFunctionBytecode */ - m = js_find_loaded_module(ctx, filename); + m = js_find_loaded_module_by_name(ctx, filename); JS_FreeAtom(ctx, filename); if (!m) { fail: @@ -31269,6 +32109,7 @@ static int exec_module_list_cmp(const void *p1, const void *p2, void *opaque) static int js_execute_async_module(JSContext *ctx, JSModuleDef *m); static int js_execute_sync_module(JSContext *ctx, JSModuleDef *m, JSValue *pvalue); +static void js_promise_set_handled(JSContext *ctx, JSValueConst promise); static JSValue js_async_module_execution_rejected(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic, @@ -31406,6 +32247,9 @@ static int js_execute_sync_module(JSContext *ctx, JSModuleDef *m, JS_FreeValue(ctx, promise); } else if (state == JS_PROMISE_REJECTED) { *pvalue = JS_PromiseResult(ctx, promise); + // rejection is propagated to module's evaluation promise; mark this internal + // promise as handled so it's not also surfaced as an unhandled rejection + js_promise_set_handled(ctx, promise); JS_FreeValue(ctx, promise); return -1; } else { @@ -31592,24 +32436,18 @@ static JSValue js_evaluate_module(JSContext *ctx, JSModuleDef *m) #ifndef QJS_DISABLE_PARSER /* Parse 'with { key: "value", ... }' clause for import attributes. - rme->attributes is set to JS_UNDEFINED if no 'with' clause or an object - containing the attributes as key/value pairs. If rme->attributes is already - set (from a previous import of the same module), we still parse the tokens - but skip adding to the object since they should be the same. */ -static __exception int js_parse_with_clause(JSParseState *s, JSReqModuleEntry *rme) + *pattributes is set to JS_UNDEFINED if no 'with' clause or to an object + containing the attributes as key/value pairs. */ +static __exception int js_parse_with_clause(JSParseState *s, JSValue *pattributes) { JSContext *ctx = s->ctx; JSAtom key; int ret; - bool already_set; + *pattributes = JS_UNDEFINED; if (s->token.val != TOK_WITH) return 0; /* no 'with' clause */ - /* If attributes already set from previous import of same module, - just parse to consume tokens but don't modify the object. */ - already_set = !JS_IsUndefined(rme->attributes); - if (next_token(s)) return -1; if (js_parse_expect(s, '{')) @@ -31639,34 +32477,32 @@ static __exception int js_parse_with_clause(JSParseState *s, JSReqModuleEntry *r JS_FreeAtom(ctx, key); return -1; } - if (!already_set) { - if (JS_IsUndefined(rme->attributes)) { - JSValue attributes = JS_NewObjectProto(ctx, JS_NULL); - if (JS_IsException(attributes)) { - JS_FreeAtom(ctx, key); - return -1; - } - rme->attributes = attributes; - } - /* check for duplicate keys */ - ret = JS_HasProperty(ctx, rme->attributes, key); - if (ret != 0) { - if (ret < 0) { - JS_FreeAtom(ctx, key); - return -1; - } else { - js_parse_error(s, "duplicate with key"); - JS_FreeAtom(ctx, key); - return -1; - } + if (JS_IsUndefined(*pattributes)) { + JSValue attributes = JS_NewObjectProto(ctx, JS_NULL); + if (JS_IsException(attributes)) { + JS_FreeAtom(ctx, key); + return -1; } - ret = JS_DefinePropertyValue(ctx, rme->attributes, key, - js_dup(s->token.u.str.str), JS_PROP_C_W_E); + *pattributes = attributes; + } + /* check for duplicate keys */ + ret = JS_HasProperty(ctx, *pattributes, key); + if (ret != 0) { if (ret < 0) { JS_FreeAtom(ctx, key); return -1; + } else { + js_parse_error(s, "duplicate with key"); + JS_FreeAtom(ctx, key); + return -1; } } + ret = JS_DefinePropertyValue(ctx, *pattributes, key, + js_dup(s->token.u.str.str), JS_PROP_C_W_E); + if (ret < 0) { + JS_FreeAtom(ctx, key); + return -1; + } JS_FreeAtom(ctx, key); if (next_token(s)) return -1; @@ -31676,9 +32512,9 @@ static __exception int js_parse_with_clause(JSParseState *s, JSReqModuleEntry *r } } /* check attributes validity if checker function provided */ - if (!already_set && !JS_IsUndefined(rme->attributes) && + if (!JS_IsUndefined(*pattributes) && ctx->rt->module_check_attrs && - ctx->rt->module_check_attrs(ctx, ctx->rt->module_loader_opaque, rme->attributes) < 0) { + ctx->rt->module_check_attrs(ctx, ctx->rt->module_loader_opaque, *pattributes) < 0) { return -1; } return js_parse_expect(s, '}'); @@ -31688,6 +32524,7 @@ static __exception int js_parse_with_clause(JSParseState *s, JSReqModuleEntry *r static __exception int js_parse_from_clause(JSParseState *s, JSModuleDef *m) { JSAtom module_name; + JSValue attributes; int idx; if (!token_is_pseudo_keyword(s, JS_ATOM_from)) { @@ -31708,14 +32545,14 @@ static __exception int js_parse_from_clause(JSParseState *s, JSModuleDef *m) return -1; } - idx = add_req_module_entry(s->ctx, m, module_name); - JS_FreeAtom(s->ctx, module_name); - if (idx < 0) + if (js_parse_with_clause(s, &attributes)) { + JS_FreeValue(s->ctx, attributes); + JS_FreeAtom(s->ctx, module_name); return -1; - if (s->token.val == TOK_WITH) { - if (js_parse_with_clause(s, &m->req_module_entries[idx])) - return -1; } + idx = add_req_module_entry(s->ctx, m, module_name, attributes); + JS_FreeValue(s->ctx, attributes); + JS_FreeAtom(s->ctx, module_name); return idx; } @@ -31971,6 +32808,8 @@ static __exception int js_parse_import(JSParseState *s) first_import = m->import_entries_count; if (s->token.val == TOK_STRING) { + JSValue attributes; + module_name = JS_ValueToAtom(ctx, s->token.u.str.str); if (module_name == JS_ATOM_NULL) return -1; @@ -31978,14 +32817,16 @@ static __exception int js_parse_import(JSParseState *s) JS_FreeAtom(ctx, module_name); return -1; } - idx = add_req_module_entry(ctx, m, module_name); + if (js_parse_with_clause(s, &attributes)) { + JS_FreeValue(ctx, attributes); + JS_FreeAtom(ctx, module_name); + return -1; + } + idx = add_req_module_entry(ctx, m, module_name, attributes); + JS_FreeValue(ctx, attributes); JS_FreeAtom(ctx, module_name); if (idx < 0) return -1; - if (s->token.val == TOK_WITH) { - if (js_parse_with_clause(s, &m->req_module_entries[idx])) - return -1; - } } else { if (s->token.val == TOK_IDENT) { if (s->token.u.ident.is_reserved) { @@ -36219,7 +37060,7 @@ static JSValue js_create_function(JSContext *ctx, JSFunctionDef *fd) b = js_mallocz(ctx, function_size); if (!b) goto fail; - b->header.ref_count = 1; + JS_REF_COUNT(b) = 1; b->byte_code_buf = (void *)((uint8_t*)b + byte_code_offset); b->byte_code_len = fd->byte_code.size; @@ -36340,7 +37181,7 @@ static void free_function_bytecode(JSRuntime *rt, JSFunctionBytecode *b) js_free_rt(rt, b->source); remove_gc_object(&b->header); - if (rt->gc_phase == JS_GC_PHASE_REMOVE_CYCLES && b->header.ref_count != 0) { + if (rt->gc_phase == JS_GC_PHASE_REMOVE_CYCLES && JS_REF_COUNT(b) != 0) { list_add_tail(&b->header.link, &rt->gc_zero_ref_count_list); } else { js_free_rt(rt, b); @@ -37653,7 +38494,7 @@ typedef enum BCTagEnum { BC_TAG_SYMBOL, } BCTagEnum; -#define BC_VERSION 26 +#define BC_VERSION 27 typedef struct BCWriterState { JSContext *ctx; @@ -38135,7 +38976,7 @@ static int JS_WriteObjectTag(BCWriterState *s, JSValueConst obj) for(pass = 0; pass < 2; pass++) { if (pass == 1) bc_put_leb128(s, prop_count); - for(i = 0, pr = sh->prop; i < sh->prop_count; i++, pr++) { + for(i = 0, pr = get_shape_prop(sh); i < sh->prop_count; i++, pr++) { atom = pr->atom; if (atom != JS_ATOM_NULL && (pr->flags & JS_PROP_ENUMERABLE)) { if (pr->flags & JS_PROP_TMASK) { @@ -38867,7 +39708,6 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s) int closure_var_offset, vardefs_offset; memset(&bc, 0, sizeof(bc)); - bc.header.ref_count = 1; //bc.gc_header.mark = 0; if (bc_get_u16(s, &v16)) @@ -38924,7 +39764,7 @@ static JSValue JS_ReadFunctionTag(BCReaderState *s) memcpy(b, &bc, sizeof(*b)); bc.func_name = JS_ATOM_NULL; - b->header.ref_count = 1; + JS_REF_COUNT(b) = 1; if (local_count != 0) { b->vardefs = (void *)((uint8_t*)b + vardefs_offset); } @@ -39127,6 +39967,7 @@ static JSValue JS_ReadModule(BCReaderState *s) for(i = 0; i < m->req_module_entries_count; i++) { JSReqModuleEntry *rme = &m->req_module_entries[i]; JSModuleDef **pm = &rme->module; + rme->attributes = JS_UNDEFINED; if (bc_get_atom(s, &rme->module_name)) goto fail; // Resolves a module either from the cache or by requesting @@ -39376,7 +40217,7 @@ static JSValue JS_ReadArrayBuffer(BCReaderState *s) byte_length, pmax_byte_length, JS_CLASS_ARRAY_BUFFER, (uint8_t*)s->ptr, - js_array_buffer_free, NULL, + js_array_buffer_realloc, NULL, /*alloc_flag*/true); if (JS_IsException(obj)) goto fail; @@ -39448,7 +40289,8 @@ static JSValue JS_ReadRegExp(BCReaderState *s) return JS_EXCEPTION; } - if (bc->is_wide_char) { + if (bc->is_wide_char || + lre_check_bytecode(str8(bc), bc->len) != 0) { js_free_string(ctx->rt, pattern); js_free_string(ctx->rt, bc); return JS_ThrowInternalError(ctx, "bad regexp bytecode"); @@ -42005,10 +42847,50 @@ static JSValue js_error_toString(JSContext *ctx, JSValueConst this_val, return JS_ConcatString(ctx, name, msg); } +static JSValue js_error_get_stack(JSContext *ctx, JSValueConst this_val) +{ + JSObject *p; + + if (JS_VALUE_GET_TAG(this_val) != JS_TAG_OBJECT) + return JS_ThrowTypeErrorNotAnObject(ctx); + p = JS_VALUE_GET_OBJ(this_val); + if (p->class_id != JS_CLASS_ERROR) + return JS_UNDEFINED; + return js_dup(p->u.object_data); +} + +static JSValue js_error_set_stack(JSContext *ctx, JSValueConst this_val, + JSValueConst value) +{ + int ret, flags; + + if (JS_VALUE_GET_TAG(this_val) != JS_TAG_OBJECT) + return JS_ThrowTypeErrorNotAnObject(ctx); + if (!JS_IsString(value)) + return JS_ThrowTypeError(ctx, "Error.prototype.stack setter expects a string"); + if (js_same_value(ctx, this_val, ctx->class_proto[JS_CLASS_ERROR])) + return JS_ThrowTypeError(ctx, "Error.prototype.stack setter called on the home object"); + ret = JS_GetOwnPropertyFlagsInternal(ctx, &flags, JS_VALUE_GET_OBJ(this_val), + JS_ATOM_stack); + if (ret < 0) + return JS_EXCEPTION; + if (ret == 0) { + if (JS_DefinePropertyValue(ctx, this_val, JS_ATOM_stack, js_dup(value), + JS_PROP_C_W_E | JS_PROP_THROW) < 0) + return JS_EXCEPTION; + } else { + if (JS_SetPropertyInternal2(ctx, this_val, JS_ATOM_stack, js_dup(value), + this_val, JS_PROP_THROW) < 0) + return JS_EXCEPTION; + } + return JS_UNDEFINED; +} + static const JSCFunctionListEntry js_error_proto_funcs[] = { JS_CFUNC_DEF("toString", 0, js_error_toString ), JS_PROP_STRING_DEF("name", "Error", JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE ), JS_PROP_STRING_DEF("message", "", JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE ), + JS_CGETSET_DEF("stack", js_error_get_stack, js_error_set_stack ), }; static JSValue js_error_isError(JSContext *ctx, JSValueConst this_val, @@ -42610,7 +43492,8 @@ static int js_typed_array_get_length_unsafe(JSContext *ctx, JSValueConst obj) static JSValue js_typed_array___speciesCreate(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv); + int argc, JSValueConst *argv, + bool require_mutable); static JSValue js_array_every(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int special) @@ -42664,7 +43547,7 @@ static JSValue js_array_every(JSContext *ctx, JSValueConst this_val, case special_map | special_TA: args[0] = obj; args[1] = js_int32(len); - ret = js_typed_array___speciesCreate(ctx, JS_UNDEFINED, 2, args); + ret = js_typed_array___speciesCreate(ctx, JS_UNDEFINED, 2, args, true); if (JS_IsException(ret)) goto exception; break; @@ -42741,7 +43624,7 @@ static JSValue js_array_every(JSContext *ctx, JSValueConst this_val, JSValue arr; args[0] = obj; args[1] = js_int32(n); - arr = js_typed_array___speciesCreate(ctx, JS_UNDEFINED, 2, args); + arr = js_typed_array___speciesCreate(ctx, JS_UNDEFINED, 2, args, true); if (JS_IsException(arr)) goto exception; args[0] = ret; @@ -43265,10 +44148,11 @@ static JSValue js_array_push(JSContext *ctx, JSValueConst this_val, ctx->std_array_prototype)) { uint32_t array_len, new_len; if (likely(JS_VALUE_GET_TAG(p->prop[0].u.value) == JS_TAG_INT && - (p->shape->prop->flags & JS_PROP_WRITABLE))) { + (get_shape_prop(p->shape)->flags & JS_PROP_WRITABLE))) { array_len = JS_VALUE_GET_INT(p->prop[0].u.value); new_len = array_len + argc; - if (likely(new_len >= array_len && new_len <= (uint32_t)INT32_MAX)) { /* no overflow and within fast-array bounds */ + if (likely(array_len == p->u.array.count && + new_len >= array_len && new_len <= (uint32_t)INT32_MAX)) { /* no overflow and within fast-array bounds */ if (unlikely(new_len > p->u.array.u1.size)) { if (expand_fast_array(ctx, p, new_len)) return JS_EXCEPTION; @@ -43855,13 +44739,12 @@ static JSValue js_array_sort(JSContext *ctx, JSValueConst this_val, /* XXX: should special case fast arrays */ for (i = 0; i < len; i++) { if (pos >= array_size) { - size_t new_size, slack; + size_t new_size; ValueSlot *new_array; new_size = (array_size + (array_size >> 1) + 31) & ~15; - new_array = js_realloc2(ctx, array, new_size * sizeof(*array), &slack); + new_array = js_realloc(ctx, array, new_size * sizeof(*array)); if (new_array == NULL) goto exception; - new_size += slack / sizeof(*new_array); array = new_array; array_size = new_size; } @@ -44176,6 +45059,8 @@ static const JSCFunctionListEntry js_iterator_wrap_proto_funcs[] = { JS_ITERATOR_NEXT_DEF("return", 0, js_iterator_wrap_next, GEN_MAGIC_RETURN ), }; +static int check_iterator(JSContext *ctx, JSValueConst obj); + static JSValue js_iterator_constructor_getset(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, @@ -44184,14 +45069,27 @@ static JSValue js_iterator_constructor_getset(JSContext *ctx, { int ret; - if (argc > 0) { // if setter - if (!JS_IsObject(argv[0])) - return JS_ThrowTypeErrorNotAnObject(ctx); - ret = JS_DefinePropertyValue(ctx, this_val, JS_ATOM_constructor, - js_dup(argv[0]), - JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); + if (magic) { // setter (the getter is registered with magic == 0) + // SetterThatIgnoresPrototypeProperties(%Iterator.prototype%, "constructor", v) + // argv[0] is the assigned value; it defaults to undefined because the + // setter is registered with length 1 (see JS_AddIntrinsicBaseObjects). + if (check_iterator(ctx, this_val) < 0) + return JS_EXCEPTION; + if (js_same_value(ctx, this_val, ctx->class_proto[JS_CLASS_ITERATOR])) + return JS_ThrowTypeError(ctx, "Cannot assign to read only property"); + ret = JS_GetOwnProperty(ctx, NULL, this_val, JS_ATOM_constructor); if (ret < 0) return JS_EXCEPTION; + if (ret) { + if (JS_SetProperty(ctx, this_val, JS_ATOM_constructor, js_dup(argv[0])) < 0) + return JS_EXCEPTION; + } else { + if (JS_DefinePropertyValue(ctx, this_val, JS_ATOM_constructor, + js_dup(argv[0]), + JS_PROP_C_W_E | JS_PROP_THROW) < 0) + return JS_EXCEPTION; + } + return JS_UNDEFINED; } return js_dup(func_data[0]); } @@ -44212,7 +45110,7 @@ static JSValue js_iterator_constructor(JSContext *ctx, JSValueConst new_target, typedef struct JSIteratorConcatData { uint32_t index : 31; // elements (not pairs!) in values[] array - uint32_t unused : 1; + uint32_t done : 1; uint32_t count : 31; uint32_t running : 1; JSValue iter, next, values[]; // array of (object, method) pairs @@ -44257,6 +45155,10 @@ static JSValue js_iterator_concat_next(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; if (it->running) return JS_ThrowTypeError(ctx, "already running"); + if (it->done) { + *pdone = true; + return JS_UNDEFINED; + } it->running = true; next: if (it->index >= it->count) { @@ -44310,35 +45212,47 @@ static JSValue js_iterator_concat_next(JSContext *ctx, JSValueConst this_val, } val = JS_GetProperty(ctx, item, JS_ATOM_value); JS_FreeValue(ctx, item); + if (JS_IsException(val)) + goto fail; *pdone = false; done: it->running = false; return val; fail: + /* an abrupt completion finishes the iterator */ + it->done = true; val = JS_EXCEPTION; goto done; } static JSValue js_iterator_concat_return(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) + int argc, JSValueConst *argv, + int *pdone, int magic) { JSIteratorConcatData *it; - JSValue ret, *pval; + JSValue *pval; + int res; it = JS_GetOpaque2(ctx, this_val, JS_CLASS_ITERATOR_CONCAT); if (!it) return JS_EXCEPTION; if (it->running) return JS_ThrowTypeError(ctx, "already running"); - ret = JS_UNDEFINED; + if (it->done) { + /* a completed generator does not run IteratorClose */ + *pdone = true; + return JS_UNDEFINED; + } + res = 0; if (!JS_IsUndefined(it->iter)) { - ret = JS_GetProperty(ctx, it->iter, JS_ATOM_return); - if (JS_IsException(ret)) - return JS_EXCEPTION; + /* IteratorClose: leaves the iterator alone when it has no .return + method and rejects a result that is not an object */ it->running = true; - ret = JS_CallFree(ctx, ret, it->iter, 0, NULL); + res = JS_IteratorClose(ctx, it->iter, /*is_exception_pending*/false); it->running = false; } + /* the iterator is closed either way, the remaining iterables are never + opened */ while (it->index < it->count) { pval = &it->values[it->index++]; JS_FreeValue(ctx, *pval); @@ -44348,15 +45262,13 @@ static JSValue js_iterator_concat_return(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, it->next); it->iter = JS_UNDEFINED; it->next = JS_UNDEFINED; - return ret; + it->done = true; + *pdone = true; + if (res < 0) + return JS_EXCEPTION; + return JS_UNDEFINED; } -static const JSCFunctionListEntry js_iterator_concat_proto_funcs[] = { - JS_ITERATOR_NEXT_DEF("next", 1, js_iterator_concat_next, 0 ), - JS_CFUNC_DEF("return", 1, js_iterator_concat_return ), - JS_PROP_STRING_DEF("[Symbol.toStringTag]", "Iterator Concat", JS_PROP_CONFIGURABLE ), -}; - static JSValue js_iterator_concat(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { @@ -44367,6 +45279,7 @@ static JSValue js_iterator_concat(JSContext *ctx, JSValueConst this_val, if (!it) return JS_EXCEPTION; it->running = false; + it->done = false; it->index = 0; it->count = 0; it->iter = JS_UNDEFINED; @@ -44464,10 +45377,15 @@ typedef struct JSIteratorHelperData { JSValue next; JSValue func; // predicate (filter) or mapper (flatMap, map) JSValue inner; // innerValue (flatMap) - int64_t count; // limit (drop, take) or counter (filter, map, flatMap) + JSValue *buf; // buffered values (chunks, windows) + int64_t count; // limit (drop, take), counter (filter, map, flatMap) or + // chunk/window size (chunks, windows) + int buf_count; // number of values in |buf| + int buf_size; // allocated size of |buf| JSIteratorHelperKindEnum kind : 8; uint8_t executing : 1; uint8_t done : 1; + uint8_t allow_partial : 1; // yield a partial final window (windows) } JSIteratorHelperData; static JSValue js_create_iterator_helper(JSContext *ctx, JSValueConst this_val, @@ -44476,14 +45394,56 @@ static JSValue js_create_iterator_helper(JSContext *ctx, JSValueConst this_val, JSValueConst func; JSValue obj, method; int64_t count; + bool allow_partial; JSIteratorHelperData *it; if (check_iterator(ctx, this_val) < 0) return JS_EXCEPTION; func = JS_UNDEFINED; count = 0; + allow_partial = false; switch(magic) { + case JS_ITERATOR_HELPER_KIND_CHUNKS: + case JS_ITERATOR_HELPER_KIND_WINDOWS: + { + const char *name; + double d; + bool ok; + + name = magic == JS_ITERATOR_HELPER_KIND_CHUNKS ? "chunkSize" + : "windowSize"; + // note: no coercion, the argument must be an integral number + d = NAN; + if (JS_IsNumber(argv[0]) && JS_ToFloat64(ctx, &d, argv[0])) + goto fail; + if (!isfinite(d) || trunc(d) != d) { + JS_ThrowTypeError(ctx, "%s is not an integral number", name); + goto fail; + } + if (d < 1 || d > UINT32_MAX) { + JS_ThrowRangeError(ctx, "%s out of range", name); + goto fail; + } + count = (int64_t)d; + if (magic == JS_ITERATOR_HELPER_KIND_WINDOWS && argc > 1 && + !JS_IsUndefined(argv[1])) { + ok = false; + if (JS_IsString(argv[1])) { + const char *str = JS_ToCString(ctx, argv[1]); + if (!str) + goto fail; + allow_partial = !strcmp(str, "allow-partial"); + ok = allow_partial || !strcmp(str, "only-full"); + JS_FreeCString(ctx, str); + } + if (!ok) { + JS_ThrowTypeError(ctx, "bad undersized option"); + goto fail; + } + } + } + break; case JS_ITERATOR_HELPER_KIND_DROP: case JS_ITERATOR_HELPER_KIND_TAKE: { @@ -44492,30 +45452,16 @@ static JSValue js_create_iterator_helper(JSContext *ctx, JSValueConst this_val, v = JS_ToNumber(ctx, argv[0]); if (JS_IsException(v)) goto fail; - // Check for Infinity. - if (JS_ToFloat64(ctx, &dlimit, v)) { - JS_FreeValue(ctx, v); - goto fail; - } - if (isnan(dlimit)) { - JS_FreeValue(ctx, v); + JS_ToFloat64Free(ctx, &dlimit, v); + if (isnan(dlimit)) goto range_error; - } - if (!isfinite(dlimit)) { - JS_FreeValue(ctx, v); - if (dlimit < 0) - goto range_error; - else - count = MAX_SAFE_INTEGER; - } else { - v = JS_ToIntegerFree(ctx, v); - if (JS_IsException(v)) - goto fail; - if (JS_ToInt64Free(ctx, &count, v)) - goto fail; - } - if (count < 0) + if (isfinite(dlimit) && dlimit > MAX_SAFE_INTEGER) goto range_error; + dlimit = trunc(dlimit); + if (dlimit < 0) + goto range_error; + // +Infinity means "no limit"; use MAX_SAFE_INTEGER + count = isfinite(dlimit) ? (int64_t)dlimit : MAX_SAFE_INTEGER; } break; case JS_ITERATOR_HELPER_KIND_FILTER: @@ -44532,9 +45478,11 @@ static JSValue js_create_iterator_helper(JSContext *ctx, JSValueConst this_val, break; } + /* GetIteratorDirect: an exception here propagates as is, the iterator + object is only closed for a bad argument */ method = JS_GetProperty(ctx, this_val, JS_ATOM_next); if (JS_IsException(method)) - goto fail; + return JS_EXCEPTION; obj = JS_NewObjectClass(ctx, JS_CLASS_ITERATOR_HELPER); if (JS_IsException(obj)) { JS_FreeValue(ctx, method); @@ -44551,9 +45499,13 @@ static JSValue js_create_iterator_helper(JSContext *ctx, JSValueConst this_val, it->func = js_dup(func); it->next = method; it->inner = JS_UNDEFINED; + it->buf = NULL; it->count = count; + it->buf_count = 0; + it->buf_size = 0; it->executing = 0; it->done = 0; + it->allow_partial = allow_partial; JS_SetOpaqueInternal(obj, it); return obj; range_error: @@ -44578,9 +45530,10 @@ static JSValue js_iterator_proto_func(JSContext *ctx, JSValueConst this_val, if (check_function(ctx, argv[0])) goto fail; func = js_dup(argv[0]); + /* GetIteratorDirect: propagates as is, no IteratorClose */ method = JS_GetProperty(ctx, this_val, JS_ATOM_next); if (JS_IsException(method)) - goto fail; + goto step_fail; r = JS_UNDEFINED; @@ -44591,7 +45544,7 @@ static JSValue js_iterator_proto_func(JSContext *ctx, JSValueConst this_val, for (idx = 0; /*empty*/; idx++) { item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done); if (JS_IsException(item)) - goto fail; + goto step_fail; if (done) break; index_val = js_int64(idx); @@ -44620,7 +45573,7 @@ static JSValue js_iterator_proto_func(JSContext *ctx, JSValueConst this_val, for (idx = 0; /*empty*/; idx++) { item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done); if (JS_IsException(item)) - goto fail; + goto step_fail; if (done) break; index_val = js_int64(idx); @@ -44641,6 +45594,7 @@ static JSValue js_iterator_proto_func(JSContext *ctx, JSValueConst this_val, } break; } + JS_FreeValue(ctx, item); index_val = JS_UNDEFINED; ret = JS_UNDEFINED; item = JS_UNDEFINED; @@ -44652,7 +45606,7 @@ static JSValue js_iterator_proto_func(JSContext *ctx, JSValueConst this_val, for (idx = 0; /*empty*/; idx++) { item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done); if (JS_IsException(item)) - goto fail; + goto step_fail; if (done) break; index_val = js_int64(idx); @@ -44676,7 +45630,7 @@ static JSValue js_iterator_proto_func(JSContext *ctx, JSValueConst this_val, for (idx = 0; /*empty*/; idx++) { item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done); if (JS_IsException(item)) - goto fail; + goto step_fail; if (done) break; index_val = js_int64(idx); @@ -44709,12 +45663,81 @@ static JSValue js_iterator_proto_func(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, method); return r; fail: + /* an abrupt completion from the callback closes the iterator + (IfAbruptCloseIterator) */ JS_IteratorClose(ctx, this_val, true); +step_fail: + /* GetIteratorDirect and IteratorStepValue leave the iterator alone */ JS_FreeValue(ctx, func); JS_FreeValue(ctx, method); return JS_EXCEPTION; } +static JSValue js_iterator_proto_includes(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + JSValue item, method; + int64_t to_skip, skipped; + double d; + int done; + + if (check_iterator(ctx, this_val) < 0) + return JS_EXCEPTION; + + // skippedElements is deliberately not coerced: anything that isn't an + // integral Number (or +/-Infinity) is a TypeError, and the underlying + // iterator is closed before the error propagates. + to_skip = 0; + if (argc > 1 && !JS_IsUndefined(argv[1])) { + if (!JS_IsNumber(argv[1])) { + JS_ThrowTypeError(ctx, "not a number"); + goto fail; + } + JS_ToFloat64(ctx, &d, argv[1]); // cannot fail + if (isnan(d) || (isfinite(d) && trunc(d) != d)) { + JS_ThrowTypeError(ctx, "not an integral number"); + goto fail; + } + if (d < 0 || (isfinite(d) && d > MAX_SAFE_INTEGER)) { + JS_ThrowRangeError(ctx, "must be positive"); + goto fail; + } + // +Infinity means "skip everything"; use MAX_SAFE_INTEGER + to_skip = isfinite(d) ? (int64_t)d : MAX_SAFE_INTEGER; + } + + // Note: a failure here propagates without closing the iterator. + method = JS_GetProperty(ctx, this_val, JS_ATOM_next); + if (JS_IsException(method)) + return JS_EXCEPTION; + + for (skipped = 0; /*empty*/; /*empty*/) { + item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done); + if (JS_IsException(item)) { + // IteratorStepValue marks the iterator done, it does not close it. + JS_FreeValue(ctx, method); + return JS_EXCEPTION; + } + if (done) { + JS_FreeValue(ctx, method); + return JS_FALSE; + } + if (skipped < to_skip) { + skipped++; + } else if (js_same_value_zero(ctx, item, argv[0])) { + JS_FreeValue(ctx, item); + JS_FreeValue(ctx, method); + if (JS_IteratorClose(ctx, this_val, false) < 0) + return JS_EXCEPTION; + return JS_TRUE; + } + JS_FreeValue(ctx, item); + } +fail: + JS_IteratorClose(ctx, this_val, true); + return JS_EXCEPTION; +} + static JSValue js_iterator_proto_reduce(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { @@ -44731,26 +45754,28 @@ static JSValue js_iterator_proto_reduce(JSContext *ctx, JSValueConst this_val, if (check_function(ctx, argv[0])) goto exception; func = js_dup(argv[0]); + /* GetIteratorDirect: propagates as is, no IteratorClose */ method = JS_GetProperty(ctx, this_val, JS_ATOM_next); if (JS_IsException(method)) - goto exception; + goto step_exception; if (argc > 1) { acc = js_dup(argv[1]); idx = 0; } else { acc = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done); if (JS_IsException(acc)) - goto exception; + goto step_exception; if (done) { + /* the iterator is already done, don't close it */ JS_ThrowTypeError(ctx, "empty iterator"); - goto exception; + goto step_exception; } idx = 1; } for (/* empty */; /*empty*/; idx++) { item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done); if (JS_IsException(item)) - goto exception; + goto step_exception; if (done) break; index_val = js_int64(idx); @@ -44772,7 +45797,11 @@ static JSValue js_iterator_proto_reduce(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, method); return acc; exception: + /* an abrupt completion from the reducer closes the iterator + (IfAbruptCloseIterator) */ JS_IteratorClose(ctx, this_val, true); +step_exception: + /* GetIteratorDirect and IteratorStepValue leave the iterator alone */ JS_FreeValue(ctx, acc); JS_FreeValue(ctx, func); JS_FreeValue(ctx, method); @@ -44815,6 +45844,69 @@ static JSValue js_iterator_proto_toArray(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; } +static JSValue js_iterator_proto_join(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv) +{ + JSValue item, method, sep = JS_UNDEFINED; + StringBuffer b_s, *b = &b_s; + JSString *p = NULL; + bool first; + int c, done; + + if (check_iterator(ctx, this_val) < 0) + return JS_EXCEPTION; + c = ','; /* default separator */ + if (!JS_IsUndefined(argv[0])) { + sep = JS_ToString(ctx, argv[0]); + if (JS_IsException(sep)) { + JS_IteratorClose(ctx, this_val, /*is_exception_pending*/true); + return JS_EXCEPTION; + } + p = JS_VALUE_GET_STRING(sep); + if (p->len == 1 && !p->is_wide_char) + c = str8(p)[0]; + else + c = -1; + } + method = JS_GetProperty(ctx, this_val, JS_ATOM_next); + if (JS_IsException(method)) { + JS_FreeValue(ctx, sep); + return JS_EXCEPTION; + } + string_buffer_init(ctx, b, 0); + for (first = true; /*empty*/; first = false) { + item = JS_IteratorNext(ctx, this_val, method, 0, NULL, &done); + if (JS_IsException(item)) + goto fail; + if (done) + break; + if (!first) { + if (c >= 0) + string_buffer_putc8(b, c); + else + string_buffer_concat(b, p, 0, p->len); + } + /* nullish values contribute the empty string */ + if (JS_IsNull(item) || JS_IsUndefined(item)) { + JS_FreeValue(ctx, item); + continue; + } + if (string_buffer_concat_value_free(b, item)) + goto close; + } + JS_FreeValue(ctx, method); + JS_FreeValue(ctx, sep); + return string_buffer_end(b); + +close: + JS_IteratorClose(ctx, this_val, /*is_exception_pending*/true); +fail: + string_buffer_free(b); + JS_FreeValue(ctx, method); + JS_FreeValue(ctx, sep); + return JS_EXCEPTION; +} + static JSValue js_async_dispose_to_undef(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic, JSValueConst *func_data); @@ -44901,7 +45993,7 @@ static JSValue js_iterator_proto_set_toStringTag(JSContext *ctx, JSValueConst th if (JS_SetProperty(ctx, this_val, JS_ATOM_Symbol_toStringTag, js_dup(val)) < 0) return JS_EXCEPTION; } else { - if (JS_DefinePropertyValueConst(ctx, this_val, JS_ATOM_Symbol_toStringTag, val, JS_PROP_C_W_E) < 0) + if (JS_DefinePropertyValueConst(ctx, this_val, JS_ATOM_Symbol_toStringTag, val, JS_PROP_C_W_E | JS_PROP_THROW) < 0) return JS_EXCEPTION; } return JS_UNDEFINED; @@ -44916,6 +46008,9 @@ static void js_iterator_helper_finalizer(JSRuntime *rt, JSValueConst val) JS_FreeValueRT(rt, it->func); JS_FreeValueRT(rt, it->next); JS_FreeValueRT(rt, it->inner); + while (it->buf_count > 0) + JS_FreeValueRT(rt, it->buf[--it->buf_count]); + js_free_rt(rt, it->buf); js_free_rt(rt, it); } } @@ -44930,6 +46025,8 @@ static void js_iterator_helper_mark(JSRuntime *rt, JSValueConst val, JS_MarkValue(rt, it->func, mark_func); JS_MarkValue(rt, it->next, mark_func); JS_MarkValue(rt, it->inner, mark_func); + for (int i = 0; i < it->buf_count; i++) + JS_MarkValue(rt, it->buf[i], mark_func); } } @@ -44938,9 +46035,21 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val, int *pdone, int magic) { JSIteratorHelperData *it; + bool finished; JSValue ret; *pdone = false; + finished = false; + + /* Iterator.concat() also hands out Iterator Helper objects, sharing this + prototype but keeping their own state */ + if (JS_VALUE_GET_TAG(this_val) == JS_TAG_OBJECT && + JS_VALUE_GET_OBJ(this_val)->class_id == JS_CLASS_ITERATOR_CONCAT) { + if (magic == GEN_MAGIC_RETURN) + return js_iterator_concat_return(ctx, this_val, argc, argv, pdone, + magic); + return js_iterator_concat_next(ctx, this_val, argc, argv, pdone, magic); + } it = JS_GetOpaque2(ctx, this_val, JS_CLASS_ITERATOR_HELPER); if (!it) @@ -44955,60 +46064,102 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val, it->executing = 1; switch (it->kind) { - case JS_ITERATOR_HELPER_KIND_DROP: + case JS_ITERATOR_HELPER_KIND_CHUNKS: + case JS_ITERATOR_HELPER_KIND_WINDOWS: { - JSValue item, method; - if (magic == GEN_MAGIC_NEXT) { - method = js_dup(it->next); - } else { - method = JS_GetProperty(ctx, it->obj, JS_ATOM_return); - if (JS_IsException(method)) - goto fail; + bool windows = it->kind == JS_ITERATOR_HELPER_KIND_WINDOWS; + JSValue item; + + if (magic == GEN_MAGIC_RETURN) + goto close; + for (;;) { + item = JS_IteratorNext(ctx, it->obj, it->next, 0, NULL, pdone); + if (JS_IsException(item)) + goto step_fail; + if (*pdone) { + JS_FreeValue(ctx, item); + /* the underlying iterator is done: yield what's left in + the buffer, if anything, then stop */ + finished = true; + ret = JS_UNDEFINED; + if (it->buf_count < 1) + goto done; + if (windows) { + /* a full window was already yielded */ + if (!it->allow_partial || it->buf_count >= it->count) + goto done; + ret = js_create_array(ctx, it->buf_count, vc(it->buf)); + } else { + ret = JS_NewArrayFrom(ctx, it->buf_count, it->buf); + it->buf_count = 0; // ownership transferred + } + if (JS_IsException(ret)) + goto step_fail; + *pdone = false; + goto done; + } + if (windows && it->buf_count == it->count) { + /* slide the window */ + JS_FreeValue(ctx, it->buf[0]); + it->buf_count--; + memmove(it->buf, &it->buf[1], + it->buf_count * sizeof(*it->buf)); + } + if (js_resize_array(ctx, (void **)&it->buf, sizeof(*it->buf), + &it->buf_size, it->buf_count + 1)) { + JS_FreeValue(ctx, item); + goto step_fail; + } + it->buf[it->buf_count++] = item; + if (it->buf_count == it->count) { + if (windows) { + ret = js_create_array(ctx, it->buf_count, vc(it->buf)); + } else { + ret = JS_NewArrayFrom(ctx, it->buf_count, it->buf); + it->buf_count = 0; // ownership transferred + } + if (JS_IsException(ret)) + goto step_fail; + goto done; + } } + } + break; + case JS_ITERATOR_HELPER_KIND_DROP: + { + JSValue item; + if (magic == GEN_MAGIC_RETURN) + goto close; while (it->count > 0) { it->count--; - item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone); - if (JS_IsException(item)) { - JS_FreeValue(ctx, method); - goto fail; - } + item = JS_IteratorNext(ctx, it->obj, it->next, 0, NULL, pdone); + if (JS_IsException(item)) + goto step_fail; JS_FreeValue(ctx, item); - if (magic == GEN_MAGIC_RETURN) - *pdone = true; if (*pdone) { - JS_FreeValue(ctx, method); ret = JS_UNDEFINED; goto done; } } - item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone); - JS_FreeValue(ctx, method); + item = JS_IteratorNext(ctx, it->obj, it->next, 0, NULL, pdone); if (JS_IsException(item)) - goto fail; + goto step_fail; ret = item; goto done; } break; case JS_ITERATOR_HELPER_KIND_FILTER: { - JSValue item, method, selected, index_val; + JSValue item, selected, index_val; JSValueConst args[2]; - if (magic == GEN_MAGIC_NEXT) { - method = js_dup(it->next); - } else { - method = JS_GetProperty(ctx, it->obj, JS_ATOM_return); - if (JS_IsException(method)) - goto fail; - } + if (magic == GEN_MAGIC_RETURN) + goto close; filter_again: - item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone); - if (JS_IsException(item)) { - JS_FreeValue(ctx, method); - goto fail; - } - if (*pdone || magic == GEN_MAGIC_RETURN) { - JS_FreeValue(ctx, method); + item = JS_IteratorNext(ctx, it->obj, it->next, 0, NULL, pdone); + if (JS_IsException(item)) + goto step_fail; + if (*pdone) { ret = item; goto done; } @@ -45018,14 +46169,14 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val, selected = JS_Call(ctx, it->func, JS_UNDEFINED, countof(args), args); JS_FreeValue(ctx, index_val); if (JS_IsException(selected)) { - JS_FreeValue(ctx, method); + JS_FreeValue(ctx, item); goto fail; } if (JS_ToBoolFree(ctx, selected)) { - JS_FreeValue(ctx, method); ret = item; goto done; } + JS_FreeValue(ctx, item); goto filter_again; } break; @@ -45033,20 +46184,14 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val, { JSValue item, method, index_val, iter; JSValueConst args[2]; + if (magic == GEN_MAGIC_RETURN) + goto close; flat_map_again: if (JS_IsUndefined(it->inner)) { - if (magic == GEN_MAGIC_NEXT) { - method = js_dup(it->next); - } else { - method = JS_GetProperty(ctx, it->obj, JS_ATOM_return); - if (JS_IsException(method)) - goto fail; - } - item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone); - JS_FreeValue(ctx, method); + item = JS_IteratorNext(ctx, it->obj, it->next, 0, NULL, pdone); if (JS_IsException(item)) - goto fail; - if (*pdone || magic == GEN_MAGIC_RETURN) { + goto step_fail; + if (*pdone) { ret = item; goto done; } @@ -45082,27 +46227,20 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val, it->inner = iter; } - if (magic == GEN_MAGIC_NEXT) - method = JS_GetProperty(ctx, it->inner, JS_ATOM_next); - else - method = JS_GetProperty(ctx, it->inner, JS_ATOM_return); + method = JS_GetProperty(ctx, it->inner, JS_ATOM_next); if (JS_IsException(method)) { inner_fail: - JS_IteratorClose(ctx, it->inner, false); + /* the inner iterator is only marked done, the outer one is + closed by the |fail| label */ JS_FreeValue(ctx, it->inner); it->inner = JS_UNDEFINED; goto fail; } - if (magic == GEN_MAGIC_RETURN && (JS_IsUndefined(method) || JS_IsNull(method))) { - goto inner_end; - } else { - item = JS_IteratorNext(ctx, it->inner, method, 0, NULL, pdone); - JS_FreeValue(ctx, method); - if (JS_IsException(item)) - goto inner_fail; - } + item = JS_IteratorNext(ctx, it->inner, method, 0, NULL, pdone); + JS_FreeValue(ctx, method); + if (JS_IsException(item)) + goto inner_fail; if (*pdone) { - inner_end: *pdone = false; // The outer iterator must continue. JS_IteratorClose(ctx, it->inner, false); JS_FreeValue(ctx, it->inner); @@ -45115,20 +46253,14 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val, break; case JS_ITERATOR_HELPER_KIND_MAP: { - JSValue item, method, index_val; + JSValue item, index_val; JSValueConst args[2]; - if (magic == GEN_MAGIC_NEXT) { - method = js_dup(it->next); - } else { - method = JS_GetProperty(ctx, it->obj, JS_ATOM_return); - if (JS_IsException(method)) - goto fail; - } - item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone); - JS_FreeValue(ctx, method); + if (magic == GEN_MAGIC_RETURN) + goto close; + item = JS_IteratorNext(ctx, it->obj, it->next, 0, NULL, pdone); if (JS_IsException(item)) - goto fail; - if (*pdone || magic == GEN_MAGIC_RETURN) { + goto step_fail; + if (*pdone) { ret = item; goto done; } @@ -45145,29 +46277,14 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val, break; case JS_ITERATOR_HELPER_KIND_TAKE: { - JSValue item, method; - if (it->count > 0) { - if (magic == GEN_MAGIC_NEXT) { - method = js_dup(it->next); - } else { - method = JS_GetProperty(ctx, it->obj, JS_ATOM_return); - if (JS_IsException(method)) - goto fail; - } - it->count--; - item = JS_IteratorNext(ctx, it->obj, method, 0, NULL, pdone); - JS_FreeValue(ctx, method); - if (JS_IsException(item)) - goto fail; - ret = item; - goto done; - } - - *pdone = true; - if (JS_IteratorClose(ctx, it->obj, false)) - ret = JS_EXCEPTION; - else - ret = JS_UNDEFINED; + JSValue item; + if (magic == GEN_MAGIC_RETURN || it->count == 0) + goto close; + it->count--; + item = JS_IteratorNext(ctx, it->obj, it->next, 0, NULL, pdone); + if (JS_IsException(item)) + goto step_fail; + ret = item; goto done; } break; @@ -45175,12 +46292,40 @@ static JSValue js_iterator_helper_next(JSContext *ctx, JSValueConst this_val, abort(); } +close: + *pdone = true; + ret = JS_UNDEFINED; + if (!JS_IsUndefined(it->inner)) { + if (JS_IteratorClose(ctx, it->inner, false)) + ret = JS_EXCEPTION; + JS_FreeValue(ctx, it->inner); + it->inner = JS_UNDEFINED; + } + if (JS_IteratorClose(ctx, it->obj, JS_IsException(ret))) + ret = JS_EXCEPTION; + done: - it->done = magic == GEN_MAGIC_NEXT ? *pdone : 1; + it->done = finished || (magic == GEN_MAGIC_NEXT ? *pdone : 1); it->executing = 0; + if (it->done && it->buf) { + while (it->buf_count > 0) + JS_FreeValue(ctx, it->buf[--it->buf_count]); + js_free(ctx, it->buf); + it->buf = NULL; + it->buf_size = 0; + } return ret; +step_fail: + /* an abrupt completion from stepping the iterator object, or from the body + of the closure, does not close it: IteratorStepValue only marks the + iterator record done */ + finished = true; + ret = JS_EXCEPTION; + goto done; fail: - /* close the iterator object, preserving pending exception */ + /* an abrupt completion from the callback closes the iterator object + (IfAbruptCloseIterator), preserving the pending exception */ + finished = true; JS_IteratorClose(ctx, it->obj, true); ret = JS_EXCEPTION; goto done; @@ -45192,15 +46337,19 @@ static const JSCFunctionListEntry js_iterator_funcs[] = { }; static const JSCFunctionListEntry js_iterator_proto_funcs[] = { + JS_CFUNC_MAGIC_DEF("chunks", 1, js_create_iterator_helper, JS_ITERATOR_HELPER_KIND_CHUNKS ), JS_CFUNC_MAGIC_DEF("drop", 1, js_create_iterator_helper, JS_ITERATOR_HELPER_KIND_DROP ), JS_CFUNC_MAGIC_DEF("filter", 1, js_create_iterator_helper, JS_ITERATOR_HELPER_KIND_FILTER ), JS_CFUNC_MAGIC_DEF("flatMap", 1, js_create_iterator_helper, JS_ITERATOR_HELPER_KIND_FLAT_MAP ), JS_CFUNC_MAGIC_DEF("map", 1, js_create_iterator_helper, JS_ITERATOR_HELPER_KIND_MAP ), JS_CFUNC_MAGIC_DEF("take", 1, js_create_iterator_helper, JS_ITERATOR_HELPER_KIND_TAKE ), + JS_CFUNC_MAGIC_DEF("windows", 1, js_create_iterator_helper, JS_ITERATOR_HELPER_KIND_WINDOWS ), JS_CFUNC_MAGIC_DEF("every", 1, js_iterator_proto_func, JS_ITERATOR_HELPER_KIND_EVERY ), JS_CFUNC_MAGIC_DEF("find", 1, js_iterator_proto_func, JS_ITERATOR_HELPER_KIND_FIND), JS_CFUNC_MAGIC_DEF("forEach", 1, js_iterator_proto_func, JS_ITERATOR_HELPER_KIND_FOR_EACH ), JS_CFUNC_MAGIC_DEF("some", 1, js_iterator_proto_func, JS_ITERATOR_HELPER_KIND_SOME ), + JS_CFUNC_DEF("includes", 1, js_iterator_proto_includes ), + JS_CFUNC_DEF("join", 1, js_iterator_proto_join ), JS_CFUNC_DEF("reduce", 1, js_iterator_proto_reduce ), JS_CFUNC_DEF("toArray", 0, js_iterator_proto_toArray ), JS_CFUNC_DEF("[Symbol.dispose]", 0, js_iterator_proto_dispose ), @@ -47831,14 +48980,6 @@ static uint64_t xorshift64star(uint64_t *pstate) return x * 0x2545F4914F6CDD1D; } -static void js_random_init(JSContext *ctx) -{ - ctx->random_state = js__gettimeofday_us(); - /* the state must be non zero */ - if (ctx->random_state == 0) - ctx->random_state = 1; -} - static JSValue js_math_random(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { @@ -48062,7 +49203,10 @@ static JSValue js_compile_regexp(JSContext *ctx, JSValueConst pattern, if (re_flags & LRE_FLAG_UNICODE_SETS) return JS_ThrowSyntaxError(ctx, "invalid regular expression flags"); - str = JS_ToCStringLen2(ctx, &len, pattern, !(re_flags & LRE_FLAG_UNICODE)); + /* The v flag implies full Unicode, like u, so the pattern must be + UTF-8 (not CESU-8) for both. */ + str = JS_ToCStringLen2(ctx, &len, pattern, + !(re_flags & (LRE_FLAG_UNICODE | LRE_FLAG_UNICODE_SETS))); if (!str) return JS_EXCEPTION; re_bytecode_buf = lre_compile(&re_bytecode_len, error_msg, @@ -48468,13 +49612,21 @@ static JSValue js_regexp_escape(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { StringBuffer b_s, *b = &b_s; + JSValue str, ret; JSString *p; uint32_t c, i; char s[16]; if (!JS_IsString(argv[0])) return JS_ThrowTypeError(ctx, "not a string"); - p = JS_VALUE_GET_STRING(argv[0]); + if (JS_VALUE_GET_TAG(argv[0]) == JS_TAG_STRING_ROPE) { + str = js_linearize_string_rope(ctx, argv[0]); + if (JS_IsException(str)) + return JS_EXCEPTION; + } else { + str = js_dup(argv[0]); + } + p = JS_VALUE_GET_STRING(str); string_buffer_init2(ctx, b, 0, p->is_wide_char); for (i = 0; i < p->len; i++) { c = p->is_wide_char ? (uint32_t)str16(p)[i] : (uint32_t)str8(p)[i]; @@ -48508,13 +49660,15 @@ static JSValue js_regexp_escape(JSContext *ctx, JSValueConst this_val, string_buffer_putc16(b, c); } } - return string_buffer_end(b); + ret = string_buffer_end(b); + JS_FreeValue(ctx, str); + return ret; } static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - int rc, capture_count, shift, index, i, re_flags, prop_flags; + int rc, capture_count, alloc_count, shift, index, i, re_flags, prop_flags; JSRegExp *re = js_get_regexp(ctx, this_val, true); JSString *str; JSValue t, ret, str_val, obj, val, groups; @@ -48523,6 +49677,7 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, uint8_t **capture, *str_buf; int64_t last_index; const char *group_name_ptr; + JSAtom group_name; JSProperty props[4]; // length, index, input, groups, in that order if (!re) @@ -48537,6 +49692,7 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, groups = JS_UNDEFINED; indices = JS_UNDEFINED; indices_groups = JS_UNDEFINED; + group_name = JS_ATOM_NULL; capture = NULL; val = JS_GetProperty(ctx, this_val, JS_ATOM_lastIndex); @@ -48550,8 +49706,14 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, } str = JS_VALUE_GET_STRING(str_val); capture_count = lre_get_capture_count(re_bytecode); - if (capture_count > 0) { - capture = js_malloc(ctx, sizeof(capture[0]) * capture_count * 2); + /* The register-based executor writes capture positions AND temporary + registers into the capture buffer; it must be sized by alloc_count + (= capture_count*2 + register_count), not capture_count*2. Sizing it + by capture_count*2 silently overflows the heap on any regexp that + uses registers (i.e. most non-trivial patterns). */ + alloc_count = lre_get_alloc_count(re_bytecode); + if (alloc_count > 0) { + capture = js_malloc(ctx, sizeof(capture[0]) * alloc_count); if (!capture) goto fail; } @@ -48621,14 +49783,19 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, goto fail; prop_flags = JS_PROP_C_W_E | JS_PROP_THROW; for(i = 0; i < capture_count; i++) { - const char *name = NULL; uint8_t **match = &capture[2 * i]; int start = -1; int end = -1; if (group_name_ptr && i > 0) { - if (*group_name_ptr) name = group_name_ptr; - group_name_ptr += strlen(group_name_ptr) + 1; + if (*group_name_ptr) { + /* XXX: slow, should create a shape when the regexp is + compiled */ + group_name = JS_NewAtom(ctx, group_name_ptr); + if (group_name == JS_ATOM_NULL) + goto fail; + } + group_name_ptr += strlen(group_name_ptr) + LRE_GROUP_NAME_TRAILER_LEN; } if (match[0] && match[1]) { @@ -48655,12 +49822,19 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, goto fail; } } - if (name && !JS_IsUndefined(indices_groups)) { - val = js_dup(val); - if (JS_DefinePropertyValueStr(ctx, indices_groups, - name, val, prop_flags) < 0) { - JS_FreeValue(ctx, val); - goto fail; + if (group_name != JS_ATOM_NULL && + !JS_IsUndefined(indices_groups)) { + /* For duplicate named groups, only the alternative that + actually matched (non-undefined) wins; a later + undefined alternative must not clobber it. */ + if (!JS_IsUndefined(val) || + !JS_HasProperty(ctx, indices_groups, group_name)) { + if (JS_DefinePropertyValue(ctx, indices_groups, + group_name, js_dup(val), + prop_flags) < 0) { + JS_FreeValue(ctx, val); + goto fail; + } } } if (JS_DefinePropertyValueUint32(ctx, indices, i, val, @@ -48676,13 +49850,18 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, goto fail; } - if (name) { - if (JS_DefinePropertyValueStr(ctx, groups, name, - js_dup(val), - prop_flags) < 0) { - JS_FreeValue(ctx, val); - goto fail; + if (group_name != JS_ATOM_NULL) { + /* duplicate named groups: matched alternative wins (see above) */ + if (!JS_IsUndefined(val) || + !JS_HasProperty(ctx, groups, group_name)) { + if (JS_DefinePropertyValue(ctx, groups, group_name, + js_dup(val), prop_flags) < 0) { + JS_FreeValue(ctx, val); + goto fail; + } } + JS_FreeAtom(ctx, group_name); + group_name = JS_ATOM_NULL; } if (JS_DefinePropertyValueUint32(ctx, obj, i, val, prop_flags) < 0) @@ -48705,6 +49884,7 @@ static JSValue js_regexp_exec(JSContext *ctx, JSValueConst this_val, ret = obj; obj = JS_UNDEFINED; fail: + JS_FreeAtom(ctx, group_name); JS_FreeValue(ctx, indices_groups); JS_FreeValue(ctx, indices); JS_FreeValue(ctx, str_val); @@ -48723,7 +49903,7 @@ static JSValue JS_RegExpDelete(JSContext *ctx, JSValueConst this_val, JSValue ar uint8_t *re_bytecode; int ret; uint8_t **capture, *str_buf; - int capture_count, shift, re_flags; + int alloc_count, shift, re_flags; int next_src_pos, start, end; int64_t last_index; StringBuffer b_s, *b = &b_s; @@ -48747,9 +49927,11 @@ static JSValue JS_RegExpDelete(JSContext *ctx, JSValueConst this_val, JSValue ar if (JS_IsException(val) || JS_ToLengthFree(ctx, &last_index, val)) goto fail; } - capture_count = lre_get_capture_count(re_bytecode); - if (capture_count > 0) { - capture = js_malloc(ctx, sizeof(capture[0]) * capture_count * 2); + /* size by alloc_count: the register executor uses capture[] beyond + the capture positions for its registers (see js_regexp_exec). */ + alloc_count = lre_get_alloc_count(re_bytecode); + if (alloc_count > 0) { + capture = js_malloc(ctx, sizeof(capture[0]) * alloc_count); if (!capture) goto fail; } @@ -48802,7 +49984,7 @@ static JSValue JS_RegExpDelete(JSContext *ctx, JSValueConst this_val, JSValue ar break; } if (end == start) { - if (!(re_flags & LRE_FLAG_UNICODE) || (unsigned)end >= str->len || !str->is_wide_char) { + if (!(re_flags & (LRE_FLAG_UNICODE | LRE_FLAG_UNICODE_SETS)) || (unsigned)end >= str->len || !str->is_wide_char) { end++; } else { string_getc(str, &end); @@ -48885,14 +50067,13 @@ static JSValue js_regexp_Symbol_match(JSContext *ctx, JSValueConst this_val, goto exception; p = JS_VALUE_GET_STRING(flags); - // TODO(bnoordhuis) query 'u' flag the same way? global = (-1 != string_indexof_char(p, 'g', 0)); if (!global) { A = JS_RegExpExec(ctx, rx, S); } else { - fullUnicode = JS_ToBoolFree(ctx, JS_GetProperty(ctx, rx, JS_ATOM_unicode)); - if (fullUnicode < 0) - goto exception; + // 'v' flag implies full Unicode, like 'u' + fullUnicode = (string_indexof_char(p, 'u', 0) >= 0 || + string_indexof_char(p, 'v', 0) >= 0); if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, js_int32(0)) < 0) goto exception; @@ -49075,7 +50256,8 @@ static JSValue js_regexp_Symbol_matchAll(JSContext *ctx, JSValueConst this_val, it->iterated_string = S; strp = JS_VALUE_GET_STRING(flags); it->global = string_indexof_char(strp, 'g', 0) >= 0; - it->unicode = string_indexof_char(strp, 'u', 0) >= 0; + it->unicode = string_indexof_char(strp, 'u', 0) >= 0 || + string_indexof_char(strp, 'v', 0) >= 0; it->done = false; JS_SetOpaqueInternal(iter, it); @@ -49127,15 +50309,14 @@ static int value_buffer_append(ValueBuffer *b, JSValue val) if (b->len >= b->size) { int new_size = (b->len + (b->len >> 1) + 31) & ~16; - size_t slack; JSValue *new_arr; if (b->arr == b->def) { - new_arr = js_realloc2(b->ctx, NULL, sizeof(*b->arr) * new_size, &slack); + new_arr = js_realloc(b->ctx, NULL, sizeof(*b->arr) * new_size); if (new_arr) memcpy(new_arr, b->def, sizeof b->def); } else { - new_arr = js_realloc2(b->ctx, b->arr, sizeof(*b->arr) * new_size, &slack); + new_arr = js_realloc(b->ctx, b->arr, sizeof(*b->arr) * new_size); } if (!new_arr) { value_buffer_free(b); @@ -49143,7 +50324,6 @@ static int value_buffer_append(ValueBuffer *b, JSValue val) b->error_status = -1; return -1; } - new_size += slack / sizeof(*new_arr); b->arr = new_arr; b->size = new_size; } @@ -49222,13 +50402,12 @@ static JSValue js_regexp_Symbol_replace(JSContext *ctx, JSValueConst this_val, goto exception; p = JS_VALUE_GET_STRING(flags); - // TODO(bnoordhuis) query 'u' flag the same way? fullUnicode = 0; is_global = (-1 != string_indexof_char(p, 'g', 0)); if (is_global) { - fullUnicode = JS_ToBoolFree(ctx, JS_GetProperty(ctx, rx, JS_ATOM_unicode)); - if (fullUnicode < 0) - goto exception; + // 'v' flag implies full Unicode, like 'u' + fullUnicode = (string_indexof_char(p, 'u', 0) >= 0 || + string_indexof_char(p, 'v', 0) >= 0); if (JS_SetProperty(ctx, rx, JS_ATOM_lastIndex, js_int32(0)) < 0) goto exception; } @@ -49454,7 +50633,8 @@ static JSValue js_regexp_Symbol_split(JSContext *ctx, JSValueConst this_val, if (JS_IsException(flags)) goto exception; strp = JS_VALUE_GET_STRING(flags); - unicodeMatching = string_indexof_char(strp, 'u', 0) >= 0; + unicodeMatching = string_indexof_char(strp, 'u', 0) >= 0 || + string_indexof_char(strp, 'v', 0) >= 0; if (string_indexof_char(strp, 'y', 0) < 0) { flags = JS_ConcatString3(ctx, "", flags, "y"); if (JS_IsException(flags)) @@ -50593,7 +51773,11 @@ JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj, goto exception; jsc->gap = JS_NewStringLen(ctx, " ", n); } else if (JS_IsString(space)) { - JSString *p = JS_VALUE_GET_STRING(space); + JSString *p; + space = JS_ToStringFree(ctx, space); + if (JS_IsException(space)) + goto exception; + p = JS_VALUE_GET_STRING(space); jsc->gap = js_sub_string(ctx, p, 0, min_int(p->len, 10)); } else { jsc->gap = js_dup(jsc->empty); @@ -51483,7 +52667,7 @@ static int js_proxy_get_own_property_names(JSContext *ctx, { JSProxyData *s; JSValue method, prop_array, val; - uint32_t len, i, len2; + uint32_t len, target_len, tab_size, i, len2; JSPropertyEnum *tab, *tab2; JSAtom atom; int res, is_extensible, idx; @@ -51501,16 +52685,12 @@ static int js_proxy_get_own_property_names(JSContext *ctx, return -1; tab = NULL; len = 0; + tab_size = 0; tab2 = NULL; len2 = 0; - if (js_get_length32(ctx, &len, prop_array)) + if (js_get_length32(ctx, &target_len, prop_array)) goto fail; - if (len > 0) { - tab = js_mallocz(ctx, sizeof(tab[0]) * len); - if (!tab) - goto fail; - } - for(i = 0; i < len; i++) { + for(i = 0; i < target_len; i++) { val = JS_GetPropertyUint32(ctx, prop_array, i); if (JS_IsException(val)) goto fail; @@ -51523,8 +52703,26 @@ static int js_proxy_get_own_property_names(JSContext *ctx, JS_FreeValue(ctx, val); if (atom == JS_ATOM_NULL) goto fail; - tab[i].atom = atom; - tab[i].is_enumerable = false; /* XXX: redundant? */ + if (len >= tab_size) { + int64_t new_size = max_int64(8, tab_size + (int64_t)tab_size / 2); + JSPropertyEnum *new_tab; + new_size = min_int64(new_size, target_len); + if (new_size > (int64_t)(SIZE_MAX / sizeof(tab[0]))) { + JS_FreeAtom(ctx, atom); + JS_ThrowOutOfMemory(ctx); + goto fail; + } + new_tab = js_realloc(ctx, tab, sizeof(tab[0]) * (size_t)new_size); + if (!new_tab) { + JS_FreeAtom(ctx, atom); + goto fail; + } + tab = new_tab; + tab_size = new_size; + } + tab[len].atom = atom; + tab[len].is_enumerable = false; /* XXX: redundant? */ + len++; } /* check duplicate properties (XXX: inefficient, could store the @@ -52139,13 +53337,13 @@ static uint32_t map_hash_key(JSContext *ctx, JSValueConst key) hash_float64: u.d = d; h = (u.u32[0] ^ u.u32[1]) * 3163; - return h ^= JS_TAG_FLOAT64; + tag = JS_TAG_FLOAT64; + break; default: h = 0; break; } - h ^= tag; - return h; + return h ^ ctx->hash_seed ^ hash32(tag); } static JSMapRecord *map_find_record(JSContext *ctx, JSMapState *s, @@ -53118,6 +54316,7 @@ static JSValue js_set_intersection(JSContext *ctx, JSValueConst this_val, } else if (map_find_record(ctx, t, item)) { JS_FreeValue(ctx, item); // no duplicates } else if ((mr = map_add_record(ctx, t, item))) { + JS_FreeValue(ctx, item); mr->value = JS_UNDEFINED; } else { JS_FreeValue(ctx, item); @@ -53145,6 +54344,7 @@ static JSValue js_set_intersection(JSContext *ctx, JSValueConst this_val, if (map_find_record(ctx, t, item)) { JS_FreeValue(ctx, item); // no duplicates } else if ((mr = map_add_record(ctx, t, item))) { + JS_FreeValue(ctx, item); mr->value = JS_UNDEFINED; } else { JS_FreeValue(ctx, item); @@ -53233,6 +54433,7 @@ static JSValue js_set_difference(JSContext *ctx, JSValueConst this_val, if (map_find_record(ctx, t, item)) { JS_FreeValue(ctx, item); // no duplicates } else if ((mr = map_add_record(ctx, t, item))) { + JS_FreeValue(ctx, item); mr->value = JS_UNDEFINED; } else { JS_FreeValue(ctx, item); @@ -53288,7 +54489,7 @@ static JSValue js_set_symmetricDifference(JSContext *ctx, JSValueConst this_val, mr = list_entry(el, JSMapRecord, link); if (mr->empty) continue; - mr = map_add_record(ctx, t, js_dup(mr->key)); + mr = map_add_record(ctx, t, mr->key); if (!mr) goto exception; mr->value = JS_UNDEFINED; @@ -53324,10 +54525,9 @@ static JSValue js_set_symmetricDifference(JSContext *ctx, JSValueConst this_val, JS_FreeValue(ctx, item); } else { mr = map_add_record(ctx, t, item); - if (!mr) { - JS_FreeValue(ctx, item); + JS_FreeValue(ctx, item); + if (!mr) goto exception; - } mr->value = JS_UNDEFINED; } } @@ -53371,7 +54571,7 @@ static JSValue js_set_union(JSContext *ctx, JSValueConst this_val, mr = list_entry(el, JSMapRecord, link); if (mr->empty) continue; - mr = map_add_record(ctx, t, js_dup(mr->key)); + mr = map_add_record(ctx, t, mr->key); if (!mr) goto exception; mr->value = JS_UNDEFINED; @@ -53619,6 +54819,7 @@ static int js_dispose_resources(JSContext *ctx, JSDisposableStack *ds, if (JS_IsUndefined(res->method)) { /* null/undefined resource, skip */ JS_FreeValue(ctx, res->value); + res->value = JS_UNDEFINED; continue; } switch (res->hint) { @@ -53634,6 +54835,8 @@ static int js_dispose_resources(JSContext *ctx, JSDisposableStack *ds, } JS_FreeValue(ctx, res->value); JS_FreeValue(ctx, res->method); + res->value = JS_UNDEFINED; + res->method = JS_UNDEFINED; if (JS_IsException(ret)) { JSValue new_error = JS_GetException(ctx); if (has_error) { @@ -54217,7 +55420,7 @@ typedef struct JSPromiseData { JSPromiseStateEnum promise_state; /* 0=fulfill, 1=reject, list of JSPromiseReactionData.link */ struct list_head promise_reactions[2]; - bool is_handled; /* Note: only useful to debug */ + bool is_handled; JSValue promise_result; } JSPromiseData; @@ -54253,6 +55456,29 @@ JSValue JS_PromiseResult(JSContext *ctx, JSValueConst promise) return js_dup(s->promise_result); } +// Notify the host tracker of an unreported rejection's state +static void call_promise_rejection_tracker(JSContext *ctx, JSValueConst promise, + bool is_handled) +{ + JSPromiseData *s = JS_GetOpaque(promise, JS_CLASS_PROMISE); + JSRuntime *rt = ctx->rt; + if (s && s->promise_state == JS_PROMISE_REJECTED && !s->is_handled && + rt->host_promise_rejection_tracker) { + rt->host_promise_rejection_tracker(ctx, promise, s->promise_result, + is_handled, rt->host_promise_rejection_tracker_opaque); + } +} + +// Mark rejected promise as handled by the engine itself and let the host know that the promise is handled +static void js_promise_set_handled(JSContext *ctx, JSValueConst promise) +{ + JSPromiseData *s = JS_GetOpaque(promise, JS_CLASS_PROMISE); + if (!s) + return; + call_promise_rejection_tracker(ctx, promise, true); + s->is_handled = true; +} + bool JS_IsPromise(JSValueConst val) { if (JS_VALUE_GET_TAG(val) != JS_TAG_OBJECT) @@ -54260,6 +55486,11 @@ bool JS_IsPromise(JSValueConst val) return JS_VALUE_GET_OBJ(val)->class_id == JS_CLASS_PROMISE; } +void JS_PromiseMarkAsHandled(JSContext *ctx, JSValueConst promise) +{ + js_promise_set_handled(ctx, promise); +} + JSValue JS_NewSettledPromise(JSContext *ctx, bool is_reject, JSValueConst value) { return js_promise_resolve(ctx, ctx->promise_ctor, 1, &value, is_reject); @@ -54368,12 +55599,7 @@ static void fulfill_or_reject_promise(JSContext *ctx, JSValueConst promise, } } - if (s->promise_state == JS_PROMISE_REJECTED && !s->is_handled) { - JSRuntime *rt = ctx->rt; - if (rt->host_promise_rejection_tracker) - rt->host_promise_rejection_tracker(ctx, promise, value, false, - rt->host_promise_rejection_tracker_opaque); - } + call_promise_rejection_tracker(ctx, promise, false); list_for_each_safe(el, el1, &s->promise_reactions[is_reject]) { rd = list_entry(el, JSPromiseReactionData, link); @@ -54447,6 +55673,8 @@ static int js_create_resolving_functions(JSContext *ctx, JSPromiseFunctionDataResolved *sr; int i, ret; + resolving_funcs[0] = JS_UNDEFINED; + resolving_funcs[1] = JS_UNDEFINED; sr = js_malloc(ctx, sizeof(*sr)); if (!sr) return -1; @@ -54462,9 +55690,8 @@ static int js_create_resolving_functions(JSContext *ctx, if (!s) { JS_FreeValue(ctx, obj); fail: - - if (i != 0) - JS_FreeValue(ctx, resolving_funcs[0]); + JS_FreeValue(ctx, resolving_funcs[0]); + resolving_funcs[0] = JS_UNDEFINED; ret = -1; break; } @@ -54728,6 +55955,43 @@ JSValue JS_NewPromiseCapability(JSContext *ctx, JSValue *resolving_funcs) return js_new_promise_capability(ctx, resolving_funcs, JS_UNDEFINED); } +JSValue JS_PromiseThen(JSContext *ctx, JSValueConst promise, + JSValueConst on_fulfilled, + JSValueConst on_rejected) +{ + JSValue result_promise, resolving_funcs[2]; + JSValueConst handlers[2] = { on_fulfilled, on_rejected }; + JSRuntime *rt = ctx->rt; + JSValueLink link; + bool have_promise_hook; + int i, ret; + + if (!JS_GetOpaque2(ctx, promise, JS_CLASS_PROMISE)) + return JS_EXCEPTION; + + /* Match the embedding API: create an intrinsic promise and do not consult + Promise.prototype.then or Symbol.species. */ + have_promise_hook = (rt->promise_hook != NULL); + if (have_promise_hook) { + link = (JSValueLink){rt->parent_promise, promise}; + rt->parent_promise = &link; + } + result_promise = JS_NewPromiseCapability(ctx, resolving_funcs); + if (have_promise_hook) + rt->parent_promise = link.next; + if (JS_IsException(result_promise)) + return result_promise; + + ret = perform_promise_then(ctx, promise, handlers, vc(resolving_funcs)); + for (i = 0; i < 2; i++) + JS_FreeValue(ctx, resolving_funcs[i]); + if (ret) { + JS_FreeValue(ctx, result_promise); + return JS_EXCEPTION; + } + return result_promise; +} + static JSValue js_promise_resolve(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic) { @@ -55162,12 +56426,7 @@ static __exception int perform_promise_then(JSContext *ctx, list_add_tail(&rd_array[i]->link, &s->promise_reactions[i]); } else { JSValueConst args[5]; - if (s->promise_state == JS_PROMISE_REJECTED && !s->is_handled) { - JSRuntime *rt = ctx->rt; - if (rt->host_promise_rejection_tracker) - rt->host_promise_rejection_tracker(ctx, promise, s->promise_result, - true, rt->host_promise_rejection_tracker_opaque); - } + call_promise_rejection_tracker(ctx, promise, true); i = s->promise_state - JS_PROMISE_FULFILLED; rd = rd_array[i]; args[0] = rd->resolving_funcs[0]; @@ -57249,28 +58508,62 @@ static JSValue js_bigint_asUintN(JSContext *ctx, res = __JS_NewShortBigInt(ctx, 0); } else if (JS_VALUE_GET_TAG(a) == JS_TAG_SHORT_BIG_INT) { /* fast case */ - if (bits >= JS_SHORT_BIG_INT_BITS) { + js_slimb_t sv = JS_VALUE_GET_SHORT_BIG_INT(a); + if (bits >= JS_SHORT_BIG_INT_BITS && (asIntN || sv >= 0)) { res = a; - } else { + } else if (bits < JS_SHORT_BIG_INT_BITS) { uint64_t v; int shift; shift = 64 - bits; - v = JS_VALUE_GET_SHORT_BIG_INT(a); + v = sv; v = v << shift; if (asIntN) v = (int64_t)v >> shift; else v = v >> shift; res = __JS_NewShortBigInt(ctx, v); + } else { + JSBigInt *r; + uint64_t len64 = (bits + JS_LIMB_BITS - 1) / JS_LIMB_BITS; + int len, shift, i; + + if (len64 > JS_BIGINT_MAX_SIZE) { + JS_FreeValue(ctx, a); + return JS_ThrowRangeError(ctx, "BigInt is too large to allocate"); + } + len = len64; + r = js_bigint_new(ctx, len); + if (!r) { + JS_FreeValue(ctx, a); + return JS_EXCEPTION; + } + r->len = len; + r->tab[0] = sv; + for(i = 1; i < len; i++) + r->tab[i] = -1; + shift = (-bits) & (JS_LIMB_BITS - 1); + r->tab[len - 1] = (r->tab[len - 1] << shift) >> shift; + r = js_bigint_extend(ctx, r, 0); + JS_FreeValue(ctx, a); + if (!r) + return JS_EXCEPTION; + res = JS_CompactBigInt(ctx, r); } } else { JSBigInt *r, *p = JS_VALUE_GET_PTR(a); - if (bits >= p->len * JS_LIMB_BITS) { + int is_neg = js_bigint_sign(p); + if (bits >= (uint64_t)p->len * JS_LIMB_BITS && + (asIntN || !is_neg)) { res = a; } else { + uint64_t len64 = (bits + JS_LIMB_BITS - 1) / JS_LIMB_BITS; int len, shift, i; js_limb_t v; - len = (bits + JS_LIMB_BITS - 1) / JS_LIMB_BITS; + if (len64 > JS_BIGINT_MAX_SIZE) { + JS_FreeValue(ctx, a); + return JS_ThrowRangeError(ctx, "BigInt is too large to allocate"); + } + len = len64; r = js_bigint_new(ctx, len); if (!r) { JS_FreeValue(ctx, a); @@ -57278,15 +58571,21 @@ static JSValue js_bigint_asUintN(JSContext *ctx, } r->len = len; for(i = 0; i < len - 1; i++) - r->tab[i] = p->tab[i]; + r->tab[i] = i < p->len ? p->tab[i] : -is_neg; shift = (-bits) & (JS_LIMB_BITS - 1); /* 0 <= shift <= JS_LIMB_BITS - 1 */ - v = p->tab[len - 1] << shift; + v = (len - 1 < p->len ? p->tab[len - 1] : -is_neg) << shift; if (asIntN) v = (js_slimb_t)v >> shift; else v = v >> shift; r->tab[len - 1] = v; + if (!asIntN) + r = js_bigint_extend(ctx, r, 0); + if (!r) { + JS_FreeValue(ctx, a); + return JS_EXCEPTION; + } r = js_bigint_normalize(ctx, r); JS_FreeValue(ctx, a); res = JS_CompactBigInt(ctx, r); @@ -57508,26 +58807,41 @@ int JS_AddIntrinsicBaseObjects(JSContext *ctx) 0); if (JS_IsException(obj2)) return -1; - // quirk: Iterator.prototype.constructor is an accessor property + // quirk: Iterator.prototype.constructor is an accessor property. The getter + // (magic == 0) returns %Iterator%; the setter (magic == 1, length 1) + // implements SetterThatIgnoresPrototypeProperties. They must be separate + // function objects so that magic, not argc, distinguishes get from set. // TODO(bnoordhuis) mildly inefficient because JS_NewCConstructor // first creates a .constructor value property that we then replace with // an accessor - obj1 = JS_NewCFunctionData(ctx, js_iterator_constructor_getset, - 0, 0, 1, vc(&obj2)); - if (JS_IsException(obj1)) { - JS_FreeValue(ctx, obj2); - return -1; - } - ctx->iterator_ctor_getset = js_dup(obj1); - if (JS_DefineProperty(ctx, ctx->class_proto[JS_CLASS_ITERATOR], - JS_ATOM_constructor, JS_UNDEFINED, - obj1, obj1, - JS_PROP_HAS_GET | JS_PROP_HAS_SET | JS_PROP_CONFIGURABLE) < 0) { - JS_FreeValue(ctx, obj2); - JS_FreeValue(ctx, obj1); - return -1; + { + JSValue getter, setter; + getter = JS_NewCFunctionData(ctx, js_iterator_constructor_getset, + 0, 0, 1, vc(&obj2)); + if (JS_IsException(getter)) { + JS_FreeValue(ctx, obj2); + return -1; + } + setter = JS_NewCFunctionData(ctx, js_iterator_constructor_getset, + 1, 1, 1, vc(&obj2)); + if (JS_IsException(setter)) { + JS_FreeValue(ctx, getter); + JS_FreeValue(ctx, obj2); + return -1; + } + ctx->iterator_ctor_getset = js_dup(getter); + if (JS_DefineProperty(ctx, ctx->class_proto[JS_CLASS_ITERATOR], + JS_ATOM_constructor, JS_UNDEFINED, + getter, setter, + JS_PROP_HAS_GET | JS_PROP_HAS_SET | JS_PROP_CONFIGURABLE) < 0) { + JS_FreeValue(ctx, getter); + JS_FreeValue(ctx, setter); + JS_FreeValue(ctx, obj2); + return -1; + } + JS_FreeValue(ctx, getter); + JS_FreeValue(ctx, setter); } - JS_FreeValue(ctx, obj1); ctx->iterator_ctor = obj2; JS_DefineAutoInitProperty(ctx, obj2, JS_ATOM_zip, JS_AUTOINIT_ID_BYTECODE, (void *)(uintptr_t)JS_BUILTIN_ITERATOR_ZIP, @@ -57536,13 +58850,6 @@ int JS_AddIntrinsicBaseObjects(JSContext *ctx) (void *)(uintptr_t)JS_BUILTIN_ITERATOR_ZIP_KEYED, JS_PROP_WRITABLE|JS_PROP_CONFIGURABLE); - ctx->class_proto[JS_CLASS_ITERATOR_CONCAT] = - JS_NewObjectProtoList(ctx, ctx->class_proto[JS_CLASS_ITERATOR], - js_iterator_concat_proto_funcs, - countof(js_iterator_concat_proto_funcs)); - if (JS_IsException(ctx->class_proto[JS_CLASS_ITERATOR_CONCAT])) - return -1; - ctx->class_proto[JS_CLASS_ITERATOR_HELPER] = JS_NewObjectProtoList(ctx, ctx->class_proto[JS_CLASS_ITERATOR], js_iterator_helper_proto_funcs, @@ -57550,6 +58857,10 @@ int JS_AddIntrinsicBaseObjects(JSContext *ctx) if (JS_IsException(ctx->class_proto[JS_CLASS_ITERATOR_HELPER])) return -1; + /* Iterator.concat() returns an Iterator Helper */ + ctx->class_proto[JS_CLASS_ITERATOR_CONCAT] = + js_dup(ctx->class_proto[JS_CLASS_ITERATOR_HELPER]); + ctx->class_proto[JS_CLASS_ITERATOR_WRAP] = JS_NewObjectProtoList(ctx, ctx->class_proto[JS_CLASS_ITERATOR], js_iterator_wrap_proto_funcs, @@ -57639,7 +58950,6 @@ int JS_AddIntrinsicBaseObjects(JSContext *ctx) return -1; /* Math: create as autoinit object */ - js_random_init(ctx); if (JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_math_obj, countof(js_math_obj))) return -1; @@ -57721,7 +59031,7 @@ static JSValue js_array_buffer_constructor3(JSContext *ctx, uint64_t len, uint64_t *max_len, JSClassID class_id, uint8_t *buf, - JSFreeArrayBufferDataFunc *free_func, + JSReallocArrayBufferDataFunc *realloc_func, void *opaque, bool alloc_flag) { JSRuntime *rt = ctx->rt; @@ -57729,12 +59039,15 @@ static JSValue js_array_buffer_constructor3(JSContext *ctx, JSArrayBuffer *abuf = NULL; uint64_t sab_alloc_len; - if (!alloc_flag && buf && max_len && free_func != js_array_buffer_free) { - // not observable from JS land, only through C API misuse; - // JS code cannot create externally managed buffers directly + // SABs commit their maximum size upfront and are therefore never + // reallocated; everything else needs a way to resize the backing memory. + // Not observable from JS land, only through C API misuse; JS code cannot + // create externally managed buffers directly. + if (!alloc_flag && buf && max_len && !realloc_func && + class_id != JS_CLASS_SHARED_ARRAY_BUFFER) { return JS_ThrowInternalError(ctx, - "resizable ArrayBuffers not supported " - "for externally managed buffers"); + "resizable ArrayBuffers require a " + "realloc function"); } obj = js_create_from_ctor(ctx, new_target, class_id); if (JS_IsException(obj)) @@ -57788,7 +59101,7 @@ static JSValue js_array_buffer_constructor3(JSContext *ctx, abuf->data = js_mallocz(ctx, 1); if (!abuf->data) goto fail; - free_func = js_array_buffer_free; + realloc_func = js_array_buffer_realloc; } } init_list_head(&abuf->array_list); @@ -57796,7 +59109,7 @@ static JSValue js_array_buffer_constructor3(JSContext *ctx, abuf->immutable = false; abuf->shared = (class_id == JS_CLASS_SHARED_ARRAY_BUFFER); abuf->opaque = opaque; - abuf->free_func = free_func; + abuf->realloc_func = realloc_func; if (alloc_flag && buf) memcpy(abuf->data, buf, len); JS_SetOpaqueInternal(obj, abuf); @@ -57807,9 +59120,10 @@ static JSValue js_array_buffer_constructor3(JSContext *ctx, return JS_EXCEPTION; } -static void js_array_buffer_free(JSRuntime *rt, void *opaque, void *ptr) +static void *js_array_buffer_realloc(JSRuntime *rt, void *opaque, void *ptr, + size_t size) { - js_free_rt(rt, ptr); + return js_realloc_rt(rt, ptr, size); } static JSValue js_array_buffer_constructor2(JSContext *ctx, @@ -57818,8 +59132,8 @@ static JSValue js_array_buffer_constructor2(JSContext *ctx, JSClassID class_id) { return js_array_buffer_constructor3(ctx, new_target, len, max_len, - class_id, NULL, js_array_buffer_free, - NULL, true); + class_id, NULL, + js_array_buffer_realloc, NULL, true); } static JSValue js_array_buffer_constructor1(JSContext *ctx, @@ -57831,13 +59145,23 @@ static JSValue js_array_buffer_constructor1(JSContext *ctx, } JSValue JS_NewArrayBuffer(JSContext *ctx, uint8_t *buf, size_t len, - JSFreeArrayBufferDataFunc *free_func, void *opaque, - bool is_shared) + size_t max_len, + JSReallocArrayBufferDataFunc *realloc_func, + void *opaque, bool is_shared) { JSClassID class_id = is_shared ? JS_CLASS_SHARED_ARRAY_BUFFER : JS_CLASS_ARRAY_BUFFER; - return js_array_buffer_constructor3(ctx, JS_UNDEFINED, len, NULL, class_id, - buf, free_func, opaque, false); + uint64_t max_len64 = max_len, *pmax_len = NULL; + + /* a zero 'max_len' means the ArrayBuffer is not resizable */ + if (max_len > 0) { + if (max_len < len) + return JS_ThrowRangeError(ctx, "invalid max array buffer length"); + pmax_len = &max_len64; + } + return js_array_buffer_constructor3(ctx, JS_UNDEFINED, len, pmax_len, + class_id, buf, realloc_func, opaque, + false); } bool JS_IsArrayBuffer(JSValueConst obj) { @@ -57850,7 +59174,7 @@ JSValue JS_NewArrayBufferCopy(JSContext *ctx, const uint8_t *buf, size_t len) return js_array_buffer_constructor3(ctx, JS_UNDEFINED, len, NULL, JS_CLASS_ARRAY_BUFFER, (uint8_t *)buf, - js_array_buffer_free, NULL, + js_array_buffer_realloc, NULL, true); } @@ -57932,8 +59256,8 @@ static void js_array_buffer_finalizer(JSRuntime *rt, JSValueConst val) if (abuf->shared && rt->sab_funcs.sab_free) { rt->sab_funcs.sab_free(rt->sab_funcs.sab_opaque, abuf->data); } else { - if (abuf->free_func) - abuf->free_func(rt, abuf->opaque, abuf->data); + if (abuf->realloc_func) + abuf->realloc_func(rt, abuf->opaque, abuf->data, 0); } js_free_rt(rt, abuf); } @@ -58034,8 +59358,13 @@ void JS_DetachArrayBuffer(JSContext *ctx, JSValueConst obj) if (!abuf || abuf->detached) return; - if (abuf->free_func) - abuf->free_func(ctx->rt, abuf->opaque, abuf->data); + if (abuf->realloc_func) { + abuf->realloc_func(ctx->rt, abuf->opaque, abuf->data, 0); + /* The backing data has been released. Do not release it again when + the detached ArrayBuffer object is later finalized. */ + abuf->realloc_func = NULL; + abuf->opaque = NULL; + } abuf->data = NULL; abuf->byte_length = 0; abuf->detached = true; @@ -58160,6 +59489,8 @@ static JSValue js_array_buffer_transfer(JSContext *ctx, JSValueConst this_val, JSArrayBuffer *abuf; uint64_t new_len, old_len, max_len, *pmax_len; uint8_t *bs, *new_bs; + JSReallocArrayBufferDataFunc *realloc_func; + void *opaque; JSValue ret; abuf = JS_GetOpaque2(ctx, this_val, JS_CLASS_ARRAY_BUFFER); @@ -58167,13 +59498,14 @@ static JSValue js_array_buffer_transfer(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; if (abuf->shared) return JS_ThrowTypeError(ctx, "cannot transfer a SharedArrayBuffer"); - if (magic == JS_ARRAY_BUFFER_TRANSFER_TO_IMMUTABLE && abuf->immutable) - return JS_ThrowTypeErrorImmutableArrayBuffer(ctx); + // Spec (ArrayBufferCopyAndDetach): the newLength argument must be + // coerced (its valueOf observed) before the buffer's detachability / + // immutability is checked, so side effects of coercion are visible. if (argc < 1 || JS_IsUndefined(argv[0])) new_len = abuf->byte_length; else if (JS_ToIndex(ctx, &new_len, argv[0])) return JS_EXCEPTION; - if (magic != JS_ARRAY_BUFFER_TRANSFER_TO_IMMUTABLE && abuf->immutable) + if (abuf->immutable) return JS_ThrowTypeErrorImmutableArrayBuffer(ctx); if (abuf->detached) return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); @@ -58183,9 +59515,7 @@ static JSValue js_array_buffer_transfer(JSContext *ctx, JSValueConst this_val, max_len = abuf->max_byte_length; if (new_len > max_len) return JS_ThrowTypeError(ctx, "invalid array buffer length"); - // TODO(bnoordhuis) support externally managed RABs - if (abuf->free_func == js_array_buffer_free) - pmax_len = &max_len; + pmax_len = &max_len; } } /* create an empty AB */ @@ -58197,23 +59527,33 @@ static JSValue js_array_buffer_transfer(JSContext *ctx, JSValueConst this_val, } bs = abuf->data; old_len = abuf->byte_length; + realloc_func = abuf->realloc_func; + opaque = abuf->opaque; /* if length mismatch, realloc. Otherwise, use the same backing buffer. */ if (new_len != old_len) { - new_bs = js_realloc(ctx, bs, new_len); + if (!realloc_func) + return JS_ThrowTypeError(ctx, "array buffer is not resizable"); + /* XXX: we are currently limited to 2 GB; check before reallocating, + new_len does not necessarily fit in a size_t */ + if (new_len > INT32_MAX) + return JS_ThrowRangeError(ctx, "invalid array buffer length"); + new_bs = realloc_func(ctx->rt, opaque, bs, new_len); if (!new_bs) - return JS_EXCEPTION; + return JS_ThrowOutOfMemory(ctx); bs = new_bs; if (new_len > old_len) memset(bs + old_len, 0, new_len - old_len); } - /* neuter the backing buffer */ + /* neuter the source */ abuf->data = NULL; abuf->byte_length = 0; abuf->detached = true; + abuf->realloc_func = NULL; + abuf->opaque = NULL; js_array_buffer_update_typed_arrays(abuf); ret = js_array_buffer_constructor3(ctx, JS_UNDEFINED, new_len, pmax_len, JS_CLASS_ARRAY_BUFFER, bs, - abuf->free_func, NULL, + realloc_func, opaque, /*alloc_flag*/false); fini: if (magic == JS_ARRAY_BUFFER_TRANSFER_TO_IMMUTABLE) { @@ -58245,9 +59585,6 @@ static JSValue js_array_buffer_resize(JSContext *ctx, JSValueConst this_val, return JS_ThrowTypeErrorDetachedArrayBuffer(ctx); if (!array_buffer_is_resizable(abuf)) return JS_ThrowTypeError(ctx, "array buffer is not resizable"); - // TODO(bnoordhuis) support externally managed RABs - if (abuf->free_func != js_array_buffer_free) - return JS_ThrowTypeError(ctx, "external array buffer is not resizable"); if (len < 0 || len > abuf->max_byte_length) { bad_length: return JS_ThrowRangeError(ctx, "invalid array buffer length"); @@ -58267,9 +59604,13 @@ static JSValue js_array_buffer_resize(JSContext *ctx, JSValueConst this_val, // 2 bytes big in A, and 1 byte big in B abuf->byte_length = len; } else { - data = js_realloc(ctx, abuf->data, max_int(len, 1)); + // the ArrayBuffer cannot be resizable without a way to resize it, + // js_array_buffer_constructor3 rejects that combination + assert(abuf->realloc_func); + data = abuf->realloc_func(ctx->rt, abuf->opaque, abuf->data, + max_int(len, 1)); if (!data) - return JS_EXCEPTION; + return JS_ThrowOutOfMemory(ctx); if (len > abuf->byte_length) memset(&data[abuf->byte_length], 0, len - abuf->byte_length); abuf->byte_length = len; @@ -58350,10 +59691,17 @@ static JSValue js_array_buffer_slice(JSContext *ctx, goto fail; } /* must test again because of side effects */ - if (abuf->detached || abuf->byte_length < start + new_len) { + if (abuf->detached) { JS_ThrowTypeErrorDetachedArrayBuffer(ctx); goto fail; } + if (abuf->byte_length < start + new_len) { + if (immutable) + JS_ThrowRangeError(ctx, "invalid array buffer length"); + else + JS_ThrowTypeErrorDetachedArrayBuffer(ctx); + goto fail; + } memcpy(new_abuf->data, abuf->data + start, new_len); new_abuf->immutable = immutable; return new_obj; @@ -58830,7 +60178,8 @@ static JSValue js_create_typed_array_iterator(JSContext *ctx, JSValueConst this_ } static JSValue js_typed_array_create(JSContext *ctx, JSValueConst ctor, - int argc, JSValueConst *argv) + int argc, JSValueConst *argv, + bool require_mutable) { JSValue ret; int new_len; @@ -58843,6 +60192,10 @@ static JSValue js_typed_array_create(JSContext *ctx, JSValueConst ctor, new_len = js_typed_array_get_length_unsafe(ctx, ret); if (new_len < 0) goto fail; + if (require_mutable && typed_array_is_immutable(JS_VALUE_GET_OBJ(ret))) { + JS_ThrowTypeErrorImmutableArrayBuffer(ctx); + goto fail; + } if (argc == 1) { /* ensure that it is large enough */ if (JS_ToLengthFree(ctx, &len, js_dup(argv[0]))) @@ -58859,7 +60212,8 @@ static JSValue js_typed_array_create(JSContext *ctx, JSValueConst ctor, static JSValue js_typed_array___speciesCreate(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) + int argc, JSValueConst *argv, + bool require_mutable) { JSValueConst obj; JSObject *p; @@ -58878,7 +60232,7 @@ static JSValue js_typed_array___speciesCreate(JSContext *ctx, ret = js_typed_array_constructor(ctx, JS_UNDEFINED, argc1, argv + 1, p->class_id); } else { - ret = js_typed_array_create(ctx, ctor, argc1, argv + 1); + ret = js_typed_array_create(ctx, ctor, argc1, argv + 1, require_mutable); JS_FreeValue(ctx, ctor); } return ret; @@ -58916,14 +60270,24 @@ static JSValue js_typed_array_from(JSContext *ctx, JSValueConst this_val, iter = JS_GetProperty(ctx, items, JS_ATOM_Symbol_iterator); if (JS_IsException(iter)) goto exception; - if (!JS_IsUndefined(iter)) { - JS_FreeValue(ctx, iter); + if (!JS_IsUndefined(iter) && !JS_IsNull(iter)) { + if (!JS_IsFunction(ctx, iter)) { + JS_FreeValue(ctx, iter); + JS_ThrowTypeError(ctx, "value is not iterable"); + goto exception; + } arr = JS_NewArray(ctx); - if (JS_IsException(arr)) + if (JS_IsException(arr)) { + JS_FreeValue(ctx, iter); goto exception; - stack[0] = js_dup(items); - if (js_for_of_start(ctx, &stack[1], false)) + } + stack[0] = JS_GetIterator2(ctx, items, iter); + JS_FreeValue(ctx, iter); + if (JS_IsException(stack[0])) goto exception; + stack[1] = JS_GetProperty(ctx, stack[0], JS_ATOM_next); + if (JS_IsException(stack[1])) + goto exception_close; for (k = 0;; k++) { v = JS_IteratorNext(ctx, stack[0], stack[1], 0, NULL, &done); if (JS_IsException(v)) @@ -58941,7 +60305,7 @@ static JSValue js_typed_array_from(JSContext *ctx, JSValueConst this_val, if (js_get_length64(ctx, &len, arr) < 0) goto exception; v = js_int64(len); - r = js_typed_array_create(ctx, this_val, 1, vc(&v)); + r = js_typed_array_create(ctx, this_val, 1, vc(&v), true); JS_FreeValue(ctx, v); if (JS_IsException(r)) goto exception; @@ -58983,7 +60347,7 @@ static JSValue js_typed_array_of(JSContext *ctx, JSValueConst this_val, int i; v = js_int32(argc); - obj = js_typed_array_create(ctx, this_val, 1, vc(&v)); + obj = js_typed_array_create(ctx, this_val, 1, vc(&v), true); if (JS_IsException(obj)) return obj; @@ -59252,18 +60616,27 @@ static JSValue js_typed_array_indexOf(JSContext *ctx, JSValueConst this_val, exception is raised) */ if (typed_array_is_oob(p) || len > p->u.array.count) { /* "includes" scans all the properties, so "undefined" can match */ - if (special == special_includes) + if (special == special_includes) { if (JS_IsUndefined(argv[0])) if (k < typed_array_length(p)) res = 0; - goto done; + goto done; + } + /* lastIndexOf scans downward, so when the buffer merely shrank + during argument coercion the scan continues in the still + valid range; the vanished indices simply cannot match */ + if (special != special_lastIndexOf || typed_array_is_oob(p)) + goto done; } // RAB may have been resized by evil .valueOf method len = min_int(len, p->u.array.count); if (len == 0) goto done; - k = min_int(k, len); + if (special == special_lastIndexOf) + k = min_int(k, len - 1); + else + k = min_int(k, len); stop = min_int(stop, len); is_bigint = 0; @@ -59582,8 +60955,10 @@ static JSValue js_typed_array_reverse(JSContext *ctx, JSValueConst this_val, len = js_typed_array_get_length_unsafe(ctx, this_val); if (len < 0) return JS_EXCEPTION; + p = JS_VALUE_GET_OBJ(this_val); + if (typed_array_is_immutable(p)) + return JS_ThrowTypeErrorImmutableArrayBuffer(ctx); if (len > 0) { - p = JS_VALUE_GET_OBJ(this_val); switch (typed_array_size_log2(p->class_id)) { case 0: { @@ -59681,7 +61056,7 @@ static JSValue js_typed_array_slice(JSContext *ctx, JSValueConst this_val, args[0] = this_val; args[1] = js_int32(count); - arr = js_typed_array___speciesCreate(ctx, JS_UNDEFINED, 2, args); + arr = js_typed_array___speciesCreate(ctx, JS_UNDEFINED, 2, args, true); if (JS_IsException(arr)) goto exception; @@ -59697,10 +61072,22 @@ static JSValue js_typed_array_slice(JSContext *ctx, JSValueConst this_val, if (p1 != NULL && p->class_id == p1->class_id && typed_array_length(p1) >= count && typed_array_length(p) >= start + count) { + uint8_t *src, *dst; + int nbytes; shift = typed_array_size_log2(p->class_id); - memmove(p1->u.array.u.uint8_ptr, - p->u.array.u.uint8_ptr + (start << shift), - count << shift); + src = p->u.array.u.uint8_ptr + (start << shift); + dst = p1->u.array.u.uint8_ptr; + nbytes = count << shift; + if (dst > src && dst < src + nbytes) { + /* per spec (step 14.g) the copy is performed byte by byte + in increasing order, observable when the species + constructor returns a view over the same buffer that + overlaps the source ahead of it */ + for (n = 0; n < nbytes; n++) + dst[n] = src[n]; + } else { + memmove(dst, src, nbytes); + } } else { slow_path: space = max_int(0, p->u.array.count - start); @@ -59725,12 +61112,11 @@ static JSValue js_typed_array_slice(JSContext *ctx, JSValueConst this_val, static JSValue js_typed_array_subarray(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { - JSArrayBuffer *abuf; JSTypedArray *ta; JSValueConst args[4]; - JSValue arr, byteOffset, ta_buffer; + JSValue arr, ta_buffer; JSObject *p; - int len, start, final, count, shift, offset; + int len, start, final, count, shift, offset, nargs; p = get_typed_array(ctx, this_val); if (!p) @@ -59744,21 +61130,13 @@ static JSValue js_typed_array_subarray(JSContext *ctx, JSValueConst this_val, goto exception; } count = max_int(final - start, 0); - byteOffset = js_typed_array_get_byteOffset(ctx, this_val); - if (JS_IsException(byteOffset)) - goto exception; ta = p->u.typed_array; - abuf = ta->buffer->u.array_buffer; - if (ta->offset > abuf->byte_length) - goto range_error; - if (ta->offset == abuf->byte_length && count > 0) { - range_error: - JS_ThrowRangeError(ctx, "invalid offset"); - goto exception; - } shift = typed_array_size_log2(p->class_id); - offset = JS_VALUE_GET_INT(byteOffset) + (start << shift); - JS_FreeValue(ctx, byteOffset); + /* per spec, read the [[ByteOffset]] slot directly: it keeps its value + even when the buffer was detached or resized by the argument + coercions above; validation is left to the constructor called by + TypedArraySpeciesCreate */ + offset = ta->offset + (start << shift); ta_buffer = js_typed_array_get_buffer(ctx, this_val); if (JS_IsException(ta_buffer)) goto exception; @@ -59766,10 +61144,13 @@ static JSValue js_typed_array_subarray(JSContext *ctx, JSValueConst this_val, args[1] = safe_const(ta_buffer); args[2] = safe_const(js_int32(offset)); args[3] = safe_const(js_int32(count)); - // result is length-tracking if source TA is and no explicit count is given + // result is length-tracking if source TA is and no explicit end is given; + // the constructor is then called without a length argument if (ta->track_rab && JS_IsUndefined(argv[1])) - args[3] = JS_UNDEFINED; - arr = js_typed_array___speciesCreate(ctx, JS_UNDEFINED, 4, args); + nargs = 3; + else + nargs = 4; + arr = js_typed_array___speciesCreate(ctx, JS_UNDEFINED, nargs, args, false); JS_FreeValue(ctx, ta_buffer); return arr; exception: @@ -60029,7 +61410,7 @@ static JSValue js_typed_array_sort(JSContext *ctx, JSValueConst this_val, size_t i, j; /* XXX: a stable sort would use less memory */ - array_idx = js_malloc(ctx, len * sizeof(array_idx[0])); + array_idx = js_calloc(ctx, len, sizeof(array_idx[0])); if (!array_idx) return JS_EXCEPTION; for(i = 0; i < len; i++) @@ -60887,13 +62268,13 @@ static JSValue js_new_uint8array(JSContext *ctx, JSValue buffer) } JSValue JS_NewUint8Array(JSContext *ctx, uint8_t *buf, size_t len, - JSFreeArrayBufferDataFunc *free_func, void *opaque, - bool is_shared) + JSReallocArrayBufferDataFunc *realloc_func, + void *opaque, bool is_shared) { JSClassID class_id = is_shared ? JS_CLASS_SHARED_ARRAY_BUFFER : JS_CLASS_ARRAY_BUFFER; JSValue buffer = js_array_buffer_constructor3(ctx, JS_UNDEFINED, len, NULL, - class_id, buf, free_func, + class_id, buf, realloc_func, opaque, false); return js_new_uint8array(ctx, buffer); } @@ -60903,7 +62284,7 @@ JSValue JS_NewUint8ArrayCopy(JSContext *ctx, const uint8_t *buf, size_t len) JSValue buffer = js_array_buffer_constructor3(ctx, JS_UNDEFINED, len, NULL, JS_CLASS_ARRAY_BUFFER, (uint8_t *)buf, - js_array_buffer_free, NULL, + js_array_buffer_realloc, NULL, true); return js_new_uint8array(ctx, buffer); } @@ -61153,6 +62534,7 @@ static JSValue js_atomics_store(JSContext *ctx, } /* check if an evil .valueOf has resized or detached the array */ if (idx >= p->u.array.count) { + JS_FreeValue(ctx, ret); return JS_ThrowRangeError(ctx, "out-of-bound access"); } ptr = p->u.array.u.uint8_ptr + ((uintptr_t)idx << size_log2); @@ -61169,6 +62551,7 @@ static JSValue js_atomics_store(JSContext *ctx, } /* check if an evil .valueOf has resized or detached the array */ if (idx >= p->u.array.count) { + JS_FreeValue(ctx, ret); return JS_ThrowRangeError(ctx, "out-of-bound access"); } ptr = p->u.array.u.uint8_ptr + ((uintptr_t)idx << size_log2); @@ -61930,12 +63313,12 @@ static void reset_weak_ref(JSRuntime *rt, JSWeakRefRecord **first_weak_ref) bool enqueue = !rt->in_free; if (enqueue && JS_IsObject(fre->held_val)) { JSObject *p = JS_VALUE_GET_OBJ(fre->held_val); - if (p->free_mark || p->header.mark) + if (p->free_mark || JS_GC_MARK(p)) enqueue = false; } if (enqueue && JS_IsObject(fre->cb)) { JSObject *p = JS_VALUE_GET_OBJ(fre->cb); - if (p->free_mark || p->header.mark) + if (p->free_mark || JS_GC_MARK(p)) enqueue = false; } if (enqueue) { @@ -62019,7 +63402,12 @@ static JSValue js_new_callsite(JSContext *ctx, JSCallSiteData *csd) { return JS_EXCEPTION; } + /* The new object takes ownership of the values in |csd|; clear them so + the caller doesn't free them a second time. */ memcpy(csd1, csd, sizeof(*csd)); + csd->filename = JS_UNDEFINED; + csd->func = JS_UNDEFINED; + csd->func_name = JS_UNDEFINED; JS_SetOpaqueInternal(obj, csd1); @@ -62031,6 +63419,7 @@ static void js_new_callsite_data(JSContext *ctx, JSCallSiteData *csd, JSStackFra const char *func_name_str; JSObject *p; + csd->constructor = sf->is_constructor; csd->func = js_dup(sf->cur_func); /* func_name_str is UTF-8 encoded if needed */ func_name_str = get_func_name(ctx, sf->cur_func); @@ -62070,6 +63459,7 @@ static void js_new_callsite_data2(JSContext *ctx, JSCallSiteData *csd, const cha csd->func = JS_NULL; csd->func_name = JS_NULL; csd->native = false; + csd->constructor = false; csd->line_num = line_num; csd->col_num = col_num; /* filename is UTF-8 encoded if needed (original argument to __JS_EvalInternal()) */ @@ -62097,17 +63487,29 @@ static JSValue js_callsite_isnative(JSContext *ctx, JSValueConst this_val, int a return js_bool(csd->native); } +static JSValue js_callsite_isconstructor(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) +{ + JSCallSiteData *csd = JS_GetOpaque2(ctx, this_val, JS_CLASS_CALL_SITE); + if (!csd) + return JS_EXCEPTION; + return js_bool(csd->constructor); +} + static JSValue js_callsite_getnumber(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int magic) { JSCallSiteData *csd = JS_GetOpaque2(ctx, this_val, JS_CLASS_CALL_SITE); if (!csd) return JS_EXCEPTION; int *field = (void *)((char *)csd + magic); + /* V8 returns null when the frame has no source position (native frames) */ + if (*field < 0) + return JS_NULL; return js_int32(*field); } static const JSCFunctionListEntry js_callsite_proto_funcs[] = { JS_CFUNC_DEF("isNative", 0, js_callsite_isnative), + JS_CFUNC_DEF("isConstructor", 0, js_callsite_isconstructor), JS_CFUNC_MAGIC_DEF("getFileName", 0, js_callsite_getfield, offsetof(JSCallSiteData, filename)), JS_CFUNC_MAGIC_DEF("getFunction", 0, js_callsite_getfield, offsetof(JSCallSiteData, func)), JS_CFUNC_MAGIC_DEF("getFunctionName", 0, js_callsite_getfield, offsetof(JSCallSiteData, func_name)), @@ -63223,6 +64625,9 @@ static JSValue js_uint8array_set_from_base64(JSContext *ctx, if (!p) return JS_EXCEPTION; + if (typed_array_is_immutable(p)) + return JS_ThrowTypeErrorImmutableArrayBuffer(ctx); + if (!JS_IsString(argv[0])) return JS_ThrowTypeError(ctx, "expected string"); @@ -63279,6 +64684,9 @@ static JSValue js_uint8array_set_from_hex(JSContext *ctx, if (!p) return JS_EXCEPTION; + if (typed_array_is_immutable(p)) + return JS_ThrowTypeErrorImmutableArrayBuffer(ctx); + if (!JS_IsString(argv[0])) return JS_ThrowTypeError(ctx, "expected string"); diff --git a/deps/quickjs/quickjs.h b/deps/quickjs/quickjs.h index 68d6f38..68402d4 100644 --- a/deps/quickjs/quickjs.h +++ b/deps/quickjs/quickjs.h @@ -68,7 +68,7 @@ extern "C" { # define JS_EXTERN /* nothing */ # endif #else -# ifdef QUICKJS_NG_CC_GNULIKE +# if defined(BUILDING_QJS_SHARED) && defined(QUICKJS_NG_CC_GNULIKE) # define JS_EXTERN __attribute__((visibility("default"))) # else # define JS_EXTERN /* nothing */ @@ -109,7 +109,7 @@ extern "C" { # define JS_MODULE_EXTERN __declspec(dllimport) # endif #else -# ifdef QUICKJS_NG_CC_GNULIKE +# if defined(QUICKJS_NG_MODULE_BUILD) && defined(QUICKJS_NG_CC_GNULIKE) # define JS_MODULE_EXTERN __attribute__((visibility("default"))) # else # define JS_MODULE_EXTERN /* nothing */ @@ -135,6 +135,25 @@ extern "C" { #endif #endif +/* + * `JS_CALL_X` -- macro tree for calling a function with a variable number of arguments. + * This is used for bulk operations such as freeing values or atoms. + */ +#define JS_COUNT_ARGS_(_0, _8, _7, _6, _5, _4, _3, _2, _1, N, ...) N +#define JS_COUNT_ARGS(...) JS_COUNT_ARGS_(0, __VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0) + +#define JS_CALLX1(F,X,a) do { F(X,a); } while (0) +#define JS_CALLX2(F,X,a,b) do { F(X,a); F(X,b); } while (0) +#define JS_CALLX3(F,X,a,b,c) do { F(X,a); F(X,b); F(X,c); } while (0) +#define JS_CALLX4(F,X,a,b,c,d) do { F(X,a); F(X,b); F(X,c); F(X,d); } while (0) +#define JS_CALLX5(F,X,a,b,c,d,e) do { F(X,a); F(X,b); F(X,c); F(X,d); F(X,e); } while (0) +#define JS_CALLX6(F,X,a,b,c,d,e,f) do { F(X,a); F(X,b); F(X,c); F(X,d); F(X,e); F(X,f); } while (0) +#define JS_CALLX7(F,X,a,b,c,d,e,f,g) do { F(X,a); F(X,b); F(X,c); F(X,d); F(X,e); F(X,f); F(X,g); } while (0) +#define JS_CALLX8(F,X,a,b,c,d,e,f,g,h) do { F(X,a); F(X,b); F(X,c); F(X,d); F(X,e); F(X,f); F(X,g); F(X,h); } while (0) + +#define JS_CALLX__(F, X, N, ...) JS_CALLX##N(F, X, __VA_ARGS__) +#define JS_CALLX_(F, X, N, ...) JS_CALLX__(F, X, N, __VA_ARGS__) + #undef QUICKJS_NG_CC_GNULIKE #undef QUICKJS_NG_PLAT_WIN32 @@ -565,7 +584,6 @@ JS_EXTERN void *js_malloc(JSContext *ctx, size_t size); JS_EXTERN void js_free(JSContext *ctx, void *ptr); JS_EXTERN void *js_realloc(JSContext *ctx, void *ptr, size_t size); JS_EXTERN size_t js_malloc_usable_size(JSContext *ctx, const void *ptr); -JS_EXTERN void *js_realloc2(JSContext *ctx, void *ptr, size_t size, size_t *pslack); JS_EXTERN void *js_mallocz(JSContext *ctx, size_t size); JS_EXTERN char *js_strdup(JSContext *ctx, const char *str); JS_EXTERN char *js_strndup(JSContext *ctx, const char *s, size_t n); @@ -599,6 +617,8 @@ JS_EXTERN JSAtom JS_DupAtom(JSContext *ctx, JSAtom v); JS_EXTERN JSAtom JS_DupAtomRT(JSRuntime *rt, JSAtom v); JS_EXTERN void JS_FreeAtom(JSContext *ctx, JSAtom v); JS_EXTERN void JS_FreeAtomRT(JSRuntime *rt, JSAtom v); +#define JS_FreeAtoms(ctx, ...) JS_CALLX_(JS_FreeAtom, ctx, JS_COUNT_ARGS(__VA_ARGS__), __VA_ARGS__) +#define JS_FreeAtomsRT(rt, ...) JS_CALLX_(JS_FreeAtomRT, rt, JS_COUNT_ARGS(__VA_ARGS__), __VA_ARGS__) JS_EXTERN JSValue JS_AtomToValue(JSContext *ctx, JSAtom atom); JS_EXTERN JSValue JS_AtomToString(JSContext *ctx, JSAtom atom); JS_EXTERN const char *JS_AtomToCStringLen(JSContext *ctx, size_t *plen, JSAtom atom); @@ -843,6 +863,8 @@ JS_EXTERN JSValue JS_PRINTF_FORMAT_ATTR(3, 4) JS_ThrowDOMException(JSContext *ct JS_EXTERN JSValue JS_ThrowOutOfMemory(JSContext *ctx); JS_EXTERN void JS_FreeValue(JSContext *ctx, JSValue v); JS_EXTERN void JS_FreeValueRT(JSRuntime *rt, JSValue v); +#define JS_FreeValues(ctx, ...) JS_CALLX_(JS_FreeValue, ctx, JS_COUNT_ARGS(__VA_ARGS__), __VA_ARGS__) +#define JS_FreeValuesRT(rt, ...) JS_CALLX_(JS_FreeValueRT, rt, JS_COUNT_ARGS(__VA_ARGS__), __VA_ARGS__) JS_EXTERN JSValue JS_DupValue(JSContext *ctx, JSValueConst v); JS_EXTERN JSValue JS_DupValueRT(JSRuntime *rt, JSValueConst v); JS_EXTERN int JS_ToBool(JSContext *ctx, JSValueConst val); /* return -1 for JS_EXCEPTION */ @@ -1047,10 +1069,24 @@ JS_EXTERN JSValue JS_ParseJSON(JSContext *ctx, const char *buf, size_t buf_len, JS_EXTERN JSValue JS_JSONStringify(JSContext *ctx, JSValueConst obj, JSValueConst replacer, JSValueConst space0); -typedef void JSFreeArrayBufferDataFunc(JSRuntime *rt, void *opaque, void *ptr); +/* Manages the backing memory of an externally created ArrayBuffer. + When 'size' is zero, 'ptr' must be freed and NULL returned. Otherwise the + block must be resized to 'size' bytes and the new pointer returned, or NULL + if that is not possible, indicating a memory error, in which case 'ptr' must + stay valid and the ArrayBuffer keeps its current size. */ +typedef void *JSReallocArrayBufferDataFunc(JSRuntime *rt, void *opaque, + void *ptr, size_t size); +/* Creates an ArrayBuffer backed by 'buf'. Pass a zero 'max_len' for a regular, + fixed length ArrayBuffer; a non-zero 'max_len' makes it resizable and is its + maxByteLength. 'realloc_func' may be NULL if the memory must not be managed + by quickjs at all; such an ArrayBuffer can neither be resized nor + transferred to a different length. It is required for resizable + ArrayBuffers, except for SharedArrayBuffers: those commit their maximum size + upfront and therefore need 'buf' to be at least 'max_len' bytes big. */ JS_EXTERN JSValue JS_NewArrayBuffer(JSContext *ctx, uint8_t *buf, size_t len, - JSFreeArrayBufferDataFunc *free_func, void *opaque, - bool is_shared); + size_t max_len, + JSReallocArrayBufferDataFunc *realloc_func, + void *opaque, bool is_shared); JS_EXTERN JSValue JS_NewArrayBufferCopy(JSContext *ctx, const uint8_t *buf, size_t len); JS_EXTERN void JS_DetachArrayBuffer(JSContext *ctx, JSValueConst obj); JS_EXTERN uint8_t *JS_GetArrayBuffer(JSContext *ctx, size_t *psize, JSValueConst obj); @@ -1083,8 +1119,8 @@ JS_EXTERN JSValue JS_GetTypedArrayBuffer(JSContext *ctx, JSValueConst obj, size_t *pbyte_length, size_t *pbytes_per_element); JS_EXTERN JSValue JS_NewUint8Array(JSContext *ctx, uint8_t *buf, size_t len, - JSFreeArrayBufferDataFunc *free_func, void *opaque, - bool is_shared); + JSReallocArrayBufferDataFunc *realloc_func, + void *opaque, bool is_shared); /* returns -1 if not a typed array otherwise return a JSTypedArrayEnum value */ JS_EXTERN int JS_GetTypedArrayType(JSValueConst obj); JS_EXTERN JSValue JS_NewUint8ArrayCopy(JSContext *ctx, const uint8_t *buf, size_t len); @@ -1105,10 +1141,14 @@ typedef enum JSPromiseStateEnum { } JSPromiseStateEnum; JS_EXTERN JSValue JS_NewPromiseCapability(JSContext *ctx, JSValue *resolving_funcs); +JS_EXTERN JSValue JS_PromiseThen(JSContext *ctx, JSValueConst promise, + JSValueConst on_fulfilled, + JSValueConst on_rejected); JS_EXTERN JSPromiseStateEnum JS_PromiseState(JSContext *ctx, JSValueConst promise); JS_EXTERN JSValue JS_PromiseResult(JSContext *ctx, JSValueConst promise); JS_EXTERN bool JS_IsPromise(JSValueConst val); +JS_EXTERN void JS_PromiseMarkAsHandled(JSContext *ctx, JSValueConst promise); JS_EXTERN JSValue JS_NewSettledPromise(JSContext *ctx, bool is_reject, JSValueConst value); JS_EXTERN JSValue JS_NewSymbol(JSContext *ctx, const char *description, bool is_global); @@ -1408,8 +1448,8 @@ JS_EXTERN int JS_SetModuleExportList(JSContext *ctx, JSModuleDef *m, /* Version */ #define QJS_VERSION_MAJOR 0 -#define QJS_VERSION_MINOR 15 -#define QJS_VERSION_PATCH 1 +#define QJS_VERSION_MINOR 16 +#define QJS_VERSION_PATCH 0 #define QJS_VERSION_SUFFIX "" JS_EXTERN const char* JS_GetVersion(void); diff --git a/deps/quickjs/run-test262.c b/deps/quickjs/run-test262.c index 4c996fb..b025e19 100644 --- a/deps/quickjs/run-test262.c +++ b/deps/quickjs/run-test262.c @@ -650,7 +650,7 @@ static void agent_start(void *arg) args[0] = JS_NewArrayBuffer(ctx, agent->broadcast_sab_buf, agent->broadcast_sab_size, - NULL, NULL, true); + /*max_len*/0, NULL, NULL, true); args[1] = JS_NewInt32(ctx, agent->broadcast_val); ret_val = JS_Call(ctx, agent->broadcast_func, JS_UNDEFINED, 2, (JSValueConst *)args); diff --git a/deps/quickjs/test262.conf b/deps/quickjs/test262.conf index 467e31b..4208016 100644 --- a/deps/quickjs/test262.conf +++ b/deps/quickjs/test262.conf @@ -98,6 +98,7 @@ destructuring-assignment destructuring-binding dynamic-import error-cause +error-stack-accessor Error.isError explicit-resource-management exponentiation @@ -140,7 +141,10 @@ Intl.NumberFormat-v3=skip Intl.RelativeTimeFormat=skip Intl.Segmenter=skip IsHTMLDDA +Iterator.prototype.join +iterator-chunking iterator-helpers +iterator-includes iterator-sequencing joint-iteration json-modules @@ -152,7 +156,7 @@ logical-assignment-operators Map Math.sumPrecise new.target -nonextensible-applies-to-private=skip +nonextensible-applies-to-private numeric-separator-literal object-rest object-spread @@ -174,10 +178,10 @@ Reflect.construct Reflect.set Reflect.setPrototypeOf regexp-dotall -regexp-duplicate-named-groups=skip +regexp-duplicate-named-groups regexp-lookbehind regexp-match-indices -regexp-modifiers=skip +regexp-modifiers regexp-named-groups regexp-unicode-property-escapes regexp-v-flag @@ -271,147 +275,6 @@ test262/test/language/expressions/compound-assignment/S11.13.2_A6.9_T1.js test262/test/language/expressions/compound-assignment/S11.13.2_A6.10_T1.js test262/test/language/expressions/compound-assignment/S11.13.2_A6.11_T1.js -# 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/ diff --git a/deps/quickjs/test262_errors.txt b/deps/quickjs/test262_errors.txt index e014e0c..082fb01 100644 --- a/deps/quickjs/test262_errors.txt +++ b/deps/quickjs/test262_errors.txt @@ -17,50 +17,6 @@ test262/test/built-ins/AsyncFromSyncIteratorPrototype/throw/iterator-result-reje 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 and makePassthrough.) -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 and makePassthrough.) -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 and makePassthrough.) -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 and makePassthrough.) -test262/test/built-ins/TypedArray/prototype/subarray/BigInt/speciesctor-get-species-custom-ctor-invocation.js:43: Test262Error: Actual [[object ArrayBuffer], 8, undefined] and expected [[object ArrayBuffer], 8] should have the same contents. Constructor called with arguments (Testing with BigInt64Array and makeResizableArrayBuffer.) -test262/test/built-ins/TypedArray/prototype/subarray/BigInt/speciesctor-get-species-custom-ctor-invocation.js:43: strict mode: Test262Error: Actual [[object ArrayBuffer], 8, undefined] and expected [[object ArrayBuffer], 8] should have the same contents. Constructor called with arguments (Testing with BigInt64Array and makeResizableArrayBuffer.) -test262/test/built-ins/TypedArray/prototype/subarray/byteoffset-with-detached-buffer.js:44: RangeError: invalid offset (Testing with Float64Array and makePassthrough.) -test262/test/built-ins/TypedArray/prototype/subarray/byteoffset-with-detached-buffer.js:44: strict mode: RangeError: invalid offset (Testing with Float64Array and makePassthrough.) -test262/test/built-ins/TypedArray/prototype/subarray/speciesctor-get-species-custom-ctor-invocation.js:43: Test262Error: Actual [[object ArrayBuffer], 8, undefined] and expected [[object ArrayBuffer], 8] should have the same contents. Constructor called with arguments (Testing with Float64Array and makeResizableArrayBuffer.) -test262/test/built-ins/TypedArray/prototype/subarray/speciesctor-get-species-custom-ctor-invocation.js:43: strict mode: Test262Error: Actual [[object ArrayBuffer], 8, undefined] and expected [[object ArrayBuffer], 8] should have the same contents. Constructor called with arguments (Testing with Float64Array and makeResizableArrayBuffer.) -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. @@ -71,23 +27,23 @@ test262/test/language/expressions/assignment/target-member-computed-reference.js 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/dynamic-import/import-attributes/2nd-param-with-type-text.js:10: TypeError: $DONE() not called -test262/test/language/expressions/dynamic-import/import-attributes/2nd-param-with-type-text.js:10: strict mode: TypeError: $DONE() not called 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/import/import-attributes/text-self.js:10: SyntaxError: Could not find export 'default' in module 'test262/test/language/import/import-attributes/text-self.js' 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/await-using/initializer-Symbol.asyncDispose-disposed-at-end-of-imported-module.js:11: SyntaxError: exported variable 'resource' does not exist +test262/test/language/statements/await-using/initializer-Symbol.dispose-disposed-at-end-of-imported-module.js:11: SyntaxError: exported variable 'resource' does not exist 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/using/initializer-disposed-at-end-of-imported-module.js:11: SyntaxError: exported variable 'resource' does not exist 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 diff --git a/deps/quickjs/tests.conf b/deps/quickjs/tests.conf index f94778c..192656e 100644 --- a/deps/quickjs/tests.conf +++ b/deps/quickjs/tests.conf @@ -12,3 +12,7 @@ tests/fixture_cyclic_import.js tests/microbench.js tests/test_worker_module.js tests/fixture_string_exports.js +tests/fixture_throwing_module.js +tests/fixture_reexport_source.js +tests/fixture_reexport_missing.js +tests/fixture_reexport_direct.js diff --git a/deps/quickjs/tests/array-fromasync-enumerable.js b/deps/quickjs/tests/array-fromasync-enumerable.js new file mode 100644 index 0000000..eeaafef --- /dev/null +++ b/deps/quickjs/tests/array-fromasync-enumerable.js @@ -0,0 +1,23 @@ +import { assert, assertArrayEquals } from "./assert.js"; + +/* Array.fromAsync must create its elements with CreateDataPropertyOrThrow, + i.e. enumerable own data properties, so they show up in Object.keys and + spreads. */ + +/* array-like source */ +{ + const arr = await Array.fromAsync([10, 20, 30]); + assertArrayEquals(Object.keys(arr), ["0", "1", "2"]); + const d = Object.getOwnPropertyDescriptor(arr, 0); + assert(d.enumerable, true); + assert(d.writable, true); + assert(d.configurable, true); +} + +/* async-iterable source */ +{ + const iter = { async *[Symbol.asyncIterator]() { yield "a"; yield "b"; } }; + const arr = await Array.fromAsync(iter); + assertArrayEquals(Object.keys(arr), ["0", "1"]); + assert(Object.getOwnPropertyDescriptor(arr, 0).enumerable, true); +} diff --git a/deps/quickjs/tests/atomics-store-leak.js b/deps/quickjs/tests/atomics-store-leak.js new file mode 100644 index 0000000..7f87312 --- /dev/null +++ b/deps/quickjs/tests/atomics-store-leak.js @@ -0,0 +1,36 @@ +/*--- +features: [skip-if-tcc] +---*/ + +import { assert } from "./assert.js"; + +const big = 0x123456789abcn; + +// Detached buffer. +{ + const ab = new ArrayBuffer(8); + const ta = new BigInt64Array(ab); + const evil = { valueOf() { ab.transfer(); return big; } }; + let err; + try { + Atomics.store(ta, 0, evil); + } catch (e) { + err = e; + } + assert(err instanceof RangeError, true); +} + +// Shrunk resizable buffer. +{ + const ab = new ArrayBuffer(8, { maxByteLength: 16 }); + const ta = new BigUint64Array(ab); + const evil = { valueOf() { ab.resize(0); return big; } }; + let err; + try { + Atomics.store(ta, 0, evil); + } catch (e) { + err = e; + } + assert(err instanceof RangeError, true); +} + diff --git a/deps/quickjs/tests/bug1221.js b/deps/quickjs/tests/bug1221.js deleted file mode 100644 index a3ed10e..0000000 --- a/deps/quickjs/tests/bug1221.js +++ /dev/null @@ -1,16 +0,0 @@ -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 diff --git a/deps/quickjs/tests/bug1552.js b/deps/quickjs/tests/bug1552.js new file mode 100644 index 0000000..4b83618 --- /dev/null +++ b/deps/quickjs/tests/bug1552.js @@ -0,0 +1,87 @@ +// `set Iterator.prototype.constructor` must implement +// SetterThatIgnoresPrototypeProperties(%Iterator.prototype%, "constructor", v): +// it operates on `this` (the receiver), not on the value being assigned. +// https://tc39.es/ecma262/#sec-set-iterator.prototype.constructor +// https://tc39.es/ecma262/#sec-SetterThatIgnoresPrototypeProperties +import { assert, assertThrows } from "./assert.js"; + +const desc = Object.getOwnPropertyDescriptor(Iterator.prototype, "constructor"); +const get = desc.get; +const set = desc.set; + +assert(typeof get, "function"); +assert(typeof set, "function"); +assert(get !== set, true); +assert(get.length, 0); +assert(set.length, 1); + +assert(get.call({}), Iterator); +assert(get.call(undefined), Iterator); +assert(Iterator.prototype.constructor, Iterator); +{ + const o = {}; + assert(get.call(o, 123), Iterator); + assert(Object.prototype.hasOwnProperty.call(o, "constructor"), false); +} + +{ + const o = {}; + assert(set.call(o), undefined); + const d = Object.getOwnPropertyDescriptor(o, "constructor"); + assert(d.value, undefined); + assert(d.writable, true); + assert(d.enumerable, true); + assert(d.configurable, true); +} + +{ + const o = {}; + assert(set.call(o, 0), undefined); + // The value `v` need not be an object; a fresh data property is created. + const d = Object.getOwnPropertyDescriptor(o, "constructor"); + assert(d.value, 0); + assert(d.writable, true); + assert(d.enumerable, true); + assert(d.configurable, true); +} + +assertThrows(TypeError, () => set.call(undefined, 0)); +assertThrows(TypeError, () => set.call(null, 0)); +assertThrows(TypeError, () => set.call(1, 0)); +assertThrows(TypeError, () => set.call("s", 0)); + +assertThrows(TypeError, () => set.call(Iterator.prototype, 0)); +assert(Iterator.prototype.constructor, Iterator); + +{ + const o = {}; + Object.defineProperty(o, "constructor", { + value: 1, writable: false, enumerable: true, configurable: true, + }); + assertThrows(TypeError, () => set.call(o, 2)); + assert(o.constructor, 1); // unchanged +} + +{ + const o = { constructor: 1 }; + assert(set.call(o, 2), undefined); + assert(o.constructor, 2); +} + +{ + const o = Object.preventExtensions({}); + assertThrows(TypeError, () => set.call(o, 0)); + assert(Object.prototype.hasOwnProperty.call(o, "constructor"), false); +} + +{ + const it = Object.create(Iterator.prototype); + it.constructor = 42; + const d = Object.getOwnPropertyDescriptor(it, "constructor"); + assert(d.value, 42); + assert(d.writable, true); + assert(d.enumerable, true); + assert(d.configurable, true); + assert(Iterator.prototype.constructor, Iterator); +} + diff --git a/deps/quickjs/tests/bug1557.js b/deps/quickjs/tests/bug1557.js new file mode 100644 index 0000000..5e74017 --- /dev/null +++ b/deps/quickjs/tests/bug1557.js @@ -0,0 +1,55 @@ +// https://github.com/quickjs-ng/quickjs/issues/1557 +import { assert, assertArrayEquals } from "./assert.js"; + +assertArrayEquals( + Iterator.from([1, 2, 3, 4]).filter(x => x > 1).take(1).toArray(), + [2] +); + +assertArrayEquals(Iterator.from([1, 2, 3, 4]).map(x => x * 2).take(2).toArray(), [2, 4]); +assertArrayEquals(Iterator.from([1, 2, 3, 4, 5]).drop(1).take(2).toArray(), [2, 3]); +assertArrayEquals(Iterator.from([1, 2, 3]).flatMap(x => [x, x * 10]).take(3).toArray(), [1, 10, 2]); +assertArrayEquals(Iterator.from([1, 2, 3, 4, 5, 6]).filter(x => x % 2 === 0).map(x => x + 1).take(2).toArray(), [3, 5]); + +// Calling `.return()` explicitly on a helper over a `return`-less source must +// not throw and must report completion with an undefined value. +for (const make of [ + it => it.map(x => x), + it => it.filter(() => true), + it => it.take(5), + it => it.drop(0), + it => it.flatMap(x => [x]), +]) { + // `[][Symbol.iterator]()` is a plain array iterator: it has no `return`. + const helper = make([1, 2, 3][Symbol.iterator]()); + const r1 = helper.return(); + assert(r1.done, true); + assert(r1.value, undefined); + // A second `.return()` is a no-op and also reports done. + const r2 = helper.return(); + assert(r2.done, true); + assert(r2.value, undefined); +} + +// When the source *does* have a `return`, closing the helper must still +// forward to it exactly once. +for (const make of [ + it => it.map(x => x), + it => it.filter(() => true), + it => it.take(5), + it => it.drop(0), + it => it.flatMap(x => [x]), +]) { + let returnCount = 0; + class Src extends Iterator { + next() { return { done: false, value: 1 }; } + return(value) { returnCount++; return { done: true, value }; } + } + const helper = make(new Src()); + helper.next(); + assert(returnCount, 0); + helper.return(); + assert(returnCount, 1); + helper.return(); // already closed: not forwarded again + assert(returnCount, 1); +} diff --git a/deps/quickjs/tests/bug1562.js b/deps/quickjs/tests/bug1562.js new file mode 100644 index 0000000..ad82119 --- /dev/null +++ b/deps/quickjs/tests/bug1562.js @@ -0,0 +1,65 @@ +import * as std from "qjs:std"; +import { assert } from "./assert.js"; + +{ + const keep = []; + for (let i = 0; i < 30; i++) { + const a = [0]; + a.length = 245; + a.push(2); + keep.push(a); + } + std.gc(); + for (const a of keep) { + assert(a.length, 246); + assert(a[0], 0); + assert(a[245], 2); + assert(a.hasOwnProperty(1), false); + } +} + +{ + const a = [0]; + a.length = 245; + assert(a.push(2), 246); + assert(a.length, 246); + assert(a[0], 0); + assert(a[245], 2); + assert(1 in a, false); + assert(244 in a, false); + assert(245 in a, true); +} + +{ + const d = [9]; + d.length = 3; + assert(d.push(7, 8), 5); + assert(d.length, 5); + assert(d[0], 9); + assert(d[3], 7); + assert(d[4], 8); + assert(1 in d, false); + assert(2 in d, false); +} + +{ + const objs = []; + for (let i = 0; i < 30; i++) { + const a = [{ a: 1 }, { b: 2 }, { c: 3 }, { d: 4 }, { e: 5 }]; + a.length = 2; + a.length = 5; + a.push({ f: 6 }); + objs.push(a); + } + std.gc(); + for (const a of objs) { + assert(a.length, 6); + assert(a[0].a, 1); + assert(a[1].b, 2); + assert(2 in a, false); + assert(3 in a, false); + assert(4 in a, false); + assert(a[5].f, 6); + } +} + diff --git a/deps/quickjs/tests/bug1564.js b/deps/quickjs/tests/bug1564.js new file mode 100644 index 0000000..d621f56 --- /dev/null +++ b/deps/quickjs/tests/bug1564.js @@ -0,0 +1,5 @@ +const s = new DisposableStack(); +s.adopt({}, () => { gc(); }); // disposed last (i=0); its disposer runs the GC +s.use({ [Symbol.dispose]() {} }); // disposed first (i=1); freed before the adopt disposer runs +s.dispose(); + diff --git a/deps/quickjs/tests/bug1565.js b/deps/quickjs/tests/bug1565.js new file mode 100644 index 0000000..e157670 --- /dev/null +++ b/deps/quickjs/tests/bug1565.js @@ -0,0 +1,16 @@ +new Set([{}]).union(new Set([9])); // leaked the {} element +new Set([{}]).symmetricDifference(new Set([9])); // same + +// symmetricDifference: element only reachable via the setlike iterator +new Set([1]).symmetricDifference(new Set([{}])); + +// intersection, |this| larger than the argument: iterates the argument's keys +var o1 = {}; +new Set([o1, 1, 2]).intersection(new Set([o1])); + +// intersection, |this| not larger: iterates |this| and probes with .has() +var o2 = {}; +new Set([o2]).intersection(new Set([o2, 1, 2])); + +// difference, |this| not larger: iterates |this| and keeps the misses +new Set([{}]).difference(new Set([9])); diff --git a/deps/quickjs/tests/bug1571.js b/deps/quickjs/tests/bug1571.js new file mode 100644 index 0000000..b087681 --- /dev/null +++ b/deps/quickjs/tests/bug1571.js @@ -0,0 +1,13 @@ +import { assert } from "./assert.js"; + +function check(unit, halfCount) { + const rope = unit.repeat(halfCount) + unit.repeat(halfCount); + const flat = unit.repeat(halfCount * 2); + assert(rope.length, flat.length); + assert(RegExp.escape(rope), RegExp.escape(flat)); +} + +check("a", 50000); +check("a.b-c|d", 4000); +check("€☃", 4000); + diff --git a/deps/quickjs/tests/bug1572.js b/deps/quickjs/tests/bug1572.js new file mode 100644 index 0000000..e1b418c --- /dev/null +++ b/deps/quickjs/tests/bug1572.js @@ -0,0 +1,18 @@ +import { assert } from "./assert.js"; + +// Every element takes the non-matching path (the predicate is never true). +{ + const o = {}; + assert([o, o, o].values().find(() => false), undefined); + assert(new Array(1000).fill(o).values().find(() => false), undefined); +} + +// The match path still returns the first match and forwards (value, index). +{ + const seen = []; + const r = [10, 20, 30, 40].values().find((v, i) => { seen.push(v, i); return v === 30; }); + assert(r, 30); + assert(seen.length, 6); // stopped at the third element + assert(seen[0], 10); assert(seen[1], 0); + assert(seen[4], 30); assert(seen[5], 2); +} diff --git a/deps/quickjs/tests/bug1591.js b/deps/quickjs/tests/bug1591.js new file mode 100644 index 0000000..742dc69 --- /dev/null +++ b/deps/quickjs/tests/bug1591.js @@ -0,0 +1,26 @@ +import { assert, assertThrows } from "./assert.js"; + +function pat(plain) { + return "(?a)" + "|x".repeat(plain) + "|(?c)"; +} + +function messageOf(re) { + try { + new RegExp(re); + } catch (e) { + return e.message; + } + return undefined; +} + +// 256 alternatives: fine. +assert(new RegExp(pat(254)).test("a"), true); + +// 257 alternatives and beyond: explicit error instead of a wrong +// "duplicate group name" report. +assert(messageOf(pat(255)), "too many named groups"); +assert(messageOf(pat(1000)), "too many named groups"); + +// A genuine duplicate within the same alternative must still be rejected. +assert(messageOf("(?a)(?b)"), "duplicate group name"); +assertThrows(SyntaxError, () => new RegExp("(?a)(?b)")); diff --git a/deps/quickjs/tests/bug567.js b/deps/quickjs/tests/bug567.js new file mode 100644 index 0000000..b7537e9 --- /dev/null +++ b/deps/quickjs/tests/bug567.js @@ -0,0 +1,5 @@ +import {assert} from "./assert.js" +import {f} from "./fixture_cyclic_import.js" +export {f} +export function g(x) { return x + 1 } +assert(f(1), 4) diff --git a/deps/quickjs/tests/callsite-isconstructor.js b/deps/quickjs/tests/callsite-isconstructor.js new file mode 100644 index 0000000..4fdb044 --- /dev/null +++ b/deps/quickjs/tests/callsite-isconstructor.js @@ -0,0 +1,30 @@ +import { assert } from "./assert.js"; + +/* CallSite.prototype.isConstructor reports whether the frame was invoked as a + constructor (via `new`). */ + +let frames; +Error.prepareStackTrace = (_, f) => { frames = f; return f; }; + +function Thing() { void new Error(""); } +new Thing(); + +function plain() { void new Error(""); } +plain(); + +Error.prepareStackTrace = undefined; + +// after plain(): frame 0 is plain (not a constructor) +assert(frames[0].getFunctionName(), "plain"); +assert(!frames[0].isConstructor()); + +// re-run for the constructor case +Error.prepareStackTrace = (_, f) => { frames = f; return f; }; +new Thing(); +Error.prepareStackTrace = undefined; + +// frame 0 is Thing, invoked via `new` +assert(frames[0].getFunctionName(), "Thing"); +assert(frames[0].isConstructor()); +// its caller (module top level) is not a constructor +assert(!frames[1].isConstructor()); diff --git a/deps/quickjs/tests/callsite-native-position.js b/deps/quickjs/tests/callsite-native-position.js new file mode 100644 index 0000000..6a8c8c8 --- /dev/null +++ b/deps/quickjs/tests/callsite-native-position.js @@ -0,0 +1,19 @@ +import { assert } from "./assert.js"; + +/* CallSite position getters return null for frames with no source position + (native frames), matching V8, instead of leaking the internal -1. */ + +Error.prepareStackTrace = (_, frames) => frames; +const frames = [1].map(function m() { return new Error().stack; })[0]; +Error.prepareStackTrace = undefined; + +const native = frames.find((f) => f.isNative()); +assert(native !== undefined, true); +assert(native.getLineNumber(), null); +assert(native.getColumnNumber(), null); +assert(native.getFileName(), null); + +/* frames with a real position still report numbers */ +const scripted = frames.find((f) => !f.isNative()); +assert(typeof scripted.getLineNumber(), "number"); +assert(typeof scripted.getColumnNumber(), "number"); diff --git a/deps/quickjs/tests/destructured-export.js b/deps/quickjs/tests/destructured-export.js index a038c6f..766827d 100644 --- a/deps/quickjs/tests/destructured-export.js +++ b/deps/quickjs/tests/destructured-export.js @@ -4,5 +4,17 @@ import * as mod from "./destructured-export.js"; export const { a, b, c } = { a: 1, b: 2, c: 3 }; export const d = 4; +/* array destructuring targets must be exported too */ +export const [e, f] = [5, 6]; +export const [g, ...h] = [7, 8, 9]; +export let [{ i }, [j]] = [{ i: 10 }, [11]]; + assert(typeof mod === 'object'); -assertArrayEquals(Object.keys(mod), ["a", "b", "c", "d"]); +assertArrayEquals(Object.keys(mod), + ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]); +assert(mod.e, 5); +assert(mod.f, 6); +assert(mod.g, 7); +assertArrayEquals(mod.h, [8, 9]); +assert(mod.i, 10); +assert(mod.j, 11); diff --git a/deps/quickjs/tests/dynamic_import_rejection_handled.js b/deps/quickjs/tests/dynamic_import_rejection_handled.js new file mode 100644 index 0000000..98d5648 --- /dev/null +++ b/deps/quickjs/tests/dynamic_import_rejection_handled.js @@ -0,0 +1,7 @@ +/*--- +flags: [qjs:track-promise-rejections] +---*/ + +// import() of a throwing module must not leak the module's internal rejection. +const error = await import("./fixture_throwing_module.js").then(() => 'ok', e => e) +print('Got this error:', error.message) diff --git a/deps/quickjs/tests/fixture_cyclic_import.js b/deps/quickjs/tests/fixture_cyclic_import.js index bac80d8..e223ad1 100644 --- a/deps/quickjs/tests/fixture_cyclic_import.js +++ b/deps/quickjs/tests/fixture_cyclic_import.js @@ -1,2 +1,2 @@ -import * as a from "./test_cyclic_import.js" +import * as a from "./bug567.js" export function f(x) { return 2 * a.g(x) } diff --git a/deps/quickjs/tests/fixture_import_attributes.json b/deps/quickjs/tests/fixture_import_attributes.json new file mode 100644 index 0000000..6e887fd --- /dev/null +++ b/deps/quickjs/tests/fixture_import_attributes.json @@ -0,0 +1 @@ +{ "answer": 42 } diff --git a/deps/quickjs/tests/fixture_reexport_direct.js b/deps/quickjs/tests/fixture_reexport_direct.js new file mode 100644 index 0000000..39e3832 --- /dev/null +++ b/deps/quickjs/tests/fixture_reexport_direct.js @@ -0,0 +1 @@ +import { doesNotExist } from "./fixture_reexport_source.js" diff --git a/deps/quickjs/tests/fixture_reexport_missing.js b/deps/quickjs/tests/fixture_reexport_missing.js new file mode 100644 index 0000000..72d1b96 --- /dev/null +++ b/deps/quickjs/tests/fixture_reexport_missing.js @@ -0,0 +1 @@ +export { doesNotExist } from "./fixture_reexport_source.js" diff --git a/deps/quickjs/tests/fixture_reexport_source.js b/deps/quickjs/tests/fixture_reexport_source.js new file mode 100644 index 0000000..9d7905a --- /dev/null +++ b/deps/quickjs/tests/fixture_reexport_source.js @@ -0,0 +1 @@ +export const real = 1 diff --git a/deps/quickjs/tests/fixture_throwing_module.js b/deps/quickjs/tests/fixture_throwing_module.js new file mode 100644 index 0000000..a5315dd --- /dev/null +++ b/deps/quickjs/tests/fixture_throwing_module.js @@ -0,0 +1 @@ +throw new Error("Nuke the entire site from orbit. It's the only way to be sure.") diff --git a/deps/quickjs/tests/for-await-normal-close.js b/deps/quickjs/tests/for-await-normal-close.js new file mode 100644 index 0000000..3bb3787 --- /dev/null +++ b/deps/quickjs/tests/for-await-normal-close.js @@ -0,0 +1,50 @@ +import { assert } from "./assert.js"; + +function makeAsyncIter(log) { + let i = 0; + return { [Symbol.asyncIterator]() { return { + next() { + return Promise.resolve(i < 2 ? { value: i++, done: false } + : { value: undefined, done: true }); + }, + return() { log.returned++; return Promise.resolve({ done: true }); }, + }; } }; +} + +/* normal completion must NOT call return() */ +{ + const log = { returned: 0 }; + for await (const x of makeAsyncIter(log)) {} + assert(log.returned, 0); +} + +/* break is an abrupt completion and must call return() */ +{ + const log = { returned: 0 }; + for await (const x of makeAsyncIter(log)) break; + assert(log.returned, 1); +} + +/* throw is an abrupt completion and must call return() */ +{ + const log = { returned: 0 }; + try { + for await (const x of makeAsyncIter(log)) throw new Error("stop"); + } catch (e) {} + assert(log.returned, 1); +} + +/* leaving the loop via break must await the result of return() */ +{ + const order = []; + const it = { [Symbol.asyncIterator]() { let i = 0; return { + next() { return Promise.resolve({ value: i++, done: false }); }, + return() { + order.push("return"); + return Promise.resolve().then(() => { order.push("resolved"); return { done: true }; }); + }, + }; } }; + for await (const x of it) break; + order.push("after"); + assert(order.join(","), "return,resolved,after"); +} diff --git a/deps/quickjs/tests/global-reference-column.js b/deps/quickjs/tests/global-reference-column.js new file mode 100644 index 0000000..a595c96 --- /dev/null +++ b/deps/quickjs/tests/global-reference-column.js @@ -0,0 +1,19 @@ +import { assert } from "./assert.js"; + +/* A ReferenceError for an undefined global should point at the column of the + reference, not column 1 or the enclosing function. The location is exposed + through the error's stack trace. */ +function refColumn(src) { + try { + (0, eval)(src); + } catch (e) { + const m = /:(\d+):(\d+)/.exec(e.stack); + if (m) + return +m[2]; + } + return -1; +} + +assert(refColumn("x"), 1); +assert(refColumn(" missingGlobal"), 4); +assert(refColumn("let a=1; alsoMissing"), 10); diff --git a/deps/quickjs/tests/import-attributes-identity.js b/deps/quickjs/tests/import-attributes-identity.js new file mode 100644 index 0000000..3c1838f --- /dev/null +++ b/deps/quickjs/tests/import-attributes-identity.js @@ -0,0 +1,35 @@ +import { assert } from "./assert.js"; + +/* Module identity is keyed by (specifier, import attributes): the same + file can be loaded as different module types, equal attribute sets + share one instance, and this module can import itself as text. */ + +import textDefault from "./fixture_import_attributes.json" with { type: "text" }; +import jsonDefault from "./fixture_import_attributes.json" with { type: "json" }; +import jsonAgain from "./fixture_import_attributes.json" with { type: "json" }; +import self from "./import-attributes-identity.js" with { type: "text" }; + +/* same file, different types, distinct modules */ +assert(typeof textDefault, "string"); +assert(JSON.parse(textDefault).answer, 42); +assert(typeof jsonDefault, "object"); +assert(jsonDefault.answer, 42); + +/* equal attributes resolve to the same module instance */ +assert(jsonAgain === jsonDefault, true); + +/* a JS module can import its own source as text */ +assert(typeof self, "string"); +assert(self.includes("import-attributes-identity"), true); + +/* dynamic imports share identity with static imports */ +const viaJson = await import("./fixture_import_attributes.json", { with: { type: "json" } }); +assert(viaJson.default === jsonDefault, true); +const viaText = await import("./fixture_import_attributes.json", { with: { type: "text" } }); +assert(viaText.default, textDefault); + +/* no attributes and .json suffix still defaults to JSON, as another + distinct module */ +const plain = await import("./fixture_import_attributes.json"); +assert(typeof plain.default, "object"); +assert(plain.default === jsonDefault, false); diff --git a/deps/quickjs/tests/iterator-filter-leak.js b/deps/quickjs/tests/iterator-filter-leak.js new file mode 100644 index 0000000..7558e97 --- /dev/null +++ b/deps/quickjs/tests/iterator-filter-leak.js @@ -0,0 +1,21 @@ +import { assert } from "./assert.js"; + +// The predicate rejects every value: each produced object must be freed. +{ + const src = Array.from({ length: 100 }, (_, i) => ({ i })); + const out = src.values().filter(() => false).toArray(); + assert(out.length, 0); +} + +// The predicate throws mid-iteration: the value being tested must be freed. +{ + let threw = false; + try { + [{ a: 1 }, { b: 2 }, { c: 3 }].values() + .filter(() => { throw new Error("boom"); }) + .toArray(); + } catch (e) { + threw = true; + } + assert(threw, true); +} diff --git a/deps/quickjs/tests/iterator-tostringtag-setter.js b/deps/quickjs/tests/iterator-tostringtag-setter.js new file mode 100644 index 0000000..f49780b --- /dev/null +++ b/deps/quickjs/tests/iterator-tostringtag-setter.js @@ -0,0 +1,44 @@ +// `set Iterator.prototype[Symbol.toStringTag]` implements +// SetterThatIgnoresPrototypeProperties(%Iterator.prototype%, @@toStringTag, v). +// In particular the CreateDataPropertyOrThrow step must throw on a +// non-extensible receiver rather than silently doing nothing. +// https://tc39.es/ecma262/#sec-set-iterator.prototype-%symbol.tostringtag% +// https://tc39.es/ecma262/#sec-SetterThatIgnoresPrototypeProperties +import { assert, assertThrows } from "./assert.js"; + +const desc = Object.getOwnPropertyDescriptor(Iterator.prototype, Symbol.toStringTag); +const set = desc.set; + +assert(Iterator.prototype[Symbol.toStringTag], "Iterator"); + +assertThrows(TypeError, () => set.call(undefined, "x")); +assertThrows(TypeError, () => set.call(null, "x")); +assertThrows(TypeError, () => set.call(1, "x")); + +assertThrows(TypeError, () => set.call(Iterator.prototype, "x")); +assert(Iterator.prototype[Symbol.toStringTag], "Iterator"); + +{ + const o = {}; + assert(set.call(o, "x"), undefined); + const d = Object.getOwnPropertyDescriptor(o, Symbol.toStringTag); + assert(d.value, "x"); + assert(d.writable, true); + assert(d.enumerable, true); + assert(d.configurable, true); +} + +{ + const o = {}; + Object.defineProperty(o, Symbol.toStringTag, { + value: "a", writable: false, enumerable: true, configurable: true, + }); + assertThrows(TypeError, () => set.call(o, "b")); + assert(o[Symbol.toStringTag], "a"); +} + +{ + const o = Object.preventExtensions({}); + assertThrows(TypeError, () => set.call(o, "x")); + assert(Object.prototype.hasOwnProperty.call(o, Symbol.toStringTag), false); +} diff --git a/deps/quickjs/tests/parse-error-column.js b/deps/quickjs/tests/parse-error-column.js new file mode 100644 index 0000000..07445aa --- /dev/null +++ b/deps/quickjs/tests/parse-error-column.js @@ -0,0 +1,26 @@ +import { assert } from "./assert.js"; + +/* A SyntaxError should report the column of the offending token, not always + column 1. The location is exposed through the error's stack trace. */ +function errorLocation(src) { + try { + eval(src); + } catch (e) { + const m = /:(\d+):(\d+)/.exec(e.stack); + if (m) + return { line: +m[1], col: +m[2] }; + } + return { line: -1, col: -1 }; +} + +assert(errorLocation("let x = ;").col, 9); +assert(errorLocation("1 + + ;").col, 7); +assert(errorLocation("hocuspocus(").col, 12); +assert(errorLocation("a b").col, 3); + +/* line number stays correct and the column is relative to the line start */ +{ + const loc = errorLocation("let ok = 1\nlet z = @"); + assert(loc.line, 2); + assert(loc.col, 9); +} diff --git a/deps/quickjs/tests/reexport-error-module.js b/deps/quickjs/tests/reexport-error-module.js new file mode 100644 index 0000000..778a307 --- /dev/null +++ b/deps/quickjs/tests/reexport-error-module.js @@ -0,0 +1,14 @@ +import { assert } from "./assert.js"; + +/* A re-export of a missing binding must blame the *source* module and the + name looked up there -- exactly like a direct import of the same missing + binding does. Comparing the two messages avoids depending on the module + path surviving intact in the error: long absolute paths get truncated in + the fixed-size atom buffer, so a substring check on the filename is + unreliable in CI. */ +const reexportErr = await import("./fixture_reexport_missing.js").then(() => null, e => e); +const directErr = await import("./fixture_reexport_direct.js").then(() => null, e => e); + +assert(reexportErr instanceof SyntaxError); +assert(directErr instanceof SyntaxError); +assert(reexportErr.message, directErr.message); diff --git a/deps/quickjs/tests/suspended-coroutine-closure-gc.js b/deps/quickjs/tests/suspended-coroutine-closure-gc.js new file mode 100644 index 0000000..3c31eb9 --- /dev/null +++ b/deps/quickjs/tests/suspended-coroutine-closure-gc.js @@ -0,0 +1,35 @@ +import * as std from "qjs:std"; +import { assert } from "./assert.js"; + +// Regression test: a suspended coroutine reachable only through a closure that +// captured one of its locals must not be collected while it is still live. +// +// A closure capturing a coroutine local holds an *open* var_ref into the +// coroutine's frame. Open var_refs are not GC objects and are not marked by +// the closure, so the edge closure -> open var_ref -> value is invisible to +// the cycle collector. An ordinary function's frame is a live C-stack root, but +// a suspended coroutine's frame is a heap GC object, so if the only thing +// keeping it reachable is such an escaped closure, the whole still-live +// coroutine used to be collected -- and resuming it, or running the closure, +// then touched freed memory. +// +// The async function below suspends at `await d.promise`; that promise is never +// resolved, so nothing keeps the coroutine reachable except `leaked`'s capture +// of the frame local `d`. Forcing a GC while it is suspended used to free it. + +globalThis.leaked = null; + +(function () { + async function step() { + const d = Promise.withResolvers(); + globalThis.leaked = () => d; // escapes, capturing the coroutine local `d` + await d.promise; // suspend: reachable only via leaked -> d + } + step(); +})(); + +std.gc(); + +// If the suspended coroutine's frame was wrongly collected, `d` is freed memory. +const d = leaked(); +assert(typeof d.resolve, "function"); diff --git a/deps/quickjs/tests/suspended-coroutine-mapped-arguments-gc.js b/deps/quickjs/tests/suspended-coroutine-mapped-arguments-gc.js new file mode 100644 index 0000000..72aa84d --- /dev/null +++ b/deps/quickjs/tests/suspended-coroutine-mapped-arguments-gc.js @@ -0,0 +1,28 @@ +import * as std from "qjs:std"; +import { assert } from "./assert.js"; + +// Regression test: a suspended coroutine kept reachable only through its mapped +// `arguments` object must not be collected. +// +// A sloppy function with a simple parameter list that uses `arguments` gets a +// *mapped* arguments object whose entries are open var_refs pointing into the +// function's frame. That object is a third var_ref holder (besides closures and +// object var_ref properties) and must be traced the same way; otherwise a +// suspended coroutine reachable only via an escaped `arguments` is either freed +// while still live (use-after-free) or wrongly retained (a leak that trips the +// gc_obj_list check at runtime teardown). + +globalThis.leaked = null; + +const AsyncFunction = (async function () {}).constructor; +const step = AsyncFunction("a", ` + globalThis.leaked = () => arguments; // escapes, capturing the frame + const d = Promise.withResolvers(); + await d.promise; // suspend; never resolved +`); +step(123); + +std.gc(); + +// If the frame was wrongly collected this reads freed memory. +assert(leaked()[0], 123); diff --git a/deps/quickjs/tests/suspended-generator-closure-gc.js b/deps/quickjs/tests/suspended-generator-closure-gc.js new file mode 100644 index 0000000..8dcd68c --- /dev/null +++ b/deps/quickjs/tests/suspended-generator-closure-gc.js @@ -0,0 +1,33 @@ +import * as std from "qjs:std"; +import { assert } from "./assert.js"; + +// Regression test: a suspended generator kept reachable only through a closure +// that captured one of its locals must not be collected. +// +// This is the sync-generator counterpart of suspended-coroutine-closure-gc.js: +// there is no promise involved. The generator object is held in a cycle through +// a captured local, and the escaped closure is the only external anchor. The +// closure holds an open var_ref into the generator's (heap) frame; if that edge +// is invisible to the cycle collector the generator and its frame are freed +// while the closure still points into them. + +globalThis.leaked = null; + +(function () { + let g; + function* gen() { + const o = {}; + o.g = g; // frame local -> generator object (a cycle) + globalThis.leaked = () => o; // escapes, capturing the frame local `o` + yield; // suspend + } + g = gen(); + g.next(); // run to the yield + g = null; // now reachable only via the cycle + leaked +})(); + +std.gc(); + +const o = leaked(); +assert(o.g !== null && o.g !== undefined); // the generator object is still alive +o.g.next(); // resume it: touches its frame diff --git a/deps/quickjs/tests/test_bigint.js b/deps/quickjs/tests/test_bigint.js index 4dc977f..06ca82e 100644 --- a/deps/quickjs/tests/test_bigint.js +++ b/deps/quickjs/tests/test_bigint.js @@ -102,6 +102,36 @@ function test_bigint_map() assert(m.size, 0); } +function test_bigint_asintn() +{ + /* BigInt.asIntN */ + assert(BigInt.asIntN(0, -1n), 0n); + assert(BigInt.asIntN(1, -1n), -1n); + assert(BigInt.asIntN(8, 128n), -128n); + assert(BigInt.asIntN(8, 127n), 127n); + assert(BigInt.asIntN(64, -1n), -1n); + assert(BigInt.asIntN(64, 0x8000000000000000n), -0x8000000000000000n); + assert(BigInt.asIntN(128, -1n), -1n); + + /* BigInt.asUintN: wrapping a negative value when the requested width is a + multiple of the internal limb size used to return the value unchanged. */ + assert(BigInt.asUintN(0, -1n), 0n); + assert(BigInt.asUintN(1, -1n), 1n); + assert(BigInt.asUintN(8, -1n), 0xffn); + assert(BigInt.asUintN(64, -1n), 0xffffffffffffffffn); + assert(BigInt.asUintN(64, -2n), 0xfffffffffffffffen); + assert(BigInt.asUintN(64, 0x8000000000000000n), 0x8000000000000000n); + assert(BigInt.asUintN(128, -1n), (1n << 128n) - 1n); + assert(BigInt.asUintN(192, -1n), (1n << 192n) - 1n); + assert(BigInt.asUintN(64, -(1n << 64n)), 0n); + assert(BigInt.asUintN(64, 1n << 64n), 0n); + + /* non-negative values are returned unchanged */ + assert(BigInt.asUintN(64, 123n), 123n); + assert(BigInt.asIntN(64, 123n), 123n); +} + test_bigint1(); test_bigint2(); test_bigint_map(); +test_bigint_asintn(); diff --git a/deps/quickjs/tests/test_bjson.js b/deps/quickjs/tests/test_bjson.js index fff1a9a..5842103 100644 --- a/deps/quickjs/tests/test_bjson.js +++ b/deps/quickjs/tests/test_bjson.js @@ -285,11 +285,11 @@ function bjson_test_bytecode() function bjson_test_fuzz() { var corpus = [ - ["Gv////8QAAAAAARg"], - ["Gv/////m5uaCLQ=="], - ["Gv////8AEQATBgYGBgYGBgYGBgb/////EAARAC8R/78vEf+/"], - ["Gv////8ACH8ACv////9//////////////////////////////9//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAA+fn5+fn5+fn5+fn5AAAAAAAGAKs="], - ["Gv////8ADgAAABQA=", bjson.READ_OBJ_REFERENCE], + ["G/////8QAAAAAARg"], + ["G//////m5uaCLQ=="], + ["G/////8AEQATBgYGBgYGBgYGBgb/////EAARAC8R/78vEf+/"], + ["G/////8ACH8ACv////9//////////////////////////////9//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAA+fn5+fn5+fn5+fn5AAAAAAAGAKs="], + ["G/////8ADgAAABQA=", bjson.READ_OBJ_REFERENCE], ]; for (var [input, flags] of corpus) { var buf = base64decode(input); diff --git a/deps/quickjs/tests/test_builtin.js b/deps/quickjs/tests/test_builtin.js index 02acc17..fb38263 100644 --- a/deps/quickjs/tests/test_builtin.js +++ b/deps/quickjs/tests/test_builtin.js @@ -646,8 +646,11 @@ function test_typed_array() }; b = a.slice(); assert(a.buffer, b.buffer); - assert(a.toString(), "0,0,0,255"); - assert(b.toString(), "0,0,255,255"); + // the copy is byte by byte in increasing order, so bytes already + // copied are read back as source values when the target overlaps + // the source ahead of it + assert(a.toString(), "0,0,0,0"); + assert(b.toString(), "0,0,0,0"); const TypedArray = class extends Object.getPrototypeOf(Uint8Array) {}; let caught = false; @@ -705,9 +708,9 @@ function test_typed_array() assert(ta[0], 0); Object.defineProperty(ta, "0", {value: 1337}); assert(ta[0], 0); - assert(desc.writable, false); + assert(desc.writable, true); assert(desc.enumerable, true); - assert(desc.configurable, false); + assert(desc.configurable, true); } function test_json() @@ -733,6 +736,18 @@ function test_json() 3 ] ]`); + + /* the space argument can be a rope, which is not a JSString: it must be + linearized before its characters are read, else the gap is filled with + the raw bytes of the rope's internal JSValues */ + var rope = "a".repeat(600) + "b".repeat(600); + var expected = '{\n' + "a".repeat(10) + '"x": 1\n}'; + assert(JSON.stringify({x:1}, null, rope), expected); + assert(JSON.stringify({x:1}, null, new String(rope)), expected); + /* wide char rope */ + var wide = "é".repeat(600) + "è".repeat(600); + assert(JSON.stringify({x:1}, null, wide), + '{\n' + "é".repeat(10) + '"x": 1\n}'); } function test_date() @@ -907,7 +922,7 @@ function test_regexp() } catch (_ex) { ex = _ex; } - assert(ex?.message, "invalid class range"); + assert(ex?.message, "invalid character in class in regular expression"); eval("/[\\-]/"); eval("/[\\-]/u"); @@ -1194,6 +1209,31 @@ function test_proxy_iter() assert(a[1], "y"); } +function test_proxy_own_keys_huge_length() +{ + for (const length of [0x20000000, 0x40000000, 0xfffffffe, 0xffffffff]) { + const p = new Proxy({}, { ownKeys() { return {length}; } }); + /* index 0 is undefined, so this must fail on the very first entry */ + assertThrows(TypeError, function() { Object.keys(p); }); + assertThrows(TypeError, function() { Object.getOwnPropertyNames(p); }); + } + + const keys = ["a", "b", Symbol("c")]; + const p = new Proxy({}, { + ownKeys() { + return new Proxy({length: 0xffffffff}, { + get(t, k) { + if (k === "length") return 0xffffffff; + const i = Number(k); + if (i < keys.length) return keys[i]; + throw new RangeError("stop at " + i); + }, + }); + }, + }); + assertThrows(RangeError, function() { Object.getOwnPropertyNames(p); }); +} + /* CVE-2023-31922 */ function test_proxy_is_array() { @@ -1303,6 +1343,7 @@ test_set(); test_weak_set(); test_generator(); test_proxy_iter(); +test_proxy_own_keys_huge_length(); test_proxy_is_array(); test_finalization_registry(); test_exception_source_pos(); diff --git a/deps/quickjs/tests/test_cyclic_import.js b/deps/quickjs/tests/test_cyclic_import.js deleted file mode 100644 index bf51d9b..0000000 --- a/deps/quickjs/tests/test_cyclic_import.js +++ /dev/null @@ -1,12 +0,0 @@ -/*--- -negative: - phase: resolution - type: SyntaxError ----*/ -// FIXME(bnoordhuis) shouldn't throw SyntaxError but that's still better -// than segfaulting, see https://github.com/quickjs-ng/quickjs/issues/567 -import {assert} from "./assert.js" -import {f} from "./fixture_cyclic_import.js" -export {f} -export function g(x) { return x + 1 } -assert(f(1), 4) diff --git a/deps/quickjs/tests/typedarray-lastindexof-shrink.js b/deps/quickjs/tests/typedarray-lastindexof-shrink.js new file mode 100644 index 0000000..f0c0e26 --- /dev/null +++ b/deps/quickjs/tests/typedarray-lastindexof-shrink.js @@ -0,0 +1,73 @@ +import { assert } from "./assert.js"; + +/* %TypedArray%.prototype.lastIndexOf: the length is read before the + fromIndex argument is coerced. When the coercion shrinks a resizable + buffer the downward scan skips the vanished indices and continues in + the still valid range instead of returning -1. */ + +{ + const rab = new ArrayBuffer(32, { maxByteLength: 32 }); + const ta = new Float64Array(rab); + + const cases = [ + [-1, 2], + [-2, 2], + [-3, 1], + [-4, 0], + [-5, -1], + ]; + + for (const [index, expected] of cases) { + rab.resize(32); + ta.fill(123); + const evil = { + valueOf() { + rab.resize(24); + return index; + } + }; + assert(ta.lastIndexOf(123, evil), expected); + } +} + +/* positive fromIndex beyond the shrunk length clamps to the new end */ +{ + const rab = new ArrayBuffer(32, { maxByteLength: 32 }); + const ta = new Int32Array(rab); + ta.fill(7); + const evil = { + valueOf() { + rab.resize(8); + return 6; + } + }; + assert(ta.lastIndexOf(7, evil), 1); +} + +/* a fixed-length view that goes out of bounds still returns -1 */ +{ + const rab = new ArrayBuffer(16, { maxByteLength: 16 }); + const ta = new Int32Array(rab, 0, 4); + ta.fill(5); + const evil = { + valueOf() { + rab.resize(8); + return 3; + } + }; + assert(ta.lastIndexOf(5, evil), -1); +} + +/* shrink to zero returns -1 */ +{ + const rab = new ArrayBuffer(16, { maxByteLength: 16 }); + const ta = new Int32Array(rab); + ta.fill(9); + const evil = { + valueOf() { + rab.resize(0); + return 3; + } + }; + assert(ta.lastIndexOf(9, evil), -1); +} diff --git a/deps/quickjs/tests/typedarray-set-invalid-index.js b/deps/quickjs/tests/typedarray-set-invalid-index.js new file mode 100644 index 0000000..e241ceb --- /dev/null +++ b/deps/quickjs/tests/typedarray-set-invalid-index.js @@ -0,0 +1,50 @@ +import { assert } from "./assert.js"; + +/* TypedArray [[Set]] (10.4.5.5): an out-of-bounds or non-canonical integer + index only coerces the value when the receiver is the typed array itself. + With any other receiver the invalid index is dropped (step ii) without + evaluating the value. */ + +/* receiver is a primitive: value must not be coerced */ +{ + let coerced = 0; + const value = { valueOf() { coerced++; return 1; } }; + const ta = new Int32Array(10); + assert(Reflect.set(ta, 100, value, "not an object"), true); + assert(coerced, 0); +} + +/* receiver is a different object: value must not be coerced */ +{ + let coerced = 0; + const value = { valueOf() { coerced++; return 1; } }; + const ta = new Int32Array(10); + assert(Reflect.set(ta, 100, value, {}), true); + assert(coerced, 0); +} + +/* BigInt typed array, different receiver: value must not be coerced */ +{ + let coerced = 0; + const value = { valueOf() { coerced++; return 1n; } }; + const ta = new BigInt64Array(10); + assert(Reflect.set(ta, 100, value, {}), true); + assert(coerced, 0); +} + +/* receiver is the typed array itself: value IS coerced (TypedArraySetElement), + even for an out-of-bounds index */ +{ + let coerced = 0; + const value = { valueOf() { coerced++; return 1; } }; + const ta = new Int32Array(10); + assert(Reflect.set(ta, 100, value, ta), true); + assert(coerced, 1); +} + +/* an in-bounds index with the typed array as receiver still stores */ +{ + const ta = new Int32Array(4); + assert(Reflect.set(ta, 2, 42, ta), true); + assert(ta[2], 42); +} diff --git a/deps/quickjs/tests/typedarray-slice-overlap.js b/deps/quickjs/tests/typedarray-slice-overlap.js new file mode 100644 index 0000000..c7943c7 --- /dev/null +++ b/deps/quickjs/tests/typedarray-slice-overlap.js @@ -0,0 +1,48 @@ +import { assert } from "./assert.js"; + +/* %TypedArray%.prototype.slice copies byte by byte in increasing order + (step 14.g). This is observable when the species constructor returns a + view over the same buffer that overlaps the source ahead of it: already + copied elements are read back as source values. */ + +function check(TA) { + const ta = new TA([10, 20, 30, 40, 50, 60]); + ta.constructor = { + [Symbol.species]: function() { + return new TA(ta.buffer, 2 * TA.BYTES_PER_ELEMENT); + } + }; + const result = ta.slice(1, 4); + assert(result.length, 4); + assert(result[0], 20); + assert(result[1], 20); + assert(result[2], 20); + assert(result[3], 60); +} + +check(Float64Array); +check(Int32Array); +check(Uint8Array); + +/* target view behind the source: plain move semantics are unaffected */ +{ + const ta = new Int32Array([10, 20, 30, 40, 50, 60]); + ta.constructor = { + [Symbol.species]: function() { + return new Int32Array(ta.buffer, 0); + } + }; + const result = ta.slice(2, 5); + assert(result[0], 30); + assert(result[1], 40); + assert(result[2], 50); +} + +/* distinct buffers keep working */ +{ + const ta = new Int32Array([1, 2, 3, 4]); + const result = ta.slice(1, 3); + assert(result.length, 2); + assert(result[0], 2); + assert(result[1], 3); +} diff --git a/deps/quickjs/tests/typedarray-subarray-species.js b/deps/quickjs/tests/typedarray-subarray-species.js new file mode 100644 index 0000000..3407f07 --- /dev/null +++ b/deps/quickjs/tests/typedarray-subarray-species.js @@ -0,0 +1,82 @@ +import { assert } from "./assert.js"; + +/* %TypedArray%.prototype.subarray: the species constructor arguments are + computed from the [[ByteOffset]] slot and must not be revalidated against + the buffer, and a length-tracking result gets no length argument. */ + +/* detaching the buffer while coercing 'end' must not throw: the species + constructor still receives the original byte offset */ +{ + const ab = new ArrayBuffer(16); + const ta = new Float64Array(ab, 8, 1); + const marker = new Float64Array(0); + let args; + ta.constructor = { + [Symbol.species]: function(...a) { + args = a; + return marker; + } + }; + const end = { + valueOf() { + ab.transfer(); + return 0; + } + }; + assert(ta.subarray(1, end), marker); + assert(args.length, 3); + assert(args[0], ab); + assert(args[1], 16); + assert(args[2], 0); +} + +/* a length-tracking view with undefined 'end' calls the species constructor + with two arguments so the result is length-tracking too */ +{ + const rab = new ArrayBuffer(24, { maxByteLength: 32 }); + const ta = new Float64Array(rab); + let args; + ta.constructor = { + [Symbol.species]: function(...a) { + args = a; + return new Float64Array(a[0], a[1]); + } + }; + const res = ta.subarray(1); + assert(args.length, 2); + assert(args[0], rab); + assert(args[1], 8); + rab.resize(32); + assert(res.length, 3); +} + +/* with an explicit 'end' the length argument is passed */ +{ + const rab = new ArrayBuffer(24, { maxByteLength: 32 }); + const ta = new Float64Array(rab); + let args; + ta.constructor = { + [Symbol.species]: function(...a) { + args = a; + return new Float64Array(a[0], a[1], a[2]); + } + }; + ta.subarray(1, 3); + assert(args.length, 3); + assert(args[2], 2); +} + +/* without a species constructor, subarray of a detached typed array still + throws a TypeError from the typed array constructor */ +{ + const ab = new ArrayBuffer(16); + const ta = new Float64Array(ab, 8); + ab.transfer(); + let err; + try { + ta.subarray(0); + } catch (e) { + err = e; + } + assert(err instanceof TypeError, true); +} diff --git a/deps/quickjs/unicode_download.sh b/deps/quickjs/unicode_download.sh index cc31b2a..6ab607e 100755 --- a/deps/quickjs/unicode_download.sh +++ b/deps/quickjs/unicode_download.sh @@ -1,7 +1,9 @@ #!/bin/sh set -e -url="https://www.unicode.org/Public/17.0.0/ucd" +baseurl="https://www.unicode.org" +license_url="${baseurl}/license.txt" +url="${baseurl}/Public/17.0.0/ucd" emoji_url="${url}/emoji/emoji-data.txt" files="CaseFolding.txt DerivedNormalizationProps.txt PropList.txt \ @@ -17,3 +19,4 @@ for f in $files; do done wget $emoji_url -O unicode/emoji-data.txt +wget $license_url -O unicode/license.txt diff --git a/deps/quickjs/unicode_gen.c b/deps/quickjs/unicode_gen.c index cb46fbc..edf13d3 100644 --- a/deps/quickjs/unicode_gen.c +++ b/deps/quickjs/unicode_gen.c @@ -3081,8 +3081,19 @@ int main(int argc, char **argv) #endif } else { - FILE *fo = fopen(outfilename, "wb"); + FILE *fo; + char license[8192] = {0}; + snprintf(filename, sizeof(filename), "%s/license.txt", unicode_db_path); + fo = fopen(filename, "r"); + if (!fo) { + perror(filename); + exit(1); + } + fread(license, 1, sizeof(license)-1, fo); + fclose(fo); + + fo = fopen(outfilename, "wb"); if (!fo) { perror(outfilename); exit(1); @@ -3091,8 +3102,10 @@ int main(int argc, char **argv) "/* Compressed unicode tables */\n" "/* Automatically generated file - do not edit */\n" "\n" + "/*\n%s*/\n" + "\n" "#include \n" - "\n"); + "\n", license); dump_case_conv_table(fo); compute_internal_props(); build_flags_tables(fo);