~ / startup analyses / Lightpanda Browser — Feature Gap & Improvement Report


Lightpanda Browser — Feature Gap & Improvement Report

AI-assisted audit (Claude Sonnet 4.6) — April 5, 2026 — codebase: Zig + V8 + html5ever

Lightpanda is a headless browser engine written in Zig that integrates V8 for JavaScript execution and implements Web APIs from scratch. It targets AI agents and browser automation, claiming 16× less RAM and 9× faster startup than Chrome. The engine is functionally solid for DOM manipulation, JavaScript execution, CSS selector matching, and HTTP networking — the core use cases of headless automation.

The codebase contains 215+ WebAPI files, 71 HTML element implementations, and 334 HTML test files. A scan reveals ~88 TODO/FIXME markers across 43 files, numerous stub/noop method implementations, and several Web APIs that are either absent or skeletal.

1. Critical Missing Features

These gaps either break real-world scripts or block entire categories of automation use cases.

1.1 Layout Engine / Visual Metrics

Status: Stub — returns zeros everywhere
File: src/browser/webapi/element/Element.zig

No layout engine exists. All geometric queries return empty/zero results:

APICurrent behavior
getBoundingClientRect()Returns {0, 0, 0, 0, 0, 0, 0, 0}
getClientRects()Returns empty DOMRectList
getComputedStyle()Not implemented
offsetWidth / offsetHeightNot implemented
offsetParentNot implemented
scrollWidth / scrollHeightNot implemented
clientWidth / clientHeightNot implemented

Impact: High. Many automation scripts check element dimensions for visibility detection, scroll position, and interaction targeting. Libraries like HTMX, Alpine.js, and virtually all UI frameworks call getBoundingClientRect().

What could be done: A simplified block layout pass (no float, no flex) that computes approximate box dimensions from CSS width/height/display properties would satisfy the majority of automation use cases without a full layout engine.

1.2 CORS Enforcement

