Skip to content

Commit 5cf8a72

Browse files
committed
fix(test): repair stripTrailingSlash normalize regression, TDZ mock, stale-lock test, and patch lib errorStack
1 parent 7a5c072 commit 5cf8a72

7 files changed

Lines changed: 84 additions & 63 deletions

File tree

CHANGELOG.md

Lines changed: 22 additions & 22 deletions
Large diffs are not rendered by default.

packages/cli/src/commands/scan/exclude-paths.mts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -194,9 +194,9 @@ export function projectIgnorePathsToReachExcludePaths(
194194
}
195195

196196
export function stripTrailingSlash(value: string): string {
197-
return value.length > 1 && normalizePath(value).endsWith('/')
198-
? value.slice(0, -1)
199-
: value
197+
// normalizePath collapses separators AND drops any trailing slash, so the
198+
// normalized form IS the stripped form (root '/' stays '/').
199+
return value.length > 1 ? normalizePath(value) : value
200200
}
201201

202202
export function toPosixPath(value: string): string {

packages/cli/test/unit/commands/whoami/cmd-whoami.test.mts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,10 @@ vi.mock(import('../../../../src/util/socket/sdk.mjs'), () => ({
123123
}))
124124

125125
// Mock TOKEN_PREFIX constant to avoid security check false positives.
126-
const MOCK_TOKEN_PREFIX = 'test_'
126+
// vi.hoisted so the hoisted vi.mock factory below can read it (a plain
127+
// module-level const is still in its TDZ when the factory runs against a
128+
// statically imported system-under-test).
129+
const MOCK_TOKEN_PREFIX = vi.hoisted(() => 'test_')
127130
vi.mock(import('../../../../src/constants/socket.mjs'), () => ({
128131
TOKEN_PREFIX: MOCK_TOKEN_PREFIX,
129132
TOKEN_PREFIX_LENGTH: MOCK_TOKEN_PREFIX.length,

packages/cli/test/unit/util/dlx/spawn-download-binary.test.mts

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -378,9 +378,8 @@ describe('downloadGitHubReleaseBinary', () => {
378378
it('recovers from a stale lock (dead PID) and re-runs download', async () => {
379379
const eexistErr = Object.assign(new Error('EEXIST'), { code: 'EEXIST' })
380380

381-
// First call: EEXIST. After stale cleanup, the recursive call's
382-
// writeFile succeeds. To exit the recursive call, make the binary
383-
// appear right after download/extract.
381+
// First writeFile: EEXIST (lock held). After the stale cleanup recurses,
382+
// the recursive call short-circuits on the cache check (existsSync below).
384383
let writeCount = 0
385384
mockFsWriteFile.mockImplementation(async () => {
386385
writeCount += 1
@@ -390,40 +389,31 @@ describe('downloadGitHubReleaseBinary', () => {
390389
return undefined
391390
})
392391

393-
// Lock file polling reads the PID; we'll make it return so that the
394-
// first poll iteration goes to lock-aliveness check (i % 5 === 4 only on i=4).
395-
// Simpler path: make the binary appear before the loop even fires.
396-
let existsCount = 0
397-
mockExistsSync.mockImplementation(() => {
398-
existsCount += 1
399-
// call 1: initial cache check (false)
400-
// call 2+ depends on flow. After we send recursion, we want the
401-
// recursive call to short-circuit on cache-check.
402-
return existsCount >= 3
403-
})
404-
392+
// Dead lock holder: the liveness probe (process.kill(pid, 0)) throws.
405393
const realKill = process.kill
406-
// First kill(0) call (in stale check) throws -> stale.
407394
let killCount = 0
408395
;(process as { kill: unknown }).kill = vi.fn(() => {
409396
killCount += 1
410-
if (killCount === 1) {
411-
// We're inside the stale-check path (kill(pid, 0)) — wait no,
412-
// the lock-busy branch is only hit on EEXIST. Stale check happens
413-
// inside the inner `for` poll's `i % 5 === 4` branch.
414-
// Actually the FIRST EEXIST goes into the wait-loop, not the stale
415-
// check directly. So skip — just throw consistently to mark stale.
416-
throw new Error('ESRCH')
417-
}
418-
return true
397+
throw new Error('ESRCH')
419398
})
420399

400+
// Keep the binary absent until the liveness probe has run, so the wait
401+
// loop reaches the i % 5 === 4 stale check instead of returning early;
402+
// after the stale cleanup, the recursive call's cache check succeeds.
403+
mockExistsSync.mockImplementation(() => killCount >= 1)
404+
405+
// setTimeout: bypass the actual 1s polls so reaching i = 4 is instant.
406+
const realSetTimeout = globalThis.setTimeout
407+
;(globalThis as { setTimeout: unknown }).setTimeout = ((cb: () => void) => {
408+
cb()
409+
return 0 as never
410+
}) as never
411+
421412
try {
422-
// Either branch is fine — we just want coverage.
423-
await downloadGitHubReleaseBinary(baseSpec).catch(() => {
424-
// Some branches may throw timeout — accept it.
425-
})
413+
const result = await downloadGitHubReleaseBinary(baseSpec)
414+
expect(result).toContain('tool')
426415
} finally {
416+
;(globalThis as { setTimeout: unknown }).setTimeout = realSetTimeout
427417
;(process as { kill: unknown }).kill = realKill
428418
}
429419

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
diff --git a/dist/errors/stack.js b/dist/errors/stack.js
2+
index 320e3b3bf7144a9ecf1933d7050cb921b25ce807..95a74e12c5abc93d2d1e744b81bb830d89febd90 100644
3+
--- a/dist/errors/stack.js
4+
+++ b/dist/errors/stack.js
5+
@@ -2,6 +2,7 @@
6+
/* Socket Lib - Built with rolldown */
7+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
8+
let src_external_pony_cause = require("../external/pony-cause");
9+
+let src_errors_predicates = require("./predicates");
10+
11+
//#region src/errors/stack.ts
12+
/**
13+
@@ -18,7 +19,7 @@ let src_external_pony_cause = require("../external/pony-cause");
14+
* errorStack(e) })` safely.
15+
*/
16+
function errorStack(value) {
17+
- if (isError(value)) return (0, src_external_pony_cause.stackWithCauses)(value);
18+
+ if (src_errors_predicates.isError(value)) return (0, src_external_pony_cause.stackWithCauses)(value);
19+
}
20+
21+
//#endregion

pnpm-lock.yaml

Lines changed: 9 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pnpm-workspace.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,12 @@ patchedDependencies:
383383
# bundle loads on node-smol SEA builds, which ship without http2. Consumer:
384384
# packages/cli SEA binary.
385385
'@sigstore/sign@4.1.0': patches/@sigstore__sign@4.1.0.patch
386+
# The 6.0.9 rolldown build of dist/errors/stack.js drops the isError import
387+
# (source imports it from ./predicates), so every errorStack() call throws
388+
# ReferenceError. Restores the require so errorStack works. Consumer:
389+
# packages/cli src/util/command/registry-core.mts. Removable once a fixed
390+
# @socketsecurity/lib ships (source on main is already correct).
391+
'@socketsecurity/lib@6.0.9': patches/@socketsecurity__lib@6.0.9.patch
386392
# signal-exit is deduped to v4, which exports a named onExit instead of the
387393
# v3 default export execa calls; restores the call contract. Consumer:
388394
# packages/cli bundled npm tooling.

0 commit comments

Comments
 (0)