Per https://webidl.spec.whatwg.org/#interface-prototype-object any
global platform object should reject prototype changes (besides
from ShadowRealmGlobalScope), and interface prototype objects on
global prototype chains must be immutable.
We already handled parts of this on the globals themselves, but not
the full chain.
Also align some spec comments to the latest WebIDL spec.
The Cache and CacheStorage interfaces are quite intertwined. A Cache
object can only be created through CacheStorage, so the Cache interface
cannot be tested on its own. So adding just this stub will allow
implementing the CacheStorage interfaces that create Cache objects. We
can then implement the Cache interface piecemeal.
This IDL change is needed for webaudio's WaveShaperNode, where a
null BufferSource for a curve attribute results in a zero-length buffer.
WebGL also has a nullable BufferSource arg in bufferData(...). But
there, a null data/srcData value returns GL_INVALID_VALUE.
generate_to_cpp is called recursively, such as when generating
dictionary values. To support factoring this (massive) function
into functions, add a forward declaration.
Whether a converted value may be null should only depend on the presence
and value of an optional default, not the nullability of the type being
passed in.
[Unscopable] members should only affect the interface prototype’s
@@unscopables object. The bindings generator was also creating an empty
@@unscopables object in define_unforgeable_attributes(), installing it
as an own property on instances.
Previously we avoided early returns and used `else if` chains instead,
since returning early could prevent other required code generation
steps from running. This structure diverged from the specification and
makes implementing [LegacyLenientThis] more difficult.
Now that attribute setter logic has been moved into its own function,
the necessary code generation can run independently, allowing us to
use early returns where appropriate.
No functional impact.
This is covered by the @fully_qualified_name@ type check just below,
WindowProxy is the only special case that we need to handle at the
IDL layer. Also split this into two separate functions while we
are at it, as this function as-is is performing a few different
specification steps all at once.
The code generator checked is_object() to detect Promise return types,
but Promise<T> is a ParameterizedType, so the check always failed and
caused crashes in WebContent in throwing callback functions.
Generate correct bindings for callback interfaces: only create an
interface object when the interface declares constants, and set up
the prototype correctly.
This also lets us tidy up some IDL for these callback interfaces.
The bindings generator derived imported interface headers from the IDL
file name. That only works when the IDL name, implemented C++ type, and
header basename all match.
Interfaces with [ImplementedAs] break that assumption, since the
generated bindings need to include the implementation header rather than
the header implied by the IDL file name.
This fixes a compile error in a future commit where EventListener
callback interface is split into its own IDL file with an
ImplementedAs of IDLEventListener.
Handle Optional<T> and Optional<Variant<...>> correctly when wrapping
dictionary members, and make ComputedEffectTiming.localTime optional
to distinguish absence from null.
For overload sets of size 1, we don't need to call into
`resolve_overload()` preventing many heap allocations. This effectively
removed EffectiveOverloadSet / resolve_overload from profiles for me on
slither.io.
Unfortunately this is a bit of a pain to test as it is surprisingly
difficult to create a non secure context in our test harness.
This is because both file scheme URLs and localhost are considered
secure contexts.
To test this, add a very specific internals setter to change the
top level origin of the environment for the current realm.
It was prevously translating it to just `bool` instead of
`Optional<bool>`.
Required elements in dictionary (such as in Notification.idl
for the NotificationAction) were treated as Optional<T> like the other
non-required elements. Now it's just the type without the Optional.
Co-authored-by: Zaggy1024 <gregory.bertilson@gmail.com>
Fold attribute setter handling into the shared [Replaceable] and
[PutForwards] paths, aligning the implementation more closely with the
WebIDL specification.
This change unfortunately introduces a regression in a WebAssembly
JS API test that expects attribute setters to throw when invoked
with no arguments (rather than treating the missing argument as
undefined). The exact specification text that mandates this
behavior for the WASM API is unclear to me.
The new behaviour seems like it would be more compatible in the
general case by not throwing an exception for all of the other
cases, so this commit accepts this as a regression until the
reasoning for needing to throw can be determined.
Intermediate classes in the initialize() chain set up prototypes and
define properties. Forgetting to call Base::initialize() in any
override would silently skip that setup.
Commit 1b8e81cd6f added a check to prevent
assigning a default value when the default value itself is null. But we
had previously generated an uninitialized type, expecting it to become
defaulted later on. So we would have generated code such as:
bool value;
if (!property.is_null() && !property.is_undefined())
value = property.to_boolean();
options.value = value;
This is undefined behavior.
We know use the same default value check to ensure we generate Optional
types instead. So the above `value` initializer becomes:
Optional<bool> value;
First check if a string is a member of the enum before attempting
numeric conversion. This generates correct code for fields like:
AudioContextOptions {
latencyHint: AudioContextLatencyCategory | double;
}
Any type ending in "Event" or "Element" does not need to be added to the
manually curated list of platform objects in is_platform_object().
Additionally, "WindowProxy" was already part of that list, so no need to
check for it separately. No functional changes.
The WebIDL spec requires that attributes marked [LegacyUnforgeable]
share the same getter and setter function objects across all instances
within the same Realm.
Previously, we were creating new JS::NativeFunction wrappers during
every instance initialization, which caused identity checks to fail.
This change moves these functions into Bindings::Intrinsics so they
are created once per Realm and reused.