diff --git a/.github/workflows/build-darwin.yml b/.github/workflows/build-darwin.yml index 2ce96b110e1e0b..58da85199b04a8 100644 --- a/.github/workflows/build-darwin.yml +++ b/.github/workflows/build-darwin.yml @@ -27,7 +27,7 @@ on: type: boolean env: - LLVM_VERSION: 16 + LLVM_VERSION: 17 BUN_VERSION: 1.1.2 jobs: diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml index 357888cdbd50d8..93392ef45879c6 100644 --- a/.github/workflows/build-windows.yml +++ b/.github/workflows/build-windows.yml @@ -28,7 +28,7 @@ on: env: # Must specify exact version of LLVM for Windows - LLVM_VERSION: 16.0.6 + LLVM_VERSION: 17.0.6 BUN_VERSION: 1.1.2 jobs: @@ -67,7 +67,7 @@ jobs: key: bun-${{ inputs.tag }}-deps-${{ steps.hash.outputs.hash }} - if: ${{ inputs.no-cache || !steps.cache.outputs.cache-hit }} name: Install LLVM - uses: KyleMayes/install-llvm-action@1a3da29f56261a1e1f937ec88f0856a9b8321d7e + uses: KyleMayes/install-llvm-action@8b37482c5a2997a3ab5dbf6561f8109e2eaa7d3b with: version: ${{ env.LLVM_VERSION }} - if: ${{ inputs.no-cache || !steps.cache.outputs.cache-hit }} @@ -145,7 +145,7 @@ jobs: with: submodules: recursive - name: Install LLVM - uses: KyleMayes/install-llvm-action@1a3da29f56261a1e1f937ec88f0856a9b8321d7e + uses: KyleMayes/install-llvm-action@8b37482c5a2997a3ab5dbf6561f8109e2eaa7d3b with: version: ${{ env.LLVM_VERSION }} - name: Install Ninja @@ -224,7 +224,7 @@ jobs: with: submodules: recursive - name: Install LLVM - uses: KyleMayes/install-llvm-action@1a3da29f56261a1e1f937ec88f0856a9b8321d7e + uses: KyleMayes/install-llvm-action@8b37482c5a2997a3ab5dbf6561f8109e2eaa7d3b with: version: ${{ env.LLVM_VERSION }} - name: Install Ninja diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 34756ebc5e0d1c..b008634a1ce833 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,6 +14,10 @@ on: run-id: type: string description: The workflow ID to download artifacts (skips the build step) + canary: + type: boolean + description: "Is this a canary build?" + default: true pull_request: push: branches: @@ -44,6 +48,7 @@ jobs: tag: linux-x64 arch: x64 cpu: haswell + canary: ${{ inputs.canary }} linux-x64-baseline: if: ${{ !github.event.inputs.run-id }} name: Build linux-x64-baseline @@ -54,6 +59,7 @@ jobs: tag: linux-x64-baseline arch: x64 cpu: nehalem + canary: ${{ inputs.canary }} linux-aarch64: if: ${{ !github.event.inputs.run-id && github.repository_owner == 'oven-sh' }} name: Build linux-aarch64 @@ -64,26 +70,29 @@ jobs: tag: linux-aarch64 arch: aarch64 cpu: native + canary: ${{ inputs.canary }} darwin-x64: if: ${{ !github.event.inputs.run-id }} name: Build darwin-x64 uses: ./.github/workflows/build-darwin.yml secrets: inherit with: - runs-on: ${{ github.repository_owner == 'oven-sh' && 'macos-12-large' || 'macos-12' }} + runs-on: ${{ github.repository_owner == 'oven-sh' && 'macos-13-large' || 'macos-13' }} tag: darwin-x64 arch: x64 cpu: haswell + canary: ${{ inputs.canary }} darwin-x64-baseline: if: ${{ !github.event.inputs.run-id }} name: Build darwin-x64-baseline uses: ./.github/workflows/build-darwin.yml secrets: inherit with: - runs-on: ${{ github.repository_owner == 'oven-sh' && 'macos-12-large' || 'macos-12' }} + runs-on: ${{ github.repository_owner == 'oven-sh' && 'macos-13-large' || 'macos-13' }} tag: darwin-x64-baseline arch: x64 cpu: nehalem + canary: ${{ inputs.canary }} darwin-aarch64: if: ${{ !github.event.inputs.run-id }} name: Build darwin-aarch64 @@ -94,6 +103,7 @@ jobs: tag: darwin-aarch64 arch: aarch64 cpu: native + canary: ${{ inputs.canary }} windows-x64: if: ${{ !github.event.inputs.run-id }} name: Build windows-x64 @@ -104,6 +114,7 @@ jobs: tag: windows-x64 arch: x64 cpu: haswell + canary: ${{ inputs.canary }} windows-x64-baseline: if: ${{ !github.event.inputs.run-id }} name: Build windows-x64-baseline @@ -114,6 +125,7 @@ jobs: tag: windows-x64-baseline arch: x64 cpu: nehalem + canary: ${{ inputs.canary }} linux-x64-test: if: ${{ github.event.inputs.run-id && always() || github.event_name == 'pull_request' }} name: Test linux-x64 @@ -156,7 +168,7 @@ jobs: with: run-id: ${{ inputs.run-id }} pr-number: ${{ github.event.number }} - runs-on: ${{ github.repository_owner == 'oven-sh' && 'macos-12-large' || 'macos-12' }} + runs-on: ${{ github.repository_owner == 'oven-sh' && 'macos-13-large' || 'macos-13' }} tag: darwin-x64 darwin-x64-baseline-test: if: ${{ github.event.inputs.run-id && always() || github.event_name == 'pull_request' }} @@ -167,7 +179,7 @@ jobs: with: run-id: ${{ inputs.run-id }} pr-number: ${{ github.event.number }} - runs-on: ${{ github.repository_owner == 'oven-sh' && 'macos-12-large' || 'macos-12' }} + runs-on: ${{ github.repository_owner == 'oven-sh' && 'macos-13-large' || 'macos-13' }} tag: darwin-x64-baseline darwin-aarch64-test: if: ${{ github.event.inputs.run-id && always() || github.event_name == 'pull_request' }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 99d098d9e1ca3a..c2dd7924749129 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,11 +3,23 @@ cmake_policy(SET CMP0091 NEW) cmake_policy(SET CMP0067 NEW) set(Bun_VERSION "1.1.5") -set(WEBKIT_TAG e3a2d89a0b1644cc8d5c245bd2ffee4d4bd6c1d5) +set(WEBKIT_TAG 2ce7bb4314c516d9c7ba12be3581f6a986013781) set(BUN_WORKDIR "${CMAKE_CURRENT_BINARY_DIR}") message(STATUS "Configuring Bun ${Bun_VERSION} in ${BUN_WORKDIR}") +set(CMAKE_COLOR_DIAGNOSTICS ON) +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_C_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_C_STANDARD_REQUIRED ON) + +# WebKit uses -std=gnu++20 on non-macOS non-Windows +# If we do not set this, it will crash at startup on the first memory allocation. +if (NOT WIN32 AND NOT APPLE) +set(CMAKE_CXX_EXTENSIONS ON) +endif() + # --- Build Type --- if(NOT CMAKE_BUILD_TYPE) message(WARNING "No CMAKE_BUILD_TYPE value specified, defaulting to Debug.\nSet a build type with -DCMAKE_BUILD_TYPE=") @@ -51,11 +63,7 @@ endif() # --- MacOS SDK --- if(APPLE AND DEFINED ENV{CI}) - if(ARCH STREQUAL "x86_64") - set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14") - else() - set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0") - endif() + set(CMAKE_OSX_DEPLOYMENT_TARGET "12.0") endif() if(APPLE AND NOT CMAKE_OSX_DEPLOYMENT_TARGET) @@ -99,7 +107,7 @@ endif() # we do some extra work afterwards to double-check, and we will rerun BUN_FIND_LLVM if the compiler did not match. # # If the user passes -DLLVM_PREFIX, most of this logic is skipped, but we still warn if invalid. -set(LLVM_VERSION 16) +set(LLVM_VERSION 17) macro(BUN_FIND_LLVM) find_program( @@ -214,12 +222,6 @@ else() ) endif() -set(CMAKE_COLOR_DIAGNOSTICS ON) -set(CMAKE_CXX_STANDARD 20) -set(CMAKE_C_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_C_STANDARD_REQUIRED ON) - project(Bun VERSION "${Bun_VERSION}") # if(MSVC) @@ -1103,15 +1105,14 @@ else() target_compile_options(${bun} PUBLIC -fPIC -mtune=${CPU_TARGET} - -fconstexpr-steps=1271242 - -fconstexpr-depth=27 + -fconstexpr-steps=2542484 + -fconstexpr-depth=54 -fno-exceptions -fvisibility=hidden -fvisibility-inlines-hidden -fno-rtti -fno-omit-frame-pointer ) - string(APPEND CMAKE_CXX_FLAGS " -std=c++2a") endif() if(APPLE) @@ -1130,7 +1131,6 @@ if(UNIX AND NOT APPLE) "-fuse-ld=lld" "-static-libstdc++" "-static-libgcc" - "-fuse-ld=lld" "-Wl,-z,now" "-Wl,--as-needed" "-Wl,--gc-sections" @@ -1143,16 +1143,17 @@ if(UNIX AND NOT APPLE) "-Wl,--wrap=log" "-Wl,--wrap=log2" "-Wl,--wrap=lstat" + "-Wl,--wrap=stat64" "-Wl,--wrap=stat" "-Wl,--wrap=fstat" "-Wl,--wrap=fstatat" "-Wl,--wrap=lstat64" - "-Wl,--wrap=stat64" "-Wl,--wrap=fstat64" "-Wl,--wrap=fstatat64" "-Wl,--wrap=mknod" "-Wl,--wrap=mknodat" "-Wl,--wrap=statx" + "-Wl,--wrap=fmod" "-Wl,--compress-debug-sections=zlib" "-Bsymbolics-functions" "-rdynamic" diff --git a/Dockerfile b/Dockerfile index 4fd86328f950d8..f36ec9e50a562c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,7 +16,7 @@ ARG BUILD_MACHINE_ARCH=x86_64 ARG BUILDARCH=amd64 ARG TRIPLET=${ARCH}-linux-gnu ARG GIT_SHA="" -ARG BUN_VERSION="bun-v1.0.30" +ARG BUN_VERSION="bun-v1.1.4" ARG BUN_DOWNLOAD_URL_BASE="https://pub-5e11e972747a44bf9aaf9394f185a982.r2.dev/releases/${BUN_VERSION}" ARG CANARY=0 ARG ASSERTIONS=OFF @@ -24,7 +24,7 @@ ARG ZIG_OPTIMIZE=ReleaseFast ARG CMAKE_BUILD_TYPE=Release ARG NODE_VERSION="20" -ARG LLVM_VERSION="16" +ARG LLVM_VERSION="17" ARG ZIG_VERSION="0.12.0-dev.1828+225fe6ddb" ARG SCCACHE_BUCKET @@ -34,7 +34,7 @@ ARG SCCACHE_ENDPOINT ARG AWS_ACCESS_KEY_ID ARG AWS_SECRET_ACCESS_KEY -FROM bitnami/minideb:bullseye as bun-base +FROM bitnami/minideb:bookworm as bun-base ARG BUN_DOWNLOAD_URL_BASE ARG DEBIAN_FRONTEND @@ -51,10 +51,10 @@ ENV CPU_TARGET=${CPU_TARGET} ENV BUILDARCH=${BUILDARCH} ENV BUN_DEPS_OUT_DIR=${BUN_DEPS_OUT_DIR} -ENV CXX=clang++-16 -ENV CC=clang-16 -ENV AR=/usr/bin/llvm-ar-16 -ENV LD=lld-16 +ENV CXX=clang++-${LLVM_VERSION} +ENV CC=clang-${LLVM_VERSION} +ENV AR=/usr/bin/llvm-ar +ENV LD=lld-${LLVM_VERSION} ENV SCCACHE_BUCKET=${SCCACHE_BUCKET} ENV SCCACHE_REGION=${SCCACHE_REGION} @@ -63,18 +63,15 @@ ENV SCCACHE_ENDPOINT=${SCCACHE_ENDPOINT} ENV AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} ENV AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} -RUN apt-get update -y \ - && install_packages \ +RUN install_packages \ ca-certificates \ curl \ gnupg \ - && echo "deb https://apt.llvm.org/bullseye/ llvm-toolchain-bullseye-${LLVM_VERSION} main" > /etc/apt/sources.list.d/llvm.list \ - && echo "deb-src https://apt.llvm.org/bullseye/ llvm-toolchain-bullseye-${LLVM_VERSION} main" >> /etc/apt/sources.list.d/llvm.list \ + && echo "deb https://apt.llvm.org/bookworm/ llvm-toolchain-bookworm-${LLVM_VERSION} main" > /etc/apt/sources.list.d/llvm.list \ + && echo "deb-src https://apt.llvm.org/bookworm/ llvm-toolchain-bookworm-${LLVM_VERSION} main" >> /etc/apt/sources.list.d/llvm.list \ && curl -fsSL "https://apt.llvm.org/llvm-snapshot.gpg.key" | apt-key add - \ && echo "deb https://deb.nodesource.com/node_${NODE_VERSION}.x nodistro main" > /etc/apt/sources.list.d/nodesource.list \ && curl -fsSL "https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key" | apt-key add - \ - && echo "deb https://apt.kitware.com/ubuntu/ focal main" > /etc/apt/sources.list.d/kitware.list \ - && curl -fsSL "https://apt.kitware.com/keys/kitware-archive-latest.asc" | apt-key add - \ && install_packages \ wget \ bash \ @@ -88,6 +85,8 @@ RUN apt-get update -y \ lld-${LLVM_VERSION} \ lldb-${LLVM_VERSION} \ clangd-${LLVM_VERSION} \ + libc++-${LLVM_VERSION}-dev \ + libc++abi-${LLVM_VERSION}-dev \ make \ cmake \ ninja-build \ @@ -104,14 +103,16 @@ RUN apt-get update -y \ perl \ python3 \ ruby \ + ruby-dev \ golang \ - nodejs \ - && ln -s /usr/bin/clang-${LLVM_VERSION} /usr/bin/clang \ - && ln -s /usr/bin/clang++-${LLVM_VERSION} /usr/bin/clang++ \ - && ln -s /usr/bin/lld-${LLVM_VERSION} /usr/bin/lld \ - && ln -s /usr/bin/lldb-${LLVM_VERSION} /usr/bin/lldb \ - && ln -s /usr/bin/clangd-${LLVM_VERSION} /usr/bin/clangd \ - && ln -s /usr/bin/llvm-ar-${LLVM_VERSION} /usr/bin/llvm-ar \ + nodejs && \ + for f in /usr/lib/llvm-${LLVM_VERSION}/bin/*; do ln -sf "$f" /usr/bin; done \ + && ln -sf /usr/bin/clang-${LLVM_VERSION} /usr/bin/clang \ + && ln -sf /usr/bin/clang++-${LLVM_VERSION} /usr/bin/clang++ \ + && ln -sf /usr/bin/lld-${LLVM_VERSION} /usr/bin/lld \ + && ln -sf /usr/bin/lldb-${LLVM_VERSION} /usr/bin/lldb \ + && ln -sf /usr/bin/clangd-${LLVM_VERSION} /usr/bin/clangd \ + && ln -sf /usr/bin/llvm-ar-${LLVM_VERSION} /usr/bin/llvm-ar \ && arch="$(dpkg --print-architecture)" \ && case "${arch##*-}" in \ amd64) variant="x64";; \ diff --git a/Makefile b/Makefile index d60b70a72cdf1f..ed17bb08c9d724 100644 --- a/Makefile +++ b/Makefile @@ -81,8 +81,8 @@ ZIG ?= $(shell which zig 2>/dev/null || echo -e "error: Missing zig. Please make # This is easier to happen than you'd expect. # Using realpath here causes issues because clang uses clang++ as a symlink # so if that's resolved, it won't build for C++ -REAL_CC = $(shell which clang-16 2>/dev/null || which clang 2>/dev/null) -REAL_CXX = $(shell which clang++-16 2>/dev/null || which clang++ 2>/dev/null) +REAL_CC = $(shell which clang-17 2>/dev/null || which clang 2>/dev/null) +REAL_CXX = $(shell which clang++-17 2>/dev/null || which clang++ 2>/dev/null) CLANG_FORMAT = $(shell which clang-format-16 2>/dev/null || which clang-format 2>/dev/null) CC = $(REAL_CC) @@ -107,14 +107,14 @@ CC_WITH_CCACHE = $(CCACHE_PATH) $(CC) ifeq ($(OS_NAME),darwin) # Find LLVM ifeq ($(wildcard $(LLVM_PREFIX)),) - LLVM_PREFIX = $(shell brew --prefix llvm@16) + LLVM_PREFIX = $(shell brew --prefix llvm@17) endif ifeq ($(wildcard $(LLVM_PREFIX)),) LLVM_PREFIX = $(shell brew --prefix llvm) endif ifeq ($(wildcard $(LLVM_PREFIX)),) # This is kinda ugly, but I can't find a better way to error :( - LLVM_PREFIX = $(shell echo -e "error: Unable to find llvm. Please run 'brew install llvm@16' or set LLVM_PREFIX=/path/to/llvm") + LLVM_PREFIX = $(shell echo -e "error: Unable to find llvm. Please run 'brew install llvm@17' or set LLVM_PREFIX=/path/to/llvm") endif LDFLAGS += -L$(LLVM_PREFIX)/lib @@ -154,7 +154,7 @@ CMAKE_FLAGS_WITHOUT_RELEASE = -DCMAKE_C_COMPILER=$(CC) \ -DCMAKE_OSX_DEPLOYMENT_TARGET=$(MIN_MACOS_VERSION) \ $(CMAKE_CXX_COMPILER_LAUNCHER_FLAG) \ -DCMAKE_AR=$(AR) \ - -DCMAKE_RANLIB=$(which llvm-16-ranlib 2>/dev/null || which llvm-ranlib 2>/dev/null) + -DCMAKE_RANLIB=$(which llvm-17-ranlib 2>/dev/null || which llvm-ranlib 2>/dev/null) @@ -657,7 +657,7 @@ endif .PHONY: assert-deps assert-deps: @echo "Checking if the required utilities are available..." - @if [ $(CLANG_VERSION) -lt "15" ]; then echo -e "ERROR: clang version >=15 required, found: $(CLANG_VERSION). Install with:\n\n $(POSIX_PKG_MANAGER) install llvm@16"; exit 1; fi + @if [ $(CLANG_VERSION) -lt "15" ]; then echo -e "ERROR: clang version >=15 required, found: $(CLANG_VERSION). Install with:\n\n $(POSIX_PKG_MANAGER) install llvm@17"; exit 1; fi @cmake --version >/dev/null 2>&1 || (echo -e "ERROR: cmake is required."; exit 1) @$(PYTHON) --version >/dev/null 2>&1 || (echo -e "ERROR: python is required."; exit 1) @$(ESBUILD) --version >/dev/null 2>&1 || (echo -e "ERROR: esbuild is required."; exit 1) @@ -1266,7 +1266,8 @@ jsc-build-linux-compile-config: cmake \ -DPORT="JSCOnly" \ -DENABLE_STATIC_JSC=ON \ - -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_BUILD_TYPE=Debug \ + -DENABLE_BUN_SKIP_FAILING_ASSERTIONS=ON \ -DUSE_THIN_ARCHIVES=OFF \ -DUSE_BUN_JSC_ADDITIONS=ON \ -DENABLE_FTL_JIT=ON \ diff --git a/docs/project/building-windows.md b/docs/project/building-windows.md index 6d64edf973204f..68bdcf181e26f3 100644 --- a/docs/project/building-windows.md +++ b/docs/project/building-windows.md @@ -73,7 +73,7 @@ The Zig compiler is automatically downloaded, installed, and updated by the buil > irm https://get.scoop.sh | iex > scoop install nodejs-lts go rust nasm ruby perl # scoop seems to be buggy if you install llvm and the rest at the same time -> scoop llvm@16.0.4 +> scoop llvm@17.0.6 ``` If you intend on building WebKit locally (optional), you should install these packages: diff --git a/docs/project/contributing.md b/docs/project/contributing.md index ed798029ca1dd8..299f0dd6ce6193 100644 --- a/docs/project/contributing.md +++ b/docs/project/contributing.md @@ -58,7 +58,7 @@ Bun requires LLVM 16 and Clang 16 (`clang` is part of LLVM). This version requir {% codetabs %} ```bash#macOS (Homebrew) -$ brew install llvm@16 +$ brew install llvm@17 ``` ```bash#Ubuntu/Debian @@ -82,12 +82,12 @@ $ sudo zypper install clang16 lld16 llvm16 {% /codetabs %} -If none of the above solutions apply, you will have to install it [manually](https://github.com/llvm/llvm-project/releases/tag/llvmorg-16.0.6). +If none of the above solutions apply, you will have to install it [manually](https://github.com/llvm/llvm-project/releases/tag/llvmorg-17.0.6). Make sure LLVM 16 is in your path: ```bash -$ which clang-16 +$ which clang-17 ``` If not, run this to manually link it: @@ -96,7 +96,7 @@ If not, run this to manually link it: ```bash#macOS (Homebrew) # use fish_add_path if you're using fish -$ export PATH="$(brew --prefix llvm@16)/bin:$PATH" +$ export PATH="$(brew --prefix llvm@17)/bin:$PATH" ``` ```bash#Arch @@ -262,7 +262,7 @@ The issue may manifest when initially running `bun setup` as Clang being unable ``` The C++ compiler - "/usr/bin/clang++-16" + "/usr/bin/clang++-17" is not able to compile a simple test program. ``` diff --git a/packages/bun-usockets/src/crypto/openssl.c b/packages/bun-usockets/src/crypto/openssl.c index 9f502ecb6044ba..3be9b950ad27a7 100644 --- a/packages/bun-usockets/src/crypto/openssl.c +++ b/packages/bun-usockets/src/crypto/openssl.c @@ -257,7 +257,6 @@ void us_internal_on_ssl_handshake( struct us_internal_ssl_socket_t * us_internal_ssl_socket_close(struct us_internal_ssl_socket_t *s, int code, void *reason) { - if (s->handshake_state != HANDSHAKE_COMPLETED) { // if we have some pending handshake we cancel it and try to check the // latest handshake error this way we will always call on_handshake with the diff --git a/scripts/env.sh b/scripts/env.sh index e6df269a9f4c7a..bdb6dee54121f7 100755 --- a/scripts/env.sh +++ b/scripts/env.sh @@ -7,8 +7,8 @@ export BUN_DEPS_DIR=${BUN_DEPS_DIR:-$BUN_BASE_DIR/src/deps/} export BUN_DEPS_OUT_DIR=${BUN_DEPS_OUT_DIR:-$BUN_BASE_DIR/src/deps/} # this compiler detection could be better -export CC=${CC:-$(which clang-16 || which clang || which cc)} -export CXX=${CXX:-$(which clang++-16 || which clang++ || which c++)} +export CC=${CC:-$(which clang-17 || which clang || which cc)} +export CXX=${CXX:-$(which clang++-17 || which clang++ || which c++)} export AR=${AR:-$(which llvm-ar || which ar)} export CPUS=${CPUS:-$(nproc || sysctl -n hw.ncpu || echo 1)} @@ -16,7 +16,7 @@ export CMAKE_CXX_COMPILER=${CXX} export CMAKE_C_COMPILER=${CC} export CFLAGS='-O3 -fno-exceptions -fvisibility=hidden -fvisibility-inlines-hidden' -export CXXFLAGS='-O3 -fno-exceptions -fvisibility=hidden -fvisibility-inlines-hidden' +export CXXFLAGS='-O3 -fno-exceptions -fno-rtti -fvisibility=hidden -fvisibility-inlines-hidden' export CMAKE_FLAGS=( -DCMAKE_C_COMPILER="${CC}" @@ -24,14 +24,19 @@ export CMAKE_FLAGS=( -DCMAKE_C_FLAGS="$CFLAGS" -DCMAKE_CXX_FLAGS="$CXXFLAGS" -DCMAKE_BUILD_TYPE=Release + -DCMAKE_CXX_STANDARD=20 + -DCMAKE_C_STANDARD=17 + -DCMAKE_CXX_STANDARD_REQUIRED=ON + -DCMAKE_C_STANDARD_REQUIRED=ON ) +if [[ $(uname -s) == 'Linux' ]]; then + # Ensure we always use -std=gnu++20 on Linux + export CMAKE_FLAGS+=( -DCMAKE_CXX_EXTENSIONS=ON ) +fi + if [[ $(uname -s) == 'Darwin' ]]; then - if ! [[ $(uname -m) == 'arm64' ]]; then - export CMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET:-10.14} - else - export CMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET:-11.0} - fi + export CMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET:-12.0} CMAKE_FLAGS+=(-DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}) export CFLAGS="$CFLAGS -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}" diff --git a/scripts/setup.sh b/scripts/setup.sh index fb57795fc0a7c0..91d6db6b0bc338 100755 --- a/scripts/setup.sh +++ b/scripts/setup.sh @@ -15,12 +15,12 @@ fail() { printf "${C_RED}setup error${C_RESET}: %s\n" "$@" } -LLVM_VERSION=16 +LLVM_VERSION=17 # this compiler detection could be better # it is copy pasted from ./env.sh -CC=${CC:-$(which clang-16 || which clang || which cc)} -CXX=${CXX:-$(which clang++-16 || which clang++ || which c++)} +CC=${CC:-$(which clang-17 || which clang || which cc)} +CXX=${CXX:-$(which clang++-17 || which clang++ || which c++)} test -n "$CC" || fail "missing LLVM $LLVM_VERSION (could not find clang)" test -n "$CXX" || fail "missing LLVM $LLVM_VERSION (could not find clang++)" diff --git a/src/bun.js/ConsoleObject.zig b/src/bun.js/ConsoleObject.zig index cb723aba418472..df7dfaaa81fea4 100644 --- a/src/bun.js/ConsoleObject.zig +++ b/src/bun.js/ConsoleObject.zig @@ -350,7 +350,7 @@ const TablePrinter = struct { var cols_iter = JSC.JSPropertyIterator(.{ .skip_empty_name = false, .include_value = true, - }).init(this.globalObject, row_value.asObjectRef()); + }).init(this.globalObject, row_value); defer cols_iter.deinit(); while (cols_iter.next()) |col_key| { @@ -524,7 +524,7 @@ const TablePrinter = struct { var rows_iter = JSC.JSPropertyIterator(.{ .skip_empty_name = false, .include_value = true, - }).init(globalObject, this.tabular_data.asObjectRef()); + }).init(globalObject, this.tabular_data); defer rows_iter.deinit(); while (rows_iter.next()) |row_key| { @@ -597,7 +597,7 @@ const TablePrinter = struct { var rows_iter = JSC.JSPropertyIterator(.{ .skip_empty_name = false, .include_value = true, - }).init(globalObject, this.tabular_data.asObjectRef()); + }).init(globalObject, this.tabular_data); defer rows_iter.deinit(); while (rows_iter.next()) |row_key| { @@ -1043,8 +1043,6 @@ pub const Formatter = struct { .cell = js_type, }; - // Cell is the "unknown" type - // if we call JSObjectGetPrivate, it can segfault if (js_type == .Cell) { return .{ .tag = .{ .NativeCode = {} }, @@ -2724,7 +2722,7 @@ pub const Formatter = struct { .skip_empty_name = true, .include_value = true, - }).init(this.globalThis, props.asObjectRef()); + }).init(this.globalThis, props); defer props_iter.deinit(); const children_prop = props.get(this.globalThis, "children"); diff --git a/src/bun.js/WebKit b/src/bun.js/WebKit index e3a2d89a0b1644..590f9c4019bf8c 160000 --- a/src/bun.js/WebKit +++ b/src/bun.js/WebKit @@ -1 +1 @@ -Subproject commit e3a2d89a0b1644cc8d5c245bd2ffee4d4bd6c1d5 +Subproject commit 590f9c4019bf8c29ce3187c12ef52892a65e18d9 diff --git a/src/bun.js/api/JSBundler.zig b/src/bun.js/api/JSBundler.zig index 96260ae481fbd7..259abc90665dd7 100644 --- a/src/bun.js/api/JSBundler.zig +++ b/src/bun.js/api/JSBundler.zig @@ -390,7 +390,7 @@ pub const JSBundler = struct { var define_iter = JSC.JSPropertyIterator(.{ .skip_empty_name = true, .include_value = true, - }).init(globalThis, define.asObjectRef()); + }).init(globalThis, define); defer define_iter.deinit(); while (define_iter.next()) |prop| { @@ -423,7 +423,7 @@ pub const JSBundler = struct { var loader_iter = JSC.JSPropertyIterator(.{ .skip_empty_name = true, .include_value = true, - }).init(globalThis, loaders.asObjectRef()); + }).init(globalThis, loaders); defer loader_iter.deinit(); var loader_names = try allocator.alloc(string, loader_iter.len); @@ -432,7 +432,7 @@ pub const JSBundler = struct { errdefer allocator.free(loader_values); while (loader_iter.next()) |prop| { - if (!prop.hasPrefixChar('.') or prop.len < 2) { + if (!prop.hasPrefixComptime(".") or prop.length() < 2) { globalThis.throwInvalidArguments("loader property names must be file extensions, such as '.txt'", .{}); return error.JSException; } diff --git a/src/bun.js/api/JSTranspiler.zig b/src/bun.js/api/JSTranspiler.zig index 60e8cf4125464d..1af8219933118c 100644 --- a/src/bun.js/api/JSTranspiler.zig +++ b/src/bun.js/api/JSTranspiler.zig @@ -343,7 +343,7 @@ fn transformOptionsFromJSC(globalObject: JSC.C.JSContextRef, temp_allocator: std .skip_empty_name = true, .include_value = true, - }).init(globalThis, define.asObjectRef()); + }).init(globalThis, define); defer define_iter.deinit(); // cannot be a temporary because it may be loaded on different threads. @@ -657,7 +657,7 @@ fn transformOptionsFromJSC(globalObject: JSC.C.JSContextRef, temp_allocator: std var iter = JSC.JSPropertyIterator(.{ .skip_empty_name = true, .include_value = true, - }).init(globalThis, replace.asObjectRef()); + }).init(globalThis, replace); if (iter.len > 0) { errdefer iter.deinit(); @@ -1196,7 +1196,7 @@ pub fn transformSync( fn namedExportsToJS(global: *JSGlobalObject, named_exports: *JSAst.Ast.NamedExports) JSC.JSValue { if (named_exports.count() == 0) - return JSC.JSValue.fromRef(JSC.C.JSObjectMakeArray(global, 0, null, null)); + return JSValue.createEmptyArray(global, 0); var named_exports_iter = named_exports.iterator(); var stack_fallback = std.heap.stackFallback(@sizeOf(bun.String) * 32, getAllocator(global)); diff --git a/src/bun.js/api/bun/h2_frame_parser.zig b/src/bun.js/api/bun/h2_frame_parser.zig index ab87adb8d7f5d1..e6815f0ad88006 100644 --- a/src/bun.js/api/bun/h2_frame_parser.zig +++ b/src/bun.js/api/bun/h2_frame_parser.zig @@ -1981,16 +1981,15 @@ pub const H2FrameParser = struct { var encoded_size: usize = 0; - const headers_obj = headers_arg.asObjectRef(); var iter = JSC.JSPropertyIterator(.{ .skip_empty_name = false, .include_value = true, - }).init(globalObject, headers_obj); + }).init(globalObject, headers_arg); defer iter.deinit(); // TODO: support CONTINUE for more headers if headers are too big while (iter.next()) |header_name| { - const name_slice = header_name.toSlice(bun.default_allocator); + const name_slice = header_name.toUTF8(bun.default_allocator); defer name_slice.deinit(); const name = name_slice.slice(); @@ -2182,19 +2181,17 @@ pub const H2FrameParser = struct { return JSC.JSValue.jsNumber(-1); } - const headers_obj = headers_arg.asObjectRef(); - // we iterate twice, because pseudo headers must be sent first, but can appear anywhere in the headers object var iter = JSC.JSPropertyIterator(.{ .skip_empty_name = false, .include_value = true, - }).init(globalObject, headers_obj); + }).init(globalObject, headers_arg); defer iter.deinit(); for (0..2) |ignore_pseudo_headers| { iter.reset(); while (iter.next()) |header_name| { - const name_slice = header_name.toSlice(bun.default_allocator); + const name_slice = header_name.toUTF8(bun.default_allocator); defer name_slice.deinit(); const name = name_slice.slice(); diff --git a/src/bun.js/api/bun/subprocess.zig b/src/bun.js/api/bun/subprocess.zig index 4a9ae15ad78069..643e7239ea3b05 100644 --- a/src/bun.js/api/bun/subprocess.zig +++ b/src/bun.js/api/bun/subprocess.zig @@ -127,6 +127,30 @@ pub const ResourceUsage = struct { } }; +pub fn appendEnvpFromJS(globalThis: *JSC.JSGlobalObject, object: JSC.JSValue, envp: *std.ArrayList(?[*:0]const u8), PATH: *[]const u8) !void { + var object_iter = JSC.JSPropertyIterator(.{ + .skip_empty_name = false, + .include_value = true, + }).init(globalThis, object); + defer object_iter.deinit(); + try envp.ensureTotalCapacityPrecise(object_iter.len + + // +1 incase there's IPC + // +1 for null terminator + 2); + while (object_iter.next()) |key| { + var value = object_iter.value; + if (value == .undefined) continue; + + var line = try std.fmt.allocPrintZ(envp.allocator, "{}={}", .{ key, value.getZigString(globalThis) }); + + if (key.eqlComptime("PATH")) { + PATH.* = bun.asByteSlice(line["PATH=".len..]); + } + + try envp.append(line); + } +} + pub const Subprocess = struct { const log = Output.scoped(.Subprocess, false); pub usingnamespace JSC.Codegen.JSSubprocess; @@ -1762,40 +1786,14 @@ pub const Subprocess = struct { } override_env = true; - var object_iter = JSC.JSPropertyIterator(.{ - .skip_empty_name = false, - .include_value = true, - }).init(globalThis, object.asObjectRef()); - defer object_iter.deinit(); - env_array.ensureTotalCapacityPrecise(allocator, object_iter.len + - // +1 incase there's IPC - // +1 for null terminator - 2) catch { + // If the env object does not include a $PATH, it must disable path lookup for argv[0] + PATH = ""; + var envp_managed = env_array.toManaged(allocator); + appendEnvpFromJS(globalThis, object, &envp_managed, &PATH) catch { globalThis.throwOutOfMemory(); return .zero; }; - - // If the env object does not include a $PATH, it must disable path lookup for argv[0] - PATH = ""; - - while (object_iter.next()) |key| { - var value = object_iter.value; - if (value == .undefined) continue; - - var line = std.fmt.allocPrintZ(allocator, "{}={}", .{ key, value.getZigString(globalThis) }) catch { - globalThis.throwOutOfMemory(); - return .zero; - }; - - if (key.eqlComptime("PATH")) { - PATH = bun.asByteSlice(line["PATH=".len..]); - } - - env_array.append(allocator, line) catch { - globalThis.throwOutOfMemory(); - return .zero; - }; - } + env_array = envp_managed.moveToUnmanaged(); } if (args.get(globalThis, "stdio")) |stdio_val| { diff --git a/src/bun.js/api/ffi.zig b/src/bun.js/api/ffi.zig index a910238d7c0005..667aa251fa1349 100644 --- a/src/bun.js/api/ffi.zig +++ b/src/bun.js/api/ffi.zig @@ -620,7 +620,7 @@ pub const FFI = struct { .skip_empty_name = true, .include_value = true, - }).init(global, object.asObjectRef()); + }).init(global, object); defer symbols_iter.deinit(); try symbols.ensureTotalCapacity(allocator, symbols_iter.len); diff --git a/src/bun.js/bindings/BunString.cpp b/src/bun.js/bindings/BunString.cpp index c50308a9693f90..7e10ff1ef6c9eb 100644 --- a/src/bun.js/bindings/BunString.cpp +++ b/src/bun.js/bindings/BunString.cpp @@ -1,6 +1,11 @@ + #include "root.h" #include "headers-handwritten.h" #include + +#include "JavaScriptCore/JSCJSValue.h" +#include "JavaScriptCore/PutPropertySlot.h" + #include "simdutf.h" #include "JSDOMURL.h" #include "DOMURL.h" @@ -36,7 +41,7 @@ extern "C" BunString BunString__fromBytes(const char* bytes, size_t length); extern "C" bool Bun__WTFStringImpl__hasPrefix(const WTF::StringImpl* impl, const char* bytes, size_t length) { - return impl->startsWith(bytes, length); + return impl->startsWith({ bytes, length }); } extern "C" void Bun__WTFStringImpl__deref(WTF::StringImpl* impl) @@ -58,7 +63,7 @@ extern "C" bool BunString__fromJS(JSC::JSGlobalObject* globalObject, JSC::Encode extern "C" BunString BunString__createAtom(const char* bytes, size_t length) { ASSERT(simdutf::validate_ascii(bytes, length)); - auto atom = tryMakeAtomString(String(StringImpl::createWithoutCopying(bytes, length))); + auto atom = tryMakeAtomString(String(StringImpl::createWithoutCopying({ bytes, length }))); atom.impl()->ref(); return { BunStringTag::WTFStringImpl, { .wtf = atom.impl() } }; } @@ -66,7 +71,7 @@ extern "C" BunString BunString__createAtom(const char* bytes, size_t length) extern "C" BunString BunString__tryCreateAtom(const char* bytes, size_t length) { if (simdutf::validate_ascii(bytes, length)) { - auto atom = tryMakeAtomString(String(StringImpl::createWithoutCopying(bytes, length))); + auto atom = tryMakeAtomString(String(StringImpl::createWithoutCopying({ bytes, length }))); if (atom.isNull()) return { BunStringTag::Dead, {} }; atom.impl()->ref(); @@ -271,9 +276,9 @@ extern "C" BunString BunString__fromBytes(const char* bytes, size_t length) extern "C" BunString BunString__createExternal(const char* bytes, size_t length, bool isLatin1, void* ctx, void (*callback)(void* arg0, void* arg1, size_t arg2)) { - Ref impl = isLatin1 ? WTF::ExternalStringImpl::create(reinterpret_cast(bytes), length, ctx, callback) : + Ref impl = isLatin1 ? WTF::ExternalStringImpl::create({ reinterpret_cast(bytes), length }, ctx, callback) : - WTF::ExternalStringImpl::create(reinterpret_cast(bytes), length, ctx, callback); + WTF::ExternalStringImpl::create({ reinterpret_cast(bytes), length }, ctx, callback); return { BunStringTag::WTFStringImpl, { .wtf = &impl.leakRef() } }; } @@ -532,7 +537,7 @@ extern "C" BunString BunString__createExternalGloballyAllocatedLatin1( size_t length) { ASSERT(length > 0); - Ref impl = WTF::ExternalStringImpl::create(bytes, length, nullptr, [](void*, void* ptr, size_t) { + Ref impl = WTF::ExternalStringImpl::create({ bytes, length }, nullptr, [](void*, void* ptr, size_t) { mi_free(ptr); }); return { BunStringTag::WTFStringImpl, { .wtf = &impl.leakRef() } }; @@ -543,7 +548,7 @@ extern "C" BunString BunString__createExternalGloballyAllocatedUTF16( size_t length) { ASSERT(length > 0); - Ref impl = WTF::ExternalStringImpl::create(bytes, length, nullptr, [](void*, void* ptr, size_t) { + Ref impl = WTF::ExternalStringImpl::create({ bytes, length }, nullptr, [](void*, void* ptr, size_t) { mi_free(ptr); }); return { BunStringTag::WTFStringImpl, { .wtf = &impl.leakRef() } }; @@ -565,4 +570,18 @@ extern "C" bool WTFStringImpl__isThreadSafe( extern "C" void Bun__WTFStringImpl__ensureHash(WTF::StringImpl* str) { str->hash(); +} + +extern "C" void JSC__JSValue__putBunString( + JSC::EncodedJSValue encodedTarget, + JSC::JSGlobalObject* global, + const BunString* key, + JSC::EncodedJSValue encodedValue) +{ + JSC::JSObject* target = JSC::JSValue::decode(encodedTarget).getObject(); + JSC::JSValue value = JSC::JSValue::decode(encodedValue); + auto& vm = global->vm(); + WTF::String str = key->toWTFString(); + Identifier id = Identifier::fromString(vm, str); + target->putDirect(vm, id, value, 0); } \ No newline at end of file diff --git a/src/bun.js/bindings/JSPropertyIterator.cpp b/src/bun.js/bindings/JSPropertyIterator.cpp new file mode 100644 index 00000000000000..4b3afe30023975 --- /dev/null +++ b/src/bun.js/bindings/JSPropertyIterator.cpp @@ -0,0 +1,78 @@ + + +#include "root.h" + +#include "JavaScriptCore/EnumerationMode.h" +#include "JavaScriptCore/ExceptionScope.h" +#include "JavaScriptCore/ThrowScope.h" +#include "JavaScriptCore/JSCJSValue.h" +#include "JavaScriptCore/JSGlobalObject.h" +#include "JavaScriptCore/PropertyNameArray.h" +#include "wtf/FastMalloc.h" +#include "headers-handwritten.h" + +namespace Bun { +using namespace JSC; + +class JSPropertyIterator { +public: + JSPropertyIterator(JSC::VM& m_vm, RefPtr m_properties) + : vm(m_vm) + , properties(m_properties) + { + } + + RefPtr properties; + JSC::VM& vm; + static JSPropertyIterator* create(JSC::VM& vm, RefPtr data) + { + return new JSPropertyIterator(vm, data); + } + + WTF_MAKE_FAST_ALLOCATED; +}; + +extern "C" JSPropertyIterator* Bun__JSPropertyIterator__create(JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue encodedValue, size_t* count) +{ + JSC::VM& vm = globalObject->vm(); + JSC::JSValue value = JSValue::decode(encodedValue); + JSC::JSObject* object = value.getObject(); + + auto scope = DECLARE_THROW_SCOPE(vm); + JSC::PropertyNameArray array(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude); + object->getPropertyNames(globalObject, array, DontEnumPropertiesMode::Exclude); + RETURN_IF_EXCEPTION(scope, nullptr); + + *count = array.size(); + if (array.size() == 0) { + return nullptr; + } + + return JSPropertyIterator::create(vm, array.releaseData()); +} + +extern "C" EncodedJSValue Bun__JSPropertyIterator__getNameAndValue(JSPropertyIterator* iter, JSC::JSGlobalObject* globalObject, JSC::JSObject* object, BunString* propertyName, size_t i) +{ + const auto& prop = iter->properties->propertyNameVector()[i]; + + auto scope = DECLARE_THROW_SCOPE(iter->vm); + JSValue result = object->get(globalObject, prop); + + RETURN_IF_EXCEPTION(scope, {}); + + *propertyName = Bun::toString(prop.impl()); + return JSValue::encode(result); +} + +extern "C" void Bun__JSPropertyIterator__getName(JSPropertyIterator* iter, BunString* propertyName, size_t i) +{ + const auto& prop = iter->properties->propertyNameVector()[i]; + *propertyName = Bun::toString(prop.impl()); +} + +extern "C" void Bun__JSPropertyIterator__deinit(JSPropertyIterator* iter) +{ + delete iter; +} + +} \ No newline at end of file diff --git a/src/bun.js/bindings/JSPropertyIterator.zig b/src/bun.js/bindings/JSPropertyIterator.zig new file mode 100644 index 00000000000000..c7079d2a1bcb9a --- /dev/null +++ b/src/bun.js/bindings/JSPropertyIterator.zig @@ -0,0 +1,82 @@ +const bun = @import("root").bun; +const JSC = bun.JSC; + +//extern "C" EncodedJSValue Bun__JSPropertyIterator__getNameAndValue(JSPropertyIterator* iter, JSC::JSGlobalObject* globalObject, JSC::JSObject* object, BunString* propertyName, size_t i) +extern "C" fn Bun__JSPropertyIterator__create(globalObject: *JSC.JSGlobalObject, encodedValue: JSC.JSValue, *usize) ?*anyopaque; +extern "C" fn Bun__JSPropertyIterator__getNameAndValue(iter: ?*anyopaque, globalObject: *JSC.JSGlobalObject, object: *anyopaque, propertyName: *bun.String, i: usize) JSC.JSValue; +extern "C" fn Bun__JSPropertyIterator__getName(iter: ?*anyopaque, propertyName: *bun.String, i: usize) void; +extern "C" fn Bun__JSPropertyIterator__deinit(iter: ?*anyopaque) void; + +pub const JSPropertyIteratorOptions = struct { + skip_empty_name: bool, + include_value: bool, +}; + +pub fn JSPropertyIterator(comptime options: JSPropertyIteratorOptions) type { + return struct { + len: usize = 0, + i: u32 = 0, + iter_i: u32 = 0, + impl: ?*anyopaque = null, + + globalObject: *JSC.JSGlobalObject, + object: *JSC.JSCell = undefined, + value: JSC.JSValue = .zero, + + pub fn deinit(this: *@This()) void { + if (this.impl) |impl| { + Bun__JSPropertyIterator__deinit(impl); + } + this.* = undefined; + } + + pub fn init(globalObject: *JSC.JSGlobalObject, object: JSC.JSValue) @This() { + var iter = @This(){ + .object = object.asCell(), + .globalObject = globalObject, + }; + + iter.impl = Bun__JSPropertyIterator__create(globalObject, object, &iter.len); + return iter; + } + + pub fn reset(this: *@This()) void { + this.iter_i = 0; + this.i = 0; + } + + /// The bun.String returned has not incremented it's reference count. + pub fn next(this: *@This()) ?bun.String { + const i: usize = this.iter_i; + if (i >= this.len) { + return null; + } + + this.i = this.iter_i; + this.iter_i += 1; + var name = bun.String.dead; + if (comptime options.include_value) { + const current = Bun__JSPropertyIterator__getNameAndValue(this.impl, this.globalObject, this.object, &name, i); + if (current.isEmpty()) { + return null; + } + current.ensureStillAlive(); + this.value = current; + } else { + Bun__JSPropertyIterator__getName(this.impl, &name, i); + } + + if (name.tag == .Dead) { + return null; + } + + if (comptime options.skip_empty_name) { + if (name.isEmpty()) { + return null; + } + } + + return name; + } + }; +} diff --git a/src/bun.js/bindings/JSWrappingFunction.cpp b/src/bun.js/bindings/JSWrappingFunction.cpp index d22ea41ccf5eae..c4294a0f0fd167 100644 --- a/src/bun.js/bindings/JSWrappingFunction.cpp +++ b/src/bun.js/bindings/JSWrappingFunction.cpp @@ -20,21 +20,22 @@ const ClassInfo JSWrappingFunction::s_info = { "Function"_s, &Base::s_info, null JS_EXPORT_PRIVATE JSWrappingFunction* JSWrappingFunction::create( VM& vm, Zig::GlobalObject* globalObject, - const ZigString* symbolName, + const BunString* symbolName, Zig::NativeFunctionPtr functionPointer, JSC::JSValue wrappedFnValue) { JSC::JSFunction* wrappedFn = jsCast(wrappedFnValue.asCell()); ASSERT(wrappedFn != nullptr); - auto name = Zig::toStringCopy(*symbolName); - NativeExecutable* executable = vm.getHostFunction(functionPointer, ImplementationVisibility::Public, nullptr, name); + auto nameStr = symbolName->toWTFString(); + auto name = Identifier::fromString(vm, nameStr); + NativeExecutable* executable = vm.getHostFunction(functionPointer, ImplementationVisibility::Public, nullptr, nameStr); // Structure* structure = globalObject->FFIFunctionStructure(); Structure* structure = JSWrappingFunction::createStructure(vm, globalObject, globalObject->objectPrototype()); JSWrappingFunction* function = new (NotNull, allocateCell(vm)) JSWrappingFunction(vm, executable, globalObject, structure); ASSERT(function->structure()->globalObject()); - function->finishCreation(vm, executable, 0, name); + function->finishCreation(vm, executable, 0, nameStr); function->m_wrappedFn.set(vm, globalObject, wrappedFn); @@ -61,7 +62,7 @@ DEFINE_VISIT_CHILDREN(JSWrappingFunction); extern "C" JSC::EncodedJSValue Bun__JSWrappingFunction__create( Zig::GlobalObject* globalObject, - const ZigString* symbolName, + const BunString* symbolName, Bun::NativeFunctionPtr functionPointer, JSC::EncodedJSValue wrappedFnEncoded) { diff --git a/src/bun.js/bindings/JSWrappingFunction.h b/src/bun.js/bindings/JSWrappingFunction.h index 6507ffb59cf971..39b00f2faf228c 100644 --- a/src/bun.js/bindings/JSWrappingFunction.h +++ b/src/bun.js/bindings/JSWrappingFunction.h @@ -50,8 +50,7 @@ class JSWrappingFunction final : public JSC::JSFunction { } DECLARE_EXPORT_INFO; - - JS_EXPORT_PRIVATE static JSWrappingFunction* create(JSC::VM& vm, Zig::GlobalObject* globalObject, const ZigString* symbolName, NativeFunctionPtr functionPointer, JSC::JSValue wrappedFn); + static JSWrappingFunction* create(JSC::VM& vm, Zig::GlobalObject* globalObject, const BunString* symbolName, NativeFunctionPtr functionPointer, JSC::JSValue wrappedFn); static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype) { diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index c1bcb693198f73..073f7387a9d3ac 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -948,24 +948,6 @@ static JSGlobalObject* deriveShadowRealmGlobalObject(JSGlobalObject* globalObjec return shadow; } -extern "C" JSC__JSValue JSC__JSValue__makeWithNameAndPrototype(JSC__JSGlobalObject* globalObject, void* arg1, void* arg2, const ZigString* visibleInterfaceName) -{ - auto& vm = globalObject->vm(); - JSClassRef jsClass = reinterpret_cast(arg1); - JSClassRef protoClass = reinterpret_cast(arg2); - JSObjectRef objectRef = JSObjectMakeConstructor(reinterpret_cast(globalObject), protoClass, jsClass->callAsConstructor); - JSObjectRef wrappedRef = JSObjectMake(reinterpret_cast(globalObject), jsClass, nullptr); - JSC::JSObject* object = JSC::JSValue::decode(reinterpret_cast(objectRef)).getObject(); - JSC::JSObject* wrapped = JSC::JSValue::decode(reinterpret_cast(wrappedRef)).getObject(); - object->setPrototypeDirect(vm, wrapped); - JSString* nameString = JSC::jsNontrivialString(vm, Zig::toString(*visibleInterfaceName)); - object->putDirect(vm, vm.propertyNames->name, nameString, PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum); - object->putDirect(vm, vm.propertyNames->toStringTagSymbol, - nameString, PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly); - - return JSC::JSValue::encode(JSC::JSValue(object)); -} - extern "C" int Bun__VM__scriptExecutionStatus(void*); JSC::ScriptExecutionStatus Zig::GlobalObject::scriptExecutionStatus(JSC::JSGlobalObject* globalObject, JSC::JSObject*) { @@ -1576,7 +1558,7 @@ JSC_DEFINE_HOST_FUNCTION(functionBTOA, LChar* ptr; unsigned length = encodedString.length(); auto dest = WTF::String::createUninitialized(length, ptr); - WTF::StringImpl::copyCharacters(ptr, encodedString.characters16(), length); + WTF::StringImpl::copyCharacters(ptr, { encodedString.characters16(), length }); encodedString = WTFMove(dest); } diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index f7e77d87222f09..ae92acc6ab9411 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -1440,7 +1440,7 @@ void WebCore__FetchHeaders__copyTo(WebCore__FetchHeaders* headers, StringPointer if (name.is8Bit()) memcpy(&buf[i], name.characters8(), name.length()); else { - StringImpl::copyCharacters(&buf[i], name.characters16(), name.length()); + StringImpl::copyCharacters(&buf[i], { name.characters16(), name.length() }); } i += name.length(); @@ -1448,7 +1448,7 @@ void WebCore__FetchHeaders__copyTo(WebCore__FetchHeaders* headers, StringPointer if (value.is8Bit()) memcpy(&buf[i], value.characters8(), value.length()); else - StringImpl::copyCharacters(&buf[i], value.characters16(), value.length()); + StringImpl::copyCharacters(&buf[i], { value.characters16(), value.length() }); i += value.length(); } @@ -2423,7 +2423,7 @@ JSC__JSValue JSC__JSValue__createRangeError(const ZigString* message, const ZigS rangeError->putDirect( vm, vm.propertyNames->name, JSC::JSValue(JSC::jsOwnedString( - vm, WTF::String(WTF::StringImpl::createWithoutCopying(range_error_name, 10)))), + vm, WTF::String(WTF::StringImpl::createWithoutCopying({ range_error_name, 10 })))), 0); if (code.len > 0) { @@ -2446,7 +2446,7 @@ JSC__JSValue JSC__JSValue__createTypeError(const ZigString* message, const ZigSt typeError->putDirect( vm, vm.propertyNames->name, JSC::JSValue(JSC::jsOwnedString( - vm, WTF::String(WTF::StringImpl::createWithoutCopying(range_error_name, 9)))), + vm, WTF::String(WTF::StringImpl::createWithoutCopying({ range_error_name, 9 })))), 0); if (code.len > 0) { @@ -2723,7 +2723,7 @@ JSC__JSValue ZigString__toExternalU16(const uint16_t* arg0, size_t len, JSC__JSG return JSC::JSValue::encode(JSC::jsEmptyString(global->vm())); } - auto ref = String(ExternalStringImpl::create(reinterpret_cast(arg0), len, reinterpret_cast(const_cast(arg0)), free_global_string)); + auto ref = String(ExternalStringImpl::create({ reinterpret_cast(arg0), len }, reinterpret_cast(const_cast(arg0)), free_global_string)); return JSC::JSValue::encode(JSC::JSValue(JSC::jsString( global->vm(), WTFMove(ref)))); @@ -2738,12 +2738,12 @@ JSC__JSValue ZigString__toExternalValue(const ZigString* arg0, JSC__JSGlobalObje } if (Zig::isTaggedUTF16Ptr(str.ptr)) { - auto ref = String(ExternalStringImpl::create(reinterpret_cast(Zig::untag(str.ptr)), str.len, Zig::untagVoid(str.ptr), free_global_string)); + auto ref = String(ExternalStringImpl::create({ reinterpret_cast(Zig::untag(str.ptr)), str.len }, Zig::untagVoid(str.ptr), free_global_string)); return JSC::JSValue::encode(JSC::JSValue(JSC::jsString( arg1->vm(), WTFMove(ref)))); } else { - auto ref = String(ExternalStringImpl::create(Zig::untag(str.ptr), str.len, Zig::untagVoid(str.ptr), free_global_string)); + auto ref = String(ExternalStringImpl::create({ Zig::untag(str.ptr), str.len }, Zig::untagVoid(str.ptr), free_global_string)); return JSC::JSValue::encode(JSC::JSValue(JSC::jsString( arg1->vm(), WTFMove(ref)))); @@ -2796,11 +2796,11 @@ JSC__JSValue ZigString__external(const ZigString* arg0, JSC__JSGlobalObject* arg if (Zig::isTaggedUTF16Ptr(str.ptr)) { return JSC::JSValue::encode(JSC::JSValue(JSC::jsString( arg1->vm(), - WTF::String(ExternalStringImpl::create(reinterpret_cast(Zig::untag(str.ptr)), str.len, arg2, ArgFn3))))); + WTF::String(ExternalStringImpl::create({ reinterpret_cast(Zig::untag(str.ptr)), str.len }, arg2, ArgFn3))))); } else { return JSC::JSValue::encode(JSC::JSValue(JSC::jsString( arg1->vm(), - WTF::String(ExternalStringImpl::create(reinterpret_cast(Zig::untag(str.ptr)), str.len, arg2, ArgFn3))))); + WTF::String(ExternalStringImpl::create({ reinterpret_cast(Zig::untag(str.ptr)), str.len }, arg2, ArgFn3))))); } } @@ -2812,11 +2812,11 @@ JSC__JSValue ZigString__toExternalValueWithCallback(const ZigString* arg0, JSC__ if (Zig::isTaggedUTF16Ptr(str.ptr)) { return JSC::JSValue::encode(JSC::JSValue(JSC::jsOwnedString( arg1->vm(), - WTF::String(ExternalStringImpl::create(reinterpret_cast(Zig::untag(str.ptr)), str.len, nullptr, ArgFn2))))); + WTF::String(ExternalStringImpl::create({ reinterpret_cast(Zig::untag(str.ptr)), str.len }, nullptr, ArgFn2))))); } else { return JSC::JSValue::encode(JSC::JSValue(JSC::jsOwnedString( arg1->vm(), - WTF::String(ExternalStringImpl::create(reinterpret_cast(Zig::untag(str.ptr)), str.len, nullptr, ArgFn2))))); + WTF::String(ExternalStringImpl::create({ reinterpret_cast(Zig::untag(str.ptr)), str.len }, nullptr, ArgFn2))))); } } @@ -3534,7 +3534,7 @@ JSC__JSValue JSC__JSValue__getIfPropertyExistsImpl(JSC__JSValue JSValue0, JSC::VM& vm = globalObject->vm(); JSC::JSObject* object = value.getObject(); - auto identifier = JSC::Identifier::fromString(vm, String(StringImpl::createWithoutCopying(arg1, arg2))); + auto identifier = JSC::Identifier::fromString(vm, String(StringImpl::createWithoutCopying({ arg1, arg2 }))); auto property = JSC::PropertyName(identifier); return JSC::JSValue::encode(object->getIfPropertyExists(globalObject, property)); diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig index a00235d193da26..51a754fd33a0e5 100644 --- a/src/bun.js/bindings/bindings.zig +++ b/src/bun.js/bindings/bindings.zig @@ -3757,11 +3757,38 @@ pub const JSValue = enum(JSValueReprInt) { return cppFn("putRecord", .{ value, global, key, values, values_len }); } - /// Note: key can't be numeric (if so, use putMayBeIndex instead) - pub fn put(value: JSValue, global: *JSGlobalObject, key: *const ZigString, result: JSC.JSValue) void { - return cppFn("put", .{ value, global, key, result }); + fn putZigString(value: JSValue, global: *JSGlobalObject, key: *const ZigString, result: JSC.JSValue) void { + @import("./headers.zig").JSC__JSValue__put(value, global, key, result); + } + + extern "C" fn JSC__JSValue__putBunString(value: JSValue, global: *JSGlobalObject, key: *const bun.String, result: JSC.JSValue) void; + fn putBunString(value: JSValue, global: *JSGlobalObject, key: *const bun.String, result: JSC.JSValue) void { + if (comptime bun.Environment.isDebug) + JSC.markBinding(@src()); + JSC__JSValue__putBunString(value, global, key, result); } + pub fn put(value: JSValue, global: *JSGlobalObject, key: anytype, result: JSC.JSValue) void { + const Key = @TypeOf(key); + if (comptime @typeInfo(Key) == .Pointer) { + const Elem = @typeInfo(Key).Pointer.child; + if (Elem == ZigString) { + putZigString(value, global, key, result); + } else if (Elem == bun.String) { + putBunString(value, global, key, result); + } else { + @compileError("Unsupported key type in put(). Expected ZigString or bun.String, got " ++ @typeName(Elem)); + } + } else if (comptime Key == ZigString) { + putZigString(value, global, &key, result); + } else if (comptime Key == bun.String) { + putBunString(value, global, &key, result); + } else { + @compileError("Unsupported key type in put(). Expected ZigString or bun.String, got " ++ @typeName(Key)); + } + } + + /// Note: key can't be numeric (if so, use putMayBeIndex instead) extern fn JSC__JSValue__putMayBeIndex(target: JSValue, globalObject: *JSGlobalObject, key: *const String, value: JSC.JSValue) void; /// Same as `.put` but accepts both non-numeric and numeric keys. @@ -3878,10 +3905,6 @@ pub const JSValue = enum(JSValueReprInt) { return cppFn("getErrorsProperty", .{ this, globalObject }); } - pub fn makeWithNameAndPrototype(globalObject: *JSGlobalObject, class: ?*anyopaque, instance: ?*anyopaque, name_: *const ZigString) JSValue { - return cppFn("makeWithNameAndPrototype", .{ globalObject, class, instance, name_ }); - } - pub fn createBufferFromLength(globalObject: *JSGlobalObject, len: usize) JSValue { JSC.markBinding(@src()); return JSBuffer__bufferFromLength(globalObject, @as(i64, @intCast(len))); @@ -5356,7 +5379,6 @@ pub const JSValue = enum(JSValueReprInt) { "jsonStringify", "keys", "kind_", - "makeWithNameAndPrototype", "parseJSON", "put", "putDirect", @@ -6193,108 +6215,7 @@ pub fn Thenable(comptime name: []const u8, comptime Then: type, comptime onResol }; } -pub const JSPropertyIteratorOptions = struct { - skip_empty_name: bool, - include_value: bool, -}; - -pub fn JSPropertyIterator(comptime options: JSPropertyIteratorOptions) type { - return struct { - /// Position in the property list array - /// Update is deferred until the next iteration - i: u32 = 0, - - iter_i: u32 = 0, - len: u32, - array_ref: JSC.C.JSPropertyNameArrayRef, - - /// The `JSValue` of the current property. - /// - /// Invokes undefined behavior if an iteration has not yet occurred and - /// zero-sized when `options.include_value` is not enabled. - value: if (options.include_value) JSC.JSValue else void, - /// Zero-sized when `options.include_value` is not enabled. - object: if (options.include_value) JSC.C.JSObjectRef else void, - /// Zero-sized when `options.include_value` is not enabled. - global: if (options.include_value) JSC.C.JSContextRef else void, - - const Self = @This(); - - inline fn initInternal(global: JSC.C.JSContextRef, object: JSC.C.JSObjectRef) Self { - const array_ref = JSC.C.JSObjectCopyPropertyNames(global, object); - return .{ - .array_ref = array_ref, - .len = @as(u32, @truncate(JSC.C.JSPropertyNameArrayGetCount(array_ref))), - .object = if (comptime options.include_value) object else .{}, - .global = if (comptime options.include_value) global else .{}, - .value = undefined, - }; - } - - /// Initializes the iterator. Make sure you `deinit()` it! - /// - /// Not recommended for use when using the CString buffer mode as the - /// buffer must be manually initialized. Instead, see - /// `JSPropertyIterator.initCStringBuffer()`. - pub inline fn init(global: JSC.C.JSContextRef, object: JSC.C.JSObjectRef) Self { - return Self.initInternal(global, object); - } - - /// Deinitializes the property name array and all of the string - /// references constructed by the copy. - pub inline fn deinit(self: *Self) void { - JSC.C.JSPropertyNameArrayRelease(self.array_ref); - } - - pub fn hasLongNames(self: *Self) bool { - var estimated_length: usize = 0; - for (self.i..self.len) |i| { - estimated_length += JSC.C.JSStringGetLength(JSC.C.JSPropertyNameArrayGetNameAtIndex(self.array_ref, i)); - if (estimated_length > 14) return true; - } - return false; - } - - /// Finds the next property string and, if `options.include_value` is - /// enabled, updates the `iter.value` to respect the latest property's - /// value. Also note the behavior of the other options. - pub fn next(self: *Self) ?ZigString { - return nextMaybeFirstValue(self, .zero); - } - - pub fn reset(self: *Self) void { - self.iter_i = 0; - self.i = 0; - } - - pub fn nextMaybeFirstValue(self: *Self, first_value: JSValue) ?ZigString { - if (self.iter_i >= self.len) { - self.i = self.iter_i; - return null; - } - self.i = self.iter_i; - var property_name_ref = JSC.C.JSPropertyNameArrayGetNameAtIndex(self.array_ref, self.iter_i); - self.iter_i += 1; - - if (comptime options.skip_empty_name) { - const len = JSC.C.JSStringGetLength(property_name_ref); - if (len == 0) return self.next(); - } - - const prop = property_name_ref.toZigString(); - - if (comptime options.include_value) { - if (self.i == 0 and first_value != .zero) { - self.value = first_value; - } else { - self.value = JSC.JSValue.fromRef(JSC.C.JSObjectGetProperty(self.global, self.object, property_name_ref, null)); - } - } - - return prop; - } - }; -} +pub usingnamespace @import("./JSPropertyIterator.zig"); // DOMCall Fields const Bun = JSC.API.Bun; diff --git a/src/bun.js/bindings/headers.h b/src/bun.js/bindings/headers.h index efd6b3e6bce16c..8dedb14382822c 100644 --- a/src/bun.js/bindings/headers.h +++ b/src/bun.js/bindings/headers.h @@ -389,7 +389,6 @@ CPP_DECL JSC__JSValue JSC__JSValue__jsTDZValue(); CPP_DECL unsigned char JSC__JSValue__jsType(JSC__JSValue JSValue0); CPP_DECL JSC__JSValue JSC__JSValue__jsUndefined(); CPP_DECL JSC__JSValue JSC__JSValue__keys(JSC__JSGlobalObject* arg0, JSC__JSValue arg1); -CPP_DECL JSC__JSValue JSC__JSValue__makeWithNameAndPrototype(JSC__JSGlobalObject* arg0, void* arg1, void* arg2, const ZigString* arg3); CPP_DECL JSC__JSValue JSC__JSValue__parseJSON(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1); CPP_DECL void JSC__JSValue__push(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, JSC__JSValue JSValue2); CPP_DECL void JSC__JSValue__put(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, const ZigString* arg2, JSC__JSValue JSValue3); diff --git a/src/bun.js/bindings/headers.zig b/src/bun.js/bindings/headers.zig index 91015dab3dc2b9..86eea29c2be43c 100644 --- a/src/bun.js/bindings/headers.zig +++ b/src/bun.js/bindings/headers.zig @@ -286,7 +286,6 @@ pub extern fn JSC__JSValue__jsTDZValue(...) JSC__JSValue; pub extern fn JSC__JSValue__jsType(JSValue0: JSC__JSValue) u8; pub extern fn JSC__JSValue__jsUndefined(...) JSC__JSValue; pub extern fn JSC__JSValue__keys(arg0: *bindings.JSGlobalObject, arg1: JSC__JSValue) JSC__JSValue; -pub extern fn JSC__JSValue__makeWithNameAndPrototype(arg0: *bindings.JSGlobalObject, arg1: ?*anyopaque, arg2: ?*anyopaque, arg3: [*c]const ZigString) JSC__JSValue; pub extern fn JSC__JSValue__parseJSON(JSValue0: JSC__JSValue, arg1: *bindings.JSGlobalObject) JSC__JSValue; pub extern fn JSC__JSValue__push(JSValue0: JSC__JSValue, arg1: *bindings.JSGlobalObject, JSValue2: JSC__JSValue) void; pub extern fn JSC__JSValue__put(JSValue0: JSC__JSValue, arg1: *bindings.JSGlobalObject, arg2: [*c]const ZigString, JSValue3: JSC__JSValue) void; diff --git a/src/bun.js/bindings/helpers.h b/src/bun.js/bindings/helpers.h index f92362dc557685..7982f624cf5d12 100644 --- a/src/bun.js/bindings/helpers.h +++ b/src/bun.js/bindings/helpers.h @@ -107,7 +107,7 @@ static const JSC::Identifier toIdentifier(ZigString str, JSC::JSGlobalObject* gl return JSC::Identifier::EmptyIdentifier; } - return JSC::Identifier::fromString(global->vm(), untag(str.ptr), str.len); + return JSC::Identifier::fromString(global->vm(), { untag(str.ptr), str.len }); } static bool isTaggedUTF16Ptr(const unsigned char* ptr) @@ -147,15 +147,15 @@ static const WTF::String toString(ZigString str) if (UNLIKELY(isTaggedExternalPtr(str.ptr))) { return !isTaggedUTF16Ptr(str.ptr) - ? WTF::String(WTF::ExternalStringImpl::create(untag(str.ptr), str.len, untagVoid(str.ptr), free_global_string)) + ? WTF::String(WTF::ExternalStringImpl::create({ untag(str.ptr), str.len }, untagVoid(str.ptr), free_global_string)) : WTF::String(WTF::ExternalStringImpl::create( - reinterpret_cast(untag(str.ptr)), str.len, untagVoid(str.ptr), free_global_string)); + { reinterpret_cast(untag(str.ptr)), str.len }, untagVoid(str.ptr), free_global_string)); } return !isTaggedUTF16Ptr(str.ptr) - ? WTF::String(WTF::StringImpl::createWithoutCopying(untag(str.ptr), str.len)) + ? WTF::String(WTF::StringImpl::createWithoutCopying({ untag(str.ptr), str.len })) : WTF::String(WTF::StringImpl::createWithoutCopying( - reinterpret_cast(untag(str.ptr)), str.len)); + { reinterpret_cast(untag(str.ptr)), str.len })); } static WTF::AtomString toAtomString(ZigString str) @@ -178,9 +178,9 @@ static const WTF::String toString(ZigString str, StringPointer ptr) } return !isTaggedUTF16Ptr(str.ptr) - ? WTF::String(WTF::StringImpl::createWithoutCopying(&untag(str.ptr)[ptr.off], ptr.len)) + ? WTF::String(WTF::StringImpl::createWithoutCopying({ &untag(str.ptr)[ptr.off], ptr.len })) : WTF::String(WTF::StringImpl::createWithoutCopying( - &reinterpret_cast(untag(str.ptr))[ptr.off], ptr.len)); + { &reinterpret_cast(untag(str.ptr))[ptr.off], ptr.len })); } static const WTF::String toStringCopy(ZigString str, StringPointer ptr) diff --git a/src/bun.js/bindings/napi.cpp b/src/bun.js/bindings/napi.cpp index fb4de6d9b84033..32e2e9261e3a85 100644 --- a/src/bun.js/bindings/napi.cpp +++ b/src/bun.js/bindings/napi.cpp @@ -2,6 +2,10 @@ #include "node_api.h" #include "root.h" #include "ZigGlobalObject.h" +#include "JavaScriptCore/JSGlobalObject.h" +#include "JavaScriptCore/SourceCode.h" +#include "js_native_api_types.h" + #include "helpers.h" #include #include @@ -53,6 +57,8 @@ #include #include "napi_external.h" +#include "wtf/Compiler.h" +#include "wtf/NakedPtr.h" #include #include @@ -668,7 +674,7 @@ extern "C" napi_status napi_create_arraybuffer(napi_env env, // because we can't guarantee the lifetime of it #define PROPERTY_NAME_FROM_UTF8(identifierName) \ size_t utf8Len = strlen(utf8name); \ - JSC::PropertyName identifierName = LIKELY(charactersAreAllASCII(std::span { reinterpret_cast(utf8name), utf8Len })) ? JSC::PropertyName(JSC::Identifier::fromString(vm, WTF::String(WTF::StringImpl::createWithoutCopying(utf8name, utf8Len)))) : JSC::PropertyName(JSC::Identifier::fromString(vm, WTF::String::fromUTF8(utf8name))); + JSC::PropertyName identifierName = LIKELY(charactersAreAllASCII(std::span { reinterpret_cast(utf8name), utf8Len })) ? JSC::PropertyName(JSC::Identifier::fromString(vm, WTF::String(WTF::StringImpl::createWithoutCopying({ utf8name, utf8Len })))) : JSC::PropertyName(JSC::Identifier::fromString(vm, WTF::String::fromUTF8(utf8name))); extern "C" napi_status napi_has_named_property(napi_env env, napi_value object, const char* utf8name, @@ -735,7 +741,7 @@ node_api_create_external_string_latin1(napi_env env, } length = length == NAPI_AUTO_LENGTH ? strlen(str) : length; - WTF::ExternalStringImpl& impl = WTF::ExternalStringImpl::create(reinterpret_cast(str), static_cast(length), finalize_hint, [finalize_callback](void* hint, void* str, unsigned length) { + WTF::ExternalStringImpl& impl = WTF::ExternalStringImpl::create({ reinterpret_cast(str), static_cast(length) }, finalize_hint, [finalize_callback](void* hint, void* str, unsigned length) { if (finalize_callback) { #if NAPI_VERBOSE printf("[napi] string finalize_callback\n"); @@ -776,7 +782,7 @@ node_api_create_external_string_utf16(napi_env env, } length = length == NAPI_AUTO_LENGTH ? std::char_traits::length(str) : length; - WTF::ExternalStringImpl& impl = WTF::ExternalStringImpl::create(reinterpret_cast(str), static_cast(length), finalize_hint, [finalize_callback](void* hint, void* str, unsigned length) { + WTF::ExternalStringImpl& impl = WTF::ExternalStringImpl::create({ reinterpret_cast(str), static_cast(length) }, finalize_hint, [finalize_callback](void* hint, void* str, unsigned length) { #if NAPI_VERBOSE printf("[napi] string finalize_callback\n"); #endif @@ -2267,6 +2273,45 @@ extern "C" napi_status napi_get_instance_data(napi_env env, return napi_ok; } +extern "C" napi_status napi_run_script(napi_env env, napi_value script, + napi_value* result) +{ + NAPI_PREMABLE + + JSC::JSGlobalObject* globalObject = toJS(env); + if (UNLIKELY(result == nullptr)) { + return napi_invalid_arg; + } + + auto& vm = globalObject->vm(); + auto throwScope = DECLARE_THROW_SCOPE(vm); + JSValue scriptValue = toJS(script); + if (UNLIKELY(scriptValue.isEmpty())) { + return napi_invalid_arg; + } + + WTF::String code = scriptValue.toWTFString(globalObject); + RETURN_IF_EXCEPTION(throwScope, napi_generic_failure); + + if (UNLIKELY(code.isNull())) { + return napi_generic_failure; + } + + JSC::SourceCode sourceCode = makeSource(code, SourceOrigin(), SourceTaintedOrigin::Untainted); + + JSValue value = JSC::evaluate(globalObject, sourceCode, globalObject->globalThis()); + + if (throwScope.exception() || value.isEmpty()) { + return napi_generic_failure; + } + + if (result != nullptr) { + *result = toNapi(value); + } + + RELEASE_AND_RETURN(throwScope, napi_ok); +} + extern "C" napi_status napi_set_instance_data(napi_env env, void* data, napi_finalize finalize_cb, diff --git a/src/bun.js/bindings/webcore/SerializedScriptValue.cpp b/src/bun.js/bindings/webcore/SerializedScriptValue.cpp index 4faca3c2adeb36..85b23f38459cbb 100644 --- a/src/bun.js/bindings/webcore/SerializedScriptValue.cpp +++ b/src/bun.js/bindings/webcore/SerializedScriptValue.cpp @@ -3241,7 +3241,7 @@ class CloneDeserializer : CloneBase { if (is8Bit) { if ((end - ptr) < static_cast(length)) return false; - str = Identifier::fromString(vm, reinterpret_cast(ptr), length); + str = Identifier::fromString(vm, {reinterpret_cast(ptr), length}); ptr += length; return true; } @@ -3251,7 +3251,7 @@ class CloneDeserializer : CloneBase { return false; #if ASSUME_LITTLE_ENDIAN - str = Identifier::fromString(vm, reinterpret_cast(ptr), length); + str = Identifier::fromString(vm, {reinterpret_cast(ptr), length}); ptr += length * sizeof(UChar); #else UChar* characters; diff --git a/src/bun.js/bindings/webcrypto/SubtleCrypto.cpp b/src/bun.js/bindings/webcrypto/SubtleCrypto.cpp index cd07c1c3dc91cf..8a1010b997ac32 100644 --- a/src/bun.js/bindings/webcrypto/SubtleCrypto.cpp +++ b/src/bun.js/bindings/webcrypto/SubtleCrypto.cpp @@ -58,7 +58,7 @@ using namespace JSC; SubtleCrypto::SubtleCrypto(ScriptExecutionContext* context) : ContextDestructionObserver(context) - , m_workQueue(WorkQueue::create("com.apple.WebKit.CryptoQueue")) + , m_workQueue(WorkQueue::create("com.apple.WebKit.CryptoQueue"_s)) { } diff --git a/src/bun.js/bindings/workaround-missing-symbols.cpp b/src/bun.js/bindings/workaround-missing-symbols.cpp index d40e521f265a3a..187437056fe2c7 100644 --- a/src/bun.js/bindings/workaround-missing-symbols.cpp +++ b/src/bun.js/bindings/workaround-missing-symbols.cpp @@ -89,6 +89,7 @@ extern "C" int __wrap_statx(int fd, const char* path, int flags, extern "C" int __real_fcntl(int fd, int cmd, ...); typedef double (*MathFunction)(double); +typedef double (*MathFunction2)(double, double); static inline double __real_exp(double x) { @@ -123,6 +124,17 @@ static inline double __real_log2(double x) return function(x); } +static inline double __real_fmod(double x, double y) +{ + static MathFunction2 function = nullptr; + if (UNLIKELY(function == nullptr)) { + function = reinterpret_cast(dlsym(nullptr, "fmod")); + if (UNLIKELY(function == nullptr)) + abort(); + } + + return function(x, y); +} extern "C" int __wrap_fcntl(int fd, int cmd, ...) { @@ -165,6 +177,11 @@ extern "C" double __wrap_log2(double x) return __real_log2(x); } +extern "C" double __wrap_fmod(double x, double y) +{ + return __real_fmod(x, y); +} + #ifndef _MKNOD_VER #define _MKNOD_VER 1 #endif diff --git a/src/bun.js/bindings/wtf-bindings.cpp b/src/bun.js/bindings/wtf-bindings.cpp index 712179eda71a14..de9a6ef55ced21 100644 --- a/src/bun.js/bindings/wtf-bindings.cpp +++ b/src/bun.js/bindings/wtf-bindings.cpp @@ -170,12 +170,12 @@ extern "C" int Bun__ttySetMode(int fd, int mode) extern "C" double WTF__parseDouble(const LChar* string, size_t length, size_t* position) { - return WTF::parseDouble(string, length, *position); + return WTF::parseDouble({string, length}, *position); } extern "C" void WTF__copyLCharsFromUCharSource(LChar* destination, const UChar* source, size_t length) { - WTF::StringImpl::copyCharacters(destination, source, length); + WTF::StringImpl::copyCharacters(destination, {source, length}); } // For whatever reason diff --git a/src/bun.js/javascript_core_c_api.zig b/src/bun.js/javascript_core_c_api.zig index 9f02acf6090e0d..b4faa3f722efc4 100644 --- a/src/bun.js/javascript_core_c_api.zig +++ b/src/bun.js/javascript_core_c_api.zig @@ -22,94 +22,13 @@ pub const JSContextGroupRef = ?*const struct_OpaqueJSContextGroup; pub const struct_OpaqueJSContext = generic; pub const JSContextRef = *cpp.JSGlobalObject; pub const JSGlobalContextRef = ?*cpp.JSGlobalObject; -pub const OpaqueJSString = opaque { - pub fn len(this: *OpaqueJSString) usize { - return JSStringGetLength(this); - } - - pub fn is16Bit(this: *OpaqueJSString) bool { - return JSStringEncoding(this) == Encoding.char16; - } - - pub fn characters16(this: *OpaqueJSString) UTF16Ptr { - if (comptime bun.Environment.allow_assert) - bun.assert(this.is16Bit()); - - return JSStringGetCharactersPtr(this); - } - - pub fn characters8(this: *OpaqueJSString) UTF8Ptr { - if (comptime bun.Environment.allow_assert) - bun.assert(!this.is16Bit()); - - return JSStringGetCharacters8Ptr(this); - } - - pub fn latin1Slice(this: *OpaqueJSString) []const u8 { - const _len = this.len(); - if (_len == 0) return ""; - return this.characters8()[0.._len]; - } - pub fn utf16Slice(this: *OpaqueJSString) []const u16 { - const _len = this.len(); - if (_len == 0) return &[_]u16{}; - return this.characters16()[0.._len]; - } - - pub fn toZigString(this: *OpaqueJSString) cpp.ZigString { - if (this.is16Bit()) { - return cpp.ZigString.init16(this.utf16Slice()); - } else { - return cpp.ZigString.init(this.latin1Slice()); - } - } - - pub fn fromZigString(zig_str: cpp.ZigString, allocator: std.mem.Allocator) *OpaqueJSString { - if (zig_str.isEmpty()) { - return JSStringCreateWithUTF8CString(""); - } - - if (zig_str.isUTF8()) { - return JSValueToStringCopy( - bun.JSC.VirtualMachine.get().global, - zig_str.toValueGC(bun.JSC.VirtualMachine.get().global).asObjectRef(), - null, - ); - } - - if (zig_str.is16Bit()) { - return JSStringCreateWithCharacters(zig_str.utf16SliceAligned().ptr, zig_str.len); - } - - // also extremely inefficient - const utf8Z = allocator.dupeZ(u8, zig_str.slice()) catch unreachable; - const cloned = JSStringCreateWithUTF8CString(utf8Z); - allocator.free(utf8Z); - return cloned; - } -}; -pub const JSStringRef = *OpaqueJSString; -pub const struct_OpaqueJSClass = opaque { - pub const name = "JSClassRef"; - pub const is_pointer = false; - pub const Type = "JSClassRef"; -}; -pub const JSClassRef = ?*struct_OpaqueJSClass; -pub const JSPropertyNameArray = opaque { - pub fn at(this: *@This(), i: usize) JSStringRef { - return JSPropertyNameArrayGetNameAtIndex(this, i); - } -}; -pub const JSPropertyNameArrayRef = ?*JSPropertyNameArray; pub const struct_OpaqueJSPropertyNameAccumulator = generic; pub const JSPropertyNameAccumulatorRef = ?*struct_OpaqueJSPropertyNameAccumulator; pub const JSTypedArrayBytesDeallocator = ?*const fn (*anyopaque, *anyopaque) callconv(.C) void; pub const OpaqueJSValue = generic; pub const JSValueRef = ?*OpaqueJSValue; pub const JSObjectRef = ?*OpaqueJSValue; -pub extern fn JSEvaluateScript(ctx: JSContextRef, script: JSStringRef, thisObject: ?*anyopaque, sourceURL: ?JSStringRef, startingLineNumber: c_int, exception: ExceptionRef) JSValueRef; -pub extern fn JSCheckScriptSyntax(ctx: JSContextRef, script: JSStringRef, sourceURL: JSStringRef, startingLineNumber: c_int, exception: ExceptionRef) bool; pub extern fn JSGarbageCollect(ctx: JSContextRef) void; pub const JSType = enum(c_uint) { kJSTypeUndefined, @@ -153,31 +72,8 @@ pub const kJSTypedArrayTypeFloat64Array = @intFromEnum(JSTypedArrayType.kJSTyped pub const kJSTypedArrayTypeArrayBuffer = @intFromEnum(JSTypedArrayType.kJSTypedArrayTypeArrayBuffer); pub const kJSTypedArrayTypeNone = @intFromEnum(JSTypedArrayType.kJSTypedArrayTypeNone); pub extern fn JSValueGetType(ctx: JSContextRef, value: JSValueRef) JSType; -pub extern fn JSValueIsUndefined(ctx: JSContextRef, value: JSValueRef) bool; -pub extern fn JSValueIsNull(ctx: JSContextRef, value: JSValueRef) bool; -pub extern fn JSValueIsBoolean(ctx: JSContextRef, value: JSValueRef) bool; -pub extern fn JSValueIsNumber(ctx: JSContextRef, value: JSValueRef) bool; -pub extern fn JSValueIsString(ctx: JSContextRef, value: JSValueRef) bool; -pub extern fn JSValueIsSymbol(ctx: JSContextRef, value: JSValueRef) bool; -pub extern fn JSValueIsObject(ctx: JSContextRef, value: JSValueRef) bool; -pub extern fn JSValueIsObjectOfClass(ctx: JSContextRef, value: JSValueRef, jsClass: JSClassRef) bool; -pub extern fn JSValueIsArray(ctx: JSContextRef, value: JSValueRef) bool; -pub extern fn JSValueIsDate(ctx: JSContextRef, value: JSValueRef) bool; -pub extern fn JSValueGetTypedArrayType(ctx: JSContextRef, value: JSValueRef, exception: ExceptionRef) JSTypedArrayType; -pub extern fn JSValueIsEqual(ctx: JSContextRef, a: JSValueRef, b: JSValueRef, exception: ExceptionRef) bool; -pub extern fn JSValueIsStrictEqual(ctx: JSContextRef, a: JSValueRef, b: JSValueRef) bool; -pub extern fn JSValueIsInstanceOfConstructor(ctx: JSContextRef, value: JSValueRef, constructor: JSObjectRef, exception: ExceptionRef) bool; -pub extern fn JSValueMakeUndefined(ctx: JSContextRef) JSValueRef; pub extern fn JSValueMakeNull(ctx: JSContextRef) JSValueRef; -pub extern fn JSValueMakeBoolean(ctx: JSContextRef, boolean: bool) JSValueRef; -pub extern fn JSValueMakeNumber(ctx: JSContextRef, number: f64) JSValueRef; -pub extern fn JSValueMakeString(ctx: JSContextRef, string: JSStringRef) JSValueRef; -pub extern fn JSValueMakeSymbol(ctx: JSContextRef, description: JSStringRef) JSValueRef; -pub extern fn JSValueMakeFromJSONString(ctx: JSContextRef, string: JSStringRef) JSValueRef; -pub extern fn JSValueCreateJSONString(ctx: JSContextRef, value: JSValueRef, indent: c_uint, exception: ExceptionRef) JSStringRef; -pub extern fn JSValueToBoolean(ctx: JSContextRef, value: JSValueRef) bool; pub extern fn JSValueToNumber(ctx: JSContextRef, value: JSValueRef, exception: ExceptionRef) f64; -pub extern fn JSValueToStringCopy(ctx: JSContextRef, value: JSValueRef, exception: ExceptionRef) JSStringRef; pub extern fn JSValueToObject(ctx: JSContextRef, value: JSValueRef, exception: ExceptionRef) JSObjectRef; const log_protection = bun.Environment.allow_assert and false; @@ -226,10 +122,6 @@ pub const kJSClassAttributeNone = @intFromEnum(JSClassAttributes.kJSClassAttribu pub const kJSClassAttributeNoAutomaticPrototype = @intFromEnum(JSClassAttributes.kJSClassAttributeNoAutomaticPrototype); pub const JSObjectInitializeCallback = *const fn (JSContextRef, JSObjectRef) callconv(.C) void; pub const JSObjectFinalizeCallback = *const fn (JSObjectRef) callconv(.C) void; -pub const JSObjectHasPropertyCallback = *const fn (JSContextRef, JSObjectRef, JSStringRef) callconv(.C) bool; -pub const JSObjectGetPropertyCallback = *const fn (JSContextRef, JSObjectRef, JSStringRef, ExceptionRef) callconv(.C) JSValueRef; -pub const JSObjectSetPropertyCallback = *const fn (JSContextRef, JSObjectRef, JSStringRef, JSValueRef, ExceptionRef) callconv(.C) bool; -pub const JSObjectDeletePropertyCallback = *const fn (JSContextRef, JSObjectRef, JSStringRef, ExceptionRef) callconv(.C) bool; pub const JSObjectGetPropertyNamesCallback = *const fn (JSContextRef, JSObjectRef, JSPropertyNameAccumulatorRef) callconv(.C) void; pub const ExceptionRef = [*c]JSValueRef; pub const JSObjectCallAsFunctionCallback = *const fn ( @@ -243,96 +135,15 @@ pub const JSObjectCallAsFunctionCallback = *const fn ( pub const JSObjectCallAsConstructorCallback = *const fn (JSContextRef, JSObjectRef, usize, [*c]const JSValueRef, ExceptionRef) callconv(.C) JSObjectRef; pub const JSObjectHasInstanceCallback = *const fn (JSContextRef, JSObjectRef, JSValueRef, ExceptionRef) callconv(.C) bool; pub const JSObjectConvertToTypeCallback = *const fn (JSContextRef, JSObjectRef, JSType, ExceptionRef) callconv(.C) JSValueRef; -pub const JSStaticValue = extern struct { - name: [*c]const u8 = null, - getProperty: ?JSObjectGetPropertyCallback = null, - setProperty: ?JSObjectSetPropertyCallback = null, - attributes: JSPropertyAttributes = .kJSPropertyAttributeNone, -}; -pub const JSStaticFunction = extern struct { - name: [*c]const u8 = null, - callAsFunction: ?JSObjectCallAsFunctionCallback = null, - attributes: JSPropertyAttributes = .kJSPropertyAttributeNone, -}; -pub const JSClassDefinition = extern struct { - version: c_int = 0, - attributes: JSClassAttributes = .kJSClassAttributeNone, - className: [*:0]const u8 = "", - parentClass: JSClassRef = null, - staticValues: [*c]const JSStaticValue = null, - staticFunctions: [*c]const JSStaticFunction = null, - initialize: ?JSObjectInitializeCallback = null, - finalize: ?JSObjectFinalizeCallback = null, - hasProperty: ?JSObjectHasPropertyCallback = null, - getProperty: ?JSObjectGetPropertyCallback = null, - setProperty: ?JSObjectSetPropertyCallback = null, - deleteProperty: ?JSObjectDeletePropertyCallback = null, - getPropertyNames: ?JSObjectGetPropertyNamesCallback = null, - callAsFunction: ?JSObjectCallAsFunctionCallback = null, - callAsConstructor: ?JSObjectCallAsConstructorCallback = null, - hasInstance: ?JSObjectHasInstanceCallback = null, - convertToType: ?JSObjectConvertToTypeCallback = null, -}; -pub extern const kJSClassDefinitionEmpty: JSClassDefinition; -pub extern "c" fn JSClassCreate(definition: [*c]const JSClassDefinition) JSClassRef; -pub extern "c" fn JSClassRetain(jsClass: JSClassRef) JSClassRef; -pub extern "c" fn JSClassRelease(jsClass: JSClassRef) void; -pub extern "c" fn JSObjectMake(ctx: JSContextRef, jsClass: JSClassRef, data: ?*anyopaque) JSObjectRef; -pub extern "c" fn JSObjectMakeFunctionWithCallback(ctx: JSContextRef, name: JSStringRef, callAsFunction: JSObjectCallAsFunctionCallback) JSObjectRef; -pub extern "c" fn JSObjectMakeConstructor(ctx: JSContextRef, jsClass: JSClassRef, callAsConstructor: JSObjectCallAsConstructorCallback) JSObjectRef; -pub extern "c" fn JSObjectMakeArray(ctx: JSContextRef, argumentCount: usize, arguments: [*c]const JSValueRef, exception: ExceptionRef) JSObjectRef; -pub extern "c" fn JSObjectMakeDate(ctx: JSContextRef, argumentCount: usize, arguments: [*c]const JSValueRef, exception: ExceptionRef) JSObjectRef; -pub extern "c" fn JSObjectMakeError(ctx: JSContextRef, argumentCount: usize, arguments: [*c]const JSValueRef, exception: ExceptionRef) JSObjectRef; -pub extern "c" fn JSObjectMakeRegExp(ctx: JSContextRef, argumentCount: usize, arguments: [*c]const JSValueRef, exception: ExceptionRef) JSObjectRef; -pub extern "c" fn JSObjectMakeDeferredPromise(ctx: JSContextRef, resolve: ?*JSObjectRef, reject: ?*JSObjectRef, exception: ExceptionRef) JSObjectRef; -pub extern "c" fn JSObjectMakeFunction(ctx: JSContextRef, name: JSStringRef, parameterCount: c_uint, parameterNames: [*c]const JSStringRef, body: JSStringRef, sourceURL: JSStringRef, startingLineNumber: c_int, exception: ExceptionRef) JSObjectRef; + pub extern "c" fn JSObjectGetPrototype(ctx: JSContextRef, object: JSObjectRef) JSValueRef; -pub extern "c" fn JSObjectSetPrototype(ctx: JSContextRef, object: JSObjectRef, value: JSValueRef) void; -pub extern "c" fn JSObjectHasProperty(ctx: JSContextRef, object: JSObjectRef, propertyName: JSStringRef) bool; -pub extern "c" fn JSObjectGetProperty(ctx: JSContextRef, object: JSObjectRef, propertyName: JSStringRef, exception: ExceptionRef) JSValueRef; -pub extern "c" fn JSObjectSetProperty(ctx: JSContextRef, object: JSObjectRef, propertyName: JSStringRef, value: JSValueRef, attributes: c_uint, exception: ExceptionRef) void; -pub extern "c" fn JSObjectDeleteProperty(ctx: JSContextRef, object: JSObjectRef, propertyName: JSStringRef, exception: ExceptionRef) bool; -pub extern "c" fn JSObjectHasPropertyForKey(ctx: JSContextRef, object: JSObjectRef, propertyKey: JSValueRef, exception: ExceptionRef) bool; -pub extern "c" fn JSObjectGetPropertyForKey(ctx: JSContextRef, object: JSObjectRef, propertyKey: JSValueRef, exception: ExceptionRef) JSValueRef; -pub extern "c" fn JSObjectSetPropertyForKey(ctx: JSContextRef, object: JSObjectRef, propertyKey: JSValueRef, value: JSValueRef, attributes: JSPropertyAttributes, exception: ExceptionRef) void; -pub extern "c" fn JSObjectDeletePropertyForKey(ctx: JSContextRef, object: JSObjectRef, propertyKey: JSValueRef, exception: ExceptionRef) bool; pub extern "c" fn JSObjectGetPropertyAtIndex(ctx: JSContextRef, object: JSObjectRef, propertyIndex: c_uint, exception: ExceptionRef) JSValueRef; pub extern "c" fn JSObjectSetPropertyAtIndex(ctx: JSContextRef, object: JSObjectRef, propertyIndex: c_uint, value: JSValueRef, exception: ExceptionRef) void; -pub extern "c" fn JSObjectGetPrivate(object: JSObjectRef) ?*anyopaque; -pub extern "c" fn JSObjectSetPrivate(object: JSObjectRef, data: ?*anyopaque) bool; -pub extern "c" fn JSObjectIsFunction(ctx: JSContextRef, object: JSObjectRef) bool; pub extern "c" fn JSObjectCallAsFunction(ctx: JSContextRef, object: JSObjectRef, thisObject: JSObjectRef, argumentCount: usize, arguments: [*c]const JSValueRef, exception: ExceptionRef) JSValueRef; pub extern "c" fn JSObjectIsConstructor(ctx: JSContextRef, object: JSObjectRef) bool; pub extern "c" fn JSObjectCallAsConstructor(ctx: JSContextRef, object: JSObjectRef, argumentCount: usize, arguments: [*c]const JSValueRef, exception: ExceptionRef) JSObjectRef; -pub extern "c" fn JSObjectCopyPropertyNames(ctx: JSContextRef, object: JSObjectRef) JSPropertyNameArrayRef; -pub extern "c" fn JSPropertyNameArrayRetain(array: JSPropertyNameArrayRef) JSPropertyNameArrayRef; -pub extern "c" fn JSPropertyNameArrayRelease(array: JSPropertyNameArrayRef) void; -pub extern "c" fn JSPropertyNameArrayGetCount(array: JSPropertyNameArrayRef) usize; -pub extern "c" fn JSPropertyNameArrayGetNameAtIndex(array: JSPropertyNameArrayRef, index: usize) JSStringRef; -pub extern "c" fn JSPropertyNameAccumulatorAddName(accumulator: JSPropertyNameAccumulatorRef, propertyName: JSStringRef) void; -pub extern "c" fn JSContextGroupCreate() JSContextGroupRef; -pub extern "c" fn JSContextGroupRetain(group: JSContextGroupRef) JSContextGroupRef; -pub extern "c" fn JSContextGroupRelease(group: JSContextGroupRef) void; -pub extern "c" fn JSGlobalContextCreate(globalObjectClass: JSClassRef) JSGlobalContextRef; -pub extern "c" fn JSGlobalContextCreateInGroup(group: JSContextGroupRef, globalObjectClass: JSClassRef) JSGlobalContextRef; -pub extern "c" fn JSGlobalContextRetain(ctx: JSGlobalContextRef) JSGlobalContextRef; -pub extern "c" fn JSGlobalContextRelease(ctx: JSGlobalContextRef) void; -pub extern "c" fn JSContextGetGlobalObject(ctx: JSContextRef) JSObjectRef; -pub extern "c" fn JSContextGetGroup(ctx: JSContextRef) JSContextGroupRef; -pub extern "c" fn JSContextGetGlobalContext(ctx: JSContextRef) JSGlobalContextRef; -pub extern "c" fn JSGlobalContextCopyName(ctx: JSGlobalContextRef) JSStringRef; -pub extern "c" fn JSGlobalContextSetName(ctx: JSGlobalContextRef, name: JSStringRef) void; +pub extern "c" fn JSObjectMakeDate(ctx: JSContextRef, argumentCount: usize, arguments: [*c]const JSValueRef, exception: ExceptionRef) JSObjectRef; pub const JSChar = u16; -pub extern fn JSStringCreateWithCharacters(chars: [*c]const JSChar, numChars: usize) JSStringRef; -pub extern fn JSStringCreateWithUTF8CString(string: [*c]const u8) JSStringRef; -pub extern fn JSStringRetain(string: JSStringRef) JSStringRef; -pub extern fn JSStringRelease(string: JSStringRef) void; -pub extern fn JSStringGetLength(string: JSStringRef) usize; -pub extern fn JSStringGetCharactersPtr(string: JSStringRef) [*]const JSChar; -pub extern fn JSStringGetMaximumUTF8CStringSize(string: JSStringRef) usize; -pub extern fn JSStringGetUTF8CString(string: JSStringRef, buffer: [*c]u8, bufferSize: usize) usize; -pub extern fn JSStringIsEqual(a: JSStringRef, b: JSStringRef) bool; -pub extern fn JSStringIsEqualToUTF8CString(a: JSStringRef, b: [*c]const u8) bool; pub extern fn JSObjectMakeTypedArray(ctx: JSContextRef, arrayType: JSTypedArrayType, length: usize, exception: ExceptionRef) JSObjectRef; pub extern fn JSObjectMakeTypedArrayWithBytesNoCopy(ctx: JSContextRef, arrayType: JSTypedArrayType, bytes: ?*anyopaque, byteLength: usize, bytesDeallocator: JSTypedArrayBytesDeallocator, deallocatorContext: ?*anyopaque, exception: ExceptionRef) JSObjectRef; pub extern fn JSObjectMakeTypedArrayWithArrayBuffer(ctx: JSContextRef, arrayType: JSTypedArrayType, buffer: JSObjectRef, exception: ExceptionRef) JSObjectRef; @@ -347,7 +158,6 @@ pub extern fn JSObjectGetArrayBufferBytesPtr(ctx: JSContextRef, object: JSObject pub extern fn JSObjectGetArrayBufferByteLength(ctx: JSContextRef, object: JSObjectRef, exception: ExceptionRef) usize; pub const OpaqueJSContextGroup = struct_OpaqueJSContextGroup; pub const OpaqueJSContext = struct_OpaqueJSContext; -pub const OpaqueJSClass = struct_OpaqueJSClass; pub const OpaqueJSPropertyNameAccumulator = struct_OpaqueJSPropertyNameAccumulator; // This is a workaround for not receiving a JSException* object @@ -358,7 +168,6 @@ pub extern "c" fn JSObjectCallAsFunctionReturnValueHoldingAPILock(ctx: JSContext pub extern fn JSRemoteInspectorDisableAutoStart() void; pub extern fn JSRemoteInspectorStart() void; -// JS_EXPORT void JSRemoteInspectorSetParentProcessInformation(JSProcessID, const uint8_t* auditData, size_t auditLength) JSC_API_AVAILABLE(macos(10.11), ios(9.0)); pub extern fn JSRemoteInspectorSetLogToSystemConsole(enabled: bool) void; pub extern fn JSRemoteInspectorGetInspectionEnabledByDefault(void) bool; @@ -366,42 +175,8 @@ pub extern fn JSRemoteInspectorSetInspectionEnabledByDefault(enabled: bool) void // -- Manual -- -// StringImpl::createWithoutCopying -// https://github.com/WebKit/webkit/blob/main/Source/JavaScriptCore/API/JSStringRef.cpp#L62 -pub extern fn JSStringCreateWithCharactersNoCopy(string: [*c]const JSChar, numChars: size_t) JSStringRef; const size_t = usize; -const then_key = "then"; -var thenable_string: JSStringRef = null; -pub fn isObjectOfClassAndResolveIfNeeded(ctx: JSContextRef, obj: JSObjectRef, class: JSClassRef) ?JSObjectRef { - if (JSValueIsObjectOfClass(ctx, obj, class)) { - return obj; - } - - if (!JSValueIsObject(ctx, obj)) { - return null; - } - - if (thenable_string == null) { - thenable_string = JSStringCreateWithUTF8CString(then_key[0.. :0]); - } - - const prop = JSObjectGetPropertyForKey(ctx, obj, JSValueMakeString(ctx, thenable_string), null); - if (prop == null) { - return null; - } -} - -pub const UTF8Ptr = [*]const u8; -pub const UTF16Ptr = [*]const u16; - -// --- Custom Methods! ---- -pub const Encoding = enum(u8) { - empty = 0, - char8 = 8, - char16 = 16, -}; -pub const JSCellValue = u64; pub const CellType = enum(u8) { pub const LastMaybeFalsyCellPrimitive = 2; pub const LastJSCObjectType = 73; @@ -494,28 +269,5 @@ pub const CellType = enum(u8) { }; } }; -pub const ExternalStringFinalizer = *const fn (finalize_ptr: ?*anyopaque, ref: JSStringRef, buffer: *anyopaque, byteLength: usize) callconv(.C) void; - -/// **DEPRECATED**: USE from JSValue instead! This whole file should be used sparingly. -pub extern fn JSStringCreate(string: UTF8Ptr, length: usize) JSStringRef; -pub extern fn JSStringCreateStatic(string: UTF8Ptr, length: usize) JSStringRef; -pub extern fn JSStringCreateExternal(string: UTF8Ptr, length: usize, finalize_ptr: ?*anyopaque, finalizer: ExternalStringFinalizer) JSStringRef; -pub extern fn JSStringEncoding(string: JSStringRef) Encoding; -pub extern fn JSStringGetCharacters8Ptr(string: JSStringRef) UTF8Ptr; -pub extern fn JSCellType(cell: JSCellValue) CellType; -pub extern fn JSStringIsStatic(ref: JSStringRef) bool; -pub extern fn JSStringIsExternal(ref: JSStringRef) bool; - -pub const JStringIteratorAppendCallback = *const fn (ctx: *JSStringIterator_, ptr: *anyopaque, length: u32) callconv(.C) anyopaque; -pub const JStringIteratorWriteCallback = *const fn (ctx: *JSStringIterator_, ptr: *anyopaque, length: u32, offset: u32) callconv(.C) anyopaque; -const JSStringIterator_ = extern struct { - ctx: *anyopaque, - stop: u8, - - append8: JStringIteratorAppendCallback, - append16: JStringIteratorAppendCallback, - write8: JStringIteratorWriteCallback, - write16: JStringIteratorWriteCallback, -}; pub extern "c" fn JSObjectGetProxyTarget(JSObjectRef) JSObjectRef; diff --git a/src/bun.js/node/util/parse_args.zig b/src/bun.js/node/util/parse_args.zig index 7ae27d1a6daa10..ac21dbbc57b49f 100644 --- a/src/bun.js/node/util/parse_args.zig +++ b/src/bun.js/node/util/parse_args.zig @@ -309,7 +309,7 @@ fn parseOptionDefinitions(globalThis: *JSGlobalObject, options_obj: JSValue, opt var iter = JSC.JSPropertyIterator(.{ .skip_empty_name = false, .include_value = true, - }).init(globalThis, options_obj.asObjectRef()); + }).init(globalThis, options_obj); defer iter.deinit(); while (iter.next()) |long_option| { diff --git a/src/bun.js/test/expect.zig b/src/bun.js/test/expect.zig index ad65756da0f9be..d42938f166488d 100644 --- a/src/bun.js/test/expect.zig +++ b/src/bun.js/test/expect.zig @@ -2380,7 +2380,7 @@ pub const Expect = struct { .skip_empty_name = false, .include_value = true, - }).init(globalObject, value.asObjectRef()); + }).init(globalObject, value); defer props_iter.deinit(); pass = props_iter.len == 0; } @@ -4044,10 +4044,10 @@ pub const Expect = struct { var iter = JSC.JSPropertyIterator(.{ .skip_empty_name = true, .include_value = true, - }).init(globalObject, matchers_to_register.asObjectRef()); + }).init(globalObject, matchers_to_register); defer iter.deinit(); - while (iter.next()) |matcher_name| { + while (iter.next()) |*matcher_name| { const matcher_fn: JSValue = iter.value; if (!matcher_fn.jsType().isFunction()) { @@ -4060,11 +4060,11 @@ pub const Expect = struct { // Even though they point to the same native functions for all matchers, // multiple instances are created because each instance will hold the matcher_fn as a property - const wrapper_fn = Bun__JSWrappingFunction__create(globalObject, &matcher_name, &Expect.applyCustomMatcher, matcher_fn, true); + const wrapper_fn = Bun__JSWrappingFunction__create(globalObject, matcher_name, &Expect.applyCustomMatcher, matcher_fn, true); - expect_proto.put(globalObject, &matcher_name, wrapper_fn); - expect_constructor.put(globalObject, &matcher_name, wrapper_fn); - expect_static_proto.put(globalObject, &matcher_name, wrapper_fn); + expect_proto.put(globalObject, matcher_name, wrapper_fn); + expect_constructor.put(globalObject, matcher_name, wrapper_fn); + expect_static_proto.put(globalObject, matcher_name, wrapper_fn); } } @@ -5136,7 +5136,7 @@ extern fn JSMockFunction__getCalls(JSValue) JSValue; /// If there were no calls, it returns an empty JSArray* extern fn JSMockFunction__getReturns(JSValue) JSValue; -extern fn Bun__JSWrappingFunction__create(globalObject: *JSC.JSGlobalObject, symbolName: *const ZigString, functionPointer: JSC.JSHostFunctionPtr, wrappedFn: JSValue, strong: bool) JSValue; +extern fn Bun__JSWrappingFunction__create(globalObject: *JSC.JSGlobalObject, symbolName: *const bun.String, functionPointer: JSC.JSHostFunctionPtr, wrappedFn: JSValue, strong: bool) JSValue; extern fn Bun__JSWrappingFunction__getWrappedFunction(this: JSC.JSValue, globalObject: *JSC.JSGlobalObject) JSValue; extern fn ExpectMatcherUtils__getSingleton(globalObject: *JSC.JSGlobalObject) JSC.JSValue; diff --git a/src/bun.js/test/pretty_format.zig b/src/bun.js/test/pretty_format.zig index 2d8e2138c5d438..b0daaf776c13e7 100644 --- a/src/bun.js/test/pretty_format.zig +++ b/src/bun.js/test/pretty_format.zig @@ -400,7 +400,6 @@ pub const JestPrettyFormat = struct { }; // Cell is the "unknown" type - // if we call JSObjectGetPrivate, it can segfault if (js_type == .Cell) { return .{ .tag = .NativeCode, @@ -1513,7 +1512,7 @@ pub const JestPrettyFormat = struct { .skip_empty_name = true, .include_value = true, - }).init(this.globalThis, props.asObjectRef()); + }).init(this.globalThis, props); defer props_iter.deinit(); const children_prop = props.get(this.globalThis, "children"); diff --git a/src/codegen/bundle-functions.ts b/src/codegen/bundle-functions.ts index 43494251605126..1fcf46189a5bb7 100644 --- a/src/codegen/bundle-functions.ts +++ b/src/codegen/bundle-functions.ts @@ -453,7 +453,7 @@ export async function bundleBuiltinFunctions({ requireTransformer }: BundleBuilt explicit ${basename}BuiltinsWrapper(JSC::VM& vm) : m_vm(vm) WEBCORE_FOREACH_${basename.toUpperCase()}_BUILTIN_FUNCTION_NAME(INITIALIZE_BUILTIN_NAMES) - #define INITIALIZE_BUILTIN_SOURCE_MEMBERS(name, functionName, overriddenName, length) , m_##name##Source(JSC::makeSource(StringImpl::createWithoutCopying(s_##name, length), { }, JSC::SourceTaintedOrigin::Untainted)) + #define INITIALIZE_BUILTIN_SOURCE_MEMBERS(name, functionName, overriddenName, length) , m_##name##Source(JSC::makeSource(StringImpl::createWithoutCopying({reinterpret_cast(s_##name), static_cast(length)}), { }, JSC::SourceTaintedOrigin::Untainted)) WEBCORE_FOREACH_${basename.toUpperCase()}_BUILTIN_CODE(INITIALIZE_BUILTIN_SOURCE_MEMBERS) #undef INITIALIZE_BUILTIN_SOURCE_MEMBERS { diff --git a/src/codegen/helpers.ts b/src/codegen/helpers.ts index 97f1cc43e81f15..463372a02d9831 100644 --- a/src/codegen/helpers.ts +++ b/src/codegen/helpers.ts @@ -22,7 +22,7 @@ export function fmtCPPCharArray(str: string, nullTerminated: boolean = true) { } export function declareASCIILiteral(name: string, value: string) { - const [chars, count] = fmtCPPCharArray(value); + const [chars, count] = fmtCPPCharArray(value, true); return `static constexpr const char ${name}Bytes[${count}] = ${chars}; static constexpr ASCIILiteral ${name} = ASCIILiteral::fromLiteralUnsafe(${name}Bytes);`; } diff --git a/src/js_ast.zig b/src/js_ast.zig index 02306a54054c0c..118d6c808b7279 100644 --- a/src/js_ast.zig +++ b/src/js_ast.zig @@ -7252,11 +7252,10 @@ pub const Macro = struct { return _entry.value_ptr.*; } - const object = value.asObjectRef(); var object_iter = JSC.JSPropertyIterator(.{ .skip_empty_name = false, .include_value = true, - }).init(this.global, object); + }).init(this.global, value); defer object_iter.deinit(); var properties = this.allocator.alloc(G.Property, object_iter.len) catch unreachable; errdefer this.allocator.free(properties); diff --git a/src/linker.lds b/src/linker.lds index 6bb5f4202c481f..27c44da3121f8e 100644 --- a/src/linker.lds +++ b/src/linker.lds @@ -1,9 +1,7 @@ -BUN_1.0 { +BUN_1.1 { global: napi*; node_api_*; - __cxa_atexit; - __cxa_thread_atexit_impl; extern "C++" { v8::*; node::*; diff --git a/src/napi/napi.zig b/src/napi/napi.zig index 6f51c712a4b406..972d5852910305 100644 --- a/src/napi/napi.zig +++ b/src/napi/napi.zig @@ -223,7 +223,7 @@ pub export fn napi_get_boolean(_: napi_env, value: bool, result: *napi_value) na } pub export fn napi_create_array(env: napi_env, result: *napi_value) napi_status { log("napi_create_array", .{}); - result.* = JSValue.c(JSC.C.JSObjectMakeArray(env.ref(), 0, null, null)); + result.* = JSValue.createEmptyArray(env, 0); return .ok; } const prefilled_undefined_args_array: [128]JSC.JSValue = brk: { @@ -887,21 +887,7 @@ pub export fn napi_is_promise(_: napi_env, value: napi_value, is_promise: *bool) is_promise.* = value.asAnyPromise() != null; return .ok; } -pub export fn napi_run_script(env: napi_env, script: napi_value, result: *napi_value) napi_status { - log("napi_run_script", .{}); - // TODO: don't copy - const ref = JSC.C.JSValueToStringCopy(env.ref(), script.asObjectRef(), TODO_EXCEPTION); - defer JSC.C.JSStringRelease(ref); - - var exception = [_]JSC.C.JSValueRef{null}; - const val = JSC.C.JSEvaluateScript(env.ref(), ref, env.ref(), null, 0, &exception); - if (exception[0] != null) { - return genericFailure(); - } - - result.* = JSValue.c(val); - return .ok; -} +pub extern fn napi_run_script(env: napi_env, script: napi_value, result: *napi_value) napi_status; pub extern fn napi_adjust_external_memory(env: napi_env, change_in_bytes: i64, adjusted_value: [*c]i64) napi_status; pub export fn napi_create_date(env: napi_env, time: f64, result: *napi_value) napi_status { log("napi_create_date", .{}); diff --git a/src/shell/interpreter.zig b/src/shell/interpreter.zig index d60d04ea3ab376..71dad1ba7ded4c 100644 --- a/src/shell/interpreter.zig +++ b/src/shell/interpreter.zig @@ -1542,7 +1542,7 @@ pub const Interpreter = struct { var object_iter = JSC.JSPropertyIterator(.{ .skip_empty_name = false, .include_value = true, - }).init(globalThis, value1.asObjectRef()); + }).init(globalThis, value1); defer object_iter.deinit(); this.root_shell.export_env.clearRetainingCapacity(); diff --git a/src/string.zig b/src/string.zig index 17d8bd223fb5e9..a7b9fbc0f49f1d 100644 --- a/src/string.zig +++ b/src/string.zig @@ -499,6 +499,18 @@ pub const String = extern struct { }; } + pub fn trunc(this: String, len: usize) String { + if (this.length() <= len) { + return this; + } + + return String.init(this.toZigString().trunc(len)); + } + + pub fn toOwnedSliceZ(this: String, allocator: std.mem.Allocator) ![:0]u8 { + return this.toZigString().toOwnedSliceZ(allocator); + } + /// Create a bun.String from a slice. This is never a copy. /// For strings created from static string literals, use `String.static` pub fn init(value: anytype) String {