Commit graph

140 commits

Author SHA1 Message Date
Andreas Kling
88d4d1b1a6 LibWeb: Use VM helpers for execution context access
Inline JS-to-JS frames no longer live in the raw execution context
vector, so LibWeb callers that need to inspect or pop contexts now go
through VM helpers instead of peeking into that storage directly.

This keeps the execution context bookkeeping encapsulated while
preserving existing microtask and realm-entry checks.
2026-04-13 18:29:43 +02:00
Andreas Kling
2ca7dfa649 LibJS: Move bytecode interpreter state to VM
The bytecode interpreter only needed the running execution context,
but still threaded a separate Interpreter object through both the C++
and asm entry points. Move that state and the bytecode execution
helpers onto VM instead, and teach the asm generator and slow paths to
use VM directly.
2026-04-13 18:29:43 +02:00
Timothy Flynn
2f3199adbf LibURL+LibWeb: Add a helper to check if a URL is a WebUI URL
Let's not have to know off-hand that we need to update Environments.cpp
when adding a new WebUI. It's more obvious just below where we define
the URLs.
2026-04-09 10:08:06 -04:00
Shannon Booth
57130908b3 LibJS+LibWeb: Make DOMException hold an [[ErrorData]] slot
Split JS::ErrorData out of JS::Error so that it can be used both
by JS::Error and WebIDL::DOMException. This adds support for
Error.isError to DOMException, also letting us report DOMException
stack information to the console.
2026-04-08 20:33:53 +02:00
Shannon Booth
bb0f244667 LibWeb: Remove ShadowRealm HTML integration 2026-04-05 13:57:58 +02:00
Shannon Booth
91e7218c22 LibWeb/HTML: Enforce CORS-mode fetch when fetching Worker script
At some point, the FIXME mentioned has been fixed.
2026-04-05 09:52:25 +02:00
Glenn Skrzypczak
e5dab9e1c7 LibWeb: Support WASM modules
This adds support for importing WASM modules in JavaScript and vice
versa.
2026-04-03 21:21:09 +02:00
Glenn Skrzypczak
7392d2a2f4 LibWeb: Support JSON modules
This adds support for importing JSON objects from JSON files in
javascript.
2026-04-03 21:21:09 +02:00
Glenn Skrzypczak
f1d3244b22 LibWeb: Support CSS modules
This adds support for importing CSS stylesheets from CSS files in
javascript.
2026-04-03 21:21:09 +02:00
Glenn Skrzypczak
8053c2a0f1 LibWeb: Update fetch single module script steps
This updates the steps for fetching single module scripts and related
functions.
2026-04-03 21:21:09 +02:00
InvalidUsernameException
7002c47ce1 LibJS+LibWeb: Pass constants into execution context constructor
The additional data being passed will be used in an upcoming commit.
Allows splitting the churn of modified function signatures from the
logically meaningful code change.

No behavior change.
2026-03-29 13:44:06 +02:00
Sam Atkins
ed6a5f25a0 LibWeb: Implement scoped custom element registries 2026-03-27 19:49:55 +00:00
Andreas Kling
b5babda288 LibWeb: Cache UniversalGlobalScopeMixin pointer on ESO
Avoid expensive cross-hierarchy dynamic_cast from JS::Object to
UniversalGlobalScopeMixin on every microtask checkpoint.

Since UniversalGlobalScopeMixin is not in the JS::Object
inheritance chain, as<UniversalGlobalScopeMixin>(JS::Object&)
falls through to dynamic_cast, which is very costly. Profiling
showed this taking ~14% of total CPU time.

Add EnvironmentSettingsObject::universal_global_scope() backed
by a pointer cached eagerly during initialization.
2026-03-24 08:28:47 +01:00
Shannon Booth
9d7b18f517 LibWeb: Fix entry_realm() to correctly find the realm execution context
entry_realm() was using the topmost execution context, but the spec
defines the entry execution context as the most recently pushed *realm*
execution context — the one owned by the environment settings object.

