Skip to content

fix(node): resume injected TLS and HTTP connections - #7

Merged
steipete merged 1 commit into
openclaw:mainfrom
RomneyDa:resume-injected-http-tls-connections
Sep 30, 2026
Merged

steipete merged 1 commit into
openclaw:mainfrom
RomneyDa:resume-injected-http-tls-connections

Conversation

@RomneyDa

Copy link
Copy Markdown
Member

Summary

  • start the TLS read side when a paused socket is injected into tls.Server
  • resume paused sockets consumed by the JavaScript HTTP/1 fallback parser
  • cover both handoffs with Node-compatible regression tests

Why

OpenClaw's protected egress proxy intentionally pauses sockets while transferring ownership between an HTTP CONNECT server, a TLS server, and an HTTP server. Node consumes both injected sockets successfully. Bun accepted the handoffs but left the transports paused:

  • CONNECT returned 200, then the TLS ClientHello timed out
  • resuming the raw socket allowed TLS to complete, then the decrypted HTTP request timed out
  • resuming both handoffs completed the request

The installed OpenClaw fork build was reproduced at 699ba4ddd138994fb258de53669d481cdcf1016d (Bun 1.4.3). The same credential-free probe under Node 26.8.2 completed both handoffs.

Validation

  • Node 26.9.0: paused raw socket injected into http.Server returns HTTP 200
  • Node 26.9.0: paused raw socket injected into https.Server completes TLS and returns HTTP 200
  • prettier@3.6.2 on all changed files
  • git diff --check

Full Bun execution requires the fork build/CI toolchain; the regressions are included in test/js/node/http/node-http.test.ts.

@steipete
steipete merged commit e89f965 into openclaw:main Sep 30, 2026
5 of 6 checks passed
steipete added a commit that referenced this pull request Sep 30, 2026
Merge upstream Bun through `ba3f27d1d1ce359d4eed842c135f0f6fba1acb00` into fork main, retaining upstream and contributor history. Land with a merge commit to retain upstream ancestry. All fork fixes #15, #7, #14, and #27 are incorporated and qualified.

The five conflict resolutions preserve the fork’s behavior while integrating upstream changes:

- Keep macOS `ProcessRetry` alongside upstream’s `Tty` event-loop flag.
- Keep the richer worker `execArgv` record and parser for preloads, TLS trust, CPU profiling, and addon/FFI restrictions; incorporate upstream’s invalid process-only flag reporting and its C++ error channel.
- Keep literal `?` file-URL handling in the module loader alongside upstream’s string-code-generation guards.
- Retain one upstream-positioned `ERR_WORKER_INVALID_EXEC_ARGV` mapping; both histories added it, and the automatic merge initially duplicated it.

