Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 143 additions & 10 deletions .github/workflows/test-and-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,10 @@ jobs:
! grep -nE "v8::|<v8.h>|\"v8.h\"" napi/include/js_native_api.h napi/include/node_api.h

- name: Build napi-v8
run: cmake -S napi/v8 -B napi/v8/build -DCMAKE_BUILD_TYPE=Release -DNAPI_V8_BUILD_TESTS=ON

- name: Compile napi-v8
run: cmake --build napi/v8/build -j4
run: make build-napi CMAKE_BUILD_TYPE=Release JOBS=4

- name: Test napi-v8
run: ctest --test-dir napi/v8/build --output-on-failure -R '^napi_v8\.'
run: make test-napi-only TEST_JOBS=4

- name: Build edge
run: |
Expand Down Expand Up @@ -236,13 +233,10 @@ jobs:
! grep -nE "v8::|<v8.h>|\"v8.h\"" napi/include/js_native_api.h napi/include/node_api.h

- name: Build napi-v8
run: cmake -S napi/v8 -B napi/v8/build -DCMAKE_BUILD_TYPE=Release -DNAPI_V8_BUILD_TESTS=ON

- name: Compile napi-v8
run: cmake --build napi/v8/build -j4
run: make build-napi CMAKE_BUILD_TYPE=Release JOBS=4

- name: Test napi-v8
run: ctest --test-dir napi/v8/build --output-on-failure -R '^napi_v8\.'
run: make test-napi-only TEST_JOBS=4

- name: Build edge
run: |
Expand All @@ -269,6 +263,145 @@ jobs:
if: always()
run: sccache --show-stats || true

build-napi-jsc-macos:
name: build-napi-jsc-macos
runs-on: macos-latest
env:
SCCACHE_GHA_ENABLED: "true"
JSC_BUILD_DIR: build-napi-jsc
JSC_STOCK_BUILD_DIR: build-jsc-stock-host
JSC_SMOKE_REGEX: "napi_jsc_test_(29_bigint|31_dataview|32_sharedarraybuffer|35_promise|39_cannot_run_js|65_unofficial_contextify|66_unofficial_unsupported)"
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup sccache
uses: mozilla-actions/sccache-action@v0.0.9
- name: Ensure submodules are initialized
shell: bash
run: |
set -euo pipefail
git submodule sync --recursive
git -c protocol.version=2 submodule update --init --recursive --depth=1
test -f node/src/node_api_types.h

- name: Validate public N-API headers stay V8-agnostic
run: |
! grep -nE "v8::|<v8.h>|\"v8.h\"" napi/include/js_native_api.h napi/include/node_api.h

- name: Resolve Bun WebKit SDK path
id: bun_webkit
shell: bash
run: |
set -euo pipefail
tag="$(bash napi/jsc/tools/bun_webkit_release_tag.sh)"
arch="$(uname -m)"
case "${arch}" in
arm64) asset_arch="arm64" ;;
x86_64) asset_arch="amd64" ;;
*) echo "Unsupported macOS architecture: ${arch}" >&2; exit 1 ;;
esac
root="${GITHUB_WORKSPACE}/.ci/jsc/${tag}/macos-${asset_arch}"
{
echo "tag=${tag}"
echo "root=${root}"
} >> "${GITHUB_OUTPUT}"

- name: Cache Bun WebKit SDK
uses: actions/cache@v4
with:
path: ${{ steps.bun_webkit.outputs.root }}
key: bun-webkit-${{ runner.os }}-${{ runner.arch }}-${{ steps.bun_webkit.outputs.tag }}

- name: Fetch Bun WebKit SDK
shell: bash
env:
BUN_WEBKIT_ROOT: ${{ steps.bun_webkit.outputs.root }}
BUN_WEBKIT_TAG: ${{ steps.bun_webkit.outputs.tag }}
run: |
set -euo pipefail
bash napi/jsc/tools/fetch_bun_webkit_macos.sh

- name: Build stock-host negative guard
shell: bash
run: |
set -euo pipefail
cmake -S napi/jsc -B "${JSC_STOCK_BUILD_DIR}" -DCMAKE_BUILD_TYPE=Release -DNAPI_JSC_BUILD_TESTS=ON
cmake --build "${JSC_STOCK_BUILD_DIR}" --parallel 4 --target napi_jsc_test_67_jsc_config_guard