In a synchronous cross-window call, JS function calls push additional
execution contexts above the entry realm, causing the wrong realm to
be returned. Fix this by walking the stack to find the context that
matches its environment settings object's realm execution context.
2026-03-23 09:00:39 +01:00
Jelle Raaijmakers
c8baa6e179 LibWeb: Remove tasks for destroyed documents instead of running them
Previously, destroyed-document tasks were forced to be runnable to
prevent them from leaking in the task queue. Instead, discard them
during task selection so their callbacks never run with stale state.

This used to cause issues with a couple of `spin_until()`s in the past,
but since we've removed some of them that had to do with the document
lifecycle, let's see if we can stick closer to the spec now.
2026-03-19 15:24:46 -05:00
Andrew Kaster
92e4c20ad5 LibJS: Generate FFI header using cbindgen instead of hand-rolling
Replace the BytecodeFactory header with cbindgen.

This will help ensure that types and enums and constants are kept in
sync between the C++ and Rust code. It's also a step in exporting more
Rust enums directly rather than relying on magic constants for
switch statements.

The FFI functions are now all placed in the JS::FFI namespace, which
is the cause for all the churn in the scripting parts of LibJS and
LibWeb.
2026-03-17 20:49:50 -05:00
Tim Ledbetter
36f74ba96c Revert "LibJS: Shrink ExecutionContext by replacing ScriptOrModule …"
… with Cell*.

This reverts commit d3495c62a7.
2026-03-11 23:13:18 +00:00
Andreas Kling
d3495c62a7 LibJS: Shrink ExecutionContext by replacing ScriptOrModule with Cell*
Replace the 16-byte Variant<Empty, GC::Ref<Script>, GC::Ref<Module>>
with a simple 8-byte GC::Ptr<Cell> that points to either a Script or
Module (or is null for Empty).

A helper function script_or_module_from_cell() converts back to the
full ScriptOrModule variant when needed (e.g. in
VM::get_active_script_or_module).
2026-03-11 13:33:47 +01:00
Andreas Kling
f02b67a700 LibJS: Remove context_owner from ExecutionContext
This field was only used by LibWeb to prevent GC collection of the
EnvironmentSettingsObject while its execution context is on the stack.

This is unnecessary because the ESO is already reachable through the
realm's host_defined pointer: EC -> realm -> host_defined ->
PrincipalHostDefined -> environment_settings_object.

Shrinks ExecutionContext from 152 to 144 bytes.
2026-03-11 13:33:47 +01:00
Andreas Kling
69bab13718 LibWeb: Drain microtasks after background parse completion
When parse_off_thread() completes, the result callback runs inside a
deferred_invoke, which executes outside the HTML event loop's task
model. This meant that any microtasks queued by the callback (e.g.
promise reactions from react_to_promise during module linking) were
never drained, since HTML::EventLoop::process() only performs
microtask checkpoints after executing an HTML task.

Fix this by performing an explicit microtask checkpoint after the
parse result callback. This ensures that promise reactions queued
during module linking are drained immediately.

This fixes module worker scripts timing out because their loading
promise chains would stall indefinitely.
2026-03-09 09:38:29 +01:00
Andreas Kling
4c1e2aeb54 LibJS+LibWeb: Parse modules off the main thread
Use the parse_off_thread() helper to submit
parse_program(ProgramType::Module) to the ThreadPool for parsing
on a worker thread. Bounce back to the main thread to compile and
deliver the result via deferred_invoke.

Falls back to synchronous parsing when the Rust pipeline is
unavailable (LIBJS_CPP=1 or LIBJS_COMPARE_PIPELINES=1).
2026-03-06 13:06:05 +01:00
Andreas Kling
3f4d3d6108 LibJS+LibWeb: Add C++ compile_parsed_module wrapper
Add compile_parsed_module() to RustIntegration, which takes a
RustParsedProgram and a SourceCode (from parse_program with
ProgramType::Module) and compiles it on the main thread with GC
interaction.

Rewrite compile_module() to use the new split functions internally.

Add SourceTextModule::parse_from_pre_parsed() and
JavaScriptModuleScript::create_from_pre_parsed() to allow creating
module scripts from a pre-parsed RustParsedProgram.

This prepares the infrastructure for off-thread module parsing.
2026-03-06 13:06:05 +01:00
Andreas Kling
d8921646f5 LibJS+LibWeb: Parse classic scripts off the main thread
Create a SourceCode on the main thread (performing UTF-8 to UTF-16
conversion), then submit parse_program() to the ThreadPool for
Rust parsing on a worker thread. This unblocks the WebContent event
loop during external script loading.

Add Script::create_from_parsed() and
ClassicScript::create_from_pre_parsed() factory methods that take a
pre-parsed RustParsedProgram and a SourceCode, performing only the
GC-allocating compile step on the main thread.

Falls back to synchronous parsing when the Rust pipeline is
unavailable (LIBJS_CPP=1 or LIBJS_COMPARE_PIPELINES=1).
2026-03-06 13:06:05 +01:00
Andreas Kling
4e0e16e510 LibJS+LibWeb: Use InterpreterStack for all execution context allocation
Replace alloca-based execution context allocation with InterpreterStack
bump allocation across all call sites: bytecode call instructions,
AbstractOperations call/construct, script evaluation, module evaluation,
and LibWeb module script evaluation.

Also replace the native stack space check with an InterpreterStack
exhaustion check, and remove the now-unused alloca macros from
ExecutionContext.h.
2026-03-04 18:53:12 +01:00
Shannon Booth
8d099b9cec LibWeb: Add non const global object getter to EnvironmentSettingsObject
And sneak in a as_if tidyup too.
2026-02-26 07:22:50 +01:00
Shannon Booth
9e7aa878bc LibWeb: Properly determine if running in SecureContext for Workers
Fixes the included imported test. Note that this required a minor
edit of the WPT import to work with our test harness setup to
try and create a non secure context setup as both file:// and
localhost are considered secure contexts.
2026-02-26 07:22:50 +01:00
Shannon Booth
025ddd385b LibWeb/HTML: Track secure context as part of Serialized{Document,Worker}
This is somewhat awkward as the spec refers to 'is secure context'
with respect to these objects 'relevant settings object'. A natural
way of implementing this could be storing a pointer to the relevant
settings object like the JS representations of these objects do
(and then changing is_secure_context to accept this representation
too), but for now it seems much simpler to just store a boolean for
this purpose and sidestep both problems above.
2026-02-26 07:22:50 +01:00
Shannon Booth
665654a1c4 LibWeb: Begin serializing global object as part of serialized ESO
Instead of passing through window's associated document's URL as
an extra argument to starting up a worker. This will allow for
improving the representation of 'outside settings' when setting
up a Worker.
2026-02-23 11:42:20 +01:00
Shannon Booth
513830532b LibWeb/HTML: Specify enum size for CanUseCrossOriginAPIs
This is passed over IPC, so we really should be explicit with the
size here.
2026-02-23 11:42:20 +01:00
Praise-Garfield
52ee05cb5d LibWeb: Visit ImportMapParseResult in HTMLScriptElement::visit_edges
The m_result Variant can hold a GC::Ref<ImportMapParseResult> when the
script element has type="importmap", but visit_edges only traced the
GC::Ref<Script> arm. This left the ImportMapParseResult unvisited,
allowing the GC to collect it while the element still held a reference.

ImportMapParseResult inherited from JS::Script::HostDefined, but no
JS::Script or JS::Module ever stored it as host_defined data, so
visit_host_defined_self was dead code. This removes the HostDefined
inheritance entirely and switches m_result visitation to Variant::visit
with a lambda that catches all GC::Ref arms.
2026-02-21 11:14:45 -05:00
Shannon Booth
00911a8b01 LibWeb/HTML: Assume WorkerGlobalScope runs in a SecureContext
As a stopgap until we have things wired up fully, consider
WorkerGlobalScope as a SecureContext so that IDL marked with
[SecureContext] is still exposed.
2026-02-14 23:23:17 +01:00
Niccolo Antonelli Dziri
bed56c676d LibWeb: Use enum instead of bool for CanUseCrossOriginIsolatedAPIs
Change the parameters types of the functions `coarsen_time` and
`coarsened_shared_current_time` from `bool` to
`CanUseCrossOriginIsolatedAPIs` for more coherence with the surrounding
code.
2026-02-13 16:47:42 +00:00
Niccolo Antonelli Dziri
bd76078f97 LibWeb: Add constructor for Notification and getter methods
The full constructor for NotificationsAPI::Notification is implemented
along with the getter methods.
It is now possible to call the elements of Notification in JS without
getting undefined but the default values (or the ones passed in
options).