The fork fixes landed since the previous sync `ee83b78b18` remain present: file-URL preloads (#22), response-finish diagnostics (#23), and macOS silent-run signal/stdio handling (#24). Earlier fork changes are retained by the merge. Upstream’s addon/FFI worker restrictions overlap the fork’s broader implementation; the shared behavior is retained in one parser, with upstream’s new invalid-flag handling added.

WebKit remains `f20ce7744553c910bcf16a33faf976af208de091` on both sides. Direct source inspection confirms that `DFGSSALoweringPhase.cpp` lowers `StringAt`, `StringCharCodeAt`, and `StringCodePointAt` to independent `CheckInBounds` nodes, and the pin includes `JSTests/stress/string-index-dce-bounds-check.js`. This is the upstream replacement for closed oven-sh/WebKit#578, so no pin rollback is needed. The release documentation now reflects that fix.

Final integration also retained both sides of the changelog conflict and added contributor credit for @SebTardif and @RomneyDa. The runtime plugin cache format remains version 34; the frozen upstream uses 33.

Native qualification exposed a pre-existing fork mismatch with two new upstream idle-sweep tests: cached idle state stays false until message timing clears, even after a bodyless response ends inside its handler. Explicit Node HTTP idle sweeps now derive response availability while preserving incomplete TLS handshakes, application-owned parser-error sockets, request bodies, partial heads, queued responses, and tunnels. Both upstream one-read/split-head tests pass unchanged, as does the existing parser-error ownership test. A TLS 1.2 relay control proves a sweep cannot close a handshake in progress. Node 26.10.0 confirms the bodyless close behavior.

Qualified head: `41dffc47212456d5ac80fc6fdddda08c4e4bfccc`, macOS arm64 release build (Bun 1.4.3, WebKit `f20ce7744553c910bcf16a33faf976af208de091`). No local SDK signpost patch was needed. Binary, hardening, duplicate-symbol, formatting, and applicable hosted checks passed. Codex review has no remaining accepted/actionable P0–P2 findings; the rejected non-regular-copy concern is ruled out by unchanged regular-file guards and eight matching baseline/candidate FIFO/device controls.

| File | Pass | Skip | Todo | Fail |
| --- | ---: | ---: | ---: | ---: |
| `test/js/bun/terminal/terminal.test.ts` | 97 | 2 | 0 | 0 |
| `test/js/bun/terminal/terminal-spawn.test.ts` | 23 | 2 | 0 | 0 |
| `test/js/bun/spawn/spawn.test.ts` | 165 | 24 | 0 | 0 |
| `test/js/node/child_process/child-process-stdio.test.js` | 9 | 0 | 0 | 0 |
| `test/js/node/http/node-http.test.ts` | 277 | 1 | 0 | 0 |
| `test/js/node/diagnostics_channel/diagnostics_channel.test.ts` | 26 | 0 | 3 | 0 |
| `test/js/node/sqlite/node-sqlite.test.ts` | 143 | 4 | 0 | 0 |
| `test/js/node/worker_threads/worker_threads.test.ts` | 172 | 0 | 0 | 0 |
| `test/cli/run/preload-test.test.js` | 2 | 0 | 3 | 0 |
| `test/cli/run/no-orphans.test.ts` | 15 | 9 | 0 | 0 |
| `test/cli/install/bun-install-lifecycle-scripts.test.ts` | 70 | 0 | 0 | 0 |
| `test/js/node/fs/fs.test.ts` | 660 | 16 | 0 | 0 |
| `test/js/node/fs/cp.test.ts` | 54 | 6 | 0 | 0 |
| `test/cli/run/transpiler-cache.test.ts` | 27 | 0 | 0 | 0 |
| `test/cli/test/isolation.test.ts` | 41 | 0 | 0 | 0 |
| `test/js/bun/plugin/plugins.test.ts` | 47 | 0 | 0 | 0 |
| `test/js/bun/plugin/plugin-namespace-drive-letter.test.ts` | 1 | 0 | 0 | 0 |
| `test/js/node/disallow-code-generation-from-strings.test.ts` | 28 | 0 | 0 | 0 |
| `test/js/node/http/node-http-server-abort-events.test.ts` | 105 | 0 | 0 | 0 |
| `test/js/node/http/node-http-server-close-drain.test.ts` | 31 | 0 | 0 | 0 |
| `test/js/node/http/node-http-connect.test.ts` | 80 | 1 | 2 | 0 |
| `test/js/node/http/node-http-upgrade-body.test.ts` | 11 | 2 | 0 | 0 |
| `test/js/node/http/node-http-req-socket-pause.test.ts` | 40 | 0 | 0 | 0 |
| `test/js/node/tls/node-tls-server.test.ts` | 99 | 0 | 0 | 0 |
| `test/js/node/tls/node-tls-wrapped-socket-close.test.ts` | 15 | 0 | 0 | 0 |
| `test/cli/install/bun-install-patch.test.ts` | 32 | 0 | 0 | 0 |
| `test/js/bun/io/bun-write.test.js (stream fallback only)` | 1 | 0 | 0 | 0 |
| `test/bundler/compile-argv.test.ts (compiled code-generation flags)` | 3 | 0 | 0 | 0 |
| **Total** | **2274** | **67** | **8** | **0** |

Filesystem and isolation suites used outer concurrency 2; nested stress work, assertions, and timeouts were unchanged. Lifecycle, TLS, and compiled-argument tests enabled the existing internal-test API at process startup (`BUN_FEATURE_FLAG_INTERNAL_FOR_TESTING=1`, `BUN_GARBAGE_COLLECTOR_LEVEL=0`). Initial lifecycle/TLS invocations without those startup flags could not load `bun:internal-for-testing`.

Earlier runs encountered recursive-readdir and copy-stress timeouts; the same readdir workload exceeded its deadline on the pre-sync baseline. Both full filesystem suites passed on the final head. The terminal ESRCH test missed its real kernel race window once (its path-reached assertion failed); the unchanged complete file passed on retry. The known broader Bun.write Response timeout was reproduced on a separately built pre-change baseline during #27 qualification and is not claimed as a passing full-suite run here; the added stream-fallback regression passes.

Additional proof: normal/strict data/blob imports and Workers behaved as expected in all 16 probes; the compiled-argument tests preserve quoted strict-mode floors. OpenClaw smoke with the built runtime passed: `OpenClaw 2026.9.6 (23ad3a5)`. No tag or release is part of this PR.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants