Commit Graph

81 Commits

Author SHA1 Message Date
Karl Seguin
43805ad698 Re-enable cached property support
The idea is that frequently accessed properties, e.g. window.document, can be
cached directly as data properties on the underlying v8::Object, removing the
need for the access call into Zig. This is only used on a handful of properties,
almost all of which are on the Window. It is important that the property be
read-only. For example, window.location cannot be cached this way because
window.location is writable (e.g. window.location.hash = '#blah').

This existed briefly before Zigdom, but was removed as part of the migration.
The implementation has changed. This previously relied on a "postAttach" feature
which no longer exists. It is not integrated in the bridge/callback directly and
lazily applied after the first access.
2026-01-20 17:34:52 +08:00
Karl Seguin
9092651b5b Merge branch 'main' into fix_context_lifetime 2026-01-20 08:50:41 +08:00
Karl Seguin
a6e7ecd9e5 Move more asserts to custom asserter.
Deciding what should be an lp.assert, vs an std.debug.assert, vs a debug-only
assert is a little arbitrary.

debug-only asserts, guarded with an `if (comptime IS_DEBUG)` obviously avoid the
check in release and thus have a performance advantage. We also use them at
library boundaries. If libcurl says it will always emit a header line with a
trailing \r\n, is that really a check we need to do in production? I don't think
so. First, that code path is checked _a lot_ in debug. Second, it feels a bit
like we're testing libcurl (in production!)..why? A debug-only assertion should
be good enough to catch any changes in libcurl.
2026-01-19 09:12:16 +08:00
Karl Seguin
5c1b7935e2 remove global handlescope 2026-01-19 07:28:35 +08:00
Karl Seguin
62aa564df1 Remove Global v8::Local<V8::Context>
When we create a js.Context, we create the underlying v8.Context and store it
for the duration of the page lifetime. This works because we have a global
HandleScope - the v8.Context (which is really a v8::Local<v8::Context>) is that
to the global HandleScope, effectively making it a global.

If we want to remove our global HandleScope, then we can no longer pin the
v8.Context in our js.Context. Our js.Context now only holds a v8.Global of the
v8.Context (v8::Global<v8::Context).

This PR introduces a new type, js.Local, which takes over a lot of the
functionality previously found in either js.Caller or js.Context. The simplest
way to think about it is:

1 - For v8 -> zig calls, we create a js.Caller (as always)
2 - For zig -> v8 calls, we go through the js.Context (as always)
3 - The shared functionality, which works on a v8.Context, now belongs to js.Local

For #1 (v8 -> zig), creating a js.Local for a js.Caller is really simple and
centralized. v8 largely gives us everything we need from the
FunctionCallbackInfo or PropertyCallbackInfo.  For #2, it's messier, because we
can only create a local v8::Context if we have a HandleScope, which we may or
may not.

Unfortunately, in many cases, what to do becomes the responsibility of the caller
and much of the code has to become aware of this local-ness. What does it means
for our code? The impact is on WebAPIs that store .Global. Because the global
can't do anything. You always need to convert that .Global to a local
(e.g. js.Function.Global -> js.Function).

If you're 100% sure the WebAPI is only being invoked by a v8 callback, you can
use `page.js.local.?.toLocal(some_global).call(...)` to get the local value.

If you're 100% sure the WebAPI is only being invoked by Zig, you need to create
 `js.Local.Scope` to get access to a local:

```zig
var ls: js.Local.Scope = undefined;
page.js.localScope(&ls);
defer ls.deinit();
ls.toLocal(some_global).call(...)
// can also access `&ls.local` for APIs that require a *const js.Local
```
For functions that can be invoked by either V8 or Zig, you should generally push
the responsibility to the caller by accepting a `local: *const js.Local`. If the
caller is a v8 callback, it can pass `page.js.local.?`. If the caller is a Zig
callback, it can create a `Local.Scope`.

