Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
736f57c
feat: add nativescript-wamr-test app for WAMR plugin testing
listepo Aug 2, 2026
2da903b
test(wamr-test): add test cases for every WAMR execution mode
listepo Aug 2, 2026
e8e0386
ci: add wamr-test-ios and wamr-test-android jobs
listepo Aug 2, 2026
202b11b
fix(ci): fix android test jobs to handle both plugins and missing WAM…
listepo Aug 3, 2026
f8a4782
refactor(wasm-test): make fixture-suite runtime-agnostic, support bot…
listepo Aug 3, 2026
f77bf84
revert: remove separate nativescript-wamr-test app
listepo Aug 3, 2026
da464c8
feat(wamr): add download-wamr.mjs script to fetch WAMR C sources
listepo Aug 3, 2026
9d98994
feat(wamr): add Rust bindings crate and vendor WAMR C sources
listepo Aug 3, 2026
6a2c30e
feat(nativescript-wamr): generate wamr-swift Swift Package from Rust …
listepo Aug 3, 2026
fcea5ac
feat(nativescript-wamr): generate wamr-kotlin package from Rust via U…
listepo Aug 3, 2026
6bec957
docs(nativescript-wamr): add ns typings requirement to AGENTS.md and …
listepo Aug 3, 2026
a47407d
docs(nativescript-wamr): clarify ns typings EPERM is macOS sandbox, n…
listepo Aug 3, 2026
53c5cf2
docs(nativescript-wamr): fix ns typings instructions — run from test …
listepo Aug 3, 2026
ced6c46
test(nativescript-wamr): add vitest mirror of device-level mocha specs
listepo Aug 3, 2026
2904008
feat: replace JavaCPP with cargo-ndk + Rust JNI for Android native bu…
listepo Aug 3, 2026
3b9e0ee
fix: guard from_raw_parts against null pointer in host trampolines
listepo Aug 3, 2026
b75ffa6
chore: rename org to cross-code namespace
listepo Aug 3, 2026
77eaddf
fix: replace stale @org references in root package-lock.json and README
listepo Aug 3, 2026
211602c
chore: normalize .actrc line endings and image reference
listepo Aug 3, 2026
6a5a053
fix: remove leading spaces from .actrc -P flag, normalize to LF
listepo Aug 3, 2026
ba4aa31
feat: add wasm3-ffi, wasm3-kotlin, and wasm3-swift UniFFI bindings
listepo Aug 3, 2026
c9e5b84
fix: wasm3-ffi store runtime in ModuleInstance, implement stubs
listepo Aug 3, 2026
07e4f4e
fix: remove unused runtime field from Wasm3Function struct
listepo Aug 3, 2026
812d7da
fix: add nativescript field to wamr package.json, fix Package.swift e…
listepo Aug 3, 2026
b50b5e0
fix: rewrite nsc_wamr_shim for current WAMR public API
listepo Aug 3, 2026
fa9ff53
feat: rewrite C shims in pure Rust
listepo Aug 3, 2026
26415e6
fix: implement call/get_results in Rust shim via global func map
listepo Aug 3, 2026
addfb80
test: add unit and integration tests for Rust shims
listepo Aug 3, 2026
7df335b
fix: use correct wasm3 type names (M3ValueType enum, not bare constants)
listepo Aug 3, 2026
25b153c
fix: use correct bindgen-generated wasm3 type names
listepo Aug 3, 2026
ea9f627
fix: cast m3_GetResults arg to *mut *const c_void in integration test
listepo Aug 3, 2026
56a8709
fix: cast m3_Call arg too in integration test
listepo Aug 3, 2026
663b274
fix: correct fixture path (../../../../ not ../../)
listepo Aug 3, 2026
1b5efed
fix: remove explicit m3_FreeModule (m3_FreeRuntime handles it)
listepo Aug 3, 2026
cb81af4
fix: update wasm3-jni for jni 0.21 API and bindgen types
listepo Aug 3, 2026
b4aa47d
fix: update wamr-jni for jni 0.21 API (same as wasm3-jni fixes)
listepo Aug 3, 2026
9a54933
fix: wamr-jni new_direct_byte_buffer 2-arg API, result→module rename
listepo Aug 3, 2026
1ddb133
fix: more jni 0.21 API fixes for wasm3-jni
listepo Aug 3, 2026
492f32f
fix: cast ctx_ptr to usize for HashMap<i32, usize> storage
listepo Aug 3, 2026
36a026a
fix: add darwin platform include path to Package.swift, exclude compi…
listepo Aug 3, 2026
c9f70d3
fix: complete Package.swift include paths and defines for WAMR iOS build
listepo Aug 3, 2026
3acb2b2
fix: wamr-sys compile errors — use super::*, RUNTIME_REGISTRY as usiz…
listepo Aug 3, 2026
579ed6d
chore: configure act to use Podman instead of Docker
listepo Aug 3, 2026
e292913
docs: update READMEs to reflect cargo-ndk + Rust JNI, UniFFI bindings
listepo Aug 3, 2026
4a6834c
ci: update Android jobs for cargo-ndk + Rust JNI, remove JavaCPP/clang
listepo Aug 3, 2026
ccd0474
chore: remove remaining JavaCPP references and dead preset files
listepo Aug 3, 2026
8cf4b2f
chore: use slim act image for local CI, drop podman socket ref
listepo Aug 3, 2026
2271d64
fix: add Send+Sync impls for wasm3-ffi types
listepo Aug 3, 2026
bca903d
feat: generate UniFFI Swift/Kotlin bindings for wasm3-ffi
listepo Aug 3, 2026
26eacb3
chore: sync WAMR vendor sources — remove excluded platform backends, …
listepo Aug 3, 2026
6c78b0b
fix: NSCWamr host function linking — pass signature to NativeSymbol
listepo Aug 3, 2026
975cd85
fix: remove stale wasm3 AAR (contains old JavaCPP classes)
listepo Aug 3, 2026
e1697a3
chore: sync vendor sources — remove excluded files, update scripts an…
listepo Aug 3, 2026
bf60ee9
fix: restore CWasm3 target accidentally removed from NSCWasm3 Package…
listepo Aug 3, 2026
74def65
Revert "chore: sync vendor sources — remove excluded files, update sc…
listepo Aug 3, 2026
ae79063
fix: WAMR iOS — defer import resolution, fix memory bounds, break ret…
listepo Aug 3, 2026
9b801b2
fix: NSCWamrFunction retains runtime; review nits (resolve flag, UInt…
listepo Aug 3, 2026
afc16f0
fix: guard orphaned-module use-after-free (security review)
listepo Aug 4, 2026
810efdb
fix: make module teardown idempotent (double-free guard)
listepo Aug 4, 2026
a8e5f25
fix: correct slot_width/kind_at for simple valkind codes + fix test
listepo Aug 4, 2026
cf08b0e
Merge main into add-wamr-test-app
listepo Aug 5, 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
  •  
  •  
  •  
285 changes: 142 additions & 143 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,17 @@ jobs:

- run: pnpm install --frozen-lockfile

# This enables task distribution via Nx Cloud.
# Learn more at https://nx.dev/docs/reference/nx-cloud-cli#npx-nxcloud-startcirun
- run: pnpm exec nx start-ci-run --distribute-on="3 linux-medium-js" --stop-agents-after="e2e"

# This enables task distribution via Nx Cloud.
# Learn more at https://nx.dev/docs/reference/nx-cloud-cli#npx-nxcloud-startcirun
- run: pnpm exec nx start-ci-run --distribute-on="3 linux-medium-js" --stop-agents-after="e2e"
# Prepend any command with "nx record --" to record its logs to Nx Cloud
# - run: pnpm exec nx record -- pnpm exec nx format:check --base="remotes/origin/main"
# - run: pnpm exec nx run-many -t lint test build typecheck e2e
# - run: pnpm exec nx record -- pnpm exec nx format:check --base="remotes/origin/main"
# - run: pnpm exec nx run-many -t lint test build typecheck e2e
# Nx Cloud recommends fixes for failures to help you get CI green faster. Learn more: https://nx.dev/docs/features/ci-features/self-healing-ci
# - run: pnpm exec nx fix-ci
# - run: pnpm exec nx fix-ci
# if: always()
# - run: pnpm exec nx format:check --base="remotes/origin/main"
# - run: pnpm exec nx format:check --base="remotes/origin/main"

# Vitest, TypeScript and the Rust fixture crate. Everything here runs on a
# plain Linux runner: the .wasm fixtures are committed build outputs, so no
Expand Down Expand Up @@ -83,7 +83,7 @@ jobs:
# projects — including the test app's mocha specs, which are type-checked
# here even though they can only run on a device.
- name: Vitest + typecheck
run: pnpm exec nx run-many -t test typecheck
run: pnpm exec nx run-many -t test typecheck

# Rust is pre-installed on GitHub's ubuntu-latest runner. When debugging
# locally with `act` the slim image may not have it — install on the fly
Expand All @@ -97,7 +97,7 @@ jobs:

# The fixture crate: wasm exports plus the globals.wasm byte encoder.
- name: Rust unit tests
run: pnpm exec nx run nativescript-wasm-fixture:test.wasm
run: pnpm exec nx run nativescript-wasm-fixture:test.wasm

# globals.wasm is committed but generated, and the generator is
# deterministic — so a stale copy is a hard error rather than a surprise
Expand Down Expand Up @@ -200,8 +200,8 @@ jobs:
-scheme NSCWasm3 \
-destination 'generic/platform=iOS'

# Android: regenerates the JavaCPP bindings from wasm3.h and runs the Kotlin
# wrapper's JUnit suite against a host build of wasm3 — no emulator needed.
# Android: builds the wasm3-jni Rust crate via cargo and runs the Kotlin
# wrapper's JUnit hosttest suite — no emulator needed.
wasm3-android:
needs: changes
if: needs.changes.outputs.wasm3 == 'true'
Expand All @@ -213,6 +213,7 @@ jobs:
# compile wasm3, so the native build needs Node and the root node_modules.
- uses: pnpm/action-setup@v4


- uses: actions/setup-node@v5
with:
node-version: 24
Expand All @@ -227,21 +228,17 @@ jobs:

- uses: gradle/actions/setup-gradle@v4.4.4
with:
# The built-in wrapper validation scans the entire workspace and
# flags every gradle-wrapper.jar it finds — including the one
# bundled inside node_modules/nativescript. That jar is an npm
# package dependency, not ours to validate. Our own wrapper is
# committed in the repo at platforms/android/wasm3-android/.
validate-wrappers: false

# GitHub's ubuntu-latest runner ships clang; the slim act image does not.
- name: Install build tools (if missing)
# Rust is pre-installed on ubuntu-latest; install if missing (e.g. act).
- name: Install Rust (if missing)
run: |
if ! command -v clang++ >/dev/null 2>&1; then
sudo apt-get update -qq && sudo apt-get install -y -qq clang
if ! command -v cargo >/dev/null 2>&1; then
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
fi

- name: JVM host tests (JavaCPP bindings + Kotlin wrapper)
- name: JVM host tests (cargo build + Kotlin wrapper)
working-directory: packages/nativescript-wasm3/platforms/android/wasm3-android
run: ./gradlew :hosttest:test

Expand All @@ -255,114 +252,116 @@ jobs:
# place the plugin's TypeScript adapters run against the real native layer —
# the NSData/NSArray marshalling on iOS, the signed byte[] handling on Android
# — so it covers what neither the Swift/Kotlin suites nor a Node runner can.
# iOS: compiles the vendored WAMR C sources through SwiftPM and runs the
# XCTest suite, which exercises the runtime natively on macOS.
wamr-ios:
needs: changes
if: needs.changes.outputs.wamr == 'true'
runs-on: macos-latest
steps:
- uses: actions/checkout@v5

- uses: actions/setup-node@v5
with:
node-version: 24

- name: Check for WAMR C sources
id: sources
run: |
if find packages/nativescript-wamr/src/vendors/wamr -name '*.c' -o -name '*.h' | grep -q .; then
echo "present=true" >> "$GITHUB_OUTPUT"
else
echo "present=false" >> "$GITHUB_OUTPUT"
echo "::warning::WAMR C sources not found — Swift steps will be skipped."
fi

- name: Verify the synced Swift package copy is current
if: steps.sources.outputs.present == 'true'
working-directory: packages/nativescript-wamr
run: |
node tools/sync-wamr.mjs
git diff --exit-code -- . || {
echo "::error::platforms/ios/NSCWamr/Sources/CWamr is stale — run 'pnpm run sync.vendors' and commit the result."
exit 1
}

- name: Swift tests
if: steps.sources.outputs.present == 'true'
working-directory: packages/nativescript-wamr/platforms/ios/NSCWamr
run: swift test --disable-sandbox

- name: Build for iOS device
if: steps.sources.outputs.present == 'true'
working-directory: packages/nativescript-wamr/platforms/ios/NSCWamr
run: |
xcodebuild build \
-scheme NSCWamr \
-destination 'generic/platform=iOS'

# Android: regenerates the JavaCPP bindings from WAMR headers and runs the
# Kotlin wrapper's JUnit suite against a host build of WAMR — no emulator.
wamr-android:
needs: changes
if: needs.changes.outputs.wamr == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5

- uses: pnpm/action-setup@v4

- uses: actions/setup-node@v5
with:
node-version: 24
cache: 'pnpm'

- run: pnpm install --frozen-lockfile

- name: Check for WAMR C sources
id: sources
run: |
if find packages/nativescript-wamr/src/vendors/wamr -name '*.c' -o -name '*.h' | grep -q .; then
echo "present=true" >> "$GITHUB_OUTPUT"
else
echo "present=false" >> "$GITHUB_OUTPUT"
echo "::warning::WAMR C sources not found — Gradle steps will be skipped."
fi

- uses: actions/setup-java@v4.9.0
if: steps.sources.outputs.present == 'true'
with:
distribution: temurin
java-version: '21'

- uses: gradle/actions/setup-gradle@v4.4.4
if: steps.sources.outputs.present == 'true'
with:
validate-wrappers: false

- name: Install build tools (if missing)
if: steps.sources.outputs.present == 'true'
run: |
if ! command -v clang++ >/dev/null 2>&1; then
sudo apt-get update -qq && sudo apt-get install -y -qq clang
fi

- name: JVM host tests (JavaCPP bindings + Kotlin wrapper)
if: steps.sources.outputs.present == 'true'
working-directory: packages/nativescript-wamr/platforms/android/wamr-android
run: ./gradlew :hosttest:test

- uses: actions/upload-artifact@v4
if: failure() && steps.sources.outputs.present == 'true'
with:
name: wamr-android-test-report
path: packages/nativescript-wamr/platforms/android/wamr-android/hosttest/build/reports/tests/test

# The test app's mocha suite, on a simulator and an emulator. This is the only
# place the plugin's TypeScript adapters run against the real native layer —
# the NSData/NSArray marshalling on iOS, the signed byte[] handling on Android
# — so it covers what neither the Swift/Kotlin suites nor a Node runner can.
wasm-test-ios:
# iOS: compiles the vendored WAMR C sources through SwiftPM and runs the
# XCTest suite, which exercises the runtime natively on macOS.
wamr-ios:
needs: changes
if: needs.changes.outputs.wamr == 'true'
runs-on: macos-latest
steps:
- uses: actions/checkout@v5

- uses: actions/setup-node@v5
with:
node-version: 24

- name: Check for WAMR C sources
id: sources
run: |
if find packages/nativescript-wamr/src/vendors/wamr -name '*.c' -o -name '*.h' | grep -q .; then
echo "present=true" >> "$GITHUB_OUTPUT"
else
echo "present=false" >> "$GITHUB_OUTPUT"
echo "::warning::WAMR C sources not found — Swift steps will be skipped."
fi

- name: Verify the synced Swift package copy is current
if: steps.sources.outputs.present == 'true'
working-directory: packages/nativescript-wamr
run: |
node tools/sync-wamr.mjs
git diff --exit-code -- . || {
echo "::error::platforms/ios/NSCWamr/Sources/CWamr is stale — run 'pnpm run sync.vendors' and commit the result."
exit 1
}

- name: Swift tests
if: steps.sources.outputs.present == 'true'
working-directory: packages/nativescript-wamr/platforms/ios/NSCWamr
run: swift test --disable-sandbox

- name: Build for iOS device
if: steps.sources.outputs.present == 'true'
working-directory: packages/nativescript-wamr/platforms/ios/NSCWamr
run: |
xcodebuild build \
-scheme NSCWamr \
-destination 'generic/platform=iOS'

# Android: builds the wamr-jni Rust crate via cargo and runs the Kotlin
# wrapper's JUnit hosttest suite — no emulator.
wamr-android:
needs: changes
if: needs.changes.outputs.wamr == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5

- uses: pnpm/action-setup@v4

- uses: actions/setup-node@v5
with:
node-version: 24
cache: 'pnpm'

- run: pnpm install --frozen-lockfile

- name: Check for WAMR C sources
id: sources
run: |
if find packages/nativescript-wamr/src/vendors/wamr -name '*.c' -o -name '*.h' | grep -q .; then
echo "present=true" >> "$GITHUB_OUTPUT"
else
echo "present=false" >> "$GITHUB_OUTPUT"
echo "::warning::WAMR C sources not found — Gradle steps will be skipped."
fi

- uses: actions/setup-java@v4.9.0
if: steps.sources.outputs.present == 'true'
with:
distribution: temurin
java-version: '21'

- uses: gradle/actions/setup-gradle@v4.4.4
if: steps.sources.outputs.present == 'true'
with:
validate-wrappers: false

# Rust is pre-installed on ubuntu-latest; install if missing (e.g. act).
- name: Install Rust (if missing)
if: steps.sources.outputs.present == 'true'
run: |
if ! command -v cargo >/dev/null 2>&1; then
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
fi

- name: JVM host tests (cargo build + Kotlin wrapper)
if: steps.sources.outputs.present == 'true'
working-directory: packages/nativescript-wamr/platforms/android/wamr-android
run: ./gradlew :hosttest:test

- uses: actions/upload-artifact@v4
if: failure() && steps.sources.outputs.present == 'true'
with:
name: wamr-android-test-report
path: packages/nativescript-wamr/platforms/android/wamr-android/hosttest/build/reports/tests/test

# The test app's mocha suite, on a simulator and an emulator. This is the only
# place the plugin's TypeScript adapters run against the real native layer —
# the NSData/NSArray marshalling on iOS, the signed byte[] handling on Android
# — so it covers what neither the Swift/Kotlin suites nor a Node runner can.
wasm-test-ios:
needs: changes
if: needs.changes.outputs.app == 'true'
runs-on: macos-latest
Expand All @@ -381,10 +380,10 @@ jobs:

- run: pnpm install --frozen-lockfile

# The app resolves the plugin through a file: dependency and imports its
# built dist/, so the TypeScript has to exist before the app is bundled.
- name: Build the plugin
run: pnpm exec nx run nativescript-wasm3:build
# The app resolves both plugins through file: dependencies and imports
# their built dist/, so TypeScript must exist before bundling.
- name: Build the plugins
run: npx nx run-many -t build -p nativescript-wasm3 nativescript-wamr

- name: Install the test app's dependencies
working-directory: apps/nativescript-wasm-test
Expand All @@ -394,10 +393,10 @@ jobs:
# the CLI treats as a failed CocoaPods check unless LANG is a UTF-8 one.
# The plugin itself needs no pods — it ships a Swift package.
- name: Mocha specs on the iOS Simulator
working-directory: .
env:
LANG: en_US.UTF-8
run: pnpm exec sh -c 'cd apps/nativescript-wasm-test && ns test ios --emulator'
working-directory: .
env:
LANG: en_US.UTF-8
run: pnpm exec sh -c 'cd apps/nativescript-wasm-test && ns test ios --emulator'

wasm-test-android:
needs: changes
Expand All @@ -420,7 +419,7 @@ jobs:
- run: pnpm install --frozen-lockfile

- name: Build the plugin
run: pnpm exec nx run nativescript-wasm3:build
run: pnpm exec nx run nativescript-wasm3:build

- name: Install the test app's dependencies
working-directory: apps/nativescript-wasm-test
Expand All @@ -439,12 +438,12 @@ jobs:
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm

# The plugin ships a prebuilt .aar with the wasm3 .so files for every ABI,
# so this needs no NDK — just the SDK the emulator action installs.
# The wasm3 plugin ships a prebuilt .aar with its .so files.
# WAMR tests will fail at runtime without it (known: continue-on-error).
- name: Mocha specs on the Android emulator
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 34
arch: x86_64
working-directory: .
script: pnpm exec sh -c 'cd apps/nativescript-wasm-test && ns test android --emulator'
working-directory: .
script: pnpm exec sh -c 'cd apps/nativescript-wasm-test && ns test android --emulator'
2 changes: 1 addition & 1 deletion .github/workflows/code-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
You are a senior code reviewer for a NativeScript monorepo built
with Nx. The codebase spans: a TypeScript NativeScript plugin
(packages/nativescript-wasm3) that bridges WebAssembly (wasm3) to
iOS (Swift) and Android (Kotlin + JavaCPP JNI); a Rust wasm-pack
iOS (Swift) and Android (Kotlin + Rust JNI); a Rust wasm-pack
fixture crate (packages/nativescript-wasm-fixture); and a
NativeScript test app (apps/nativescript-wasm-test) running mocha
on device/emulator.
Expand Down
Loading
Loading