Grounded in a source-level audit of WebKit trunk (July 2026), the GNUstep core library stack installed on NextBSD (libs-opal, libs-quartzcore, libs-corebase, libs-av, gnustep-base, gnustep-gui), and lessons from four prior porting attempts (v1–v4). This plan ports the macOS/Cocoa WebKit — not the GTK or Linux port — using native GNUstep framework implementations with zero GTK, GLib, GStreamer, Skia, Mesa, or Wayland dependencies.
libs-opal/Cairo), CoreText (libs-opal/FreeType), CoreFoundation (libs-corebase), QuartzCore (libs-quartzcore), AVFoundation (libs-av/FFmpeg), Foundation (gnustep-base), AppKit (gnustep-gui).OptionsMac.cmake/OptionsCocoa.cmake. Create OptionsGNUstep.cmake that mirrors the Mac port's choices, not the GTK port's.libs-security, libs-iosurface, libs-corevideo, libs-coremedia), (b) API additions to existing libs, or (c) minimal compile-time stubs for features disabled in the initial build.MiniBrowser.app window.data:text/html colored background) then iterate.We are porting the Cocoa WebKit. Every architectural decision follows what Apple's port does. When in doubt about how to structure something — a process, a rendering pipeline step, a threading model — look at Source/WebKit/Platform/mac/, Source/WebCore/platform/cocoa/, and Source/WebKit/UIProcess/Cocoa/. Those are the references.
Zero GTK, GLib, GStreamer, Skia, libsoup, Mesa, Wayland as WebKit dependencies. GNUstep's backends may use X11/Cairo internally — that's behind the framework boundary, not WebKit's concern. WebKit calls CGContextFillRect(), not cairo_fill(). What Cairo does internally inside libs-opal is irrelevant to WebKit.
Where GNUstep is missing an API that macOS provides, the correct fix is to add that API to the appropriate GNUstep core lib (or create a new one) — not to substitute a Linux library. Substituting a Linux library is what v1 through v4 attempted in various ways, and it always led to architectural rot. The GNUstep framework stack exists precisely to avoid this. Use it. Extend it where necessary.
Every missing API is documented (see §5 below). The gap list IS the work plan for GNUstep framework development. Gaps have three resolution paths:
#if PLATFORM(GNUSTEP) — acceptable for code paths we explicitly disable (no Metal, no GPU process, etc.).If macOS WebKit doesn't link against it, neither do we. The dependency list should be: GNUstep core libs + libcurl (inside NSURLSession) + libxml2 + libxslt + sqlite3 + ICU + image libs (png, jpeg, webp) + font libs (freetype, harfbuzz, fontconfig) + woff2. That's it. Any build script that adds glib, gtk, gstreamer, or libsoup to the dependency list has gone off-track.
Disable everything optional. Get data:text/html,<body style="background:red"> rendering in MiniBrowser.app. Then iterate. Each phase adds one category of capability and verifies it before moving on. A browser that shows a red window is infinitely more valuable than a browser that almost compiles with video support.
| Version | Base Port | Graphics | Result |
|---|---|---|---|
| v1 | GTK (strip GLib) | Skia | Abandoned — ~565 files to replace; GLib is woven through every GTK WebKit source file at the include level |
| v2 | Windows port (no GLib) | Skia | Better — ~279 files, but still building a from-scratch browser on top of a non-Cocoa base |
| v3 | Windows + Mac MiniBrowser shell | Skia | Build succeeded — window opens, no pixels rendered; AcceleratedSurface::create() was RELEASE_ASSERT_NOT_REACHED() |
| v4 | v3 + PageClient bridge | Skia | Bridge designed — WKViewGNUstepPaint → NSBitmapImageRep → drawInRect: path architected; pixels never appeared because Skia's surface creation was unimplemented |
MiniBrowser/ compiles under GNUstep with relatively few changes — it uses standard AppKit.WKViewGNUstepPaint → NSBitmapImageRep → drawInRect: pixel blit path is architecturally sound. The problem was never the NSView side — it was the upstream rendering surface.AcceleratedSurface::create() was RELEASE_ASSERT_NOT_REACHED() on every platform attempted.CGContextFillRect() is using Apple's CG or libs-opal's Cairo under the hood.The critical point: WebKit code doesn't change. It calls CGContextFillRect(), CTFontGetGlyphsForCharacters(), [CALayer addSublayer:], [NSView setNeedsDisplay:] — identical calls on macOS and GNUstep. The framework implementations differ internally. The call sites in WebKit source remain the same.
macOS WebKit uses Mach ports for IPC and XPC for process launching. GNUstep uses Unix domain sockets — this was proven viable in v3/v4 using the PlayStation port's Source/WebKit/Platform/IPC/unix/ConnectionUnix.cpp. We do not use GLib's GSocket or any GLib construct. MachSendRight wrapper types get POSIX file-descriptor equivalents. NSXPCConnection in gnustep-base provides basic XPC-style IPC; process launching uses fork(2)/execve(2) directly.
For the initial single-process build (Phase 1–3), none of this IPC machinery is exercised — everything runs in a single process. Multi-process comes in Phase 3.
For each Apple framework that macOS WebKit depends on, this section documents what GNUstep currently provides and what is missing. This gap table is the definitive work plan.
GNUstep implementation: libs-opal — 35 public headers, Cairo rendering backend, LCMS2 color management.
| API | GNUstep Status | Notes |
|---|---|---|
| CGContext (full drawing API) | Yes | All blend modes, paths, gradients, clipping, transforms, text drawing |
| CGBitmapContext | Yes | CGBitmapContextCreate, CGBitmapContextCreateImage, data access |
| CGPath (mutable/immutable) | Yes | Full path construction, arcs, curves, ellipses, rounded rects |
| CGImage | Yes | All pixel formats, alpha modes, premultiplied/non-premultiplied |
| CGImageSource / CGImageDestination | Yes | PNG, JPEG, TIFF, GIF decoding and encoding |
| CGColor / CGColorSpace | Yes | LCMS2 backend for color management; sRGB, DisplayP3, generic CMYK |
| CGFont | Yes | FreeType/Fontconfig backend; glyph metrics, advances, bounding boxes |
| CGGradient / CGShading | Yes | Linear, radial gradients; axial and radial shadings |
| CGPattern | Yes | Pattern fills, colored and stencil patterns |
| CGLayer | Yes | Offscreen drawing surfaces, reusable across contexts |
| CGPDFDocument / CGPDFPage / CGPDFContext | Yes | Full PDF read/write support via Cairo PDF backend |
| CGAffineTransform | Yes | All transform construction and application functions |
| CGDataProvider / CGDataConsumer | Yes | Callback-based and direct-pointer data access |
CGContextDrawConicGradient — not in libs-opal. Needed for CSS conic-gradient(). Cairo supports conic gradients since 1.17; needs to be wrapped.
CGPathAddUnevenCornersRoundedRect, CGPathAddContinuousRoundedRect — not in libs-opal. Required for CSS border-radius with per-corner radii and iOS-style "squircle" rounding. Must add to libs-opal.
CGColorSpaceUsesExtendedRange, CGColorSpaceCopyICCProfileDescription — color management SPI. Stub as no-op / return nil initially; add LCMS2 implementation later.
CGImageSetCachingFlags, CGImageSetProperty — image cache control SPI. Safe to stub as no-ops.
CGContextSetBaseCTM — SPI. Map to CGContextSetCTM or stub; verify impact on text rendering.
CGStyleRef family — CGStyleCreateFocusRingWithColor, CGStyleCreateShadow2, CGStyleCreateGaussianBlur, CGStyleCreateColorMatrix. Used for CSS filters (blur, drop-shadow, color-matrix). Stub initially; implement using Cairo's filter/surface API or a software pass.
CGIOSurfaceContextCreate and all IOSurface-backed CG APIs. Requires libs-iosurface (see §6). Not needed for Phase 1–4 software rendering path.
CGDisplayScreenSize, CGDisplayModeGetPixelsWide, CGDisplayModeGetPixelsHigh — display management. Implement behind the API using X11/RandR queries or XGetGeometry.
CGS* Window Server SPI — CGSConnectionID, CGSSetWindowAlpha, CGSSetWindowLevel, etc. Mach/WindowServer-specific. Guard with #if PLATFORM(GNUSTEP) and stub; not applicable under X11.
CGContextDrawConicGradient, CGPathAddUnevenCornersRoundedRect) that need to be added to libs-opal.
GNUstep implementation: CoreText is provided by libs-opal (the same library that provides CoreGraphics and ImageIO). Opal bundles CoreText as the OpalText subproject with 15 public headers under CoreText/, backed by FreeType/Fontconfig for font access and HarfBuzz for complex script shaping. This mirrors Apple's architecture where CoreText and CoreGraphics are both part of the same low-level graphics stack.
| API | GNUstep Status | Notes |
|---|---|---|
| CTFont (create, metrics, glyphs) | Yes | Full font creation, size, weight, slant, metric accessors |
| CTFontDescriptor | Yes | Attribute-based font matching via Fontconfig |
| CTFontCollection | Yes | System font enumeration via Fontconfig |
| CTFontManager | Yes | Font registration, dynamic font loading from file |
| CTLine (create, draw, metrics) | Yes | Line layout, line metrics (ascent/descent/leading/width) |
| CTRun (glyphs, advances, positions) | Yes | Per-run glyph access, advance widths, origins |
| CTFrame / CTFramesetter | Yes | Frame-based multi-line layout in an arbitrary path |
| CTTypesetter | Yes | Line breaking, soft hyphenation |
| CTParagraphStyle | Yes | Paragraph alignment, line spacing, writing direction |
CTFontCreateForCharactersWithLanguageAndOption — SPI for font fallback with language hint. Critical for correct international text rendering (CJK, Arabic, Indic scripts). Needs implementation in libs-opal using Fontconfig's language matching and HarfBuzz font selection.
CTFontDrawGlyphs — public API for drawing an array of glyphs to a CGContext. May need verification that libs-opal's implementation handles all edge cases (vertical text, color emoji).
CTFontShapeGlyphs — SPI for complex script glyph shaping (Arabic ligatures, Indic conjuncts). HarfBuzz performs this internally; the SPI exposes it as a CT call. Needs a CT-API wrapper around HarfBuzz's hb_shape().
CTFontCopyColorGlyphCoverage — SPI for detecting which codepoints have color (emoji) glyphs. Stub as returning NULL; implement by inspecting font CBDT/COLR tables later.
CTFontIsAppleColorEmoji — SPI. Stub to always return false. Web content degrades gracefully (text emoji instead of color).
CTLineCreateWithUniCharProvider — SPI for efficient line layout avoiding NSAttributedString allocation per line. Implement later as a performance optimization; not needed for correctness.
CTRunGetBaseAdvancesAndOrigins — SPI for vertical text metrics. Stub initially; implement when adding vertical writing mode support.
CTFontDescriptorCreateForCSSFamily — SPI mapping CSS generic font families (serif, sans-serif, monospace, cursive, fantasy) to actual system fonts. Essential for web content to render with appropriate fonts. Implement using Fontconfig's generic alias system.
CTFontCopyDefaultCascadeListForLanguages — public API returning the font fallback cascade list for a set of BCP 47 language tags. Needed for correct rendering of multilingual pages. Implement using Fontconfig's font substitution database.
CTFontCopyDefaultCascadeListForLanguages) and CSS family mapping (CTFontDescriptorCreateForCSSFamily) are the most critical missing pieces for correct web content rendering — these must be implemented before Phase 6 (real web content).
GNUstep implementation: libs-corebase — 36 public headers.
| API | GNUstep Status | Notes |
|---|---|---|
| CFString / CFMutableString | Yes | Full Unicode string API, encoding conversion, string comparison |
| CFArray / CFMutableArray | Yes | Typed collections with custom callbacks |
| CFDictionary / CFMutableDictionary | Yes | Hash table collections |
| CFSet / CFMutableSet | Yes | Set collections |
| CFData / CFMutableData | Yes | Byte buffer type |
| CFNumber / CFBoolean | Yes | Numeric boxing |
| CFRunLoop / CFRunLoopSource / CFRunLoopTimer / CFRunLoopObserver | Yes | Event loop primitives |
| CFURL / CFURLComponents | Yes | URL creation, resolution, component access |
| CFBundle | Yes | Bundle resource loading, Info.plist access |
| CFPropertyList | Yes | Plist serialization (XML and binary formats) |
| CFDate / CFCalendar / CFTimeZone / CFLocale | Yes | Date, time, locale primitives |
| CFError | Yes | Error domain/code/userInfo model |
| CFSocket / CFStream / CFReadStream / CFWriteStream | Yes | Socket and stream I/O |
| CFUUID | Yes | UUID generation and string conversion |
CFNotificationCenter — MISSING from libs-corebase. WebKit uses CFNotificationCenterGetLocalCenter() and CFNotificationCenterGetDistributedCenter() extensively for inter-component notifications (preference changes, cache invalidation, font change broadcasts). Must add to libs-corebase. Implementation strategy: bridge to NSNotificationCenter — they share semantics.
CFPreferences — MISSING from libs-corebase. CFPreferencesGetAppBooleanValue, CFPreferencesCopyAppValue, CFPreferencesSetAppValue are used for feature flags and user settings. Must add to libs-corebase. Implementation strategy: map to NSUserDefaults.
CFStringTokenizer — MISSING from libs-corebase. Used for text boundary detection (word breaks, sentence breaks) for text selection, double-click word selection, spell checking. Implementation: wrap ICU's BreakIterator API.
CFHTTPCookieRef, CFHTTPCookieStorageRef, CFURLStorageSessionRef — CFNetwork-layer types. Not in libs-corebase. Create stubs that delegate cookie management to NSHTTPCookieStorage.
CFMessagePort — MISSING. Used for lightweight in-process IPC. Stub with Unix domain socket or POSIX shared memory backing; implement fully later.
CFFileDescriptor — MISSING. A CFRunLoop source wrapping a file descriptor. Needed for integrating Unix sockets into the run loop. Implement using kqueue (NextBSD) via EVFILT_READ/EVFILT_WRITE.
CFNotificationCenter and CFPreferences are the most critical missing pieces — they must be added to libs-corebase before WebCore will compile cleanly. CFStringTokenizer is important for correct text interaction. The remaining gaps are CFNetwork types that can be delegated to NSURLSession/NSHTTPCookieStorage at a higher level.
GNUstep implementation: libs-quartzcore — 24 public headers, OpenGL compositor.
| API | GNUstep Status | Notes |
|---|---|---|
| CALayer (core properties, sublayers, display) | Partial | backgroundColor, opacity, transform, sublayers, zPosition work; mask, frame, geometry conversion missing |
| CABasicAnimation | Yes | from/to/by value interpolation |
| CAKeyframeAnimation | Yes | values array, path, calculationMode, keyTimes |
| CASpringAnimation | Yes | mass, stiffness, damping, initialVelocity |
| CATransaction | Partial | begin/commit, disableActions, animationDuration work; completionBlock is TODO in source |
| CAMediaTimingFunction | Yes | Named functions (ease, linear, etc.) + cubic bezier control points |
| CATransform3D | Yes | Full 4×4 matrix math, perspective, rotation, scale, translate |
| CAShapeLayer | Yes | Full CGPath-based vector layer with stroke/fill control |
| CARenderer | Yes | OpenGL-backed compositor for rendering layer trees |
| CAFilter | Partial | Filter name constants defined; CAFilter class is a stub |
CAContext — MISSING. SPI class critical for multi-process layer-tree compositing. On macOS, CAContext allows a WebProcess CALayer tree to be hosted in the UIProcess window via Mach port-based layer hosting. Without Mach ports, we need an alternative. For Phase 1–4 (ENABLE_GPU_PROCESS=OFF), not needed — we use software rendering via CGBitmapContext + POSIX shared memory blit. Long-term: implement CAContext in libs-quartzcore using Unix domain socket signaling + shared memory pixel buffers.
CADisplayLink — header exists as stub only. Needed for animation frame timing synchronized to display refresh. Implement using a timer thread that approximates 60Hz, or using X11's XSync extension, or DRM's vblank wait. Must implement before smooth CSS animations work.
CATiledLayer — stub. Used by WebKit for large-canvas tile-based page rendering (scrolling). Without it, very long pages won't render correctly. Must implement: a CALayer subclass that draws content in tiles across multiple threads.
CATextLayer — stub. Used for direct text compositing into the layer tree. Implement using CTLine/CGContext drawing to a CALayer backing store.
CAGradientLayer — stub. Used for gradient compositing. Implement using CGGradient drawing to a CALayer backing bitmap.
CALayer.mask — property not implemented. Needed for CSS mask, clip-path. Must add to CALayer in libs-quartzcore.
CALayer.frame — not implemented (only bounds+position are). Frame is derived but WebKit sets it directly. Must implement the setter (sets bounds + position) and getter (computes from bounds + position + anchorPoint).
CALayer geometry conversion: convertPoint:fromLayer:, convertPoint:toLayer:, convertRect:fromLayer:, convertRect:toLayer:. Used by WebKit hit testing and event routing. Must implement by walking the layer tree and composing transforms.
CATransaction completionBlock — marked TODO in libs-quartzcore source. Used to chain animation completions. Must implement.
CATransaction addCommitHandler:forPhase: — SPI for commit-phase callbacks. Stub initially.
CABackdropLayer — SPI for backdrop blur (CSS backdrop-filter). Stub; implement software blur pass later.
CAPresentationModifier, CAMachPort — Mach-specific SPI. Guard with #if PLATFORM(GNUSTEP); replace CAMachPort with POSIX file descriptor equivalent.
ENABLE_GPU_PROCESS=OFF), the biggest gaps to address first are: CALayer.frame, geometry conversion methods, CATransaction completionBlock, CADisplayLink, and CATextLayer/CAGradientLayer. CAContext and multi-process compositing are Phase 3+ concerns.
GNUstep implementation: gnustep-base — 167 public headers. The most mature component in the GNUstep stack.
NSURLSession (libcurl backend), NSRunLoop, NSFileManager, NSJSONSerialization, NSXMLParser, NSOperationQueue, NSThread, NSNotificationCenter, NSUserDefaults, NSURL, NSData, NSString, NSAttributedString, NSRegularExpression, NSPredicate, NSKeyValueObserving, NSKeyedArchiver, NSDateFormatter, NSNumberFormatter, NSHashTable, NSMapTable, NSPointerArray, NSProgress, NSUndoManager, NSTask, NSPipe, dispatch_* (libdispatch). Minor gaps:
NSDataDetector — absent. Disable data detection features via ENABLE_TELEPHONE_NUMBER_DETECTION=OFF.NSLinguisticTagger — partial. Stub remaining methods; language tagging is non-critical for initial build.NSXPCConnection — basic implementation present. Sufficient for Phase 3 multi-process IPC bridging.NSBackgroundActivityScheduler — not present. Not needed for browser core.GNUstep implementation: gnustep-gui — 303 public headers (256 implemented in source), rendered by gnustep-back X11 backend.
NSApplication, NSWindow, NSView, NSTextField, NSButton, NSToolbar, NSMenu, NSMenuItem, NSEvent (mouse, keyboard, scroll), NSCursor, NSPasteboard, NSColor, NSFont, NSImage, NSBezierPath, NSGraphicsContext, NSScrollView, NSClipView, NSAlert, NSOpenPanel, NSSavePanel, NSSplitView, NSStackView, NSOpenGLView, NSScreen, NSWorkspace, NSTextInputClient (protocol), NSSpellChecker, NSPrintOperation. Notable status:
NSView wantsLayer — present; partial QuartzCore integration (sufficient for initial build)NSTextInputClient protocol — present; handles IME composition for international text inputNSScrollerImp / overlay scroller SPI — not applicable; use GNUstep's native scroll bar renderingNSSharingService — stub initially; not critical for browser coreNSAccessibility — partial; sufficient for basic VoiceOver later, but not needed initiallyGNUstep implementation: MISSING — no libs-security exists.
SecCertificateRef, SecTrustRef, SecPolicyRef — TLS certificate typesSecTrustCreateWithCertificates, SecTrustEvaluateWithError — certificate chain verificationSecCertificateCopySubjectSummary, SecCertificateCopyData — certificate display infoSecTrustCopyResult, SecTrustGetCertificateCount — trust result inspectionlibs-security core lib. For the initial build, TLS is handled by libcurl inside NSURLSession (using OpenSSL or GnuTLS). Security framework APIs can be stubbed initially and implemented later wrapping OpenSSL's X.509 API. Certificate errors will not display detailed information, but HTTPS connections will work through libcurl.
CommonCrypto — MISSING. CC_SHA1, CC_SHA256, CCHmac, CCCryptorGCM used in WebKit for SubtleCrypto, authentication tokens, and session key derivation. Implement as thin wrappers around OpenSSL's EVP API or libgcrypt. Low complexity — about 20 functions to wrap. Create libs-commoncrypto or incorporate into libs-security.
GNUstep implementation: MISSING — no libs-iosurface exists.
ENABLE_GPU_PROCESS=OFF), IOSurface is NOT needed. We use CGBitmapContext + POSIX shared memory (shm_open/memfd_create) for cross-process pixel transfer — exactly the approach proven in v3/v4. Long-term: create libs-iosurface wrapping DMA-BUF (Linux/BSD kernel) or POSIX shared memory with the full IOSurface C API (IOSurfaceCreate, IOSurfaceLock, IOSurfaceGetBaseAddress, IOSurfaceGetBytesPerRow).
GNUstep implementation: MISSING — no libs-corevideo exists.
CVDisplayLink (display refresh synchronization for smooth animation), CVPixelBuffer (video frame buffer management), CVImageBuffer, CVMetalTextureCacheRef. For initial build with ENABLE_VIDEO=OFF and ENABLE_GPU_PROCESS=OFF: not needed. Stub the headers. Long-term: create libs-corevideo. CVDisplayLink can be implemented using X11's XSync extension, DRM's DRM_IOCTL_WAIT_VBLANK, or a high-resolution timer thread targeting 60Hz. CVPixelBuffer is a tagged pixel buffer with plane descriptors — straightforward to implement wrapping a malloc'd buffer or DMA-BUF.
GNUstep implementation: libs-av already provides CMTime and CMTimeRange in AVTime.h, and its FFmpeg backend already handles the audio/video decode pipeline that CoreMedia, AudioToolbox, and VideoToolbox represent on macOS. The remaining work is expanding libs-av's API surface to expose these capabilities through Apple-compatible headers.
ENABLE_VIDEO=OFF and ENABLE_WEB_AUDIO=OFF: these entire frameworks can be stubbed. Long-term, these are extensions to libs-av (not new standalone libs), since libs-av already has the FFmpeg backend:
CMSampleBuffer, CMBlockBuffer, CMFormatDescription, CMBufferQueue wrapping FFmpeg's AVPacket/AVFrame and format description types. These are data structures that flow through the decode pipeline libs-av already implements.AudioConverter wraps FFmpeg's swr_convert (already used by libs-av's AVAudioPlayer). ExtAudioFile wraps FFmpeg's demuxer (already in libs-av).VTDecompressionSession wraps FFmpeg's avcodec_send_packet/avcodec_receive_frame. Hardware decode via VA-API is possible through FFmpeg's hwaccel.AudioOutputUnitStart, AudioComponentFindNext) would extend libs-av's existing libao backend or add a PulseAudio/OSS backend.GNUstep implementation: libs-av — 11 public headers, FFmpeg backend for basic playback.
ENABLE_VIDEO=OFF: not needed. libs-av covers basic AVPlayer/AVAudioPlayer for future video support. Gaps for eventual video support:
AVCaptureSession/AVCaptureDevice — camera access via V4L2 or libv4lAVSpeechSynthesizer — speech synthesis via espeak-ng or FestivalAVSampleBufferDisplayLayer — video rendering directly into a CALayerAVPlayerLayer — video rendering via CALayer compositingAVAssetReader/AVAssetWriter — media file I/O via FFmpeg's avformatAVMutableComposition — timeline editing (low priority for a browser)GNUstep implementation: MISSING — not applicable on X11/OpenGL platforms.
ENABLE_WEBGL=OFF, ENABLE_WEBGPU=OFF, and ENABLE_GPU_PROCESS=OFF: not needed at all. Zero Metal code will be compiled. Long-term: consider Vulkan as a Metal-compatible GPU API (MoltenVK proves the semantic equivalence), or implement WebGL directly via OpenGL through libs-quartzcore's existing OpenGL infrastructure. This is the lowest priority item in the entire porting plan.
GNUstep implementation: MISSING.
ENABLE_WEB_AUDIO=OFF: vDSP not needed. CSS filters without vImage can use fallback software paths in WebCore (WebKit has software fallbacks for all CSS filters). Long-term: implement the specific vDSP functions used (about 10–15: vDSP_fft_zrip, vDSP_vmul, vDSP_vadd, etc.) using FFTW or direct SIMD intrinsics. Implement vImage pixel conversion and convolution using optimized C loops or libswscale.
GNUstep implementation: MISSING.
ENABLE_VIDEO=OFF: not needed at all. No stubs required — just guard the code paths with #if ENABLE(VIDEO) which is already how WebKit structures these calls.
GNUstep: Unix domain sockets + POSIX shared memory.
Source/WebKit/Platform/IPC/unix/ConnectionUnix.cpp. The PlayStation port ships this file as production code. We use it directly. Key implementation notes:
MachSendRight, MachReceiveRight wrapper types get POSIX file-descriptor equivalents (a thin wrapper around int fd with sendmsg/recvmsg)fork(2) + execve(2) instead of xpc_connection_create_mach_serviceNSXPCConnection in gnustep-base provides higher-level bridgingshm_open/mmap (POSIX) or memfd_create (Linux-compat) instead of mach_vm_map| Framework | WebKit Feature | Initial Build Status |
|---|---|---|
| PassKit | Apple Pay | Disable: ENABLE_APPLE_PAY=OFF |
| GameController | Gamepad API | Disable: ENABLE_GAMEPAD=OFF |
| CoreLocation | Geolocation | Disable: ENABLE_GEOLOCATION=OFF |
| Speech | Speech recognition / synthesis | Stub; disabled by feature flags |
| NaturalLanguage | Text analysis, language detection | Stub |
| DataDetectors | Link/phone number detection | Disable: ENABLE_TELEPHONE_NUMBER_DETECTION=OFF |
| VisionKit | Live Text in images | Stub |
| LinkPresentation | Rich link previews | Stub |
| Contacts | Contact autofill | Stub |
| ScreenTime | Screen time enforcement | Stub |
| WritingTools | Apple Intelligence writing assistance | Disable: ENABLE_WRITING_TOOLS=OFF |
| ARKit | WebXR AR content | Stub; ENABLE_WEBXR=OFF |
| BrowserEngineKit | Process hosting (iOS-new API) | Replace with Unix socket + shared memory |
| CoreUI | Native widget rendering (SPI) | Not needed — gnustep-gui/Eau renders native widgets via AppKit |
| ColorSync | ICC color profile application | Stub — use LCMS2 via libs-opal's existing color management |
| IOKit / IOPMLib | Sleep prevention, battery status | Stub — not critical; use kqueue power events if needed later |
| MediaRemote | AirPlay, Now Playing info | Stub |
| Network.framework | Low-level networking (NW path monitor) | Not needed — use NSURLSession; stub NWPathMonitor |
| UniformTypeIdentifiers | File type system (UTType) | Implement basic UTType → MIME mapping or stub common types |
Nearly every missing Apple framework can be sidestepped for the initial build by disabling the WebKit feature that requires it. This table maps each missing framework to the CMake flag that removes the dependency entirely:
| Missing Framework | CMake Flag to Disable | Effect |
|---|---|---|
| AVFoundation / CoreMedia / AudioToolbox / VideoToolbox | ENABLE_VIDEO=OFF | Cascades to disable MediaSource, MediaStream, WebRTC, MediaRecorder, MediaSession, EncryptedMedia, PictureInPicture, AVF captions — removes entire media pipeline |
| CoreAudio / Accelerate (vDSP) | ENABLE_WEB_AUDIO=OFF | No Web Audio API, no audio DSP, no FFT — eliminates all Accelerate/vDSP usage |
| Metal | ENABLE_WEBGL=OFF, ENABLE_WEBGPU=OFF, ENABLE_GPU_PROCESS=OFF | No GPU rendering path needed at all |
| IOSurface | ENABLE_GPU_PROCESS=OFF | No cross-process GPU surface sharing — software blit via shared memory instead |
| CoreVideo (CVDisplayLink) | ENABLE_GPU_PROCESS=OFF | No display-sync needed for software rendering path |
| CoreImage (CIFilter, CIContext) | ENABLE_VIDEO=OFF | Only used in video frame processing — disabled with video |
| Security framework | No flag needed | TLS handled internally by libcurl inside NSURLSession; disable ENABLE_WEB_AUTHN=OFF to remove SecKey/FIDO2 dependency |
| GameController | ENABLE_GAMEPAD=OFF | No Gamepad API |
| CoreLocation | ENABLE_GEOLOCATION=OFF | No geolocation |
| PassKit | ENABLE_APPLE_PAY=OFF | No Apple Pay / Payment Request API |
| Speech framework | ENABLE_SPEECH_SYNTHESIS=OFF | No speech synthesis or recognition |
| WritingTools | ENABLE_WRITING_TOOLS=OFF | No Apple Intelligence writing features |
| DataDetectors | ENABLE_TELEPHONE_NUMBER_DETECTION=OFF | No phone number / link detection |
| PDFKit | ENABLE_PDF_PLUGIN=OFF, ENABLE_PDFKIT_PLUGIN=OFF, ENABLE_UNIFIED_PDF=OFF | No inline PDF viewing |
| ARKit / WebXR | ENABLE_WEBXR=OFF | No AR/VR/XR content |
| Contacts | Stub only | Contact picker not critical — empty stub |
| ScreenTime | Stub only | Screen time enforcement not applicable — empty stub |
libs-opal (~85% covered)libs-corebase (~75% — add CFNotificationCenter, CFPreferences)libs-quartzcore (~50% — but software rendering bypasses most CA)gnustep-base (95%+ covered)gnustep-gui (90%+ covered)swift-corelibs-libdispatch (100% covered)Every other missing framework is either disabled by a feature flag or covered by an empty stub header. Zero new GNUstep core libs are needed for the initial build. The new libs (libs-security, libs-iosurface, libs-corevideo, etc.) become needed only as features are re-enabled in later phases.
These libraries follow the GNUstep pattern: same Apple public header API, different internal implementation. Each is a new pkg in the GNUstep ecosystem.
| Library | Priority | What it provides | Complexity |
|---|---|---|---|
libs-security |
Phase 2 | Security framework: SecCertificateRef, SecTrustRef, SecKeyRef, SecPolicyRef, SecTrustEvaluateWithError, SecCertificateCopySubjectSummary — wrapping OpenSSL's X.509 API. Also includes CommonCrypto: CC_SHA1/256/512, CCHmac, CCCryptor, CCCryptorGCM. |
Medium — ~50 functions to wrap; OpenSSL API is straightforward but Security framework semantics require careful mapping |
libs-commoncrypto |
Phase 2 | CommonCrypto standalone: hash functions (SHA1, SHA256, SHA512, MD5), HMAC, symmetric ciphers (AES-CBC, AES-GCM, 3DES), PBKDF2, random bytes. May be folded into libs-security. | Low — ~20 thin wrappers around OpenSSL EVP or libgcrypt |
libs-iosurface |
Phase 3+ | IOSurface C API: IOSurfaceCreate, IOSurfaceLock/Unlock, IOSurfaceGetBaseAddress, IOSurfaceGetBytesPerRow, IOSurfaceGetWidth/Height, IOSurfaceGetPixelFormat, cross-process surface passing via file descriptor. Backend: DMA-BUF (preferred for GPU sharing) or POSIX shared memory (simpler, no GPU sharing). |
Medium — DMA-BUF integration requires kernel knowledge; POSIX shm backend is straightforward |
libs-corevideo |
Phase 3+ | CoreVideo: CVDisplayLink (display-sync timer), CVPixelBuffer (pixel plane management), CVPixelBufferPool, CVOpenGLTextureCacheRef. Backend: DRM vblank for CVDisplayLink; malloc/mmap for CVPixelBuffer. |
Medium — CVDisplayLink synchronization requires platform-specific vblank source |
libs-av expansion (CoreMedia/AudioToolbox/VideoToolbox headers) |
Phase 3+ | Expand libs-av with Apple-compatible headers: CMSampleBuffer, CMBlockBuffer, CMFormatDescription, CMBufferQueue (wrapping FFmpeg AVPacket/AVFrame); AudioConverter (wrapping swr_convert); VTDecompressionSession (wrapping avcodec). CMTime/CMTimeRange already in libs-av. |
Medium — the FFmpeg backend already exists in libs-av; this is adding Apple-compatible API wrappers around it |
libs-accelerate |
Phase 3+ | Accelerate framework subset: vDSP FFT (vDSP_fft_zrip, vDSP_fft_zop), vector arithmetic (vDSP_vadd, vDSP_vmul, vDSP_vsmul, vDSP_vdiv), vImage pixel format conversion and convolution (Gaussian blur, color matrix). Backend: FFTW for FFT; SIMD intrinsics or libswscale for vImage. |
Low-Medium — the ~15 vDSP functions WebKit uses are well-documented; vImage needs SIMD optimization work |
All of these libs should be hosted alongside the existing GNUstep core libs (libs-opal, libs-quartzcore, libs-corebase, libs-av) in the GNUstep GitHub organization and follow the same CMake/GNUstep-make dual build system pattern.
On macOS, WebKit is built with Xcode via .xcodeproj files — not CMake, not Ninja, not Make. The CMake+Ninja path exists only for the GTK/WPE/Windows/PlayStation ports. Since we are modeling the macOS port exclusively, we use buildtool from libs-xcode — GNUstep's tool for building from .xcodeproj files.
.xcodeproj files ARE the macOS build system. They define every source file, every framework dependency, every build setting, every conditional compilation flag. The CMake files are a parallel build system maintained for non-Mac ports.buildtool reads .xcodeproj natively. It parses the PBX format and drives builds using GNUstep-make or generates GNUmakefiles/CMake files. This means we build from the same project files Apple uses..xcodeproj build settings. On macOS, ENABLE_VIDEO, ENABLE_WEBGL, etc. are Xcode build settings in XCBuildConfiguration objects — not CMake variables. buildtool reads these directly..xcodeproj structureWebKit.xcworkspace ← master workspace Source/WTF/WTF.xcodeproj ← Web Template Framework (platform abstractions) Source/bmalloc/bmalloc.xcodeproj ← memory allocator Source/JavaScriptCore/JavaScriptCore.xcodeproj ← JS engine Source/WebCore/WebCore.xcodeproj ← rendering engine Source/WebKit/WebKit.xcodeproj ← multi-process layer (UIProcess/WebProcess/NetworkProcess) Tools/MiniBrowser/MiniBrowser.xcodeproj ← browser shell
. /System/Library/Makefiles/GNUstep.sh # Build order (matching Xcode workspace dependency graph): buildtool build -project Source/WTF/WTF.xcodeproj buildtool build -project Source/bmalloc/bmalloc.xcodeproj buildtool build -project Source/JavaScriptCore/JavaScriptCore.xcodeproj buildtool build -project Source/WebCore/WebCore.xcodeproj buildtool build -project Source/WebKit/WebKit.xcodeproj buildtool build -project Tools/MiniBrowser/MiniBrowser.xcodeproj
On macOS, features are controlled by GCC_PREPROCESSOR_DEFINITIONS in the Xcode build configuration. To disable features for the minimal build, override build settings:
buildtool build -project Source/WebCore/WebCore.xcodeproj \ GCC_PREPROCESSOR_DEFINITIONS='$(inherited) ENABLE_VIDEO=0 ENABLE_WEB_AUDIO=0 \ ENABLE_WEBGL=0 ENABLE_WEBGPU=0 ENABLE_GPU_PROCESS=0 ENABLE_APPLE_PAY=0 \ ENABLE_GAMEPAD=0 ENABLE_WEB_RTC=0 ENABLE_WEB_AUTHN=0 ENABLE_WEBXR=0 \ ENABLE_PDF_PLUGIN=0 ENABLE_WEBASSEMBLY=0 ENABLE_SPEECH_SYNTHESIS=0'
buildtool needs to be validated against WebKit's .xcodeproj files, which are large and complex (WebCore.xcodeproj alone has thousands of file references). If buildtool cannot handle the full project initially, a fallback is to use buildtool generate to produce GNUmakefiles from the .xcodeproj and then build with gmake. This is still modeling macOS (same source file list, same build settings) but using GNUstep-make as the driver instead of xcodebuild.
WebKit's .xcodeproj build settings assume macOS/Xcode. We need to add GNUstep detection so the correct platform headers and libraries are found:
Source/WTF/wtf/PlatformLegacy.h ← modify: add PLATFORM(GNUSTEP) detection (same as v3/v4 approach) Source/WTF/wtf/PlatformHave.h ← modify: set HAVE() macros for GNUstep capabilities Source/WTF/wtf/PlatformUse.h ← modify: set USE() macros for GNUstep choices Source/WTF/wtf/PlatformEnable.h ← modify: set ENABLE() overrides for disabled features
Only what macOS WebKit equivalent needs — no Linux desktop stack.
On macOS, Ruby and gperf ship with Xcode Command Line Tools. WebKit is built by Xcode (xcodebuild), not CMake+Ninja. On GNUstep, buildtool (from libs-xcode, already installed) replaces xcodebuild. Install from pkg:
pkg install -y ruby gperf
Why these two: On macOS, both ship with Xcode Command Line Tools. Ruby runs WebKit's build-time code generators (DOM bindings from .idl, CSS property tables, settings from .yaml). gperf generates perfect hash tables for CSS properties, CSS values, CSS pseudo-selectors, and HTTP header names.
Not needed: bison flex — macOS WebKit does not use them (JSC's parser is hand-written). ninja — macOS does not ship Ninja; WebKit uses Xcode, we use buildtool. cmake — the .xcodeproj files are the build system, not CMake (CMake is only for the GTK/WPE Linux ports).
Deferred: woff2 — on macOS, CoreText handles WOFF2 web font decoding natively (HAVE_WOFF_SUPPORT=1), so no external library is needed. libs-opal does not yet decode WOFF2 natively. If web font rendering issues arise, either: (a) install pkg install woff2 and set HAVE_WOFF_SUPPORT=0 to use WebKit's bundled WOFFFileFormat.cpp with libwoff2, or (b) add WOFF2 decoding support to libs-opal's OpalText (the macOS-model approach). System fonts render fine without WOFF2.
These are already present on this NextBSD system (verified via pkg-config). On a fresh FreeBSD system they would need installing:
# Already installed — listed for reference only # libxml2 2.15 libxslt 1.1.45 sqlite3 3.53 icu 76.1 # freetype2 26.6 fontconfig 2.17 harfbuzz 14.2 # libpng 1.6.58 libjpeg 3.1 libwebp 1.6 lcms2 2.19
| Package / Library | Provides |
|---|---|
gnustep-base | Foundation (NSString, NSURLSession, NSRunLoop, NSThread, NSNotificationCenter, …) |
gnustep-gui | AppKit (NSApplication, NSWindow, NSView, NSEvent, NSFont, NSImage, …) |
gnustep-back | X11 backend for gnustep-gui (event loop, window creation, OpenGL surface) |
libs-opal | CoreGraphics + CoreText + ImageIO (CGContext, CGPath, CTFont, CTLine, CGImageSource) |
libs-quartzcore | QuartzCore / CoreAnimation (CALayer, CABasicAnimation, CATransform3D) |
libs-corebase | CoreFoundation (CFString, CFArray, CFRunLoop, CFURL) |
libs-av | AVFoundation (AVPlayer, AVAudioPlayer, CMTime) via FFmpeg |
libobjc2 | Objective-C 2.0 runtime (GNUstep-maintained, LLVM-compatible) |
libdispatch | Grand Central Dispatch (libpthread backend) |
libBlocksRuntime | Blocks closure support (from LLVM compiler-rt) |
If these appear in any build script, something has gone wrong:
glib2
gtk3
gtk4
gstreamer1
gstreamer1-plugins-base
libsoup3
skia
mesa-libs
wayland
libepoxy
enchant2
at-spi2-core
libmanette
libsecret
libbacktrace
sysprof
bubblewrap
xdg-dbus-proxy
# Phase 2: TLS certificate validation and crypto pkg install -y openssl gnutls libgcrypt # Performance pkg install -y ccache # Phase 3+: video support via libs-av/FFmpeg pkg install -y ffmpeg # Phase 3+: OpenGL compositing (may already be present) pkg install -y mesa-libGL mesa-libEGL
Note: Mesa GL/EGL are needed only by libs-quartzcore's OpenGL compositor — they are a dependency of libs-quartzcore, not of WebKit directly. WebKit calls CALayer/CARenderer APIs; the OpenGL calls are behind the libs-quartzcore boundary.
Goal: CMake configures without errors. No source files compiled yet.
Source/cmake/OptionsGNUstep.cmake mirroring OptionsMac.cmake with GNUstep framework detection via gnustep-config --objc-flags and gnustep-config --base-libsSource/cmake/FindGNUstep.cmake — detect gnustep-config, query header/library paths, set GNUSTEP_INCLUDE_DIRS, GNUSTEP_LIBRARIES, GNUSTEP_DEFINITIONSPLATFORM(GNUSTEP) to Source/WTF/wtf/PlatformLegacy.h (reuse proven v3/v4 approach: detect via __GNUSTEP__ preprocessor define)PlatformHaveGNUstep.h, PlatformUseGNUstep.h, PlatformEnableGNUstep.h — mirror the Mac equivalents, set GNUstep-specific HAVE/USE/ENABLE macrosPlatform{WTF,JavaScriptCore,WebCore,PAL,WebKit}GNUstep.cmake — file lists including the gnustep/ subdirectories and excluding Mac-only files that won't applySuccess criterion: cmake -B Build -G Ninja -DPORT=GNUstep [flags] completes without errors and generates a valid Ninja build graph.
Goal: jsc (JavaScript shell) binary runs and executes JavaScript.
CFRunLoop, CFString bridging, dispatch_*). Create Source/WTF/wtf/gnustep/ only for things that truly differ — Mach port wrappers → POSIX fd wrappers, MachSendRight.cpp → PosixFdRight.cppThreading, RunLoop, WorkQueue use libdispatch — already works on NextBSDmach/mach.h includes in WTF that are guarded by PLATFORM(MAC) — add || PLATFORM(GNUSTEP) where appropriate or provide POSIX alternatives#include <SomePrivateHeader_priv.h> fails — create empty stub files in a WebKitAdditions/ include directorySuccess criterion: Build/bin/jsc -e "print(1+1)" outputs 2.
Goal: libWebCore.so links successfully.
platform/cocoa/ and platform/mac/ sources directly — they call CG/CT/CF/CA APIs that GNUstep implements via libs-opal, libs-quartzcore, libs-corebaseSource/WebCore/platform/gnustep/ only for things with no Cocoa equivalent:
PlatformScreenGNUstep.mm — X11/RandR screen size, resolution, color depth queriesPlatformPasteboardGNUstep.mm — X11 clipboard (PRIMARY/CLIPBOARD selections via NSPasteboard/GNUstep)RunLoopGNUstep.mm — any run loop integration differences#if PLATFORM(GNUSTEP) guards around Mach-specific code (task_policy_set, vm_allocate, mach_port_*)<IOSurface/IOSurface.h> that defines the types as opaque structsCFNotificationCenter and CFPreferences to libs-corebase (Phase 2 prerequisite)Success criterion: ninja -C Build WebCore completes. Build/lib/libWebCore.so exists and is a valid shared library.
Goal: All three process executables build. MiniBrowser.app builds.
UIProcess/Cocoa/, WebProcess/cocoa/, Shared/cocoa/ sources directly where possibleSource/WebKit/Platform/IPC/unix/ConnectionUnix.cpp (PlayStation port — proven in v3/v4). Guard out ConnectionMach.mm with #if !PLATFORM(GNUSTEP)ProcessLauncherGNUstep.mm using fork(2)/execve(2) to launch WebProcess and NetworkProcess. Guard out ProcessLauncherMac.mm.Source/WebKit/UIProcess/gnustep/WebViewGNUstep.mm: NSView subclass implementing -drawRect: that blits the CGBitmapContext pixel buffer to the windowSource/WebKit/UIProcess/gnustep/PageClientImplGNUstep.mm: Implement the ~5–10 critical virtual methods of the PageClient protocol (drawing callback, scroll notification, cursor change, focus change); stub all ~200 othersSource/WebKit/UIProcess/gnustep/WKWebViewGNUstep.mm: WKWebView subclass or extension connecting to WebViewGNUstepXPCService*, SandboxExtension*, SecItem* calls with #if !PLATFORM(GNUSTEP)Success criterion: ninja -C Build MiniBrowser completes. MiniBrowser.app/Contents/MacOS/MiniBrowser is a valid executable. Build/WebKitWebProcess and Build/WebKitNetworkProcess executables exist.
Goal: A red window. Any pixel on screen.
Safari*, BrowserEngineKit, etc.)WKWebView → WebViewGNUstep so the painting path reaches -drawRect:CGBitmapContextCreate produces valid pixel buffers (test with a direct CG fill before wiring to WebKit)[webView loadHTMLString:@"<body style='background:red'>" baseURL:nil]WebCore::GraphicsContext get a CGBitmapContext?WebCore::RenderView::paintDocumentMarkers fire?WebCore::RenderBlock::paintBackground fill red?drawInRect: in the NSView?Success criterion: A window appears on screen showing a solid red (or any non-black, non-white) background. This is the inflection point — once there are pixels, everything else is incremental improvement.
Goal: User can navigate pages by typing URLs and clicking links.
NSEvent → WebKit event translation: mouse moved, mouse down/up, key down/up, scroll wheelWKNavigationDelegate in MiniBrowser for page load callbacksNSTextField URL bar → [webView loadRequest:]WKWebView navigation APIsNSPasteboard for copy/paste (NSPasteboard generalPasteboard → X11 CLIPBOARD)NSCursor → X11 cursor changes for links, text, resize handlesNSTextInputClient for correct IME supportNSMenuSuccess criterion: Type a URL in the address bar, press Enter, page loads and is visible. Can click links. Can select text and copy it.
Goal: example.com, wikipedia.org, and typical websites render correctly.
CTFontCopyDefaultCascadeListForLanguages and CTFontDescriptorCreateForCSSFamily in libs-opalCTFontShapeGlyphs / HarfBuzz integration for correct glyph shapingCGPathAddUnevenCornersRoundedRect in libs-opalCGContextDrawConicGradient in libs-opalCGImageSource handles WebP, JPEG XL (if enabled), animated GIF/WebPNSScrollView works correctlyCADisplayLink in libs-quartzcore for smooth animation timingCATransform3D compositing works for 3D transformsCALayer geometry conversion methodsENABLE_REMOTE_INSPECTOR=ON) for debuggingSuccess criterion: example.com and wikipedia.org render legibly and interactively.
Enable features one at a time, each as a self-contained sub-project:
| Feature | CMake flag | Dependencies | Notes |
|---|---|---|---|
| Web Inspector | ENABLE_REMOTE_INSPECTOR=ON | None extra | Full DevTools UI via WebKit's own inspector frontend |
| Video | ENABLE_VIDEO=ON | libs-av / FFmpeg, libs-coremedia | H.264, VP8/VP9 via FFmpeg decode pipeline |
| Web Audio | ENABLE_WEB_AUDIO=ON | libs-accelerate (vDSP), audio output | AudioContext, GainNode, ConvolverNode |
| WebGL | ENABLE_WEBGL=ON | Mesa OpenGL, libs-quartzcore | OpenGL ES 2.0 / 3.0 via EGL |
| WebRTC | ENABLE_WEB_RTC=ON | libwebrtc, audio/video | Complex — requires full media stack first |
| HTTPS certificates | N/A (always on) | libs-security (OpenSSL) | Implement SecTrust for certificate error UI |
| GPU Process | ENABLE_GPU_PROCESS=ON | libs-iosurface, CAContext | Requires Phase 3+ libs; enables GPU compositing |
| WebAssembly | ENABLE_WEBASSEMBLY=ON | None extra (JIT-based) | JSC's WASM interpreter and B3 JIT — largely works on any platform |
| Accessibility | ENABLE_ACCESSIBILITY=ON | ATK/AT-SPI via gnustep-gui | Screen reader support |
OptionsGNUstep.cmake as new file vs. guards in OptionsMac.cmake?OptionsMac.cmake into a new OptionsGNUstep.cmake that includes it and overrides as needed, or add if(GNUSTEP) / #if PLATFORM(GNUSTEP) guards throughout the existing Mac cmake files?OptionsGNUstep.cmake is cleaner — it's a first-class port alongside Mac, GTK, Win. Guards in Mac files make the Mac port harder to read and harder to upstream. The separate file approach also makes it easy to track what differs from the Mac baseline. Recommendation: separate file, include OptionsMac.cmake at the top, override below it.
--single-web-process launch flag for debugging. WebKit already has this flag.
CAContext replacement for multi-process GPU compositing?CAContext hosts a layer tree across process boundaries via Mach ports and WindowServer. Without Mach ports, what's the alternative for GPU-accelerated cross-process compositing?gnustep/ subdirectories (per the v3 convention) — this minimizes conflicts with upstream changes that don't touch those directories. Recommendation: upstream patchset approach. Maintain a gnustep/ subdirectory convention. Attempt to upstream generic improvements (platform registration cmake, CFNotificationCenter stubs) to the WebKit project.
#if PLATFORM(GNUSTEP) guards — skip SPI call sites entirely. Changes WebKit source, harder to rebase.#if PLATFORM(GNUSTEP) guards for SPI that has semantically different behavior (Mach-specific, WindowServer-specific). Implement in GNUstep libs for SPI that's actually important for rendering quality (CTFontShapeGlyphs, CTFontCopyDefaultCascadeListForLanguages, CGStyleRef filters).
NetworkProcess/cocoa/NetworkSessionCocoa.mm. Using NSURLSession also means HTTP/2, HTTP/3 (via curl's QUIC support), and cookie management work with minimal platform-specific code.