Status: Not enforced (open issue #2015)
File: src/browser/webapi/fetch/Fetch.zig

All cross-origin requests are treated as mode "cors" for labeling purposes, but no preflight is issued, no Access-Control-Allow-Origin header is validated, and no request is blocked. Scripts that intentionally rely on CORS failures will silently succeed. CORS-dependent auth flows may bypass security checks.

1.3 Web Workers

Status: Absent

No Web Workers, Shared Workers, or Service Workers are implemented. The server uses internal Zig threads but none are exposed to the JS runtime. navigator.serviceWorker returning undefined causes hard failures in PWAs.

What could be done: A minimal Web Worker implementation running a JS bundle in a separate V8 isolate and communicating via postMessage would cover the majority of use cases.

1.4 IndexedDB

Status: Absent

window.indexedDB is not defined. A large fraction of modern web apps use IndexedDB for client-side state, causing hard JS errors on page load.

1.5 File API

Status: Completely stubbed
File: src/browser/webapi/file/File.zig

The File interface has a comment: // TODO: Implement File API. The constructor creates a Blob, not a real File object. FileReader is mostly noop. File upload forms and drag-and-drop automations cannot work.

1.6 Cache API

Status: Absent

window.caches / CacheStorage / Cache are not present. Service Worker integration depends on this.

2. Partially Implemented APIs

These APIs exist in the codebase but have significant gaps marked by TODOs, noop methods, or stub returns.

2.1 Canvas 2D Context

Files: src/browser/webapi/canvas/OffscreenCanvasRenderingContext2D.zig, Canvas.zig

OffscreenCanvasRenderingContext2D has dozens of noop methods: save, restore, scale, rotate, translate, transform, setTransform, resetTransform, clearRect, fillRect, strokeRect, beginPath, closePath, moveTo, lineTo, quadraticCurveTo, bezierCurveTo, arc, arcTo, rect, fill, stroke, clip, fillText, putImageData.

getImageData() returns a DOMException. OffscreenCanvas.transferToImageBitmap() returns null because ImageBitmap is not implemented. Inline canvas also missing CanvasGradient and CanvasPattern.

2.2 WebGL

File: src/browser/webapi/canvas/WebGLRenderingContext.zig

getParameter() returns an empty string for all queries. getSupportedExtensions() is a stub empty array. Only extension returned is WEBGL_lose_context with noop methods. No shader compilation, buffer management, or draw calls.

2.3 Animation API

File: src/browser/webapi/animation/Animation.zig

Animations simulate a fake lifecycle: idle → running → finished. The effect and timeline constructor parameters are explicitly ignored (TODO in source). No actual timing, keyframe interpolation, or composite operations.

2.4 Performance Timing

File: src/browser/webapi/performance/Performance.zig

performance.timing returns 0 for all navigation timing properties. performance.navigation returns hard-coded values. Scripts that gate on performance.timing.loadEventEnd > 0 will hang indefinitely.

2.5 SubtleCrypto

Files: src/browser/webapi/SubtleCrypto.zig, src/browser/webapi/crypto/

Implemented algorithms: HMAC, X25519. Missing: RSA-OAEP, AES-GCM, AES-CBC, AES-CTR, ECDSA, ECDH, SHA-based KDFs. pkcs8 key format is explicitly marked unsupported. Any authentication library using RSA/AES/ECDSA operations will throw.

2.6 XMLHttpRequest

File: src/browser/webapi/xhr/XMLHttpRequest.zig

Only text and json response types supported; arraybuffer, blob, document missing. URL parameter accepts only strings; spec allows URL objects. Optional withCredentials and timeout handling incomplete.

2.7 Streams API

Files: src/browser/webapi/streams/, encoding/TextEncoderStream.zig, TextDecoderStream.zig

ReadableStream, WritableStream, TransformStream implementations exist but streaming encoding/decoding has a TODO: "handle encoding properly". Backpressure and byte stream modes are unverified for spec compliance.

2.8 Other Partial APIs

APIGapFile
FontFaceSetEvents fire before font is parsed (TODO)FontFaceSet.zig
SelectiongetComposedRanges() unimplementedSelection.zig
AbstractRange / StaticRangeMissing static_range field (TODO); StaticRange absentAbstractRange.zig
InputEventdataTransfer not implemented (TODO)event/InputEvent.zig
UIEventsourceCapabilities not implementedevent/UIEvent.zig
PerformanceObserverbuffered option ignored (TODO)PerformanceObserver.zig
MediaElement (Audio/Video)API surface present, no media pipelineelement/html/Media.zig

3. CDP Protocol Gaps

3.1 Emulation Domain

File: src/cdp/domains/emulation.zig

Four methods are noop:

MethodStatus
setEmulatedMedianoop
setFocusEmulationEnablednoop
setDeviceMetricsOverridenoop
setTouchEmulationEnablednoop

Playwright's device emulation (page.emulate(devices['iPhone 14'])) silently has no effect. Tests that verify mobile rendering will pass without actually testing mobile behavior.

3.2 Other CDP Gaps

DomainGapFile
Browser5 noop methods, hard-coded version/window datadomains/browser.zig
NetworkMissing requestWillBeSentExtraInfo, responseReceivedExtraInfodomains/network.zig
DOMQuad computation incomplete for certain CSSdomains/dom.zig
PagetransitionType and referrerPolicy not typed to enumdomains/page.zig
FetchOrigin determination for proxied requests is TODOdomains/fetch.zig

4. CSS Engine Gaps

FeatureStatusFile
CSS URL parserSimplified — TODO: "Need a true URL parser here"css/Tokenizer.zig
@supports ruleNot parsed — blocks gated behind it may be applied unconditionallycss/Parser.zig
:placeholder-shownDefined in selector list but match returns falseselector/Selector.zig
getComputedStyle()Not implemented at DOM level; only inline styles accessibleelement/Element.zig
@importNo support for CSS @import chaining
@layerCascade layers absent

5. Absent Web APIs

APIs with zero implementation:

APISpecAutomation Priority
ImageBitmapHTML Living StandardMedium — blocks Canvas pipeline
Broadcast ChannelHTML Living StandardMedium — inter-tab messaging
GeolocationW3CMedium — some sites gate on it
Clipboard APIW3CMedium — copy-paste automations
Screen OrientationW3CMedium — mobile simulation
Credential ManagementW3CMedium — auth flows
Pointer Lock APIW3CLow
View Transitions APIW3CLow
WebRTCW3CLow
WebTransportW3CLow
WebCodecsW3CLow
WebXRW3CLow
Web Speech APIW3CLow
Ambient Light SensorW3CLow

6. Spec Compliance Issues

IssueDetailFile
hidden tri-stateSpec defines "", "until-found", and absent. Only boolean implemented.element/html/Html.zig
Element.localName / prefixNamespace prefix comparison not fully implemented; affects SVG/XMLelement/Element.zig
CustomElementDefinitionNeeds Map<String> for observedAttributes; callback chain brokenCustomElementDefinition.zig
URLSearchParams memory leakTODO: "Release params on error" — leak on construction failureURLSearchParams.zig
Duplicate Headers structTwo header structs with unclear ownership; XHR vs fetch inconsistencyfetch/Headers.zig

7. Infrastructure & Architecture

7.1 V8 Snapshot Hacks

File: src/browser/js/Snapshot.zig

V8 snapshot creation has TODO comments around function name registration. The current workaround may break with newer V8 versions. A clean function registration mechanism needs to be designed before upgrading V8.

7.2 Inspector / Debugger Support

File: src/browser/js/Inspector.zig

CDP's Debugger domain is partially wired through the V8 Inspector interface but breakpoints, step-through debugging, and heap snapshots are not functional. This limits --inspect mode for script authors debugging automation workflows.

7.3 Shadow DOM Event Retargeting

Event retargeting across shadow boundaries (spec §10.5) needs verification. composedPath() exists but correctness when events cross open/closed shadow roots is untested.

7.4 ES Module Loading

File: src/browser/js/Module.zig

Dynamic import() with complex dependency graphs and circular imports has not been validated against real-world module bundlers.

8. Test Coverage Gaps

AreaGap
WebGLNo tests for any WebGL methods
SubtleCryptoNo tests for RSA/AES operations
OffscreenCanvasNo rendering correctness tests
AnimationOnly lifecycle tests; no timing accuracy
Custom ElementsobservedAttributes callback chain untested
Shadow DOMEvent retargeting across boundaries not tested
ES ModulesDynamic import() circular dependency not tested
StreamsBackpressure and byte stream modes untested
CDP emulationNoop methods have no behavior tests
XHR arraybufferResponse type arraybuffer not tested (unimplemented)
FontFaceSetEvent timing relative to parse state untested
CSS @supportsParsing and cascade behavior untested
CORSNo tests validating CORS enforcement (or lack thereof)

9. Prioritized Roadmap

Priority 1 — High Impact, Feasible

FeatureFiles to touchRationale
Approximate layout metricsElement.zig + new layout/ moduleUnblocks visibility checks; essential for agent interaction
CORS enforcementFetch.zig, HttpClient.zigSecurity correctness; required for spec compliance
ImageBitmapNew ImageBitmap.zig + OffscreenCanvas.zigUnblocks canvas pipeline
CDP setDeviceMetricsOverridecdp/domains/emulation.zigPlaywright device emulation is silently broken
performance.timing real valuesperformance/Performance.zigScripts hang on load detection
@supports CSS parsingcss/Parser.zigMany modern stylesheets gate on feature detection
hidden tri-stateelement/html/Html.zigSimple spec fix, affects form UX testing
:placeholder-shown matchingselector/Selector.zigOne-line fix, styling correctness

Priority 2 — Medium Impact

FeatureFiles to touchRationale
Web Workers (basic)New worker/ module + V8 isolateSPA compatibility
SubtleCrypto RSA/AESSubtleCrypto.zig + crypto/Auth library support
XHR arraybuffer / blobxhr/XMLHttpRequest.zigBinary data fetching
Canvas 2D renderingcanvas/CanvasRenderingContext2D.zigChart/captcha support
Broadcast ChannelNew BroadcastChannel.zigInter-tab messaging
Clipboard APINew Clipboard.zigCopy-paste automation
CDP requestWillBeSentExtraInfocdp/domains/network.zigCookie inspection in Playwright
getComputedStyle()Element.zig + StyleManager.zigStyle introspection
Animation KeyframeEffectanimation/Animation.zig + new filesReal animation timing

Priority 3 — Lower Impact or High Complexity

FeatureRationale
IndexedDBHigh complexity; critical for PWAs but rarely needed for agents
Service WorkersRequires Workers + Cache API first
File APIHeadless design limits utility
WebRTCVery high complexity, low agent use case
Full WebGL renderingGPU pipeline; very high complexity
V8 Inspector full debuggerDeveloper tooling, not agent use
CSS @import chainingAffects style correctness for complex sites
CustomElementDefinition observed attrsWeb Components completeness

11. Appendix: TODO/FIXME Hotspots

FileTODO countTheme
src/cdp/domains/emulation.zig4Device simulation
src/cdp/domains/browser.zig5Browser info stubs
src/browser/webapi/xhr/XMLHttpRequest.zig3Response types
src/browser/webapi/canvas/OffscreenCanvasRenderingContext2D.zigmany noopsRendering
src/browser/js/Snapshot.zig2V8 naming hacks
src/browser/css/Tokenizer.zig1URL parsing
src/browser/webapi/AbstractRange.zig1StaticRange
src/browser/webapi/Selection.zig1getComposedRanges
src/browser/webapi/SubtleCrypto.zig1pkcs8 format
src/browser/webapi/FontFaceSet.zig1Event timing
src/browser/webapi/encoding/TextEncoderStream.zig1Encoding
src/browser/webapi/event/InputEvent.zig1dataTransfer
src/browser/webapi/URLSearchParams.zig1Memory leak