Commit Graph
12 Commits
Author SHA1 Message Date
Karl Seguin 7a4e2f62bd mem: fix robot store key leak
The RobotStore is shared by all Browsers. While every browser has a single
flight to prevent duplicate requests to the same robots.txt, that's limited to
that specific browser. So, 2 browsers can ask for the same robots.txt and then
put try to store the result. The RobotStore _is_ thread safe, but it's a simple
last-one-wins which overrites the previous record, without freeing either the
key or value.

This replaces the last-write-wins with a first-write-wins, avoiding the leak.
2026-09-12 11:39:27 +08:00
Karl Seguin 2e6999f20b chore: make declarations private if they don't need to be public
This change is 99%  s/pub//   + a handful of dead code removal.
2026-09-10 14:42:09 +08:00
Karl Seguin 09edfd3ce5 http: Add optional rate limit
Add an optional per-host rate limit. This currently only applies to the top-
level navigation. This makes it simpler to implement and simpler to reason
about. The full load of a page is only ever delayed at its head, not
sporadically through the page loading.

The use-case where a RateLimiter is most useful is when the browser is crawling
multiple pages of the same site, and in that case, the top-level rate limit
still applies some degree of limit to any linked resources (e.g. a JS on a
different host).

`--http-nav-delay` is the delay, in milliseconds, to apply to top level
navigates per host. Currently defaults to 0 (disabled).

`--http-nav-burst` is the burst allowed per host. Defaults to 1 (has no impact
when `--http-nav-delay` is disabled).
2026-08-20 16:03:42 +08:00
Muki Kiboigo 7cb6590642 better handling of allowed and disallowed robots cases 2026-08-14 08:52:37 -07:00
Karl Seguin 6a83881634 chore: add lp.IS_DEBUG and lp.IS_TEST
Change all users to builtin.mode and built.is_test
2026-08-01 09:15:18 +08:00
Karl Seguin 8e42d63c1c zig: Zig 0.16
Built against https://github.com/lightpanda-io/zig-v8-fork/tree/zig-0.16 but
it doesn't require a new v8 build.

Built against https://github.com/lightpanda-io/boringssl-zig/tree/zig-0.16
since the current fork we point to isn't updated.

A global std.Io instance, lp.io. Way easier this way and requires 0 changes to
our libcurl integration / event loop.

Network code uses a new layer that does what Zig 0.15's posix package used to
do. Again, quicker migration that way. But, as long as we have the global IO,
and given the half-baked nature of networking in std.Io 0.16, this just makes
sense. Things can be migrated as needed.

The std.time.* -> std.Io.Timestamp/Clock/Duration resulted in _a lot_ of
changes. ArrayList = .{} -> ArrayList -> .empty also resulted in a lot of
changes, but that's obviously superficial. As is the trimLeft/trimRight ->
trimStart/trimEnd rename.

Locking adopt the `Uncancelable` variants, e.g. mutex.lockUncancelable() to
preserve the error-free signature (and, because cancellation would be something
we'd have to put more thought into).

std.json.ObjectMap is now unmanaged, so the allocator had to be passed along.
However, there's still a deprecated managed variant of MemoryPool, so I switched
to it (we can do a small follow up PR to move to the unmanaged after).

I tried use_llvm = false, but it locks my computer, consuming RAM until MacOS
gives me a popup I've never seen before, begging me to start killing processes.

Agent and the networking stuff saw the most significant changes.
2026-07-22 13:26:03 +08:00
Karl Seguin 7a9b93becc robots.txt: Improve robots.txt correctness.
This applies two individual fixes to our robots.txt parser. The first is that
instead of doing an exact match with the User-Agent, it extracts the
"productToken". A UA of Lightpanda/1.0, should match "Lightpanda". The second is
that an empty directive matches.

Given:

User-agent: Lightpanda
Disallow:

User-agent: *
Disallow: /

We would have failed for 2 reasons. Fix #1 is necessary, otherwise
"Lightpanda" != "Lightpanda/1.0". Fix #2 is necessary  because this robots.txt
does _not_ disallow Lightpanda from anything (e.g. the fallback doesn't apply
to us).
2026-07-20 15:00:04 +08:00
Karl Seguin eec06238d0 nits: just personalizing the code as a means to understand it. 2026-06-14 10:17:39 +08:00
Navid EMAD b0a087450d Surface server-side agent-discovery signals (Link header + Content-Signal)
Parse the HTTP `Link:` response header (RFC 8288) and the robots.txt
`Content-Signal` directive, surfacing both to the driving agent.

- structured_data: extract the registered Link relations (service-doc,
  service-desc, api) from the frame's retained response headers into a
  new `linkHeaders` field, flowing out via the structuredData MCP tool
  and LP.getStructuredData. Emitted only when present.
- Robots: capture Content-Signal preferences on a new content_signals
  field, read back via RobotStore.getContentSignals and the new
  LP.getContentSignal CDP command. Advisory only - never reaches
  isAllowed.

Refs #2680
2026-06-09 15:29:48 +02:00
Karl Seguin 2275416505 Page -> Frame
This is to pave the way for introducing a new "Page" container, which will take
over the page lifecycle currently burdening Session. The ultimate goal of that
is to allow the Session to have multiple pages (mostly for better transitions
between pages), which is hard to do now since the Session has so much state.

This rename was aggressive, e.g. currentPage() -> currentFrame() so that, when
the new Page container is added, you won't see "currentPage()" and wonder:

  "Does 'currentPage' mean the new Page container, or the Frame (which
  used to be called Page)".
2026-04-22 08:42:18 +08:00
Karl Seguin 2d20e57f80 Change all @import("...../log.zig") to const log = lp.log;
@import("lightpanda") where needed.

Would also like to do this for String, Page, Session and js which all stand out
as types that are use across the codebase.

I know that a few devs are doing this in new work and I haven't heard anyone
voice an objection.
2026-04-20 12:40:04 +08:00
Nikolay Govorov 8e59ce9e9f Prepare global NetworkRuntime module 2026-03-10 03:00:47 +00:00