The method `current_wall_time` is added in EnvironmentSettingsObject.

This passes a least a few more tests because of the getter methods
that are created.

https://wpt.live/notifications/constructor-basic.https.html

https://wpt.live/notifications/idlharness.https.any.html
2026-02-13 16:47:42 +00:00
Aliaksandr Kalenik
901cc28272 LibWeb: Reduce recompilation impact of DOM/Document.h
Remove 11 heavy includes from Document.h that were only needed for
pointer/reference types (already forward-declared in Forward.h), and
extract the nested ViewportClient interface to a standalone header.

This reduces Document.h's recompilation cascade from ~1228 files to
~717 files (42% reduction). Headers like BrowsingContext.h that were
previously transitively included see even larger improvements (from
~1228 down to ~73 dependents).
2026-02-11 20:02:28 +01:00
Andreas Kling
4fa4ecf31b LibJS: Inline ExecutionContextRareData fields into ExecutionContext
After removing the unwind context stack, ExecutionContextRareData only
held two GC::Ptr fields — both trivially destructible. The indirection
cost more than it saved: a GC cell allocation per EC, an extra pointer
chase on every source range lookup, and unnecessary complexity.

Replace the rare data cell with two inline fields on ExecutionContext:
cached_source_range and context_owner.
2026-02-09 16:35:39 +01:00
Aliaksandr Kalenik
2452680615 LibWeb: Remove Document.h include from DOMParser.h, DOMImplementation.h
...and WorkerEnvironmentSettingsObject.h

These headers only use Document via forward-declarable references and
smart pointers, so the full include is unnecessary.
2026-02-08 18:51:13 +01:00
CountBleck
625926bdeb LibWeb: Set the creation_url of worker environment settings objects
This originally was part of a FIXME in step 5 of "setup a worker
environment settings object". After this change, all the WPT subtests in
https://wpt.live/referrer-policy/gen/worker-classic.http-rp/no-referrer-when-downgrade/fetch.http.html
will pass!
2026-01-31 22:45:08 +01:00
Timothy Flynn
6120b3b918 LibWeb+LibWebView+WebWorker: Enable the HTTP memory cache in workers
This is expected by WPT. For this to work, we must be able to determine
the network partition key for shared worker environments. So we now set
a top-level origin for these environments, with a FIXME to implement it
in accordance with the Client-Side Storage Partitioning spec.
2026-01-22 07:05:06 -05:00
Luke Wilde
babfd70ca7 LibGC: Enforce that a Cell type must declare the allocator to use
This ensures that we are explicitly declaring the allocator to use when
allocating a cell(-inheriting) type, instead of silently falling back
to size-based allocation.

Since this is done in allocate_cell, this will only be detected for
types that are actively being allocated. However, since that means
they're _not_ being allocated, that means it's safe to not declare
an allocator to use for those. For example, the base TypedArray<T>,
which is never directly allocated and only the defined specializations
are ever allocated.
2026-01-20 12:00:11 +01:00
Andreas Kling
4d92c4d71a LibJS: Skip initializing constant slots in ExecutionContext
Every function call allocates an ExecutionContext with a trailing array
of Values for registers, locals, constants, and arguments. Previously,
the constructor would initialize all slots to js_special_empty_value(),
but constant slots were then immediately overwritten by the interpreter
copying in values from the Executable before execution began.

To eliminate this redundant initialization, we rearrange the layout from
[registers | constants | locals] to [registers | locals | constants].
This groups registers and locals together at the front, allowing us to
initialize only those slots while leaving constant slots uninitialized
until they're populated with their actual values.

