Skip to content

Conversation

@Saadnajmi
Copy link
Collaborator

@Saadnajmi Saadnajmi commented Nov 26, 2025

Summary:

Resolves #2738

Borders and box shadows didn't render consistently. shadows would disappear if i resized the view, and most borders didn't render at all. I asked VSCode Copilot with Claude Opus 4.5 to debug, and after lots of back and forth, we are here..

Summary
This PR fixes rendering issues with borders and box shadows on macOS in Fabric. The core problem was that NSImage's CGImageForProposedRect: returns a new autoreleased CGImageRef each time it's called, which causes issues when used with CALayer.contents - the CGImage would get deallocated while still being referenced by Core Animation.

Changes

  1. RCTUIImage - NSImage subclass with cached CGImage (RCTUIKit.h, RCTUIKit.m)
    Created RCTUIImage, a subclass of NSImage that caches its CGImageRef representation
    The cached CGImage is retained and only released on dealloc, ensuring it stays valid while used by CALayer.contents
    Added .CGImage property that returns the cached CGImage
    Updated UIImageGetCGImageRef() to use the new .CGImage property
    Updated UIImageWithContentsOfFile() and UIImageWithData() to return RCTUIImage
    Changed @compatibility_alias UIImage from NSImage to RCTUIImage
  2. RCTUIGraphicsImageRenderer improvements (RCTUIKit.m)
    Changed imageWithActions: to return RCTUIImage instead of NSImage
    Replaced the deferred drawingHandler: block approach with immediate bitmap context rendering
    This ensures the image data is fully rendered and available for CGImage extraction
    Properly handles scale factor and coordinate system flipping
  3. RCTViewComponentView fixes (RCTViewComponentView.mm)
    Border layer frame: Added explicit frame update for _borderLayer on macOS to handle view resizing
    Box shadow z-position: Fixed _boxShadowLayer.zPosition to be behind content (BACKGROUND_COLOR_ZPOSITION - 1)
    Container view clipping: Fixed clipsToBounds and layer.masksToBounds handling for macOS:
    When _useCustomContainerView is true (boxShadow + overflow:hidden), the container view handles clipping while the main layer stays unclipped for the shadow
    Explicitly set wantsLayer = YES on container view
    CGImage usage: Updated to use image.CGImage directly instead of UIImageGetCGImageRef(image)
    Root Cause
    On macOS, NSImage's CGImageForProposedRect:context:hints: creates a new autoreleased CGImageRef each call. When this was assigned to CALayer.contents, the CGImage would be deallocated during the next autorelease pool drain, leaving the layer with a dangling pointer. This caused rendering artifacts and potential crashes.

Testing
Tested borders with various styles (solid, dashed, different colors per side)
Tested box shadows (inset and outset) with overflow:hidden
Tested combined borders + shadows + clipping scenarios

Test Plan:

RNTester seems better :)

Screen.Recording.2025-11-26.at.3.39.04.PM.mov

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.

[Fabric] TextInput is missing border rendering

1 participant