This is a very small / mechanical change.

Three changes:
- js.Execution now has a page (instead of calling exec.context.page)
- js.Execution now has a session (instead of calling exec.context.page.session)
- js.Execution.context renamed to .js to be consistent with Frame and WGS
This commit is contained in:
Karl Seguin
2026-05-28 08:23:35 +08:00
parent 4e2f21990c
commit 05daa4a6dc
31 changed files with 133 additions and 126 deletions

View File

@@ -304,11 +304,13 @@ fn _createContext(self: *Env, global: anytype, params: ContextParams) !*Context
};
context.execution = .{
.js = context,
.url = &global.url,
.buf = &global.buf,
.charset = &global.charset,
.context = context,
.arena = global.arena,
.page = context.page,
.session = page.session,
.call_arena = params.call_arena,
._factory = global._factory,
._scheduler = &context.scheduler,

View File

@@ -30,6 +30,8 @@ const lp = @import("lightpanda");
const Context = @import("Context.zig");
const Scheduler = @import("Scheduler.zig");
const Page = @import("../Page.zig");
const Session = @import("../Session.zig");
const Factory = @import("../Factory.zig");
const HttpClient = @import("../HttpClient.zig");
const EventManagerBase = @import("../EventManagerBase.zig");
@@ -43,12 +45,15 @@ const Allocator = std.mem.Allocator;
const Execution = @This();
context: *Context,
js: *Context,
// Fields named to match Page for generic code (executor._factory works for both)
buf: []u8,
arena: Allocator,
call_arena: Allocator,
page: *Page,
session: *Session,
_factory: *Factory,
_scheduler: *Scheduler,
@@ -60,7 +65,7 @@ charset: *[]const u8,
// Returns the current base URL of the global scope.
pub fn base(self: *const Execution) [:0]const u8 {
return self.context.global.base();
return self.js.global.base();
}
pub fn dupeString(self: *const Execution, value: []const u8) ![]const u8 {
@@ -71,27 +76,27 @@ pub fn dupeString(self: *const Execution, value: []const u8) ![]const u8 {
}
pub fn getArena(self: *const Execution, size_or_bucket: anytype, debug: []const u8) !Allocator {
return self.context.page.getArena(size_or_bucket, debug);
return self.page.getArena(size_or_bucket, debug);
}
pub fn releaseArena(self: *const Execution, allocator: Allocator) void {
self.context.page.releaseArena(allocator);
self.page.releaseArena(allocator);
}
pub fn headersForRequest(self: *const Execution, headers: *HttpClient.Headers) !void {
return switch (self.context.global) {
return switch (self.js.global) {
inline else => |g| g.headersForRequest(headers),
};
}
pub fn isSameOrigin(self: *const Execution, url: [:0]const u8) bool {
return switch (self.context.global) {
return switch (self.js.global) {
inline else => |g| g.isSameOrigin(url),
};
}
pub fn makeRequest(self: *const Execution, req: HttpClient.Request) !void {
return switch (self.context.global) {
return switch (self.js.global) {
inline else => |g| g.makeRequest(req),
};
}
@@ -101,7 +106,7 @@ pub fn makeRequest(self: *const Execution, req: HttpClient.Request) !void {
// owning scope without caring whether it's a Frame or a Worker — e.g.
// WebSocket.init appending to `.websockets`.
pub fn httpOwner(self: *const Execution) *HttpClient.Owner {
return switch (self.context.global) {
return switch (self.js.global) {
inline else => |g| &g._http_owner,
};
}
@@ -113,31 +118,31 @@ pub fn dispatch(
handler: anytype,
comptime opts: EventManagerBase.DispatchDirectOptions,
) !void {
return switch (self.context.global) {
return switch (self.js.global) {
inline else => |g| g.dispatch(target, event, handler, opts),
};
}
pub fn hasDirectListeners(self: *const Execution, target: *EventTarget, typ: []const u8, handler: anytype) bool {
return switch (self.context.global) {
return switch (self.js.global) {
inline else => |g| g.hasDirectListeners(target, typ, handler),
};
}
pub fn performance(self: *const Execution) *Performance {
return switch (self.context.global) {
return switch (self.js.global) {
inline else => |g| g.performance(),
};
}
pub fn frameId(self: *const Execution) u32 {
return switch (self.context.global) {
return switch (self.js.global) {
inline else => |g| g._frame_id,
};
}
pub fn loaderId(self: *const Execution) u32 {
return switch (self.context.global) {
return switch (self.js.global) {
inline else => |g| g._loader_id,
};
}

View File

@@ -130,7 +130,7 @@ fn markAborted(self: *AbortSignal, reason_: ?Reason, exec: *const Execution) !vo
fn dispatchAbortEvent(self: *AbortSignal, exec: *const Execution) !void {
const target = self.asEventTarget();
const on_abort = self._on_abort;
switch (exec.context.global) {
switch (exec.js.global) {
inline else => |g| {
if (g._event_manager.hasDirectListeners(target, "abort", on_abort)) {
const event = try Event.initTrusted(comptime .wrap("abort"), .{}, g._page);
@@ -191,7 +191,7 @@ const ThrowIfAborted = union(enum) {
undefined: void,
};
pub fn throwIfAborted(self: *const AbortSignal, exec: *const Execution) !ThrowIfAborted {
const local = exec.context.local.?;
const local = exec.js.local.?;
if (self._aborted) {
const exception = switch (self._reason) {

View File

@@ -261,7 +261,7 @@ pub fn writePartWithEndings(part: []const u8, use_native_endings: bool, writer:
/// Returns a Promise that resolves with the contents of the blob
/// as binary data contained in an ArrayBuffer.
pub fn arrayBuffer(self: *const Blob, exec: *Execution) !js.Promise {
return exec.context.local.?.resolvePromise(js.ArrayBuffer{ .values = self._slice });
return exec.js.local.?.resolvePromise(js.ArrayBuffer{ .values = self._slice });
}
const ReadableStream = @import("streams/ReadableStream.zig");
@@ -274,7 +274,7 @@ pub fn stream(self: *const Blob, exec: *Execution) !*ReadableStream {
/// Returns a Promise that resolves with a string containing
/// the contents of the blob, interpreted as UTF-8.
pub fn text(self: *const Blob, exec: *Execution) !js.Promise {
return exec.context.local.?.resolvePromise(self._slice);
return exec.js.local.?.resolvePromise(self._slice);
}
/// Extension to Blob; works on Firefox and Safari.
@@ -282,7 +282,7 @@ pub fn text(self: *const Blob, exec: *Execution) !js.Promise {
/// Returns a Promise that resolves with a Uint8Array containing
/// the contents of the blob as an array of bytes.
pub fn bytes(self: *const Blob, exec: *Execution) !js.Promise {
return exec.context.local.?.resolvePromise(js.TypedArray(u8){ .values = self._slice });
return exec.js.local.?.resolvePromise(js.TypedArray(u8){ .values = self._slice });
}
/// Returns a new Blob object which contains data

View File

@@ -34,7 +34,7 @@ _counts: std.StringHashMapUnmanaged(u64) = .{},
pub const init: Console = .{};
fn dispatchConsoleMessage(values: []js.Value, console_type: Notification.ConsoleMessageType, exec: *js.Execution) void {
const notification = exec.context.page.session.notification;
const notification = exec.session.notification;
const ts = datetime.timestamp(.monotonic);
notification.dispatch(.console_message, &.{
@@ -54,7 +54,7 @@ fn dispatchConsoleMessage(values: []js.Value, console_type: Notification.Console
pub fn trace(_: *const Console, values: []js.Value, exec: *js.Execution) !void {
logger.debug(.js, "console.trace", .{
.stack = exec.context.local.?.stackTrace() catch "???",
.stack = exec.js.local.?.stackTrace() catch "???",
.args = ValueWriter{ .values = values },
});
dispatchConsoleMessage(values, .trace, exec);
@@ -90,7 +90,7 @@ pub fn assert(_: *const Console, assertion: js.Value, values: []js.Value) void {
}
pub fn @"error"(_: *const Console, values: []js.Value, exec: *js.Execution) void {
logger.warn(.js, "console.error", .{ValueWriter{ .values = values, .stack = exec.context.local.?.stackTrace() catch |err| @errorName(err) orelse "???" }});
logger.warn(.js, "console.error", .{ValueWriter{ .values = values, .stack = exec.js.local.?.stackTrace() catch |err| @errorName(err) orelse "???" }});
dispatchConsoleMessage(values, .@"error", exec);
}

View File

@@ -329,7 +329,7 @@ pub fn composedPath(self: *Event, exec: *Execution) ![]const *EventTarget {
// Add window at the end (unless we stopped at shadow boundary)
if (!stopped_at_shadow_boundary) {
if (path_len < path_buffer.len) {
switch (exec.context.global) {
switch (exec.js.global) {
.worker => {},
.frame => |frame| {
path_buffer[path_len] = frame.window.asEventTarget();

View File

@@ -63,7 +63,7 @@ pub fn dispatchEvent(self: *EventTarget, event: *Event, exec: *js.Execution) !bo
}
event._is_trusted = false;
switch (exec.context.global) {
switch (exec.js.global) {
.frame => |frame| {
event.acquireRef();
defer _ = event.releaseRef(frame._page);
@@ -99,7 +99,7 @@ pub fn addEventListener(self: *EventTarget, typ: []const u8, callback_: ?EventLi
};
};
switch (exec.context.global) {
switch (exec.js.global) {
inline else => |g| _ = try g._event_manager.register(self, typ, em_callback, options),
}
}
@@ -135,7 +135,7 @@ pub fn removeEventListener(self: *EventTarget, typ: []const u8, callback_: ?Even
};
};
switch (exec.context.global) {
switch (exec.js.global) {
inline else => |g| g._event_manager.remove(self, typ, em_callback, use_capture),
}
}

View File

@@ -257,7 +257,7 @@ fn dispatch(self: *FileReader, comptime event_type: DispatchType, progress_: ?Pr
const event = (try ProgressEvent.initTrusted(
comptime .wrap(typ),
.{ .total = progress.total, .loaded = progress.loaded },
exec.context.page,
exec.page,
)).asEvent();
return exec.dispatch(

View File

@@ -80,7 +80,7 @@ pub fn init(
return exec._factory.create(ImageData{
._width = width,
._height = height,
._data = try exec.context.local.?.createTypedArray(.uint8_clamped, size).persist(),
._data = try exec.js.local.?.createTypedArray(.uint8_clamped, size).persist(),
});
}

View File

@@ -121,7 +121,7 @@ pub fn registerTool(
// native MCP forwarder) can surface the new tool.
const event: Notification.ModelContextToolEvent = .{ .exec = exec, .tool = entry };
const session = switch (exec.context.global) {
const session = switch (exec.js.global) {
inline else => |g| g._session,
};
@@ -147,7 +147,7 @@ pub fn findTool(self: *ModelContext, name: []const u8) ?*Tool {
/// dispatching `model_context_tool_removed` for each. Cheap when no
/// signals fired (which is the common case).
fn markAborted(self: *ModelContext, tool: *Tool, exec: *const Execution) !void {
const session = switch (exec.context.global) {
const session = switch (exec.js.global) {
inline else => |g| g._session,
};
@@ -191,7 +191,7 @@ pub const ModelContextClient = struct {
exec: *const Execution,
) !js.Promise {
var ls: js.Local.Scope = undefined;
exec.context.global.getJs().localScope(&ls);
exec.js.global.getJs().localScope(&ls);
defer ls.deinit();
const resolver = ls.local.createPromiseResolver();

View File

@@ -61,7 +61,7 @@ pub fn init(callback: js.Function.Global, exec: *const Execution) !*PerformanceO
._interests = 0,
._entries = .{},
._performance = exec.performance(),
._js = exec.context,
._js = exec.js,
._arena = exec.arena,
});
}

View File

@@ -51,7 +51,7 @@ pub fn generateKey(
key_usages: []const []const u8,
exec: *const Execution,
) !js.Promise {
const local = exec.context.local.?;
const local = exec.js.local.?;
switch (algo) {
.hmac_key_gen => |params| return HMAC.init(params, extractable, key_usages, exec),
.aes_key_gen => |params| {
@@ -87,7 +87,7 @@ fn generateKeyFromName(
exec: *const Execution,
) !js.Promise {
return _generateKeyFromName(name, extractable, key_usages, exec) catch |err| {
return exec.context.local.?.rejectPromise(.{ .dom_exception = .{ .err = err } });
return exec.js.local.?.rejectPromise(.{ .dom_exception = .{ .err = err } });
};
}
@@ -147,7 +147,7 @@ pub fn exportKey(
key: *CryptoKey,
exec: *const Execution,
) !js.Promise {
const local = exec.context.local.?;
const local = exec.js.local.?;
if (!key.canExportKey()) {
return local.rejectPromise(.{ .dom_exception = .{ .err = error.InvalidAccessError } });
}
@@ -175,7 +175,7 @@ pub fn deriveBits(
length: usize,
exec: *const Execution,
) !js.Promise {
const local = exec.context.local.?;
const local = exec.js.local.?;
return switch (algo) {
.ecdh_or_x25519 => |params| {
const name = params.name;
@@ -213,7 +213,7 @@ pub fn sign(
.hmac => return HMAC.sign(algo, key, data, exec),
else => {
log.warn(.not_implemented, "SubtleCrypto.sign", .{ .key_type = key._type });
return exec.context.local.?.rejectPromise(.{ .dom_exception = .{ .err = error.InvalidAccessError } });
return exec.js.local.?.rejectPromise(.{ .dom_exception = .{ .err = error.InvalidAccessError } });
},
};
}
@@ -227,7 +227,7 @@ pub fn verify(
data: []const u8, // ArrayBuffer.
exec: *const Execution,
) !js.Promise {
const local = exec.context.local.?;
const local = exec.js.local.?;
if (!algo.isHMAC()) {
return local.rejectPromise(.{ .dom_exception = .{ .err = error.InvalidAccessError } });
}
@@ -240,7 +240,7 @@ pub fn verify(
/// Generates a digest of the given data, using the specified hash function.
pub fn digest(_: *const SubtleCrypto, algo: []const u8, data: js.TypedArray(u8), exec: *const Execution) !js.Promise {
const local = exec.context.local.?;
const local = exec.js.local.?;
if (algo.len > 10) {
return local.rejectPromise(.{ .dom_exception = .{ .err = error.NotSupported } });

View File

@@ -108,7 +108,7 @@ pub fn schedule(
};
gop.value_ptr.* = callback;
try exec.context.scheduler.add(callback, ScheduleCallback.run, delay_ms, .{
try exec.js.scheduler.add(callback, ScheduleCallback.run, delay_ms, .{
.name = opts.name,
.low_priority = opts.low_priority,
.finalizer = ScheduleCallback.cancelled,
@@ -135,7 +135,7 @@ pub const LegacyHandler = union(enum) {
switch (handler) {
.function => |fun| return fun,
.string => |str| {
const fun = try exec.context.local.?.compileFunction(str, &.{}, &.{});
const fun = try exec.js.local.?.compileFunction(str, &.{}, &.{});
return fun.temp();
},
}
@@ -182,7 +182,7 @@ const ScheduleCallback = struct {
}
var ls: js.Local.Scope = undefined;
self.exec.context.localScope(&ls);
self.exec.js.localScope(&ls);
defer ls.deinit();
switch (self.mode) {
@@ -195,7 +195,7 @@ const ScheduleCallback = struct {
.animation_frame => {
// requestAnimationFrame is window-only; if a worker ever
// schedules with this mode it's a programming error.
const window = switch (self.exec.context.global) {
const window = switch (self.exec.js.global) {
.frame => |frame| frame.window,
.worker => unreachable,
};

View File

@@ -251,7 +251,7 @@ pub fn createObjectURL(blob: *Blob, exec: *const Execution) ![]const u8 {
var uuid_buf: [36]u8 = undefined;
@import("../../id.zig").uuidv4(&uuid_buf);
switch (exec.context.global) {
switch (exec.js.global) {
inline else => |g| {
const blob_url = try std.fmt.allocPrint(
g.arena,
@@ -271,7 +271,7 @@ pub fn revokeObjectURL(url: []const u8, exec: *const Execution) void {
return;
}
switch (exec.context.global) {
switch (exec.js.global) {
inline else => |g| {
if (g._blob_urls.fetchRemove(url)) |entry| {
entry.value.releaseRef(g._page);

View File

@@ -73,8 +73,8 @@ pub fn getContext(_: *OffscreenCanvas, context_type: []const u8, exec: *Executio
/// Returns a Promise that resolves to a Blob containing the image.
/// Since we have no actual rendering, this returns an empty blob.
pub fn convertToBlob(_: *OffscreenCanvas, exec: *Execution) !js.Promise {
const blob = try Blob.init(null, null, exec.context.page);
return exec.context.local.?.resolvePromise(blob);
const blob = try Blob.init(null, null, exec.page);
return exec.js.local.?.resolvePromise(blob);
}
/// Returns an ImageBitmap with the rendered content (stub).

View File

@@ -35,7 +35,7 @@ pub fn init(
key_usages: []const []const u8,
exec: *const Execution,
) !js.Promise {
const local = exec.context.local.?;
const local = exec.js.local.?;
// Per spec, an unrecognized hash is caught during algorithm normalization
// and surfaces as NotSupportedError.
const digest = crypto.findDigest(switch (params.hash) {
@@ -99,7 +99,7 @@ pub fn sign(
data: []const u8,
exec: *const Execution,
) !js.Promise {
var resolver = exec.context.local.?.createPromiseResolver();
var resolver = exec.js.local.?.createPromiseResolver();
if (!algo.isHMAC() or !crypto_key.canSign()) {
resolver.rejectError("HMAC.sign", .{ .dom_exception = .{ .err = error.InvalidAccessError } });
@@ -135,7 +135,7 @@ pub fn verify(
data: []const u8,
exec: *const Execution,
) !js.Promise {
var resolver = exec.context.local.?.createPromiseResolver();
var resolver = exec.js.local.?.createPromiseResolver();
if (!crypto_key.canVerify()) {
resolver.rejectError("HMAC.verify", .{ .dom_exception = .{ .err = error.InvalidAccessError } });

View File

@@ -37,7 +37,7 @@ pub fn init(
// gather them together with a single alloc call. Not sure if factory
// pattern is suitable for it though.
const local = exec.context.local.?;
const local = exec.js.local.?;
// Calculate usages; only matters for private key.
// Only deriveKey() and deriveBits() be used for X25519.

View File

@@ -47,7 +47,7 @@ pub const Input = Request.Input;
pub const InitOpts = Request.InitOpts;
pub fn init(input: Input, options: ?InitOpts, exec: *const Execution) !js.Promise {
const resolver = exec.context.local.?.createPromiseResolver();
const resolver = exec.js.local.?.createPromiseResolver();
// A bad RequestInit (e.g. an invalid priority) must reject the promise,
// not throw synchronously.
@@ -64,7 +64,7 @@ pub fn init(input: Input, options: ?InitOpts, exec: *const Execution) !js.Promis
}
const response = try Response.init(null, .{ .status = 0 }, exec);
errdefer response.deinit(exec.context.page);
errdefer response.deinit(exec.page);
const fetch = try response._arena.create(Fetch);
fetch.* = .{
@@ -77,7 +77,7 @@ pub fn init(input: Input, options: ?InitOpts, exec: *const Execution) !js.Promis
._signal = request._signal,
};
const session = exec.context.page.session;
const session = exec.session;
const http_client = &session.browser.http_client;
var headers = try http_client.newHeaders();
if (request._headers) |h| {
@@ -213,7 +213,7 @@ fn httpDoneCallback(ctx: *anyopaque) !void {
});
var ls: js.Local.Scope = undefined;
self._exec.context.localScope(&ls);
self._exec.js.localScope(&ls);
defer ls.deinit();
const js_val = try ls.local.zigValueToJs(self._response, .{});
@@ -244,11 +244,11 @@ fn httpErrorCallback(ctx: *anyopaque, err: anyerror) void {
// clear this. (defer since `self is in the response's arena).
defer if (owns_response) {
response.deinit(self._exec.context.page);
response.deinit(self._exec.page);
};
var ls: js.Local.Scope = undefined;
self._exec.context.localScope(&ls);
self._exec.js.localScope(&ls);
defer ls.deinit();
// fetch() must reject with a TypeError on network errors per spec
@@ -261,7 +261,7 @@ fn httpShutdownCallback(ctx: *anyopaque) void {
if (self._owns_response) {
var response = self._response;
response._http_response = null;
response.deinit(self._exec.context.page);
response.deinit(self._exec.page);
// Do not access `self` after this point: the Fetch struct was
// allocated from response._arena which has been released.
}

View File

@@ -68,7 +68,7 @@ pub fn init(form_: ?*Form, submitter: ?*Element, exec: *const Execution) !*FormD
});
};
const frame = switch (exec.context.global) {
const frame = switch (exec.js.global) {
.frame => |f| f,
.worker => lp.assert(false, "FormData worker form", .{}),
};

View File

@@ -214,7 +214,7 @@ fn consume(self: *Request, local: *const js.Local) ?js.Promise {
}
pub fn blob(self: *Request, exec: *const Execution) !js.Promise {
const local = exec.context.local.?;
const local = exec.js.local.?;
if (self.consume(local)) |rejected| {
return rejected;
}
@@ -223,12 +223,12 @@ pub fn blob(self: *Request, exec: *const Execution) !js.Promise {
const headers = try self.getHeaders(exec);
const content_type = try headers.get("content-type", exec) orelse "";
const b = try Blob.initFromBytes(body, content_type, true, exec.context.page);
const b = try Blob.initFromBytes(body, content_type, true, exec.page);
return local.resolvePromise(b);
}
pub fn text(self: *Request, exec: *const Execution) !js.Promise {
const local = exec.context.local.?;
const local = exec.js.local.?;
if (self.consume(local)) |rejected| {
return rejected;
}
@@ -236,7 +236,7 @@ pub fn text(self: *Request, exec: *const Execution) !js.Promise {
}
pub fn json(self: *Request, exec: *const Execution) !js.Promise {
const local = exec.context.local.?;
const local = exec.js.local.?;
if (self.consume(local)) |rejected| {
return rejected;
}
@@ -248,7 +248,7 @@ pub fn json(self: *Request, exec: *const Execution) !js.Promise {
}
pub fn arrayBuffer(self: *Request, exec: *const Execution) !js.Promise {
const local = exec.context.local.?;
const local = exec.js.local.?;
if (self.consume(local)) |rejected| {
return rejected;
}
@@ -256,7 +256,7 @@ pub fn arrayBuffer(self: *Request, exec: *const Execution) !js.Promise {
}
pub fn bytes(self: *Request, exec: *const Execution) !js.Promise {
const local = exec.context.local.?;
const local = exec.js.local.?;
if (self.consume(local)) |rejected| {
return rejected;
}

View File

@@ -70,7 +70,7 @@ const InitOpts = struct {
pub const BodyInit = body_init.BodyInit;
pub fn init(body_: ?BodyInit, opts_: ?InitOpts, exec: *const Execution) !*Response {
const session = exec.context.page.session;
const session = exec.session;
const arena = try session.getArena(.large, "Response");
errdefer session.releaseArena(arena);
@@ -191,7 +191,7 @@ fn consume(self: *Response, local: *const js.Local) ?js.Promise {
}
pub fn getText(self: *Response, exec: *const Execution) !js.Promise {
const local = exec.context.local.?;
const local = exec.js.local.?;
if (self.consume(local)) |rejected| {
return rejected;
}
@@ -205,7 +205,7 @@ pub fn getText(self: *Response, exec: *const Execution) !js.Promise {
}
pub fn getJson(self: *Response, exec: *const Execution) !js.Promise {
const local = exec.context.local.?;
const local = exec.js.local.?;
if (self.consume(local)) |rejected| {
return rejected;
}
@@ -222,7 +222,7 @@ pub fn getJson(self: *Response, exec: *const Execution) !js.Promise {
}
pub fn arrayBuffer(self: *Response, exec: *const Execution) !js.Promise {
const local = exec.context.local.?;
const local = exec.js.local.?;
if (self.consume(local)) |rejected| {
return rejected;
}
@@ -246,7 +246,7 @@ const StreamConsumer = struct {
resolver: js.PromiseResolver.Global,
fn start(stream: *ReadableStream, exec: *const Execution) !js.Promise {
const local = exec.context.local.?;
const local = exec.js.local.?;
var resolver = local.createPromiseResolver();
const promise = resolver.promise();
@@ -267,7 +267,7 @@ const StreamConsumer = struct {
}
fn pumpRead(self: *StreamConsumer) !void {
const local = self.execution.context.local.?;
const local = self.execution.js.local.?;
const read_promise = try self.reader.read(self.execution);
const then_fn = local.newCallback(onReadFulfilled, self);
@@ -284,7 +284,7 @@ const StreamConsumer = struct {
};
fn onReadFulfilled(self: *StreamConsumer, data_: ?ReadData) void {
const local = self.execution.context.local.?;
const local = self.execution.js.local.?;
const data = data_ orelse {
return self.finish(local, null);
@@ -297,7 +297,7 @@ const StreamConsumer = struct {
fn _onReadFulfilled(self: *StreamConsumer, data: ReadData) !void {
const exec = self.execution;
const local = exec.context.local.?;
const local = exec.js.local.?;
if (data.done) {
// Stream is finished, concatenate all chunks and resolve
@@ -328,7 +328,7 @@ const StreamConsumer = struct {
}
fn onReadRejected(self: *StreamConsumer) void {
self.finish(self.execution.context.local.?, null);
self.finish(self.execution.js.local.?, null);
}
fn concatenateChunks(self: *StreamConsumer, allocator: Allocator) ![]const u8 {
@@ -348,7 +348,7 @@ const StreamConsumer = struct {
};
pub fn blob(self: *Response, exec: *const Execution) !js.Promise {
const local = exec.context.local.?;
const local = exec.js.local.?;
if (self.consume(local)) |rejected| return rejected;
const body = switch (self._body) {
.bytes => |b| b,
@@ -356,12 +356,12 @@ pub fn blob(self: *Response, exec: *const Execution) !js.Promise {
.stream => return local.rejectPromise(.{ .type_error = "Cannot read blob from stream body" }),
};
const content_type = try self._headers.get("content-type", exec) orelse "";
const b = try Blob.initFromBytes(body, content_type, true, exec.context.page);
const b = try Blob.initFromBytes(body, content_type, true, exec.page);
return local.resolvePromise(b);
}
pub fn bytes(self: *Response, exec: *const Execution) !js.Promise {
const local = exec.context.local.?;
const local = exec.js.local.?;
if (self.consume(local)) |rejected| return rejected;
const body = switch (self._body) {
.bytes => |b| b,
@@ -372,7 +372,7 @@ pub fn bytes(self: *Response, exec: *const Execution) !js.Promise {
}
pub fn clone(self: *const Response, exec: *const Execution) !*Response {
const session = exec.context.page.session;
const session = exec.session;
const body_len = switch (self._body) {
.bytes => |b| b.len,
.empty => 0,

View File

@@ -117,7 +117,7 @@ pub fn init(url: []const u8, protocols: [][]const u8, exec: *const Execution) !*
const resolved_url = try URL.resolve(arena, exec.base(), url, .{ .always_dupe = true, .encoding = exec.charset.* });
const http_client = &exec.context.page.session.browser.http_client;
const http_client = &exec.session.browser.http_client;
const conn = http_client.network.newConnection() orelse {
return error.NoFreeConnection;
};
@@ -240,7 +240,7 @@ fn cleanup(self: *WebSocket) void {
self._http_client.removeConn(conn);
self._req_headers.deinit();
self._conn = null;
self.releaseRef(self._exec.context.page);
self.releaseRef(self._exec.page);
self._send_queue.clearRetainingCapacity();
}
}
@@ -457,7 +457,7 @@ fn dispatchOpenEvent(self: *WebSocket) !void {
const target = self.asEventTarget();
if (exec.hasDirectListeners(target, "open", self._on_open)) {
const event = try Event.initTrusted(comptime .wrap("open"), .{}, exec.context.page);
const event = try Event.initTrusted(comptime .wrap("open"), .{}, exec.page);
try exec.dispatch(target, event, self._on_open, .{ .context = "WebSocket open" });
}
}
@@ -471,7 +471,7 @@ fn dispatchMessageEvent(self: *WebSocket, data: []const u8, frame_type: http.WsF
switch (self._binary_type) {
.arraybuffer => .{ .arraybuffer = .{ .values = data } },
.blob => blk: {
const blob = try Blob.initFromBytes(data, "", false, exec.context.page);
const blob = try Blob.initFromBytes(data, "", false, exec.page);
blob.acquireRef();
break :blk .{ .blob = blob };
},
@@ -482,7 +482,7 @@ fn dispatchMessageEvent(self: *WebSocket, data: []const u8, frame_type: http.WsF
const event = try MessageEvent.initTrusted(comptime .wrap("message"), .{
.data = msg_data,
.origin = "",
}, exec.context.page);
}, exec.page);
try exec.dispatch(target, event.asEvent(), self._on_message, .{ .context = "WebSocket message" });
}
}
@@ -492,7 +492,7 @@ fn dispatchErrorEvent(self: *WebSocket) !void {
const target = self.asEventTarget();
if (exec.hasDirectListeners(target, "error", self._on_error)) {
const event = try Event.initTrusted(comptime .wrap("error"), .{}, exec.context.page);
const event = try Event.initTrusted(comptime .wrap("error"), .{}, exec.page);
try exec.dispatch(target, event, self._on_error, .{ .context = "WebSocket error" });
}
}
@@ -506,7 +506,7 @@ fn dispatchCloseEvent(self: *WebSocket, code: u16, reason: []const u8, was_clean
.code = code,
.reason = reason,
.wasClean = was_clean,
}, exec.context.page);
}, exec.page);
try exec.dispatch(target, event.asEvent(), self._on_close, .{ .context = "WebSocket close" });
}
}
@@ -580,7 +580,7 @@ fn writeContent(self: *WebSocket, conn: *http.Connection, buf: []u8, byte_msg: M
if (self._send_offset >= byte_msg.data.len) {
const removed = self._send_queue.orderedRemove(0);
removed.deinit(self._exec.context.page);
removed.deinit(self._exec.page);
if (comptime IS_DEBUG) {
log.debug(.websocket, "send complete", .{ .url = self._url, .len = byte_msg.data.len, .queue = self._send_queue.items.len });
}

View File

@@ -146,7 +146,7 @@ fn releaseSelfRef(self: *XMLHttpRequest) void {
return;
}
self._active_request = false;
self.releaseRef(self._exec.context.page);
self.releaseRef(self._exec.page);
}
pub fn releaseRef(self: *XMLHttpRequest, page: *Page) void {
@@ -249,7 +249,7 @@ pub fn send(self: *XMLHttpRequest, body_: ?BodyInit, exec_: *const Execution) !v
const exec = self._exec;
const session = exec.context.page.session;
const session = exec.session;
const http_client = &session.browser.http_client;
var headers = try http_client.newHeaders();
@@ -367,13 +367,13 @@ pub fn getResponse(self: *XMLHttpRequest, exec: *const Execution) !?Response {
const res: Response = switch (self._response_type) {
.text => .{ .text = data },
.json => blk: {
const value = try exec.context.local.?.parseJSON(data);
const value = try exec.js.local.?.parseJSON(data);
break :blk .{ .json = try value.persist() };
},
.document => blk: {
// responseType=document is only meaningful in a Frame; workers
// have no DOM. Drastically different impls -> switch on global.
switch (exec.context.global) {
switch (exec.js.global) {
.frame => |frame| {
const document = try exec._factory.node(Node.Document{ ._proto = undefined, ._type = .generic });
try frame.parseHtmlAsChildren(document.asNode(), data);
@@ -449,7 +449,7 @@ fn httpHeaderDoneCallback(response: HttpClient.Response) !bool {
const exec = self._exec;
var ls: js.Local.Scope = undefined;
exec.context.localScope(&ls);
exec.js.localScope(&ls);
defer ls.deinit();
try self.stateChanged(.headers_received, exec);
@@ -570,7 +570,7 @@ fn stateChanged(self: *XMLHttpRequest, state: ReadyState, exec: *const Execution
const target = self.asEventTarget();
if (exec.hasDirectListeners(target, "readystatechange", self._on_ready_state_change)) {
const event = try Event.initTrusted(.wrap("readystatechange"), .{}, exec.context.page);
const event = try Event.initTrusted(.wrap("readystatechange"), .{}, exec.page);
try exec.dispatch(target, event, self._on_ready_state_change, .{ .context = "XHR state change" });
}
}

View File

@@ -61,7 +61,7 @@ pub fn dispatch(self: *XMLHttpRequestEventTarget, comptime event_type: DispatchT
const event = (try ProgressEvent.initTrusted(
comptime .wrap(typ),
.{ .total = progress.total, .loaded = progress.loaded },
exec.context.page,
exec.page,
)).asEvent();
return exec.dispatch(

View File

@@ -145,9 +145,9 @@ pub fn callPullIfNeeded(self: *ReadableStream) !void {
const exec = self._execution;
if (comptime IS_DEBUG) {
if (exec.context.local == null) {
if (exec.js.local == null) {
log.fatal(.bug, "null context scope", .{ .src = "ReadableStream.callPullIfNeeded", .url = exec.url.* });
std.debug.assert(exec.context.local != null);
std.debug.assert(exec.js.local != null);
}
}
@@ -155,7 +155,7 @@ pub fn callPullIfNeeded(self: *ReadableStream) !void {
const func = self._pull_fn orelse return;
var ls: js.Local.Scope = undefined;
exec.context.localScope(&ls);
exec.js.localScope(&ls);
defer ls.deinit();
// Call the pull function
@@ -187,7 +187,7 @@ fn shouldCallPull(self: *const ReadableStream) bool {
}
pub fn cancel(self: *ReadableStream, reason: ?[]const u8, exec: *const Execution) !js.Promise {
const local = exec.context.local.?;
const local = exec.js.local.?;
if (self._state != .readable) {
if (self._cancel) |c| {
@@ -257,10 +257,10 @@ pub fn pipeThrough(self: *ReadableStream, transform: PipeTransform, exec: *const
/// Returns a promise that resolves when piping is complete.
pub fn pipeTo(self: *ReadableStream, destination: *WritableStream, exec: *const Execution) !js.Promise {
if (self.getLocked()) {
return exec.context.local.?.rejectPromise(.{ .type_error = "ReadableStream is locked" });
return exec.js.local.?.rejectPromise(.{ .type_error = "ReadableStream is locked" });
}
const local = exec.context.local.?;
const local = exec.js.local.?;
var pipe_resolver = local.createPromiseResolver();
const promise = pipe_resolver.promise();
const persisted_resolver = try pipe_resolver.persist();
@@ -295,7 +295,7 @@ const PipeState = struct {
fn pumpRead(state: *PipeState) !void {
const exec = state.execution;
const local = exec.context.local.?;
const local = exec.js.local.?;
// Call reader.read() which returns a Promise
const read_promise = try state.reader.read(exec);
@@ -315,7 +315,7 @@ const PipeState = struct {
};
fn onReadFulfilled(self: *PipeState, data_: ?ReadData) void {
const exec = self.execution;
const local = exec.context.local.?;
const local = exec.js.local.?;
const data = data_ orelse {
return self.finish(local);
};
@@ -346,7 +346,7 @@ const PipeState = struct {
}
fn onReadRejected(self: *PipeState) void {
self.finish(self.execution.context.local.?);
self.finish(self.execution.js.local.?);
}
fn finish(self: *PipeState, local: *const js.Local) void {
@@ -399,7 +399,7 @@ pub const AsyncIterator = struct {
pub fn @"return"(self: *AsyncIterator, exec: *const Execution) !js.Promise {
self._reader.releaseLock();
return exec.context.local.?.resolvePromise(.{ .done = true, .value = null });
return exec.js.local.?.resolvePromise(.{ .done = true, .value = null });
}
pub const JsApi = struct {

View File

@@ -64,7 +64,7 @@ pub fn init(stream: *ReadableStream, high_water_mark: u32, exec: *const Executio
}
pub fn addPendingRead(self: *ReadableStreamDefaultController) !js.Promise {
const resolver = self._execution.context.local.?.createPromiseResolver();
const resolver = self._execution.js.local.?.createPromiseResolver();
try self._pending_reads.append(self._arena, try resolver.persist());
return resolver.promise();
}
@@ -89,14 +89,14 @@ pub fn enqueue(self: *ReadableStreamDefaultController, chunk: Chunk) !void {
};
if (comptime IS_DEBUG) {
if (exec.context.local == null) {
if (exec.js.local == null) {
log.fatal(.bug, "null context scope", .{ .src = "ReadableStreamDefaultController.enqueue", .url = exec.url.* });
std.debug.assert(exec.context.local != null);
std.debug.assert(exec.js.local != null);
}
}
var ls: js.Local.Scope = undefined;
exec.context.localScope(&ls);
exec.js.localScope(&ls);
defer ls.deinit();
ls.toLocal(resolver).resolve("stream enqueue", result);
@@ -124,14 +124,14 @@ pub fn enqueueValue(self: *ReadableStreamDefaultController, value: js.Value) !vo
};
if (comptime IS_DEBUG) {
if (exec.context.local == null) {
if (exec.js.local == null) {
log.fatal(.bug, "null context scope", .{ .src = "ReadableStreamDefaultController.enqueueValue", .url = exec.url.* });
std.debug.assert(exec.context.local != null);
std.debug.assert(exec.js.local != null);
}
}
var ls: js.Local.Scope = undefined;
exec.context.localScope(&ls);
exec.js.localScope(&ls);
defer ls.deinit();
ls.toLocal(resolver).resolve("stream enqueue value", result);
@@ -152,15 +152,15 @@ pub fn close(self: *ReadableStreamDefaultController) !void {
const exec = self._execution;
if (comptime IS_DEBUG) {
if (exec.context.local == null) {
if (exec.js.local == null) {
log.fatal(.bug, "null context scope", .{ .src = "ReadableStreamDefaultController.close", .url = exec.url.* });
std.debug.assert(exec.context.local != null);
std.debug.assert(exec.js.local != null);
}
}
for (self._pending_reads.items) |resolver| {
var ls: js.Local.Scope = undefined;
exec.context.localScope(&ls);
exec.js.localScope(&ls);
defer ls.deinit();
ls.toLocal(resolver).resolve("stream close", result);
}
@@ -178,7 +178,7 @@ pub fn doError(self: *ReadableStreamDefaultController, err: []const u8) !void {
// Reject all pending reads
for (self._pending_reads.items) |resolver| {
self._execution.context.toLocal(resolver).reject("stream error", err);
self._execution.js.toLocal(resolver).reject("stream error", err);
}
self._pending_reads.clearRetainingCapacity();
}

View File

@@ -58,7 +58,7 @@ pub const ReadResult = struct {
};
pub fn read(self: *ReadableStreamDefaultReader, exec: *const Execution) !js.Promise {
const local = exec.context.local.?;
const local = exec.js.local.?;
const stream = self._stream orelse {
return local.rejectPromise(.{ .type_error = "Reader has been released" });
};
@@ -97,7 +97,7 @@ pub fn releaseLock(self: *ReadableStreamDefaultReader) void {
pub fn cancel(self: *ReadableStreamDefaultReader, reason_: ?[]const u8, exec: *const Execution) !js.Promise {
const stream = self._stream orelse {
return exec.context.local.?.rejectPromise(.{ .type_error = "Reader has been released" });
return exec.js.local.?.rejectPromise(.{ .type_error = "Reader has been released" });
};
self.releaseLock();

View File

@@ -94,7 +94,7 @@ pub fn transformWrite(self: *TransformStream, chunk: js.Value, exec: *const Exec
if (self._controller._transform_fn) |transform_fn| {
var ls: js.Local.Scope = undefined;
exec.context.localScope(&ls);
exec.js.localScope(&ls);
defer ls.deinit();
try ls.toLocal(transform_fn).call(void, .{ chunk, self._controller });
@@ -106,7 +106,7 @@ pub fn transformWrite(self: *TransformStream, chunk: js.Value, exec: *const Exec
pub fn transformClose(self: *TransformStream, exec: *const Execution) !void {
if (self._controller._flush_fn) |flush_fn| {
var ls: js.Local.Scope = undefined;
exec.context.localScope(&ls);
exec.js.localScope(&ls);
defer ls.deinit();
try ls.toLocal(flush_fn).call(void, .{self._controller});

View File

@@ -111,7 +111,7 @@ pub fn writeChunk(self: *WritableStream, chunk: js.Value, exec: *const Execution
if (self._write_fn) |write_fn| {
var ls: js.Local.Scope = undefined;
exec.context.localScope(&ls);
exec.js.localScope(&ls);
defer ls.deinit();
try ls.toLocal(write_fn).call(void, .{ chunk, self._controller });
@@ -129,7 +129,7 @@ pub fn closeStream(self: *WritableStream, exec: *const Execution) !void {
if (self._close_fn) |close_fn| {
var ls: js.Local.Scope = undefined;
exec.context.localScope(&ls);
exec.js.localScope(&ls);
defer ls.deinit();
try ls.toLocal(close_fn).call(void, .{self._controller});

View File

@@ -32,7 +32,7 @@ pub fn init(stream: *WritableStream, exec: *const Execution) !*WritableStreamDef
}
pub fn write(self: *WritableStreamDefaultWriter, chunk: js.Value, exec: *const Execution) !js.Promise {
const local = exec.context.local.?;
const local = exec.js.local.?;
const stream = self._stream orelse {
return local.rejectPromise(.{ .type_error = "Writer has been released" });
};
@@ -47,7 +47,7 @@ pub fn write(self: *WritableStreamDefaultWriter, chunk: js.Value, exec: *const E
}
pub fn close(self: *WritableStreamDefaultWriter, exec: *const Execution) !js.Promise {
const local = exec.context.local.?;
const local = exec.js.local.?;
const stream = self._stream orelse {
return local.rejectPromise(.{ .type_error = "Writer has been released" });
};
@@ -69,7 +69,7 @@ pub fn releaseLock(self: *WritableStreamDefaultWriter) void {
}
pub fn getClosed(self: *WritableStreamDefaultWriter, exec: *const Execution) !js.Promise {
const local = exec.context.local.?;
const local = exec.js.local.?;
const stream = self._stream orelse {
return local.rejectPromise(.{ .type_error = "Writer has been released" });
};
@@ -92,7 +92,7 @@ pub fn getDesiredSize(self: *const WritableStreamDefaultWriter) ?i32 {
pub fn getReady(self: *WritableStreamDefaultWriter, exec: *const Execution) !js.Promise {
_ = self;
return exec.context.local.?.resolvePromise(.{});
return exec.js.local.?.resolvePromise(.{});
}
pub const JsApi = struct {

View File

@@ -256,7 +256,7 @@ pub fn onToolAdded(
bc: *CDP.BrowserContext,
event: *const Notification.ModelContextToolEvent,
) !void {
const global = event.exec.context.global;
const global = event.exec.js.global;
var ls: js.Local.Scope = undefined;
global.getJs().localScope(&ls);
@@ -280,7 +280,7 @@ pub fn onToolRemoved(
bc: *CDP.BrowserContext,
event: *const Notification.ModelContextToolEvent,
) !void {
const frame_id = switch (event.exec.context.global) {
const frame_id = switch (event.exec.js.global) {
inline else => |g| g._frame_id,
};
try bc.cdp.sendEvent("WebMCP.toolsRemoved", .{