Skip to content

feat(ios): show the app's forwarded stdout and stderr - #6181

Draft
rigor789 wants to merge 11 commits into
feat/ios-structured-logsfrom
feat/ios-stdio-logs
Draft

rigor789 wants to merge 11 commits into
feat/ios-structured-logsfrom
feat/ios-stdio-logs

Conversation

@rigor789

@rigor789 rigor789 commented Oct 30, 2026 •

Copy link
Copy Markdown
Member

Draft for the same reason as its base: it can't compile until ios-device-lib is released and bumped.

What is the current behavior?

print() output and, on devices, NSLog never reach the CLI, even with --log debug, because the app's stdio is /dev/null.

What is the new behavior?

  • Debug builds write forwardStdio to the app's package.json, next to logFormat.
  • Entries under the org.nativescript.stdio subsystem show from --log debug up, labeled stdout: or stderr:, like the rest of the app's native output and Xcode's console.
  • The default scope stays JS only.

If a device falls back to the syslog relay, forwarded lines arrive as ordinary syslog text with the subsystem visible in them. They aren't hidden by scope there.

Testing

Results are in NativeScript/ios#532, and unit tests cover the scope, labels, stitching and the key. Release prepare leaves the key out.

Part of a stack

Base: #6179. Needs NativeScript/ios#532.

restartApplication launched the app and then connected to its debug socket with ensureAppStarted, which launched it again with --terminate-existing and killed the first process. The socket now connects to the running instance. A launch waiting for a debugger keeps the second start, since that instance cannot answer the attach request.
@coderabbitai

coderabbitai Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

The socket setup started the app a second time for debug-brk, replacing the instance waiting for the debugger with one that ran straight on.
…nects

The port check bound localhost while the server binds every interface, and on macOS those do not conflict, so a taken port passed the check and the listen crashed the CLI. The check now tests all four addresses and the proxy moves on if the bind still fails.

The connection lock was released on the connection event, which never fires for a client that drops during the handshake, so every later client timed out until the CLI exited. A late close from a replaced client could also destroy the socket its successor had just received. Connections now run through an in-process queue, and each session only cleans up after itself; a replaced client is closed with a reason.

Also clears the port service's timers, whose number type check never matched in Node, which produced false port warnings.
…d DevTools

The proxy listened on every interface with no origin check, while the debugger can run any code in the app. Anything on the network, or any web page, could connect. It now binds the two loopback addresses and rejects browser origins other than DevTools and localhost.
The backend close handler cleared the session before closing the WebSocket, so the WebSocket's close handler no longer saw it as current and skipped destroying the socket and exiting without --watch.
DerivedData moves into platforms/ios/build through the per-user WorkspaceSettings, so CLI and Xcode builds reuse each other's output. Settings that made the two builds differ come off the xcodebuild command line: -sdk and forced explicit modules are gone, and the deployment target moves into the Podfile post_install.

Simulator builds target the specific destination, debug device builds use a plain build instead of an archive, and the compilation cache lives in platforms/.cache/ios. Device discovery stops waiting as soon as the requested device is found.
With 100 ms polling, an unrelated device ended the wait almost immediately. A requested device now only ends it by being found, and otherwise the 2 seconds the old polling allowed still apply, so device indexes stay stable.
Devices stream com.apple.os_trace_relay and simulators use log stream, both selected by executable name, so logs survive closing and reopening the app. --log picks the scope: JS output by default, the app's native logs without debug entries with debug, everything with trace or all. Without a new enough ios-device-lib, devices fall back to the syslog relay.

Debug builds ask the runtime for chunk markers through logChunkMarkers in the app's package.json, and the CLI stitches split messages back together per process and thread.
@rigor789
rigor789 force-pushed the feat/ios-structured-logs branch from bfef406 to 8783785 Compare October 30, 2026 22:15
@rigor789
rigor789 force-pushed the feat/ios-stdio-logs branch from bbb183e to 3816e9c Compare October 30, 2026 22:15
edusperoni and others added 2 commits November 8, 2026 16:36
Asks the runtime for log format 1 through the logFormat key of the app's
package.json, in place of logChunkMarkers.

In format 1, each piece of a message the runtime had to split is logged as
"[ns <id> <index>/<count>] <piece>", where the pieces are consecutive
slices of the message. The stitcher now collects pieces by process and
message id, prints the message as soon as its last piece arrives, and
after 500 ms prints what it has with "<…lost…>" where pieces never
arrived. A message can no longer be joined onto another one whose last
piece os_log dropped.

Pieces are joined before the entry is turned into text, so the repeated
console prefix no longer has to be stripped. The syslog fallback, which
doesn't reassemble, removes the headers and shows the pieces as lines.
Debug builds ask the runtime to forward stdout and stderr through forwardStdio in the app's package.json. They arrive under the org.nativescript.stdio subsystem and show from --log debug, like the rest of the app's native output and as Xcode's console does, labeled with their stream.
@edusperoni
edusperoni force-pushed the feat/ios-structured-logs branch from 5461769 to e9a3bd7 Compare November 8, 2026 19:39
@edusperoni
edusperoni force-pushed the feat/ios-structured-logs branch from e9a3bd7 to 071afe8 Compare November 8, 2026 19:58

This branch has not been deployed

No deployments
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