This reduces the per-call initialization cost from O(registers + locals
+ constants) to O(registers + locals).

Also tightens up the types involved (size_t -> u32) and adds VERIFYs to
guard against overflow when computing the combined slot counts, and to
ensure the total fits within the 29-bit operand index field.
2026-01-19 10:48:12 +01:00
Shannon Booth
8eec7d4585 LibWeb/HTML: Do not disable scripting for script based about: pages 2026-01-17 11:51:24 +00:00
Christoffer Haglund
14ccc87190 LibWeb: Address edge case on async module load
Issue #6294 describes an edge case where the browser crash if the same
module is loaded three times in a document, but all attempts fail.

Failure scenario:
1. Module load 1 set the state to "Fetching"
2. Module load 2 registers a callback to `on_complete` since the
   current state is "Fetching"
3. Module load 1 finish with a failure, invoking the callback for load
   number 2
4. Module load 3 cause a crash. The state is neither "Fetching" or
   "ModuleScript", so we'll reset the state to "Fetching". This invokes
   the callback for module load 2 again, now with an unexpected state
   which will cause an assert violation.

Proposed fix is to remove the condition that invokes `on_complete`
immediately for successfully loaded modules only, the callback should
be invoked regardless of whether the fetch succeeded or failed.

This reveals a separate bug in HTMLScriptElement, where
`mark_as_ready()` can be invoked before
`m_steps_to_run_when_the_result_is_ready` is assigned.
This appears to be a spec bug, reported as
https://github.com/whatwg/html/issues/12073 and addressed by delaying
the callback by a task, similar to the issue was resolved for inline
scripts.
2026-01-13 18:12:38 +01:00
Shannon Booth
1106496d1c LibWeb/HTML: Ensure data: URL workers are same-origin with themselves
See: baff3f5
2026-01-13 16:59:54 +01:00
Gingeh
fbde887cc8 LibWeb: Remove API URL character encoding
See https://github.com/whatwg/html/pull/9755/
2026-01-13 13:51:32 +00:00
Andreas Kling
2ac363dcba LibGC: Only call finalize() on types that override finalize()
This dramatically cuts down on time spent in the GC's finalizer pass,
since most types don't override finalize().
2026-01-07 20:51:17 +01:00
Shannon Booth
2a8b83a568 LibWeb/WebIDL: Upgrade QuotaExceededError to its own interface
See 48eba6d
2025-12-29 17:15:11 +01:00
Andreas Kling
9a5c648b2f LibWeb: Use weak references in the custom elements reaction stack 2025-12-25 20:21:37 +01:00
Daniel Price
b0c48b961e LibWeb: Check that import map elements are ordered maps (json objects) 2025-11-27 14:15:33 -06:00
Timothy Flynn
9375660b64 LibHTTP+LibWeb+RequestServer: Move Fetch's HTTP header infra to LibHTTP
The end goal here is for LibHTTP to be the home of our RFC 9111 (HTTP
caching) implementation. We currently have one implementation in LibWeb
for our in-memory cache and another in RequestServer for our disk cache.

The implementations both largely revolve around interacting with HTTP
headers. But in LibWeb, we are using Fetch's header infra, and in RS we
are using are home-grown header infra from LibHTTP.

So to give these a common denominator, this patch replaces the LibHTTP
implementation with Fetch's infra. Our existing LibHTTP implementation
was not particularly compliant with any spec, so this at least gives us
a standards-based common implementation.

This migration also required moving a handful of other Fetch AOs over
to LibHTTP. (It turns out these AOs were all from the Fetch/Infra/HTTP
folder, so perhaps it makes sense for LibHTTP to be the implementation
of that entire set of facilities.)
2025-11-27 14:57:29 +01:00
Timothy Flynn
3dce6766a3 LibWeb: Extract some CORS and MIME Fetch helpers to their own files
An upcoming commit will migrate the contents of Headers.h/cpp to LibHTTP
for use outside of LibWeb. These CORS and MIME helpers depend on other
LibWeb facilities, however, so they cannot be moved.
2025-11-27 14:57:29 +01:00