Skip to content

fix: chalk boolean style modifiers — <Text dimColor> no longer renders [object Object] (#5039)#5045

Merged
proggeramlug merged 2 commits into
mainfrom
worktree-fix-5039-ink-dimcolor
Jun 12, 2026
Merged

fix: chalk boolean style modifiers — <Text dimColor> no longer renders [object Object] (#5039)#5045
proggeramlug merged 2 commits into
mainfrom
worktree-fix-5039-ink-dimcolor

Conversation

@proggeramlug

@proggeramlug proggeramlug commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Fixes #5039 — ink <Text dimColor> rendered [object Object] instead of its text.

chalk 5's style modifiers are getter accessors on a function prototype chain (Object.defineProperties(createChalk.prototype, styles), reached via Object.setPrototypeOf(chalk, createChalk.prototype) where chalk is itself a function). Four independent gaps conspired so chalk.dim never resolved; the issue's "boolean modifier vs string color" framing turned out to be a red herring — color="cyan" only looked fine because broken chalk made ink fall back to the unstyled string.

The four fixes

  1. runtime — closure/dynamic_props.rs: closure_get_dynamic_prop's static-prototype walk only consulted data properties. Both arms (closure proto and plain-object proto) now resolve accessor descriptors, invoking the getter with the original receiver (clone_closure_rebind_this), so chalk's Object.defineProperty(this, styleName, {value: builder}) self-cache lands on the instance instead of throwing Cannot redefine property: dim against the non-configurable accessor on the shared proto.

  2. codegen — lower_call/property_get.rs: Annex B HTML-wrapper names (bold, link, anchor, big, …) on any-typed receivers were force-routed to String.prototype, so chalk.bold(s) coerced the chalk closure to its source text and returned <b>(...strings) => strings.join(' ')</b>. Dropped them from the force list; an Any receiver that really is a string still resolves through the jsval.is_string() arm of js_native_call_method (covered in the gap test).

  3. resolver — commands/compile/resolve.rs: Node subpath imports (#-prefixed specifiers via the package's own package.json "imports" map) were unsupported, so chalk's import ansiStyles from '#ansi-styles' (vendored dep) silently resolved to nothing and every style table came up empty. Reuses the exports-conditions resolver with node ranked above default (chalk's #supports-color ships a browser build as default). Per Node's package-scope rule only the nearest package.json is consulted.

  4. HIR — lower_patterns.rs: unescape_template didn't decode \xHH / \uHHHH / \u{…} (nor \b \f \v \0, line continuations), so ansi-styles' `\^[[${code}m` template literals produced 6 literal chars instead of ESC. Surrogate pairs combine; a lone surrogate becomes U+FFFD (WTF-8 stays a categorical gap).

Validation

  • New test-files/test_gap_chalk_proto_styles_5039.ts — byte-identical vs node --experimental-strip-types (chalk's exact proto shape incl. the defineProperty self-cache, nested chalk.dim.bold, Annex B-on-string behavior, template escapes).
  • Real chalk 5 compiled via perry.compilePackages produces Node-identical ANSI output for dim/bold/cyan.
  • The issue's ink repro (main now includes feat: native yoga-layout via taffy + JSON module imports — ink #348 end-to-end #5038) renders all lines correctly on this branch:
    ^[[2mA dimColor plain ascii^[[22m
    B plain text
    ^[[36mC colored ascii^[[39m
    ^[[1mD bold ascii^[[22m
    
    (cyan now emits real escapes too — previously it silently rendered unstyled.)
  • 3 new resolver unit tests for the imports map (exact, conditional node/default, unmapped).
  • cargo test --release for perry-hir / perry-codegen / perry-runtime / perry: green (issue_4908_subclass_native_member_base failed once under full-suite load, passes in isolation — known load artifact).
  • Full parity sweep (886-file corpus): 716 pass / 47 parity-fail / 0 compile-fail (93.8%). All 47 fails verified pre-existing: re-ran the exact subset on a baseline build of a46ca1dd6 (pre-fix main) — 46 fail identically there, and the 47th (test_issue_2131_net_lifecycle_edge) is the documented load flake (passes 100% idle on this branch).

Deferred (pre-existing, observed while validating)

Rebased onto main after #5038/#5040/#5043/#5041 landed; this PR is v0.5.1163.

@proggeramlug proggeramlug force-pushed the worktree-fix-5039-ink-dimcolor branch from c76b100 to e62a73b Compare June 12, 2026 19:10
@proggeramlug proggeramlug merged commit 6c85905 into main Jun 12, 2026
13 checks passed
@proggeramlug proggeramlug deleted the worktree-fix-5039-ink-dimcolor branch June 12, 2026 20:26
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.

ink: <Text dimColor> renders as [object Object]

1 participant