- name: Run stock-host negative guard
shell: bash
run: |
set -euo pipefail
env -u BUN_WEBKIT_ROOT -u DYLD_FRAMEWORK_PATH -u DYLD_LIBRARY_PATH -u __XPC_DYLD_FRAMEWORK_PATH -u __XPC_DYLD_LIBRARY_PATH \
"./${JSC_STOCK_BUILD_DIR}/tests/napi_jsc_test_67_jsc_config_guard" \
--gtest_filter=Test67JscConfigGuard.RejectsSablessHostConfiguration

- name: Build napi-jsc
shell: bash
env:
BUN_WEBKIT_ROOT: ${{ steps.bun_webkit.outputs.root }}
run: |
set -euo pipefail
make build-napi-jsc BUILD_DIR="${JSC_BUILD_DIR}" CMAKE_BUILD_TYPE=Release JOBS=4

- name: Run JSC runtime probe
shell: bash
run: |
set -euo pipefail
"${JSC_BUILD_DIR}/napi-jsc/tests/napi_jsc_runtime_probe" | tee "${JSC_BUILD_DIR}/jsc-runtime-probe.txt"

- name: Check JSC linkage
shell: bash
run: |
set -euo pipefail
otool -L "${JSC_BUILD_DIR}/napi-jsc/tests/napi_jsc_test_32_sharedarraybuffer" | tee "${JSC_BUILD_DIR}/jsc-runtime-otool.txt"
! grep -q '/System/Library/Frameworks/JavaScriptCore.framework' "${JSC_BUILD_DIR}/jsc-runtime-otool.txt"

- name: Run JSC smoke subset
shell: bash
run: |
set -euo pipefail
ctest --test-dir "${JSC_BUILD_DIR}" --output-on-failure -j4 -R "${JSC_SMOKE_REGEX}"

- name: Run JSC ctest suite
shell: bash
run: |
set -euo pipefail
ctest --test-dir "${JSC_BUILD_DIR}" --output-on-failure -j4 -R '^napi_jsc\.'

- name: Write JSC runtime report
if: always()
shell: bash
run: |
set -euo pipefail
mkdir -p "${JSC_BUILD_DIR}"
{
echo "BUN_WEBKIT_TAG: ${{ steps.bun_webkit.outputs.tag }}"
echo "BUN_WEBKIT_ROOT: ${{ steps.bun_webkit.outputs.root }}"
echo "Build directory: ${JSC_BUILD_DIR}"
echo "Smoke regex: ${JSC_SMOKE_REGEX}"
echo "Probe binary: ${JSC_BUILD_DIR}/napi-jsc/tests/napi_jsc_runtime_probe"
echo "Full ctest command: ctest --test-dir ${JSC_BUILD_DIR} --output-on-failure -j4 -R ^napi_jsc\\."
} > "${JSC_BUILD_DIR}/jsc-runtime-report.txt"

- name: Upload JSC diagnostics
if: always()
uses: actions/upload-artifact@v4
with:
name: napi-jsc-macos-diagnostics
if-no-files-found: ignore
path: |
build-napi-jsc/jsc-runtime-probe.txt
build-napi-jsc/jsc-runtime-report.txt
build-napi-jsc/jsc-runtime-otool.txt
build-napi-jsc/Testing/Temporary/LastTest.log
build-jsc-stock-host/Testing/Temporary/LastTest.log

- name: sccache stats
if: always()
run: sccache --show-stats || true

# build-windows-smoke:
# name: build-windows-smoke
# runs-on: windows-latest
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ v8-*.tar.xz
/deps/openssl-wasix
/dist
/v8-custom-builds
/.ci/jsc
/.vscode

# direnv
Expand Down
28 changes: 21 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ set(CMAKE_CXX_EXTENSIONS OFF)
set(PROJECT_ROOT "${CMAKE_CURRENT_SOURCE_DIR}")
set(EDGE_ROOT "${PROJECT_ROOT}")
set(NAPI_V8_ROOT "${PROJECT_ROOT}/napi/v8")
set(NAPI_JSC_ROOT "${PROJECT_ROOT}/napi/jsc")
set(NAPI_INCLUDE_ROOT "${PROJECT_ROOT}/napi/include")
find_package(Python3 REQUIRED COMPONENTS Interpreter)

Expand Down Expand Up @@ -137,23 +138,26 @@ if(EDGE_IS_WASIX_TARGET)
endif()
set(EDGE_NAPI_PROVIDER
"${_edge_napi_provider_default}"
CACHE STRING "N-API provider backend: bundled-v8|imports"
CACHE STRING "N-API provider backend: bundled-v8|bundled-jsc|imports"
)
set_property(CACHE EDGE_NAPI_PROVIDER PROPERTY STRINGS bundled-v8 imports)
set_property(CACHE EDGE_NAPI_PROVIDER PROPERTY STRINGS bundled-v8 bundled-jsc imports)
option(EDGE_NAPI_PROVIDER_BUILD_TESTS
"Build bundled N-API provider tests when using a bundled provider"
OFF)
if(EDGE_EXTERNAL_NAPI_V8)
message(WARNING
"EDGE_EXTERNAL_NAPI_V8 is deprecated; use EDGE_NAPI_PROVIDER=imports.")
set(EDGE_NAPI_PROVIDER "imports" CACHE STRING
"N-API provider backend: bundled-v8|imports" FORCE)
"N-API provider backend: bundled-v8|bundled-jsc|imports" FORCE)
endif()
string(TOLOWER "${EDGE_NAPI_PROVIDER}" EDGE_NAPI_PROVIDER)
if(NOT EDGE_NAPI_PROVIDER MATCHES "^(bundled-v8|imports)$")
if(NOT EDGE_NAPI_PROVIDER MATCHES "^(bundled-v8|bundled-jsc|imports)$")
message(FATAL_ERROR
"Invalid EDGE_NAPI_PROVIDER='${EDGE_NAPI_PROVIDER}'. "
"Valid values: bundled-v8, imports.")
"Valid values: bundled-v8, bundled-jsc, imports.")
endif()
set(EDGE_NAPI_PROVIDER "${EDGE_NAPI_PROVIDER}" CACHE STRING
"N-API provider backend: bundled-v8|imports" FORCE)
"N-API provider backend: bundled-v8|bundled-jsc|imports" FORCE)

