From 912d671d3c6a9de5a2437e3a8f58d25929501139 Mon Sep 17 00:00:00 2001 From: Tim Fish Date: Wed, 1 Apr 2026 23:49:18 +0100 Subject: [PATCH 1/7] Test Node v25 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 33c9524..dbb5683 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -324,7 +324,7 @@ jobs: macos-15-intel, # macOS x64 windows-latest, ] - node: [18, 20, 22, 24] + node: [18, 20, 22, 24, 25] steps: - name: Check out current commit uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 From 1b405c73c07388fc5a5881676103babc230f7674 Mon Sep 17 00:00:00 2001 From: Tim Fish Date: Wed, 1 Apr 2026 23:55:42 +0100 Subject: [PATCH 2/7] Parse JSON in JavaScript --- module.cc | 38 ++++++++++++++------------------------ src/index.ts | 17 +++++++++++++++-- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/module.cc b/module.cc index 9e9731a..6945d36 100644 --- a/module.cc +++ b/module.cc @@ -467,18 +467,13 @@ void CaptureStackTraces(const FunctionCallbackInfo &args) { capture_from_isolate, result.poll_state.c_str(), NewStringType::kNormal); if (!stateStr.IsEmpty()) { - v8::MaybeLocal maybeStateVal = - v8::JSON::Parse(current_context, stateStr.ToLocalChecked()); - v8::Local stateVal; - if (maybeStateVal.ToLocal(&stateVal)) { - threadObj - ->Set(current_context, - String::NewFromUtf8(capture_from_isolate, "pollState", - NewStringType::kInternalized) - .ToLocalChecked(), - stateVal) - .Check(); - } + threadObj + ->Set(current_context, + String::NewFromUtf8(capture_from_isolate, "pollState", + NewStringType::kInternalized) + .ToLocalChecked(), + stateStr.ToLocalChecked()) + .Check(); } } @@ -487,18 +482,13 @@ void CaptureStackTraces(const FunctionCallbackInfo &args) { capture_from_isolate, result.stack_trace.async_state.c_str(), NewStringType::kNormal); if (!stateStr.IsEmpty()) { - v8::MaybeLocal maybeStateVal = - v8::JSON::Parse(current_context, stateStr.ToLocalChecked()); - v8::Local stateVal; - if (maybeStateVal.ToLocal(&stateVal)) { - threadObj - ->Set(current_context, - String::NewFromUtf8(capture_from_isolate, "asyncState", - NewStringType::kInternalized) - .ToLocalChecked(), - stateVal) - .Check(); - } + threadObj + ->Set(current_context, + String::NewFromUtf8(capture_from_isolate, "asyncState", + NewStringType::kInternalized) + .ToLocalChecked(), + stateStr.ToLocalChecked()) + .Check(); } } diff --git a/src/index.ts b/src/index.ts index 810066e..2bfcf60 100644 --- a/src/index.ts +++ b/src/index.ts @@ -49,7 +49,7 @@ interface Native { registerThread(threadName: string): void; registerThread(storage: AsyncStorageArgs, threadName: string): void; threadPoll(enableLastSeen?: boolean, pollState?: object): void; - captureStackTrace(): Record>; + captureStackTrace(): Record>; getThreadsLastSeen(): Record; } @@ -230,7 +230,20 @@ export function threadPoll(enableLastSeen: boolean = true, pollState?: object): * Captures stack traces for all registered threads. */ export function captureStackTrace(): Record> { - return native.captureStackTrace(); + const result = native.captureStackTrace(); + + // Parse the asyncState and pollState from JSON strings back into objects + const transformedResult: Record> = {}; + for (const [key, value] of Object.entries(result)) { + const thread: Thread = { + frames: value.frames, + ...(value.asyncState && { asyncState: JSON.parse(value.asyncState) }), + ...(value.pollState && { pollState: JSON.parse(value.pollState) }), + }; + transformedResult[key] = thread; + } + + return transformedResult; } /** From d37eb4dd9f76c160da38070ad52bfd473f267eea Mon Sep 17 00:00:00 2001 From: Tim Fish Date: Thu, 2 Apr 2026 09:58:12 +0100 Subject: [PATCH 3/7] Build --- .github/workflows/ci.yml | 33 +++++++++++++++++++++++++++++++-- package.json | 2 +- src/index.ts | 21 +++++++++++++++++++++ yarn.lock | 8 ++++---- 4 files changed, 57 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dbb5683..246307c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,3 @@ - name: "CI: Build & Test" on: push: @@ -9,7 +8,7 @@ on: permissions: contents: read - packages: read # Required for GHCR + packages: read # Required for GHCR jobs: job_lint: @@ -54,6 +53,10 @@ jobs: container: ghcr.io/getsentry/sentry-test-ubuntu-20.04-amd64:0dd255f3d41d013c1db4c4e08ffd22ee7959c3cc node: 24 binary: linux-x64-glibc-137 + - os: ubuntu-22.04 + container: ghcr.io/getsentry/sentry-test-ubuntu-20.04-amd64:0dd255f3d41d013c1db4c4e08ffd22ee7959c3cc + node: 25 + binary: linux-x64-glibc-141 # x64 musl - os: ubuntu-22.04 @@ -72,6 +75,10 @@ jobs: container: node:24-alpine3.20 node: 24 binary: linux-x64-musl-137 + - os: ubuntu-22.04 + container: node:25-alpine3.21 + node: 25 + binary: linux-x64-musl-141 # arm64 glibc - os: ubuntu-22.04 @@ -90,6 +97,10 @@ jobs: arch: arm64 node: 24 binary: linux-arm64-glibc-137 + - os: ubuntu-22.04 + arch: arm64 + node: 25 + binary: linux-arm64-glibc-141 # arm64 musl - os: ubuntu-22.04 @@ -112,6 +123,11 @@ jobs: container: node:24-alpine3.20 node: 24 binary: linux-arm64-musl-137 + - os: ubuntu-22.04 + arch: arm64 + container: node:24-alpine3.20 + node: 25 + binary: linux-arm64-musl-141 # macos x64 - os: macos-15-intel @@ -130,6 +146,10 @@ jobs: node: 24 arch: x64 binary: darwin-x64-137 + - os: macos-15-intel + node: 25 + arch: x64 + binary: darwin-x64-141 # macos arm64 - os: macos-15 @@ -152,6 +172,11 @@ jobs: node: 24 target_platform: darwin binary: darwin-arm64-137 + - os: macos-15 + arch: arm64 + node: 25 + target_platform: darwin + binary: darwin-arm64-141 # windows x64 - os: windows-2022 @@ -170,6 +195,10 @@ jobs: node: 24 arch: x64 binary: win32-x64-137 + - os: windows-2022 + node: 25 + arch: x64 + binary: win32-x64-141 steps: - name: Setup (alpine) diff --git a/package.json b/package.json index 74e4056..e45b5e3 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ }, "dependencies": { "detect-libc": "^2.0.4", - "node-abi": "^3.73.0" + "node-abi": "^3.89.0" }, "devDependencies": { "@sentry-internal/eslint-config-sdk": "^9.22.0", diff --git a/src/index.ts b/src/index.ts index 2bfcf60..9bb2efe 100644 --- a/src/index.ts +++ b/src/index.ts @@ -93,6 +93,9 @@ function getNativeModule(): Native { if (abi === '137') { return require('./stack-trace-darwin-x64-137.node'); } + if (abi === '141') { + return require('./stack-trace-darwin-x64-141.node'); + } } if (arch === 'arm64') { @@ -108,6 +111,9 @@ function getNativeModule(): Native { if (abi === '137') { return require('./stack-trace-darwin-arm64-137.node'); } + if (abi === '141') { + return require('./stack-trace-darwin-arm64-141.node'); + } } } @@ -125,6 +131,9 @@ function getNativeModule(): Native { if (abi === '137') { return require('./stack-trace-win32-x64-137.node'); } + if (abi === '141') { + return require('./stack-trace-win32-x64-141.node'); + } } } @@ -143,6 +152,9 @@ function getNativeModule(): Native { if (abi === '137') { return require('./stack-trace-linux-x64-musl-137.node'); } + if (abi === '141') { + return require('./stack-trace-linux-x64-musl-141.node'); + } } if (stdlib === 'glibc') { if (abi === '108') { @@ -157,6 +169,9 @@ function getNativeModule(): Native { if (abi === '137') { return require('./stack-trace-linux-x64-glibc-137.node'); } + if (abi === '141') { + return require('./stack-trace-linux-x64-glibc-141.node'); + } } } if (arch === 'arm64') { @@ -173,6 +188,9 @@ function getNativeModule(): Native { if (abi === '137') { return require('./stack-trace-linux-arm64-musl-137.node'); } + if (abi === '141') { + return require('./stack-trace-linux-arm64-musl-141.node'); + } } if (stdlib === 'glibc') { @@ -188,6 +206,9 @@ function getNativeModule(): Native { if (abi === '137') { return require('./stack-trace-linux-arm64-glibc-137.node'); } + if (abi === '141') { + return require('./stack-trace-linux-arm64-glibc-141.node'); + } } } } diff --git a/yarn.lock b/yarn.lock index 96a7d8a..4189920 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2291,10 +2291,10 @@ negotiator@^1.0.0: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-1.0.0.tgz#b6c91bb47172d69f93cfd7c357bbb529019b5f6a" integrity sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg== -node-abi@^3.73.0: - version "3.75.0" - resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.75.0.tgz#2f929a91a90a0d02b325c43731314802357ed764" - integrity sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg== +node-abi@^3.89.0: + version "3.89.0" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.89.0.tgz#eea98bf89d4534743bbbf2defa9f4f9bd3bdccfd" + integrity sha512-6u9UwL0HlAl21+agMN3YAMXcKByMqwGx+pq+P76vii5f7hTPtKDp08/H9py6DY+cfDw7kQNTGEj/rly3IgbNQA== dependencies: semver "^7.3.5" From 90e5c9de532b57de73d5c45b9b981b3466686d42 Mon Sep 17 00:00:00 2001 From: Tim Fish Date: Thu, 2 Apr 2026 14:50:12 +0100 Subject: [PATCH 4/7] Revert --- .github/workflows/ci.yml | 33 ++------------------------------- src/index.ts | 21 --------------------- 2 files changed, 2 insertions(+), 52 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 246307c..dbb5683 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,3 +1,4 @@ + name: "CI: Build & Test" on: push: @@ -8,7 +9,7 @@ on: permissions: contents: read - packages: read # Required for GHCR + packages: read # Required for GHCR jobs: job_lint: @@ -53,10 +54,6 @@ jobs: container: ghcr.io/getsentry/sentry-test-ubuntu-20.04-amd64:0dd255f3d41d013c1db4c4e08ffd22ee7959c3cc node: 24 binary: linux-x64-glibc-137 - - os: ubuntu-22.04 - container: ghcr.io/getsentry/sentry-test-ubuntu-20.04-amd64:0dd255f3d41d013c1db4c4e08ffd22ee7959c3cc - node: 25 - binary: linux-x64-glibc-141 # x64 musl - os: ubuntu-22.04 @@ -75,10 +72,6 @@ jobs: container: node:24-alpine3.20 node: 24 binary: linux-x64-musl-137 - - os: ubuntu-22.04 - container: node:25-alpine3.21 - node: 25 - binary: linux-x64-musl-141 # arm64 glibc - os: ubuntu-22.04 @@ -97,10 +90,6 @@ jobs: arch: arm64 node: 24 binary: linux-arm64-glibc-137 - - os: ubuntu-22.04 - arch: arm64 - node: 25 - binary: linux-arm64-glibc-141 # arm64 musl - os: ubuntu-22.04 @@ -123,11 +112,6 @@ jobs: container: node:24-alpine3.20 node: 24 binary: linux-arm64-musl-137 - - os: ubuntu-22.04 - arch: arm64 - container: node:24-alpine3.20 - node: 25 - binary: linux-arm64-musl-141 # macos x64 - os: macos-15-intel @@ -146,10 +130,6 @@ jobs: node: 24 arch: x64 binary: darwin-x64-137 - - os: macos-15-intel - node: 25 - arch: x64 - binary: darwin-x64-141 # macos arm64 - os: macos-15 @@ -172,11 +152,6 @@ jobs: node: 24 target_platform: darwin binary: darwin-arm64-137 - - os: macos-15 - arch: arm64 - node: 25 - target_platform: darwin - binary: darwin-arm64-141 # windows x64 - os: windows-2022 @@ -195,10 +170,6 @@ jobs: node: 24 arch: x64 binary: win32-x64-137 - - os: windows-2022 - node: 25 - arch: x64 - binary: win32-x64-141 steps: - name: Setup (alpine) diff --git a/src/index.ts b/src/index.ts index 9bb2efe..2bfcf60 100644 --- a/src/index.ts +++ b/src/index.ts @@ -93,9 +93,6 @@ function getNativeModule(): Native { if (abi === '137') { return require('./stack-trace-darwin-x64-137.node'); } - if (abi === '141') { - return require('./stack-trace-darwin-x64-141.node'); - } } if (arch === 'arm64') { @@ -111,9 +108,6 @@ function getNativeModule(): Native { if (abi === '137') { return require('./stack-trace-darwin-arm64-137.node'); } - if (abi === '141') { - return require('./stack-trace-darwin-arm64-141.node'); - } } } @@ -131,9 +125,6 @@ function getNativeModule(): Native { if (abi === '137') { return require('./stack-trace-win32-x64-137.node'); } - if (abi === '141') { - return require('./stack-trace-win32-x64-141.node'); - } } } @@ -152,9 +143,6 @@ function getNativeModule(): Native { if (abi === '137') { return require('./stack-trace-linux-x64-musl-137.node'); } - if (abi === '141') { - return require('./stack-trace-linux-x64-musl-141.node'); - } } if (stdlib === 'glibc') { if (abi === '108') { @@ -169,9 +157,6 @@ function getNativeModule(): Native { if (abi === '137') { return require('./stack-trace-linux-x64-glibc-137.node'); } - if (abi === '141') { - return require('./stack-trace-linux-x64-glibc-141.node'); - } } } if (arch === 'arm64') { @@ -188,9 +173,6 @@ function getNativeModule(): Native { if (abi === '137') { return require('./stack-trace-linux-arm64-musl-137.node'); } - if (abi === '141') { - return require('./stack-trace-linux-arm64-musl-141.node'); - } } if (stdlib === 'glibc') { @@ -206,9 +188,6 @@ function getNativeModule(): Native { if (abi === '137') { return require('./stack-trace-linux-arm64-glibc-137.node'); } - if (abi === '141') { - return require('./stack-trace-linux-arm64-glibc-141.node'); - } } } } From 12202d4f0fc3a7e95951d8a5d8019828c31d5efc Mon Sep 17 00:00:00 2001 From: Tim Fish Date: Thu, 2 Apr 2026 20:55:53 +0200 Subject: [PATCH 5/7] Ensure binary is copied after compile from source --- scripts/check-build.mjs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/check-build.mjs b/scripts/check-build.mjs index 811f3cc..3509866 100644 --- a/scripts/check-build.mjs +++ b/scripts/check-build.mjs @@ -31,6 +31,8 @@ function recompileFromSource() { console.log(clean(spawn.stderr)); return; } + + require('./copy-target.mjs'); } if (fs.existsSync(binaries.target)) { From 58ec8fad1e4b0e6abf89d7f28fd58a2f1ffbc583 Mon Sep 17 00:00:00 2001 From: Tim Fish Date: Thu, 2 Apr 2026 21:04:25 +0200 Subject: [PATCH 6/7] dont require(esm) --- scripts/check-build.mjs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/check-build.mjs b/scripts/check-build.mjs index 3509866..4766ec3 100644 --- a/scripts/check-build.mjs +++ b/scripts/check-build.mjs @@ -9,7 +9,7 @@ function clean(err) { return err.toString().trim(); } -function recompileFromSource() { +async function recompileFromSource() { console.log('Compiling from source...'); let spawn = child_process.spawnSync('node-gyp', ['configure'], { stdio: ['inherit', 'inherit', 'pipe'], @@ -32,7 +32,7 @@ function recompileFromSource() { return; } - require('./copy-target.mjs'); + await import('./copy-target.mjs'); } if (fs.existsSync(binaries.target)) { @@ -47,7 +47,7 @@ if (fs.existsSync(binaries.target)) { console.log(e); } try { - recompileFromSource(); + await recompileFromSource(); } catch (e) { console.log('Failed to compile from source'); throw e; @@ -55,5 +55,5 @@ if (fs.existsSync(binaries.target)) { } } else { console.log('No precompiled binary found'); - recompileFromSource(); + await recompileFromSource(); } From 2c8b796daa5a5fa649f0a71ec3dbd1ec5dae806a Mon Sep 17 00:00:00 2001 From: Tim Fish Date: Thu, 2 Apr 2026 21:48:47 +0200 Subject: [PATCH 7/7] remove unnecessary catch --- scripts/check-build.mjs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/scripts/check-build.mjs b/scripts/check-build.mjs index 4766ec3..03eb347 100644 --- a/scripts/check-build.mjs +++ b/scripts/check-build.mjs @@ -46,12 +46,8 @@ if (fs.existsSync(binaries.target)) { } else { console.log(e); } - try { - await recompileFromSource(); - } catch (e) { - console.log('Failed to compile from source'); - throw e; - } + + await recompileFromSource(); } } else { console.log('No precompiled binary found');