Repository navigation
Add opt-in Web API foundation: Options.WebApi, DOMException and console - #3079
Merged
Merged
Conversation
Introduces the plumbing for a WHATWG-faithful web platform surface, plus the first two APIs on it. Nothing is installed unless a host asks: an engine that does not is byte-for-byte the engine it was before. - Options.WebApi (net8+ only, whole-file gated) with WebApiFeatures, the ConsoleSink abstraction and UseWebApis/UseConsole extensions. The options group is allocated on first touch, so a default engine allocates nothing for it and Options.Apply reads the backing field. - WebApiRegistration installs one LazyPropertyDescriptor<Engine> per global through GlobalObject.SetProperty, from the one gated block in Options.Apply. Non-clobbering: a name the host already registered is left alone, checked with a probe so a host's own lazy global is not materialized by the look. Only the principal realm is touched, so a ShadowRealm gets nothing. - DOMException per WebIDL: prototype chained to %Error.prototype%, name/message/ code as brand-checked prototype accessors, the 25 legacy constants on both the interface object and the prototype, a lazy own `stack`, @@toStringTag. - console per the Console Standard: the log family, assert, trace, dir, group, count and time, with the %s/%d/%i/%f/%o/%O/%c/%% formatter, group indentation and a bounded, cycle-safe, getter-free object inspection. Exactly one ConsoleSink.Write per emitted record. - Jint.Repl adopts UseConsole(Console.Out) and drops its hand-rolled JsConsole. - Error.prototype.toString now performs Get(O, "name"/"message") with O as the receiver rather than %Error.prototype%, as steps 3 and 5 specify. It is unobservable for an ordinary error, whose name and message are data properties, but a WebIDL-shaped error whose attributes are brand-checking prototype accessors was handed the wrong receiver and rightly refused. - README gains a "Web APIs (opt-in)" section; AGENTS.md scopes the unconditional-registration rule to TC39 features, documents the Jint/WebApi subtree and adds the WHATWG citation URLs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This was referenced Aug 20, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is the first PR of a planned series that gives Jint an opt-in, WHATWG-faithful set of web platform APIs —
console, timers,TextEncoder,URL,AbortControllerand ultimatelyfetch— guided by WinterTC's Minimum Common Web Platform API. Users have asked for this since 2017 (#442, discussion #1253), and every embedder that wanted logging or HTTP has had to hand-roll its own shims.Three ground rules hold for the whole series, and this PR lays them down:
#if NET8_0_OR_GREATER(the same shape as the Float16 APIs and the System.Text.Json interop): onnet462/netstandard2.xthe options and types simply do not exist.UseWebApis()enables the non-network set; fetch, when it lands, will always require its own explicitUseFetch(...).Options.Apply, after the host's own configuration, and the install is non-clobbering — aconsolethe host registered itself is left exactly as the host left it (checked with a probe, so a host's lazy global is not even materialized by the look). Only the principal realm is touched, so aShadowRealmgets none of this.What's in this PR
Options.WebApi+[Flags] WebApiFeatures+UseWebApis/UseConsoleextensions, andWebApiRegistration— the plumbing every later feature rides on. Flags are declared only once the feature behind them exists; the bit layout is reserved up front.DOMExceptionper WebIDL: prototype chained to%Error.prototype%(soinstanceof Errorholds andstackworks),name/message/codeas brand-checked prototype accessors, the 25 legacy constants on both the interface object and the prototype. It has no feature flag — it is how every web API reports failure, so it exists whenever any of them does.consoleper the Console Standard: the log family,assert,trace,dir,group,countandtime, with the%s/%d/%i/%f/%o/%O/%c/%%formatter, group indentation, and a bounded, cycle-safe, getter-free object inspection. Output goes to a host-suppliedConsoleSink(one finished line per record); the default sink discards everything, so enabling the feature never surprises a server host with stdout writes.Jint.RepladoptsUseConsole(Console.Out)and drops its hand-rolledJsConsole— first dogfooding consumer.Error.prototype.toStringpassed%Error.prototype%as the receiver for itsname/messagereads where spec steps 3 and 5 sayGet(O, …). Unobservable for ordinary errors (data properties); wrong for any error whose attributes are prototype accessors that brand-check their receiver, which DOMException's are. Full test262 stays green.Verification
dotnet build -c Release— all five TFMs, 0 errors (the#ifgate is proven by the downlevel targets compiling).Jint.TestsandJint.Tests.PublicInterfacegreen on net10.0 and net472, in both the default and theJINT_HOST_CONTRACT_VERIFICATION=1configurations.The next PRs in the series, in dependency order: timers +
queueMicrotask(the one event-loop change, benchmark-gated), then Event/AbortController, TextEncoder/TextDecoder, atob/btoa, structuredClone, crypto, performance, WHATWG URL, Blob/File/FormData, and finally fetch itself with bounded default policy (scheme allowlist, redirect-hop re-validation, response-size cap, timeout) and a threat-model entry.🤖 Generated with Claude Code