# Hard gate: edge runtime/library sources must never directly reference V8.
file(GLOB_RECURSE EDGE_PURE_SRC_FILES
Expand Down Expand Up @@ -192,8 +196,11 @@ if(EDGE_NAPI_PROVIDER STREQUAL "bundled-v8")
endif()
endif()
endif()
set(NAPI_V8_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(NAPI_V8_BUILD_TESTS ${EDGE_NAPI_PROVIDER_BUILD_TESTS} CACHE BOOL "" FORCE)
add_subdirectory("${NAPI_V8_ROOT}" "${CMAKE_CURRENT_BINARY_DIR}/napi-v8")
elseif(EDGE_NAPI_PROVIDER STREQUAL "bundled-jsc")
set(NAPI_JSC_BUILD_TESTS ${EDGE_NAPI_PROVIDER_BUILD_TESTS} CACHE BOOL "" FORCE)
add_subdirectory("${NAPI_JSC_ROOT}" "${CMAKE_CURRENT_BINARY_DIR}/napi-jsc")
elseif(EDGE_NAPI_PROVIDER STREQUAL "imports")
add_library(edge_napi_headers INTERFACE)
target_include_directories(edge_napi_headers INTERFACE "${NAPI_INCLUDE_ROOT}")
Expand Down Expand Up @@ -611,6 +618,9 @@ target_include_directories(edge_environment_core
"${NAPI_INCLUDE_ROOT}"
)
target_link_libraries(edge_environment_core PUBLIC uv_a)
if(EDGE_NAPI_PROVIDER MATCHES "^bundled-")
target_compile_definitions(edge_environment_core PUBLIC EDGE_BUNDLED_NAPI_PROVIDER=1)
endif()
if(EDGE_NAPI_PROVIDER STREQUAL "bundled-v8")
target_compile_definitions(edge_environment_core PUBLIC EDGE_BUNDLED_NAPI_V8=1)
endif()
Expand Down Expand Up @@ -749,6 +759,8 @@ target_link_libraries(edge_node_api
if(EDGE_NAPI_PROVIDER STREQUAL "bundled-v8")
target_compile_definitions(napi_v8 PUBLIC EDGE_BUNDLED_NAPI_V8=1)
target_link_libraries(edge_node_api PUBLIC napi_v8)
elseif(EDGE_NAPI_PROVIDER STREQUAL "bundled-jsc")
target_link_libraries(edge_node_api PUBLIC napi_jsc)
endif()

add_library(edge_runtime STATIC
Expand Down Expand Up @@ -916,6 +928,8 @@ target_link_libraries(edge_runtime
)
if(EDGE_NAPI_PROVIDER STREQUAL "bundled-v8")
target_link_libraries(edge_runtime PUBLIC napi_v8)
elseif(EDGE_NAPI_PROVIDER STREQUAL "bundled-jsc")
target_link_libraries(edge_runtime PUBLIC napi_jsc)
endif()
set(EDGE_NODE_SHARED_OPENSSL 0)
if(NOT EDGE_IS_WASIX_TARGET AND EDGE_SHARED_OPENSSL)
Expand Down
34 changes: 32 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
.PHONY: build test test-only check-portability clean-dist dist dist-only
.PHONY: build build-napi-v8 build-napi-jsc test test-only check-portability clean-dist dist dist-only

UNAME_S := $(shell uname -s)
BUILD_NAPI_DIR ?= build-v8-napi
BUILD_DIR ?= build-edge
BUILD_TARGET ?=
DIST_DIR ?= dist
DIST_BIN_DIR ?= $(DIST_DIR)/bin
DIST_BIN_COMPAT_DIR ?= $(DIST_DIR)/bin-compat
Expand All @@ -15,14 +17,42 @@ EDGEENV_BINARY ?= $(BUILD_DIR)/edgeenv
CMAKE_ARGS ?=
BUILD_ENV ?= env
EXTRA_CMAKE_ARGS ?=
NAPI_V8_BUILD_DIR ?= build-napi-v8
NAPI_JSC_BUILD_DIR ?= build-napi-jsc

ifeq ($(UNAME_S),Darwin)
BUILD_ENV := env -u CPPFLAGS -u LDFLAGS
endif

build-napi:
$(BUILD_ENV) cmake -S napi/v8 -B $(BUILD_NAPI_DIR) -DCMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) $(EXTRA_CMAKE_ARGS) $(CMAKE_ARGS)
$(BUILD_ENV) cmake --build $(BUILD_NAPI_DIR) -j$(JOBS)

test-napi: build-napi test-napi-only

test-napi-only:
$(BUILD_ENV) ctest --test-dir $(BUILD_NAPI_DIR) --output-on-failure -R '^napi_v8\.'

build:
$(BUILD_ENV) cmake -S . -B $(BUILD_DIR) -DCMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE) $(EXTRA_CMAKE_ARGS) $(CMAKE_ARGS)
$(BUILD_ENV) cmake --build $(BUILD_DIR) -j$(JOBS)
$(BUILD_ENV) cmake --build $(BUILD_DIR) -j$(JOBS) $(if $(strip $(BUILD_TARGET)),--target $(BUILD_TARGET),)

build-napi-v8:
$(MAKE) build \
BUILD_DIR=$(NAPI_V8_BUILD_DIR) \
BUILD_TARGET=napi_v8_tests \
CMAKE_ARGS='$(CMAKE_ARGS) -DEDGE_NAPI_PROVIDER=bundled-v8 -DEDGE_NAPI_PROVIDER_BUILD_TESTS=ON'

build-napi-jsc:
ifeq ($(UNAME_S),Darwin)
$(MAKE) build \
BUILD_DIR=$(NAPI_JSC_BUILD_DIR) \
BUILD_TARGET=napi_jsc_tests \
CMAKE_ARGS='$(CMAKE_ARGS) -DEDGE_NAPI_PROVIDER=bundled-jsc -DEDGE_NAPI_PROVIDER_BUILD_TESTS=ON'
else
@echo "build-napi-jsc is macOS-only for now." >&2
@exit 1
endif

test: build test-only

Expand Down
5 changes: 5 additions & 0 deletions napi/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ cmake_minimum_required(VERSION 3.20)
project(napi_engines LANGUAGES C CXX)

option(NAPI_BUILD_V8 "Build the V8-backed Node-API engine" ON)
option(NAPI_BUILD_JSC "Build the JavaScriptCore-backed Node-API engine" ON)

if(NAPI_BUILD_V8)
add_subdirectory(v8)
endif()

if(NAPI_BUILD_JSC)
add_subdirectory(jsc)
endif()
Loading
Loading