As an alternative, it is possible to simply pass the *Page, and check
`if page.js.local == null` and, if so, create a Local.Scope. But this should only
be done for performance reasons. We currently only do this in 1 place, and it's
because the Zig caller doesn't know whether a Local will actually be needed and
it's potentially called on every element creating from the parser.
2026-01-19 07:28:33 +08:00
Karl Seguin
cd67ed8a27 Fix static accessors
These are called without a self from v8, and should match that in Zig code.
2026-01-19 07:08:58 +08:00
Halil Durak
d5e9ae23ef ground zero SubtleCrypto 2026-01-15 19:09:59 +03:00
Karl Seguin
47760e00f7 Reject constructor calls without new
This was previously a fixed bug, but it got lost in the direct_v8 merging.

https://github.com/lightpanda-io/browser/pull/1316
2026-01-15 19:25:43 +08:00
Karl Seguin
1b0ea44519 merge main 2026-01-13 12:58:31 +08:00
Karl Seguin
f2a9125b99 js.v8 is not equal to js.v8.c
This means the C funtions/types now sit in the root of v8.
2026-01-13 12:58:30 +08:00
Karl Seguin
8438b7d561 remove remaining direct v8 references 2026-01-13 12:58:30 +08:00
Karl Seguin
18c846757b migrate almost all types 2026-01-13 12:58:28 +08:00
Karl Seguin
bc11a48e6b migrate most cases, merge Caller into bridge 2026-01-13 12:57:06 +08:00
Halil Durak
83e9d705cf backport dummy canvas APIs 2026-01-09 16:47:19 +03:00
Karl Seguin
0c97b8238b Adds a number of HTML elements
Instead of being mapped to HTMLUnknownElement, these will all be mapped to the
correct type. This is important for many WPT tests. But it's not impossible that
some script checks `if (x instanceof HTMLBaseElement)` and, without this, that
would error since HTMLBaseElement wouldn't be defined.
2026-01-09 10:56:23 +08:00
Karl Seguin
d4c8af2a61 add an explicit HTMLSpanElement 2026-01-08 16:03:50 +08:00
Karl Seguin
c88cb35b84 add AbstractRange 2025-12-25 13:15:57 +08:00
Karl Seguin
8215f2fd8f Merge branch 'snapshots_v2' into zigdom 2025-12-22 17:03:38 +08:00
Karl Seguin
da32440a14 pass IdleDeadline to idle callback 2025-12-21 18:26:54 +08:00
Karl Seguin
b3a0aaaeea Enable v8 snapshots
There are two layers here. The first is that, on startup, a v8 SnapshotCreator
is created, and a snapshot-specific isolate/context is setup with our browser
environment. This contains most of what was in Env.init and a good chunk of
what was in ExecutionWorld.createContext. From this, we create a v8.StartupData
which is used for the creation of all subsequent contexts. The snapshot sits
at the application level, above the Env - it's re-used for all envs/isolates, so
this gives a nice performance boost for both 1 connection opening multiple pages
or multiple connections opening 1 page.

The second layer is that the Snapshot data can be embedded into the binary, so
that it doesn't have to be created on startup, but rather created at build-time.
This improves the startup time (though, I'm not really sure how to measure that
accurately...).

The first layer is the big win (and just works as-is without any build / usage
changes).

with snapshot
total runs 1000
total duration (ms) 7527
avg run duration (ms) 7
min run duration (ms) 5
max run duration (ms) 41

without snapshot
total runs 1000
total duration (ms) 9350
avg run duration (ms) 9
min run duration (ms) 8
max run duration (ms) 42

To embed a snapshot into the binary, we first need to create the snapshot file:

zig build -Doptimize=ReleaseFast snapshot_creator -- src/snapshot.bin

And then build using the new snapshot_path argument:

zig build -Dsnapshot_path=../../snapshot.bin -Doptimize=ReleaseFast

The paths are weird, I know...since it's embedded, it needs to be inside the
project path, hence we put it in src/snapshot.bin. And since it's embedded
relative to the embedder (src/browser/js/Snapshot.zig) the path has to be
relative to that, hence ../../snapshot.bin. I'm open to suggestions on
improving this.
2025-12-18 20:10:38 +08:00
Muki Kiboigo
9dbfac02b2 add KeyboardEvent 2025-12-17 14:45:36 -08:00
Muki Kiboigo
6f43d9979d add MouseEvent 2025-12-17 14:11:49 -08:00
Muki Kiboigo
d63a045534 proper UIEvent 2025-12-17 11:51:55 -08:00
Karl Seguin
ea399390ef Improve DOMImplementation, DocumentType and DOMException 2025-12-16 14:58:36 +08:00
Karl Seguin
d26869278f dummy HTMLCanvasElement 2025-12-16 11:13:57 +08:00
Karl Seguin
5eb54bbc95 Media/Audio/Video elements 2025-12-12 17:34:57 +08:00
Muki Kiboigo
7c9d7259e6 add NavigationActivation 2025-12-09 17:11:04 -08:00
Muki Kiboigo
01d71323fc complete History impl backed by Navigation 2025-12-09 16:51:05 -08:00
Muki Kiboigo
907298c6b1 backport pageshow event 2025-12-09 16:51:04 -08:00
Muki Kiboigo
370c3a49a7 initial Navigation 2025-12-09 16:51:01 -08:00
Karl Seguin
0479813494 add CDATASection 2025-12-08 22:09:15 +08:00
Karl Seguin
ef3ba13979 Add keys/values/entries/forEach/toString to DOMTokenList 2025-12-08 21:31:58 +08:00
Karl Seguin
0beae3b1a6 Various legacy document tests
document.embeds, document.plugins, document.anchor, document.getElementsByName

getElementsByClassName support for multiple class names

various document getters
2025-12-08 14:22:24 +08:00
Karl Seguin
e41d53019f CompositionEvent 2025-12-05 18:18:54 +08:00
Karl Seguin
c9882e10a4 Properly handle insertion of DocumentFragment
Add various CData methods

XHR and Fetch request headers

Animation mocks
2025-12-04 14:40:22 +08:00
Karl Seguin
7cb06f3e58 MediaError and :scope pseudoclass 2025-12-03 22:30:08 +08:00
Karl Seguin
60c1f19581 add TextTrackCue and VTTCue (for reddit) 2025-12-03 20:04:07 +08:00
Karl Seguin
3dd61aeb71 css.zig -> CSS.zig 2025-12-02 11:14:06 +08:00
Karl Seguin
6a46a9ba47 HTMLDataElement 2025-12-02 11:08:56 +08:00
Karl Seguin
fd39168106 Range 2025-12-02 10:57:20 +08:00
Karl Seguin
e807c9b6be Add XmlSerializer, add Response.type, tweak HTMLTemplate to redirect some calls to its Content (DocumentFragment) 2025-12-02 00:08:57 +08:00
Karl Seguin
bfa2e6b4dd Merge pull request #1235 from lightpanda-io/fix-ci-install
Cleanup installation instructions
2025-12-01 16:21:22 +08:00
Pierre Tachoire
d18253d50b fix import for rename CSS.zig insto css.zig 2025-12-01 08:59:21 +01:00
Karl Seguin
92ae2c46b6 ReadableStream 2025-12-01 15:16:33 +08:00
Karl Seguin
9f587ab24b MessageChannel and MessagePort 2025-11-28 22:11:59 +08:00
Karl Seguin
8858f889b4 Window.scrollX/Y, postMessage, more custom element edge cases 2025-11-28 18:01:50 +08:00
Karl Seguin
0d57356c11 Response constructor, window.CSS 2025-11-27 15:13:16 +08:00
Karl Seguin
e1d9732a60 PerformanceObserver.supportedEntryTypes 2025-11-26 07:42:19 +08:00
Karl Seguin
be0a808f01 Add HTMLSlotElement, PerformanceObserver and Script get/set type 2025-11-25 19:50:53 +08:00
Karl Seguin
6d6f1340af window.screen 2025-11-25 15:58:34 +08:00