Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
05545bd
chore: update quickjs-ng to latest
ammarahm-ed Jul 1, 2026
5055b2d
rewrite v8 host objects implementation
ammarahm-ed Jul 1, 2026
4f31c2c
feat: runtime optimize
ammarahm-ed Jul 1, 2026
99f96bd
update helpers
ammarahm-ed Jul 1, 2026
84ba313
chore: update properties
ammarahm-ed Jul 1, 2026
2053296
mobile: disable useHostObjects
ammarahm-ed Jul 1, 2026
ec7051d
auto enable host objects on build
ammarahm-ed Jul 1, 2026
ef20f1d
fix(URL): allow undefined 2nd args
ammarahm-ed Jul 1, 2026
b46586b
fix: `exit(0)` causes ANR due to destroyed mutex
ammarahm-ed Jul 3, 2026
6f01665
fix: gradle error when compileSdk or targetSdk is provided
ammarahm-ed Jul 3, 2026
ca93e66
feat: support 16 KB page sizes
ammarahm-ed Jul 3, 2026
8109ff9
feat: Ada 3.3.0 + URLPattern API
ammarahm-ed Jul 3, 2026
cc580c2
feat: Java 21 source compatibility
ammarahm-ed Jul 3, 2026
ebf167e
feat: update libzip to 1.11.4
ammarahm-ed Jul 3, 2026
3bfb07a
feat: kotlin 2.2.x support
ammarahm-ed Jul 3, 2026
3459c6e
feat: queueMicrotask support
ammarahm-ed Jul 3, 2026
de4e794
fix: prevent crash when jweak points to null
ammarahm-ed Jul 3, 2026
65c671d
fix: improve reThrowToJava exception handling
ammarahm-ed Jul 3, 2026
e5c679a
fix: proguard builds
ammarahm-ed Jul 3, 2026
c9920e4
fix: URLSearchParams.forEach() duplicate-key handling
ammarahm-ed Jul 3, 2026
252c3e0
feat: log uncaught native exceptions before aborting
ammarahm-ed Jul 4, 2026
de9c2bc
fix: multithreadedJS should use concurrent java maps
ammarahm-ed Jul 4, 2026
7df02d6
docs(migration): defer @CriticalNative/@FastNative pair (#1921 + #1942)
ammarahm-ed Jul 4, 2026
d008377
fix: select correct runtime when calling from different threads
ammarahm-ed Jul 4, 2026
9db6492
fix(jsparser): sourcemap off, report empty webpack output, skip non-I…
ammarahm-ed Jul 4, 2026
a175913
fix: circular dependencies when using proguard
ammarahm-ed Jul 4, 2026
a8c0d72
fix: ensure dex cache directory exists before proxy generation
ammarahm-ed Jul 4, 2026
5987fa7
docs(migration): defer DexFactory parent-classloader pair (#1951 + #1…
ammarahm-ed Jul 4, 2026
2e0ad39
docs(migration): triage remaining commits to HEAD (ESM deps, workers,…
ammarahm-ed Jul 4, 2026
fda1c2f
feat: @CriticalNative/@FastNative for hot JNI methods with safe regis…
ammarahm-ed Jul 4, 2026
127191e
fix(DexFactory): inject generated proxies into the app class loader f…
ammarahm-ed Jul 4, 2026
9664c31
docs(migration): mark @CriticalNative + DexFactory pairs as ported (2…
ammarahm-ed Jul 4, 2026
af90398
fix(timers): order timers with the Java MessageQueue instead of ALoop…
ammarahm-ed Jul 4, 2026
45b84d4
fix: URLSearchParams construction and iteration spec compliance
ammarahm-ed Jul 4, 2026
5700515
feat(workers): move worker threading and messaging to C++
ammarahm-ed Jul 4, 2026
9721bb5
fix: build all engines with C++20 (ada 3.3.0 requires it)
ammarahm-ed Jul 4, 2026
f8bc822
feat(inspector): serve source maps to DevTools + attach DevTools to W…
ammarahm-ed Jul 4, 2026
5038e14
fix: add missing try/catch handlers
ammarahm-ed Jul 5, 2026
867e4a7
fix: crash in finalizers and failing tests
ammarahm-ed Jul 5, 2026
7eb4388
fix(workers): propagate both errors when a worker onerror handler throws
ammarahm-ed Jul 5, 2026
3fc4026
fix: do not inject duplicate dex if class is already present in class…
ammarahm-ed Jul 5, 2026
0fbb9c3
fix(metadata): resolve companion objects with nested classes
ammarahm-ed Jul 5, 2026
4d93438
fix: finalizer callback arguments error
ammarahm-ed Jul 6, 2026
0c3111b
feat: update to hermes latest
ammarahm-ed Jul 6, 2026
fb87bbc
chore: bump version to 9.0.0
ammarahm-ed Jul 6, 2026
3330c49
chore: update js_native_api headers
ammarahm-ed Jul 6, 2026
f8e92ab
feat(hermes): host objects
ammarahm-ed Jul 6, 2026
3cd93d0
fix napi_post_finalizer args
ammarahm-ed Jul 8, 2026
22496e2
feat(jsc): Update to newer version of JSC and add support for host ob…
ammarahm-ed Jul 8, 2026
2f7790e
feat(primjs): update to the latest version of primjs and rewrite napi…
ammarahm-ed Jul 8, 2026
30203a4
chore: misc updates to runtime
ammarahm-ed Jul 8, 2026
f921827
fix ts_helpers to use globalThis
ammarahm-ed Jul 8, 2026
5122d34
fix abis in test-app when jsc engine is enabled
ammarahm-ed Jul 8, 2026
c409c34
show warning when using JSC engine
ammarahm-ed Jul 8, 2026
5cc644e
Update quickjs to latest
ammarahm-ed Jul 9, 2026
69640d8
chore: update lib versions
ammarahm-ed Jul 9, 2026
528c72a
feat: update js_parser to support .mjs files
ammarahm-ed Jul 9, 2026
55b886a
fix(hermes): microtask handling
ammarahm-ed Jul 10, 2026
7a5c9d1
feat(jsc): unhandled promise rejection tracker
ammarahm-ed Jul 10, 2026
54c5bb5
fix(jsc): allow property keys to be symbol or string
ammarahm-ed Jul 10, 2026
441f2aa
fix: initialize void pointers with nullptr
ammarahm-ed Jul 10, 2026
19db909
fix(quickjs): fixed every public napi_* function that ignored a napi_…
ammarahm-ed Jul 10, 2026
317f5e9
feat: add jsEnter state to quickjs/primjs jsr
ammarahm-ed Jul 10, 2026
3c3012c
fix: do not call notifyGCFast as it can block
ammarahm-ed Jul 10, 2026
0901dc0
feat: improve error handling in the runtime
ammarahm-ed Jul 10, 2026
ae10592
chore: cleanup
ammarahm-ed Jul 11, 2026
621ab19
chore: cleanup
ammarahm-ed Jul 11, 2026
b61ca02
feat: bytecode and code_cache support
ammarahm-ed Jul 14, 2026
b06aa2b
ci: fix
ammarahm-ed Jul 14, 2026
d4549ba
ci: fix build
ammarahm-ed Jul 14, 2026
0fac2df
ci: update
ammarahm-ed Jul 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
327 changes: 327 additions & 0 deletions .github/workflows/bytecode-compilers.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,327 @@
name: Build bytecode compilers

# Builds the per-host bytecode compiler CLIs for every engine that supports
# ahead-of-time bytecode, by cloning each engine's UPSTREAM repo (not the
# android-runtime vendored sources) and building the CLI there.
#
# Output: one artifact per (engine, host), named `bytecode-compiler-<engine>-<host>`,
# each containing `<engine>/<host>/<binary>` so the downloads merge straight into
# tools/bytecode-compiler/bin/.
#
# NOTE ON COMPATIBILITY: the produced bytecode must be loadable by the engine
# library the runtime ships. Hermes/PrimJS runtimes link prebuilt .so's and
# QuickJS/QuickJS-NG compile from vendored source, so the refs below must be kept
# in step with what the runtime actually bundles. Pin these to exact commits once
# validated instead of moving branches.
on:
workflow_dispatch:
inputs:
hermes_ref:
description: "facebook/hermes ref"
default: "10a40b5f1de81d007cba6afe567c4ba7a0b45f5d"
quickjs_ref:
# MUST match the quickjs submodule pin (BC_VERSION must agree with the
# runtime). See .gitmodules / scripts/vendor-engines-as-submodules.sh.
description: "bellard/quickjs ref (match the submodule pin)"
default: "04be246001599f5995fa2f2d8c91a0f198d3f34c"
quickjs_ng_ref:
# MUST match the quickjs_ng submodule pin (BC_VERSION must agree with the
# runtime, or JS_ReadObject rejects the blob). See .gitmodules /
# scripts/vendor-engines-as-submodules.sh.
description: "quickjs-ng/quickjs ref (match the submodule pin)"
default: "d950d55e950dd7994a96c669c31efa967b8b79f3"
primjs_ref:
description: "lynx-family/primjs ref"
default: "9c1fe150179b86f0ae5c6fbe670af7d76eca9df6"

env:
HERMES_REPO: https://github.com/facebook/hermes
QUICKJS_REPO: https://github.com/bellard/quickjs
QUICKJS_NG_REPO: https://github.com/quickjs-ng/quickjs
PRIMJS_REPO: https://github.com/lynx-family/primjs

jobs:
# ---------------------------------------------------------------------------
# Hermes — `hermesc` already emits a loadable HBC blob; no shim needed.
# ---------------------------------------------------------------------------
hermes:
name: hermes (${{ matrix.host }})
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- { host: linux-x64, runner: ubuntu-24.04 }
- { host: linux-arm64, runner: ubuntu-24.04-arm }
- { host: darwin-x64, runner: macos-13 }
- { host: darwin-arm64, runner: macos-14 }
- { host: win32-x64, runner: windows-2022 }
# win32-arm64 dropped: hermes' Boost.Context ARM64 assembler + CMake's
# ASM_ARMASM linker support fail on windows-11-arm. The win32-x64
# hermesc runs on ARM Windows via x64 emulation (HBC output is portable).
steps:
- name: Install toolchain (Linux)
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y cmake ninja-build build-essential python3
- name: Install toolchain (macOS)
if: runner.os == 'macOS'
run: brew install cmake ninja
- name: Install toolchain (Windows)
if: runner.os == 'Windows'
run: choco install ninja -y

- name: Clone Hermes
shell: bash
# Fetch by ref so an exact commit SHA works (git clone --branch only
# accepts branch/tag names). GitHub allows fetching arbitrary SHAs.
run: |
set -euxo pipefail
ref="${{ github.event.inputs.hermes_ref || 'master' }}"
git init hermes
git -C hermes remote add origin "$HERMES_REPO"
git -C hermes fetch --depth 1 origin "$ref"
git -C hermes -c advice.detachedHead=false checkout FETCH_HEAD

- name: Build hermesc (Unix)
if: runner.os != 'Windows'
shell: bash
run: |
set -euxo pipefail
cmake -S hermes -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DHERMES_BUILD_APPLE_FRAMEWORK=OFF
cmake --build build --target hermesc

- name: Build hermesc (Windows)
if: runner.os == 'Windows'
shell: bash
run: |
set -euxo pipefail
# Use the default (Visual Studio) generator; Ninja+MSVC also works if the
# VS dev environment is on PATH.
cmake -S hermes -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --target hermesc --config Release

- name: Stage binary
shell: bash
run: |
set -euxo pipefail
mkdir -p "out/hermes/${{ matrix.host }}"
bin="$(find build -type f \( -name hermesc -o -name hermesc.exe \) | head -n1)"
test -n "$bin"
cp "$bin" "out/hermes/${{ matrix.host }}/"

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {}
- uses: actions/upload-artifact@v4
with:
name: bytecode-compiler-hermes-${{ matrix.host }}
path: out/hermes/${{ matrix.host }}
if-no-files-found: error

# ---------------------------------------------------------------------------
# QuickJS (bellard) — build via its own Makefile (libquickjs.a, which injects
# -D_GNU_SOURCE -DCONFIG_VERSION), then link our blob-emitting shim.
# win32-x64 is CROSS-compiled on Linux via bellard's CONFIG_WIN32 (mingw-w64);
# win32-arm64 is not possible (mingw-w64 targets x86 only).
# ---------------------------------------------------------------------------
quickjs:
name: quickjs (${{ matrix.host }})
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- { host: linux-x64, runner: ubuntu-24.04 }
- { host: linux-arm64, runner: ubuntu-24.04-arm }
- { host: darwin-x64, runner: macos-13 }
- { host: darwin-arm64, runner: macos-14 }
- { host: win32-x64, runner: ubuntu-24.04 } # mingw cross-compile
steps:
- uses: actions/checkout@v4
- name: Install toolchain (Linux)
if: runner.os == 'Linux'
run: |
set -euxo pipefail
sudo apt-get update
sudo apt-get install -y build-essential
# mingw-w64 for the win32-x64 cross build.
if [ "${{ matrix.host }}" = "win32-x64" ]; then sudo apt-get install -y mingw-w64; fi
# macOS: make + clang ship with the Xcode command-line tools.

- name: Clone QuickJS
shell: bash
run: |
set -euxo pipefail
ref="${{ github.event.inputs.quickjs_ref || 'master' }}"
git init quickjs
git -C quickjs remote add origin "$QUICKJS_REPO"
git -C quickjs fetch --depth 1 origin "$ref"
git -C quickjs -c advice.detachedHead=false checkout FETCH_HEAD

- name: Build lib + shim
shell: bash
env:
SHIM: ${{ github.workspace }}/tools/bytecode-compiler/native/qjs-compile.c
run: |
set -euxo pipefail

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}
cd quickjs
jobs="$(getconf _NPROCESSORS_ONLN)"
out="../out/quickjs/${{ matrix.host }}"; mkdir -p "$out"
if [ "${{ matrix.host }}" = "win32-x64" ]; then
# CONFIG_WIN32=y selects the x86_64-w64-mingw32- cross toolchain.
make -j"$jobs" CONFIG_WIN32=y libquickjs.a
x86_64-w64-mingw32-gcc -O2 -DNSBC_MAGIC='"NSBCQJS"' -I. \
-o "$out/nsbc-quickjs.exe" "$SHIM" libquickjs.a -lm
# Cross-built Windows binary — not runnable on the Linux host.
else
# Use bellard's own Makefile so CONFIG_VERSION / _GNU_SOURCE and the
# correct source set come from upstream.
make -j"$jobs" libquickjs.a
cc -O2 -DNSBC_MAGIC='"NSBCQJS"' -I. -o "$out/nsbc-quickjs" "$SHIM" libquickjs.a -lm
"$out/nsbc-quickjs" || true # usage line (exit 2) proves it links & runs
fi

- uses: actions/upload-artifact@v4
with:
name: bytecode-compiler-quickjs-${{ matrix.host }}
path: out/quickjs/${{ matrix.host }}
if-no-files-found: error

# ---------------------------------------------------------------------------
# QuickJS-NG — CMake build of libqjs, then our shim (same JS_* API).
# ---------------------------------------------------------------------------
quickjs-ng:
name: quickjs-ng (${{ matrix.host }})
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- { host: linux-x64, runner: ubuntu-24.04 }
- { host: linux-arm64, runner: ubuntu-24.04-arm }
- { host: darwin-x64, runner: macos-13 }
- { host: darwin-arm64, runner: macos-14 }
- { host: win32-x64, runner: windows-2022 }
- { host: win32-arm64, runner: windows-11-arm }
steps:
- uses: actions/checkout@v4
- name: Install toolchain (Linux)
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y cmake ninja-build build-essential
- name: Install toolchain (macOS)
if: runner.os == 'macOS'
run: brew install cmake ninja
- name: Install toolchain (Windows)
if: runner.os == 'Windows'
run: choco install ninja llvm -y

- name: Clone QuickJS-NG
shell: bash
run: |
set -euxo pipefail
ref="${{ github.event.inputs.quickjs_ng_ref || 'master' }}"
git init quickjs-ng
git -C quickjs-ng remote add origin "$QUICKJS_NG_REPO"

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}
git -C quickjs-ng fetch --depth 1 origin "$ref"
git -C quickjs-ng -c advice.detachedHead=false checkout FETCH_HEAD

- name: Build lib + shim
shell: bash
env:
SHIM: ${{ github.workspace }}/tools/bytecode-compiler/native/qjs-compile.c
run: |
set -euxo pipefail
# Build only the static engine lib target ('qjs' -> libqjs.a / qjs.lib);
# skip the CLI/test executables.
cmake -S quickjs-ng -B quickjs-ng/build -DCMAKE_BUILD_TYPE=Release
cmake --build quickjs-ng/build --config Release --target qjs
lib="$(find quickjs-ng/build -type f \( -name 'libqjs.a' -o -name 'qjs.lib' \) | head -n1)"
test -n "$lib"
# Windows has no libm (math is in the CRT); only pass -lm off-Windows.
CC="cc"; LIBM="-lm"
if [ "${{ runner.os }}" = "Windows" ]; then CC="clang"; LIBM=""; fi
out="out/quickjs-ng/${{ matrix.host }}"; mkdir -p "$out"
bin="$out/nsbc-quickjs-ng"; [ "${{ runner.os }}" = "Windows" ] && bin="$bin.exe"
$CC -O2 -DNSBC_MAGIC='"NSBCNGS"' -I quickjs-ng -o "$bin" "$SHIM" "$lib" $LIBM
"$bin" || true

- uses: actions/upload-artifact@v4
with:
name: bytecode-compiler-quickjs-ng-${{ matrix.host }}
path: out/quickjs-ng/${{ matrix.host }}
if-no-files-found: error

# ---------------------------------------------------------------------------
# PrimJS — build via its own toolchain: `hab sync` fetches gn + ninja + a
# bundled clang + sysroot, then GN/ninja build the engine. We add our LEPUS_*
# shim as a sibling GN executable (reusing the qjs-cli engine deps).
#
# Unix only, and NOT linux-arm64: PrimJS's envsetup.sh aborts on Windows, and
# its DEPS only provides a linux sysroot for x86_64. So: linux-x64 + macOS.
#
# NOTE: this is the first automated PrimJS build; `hab sync` pulls a large
# toolchain and the exact gn/ninja target may need tweaking on the first run.
# ---------------------------------------------------------------------------
primjs:
name: primjs (${{ matrix.host }})
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- { host: linux-x64, runner: ubuntu-24.04 }
- { host: darwin-x64, runner: macos-13 }
- { host: darwin-arm64, runner: macos-14 }
steps:
- uses: actions/checkout@v4
- name: Install prerequisites (Linux)
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y python3 curl

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}
- name: Clone PrimJS
shell: bash
run: |
set -euxo pipefail
ref="${{ github.event.inputs.primjs_ref || 'develop' }}"
git init primjs
git -C primjs remote add origin "$PRIMJS_REPO"
git -C primjs fetch --depth 1 origin "$ref"
git -C primjs -c advice.detachedHead=false checkout FETCH_HEAD

- name: Add shim as a GN target
shell: bash
env:
SHIM: ${{ github.workspace }}/tools/bytecode-compiler/native/primjs-compile.c
run: |
set -euxo pipefail
# Build as C++ (.cc) to match the working qjs-cli target; the LEPUS_*
# API is extern "C", so linkage is fine either way.
cp "$SHIM" primjs/tools/qjs-cli/nsbc-primjs.cc
# A standalone executable that links the same engine as qjs-cli.
cat >> primjs/tools/qjs-cli/BUILD.gn <<'GN'

executable("nsbc-primjs") {
cflags = [ "-Wno-c99-designator" ]
sources = [ "nsbc-primjs.cc" ]
include_dirs = [ "//include" ]
deps = [ ":qjs_wasm_binding" ]
configs += [ ":wasm_internal_config" ]
}
GN

- name: Build (hab sync + gn + ninja)
shell: bash
working-directory: primjs
run: |
set -euxo pipefail
# hab (in-repo) fetches gn, ninja, the bundled clang toolchain + sysroot.
source tools/envsetup.sh
hab sync .
gn gen out/Default --args="is_debug=false"
ninja -C out/Default nsbc-primjs
out="../out/primjs/${{ matrix.host }}"; mkdir -p "$out"
cp out/Default/nsbc-primjs "$out/nsbc-primjs"
"$out/nsbc-primjs" || true # usage line (exit 2) proves it links & runs

- uses: actions/upload-artifact@v4
with:
name: bytecode-compiler-primjs-${{ matrix.host }}
path: out/primjs/${{ matrix.host }}
if-no-files-found: error
7 changes: 3 additions & 4 deletions .github/workflows/npm_trusted_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ jobs:
set -euo pipefail
case "$ENGINE" in
all)
echo 'engines=["v8","hermes","jsc","quickjs","quickjs-ng","shermes","primjs"]' >> "$GITHUB_OUTPUT"
echo 'engines=["v8","hermes","jsc","quickjs","quickjs-ng","primjs"]' >> "$GITHUB_OUTPUT"
;;
v8|hermes|jsc|quickjs|quickjs-ng|shermes|primjs)
printf 'engines=["%s"]\n' "$ENGINE" >> "$GITHUB_OUTPUT"
Expand Down Expand Up @@ -123,6 +123,8 @@ jobs:
distribution: "temurin"
- name: Install root dependencies
run: npm install
- name: Set up engine submodules, patches, and jsparser
run: npm run setup
- name: Resolve engine target
id: target
shell: bash
Expand Down Expand Up @@ -200,9 +202,6 @@ jobs:
echo "NPM_VERSION=$NPM_VERSION" >> "$GITHUB_OUTPUT"
echo "NPM_TAG=$NPM_TAG" >> "$GITHUB_OUTPUT"
echo "Resolved $PACKAGE_NAME@$NPM_VERSION (tag: $NPM_TAG)"
- name: Install jsparser dependencies
working-directory: ${{ env.JS_PARSER_DIR }}
run: npm ci
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build (-Pengine=${{ steps.target.outputs.GRADLE_ENGINE }})
Expand Down
8 changes: 8 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[submodule "test-app/runtime/src/main/cpp/napi/quickjs/source"]
path = test-app/runtime/src/main/cpp/napi/quickjs/source
url = https://github.com/bellard/quickjs
ignore = dirty
[submodule "test-app/runtime/src/main/cpp/napi/quickjs/source_ng"]
path = test-app/runtime/src/main/cpp/napi/quickjs/source_ng
url = https://github.com/quickjs-ng/quickjs
ignore = dirty
Loading
Loading