From 3ce51bb12c2f462862047ce2c23e31e6fa63b1f6 Mon Sep 17 00:00:00 2001 From: RetricSu Date: Thu, 29 Jan 2026 16:21:40 +0800 Subject: [PATCH 1/3] fix(debugger): use Node.js script on Windows to forward stdin properly On Windows, batch files (.cmd) do not forward stdin to child processes. This breaks tools like ckb-testtool that pass transaction data via stdin using spawnSync with the input option. Replace the Windows batch file with a Node.js script that uses spawn with stdio: 'inherit' to properly forward stdin, stdout, and stderr. --- src/tools/ckb-debugger.ts | 73 +++++++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 23 deletions(-) diff --git a/src/tools/ckb-debugger.ts b/src/tools/ckb-debugger.ts index e2a3fab..5afa177 100644 --- a/src/tools/ckb-debugger.ts +++ b/src/tools/ckb-debugger.ts @@ -134,12 +134,15 @@ export class CKBDebugger { * This creates a shell script that calls: offckb debugger [args] * Purpose: Reduce user friction by providing a placeholder when native binary is not available * Users can install the real ckb-debugger binary for better performance if needed + * + * On Windows, we create a Node.js script instead of a batch file because batch files + * do not properly forward stdin to child processes. This is critical for tools like + * ckb-testtool that pass transaction data via stdin (e.g., `--tx-file -`). */ static createCkbDebuggerFallback() { const fs = require('fs'); const { spawnSync } = require('child_process'); const isWindows = process.platform === 'win32'; - const binName = isWindows ? 'ckb-debugger.cmd' : 'ckb-debugger'; // Find the offckb binary location let offckbPath: string; @@ -158,41 +161,65 @@ export class CKBDebugger { // Get the directory where offckb is located const offckbDir = path.dirname(offckbPath); - const targetPath = path.join(offckbDir, binName); - - // Create the binary content - let binContent; - if (isWindows) { - // Windows batch file - binContent = `@echo off -offckb debugger %*`; - } else { - // Unix shell script - binContent = `#!/bin/sh -exec offckb debugger "$@"`; - } try { // Ensure directory exists - fs.mkdirSync(path.dirname(targetPath), { recursive: true }); - - // Write the binary - fs.writeFileSync(targetPath, binContent); + fs.mkdirSync(offckbDir, { recursive: true }); + + if (isWindows) { + // On Windows, create a Node.js script that properly forwards stdin + // Batch files (.cmd) do NOT forward stdin to child processes, which breaks + // tools like ckb-testtool that use `spawnSync('ckb-debugger', args, { input: data })` + const jsPath = path.join(offckbDir, 'ckb-debugger.js'); + const cmdPath = path.join(offckbDir, 'ckb-debugger.cmd'); + + // Node.js script that uses spawn with stdio: 'inherit' to forward stdin properly + const jsContent = `#!/usr/bin/env node +const { spawn } = require('child_process'); +const child = spawn('offckb', ['debugger', ...process.argv.slice(2)], { + stdio: 'inherit', + shell: false +}); +child.on('error', (err) => { + console.error('Failed to start offckb:', err.message); + process.exit(1); +}); +child.on('exit', (code) => { + process.exit(code ?? 0); +}); +`; + + // CMD wrapper that calls the Node.js script + // %~dp0 expands to the directory containing the batch file + const cmdContent = `@echo off +node "%~dp0ckb-debugger.js" %* +`; + + fs.writeFileSync(jsPath, jsContent); + fs.writeFileSync(cmdPath, cmdContent); + + logger.info(`✅ Created ckb-debugger fallback at: ${cmdPath}`); + logger.info(` Helper script: ${jsPath}`); + } else { + // Unix shell script - use exec to replace the shell process + // This ensures stdin is properly inherited by offckb + const targetPath = path.join(offckbDir, 'ckb-debugger'); + const binContent = `#!/bin/sh +exec offckb debugger "$@"`; - // Make executable on Unix systems - if (!isWindows) { + fs.writeFileSync(targetPath, binContent); fs.chmodSync(targetPath, '755'); + + logger.info(`✅ Created ckb-debugger fallback at: ${targetPath}`); } - logger.info(`✅ Created ckb-debugger fallback at: ${targetPath}`); logger.info(` This fallback uses WASM and calls: offckb debugger [args]`); logger.info( ` For better performance, install the real binary: cargo install --git https://github.com/nervosnetwork/ckb-standalone-debugger ckb-debugger`, ); - logger.info(` To uninstall the fallback binary: rm ${targetPath}`); } catch (error: unknown) { logger.error(`❌ Failed to create ckb-debugger fallback: ${(error as Error).message}`); - logger.error(` Make sure you have write permissions to: ${path.dirname(targetPath)}`); + logger.error(` Make sure you have write permissions to: ${offckbDir}`); process.exit(1); } } From 5a8591e198a911508bbc580def78643da46f4048 Mon Sep 17 00:00:00 2001 From: RetricSu Date: Thu, 29 Jan 2026 16:33:22 +0800 Subject: [PATCH 2/3] feat(test): enable Windows mock tests with native debugger Now that Windows supports stdin forwarding via the Node.js wrapper, we can enable mock tests on Windows by commenting out the setWasmDebuggerEnabled(true) line in generated test files. Changes: - Detect Windows platform early in create-test.sh - Post-process mock.test files on Windows to comment out WASM mode - Remove Windows test skip logic (now runs all tests on all platforms) This allows GitHub Actions Windows CI to test the stdin forwarding fix. --- scripts/create-test.sh | 55 ++++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/scripts/create-test.sh b/scripts/create-test.sh index e085fed..fdb1833 100755 --- a/scripts/create-test.sh +++ b/scripts/create-test.sh @@ -143,6 +143,39 @@ done echo "✓ All essential files are present" +# Detect if we're on Windows +# In GitHub Actions, even with bash shell, we're still on Windows OS +IS_WINDOWS=false +if [[ "$OSTYPE" == "cygwin" ]] || [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]]; then + IS_WINDOWS=true +elif [[ "$(uname -s)" == MINGW* ]] || [[ "$(uname -s)" == MSYS* ]]; then + IS_WINDOWS=true +elif [[ -n "$WINDIR" ]] || [[ -n "$windir" ]]; then + # WINDIR environment variable is set on Windows + IS_WINDOWS=true +fi + +# On Windows, comment out setWasmDebuggerEnabled in mock tests +# Windows now supports stdin forwarding via Node.js wrapper, so we can use native debugger +if [ "$IS_WINDOWS" = true ]; then + echo "" + echo "Configuring tests for Windows..." + echo " Commenting out setWasmDebuggerEnabled in mock tests (using native debugger instead)" + + # Find all mock.test files and comment out the setWasmDebuggerEnabled line + find "$TEST_PROJECT_DIR/tests" -name "*.mock.test.*" -type f | while read -r test_file; do + if [ -f "$test_file" ]; then + # Use sed to comment out the setWasmDebuggerEnabled line + # Works for both .ts and .js files + sed -i.bak 's/\(.*\)verifier\.setWasmDebuggerEnabled(true);/\1\/\/ verifier.setWasmDebuggerEnabled(true);/' "$test_file" + rm -f "${test_file}.bak" + echo " ✓ Modified: $(basename "$test_file")" + fi + done + + echo " ✓ Mock tests configured for Windows (native debugger mode)" +fi + # Install dependencies explicitly to make test deterministic echo "" echo "Installing dependencies..." @@ -217,27 +250,7 @@ echo "" echo "Running tests..." cd "$TEST_PROJECT_DIR" -# Check if we're on Windows -# In GitHub Actions, even with bash shell, we're still on Windows OS -IS_WINDOWS=false -if [[ "$OSTYPE" == "cygwin" ]] || [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]]; then - IS_WINDOWS=true -elif [[ "$(uname -s)" == MINGW* ]] || [[ "$(uname -s)" == MSYS* ]]; then - IS_WINDOWS=true -elif [[ -n "$WINDIR" ]] || [[ -n "$windir" ]]; then - # WINDIR environment variable is set on Windows - IS_WINDOWS=true -fi - -if [ "$IS_WINDOWS" = true ]; then - echo "⚠ Skipping mock tests on Windows due to WASI path compatibility issues" - echo " (ckb-testtool WASM debugger doesn't support Windows paths yet)" - echo " Running devnet tests only..." - # Only run devnet tests on Windows (mock tests use WASI which has path issues) - pnpm run test:only --testPathIgnorePatterns "mock.test.ts" -else - pnpm run test -fi +pnpm run test echo "✓ All tests passed" From 3903ec561bd83b5aa29d85b2a057532f984390a9 Mon Sep 17 00:00:00 2001 From: RetricSu Date: Thu, 29 Jan 2026 16:35:14 +0800 Subject: [PATCH 3/3] fix(debugger): use shell mode on Windows to resolve offckb.cmd On Windows, npm global installs create .cmd files that require shell execution. Change the Node.js wrapper to use shell: isWindows so that spawn can properly find and execute offckb.cmd via cmd.exe. This fixes the build failure in CI: Failed to start offckb: spawn offckb ENOENT --- src/tools/ckb-debugger.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tools/ckb-debugger.ts b/src/tools/ckb-debugger.ts index 5afa177..e2fb367 100644 --- a/src/tools/ckb-debugger.ts +++ b/src/tools/ckb-debugger.ts @@ -176,9 +176,10 @@ export class CKBDebugger { // Node.js script that uses spawn with stdio: 'inherit' to forward stdin properly const jsContent = `#!/usr/bin/env node const { spawn } = require('child_process'); +const isWindows = process.platform === 'win32'; const child = spawn('offckb', ['debugger', ...process.argv.slice(2)], { stdio: 'inherit', - shell: false + shell: isWindows }); child.on('error', (err) => { console.error('Failed to start offckb:', err.message);