Commit Graph

43 Commits

Author SHA1 Message Date
Muki Kiboigo
e9b08f19cf fix navigation and related tests 2025-10-21 18:29:28 -07:00
Karl Seguin
2e734fae57 This is the last of the big changes to the js code
This Pr largely tightens up a lot of the code. 'v8' is no longer imported
outside of js. A number of helper functions have been moved to the js.Context.
For example, js.Function.getName used to call:

```zig
return js.valueToString(allocator, name, self.context.isolate, self.context.v8_context);
```

It now calls:

```zig
return self.context.valueToString(name, .{ .allocator = allocator });
```

Page.main_context has been renamed to `Page.js`. This, in combination with new
promise helpers, turns:

```zig
const resolver = page.main_context.createPromiseResolver();
try resolver.resolve({});
return resolver.promise();
```

into:

```zig
return page.js.resolvePromise({});
```
2025-10-03 15:06:16 +08:00
Karl Seguin
dab8012b6a Start extract JS structs into their own files
Renames JsContext -> js.Context, JsObject -> js.Object and JsThis -> js.This
which is more consistent with the other types. The JsObject -> js.Object is
the reason so many files were touched.

This is still a [messy] transition, with more refactoring planned to clean it
up.
2025-10-02 12:48:50 +08:00
Muki Kiboigo
05e7079178 functional history WebAPI 2025-09-24 00:21:16 -07:00
Karl Seguin
024f7ad9ef Merge pull request #1056 from lightpanda-io/DOM_NO_ERR
Convert more DOM_NO_ERR cases to assertions
2025-09-18 19:06:32 +08:00
Pierre Tachoire
94fe34bd10 cdp: multiple isolated worlds 2025-09-17 14:42:08 +02:00
Karl Seguin
58acb2b821 Convert more DOM_NO_ERR cases to assertions
There is some risk to this change. The first is that I made a mistake. The
other is that one of the APIs that doesn't currently return an error changes
in the future.
2025-09-17 13:37:48 +08:00
Karl Seguin
ac10d5b2a3 Don't assume that page events means the BrowserContext has a page
CDP currently assumes that if we get a page-related notification (like a
request interception, or page lifecycle event), then we must have a session
and page.

But, Target.detachFromTarget can remove the session from the BrowserContext
while still having the page run (I wonder if we should stop the page at this
point??). So, remove these assumptions and make sure we have a page/session
in the handling of page events.
2025-09-05 15:07:30 +08:00
Karl Seguin
5dda86bf4a Emit networkIdle and networkAlmostIdle Page.lifecycleEvent
Most CDP drivers have a mechanism to wait for idle network, or an almost idle
network (sometimes called networkIdle2). These are events the browser must emit.

The page will now emit `networkIdle` when we are reasonably sure there's no more
network activity (this requires some slight changes to request interception,
since, I believe, intercepted requests should be considered).

`networkAlmostIdle` is currently _always_ emitted prior to emitting
`networkIdle`. We should tweak this but I can't, at a glance, think of a great
heuristic for when this should be emitted.
2025-09-04 16:36:29 +08:00
Karl Seguin
e237e709b6 Change loader id on navigation
This appears to be what chrome is doing. I don't know why we weren't before.
2025-09-03 08:17:14 +08:00
Karl Seguin
f65a39a3e3 Re-enable telemetry
Start work on supporting navigation events (clicks, form submission).
2025-08-11 21:37:00 +08:00
Karl Seguin
54ab1326e5 Switch XHR to new http client
get puppeteer/cdp.js working again

make test are all passing
2025-08-11 21:37:00 +08:00
Karl Seguin
b0fe5d60ab Initial work on integrating libcurl and making all http nonblocking 2025-08-11 21:36:56 +08:00
Karl Seguin
fae2b5acfa Noop CDP methods that go-rod requires
go-rod appears to stop processing when it receives an error, such as
UnknownMethod. Added placeholder handlers for Network.setUserAgentOverride and
Page.stopLoading.

Setting a custom user agent is something still being discussed, so no-oping it
seems reasonable. And, due to the currently synchronous nature of the initial
page load, no-oping stopLoading also seems reasonable.

https://github.com/lightpanda-io/browser/issues/867
2025-07-14 11:21:02 +08:00
Karl Seguin
1602932d72 Add a "pre" polyfill
This is always run, but only the full webcomponents polyfill, it's very
small and isn't intrusive. This introduces a layer of indirection so that,
if the full polyfill is loaded, its monkeypatched constructor will be called
2025-07-12 19:49:19 +08:00
Pierre Tachoire
941dace7f9 enable conditionnal loading for polyfill 2025-07-07 16:31:53 -07:00
sjorsdonkers
0c0ddc10ee rename scope jscontext
Some checks failed
e2e-test / zig build release (push) Has been cancelled
zig-test / zig build dev (push) Has been cancelled
zig-test / zig test (push) Has been cancelled
e2e-test / puppeteer-perf (push) Has been cancelled
e2e-test / demo-scripts (push) Has been cancelled
e2e-test / cdp-and-hyperfine-bench (push) Has been cancelled
e2e-test / perf-fmt (push) Has been cancelled
zig-test / browser fetch (push) Has been cancelled
zig-test / perf-fmt (push) Has been cancelled
nightly build / build-linux-x86_64 (push) Has been cancelled
nightly build / build-linux-aarch64 (push) Has been cancelled
nightly build / build-macos-aarch64 (push) Has been cancelled
nightly build / build-macos-x86_64 (push) Has been cancelled
wpt / web platform tests json output (push) Has been cancelled
wpt / perf-fmt (push) Has been cancelled
2025-06-13 10:30:50 +02:00
Karl Seguin
872a9d393d Internal navigation should change the CDP loader-id
This is one of the ways that puppeteer knows that navigation happened
and is needed to support `waitForNavigation` which compares the
existing loader-id with the new one, so it has to change.

Also, fix a crash that could happen if CDP disconnects while
connections are being aborted.
2025-06-12 19:11:26 +08:00
Karl Seguin
74b36d6d32 support form.submit()
Only supports application/x-www-form-urlencoded
2025-05-29 14:10:07 +08:00
Karl Seguin
94a30b2167 HTTP request notification
- Add 2 internal notifications
  1 - http_request_start
  2 - http_request_complete

- When Network.enable CDP message is received, browser context registers for
  these 2 events (when Network.disable is called, it unregisters)

- On http_request_start, CDP will emit a Network.requestWillBeSent message.
  This _does not_ include all the fields, but what we have appears to be enough
  for puppeteer.waitForNetworkIdle.

- On http_request_complete, CDP will emit a Network.responseReceived message.
  This _does not_ include all the fields, bu what we have appears to be enough
  for puppeteer.waitForNetworkIdle.

We currently don't emit any other new events, including any network-specific
lifecycleEvent (i.e. Chrome will emit an networkIdle and networkAlmostIdle).

To support this, the following other things were done:
- CDP now has a `notification_arena` which is re-used between browser contexts.
  Normally, CDP code runs based on a "cmd" which has its own message_arena, but
  these notifications happen out-of-band, so we needed a new arena which is
  valid for handling 1 notification.

- HTTP Client is notification-aware. The SessionState no longer includes the
  *http.Client directly. It instead includes an http.RequestFactory which is
  the combination fo the client + a specific configuration (i.e. *Notification).
  This ensures that all requests made from that factory have the same settings.

- However, despite the above, _some_ requests do not appear to emit CDP events,
  such as loading a <script src="X">. So the page still deals directly with the
  *http.Client.

- Playwright and Puppeteer (but Playwright in particular) are very sensitive to
  event ordering. These new events have introduced additional sensitivity.
  The result sent to Page.navigate had to be moved to inside the navigate event
  handler, which meant passing some cdp-specific data (the input.id) into the
  NavigateOpts. This is the only way I found to keep both happy - the sequence
  of events is closer (but still pretty far) from what Chrome does.
2025-05-24 09:01:12 +08:00
sjorsdonkers
193e012aa6 Rename to ExecutionWorlds 2025-05-21 14:34:23 +02:00
Karl Seguin
e44e68f8fc Move Session, Page and Renderer into their own respective files 2025-05-15 22:43:50 +08:00
Pierre Tachoire
7f2506d8a6 Merge pull request #598 from lightpanda-io/unused_imports
Some checks failed
e2e-test / zig build release (push) Has been cancelled
wpt / web platform tests (push) Has been cancelled
wpt / web platform tests json output (push) Has been cancelled
zig-test / zig build dev (push) Has been cancelled
zig-test / zig test (push) Has been cancelled
e2e-test / puppeteer-perf (push) Has been cancelled
e2e-test / demo-scripts (push) Has been cancelled
wpt / perf-fmt (push) Has been cancelled
zig-test / browser fetch (push) Has been cancelled
zig-test / perf-fmt (push) Has been cancelled
nightly build / build-linux-x86_64 (push) Has been cancelled
nightly build / build-linux-aarch64 (push) Has been cancelled
nightly build / build-macos-aarch64 (push) Has been cancelled
nightly build / build-macos-x86_64 (push) Has been cancelled
remove unused code, mostly imports
2025-05-05 12:07:29 +02:00
sjorsdonkers
9f72c98967 Error on null page/scope 2025-05-05 08:46:33 +02:00
sjorsdonkers
cddc55694a load polyfills on creation 2025-05-05 08:46:32 +02:00
sjorsdonkers
8930e2f06e isolated polyfill + create when needed 2025-05-05 08:46:32 +02:00
Karl Seguin
b8e5e130b9 remove unused code, mostly imports 2025-05-05 13:29:41 +08:00
Karl Seguin
7309fec51d Fully fake contextCreated
emit contextCreated when it's needed, not when it actually happens.

I thought we could make this sync-up, but we'd need to create 3 contexts to
satisfy both puppeteer and chromedp. So rather than having it partially
driven by notifications from Browser, I rather just fake it all for now.
2025-04-29 13:29:42 +08:00
Karl Seguin
2d5ff8252c Reorganize v8 contexts and scope
- Pages within the same session have proper isolation
  - they have their own window
  - they have their own SessionState
  - they have their own v8.Context

- Move inspector to CDP browser context
  - Browser now knows nothing about the inspector

- Use notification to emit a context-created message
  - This is still a bit hacky, but again, it decouples browser from CDP
2025-04-29 10:22:08 +08:00
Pierre Tachoire
11c7f57745 cdp: dispatch Page.frameNavigated before DOM.documentUpdated
chromedp client expects to receive Page.frameNavigated before
DOM.documentUpdated.
2025-04-24 18:28:43 +02:00
Pierre Tachoire
cfef22257e Merge pull request #560 from lightpanda-io/remove_arena_frees
Remove unnecessary cleanup when we know we have an arena
2025-04-24 09:04:46 +02:00
sjorsdonkers
e0bcb625c2 browsercontext arena 2025-04-23 17:00:22 +02:00
sjorsdonkers
9ae4d66194 page cleanup 2025-04-23 17:00:22 +02:00
sjorsdonkers
09850d7500 Fix executor used in resolveNode 2025-04-23 17:00:22 +02:00
sjorsdonkers
8897d9179c isolated world 2025-04-23 17:00:22 +02:00
Karl Seguin
2d1b9d64bd Remove unnecessary cleanup when we know we have an arena
Change a few old alloc+memcpy to dupe

Some other smaller cleanups.
2025-04-23 17:52:13 +08:00
Karl Seguin
3134ff81f4 JS clicks and MouseInput clicks trigger page navigation 2025-04-18 16:24:04 +08:00
Karl Seguin
3fc7ffadbf rename ts => timestamp, ctx => notify_ctx 2025-04-10 18:27:14 +08:00
Karl Seguin
30fd358286 improve playwright pafe lifecycle message compatibility 2025-04-10 16:07:31 +08:00
Karl Seguin
71c3d484a9 Communicate page navigation state via notifications
In order to support click handling on anchors from JavaScript, we need some hook
from the page/session to the CDP instance. This first phase adds notifications
in page.navigate, as well as a primitive notification hook to the session.

CDP's existing Page.navigate uses this new notifiation system.
2025-04-10 14:25:19 +08:00
Karl Seguin
f38a0d2d67 Remove BrowserContext URL
Add BrowserContext.getURL which gets the URL from the session.page.
2025-04-08 22:51:17 +08:00
Karl Seguin
0253de80de Add a dumb renderer to get coordinates
FlatRenderer positions items on a single row, giving each a height and width of
1.

Added getBoundingClientRect to the DOMelement which, when requested for the
first time, will place the item in with the renderer.

The goal here is to give elements a fixed position and to make it easy to map
x,y coordinates onto an element. This should work, at least with puppeteer,
since it first requests the boundingClientRect before issuing a click.
2025-04-08 22:43:53 +08:00
Karl Seguin
be9e953971 Add CDP Node Registry
This expands on the existing CDP node work used in  DOM.search. It introduces
a node registry to track all nodes returned to the client and give lookups to
get a node from a Id or a *parser.node.

Eventually, the goal is to have the Registry emit the DOM.setChildNodes event
whenever necessary, as well as support many of the missing DOM actions.

Added tests to existing search handlers. Reworked search a little bit to avoid
some unnecessary allocations and to hook it into the registry.

The generated Node is currently incomplete. The parentId is missing, the
children are missing. Also, we still need to associate the v8 ObjectId to the
node.

Finally, I moved all action handlers into a nested "domain" folder.
2025-03-28 19:00:29 +08:00