Skip to content

macOS clipboard image AppleScript never compiles, osascript path is dead code #1195

Description

@aphelion31

Summary

The macOS branch of clipboard_image() in crates/jcode-tui/src/tui/app/helpers.rs has never worked. The AppleScript fails to compile, so the whole osascript path is dead code and every image paste on macOS silently falls through to the arboard fallback.

Low user-visible impact, because arboard catches it. Filing it because the branch is a trap for whoever edits it next, and the intended higher-fidelity path is unreachable.

Environment

  • macOS 15, aarch64
  • jcode v0.84.0 (57d5878)

Reproduction

Straight from the shipped binary, no build required:

$ strings -a ~/.local/bin/jcode | grep representationUsingType
set pngData to bitmapRep's representationUsingType:(current application's NSBitmapImageFileTypePNG) properties:(missing value)

$ osascript -l AppleScript -e '<that same script>'
595:605: syntax error: Expected end of line, etc. but found plural class name. (-2741)

Expected: the script writes a PNG and returns ok or none.
Actual: it never compiles, so clipboard_image() always reaches the arboard fallback on macOS.

Root cause

Three defects in one string literal:

  1. properties is a plural class name in AppleScript's grammar. An unquoted properties: label in an ObjC-style message send aborts compilation with -2741 before any statement runs. It has to be escaped as |properties|:.
  2. representationUsingType:properties: rejects missing value for that argument and needs a real dictionary.
  3. \" escapes inside a Rust raw string. r#"use framework \"AppKit\""# passes literal backslashes to osascript -e, a syntax error on line 1 regardless of the rest.

Verified fix

set pngType to current application's NSBitmapImageFileTypePNG
set emptyProps to current application's NSDictionary's dictionary()
set pngData to bitmapRep's representationUsingType:pngType |properties|:emptyProps

Both branches checked by hand:

$ osascript -e 'set the clipboard to "halo"' && osascript -l AppleScript -e '<new script>'
none

$ osascript -e 'set the clipboard to (read (POSIX file "~/Pictures/Avatar.png") as «class PNGf»)'
$ osascript -l AppleScript -e '<new script>'
ok
$ file /tmp/jcode_clip_verify.png
PNG image data, 1254 x 1254, 8-bit/color RGB, non-interlaced

Reference branch

I have a branch with the fix plus two regression tests, but I cannot open a PR against this repo (CreatePullRequest returns a permissions error for my account), so linking it here instead:

https://github.com/aphelion31/jcode/tree/fix/macos-clipboard-image-applescript

Diff (2 files, +105/-17): master...aphelion31:jcode:fix/macos-clipboard-image-applescript

Contents:

  • Script body extracted into macos_clipboard_png_script() so it is testable without a clipboard fixture.
  • Nil guards on imgList / tiffData / bitmapRep / pngData, which would have thrown at runtime had the script ever compiled.
  • macos_clipboard_script_escapes_the_properties_label asserting source shape.
  • macos_clipboard_script_compiles_and_runs_under_osascript actually invoking osascript, so a rewrite that changes the string shape is still covered. An empty clipboard is a valid fixture: it exercises the full parse plus the else branch.

Both tests fail against the old script and pass against the new one, confirmed by reverting the fix in place:

# old script
test result: FAILED. 0 passed; 2 failed
  AppleScript failed to compile: 798:808: syntax error: Expected end of line,
  etc. but found plural class name. (-2741)

# fixed
test result: ok. 2 passed; 0 failed

cargo clippy --profile selfdev -p jcode-tui is clean on the touched file.

Edge cases and tradeoffs

  • Fixing this makes the osascript path take priority over arboard on macOS, as originally intended. It writes native PNG bytes rather than re-encoding decoded RGBA, so it is a fidelity improvement, but also a behavior change for anyone whose output currently comes from arboard.
  • The temp file is still a fixed jcode_clipboard.png, unchanged. Two concurrent instances pasting at once could race. Out of scope, noting it.
  • The compile test shells out to osascript. macOS-gated and sub-second, but not hermetic. Reasonable to drop it and keep only the string-shape assertion.
  • Unrelated but easy to conflate: terminals that intercept Cmd+V (VS Code's integrated terminal) hand jcode text-only paste and never reach this code. Ctrl+V / Alt+V work fine there. Different failure mode, terminal-side.

Per CONTRIBUTING.md, treating the branch as a reference and reproduction rather than something to merge as-is.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    autonomous: noNeeds your brain: a product/design decision is required before anyone acts.bugSomething isn't workingtriage: needs-decisionNeeds maintainer decision/design thought

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions