mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-03-22 20:54:43 +00:00
Remove the generic nature of Env and most of the JS classes
Back in the zig-js-runtime days, globals were used for the state and webapi
declarations. This caused problems largely because it was done across
compilation units (using @import("root")...).
The generic Env(S, WebApi) was used to solve these problems, while still making
it work for different States and WebApis.
This change removes the generics and hard-codes the *Page as the state and
only supports our WebApis for the class declarations.
To accommodate this change, the runtime/*tests* have been removed. I don't
consider this a huge loss - whatever behavior these were testing, already
exists in the browser/**/*.zig web api.
As we write more complex/complete WebApis, we're seeing more and more cases
that need to rely on js objects directly (JsObject, Function, Promises, etc...).
The goal is to make these easier to use. Rather than using Env.JsObject, you
now import "js.zig" and use js.JsObject (TODO: rename JsObject to Object).
Everything is just a plain Zig struct, rather than being nested in a generic.
After this change, I plan on:
1 - Renaming the js objects, JsObject -> Object. These should be referenced in
the webapi as js.Object, js.This, ...
2 - Splitting the code across multiple files (Env.zig, Context.zig,
Caller.zig, ...)
This commit is contained in:
@@ -4,7 +4,7 @@ const Allocator = std.mem.Allocator;
|
|||||||
|
|
||||||
const log = @import("log.zig");
|
const log = @import("log.zig");
|
||||||
const Http = @import("http/Http.zig");
|
const Http = @import("http/Http.zig");
|
||||||
const Platform = @import("runtime/js.zig").Platform;
|
const Platform = @import("browser/js/js.zig").Platform;
|
||||||
|
|
||||||
const Telemetry = @import("telemetry/telemetry.zig").Telemetry;
|
const Telemetry = @import("telemetry/telemetry.zig").Telemetry;
|
||||||
const Notification = @import("notification.zig").Notification;
|
const Notification = @import("notification.zig").Notification;
|
||||||
|
|||||||
@@ -18,10 +18,10 @@
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
|
const js = @import("js/js.zig");
|
||||||
const log = @import("../log.zig");
|
const log = @import("../log.zig");
|
||||||
const parser = @import("netsurf.zig");
|
const parser = @import("netsurf.zig");
|
||||||
|
|
||||||
const Env = @import("env.zig").Env;
|
|
||||||
const Page = @import("page.zig").Page;
|
const Page = @import("page.zig").Page;
|
||||||
const DataURI = @import("DataURI.zig");
|
const DataURI = @import("DataURI.zig");
|
||||||
const Http = @import("../http/Http.zig");
|
const Http = @import("../http/Http.zig");
|
||||||
@@ -627,7 +627,7 @@ const Script = struct {
|
|||||||
|
|
||||||
const Callback = union(enum) {
|
const Callback = union(enum) {
|
||||||
string: []const u8,
|
string: []const u8,
|
||||||
function: Env.Function,
|
function: js.Function,
|
||||||
};
|
};
|
||||||
|
|
||||||
const Source = union(enum) {
|
const Source = union(enum) {
|
||||||
@@ -664,7 +664,7 @@ const Script = struct {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const js_context = page.main_context;
|
const js_context = page.main_context;
|
||||||
var try_catch: Env.TryCatch = undefined;
|
var try_catch: js.TryCatch = undefined;
|
||||||
try_catch.init(js_context);
|
try_catch.init(js_context);
|
||||||
defer try_catch.deinit();
|
defer try_catch.deinit();
|
||||||
|
|
||||||
@@ -706,7 +706,7 @@ const Script = struct {
|
|||||||
|
|
||||||
switch (callback) {
|
switch (callback) {
|
||||||
.string => |str| {
|
.string => |str| {
|
||||||
var try_catch: Env.TryCatch = undefined;
|
var try_catch: js.TryCatch = undefined;
|
||||||
try_catch.init(page.main_context);
|
try_catch.init(page.main_context);
|
||||||
defer try_catch.deinit();
|
defer try_catch.deinit();
|
||||||
|
|
||||||
@@ -728,7 +728,7 @@ const Script = struct {
|
|||||||
};
|
};
|
||||||
defer parser.eventDestroy(loadevt);
|
defer parser.eventDestroy(loadevt);
|
||||||
|
|
||||||
var result: Env.Function.Result = undefined;
|
var result: js.Function.Result = undefined;
|
||||||
const iface = Event.toInterface(loadevt);
|
const iface = Event.toInterface(loadevt);
|
||||||
f.tryCall(void, .{iface}, &result) catch {
|
f.tryCall(void, .{iface}, &result) catch {
|
||||||
log.warn(.user_script, "script callback", .{
|
log.warn(.user_script, "script callback", .{
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
// this quickly proved necessary, since different fields are needed on the same
|
// this quickly proved necessary, since different fields are needed on the same
|
||||||
// data at different levels of the prototype chain. This isn't memory efficient.
|
// data at different levels of the prototype chain. This isn't memory efficient.
|
||||||
|
|
||||||
const Env = @import("env.zig").Env;
|
const js = @import("js/js.zig");
|
||||||
const parser = @import("netsurf.zig");
|
const parser = @import("netsurf.zig");
|
||||||
const DataSet = @import("html/DataSet.zig");
|
const DataSet = @import("html/DataSet.zig");
|
||||||
const ShadowRoot = @import("dom/shadow_root.zig").ShadowRoot;
|
const ShadowRoot = @import("dom/shadow_root.zig").ShadowRoot;
|
||||||
@@ -34,8 +34,8 @@ const StyleSheet = @import("cssom/StyleSheet.zig");
|
|||||||
const CSSStyleDeclaration = @import("cssom/CSSStyleDeclaration.zig");
|
const CSSStyleDeclaration = @import("cssom/CSSStyleDeclaration.zig");
|
||||||
|
|
||||||
// for HTMLScript (but probably needs to be added to more)
|
// for HTMLScript (but probably needs to be added to more)
|
||||||
onload: ?Env.Function = null,
|
onload: ?js.Function = null,
|
||||||
onerror: ?Env.Function = null,
|
onerror: ?js.Function = null,
|
||||||
|
|
||||||
// for HTMLElement
|
// for HTMLElement
|
||||||
style: CSSStyleDeclaration = .empty,
|
style: CSSStyleDeclaration = .empty,
|
||||||
@@ -53,7 +53,7 @@ style_sheet: ?*StyleSheet = null,
|
|||||||
|
|
||||||
// for dom/document
|
// for dom/document
|
||||||
active_element: ?*parser.Element = null,
|
active_element: ?*parser.Element = null,
|
||||||
adopted_style_sheets: ?Env.JsObject = null,
|
adopted_style_sheets: ?js.JsObject = null,
|
||||||
|
|
||||||
// for HTMLSelectElement
|
// for HTMLSelectElement
|
||||||
// By default, if no option is explicitly selected, the first option should
|
// By default, if no option is explicitly selected, the first option should
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ const std = @import("std");
|
|||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const ArenaAllocator = std.heap.ArenaAllocator;
|
const ArenaAllocator = std.heap.ArenaAllocator;
|
||||||
|
|
||||||
|
const js = @import("js/js.zig");
|
||||||
const State = @import("State.zig");
|
const State = @import("State.zig");
|
||||||
const Env = @import("env.zig").Env;
|
|
||||||
const App = @import("../app.zig").App;
|
const App = @import("../app.zig").App;
|
||||||
const Session = @import("session.zig").Session;
|
const Session = @import("session.zig").Session;
|
||||||
const Notification = @import("../notification.zig").Notification;
|
const Notification = @import("../notification.zig").Notification;
|
||||||
@@ -34,7 +34,7 @@ const HttpClient = @import("../http/Client.zig");
|
|||||||
// You can create multiple browser instances.
|
// You can create multiple browser instances.
|
||||||
// A browser contains only one session.
|
// A browser contains only one session.
|
||||||
pub const Browser = struct {
|
pub const Browser = struct {
|
||||||
env: *Env,
|
env: *js.Env,
|
||||||
app: *App,
|
app: *App,
|
||||||
session: ?Session,
|
session: ?Session,
|
||||||
allocator: Allocator,
|
allocator: Allocator,
|
||||||
@@ -48,7 +48,7 @@ pub const Browser = struct {
|
|||||||
pub fn init(app: *App) !Browser {
|
pub fn init(app: *App) !Browser {
|
||||||
const allocator = app.allocator;
|
const allocator = app.allocator;
|
||||||
|
|
||||||
const env = try Env.init(allocator, &app.platform, .{});
|
const env = try js.Env.init(allocator, &app.platform, .{});
|
||||||
errdefer env.deinit();
|
errdefer env.deinit();
|
||||||
|
|
||||||
const notification = try Notification.init(allocator, app.notification);
|
const notification = try Notification.init(allocator, app.notification);
|
||||||
|
|||||||
@@ -20,47 +20,47 @@ const std = @import("std");
|
|||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
|
|
||||||
|
const js = @import("../js/js.zig");
|
||||||
const Page = @import("../page.zig").Page;
|
const Page = @import("../page.zig").Page;
|
||||||
const JsObject = @import("../env.zig").Env.JsObject;
|
|
||||||
|
|
||||||
pub const Console = struct {
|
pub const Console = struct {
|
||||||
// TODO: configurable writer
|
// TODO: configurable writer
|
||||||
timers: std.StringHashMapUnmanaged(u32) = .{},
|
timers: std.StringHashMapUnmanaged(u32) = .{},
|
||||||
counts: std.StringHashMapUnmanaged(u32) = .{},
|
counts: std.StringHashMapUnmanaged(u32) = .{},
|
||||||
|
|
||||||
pub fn _lp(values: []JsObject, page: *Page) !void {
|
pub fn _lp(values: []js.JsObject, page: *Page) !void {
|
||||||
if (values.len == 0) {
|
if (values.len == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
log.fatal(.console, "lightpanda", .{ .args = try serializeValues(values, page) });
|
log.fatal(.console, "lightpanda", .{ .args = try serializeValues(values, page) });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _log(values: []JsObject, page: *Page) !void {
|
pub fn _log(values: []js.JsObject, page: *Page) !void {
|
||||||
if (values.len == 0) {
|
if (values.len == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
log.info(.console, "info", .{ .args = try serializeValues(values, page) });
|
log.info(.console, "info", .{ .args = try serializeValues(values, page) });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _info(values: []JsObject, page: *Page) !void {
|
pub fn _info(values: []js.JsObject, page: *Page) !void {
|
||||||
return _log(values, page);
|
return _log(values, page);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _debug(values: []JsObject, page: *Page) !void {
|
pub fn _debug(values: []js.JsObject, page: *Page) !void {
|
||||||
if (values.len == 0) {
|
if (values.len == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
log.debug(.console, "debug", .{ .args = try serializeValues(values, page) });
|
log.debug(.console, "debug", .{ .args = try serializeValues(values, page) });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _warn(values: []JsObject, page: *Page) !void {
|
pub fn _warn(values: []js.JsObject, page: *Page) !void {
|
||||||
if (values.len == 0) {
|
if (values.len == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
log.warn(.console, "warn", .{ .args = try serializeValues(values, page) });
|
log.warn(.console, "warn", .{ .args = try serializeValues(values, page) });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _error(values: []JsObject, page: *Page) !void {
|
pub fn _error(values: []js.JsObject, page: *Page) !void {
|
||||||
if (values.len == 0) {
|
if (values.len == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -132,7 +132,7 @@ pub const Console = struct {
|
|||||||
log.warn(.console, "timer stop", .{ .label = label, .elapsed = elapsed - kv.value });
|
log.warn(.console, "timer stop", .{ .label = label, .elapsed = elapsed - kv.value });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _assert(assertion: JsObject, values: []JsObject, page: *Page) !void {
|
pub fn _assert(assertion: js.JsObject, values: []js.JsObject, page: *Page) !void {
|
||||||
if (assertion.isTruthy()) {
|
if (assertion.isTruthy()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -143,7 +143,7 @@ pub const Console = struct {
|
|||||||
log.info(.console, "assertion failed", .{ .values = serialized_values });
|
log.info(.console, "assertion failed", .{ .values = serialized_values });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serializeValues(values: []JsObject, page: *Page) ![]const u8 {
|
fn serializeValues(values: []js.JsObject, page: *Page) ![]const u8 {
|
||||||
if (values.len == 0) {
|
if (values.len == 0) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,14 +17,14 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const Env = @import("../env.zig").Env;
|
const js = @import("../js/js.zig");
|
||||||
const uuidv4 = @import("../../id.zig").uuidv4;
|
const uuidv4 = @import("../../id.zig").uuidv4;
|
||||||
|
|
||||||
// https://w3c.github.io/webcrypto/#crypto-interface
|
// https://w3c.github.io/webcrypto/#crypto-interface
|
||||||
pub const Crypto = struct {
|
pub const Crypto = struct {
|
||||||
_not_empty: bool = true,
|
_not_empty: bool = true,
|
||||||
|
|
||||||
pub fn _getRandomValues(_: *const Crypto, js_obj: Env.JsObject) !Env.JsObject {
|
pub fn _getRandomValues(_: *const Crypto, js_obj: js.JsObject) !js.JsObject {
|
||||||
var into = try js_obj.toZig(Crypto, "getRandomValues", RandomValues);
|
var into = try js_obj.toZig(Crypto, "getRandomValues", RandomValues);
|
||||||
const buf = into.asBuffer();
|
const buf = into.asBuffer();
|
||||||
if (buf.len > 65_536) {
|
if (buf.len > 65_536) {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
const Env = @import("../env.zig").Env;
|
const js = @import("../js/js.zig");
|
||||||
const Page = @import("../page.zig").Page;
|
const Page = @import("../page.zig").Page;
|
||||||
const StyleSheet = @import("StyleSheet.zig");
|
const StyleSheet = @import("StyleSheet.zig");
|
||||||
const CSSRuleList = @import("CSSRuleList.zig");
|
const CSSRuleList = @import("CSSRuleList.zig");
|
||||||
@@ -73,7 +73,7 @@ pub fn _deleteRule(self: *CSSStyleSheet, index: usize) !void {
|
|||||||
_ = self.css_rules.list.orderedRemove(index);
|
_ = self.css_rules.list.orderedRemove(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _replace(self: *CSSStyleSheet, text: []const u8, page: *Page) !Env.Promise {
|
pub fn _replace(self: *CSSStyleSheet, text: []const u8, page: *Page) !js.Promise {
|
||||||
_ = self;
|
_ = self;
|
||||||
_ = text;
|
_ = text;
|
||||||
// TODO: clear self.css_rules
|
// TODO: clear self.css_rules
|
||||||
|
|||||||
@@ -18,19 +18,17 @@
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
|
const js = @import("../js/js.zig");
|
||||||
const Page = @import("../page.zig").Page;
|
const Page = @import("../page.zig").Page;
|
||||||
const JsObject = @import("../env.zig").JsObject;
|
|
||||||
const Promise = @import("../env.zig").Promise;
|
|
||||||
const PromiseResolver = @import("../env.zig").PromiseResolver;
|
|
||||||
|
|
||||||
const Animation = @This();
|
const Animation = @This();
|
||||||
|
|
||||||
effect: ?JsObject,
|
effect: ?js.JsObject,
|
||||||
timeline: ?JsObject,
|
timeline: ?js.JsObject,
|
||||||
ready_resolver: ?PromiseResolver,
|
ready_resolver: ?js.PromiseResolver,
|
||||||
finished_resolver: ?PromiseResolver,
|
finished_resolver: ?js.PromiseResolver,
|
||||||
|
|
||||||
pub fn constructor(effect: ?JsObject, timeline: ?JsObject) !Animation {
|
pub fn constructor(effect: ?js.JsObject, timeline: ?js.JsObject) !Animation {
|
||||||
return .{
|
return .{
|
||||||
.effect = if (effect) |eo| try eo.persist() else null,
|
.effect = if (effect) |eo| try eo.persist() else null,
|
||||||
.timeline = if (timeline) |to| try to.persist() else null,
|
.timeline = if (timeline) |to| try to.persist() else null,
|
||||||
@@ -49,7 +47,7 @@ pub fn get_pending(self: *const Animation) bool {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_finished(self: *Animation, page: *Page) !Promise {
|
pub fn get_finished(self: *Animation, page: *Page) !js.Promise {
|
||||||
if (self.finished_resolver == null) {
|
if (self.finished_resolver == null) {
|
||||||
const resolver = page.main_context.createPromiseResolver();
|
const resolver = page.main_context.createPromiseResolver();
|
||||||
try resolver.resolve(self);
|
try resolver.resolve(self);
|
||||||
@@ -58,7 +56,7 @@ pub fn get_finished(self: *Animation, page: *Page) !Promise {
|
|||||||
return self.finished_resolver.?.promise();
|
return self.finished_resolver.?.promise();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_ready(self: *Animation, page: *Page) !Promise {
|
pub fn get_ready(self: *Animation, page: *Page) !js.Promise {
|
||||||
// never resolved, because we're always "finished"
|
// never resolved, because we're always "finished"
|
||||||
if (self.ready_resolver == null) {
|
if (self.ready_resolver == null) {
|
||||||
const resolver = page.main_context.createPromiseResolver();
|
const resolver = page.main_context.createPromiseResolver();
|
||||||
@@ -67,19 +65,19 @@ pub fn get_ready(self: *Animation, page: *Page) !Promise {
|
|||||||
return self.ready_resolver.?.promise();
|
return self.ready_resolver.?.promise();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_effect(self: *const Animation) ?JsObject {
|
pub fn get_effect(self: *const Animation) ?js.JsObject {
|
||||||
return self.effect;
|
return self.effect;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_effect(self: *Animation, effect: JsObject) !void {
|
pub fn set_effect(self: *Animation, effect: js.JsObject) !void {
|
||||||
self.effect = try effect.persist();
|
self.effect = try effect.persist();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_timeline(self: *const Animation) ?JsObject {
|
pub fn get_timeline(self: *const Animation) ?js.JsObject {
|
||||||
return self.timeline;
|
return self.timeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_timeline(self: *Animation, timeline: JsObject) !void {
|
pub fn set_timeline(self: *Animation, timeline: js.JsObject) !void {
|
||||||
self.timeline = try timeline.persist();
|
self.timeline = try timeline.persist();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,13 +20,11 @@ const std = @import("std");
|
|||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
const parser = @import("../netsurf.zig");
|
const parser = @import("../netsurf.zig");
|
||||||
|
|
||||||
const Env = @import("../env.zig").Env;
|
const js = @import("../js/js.zig");
|
||||||
const Page = @import("../page.zig").Page;
|
const Page = @import("../page.zig").Page;
|
||||||
const EventTarget = @import("../dom/event_target.zig").EventTarget;
|
const EventTarget = @import("../dom/event_target.zig").EventTarget;
|
||||||
const EventHandler = @import("../events/event.zig").EventHandler;
|
const EventHandler = @import("../events/event.zig").EventHandler;
|
||||||
|
|
||||||
const JsObject = Env.JsObject;
|
|
||||||
const Function = Env.Function;
|
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
const MAX_QUEUE_SIZE = 10;
|
const MAX_QUEUE_SIZE = 10;
|
||||||
@@ -72,22 +70,22 @@ pub const MessagePort = struct {
|
|||||||
pair: *MessagePort,
|
pair: *MessagePort,
|
||||||
closed: bool = false,
|
closed: bool = false,
|
||||||
started: bool = false,
|
started: bool = false,
|
||||||
onmessage_cbk: ?Function = null,
|
onmessage_cbk: ?js.Function = null,
|
||||||
onmessageerror_cbk: ?Function = null,
|
onmessageerror_cbk: ?js.Function = null,
|
||||||
// This is the queue of messages to dispatch to THIS MessagePort when the
|
// This is the queue of messages to dispatch to THIS MessagePort when the
|
||||||
// MessagePort is started.
|
// MessagePort is started.
|
||||||
queue: std.ArrayListUnmanaged(JsObject) = .empty,
|
queue: std.ArrayListUnmanaged(js.JsObject) = .empty,
|
||||||
|
|
||||||
pub const PostMessageOption = union(enum) {
|
pub const PostMessageOption = union(enum) {
|
||||||
transfer: JsObject,
|
transfer: js.JsObject,
|
||||||
options: Opts,
|
options: Opts,
|
||||||
|
|
||||||
pub const Opts = struct {
|
pub const Opts = struct {
|
||||||
transfer: JsObject,
|
transfer: js.JsObject,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn _postMessage(self: *MessagePort, obj: JsObject, opts_: ?PostMessageOption, page: *Page) !void {
|
pub fn _postMessage(self: *MessagePort, obj: js.JsObject, opts_: ?PostMessageOption, page: *Page) !void {
|
||||||
if (self.closed) {
|
if (self.closed) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -124,10 +122,10 @@ pub const MessagePort = struct {
|
|||||||
self.pair.closed = true;
|
self.pair.closed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_onmessage(self: *MessagePort) ?Function {
|
pub fn get_onmessage(self: *MessagePort) ?js.Function {
|
||||||
return self.onmessage_cbk;
|
return self.onmessage_cbk;
|
||||||
}
|
}
|
||||||
pub fn get_onmessageerror(self: *MessagePort) ?Function {
|
pub fn get_onmessageerror(self: *MessagePort) ?js.Function {
|
||||||
return self.onmessageerror_cbk;
|
return self.onmessageerror_cbk;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,7 +150,7 @@ pub const MessagePort = struct {
|
|||||||
|
|
||||||
// called from our pair. If port1.postMessage("x") is called, then this
|
// called from our pair. If port1.postMessage("x") is called, then this
|
||||||
// will be called on port2.
|
// will be called on port2.
|
||||||
fn dispatchOrQueue(self: *MessagePort, obj: JsObject, arena: Allocator) !void {
|
fn dispatchOrQueue(self: *MessagePort, obj: js.JsObject, arena: Allocator) !void {
|
||||||
// our pair should have checked this already
|
// our pair should have checked this already
|
||||||
std.debug.assert(self.closed == false);
|
std.debug.assert(self.closed == false);
|
||||||
|
|
||||||
@@ -167,7 +165,7 @@ pub const MessagePort = struct {
|
|||||||
return self.queue.append(arena, try obj.persist());
|
return self.queue.append(arena, try obj.persist());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dispatch(self: *MessagePort, obj: JsObject) !void {
|
fn dispatch(self: *MessagePort, obj: js.JsObject) !void {
|
||||||
// obj is already persisted, don't use `MessageEvent.constructor`, but
|
// obj is already persisted, don't use `MessageEvent.constructor`, but
|
||||||
// go directly to `init`, which assumes persisted objects.
|
// go directly to `init`, which assumes persisted objects.
|
||||||
var evt = try MessageEvent.init(.{ .data = obj });
|
var evt = try MessageEvent.init(.{ .data = obj });
|
||||||
@@ -182,7 +180,7 @@ pub const MessagePort = struct {
|
|||||||
alloc: Allocator,
|
alloc: Allocator,
|
||||||
typ: []const u8,
|
typ: []const u8,
|
||||||
listener: EventHandler.Listener,
|
listener: EventHandler.Listener,
|
||||||
) !?Function {
|
) !?js.Function {
|
||||||
const target = @as(*parser.EventTarget, @ptrCast(self));
|
const target = @as(*parser.EventTarget, @ptrCast(self));
|
||||||
const eh = (try EventHandler.register(alloc, target, typ, listener, null)) orelse unreachable;
|
const eh = (try EventHandler.register(alloc, target, typ, listener, null)) orelse unreachable;
|
||||||
return eh.callback;
|
return eh.callback;
|
||||||
@@ -207,12 +205,12 @@ pub const MessageEvent = struct {
|
|||||||
pub const union_make_copy = true;
|
pub const union_make_copy = true;
|
||||||
|
|
||||||
proto: parser.Event,
|
proto: parser.Event,
|
||||||
data: ?JsObject,
|
data: ?js.JsObject,
|
||||||
|
|
||||||
// You would think if port1 sends to port2, the source would be port2
|
// You would think if port1 sends to port2, the source would be port2
|
||||||
// (which is how I read the documentation), but it appears to always be
|
// (which is how I read the documentation), but it appears to always be
|
||||||
// null. It can always be set explicitly via the constructor;
|
// null. It can always be set explicitly via the constructor;
|
||||||
source: ?JsObject,
|
source: ?js.JsObject,
|
||||||
|
|
||||||
origin: []const u8,
|
origin: []const u8,
|
||||||
|
|
||||||
@@ -226,8 +224,8 @@ pub const MessageEvent = struct {
|
|||||||
ports: []*MessagePort,
|
ports: []*MessagePort,
|
||||||
|
|
||||||
const Options = struct {
|
const Options = struct {
|
||||||
data: ?JsObject = null,
|
data: ?js.JsObject = null,
|
||||||
source: ?JsObject = null,
|
source: ?js.JsObject = null,
|
||||||
origin: []const u8 = "",
|
origin: []const u8 = "",
|
||||||
lastEventId: []const u8 = "",
|
lastEventId: []const u8 = "",
|
||||||
ports: []*MessagePort = &.{},
|
ports: []*MessagePort = &.{},
|
||||||
@@ -243,7 +241,7 @@ pub const MessageEvent = struct {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is like "constructor", but it assumes JsObjects have already been
|
// This is like "constructor", but it assumes js.JsObjects have already been
|
||||||
// persisted. Necessary because this `new MessageEvent()` can be called
|
// persisted. Necessary because this `new MessageEvent()` can be called
|
||||||
// directly from JS OR from a port.postMessage. In the latter case, data
|
// directly from JS OR from a port.postMessage. In the latter case, data
|
||||||
// may have already been persisted (as it might need to be queued);
|
// may have already been persisted (as it might need to be queued);
|
||||||
@@ -263,7 +261,7 @@ pub const MessageEvent = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_data(self: *const MessageEvent) !?JsObject {
|
pub fn get_data(self: *const MessageEvent) !?js.JsObject {
|
||||||
return self.data;
|
return self.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,7 +269,7 @@ pub const MessageEvent = struct {
|
|||||||
return self.origin;
|
return self.origin;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_source(self: *const MessageEvent) ?JsObject {
|
pub fn get_source(self: *const MessageEvent) ?js.JsObject {
|
||||||
return self.source;
|
return self.source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
|
const js = @import("../js/js.zig");
|
||||||
const parser = @import("../netsurf.zig");
|
const parser = @import("../netsurf.zig");
|
||||||
const Page = @import("../page.zig").Page;
|
const Page = @import("../page.zig").Page;
|
||||||
|
|
||||||
@@ -37,8 +38,6 @@ const Range = @import("range.zig").Range;
|
|||||||
|
|
||||||
const CustomEvent = @import("../events/custom_event.zig").CustomEvent;
|
const CustomEvent = @import("../events/custom_event.zig").CustomEvent;
|
||||||
|
|
||||||
const Env = @import("../env.zig").Env;
|
|
||||||
|
|
||||||
const DOMImplementation = @import("implementation.zig").DOMImplementation;
|
const DOMImplementation = @import("implementation.zig").DOMImplementation;
|
||||||
|
|
||||||
// WEB IDL https://dom.spec.whatwg.org/#document
|
// WEB IDL https://dom.spec.whatwg.org/#document
|
||||||
@@ -155,13 +154,13 @@ pub const Document = struct {
|
|||||||
// the spec changed to return an HTMLCollection instead.
|
// the spec changed to return an HTMLCollection instead.
|
||||||
// That's why we reimplemented getElementsByTagName by using an
|
// That's why we reimplemented getElementsByTagName by using an
|
||||||
// HTMLCollection in zig here.
|
// HTMLCollection in zig here.
|
||||||
pub fn _getElementsByTagName(self: *parser.Document, tag_name: Env.String) !collection.HTMLCollection {
|
pub fn _getElementsByTagName(self: *parser.Document, tag_name: js.String) !collection.HTMLCollection {
|
||||||
return collection.HTMLCollectionByTagName(parser.documentToNode(self), tag_name.string, .{
|
return collection.HTMLCollectionByTagName(parser.documentToNode(self), tag_name.string, .{
|
||||||
.include_root = true,
|
.include_root = true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _getElementsByClassName(self: *parser.Document, class_names: Env.String) !collection.HTMLCollection {
|
pub fn _getElementsByClassName(self: *parser.Document, class_names: js.String) !collection.HTMLCollection {
|
||||||
return collection.HTMLCollectionByClassName(parser.documentToNode(self), class_names.string, .{
|
return collection.HTMLCollectionByClassName(parser.documentToNode(self), class_names.string, .{
|
||||||
.include_root = true,
|
.include_root = true,
|
||||||
});
|
});
|
||||||
@@ -299,7 +298,7 @@ pub const Document = struct {
|
|||||||
return &.{};
|
return &.{};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_adoptedStyleSheets(self: *parser.Document, page: *Page) !Env.JsObject {
|
pub fn get_adoptedStyleSheets(self: *parser.Document, page: *Page) !js.JsObject {
|
||||||
const state = try page.getOrCreateNodeState(@ptrCast(@alignCast(self)));
|
const state = try page.getOrCreateNodeState(@ptrCast(@alignCast(self)));
|
||||||
if (state.adopted_style_sheets) |obj| {
|
if (state.adopted_style_sheets) |obj| {
|
||||||
return obj;
|
return obj;
|
||||||
@@ -310,7 +309,7 @@ pub const Document = struct {
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_adoptedStyleSheets(self: *parser.Document, sheets: Env.JsObject, page: *Page) !void {
|
pub fn set_adoptedStyleSheets(self: *parser.Document, sheets: js.JsObject, page: *Page) !void {
|
||||||
const state = try page.getOrCreateNodeState(@ptrCast(@alignCast(self)));
|
const state = try page.getOrCreateNodeState(@ptrCast(@alignCast(self)));
|
||||||
state.adopted_style_sheets = try sheets.persist();
|
state.adopted_style_sheets = try sheets.persist();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
|
const js = @import("../js/js.zig");
|
||||||
const parser = @import("../netsurf.zig");
|
const parser = @import("../netsurf.zig");
|
||||||
const Env = @import("../env.zig").Env;
|
|
||||||
const Page = @import("../page.zig").Page;
|
const Page = @import("../page.zig").Page;
|
||||||
|
|
||||||
const css = @import("css.zig");
|
const css = @import("css.zig");
|
||||||
@@ -34,7 +34,6 @@ const HTMLElem = @import("../html/elements.zig");
|
|||||||
const ShadowRoot = @import("../dom/shadow_root.zig").ShadowRoot;
|
const ShadowRoot = @import("../dom/shadow_root.zig").ShadowRoot;
|
||||||
|
|
||||||
const Animation = @import("Animation.zig");
|
const Animation = @import("Animation.zig");
|
||||||
const JsObject = @import("../env.zig").JsObject;
|
|
||||||
|
|
||||||
pub const Union = @import("../html/elements.zig").Union;
|
pub const Union = @import("../html/elements.zig").Union;
|
||||||
|
|
||||||
@@ -436,7 +435,7 @@ pub const Element = struct {
|
|||||||
return try parser.elementRemoveAttributeNode(self, attr);
|
return try parser.elementRemoveAttributeNode(self, attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _getElementsByTagName(self: *parser.Element, tag_name: Env.String) !collection.HTMLCollection {
|
pub fn _getElementsByTagName(self: *parser.Element, tag_name: js.String) !collection.HTMLCollection {
|
||||||
return collection.HTMLCollectionByTagName(
|
return collection.HTMLCollectionByTagName(
|
||||||
parser.elementToNode(self),
|
parser.elementToNode(self),
|
||||||
tag_name.string,
|
tag_name.string,
|
||||||
@@ -444,7 +443,7 @@ pub const Element = struct {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _getElementsByClassName(self: *parser.Element, class_names: Env.String) !collection.HTMLCollection {
|
pub fn _getElementsByClassName(self: *parser.Element, class_names: js.String) !collection.HTMLCollection {
|
||||||
return try collection.HTMLCollectionByClassName(
|
return try collection.HTMLCollectionByClassName(
|
||||||
parser.elementToNode(self),
|
parser.elementToNode(self),
|
||||||
class_names.string,
|
class_names.string,
|
||||||
@@ -661,7 +660,7 @@ pub const Element = struct {
|
|||||||
return sr;
|
return sr;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _animate(self: *parser.Element, effect: JsObject, opts: JsObject) !Animation {
|
pub fn _animate(self: *parser.Element, effect: js.JsObject, opts: js.JsObject) !Animation {
|
||||||
_ = self;
|
_ = self;
|
||||||
_ = opts;
|
_ = opts;
|
||||||
return Animation.constructor(effect, null);
|
return Animation.constructor(effect, null);
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ const parser = @import("../netsurf.zig");
|
|||||||
|
|
||||||
const Element = @import("element.zig").Element;
|
const Element = @import("element.zig").Element;
|
||||||
const Union = @import("element.zig").Union;
|
const Union = @import("element.zig").Union;
|
||||||
const JsThis = @import("../env.zig").JsThis;
|
|
||||||
const Walker = @import("walker.zig").Walker;
|
const Walker = @import("walker.zig").Walker;
|
||||||
|
|
||||||
const Matcher = union(enum) {
|
const Matcher = union(enum) {
|
||||||
|
|||||||
@@ -18,11 +18,11 @@
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
|
const js = @import("../js/js.zig");
|
||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
const parser = @import("../netsurf.zig");
|
const parser = @import("../netsurf.zig");
|
||||||
const Page = @import("../page.zig").Page;
|
const Page = @import("../page.zig").Page;
|
||||||
|
|
||||||
const Env = @import("../env.zig").Env;
|
|
||||||
const Element = @import("element.zig").Element;
|
const Element = @import("element.zig").Element;
|
||||||
|
|
||||||
pub const Interfaces = .{
|
pub const Interfaces = .{
|
||||||
@@ -40,14 +40,14 @@ pub const Interfaces = .{
|
|||||||
// https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver
|
// https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver
|
||||||
pub const IntersectionObserver = struct {
|
pub const IntersectionObserver = struct {
|
||||||
page: *Page,
|
page: *Page,
|
||||||
callback: Env.Function,
|
callback: js.Function,
|
||||||
options: IntersectionObserverOptions,
|
options: IntersectionObserverOptions,
|
||||||
|
|
||||||
observed_entries: std.ArrayListUnmanaged(IntersectionObserverEntry),
|
observed_entries: std.ArrayListUnmanaged(IntersectionObserverEntry),
|
||||||
|
|
||||||
// new IntersectionObserver(callback)
|
// new IntersectionObserver(callback)
|
||||||
// new IntersectionObserver(callback, options) [not supported yet]
|
// new IntersectionObserver(callback, options) [not supported yet]
|
||||||
pub fn constructor(callback: Env.Function, options_: ?IntersectionObserverOptions, page: *Page) !IntersectionObserver {
|
pub fn constructor(callback: js.Function, options_: ?IntersectionObserverOptions, page: *Page) !IntersectionObserver {
|
||||||
var options = IntersectionObserverOptions{
|
var options = IntersectionObserverOptions{
|
||||||
.root = parser.documentToNode(parser.documentHTMLToDocument(page.window.document)),
|
.root = parser.documentToNode(parser.documentHTMLToDocument(page.window.document)),
|
||||||
.rootMargin = "0px 0px 0px 0px",
|
.rootMargin = "0px 0px 0px 0px",
|
||||||
@@ -84,7 +84,7 @@ pub const IntersectionObserver = struct {
|
|||||||
.options = &self.options,
|
.options = &self.options,
|
||||||
});
|
});
|
||||||
|
|
||||||
var result: Env.Function.Result = undefined;
|
var result: js.Function.Result = undefined;
|
||||||
self.callback.tryCall(void, .{self.observed_entries.items}, &result) catch {
|
self.callback.tryCall(void, .{self.observed_entries.items}, &result) catch {
|
||||||
log.debug(.user_script, "callback error", .{
|
log.debug(.user_script, "callback error", .{
|
||||||
.err = result.exception,
|
.err = result.exception,
|
||||||
|
|||||||
@@ -18,11 +18,11 @@
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
|
const js = @import("../js/js.zig");
|
||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
const parser = @import("../netsurf.zig");
|
const parser = @import("../netsurf.zig");
|
||||||
const Page = @import("../page.zig").Page;
|
const Page = @import("../page.zig").Page;
|
||||||
|
|
||||||
const Env = @import("../env.zig").Env;
|
|
||||||
const NodeList = @import("nodelist.zig").NodeList;
|
const NodeList = @import("nodelist.zig").NodeList;
|
||||||
|
|
||||||
pub const Interfaces = .{
|
pub const Interfaces = .{
|
||||||
@@ -35,7 +35,7 @@ const Walker = @import("../dom/walker.zig").WalkerChildren;
|
|||||||
// WEB IDL https://dom.spec.whatwg.org/#interface-mutationobserver
|
// WEB IDL https://dom.spec.whatwg.org/#interface-mutationobserver
|
||||||
pub const MutationObserver = struct {
|
pub const MutationObserver = struct {
|
||||||
page: *Page,
|
page: *Page,
|
||||||
cbk: Env.Function,
|
cbk: js.Function,
|
||||||
scheduled: bool,
|
scheduled: bool,
|
||||||
observers: std.ArrayListUnmanaged(*Observer),
|
observers: std.ArrayListUnmanaged(*Observer),
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ pub const MutationObserver = struct {
|
|||||||
// execute our callback with it.
|
// execute our callback with it.
|
||||||
observed: std.ArrayListUnmanaged(MutationRecord),
|
observed: std.ArrayListUnmanaged(MutationRecord),
|
||||||
|
|
||||||
pub fn constructor(cbk: Env.Function, page: *Page) !MutationObserver {
|
pub fn constructor(cbk: js.Function, page: *Page) !MutationObserver {
|
||||||
return .{
|
return .{
|
||||||
.cbk = cbk,
|
.cbk = cbk,
|
||||||
.page = page,
|
.page = page,
|
||||||
@@ -122,7 +122,7 @@ pub const MutationObserver = struct {
|
|||||||
|
|
||||||
defer self.observed.clearRetainingCapacity();
|
defer self.observed.clearRetainingCapacity();
|
||||||
|
|
||||||
var result: Env.Function.Result = undefined;
|
var result: js.Function.Result = undefined;
|
||||||
self.cbk.tryCallWithThis(void, self, .{records}, &result) catch {
|
self.cbk.tryCallWithThis(void, self, .{records}, &result) catch {
|
||||||
log.debug(.user_script, "callback error", .{
|
log.debug(.user_script, "callback error", .{
|
||||||
.err = result.exception,
|
.err = result.exception,
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ const std = @import("std");
|
|||||||
|
|
||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
const parser = @import("../netsurf.zig");
|
const parser = @import("../netsurf.zig");
|
||||||
const generate = @import("../../runtime/generate.zig");
|
const generate = @import("../js/generate.zig");
|
||||||
|
|
||||||
const Page = @import("../page.zig").Page;
|
const Page = @import("../page.zig").Page;
|
||||||
const EventTarget = @import("event_target.zig").EventTarget;
|
const EventTarget = @import("event_target.zig").EventTarget;
|
||||||
|
|||||||
@@ -17,8 +17,8 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const js = @import("../js/js.zig");
|
||||||
const parser = @import("../netsurf.zig");
|
const parser = @import("../netsurf.zig");
|
||||||
const Env = @import("../env.zig").Env;
|
|
||||||
const Node = @import("node.zig").Node;
|
const Node = @import("node.zig").Node;
|
||||||
|
|
||||||
pub const NodeFilter = struct {
|
pub const NodeFilter = struct {
|
||||||
@@ -43,7 +43,7 @@ pub const NodeFilter = struct {
|
|||||||
|
|
||||||
const VerifyResult = enum { accept, skip, reject };
|
const VerifyResult = enum { accept, skip, reject };
|
||||||
|
|
||||||
pub fn verify(what_to_show: u32, filter: ?Env.Function, node: *parser.Node) !VerifyResult {
|
pub fn verify(what_to_show: u32, filter: ?js.Function, node: *parser.Node) !VerifyResult {
|
||||||
const node_type = parser.nodeType(node);
|
const node_type = parser.nodeType(node);
|
||||||
|
|
||||||
// Verify that we can show this node type.
|
// Verify that we can show this node type.
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
|
const js = @import("../js/js.zig");
|
||||||
const parser = @import("../netsurf.zig");
|
const parser = @import("../netsurf.zig");
|
||||||
const Env = @import("../env.zig").Env;
|
|
||||||
const NodeFilter = @import("node_filter.zig");
|
const NodeFilter = @import("node_filter.zig");
|
||||||
const Node = @import("node.zig").Node;
|
const Node = @import("node.zig").Node;
|
||||||
const NodeUnion = @import("node.zig").Union;
|
const NodeUnion = @import("node.zig").Union;
|
||||||
@@ -37,7 +37,7 @@ pub const NodeIterator = struct {
|
|||||||
reference_node: *parser.Node,
|
reference_node: *parser.Node,
|
||||||
what_to_show: u32,
|
what_to_show: u32,
|
||||||
filter: ?NodeIteratorOpts,
|
filter: ?NodeIteratorOpts,
|
||||||
filter_func: ?Env.Function,
|
filter_func: ?js.Function,
|
||||||
pointer_before_current: bool = true,
|
pointer_before_current: bool = true,
|
||||||
// used to track / block recursive filters
|
// used to track / block recursive filters
|
||||||
is_in_callback: bool = false,
|
is_in_callback: bool = false,
|
||||||
@@ -45,15 +45,15 @@ pub const NodeIterator = struct {
|
|||||||
// One of the few cases where null and undefined resolve to different default.
|
// One of the few cases where null and undefined resolve to different default.
|
||||||
// We need the raw JsObject so that we can probe the tri state:
|
// We need the raw JsObject so that we can probe the tri state:
|
||||||
// null, undefined or i32.
|
// null, undefined or i32.
|
||||||
pub const WhatToShow = Env.JsObject;
|
pub const WhatToShow = js.JsObject;
|
||||||
|
|
||||||
pub const NodeIteratorOpts = union(enum) {
|
pub const NodeIteratorOpts = union(enum) {
|
||||||
function: Env.Function,
|
function: js.Function,
|
||||||
object: struct { acceptNode: Env.Function },
|
object: struct { acceptNode: js.Function },
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn init(node: *parser.Node, what_to_show_: ?WhatToShow, filter: ?NodeIteratorOpts) !NodeIterator {
|
pub fn init(node: *parser.Node, what_to_show_: ?WhatToShow, filter: ?NodeIteratorOpts) !NodeIterator {
|
||||||
var filter_func: ?Env.Function = null;
|
var filter_func: ?js.Function = null;
|
||||||
if (filter) |f| {
|
if (filter) |f| {
|
||||||
filter_func = switch (f) {
|
filter_func = switch (f) {
|
||||||
.function => |func| func,
|
.function => |func| func,
|
||||||
|
|||||||
@@ -19,11 +19,10 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
|
const js = @import("../js/js.zig");
|
||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
const parser = @import("../netsurf.zig");
|
const parser = @import("../netsurf.zig");
|
||||||
|
|
||||||
const JsThis = @import("../env.zig").JsThis;
|
|
||||||
const Function = @import("../env.zig").Function;
|
|
||||||
|
|
||||||
const NodeUnion = @import("node.zig").Union;
|
const NodeUnion = @import("node.zig").Union;
|
||||||
const Node = @import("node.zig").Node;
|
const Node = @import("node.zig").Node;
|
||||||
@@ -148,10 +147,10 @@ pub const NodeList = struct {
|
|||||||
// };
|
// };
|
||||||
// }
|
// }
|
||||||
|
|
||||||
pub fn _forEach(self: *NodeList, cbk: Function) !void { // TODO handle thisArg
|
pub fn _forEach(self: *NodeList, cbk: js.Function) !void { // TODO handle thisArg
|
||||||
for (self.nodes.items, 0..) |n, i| {
|
for (self.nodes.items, 0..) |n, i| {
|
||||||
const ii: u32 = @intCast(i);
|
const ii: u32 = @intCast(i);
|
||||||
var result: Function.Result = undefined;
|
var result: js.Function.Result = undefined;
|
||||||
cbk.tryCall(void, .{ n, ii, self }, &result) catch {
|
cbk.tryCall(void, .{ n, ii, self }, &result) catch {
|
||||||
log.debug(.user_script, "forEach callback", .{ .err = result.exception, .stack = result.stack });
|
log.debug(.user_script, "forEach callback", .{ .err = result.exception, .stack = result.stack });
|
||||||
};
|
};
|
||||||
@@ -175,7 +174,7 @@ pub const NodeList = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO entries() https://developer.mozilla.org/en-US/docs/Web/API/NodeList/entries
|
// TODO entries() https://developer.mozilla.org/en-US/docs/Web/API/NodeList/entries
|
||||||
pub fn postAttach(self: *NodeList, js_this: JsThis) !void {
|
pub fn postAttach(self: *NodeList, js_this: js.JsThis) !void {
|
||||||
const len = self.get_length();
|
const len = self.get_length();
|
||||||
for (0..len) |i| {
|
for (0..len) |i| {
|
||||||
const node = try self._item(@intCast(i)) orelse unreachable;
|
const node = try self._item(@intCast(i)) orelse unreachable;
|
||||||
|
|||||||
@@ -18,9 +18,9 @@
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
|
const js = @import("../js/js.zig");
|
||||||
const parser = @import("../netsurf.zig");
|
const parser = @import("../netsurf.zig");
|
||||||
const EventTarget = @import("../dom/event_target.zig").EventTarget;
|
const EventTarget = @import("../dom/event_target.zig").EventTarget;
|
||||||
const Env = @import("../env.zig").Env;
|
|
||||||
const Page = @import("../page.zig").Page;
|
const Page = @import("../page.zig").Page;
|
||||||
|
|
||||||
const milliTimestamp = @import("../../datetime.zig").milliTimestamp;
|
const milliTimestamp = @import("../../datetime.zig").milliTimestamp;
|
||||||
@@ -61,7 +61,7 @@ pub const Performance = struct {
|
|||||||
return milliTimestamp() - self.time_origin;
|
return milliTimestamp() - self.time_origin;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _mark(_: *Performance, name: Env.String, _options: ?PerformanceMark.Options, page: *Page) !PerformanceMark {
|
pub fn _mark(_: *Performance, name: js.String, _options: ?PerformanceMark.Options, page: *Page) !PerformanceMark {
|
||||||
const mark: PerformanceMark = try .constructor(name, _options, page);
|
const mark: PerformanceMark = try .constructor(name, _options, page);
|
||||||
// TODO: Should store this in an entries list
|
// TODO: Should store this in an entries list
|
||||||
return mark;
|
return mark;
|
||||||
@@ -148,14 +148,14 @@ pub const PerformanceMark = struct {
|
|||||||
pub const prototype = *PerformanceEntry;
|
pub const prototype = *PerformanceEntry;
|
||||||
|
|
||||||
proto: PerformanceEntry,
|
proto: PerformanceEntry,
|
||||||
detail: ?Env.JsObject,
|
detail: ?js.JsObject,
|
||||||
|
|
||||||
const Options = struct {
|
const Options = struct {
|
||||||
detail: ?Env.JsObject = null,
|
detail: ?js.JsObject = null,
|
||||||
startTime: ?f64 = null,
|
startTime: ?f64 = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn constructor(name: Env.String, _options: ?Options, page: *Page) !PerformanceMark {
|
pub fn constructor(name: js.String, _options: ?Options, page: *Page) !PerformanceMark {
|
||||||
const perf = &page.window.performance;
|
const perf = &page.window.performance;
|
||||||
|
|
||||||
const options = _options orelse Options{};
|
const options = _options orelse Options{};
|
||||||
@@ -171,7 +171,7 @@ pub const PerformanceMark = struct {
|
|||||||
return .{ .proto = proto, .detail = detail };
|
return .{ .proto = proto, .detail = detail };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_detail(self: *const PerformanceMark) ?Env.JsObject {
|
pub fn get_detail(self: *const PerformanceMark) ?js.JsObject {
|
||||||
return self.detail;
|
return self.detail;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const Env = @import("../env.zig").Env;
|
const js = @import("../js/js.zig");
|
||||||
|
|
||||||
const PerformanceEntry = @import("performance.zig").PerformanceEntry;
|
const PerformanceEntry = @import("performance.zig").PerformanceEntry;
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ const PerformanceEntry = @import("performance.zig").PerformanceEntry;
|
|||||||
pub const PerformanceObserver = struct {
|
pub const PerformanceObserver = struct {
|
||||||
pub const _supportedEntryTypes = [0][]const u8{};
|
pub const _supportedEntryTypes = [0][]const u8{};
|
||||||
|
|
||||||
pub fn constructor(cbk: Env.Function) PerformanceObserver {
|
pub fn constructor(cbk: js.Function) PerformanceObserver {
|
||||||
_ = cbk;
|
_ = cbk;
|
||||||
return .{};
|
return .{};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
const Env = @import("../env.zig").Env;
|
const js = @import("../js/js.zig");
|
||||||
const parser = @import("../netsurf.zig");
|
const parser = @import("../netsurf.zig");
|
||||||
|
|
||||||
pub const Interfaces = .{
|
pub const Interfaces = .{
|
||||||
@@ -25,7 +25,7 @@ pub const Interfaces = .{
|
|||||||
|
|
||||||
// WEB IDL https://drafts.csswg.org/resize-observer/#resize-observer-interface
|
// WEB IDL https://drafts.csswg.org/resize-observer/#resize-observer-interface
|
||||||
pub const ResizeObserver = struct {
|
pub const ResizeObserver = struct {
|
||||||
pub fn constructor(cbk: Env.Function) ResizeObserver {
|
pub fn constructor(cbk: js.Function) ResizeObserver {
|
||||||
_ = cbk;
|
_ = cbk;
|
||||||
return .{};
|
return .{};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ const std = @import("std");
|
|||||||
const dump = @import("../dump.zig");
|
const dump = @import("../dump.zig");
|
||||||
const parser = @import("../netsurf.zig");
|
const parser = @import("../netsurf.zig");
|
||||||
|
|
||||||
const Env = @import("../env.zig").Env;
|
const js = @import(".././js/js.zig");
|
||||||
const Page = @import("../page.zig").Page;
|
const Page = @import("../page.zig").Page;
|
||||||
const Node = @import("node.zig").Node;
|
const Node = @import("node.zig").Node;
|
||||||
const Element = @import("element.zig").Element;
|
const Element = @import("element.zig").Element;
|
||||||
@@ -34,7 +34,7 @@ pub const ShadowRoot = struct {
|
|||||||
mode: Mode,
|
mode: Mode,
|
||||||
host: *parser.Element,
|
host: *parser.Element,
|
||||||
proto: *parser.DocumentFragment,
|
proto: *parser.DocumentFragment,
|
||||||
adopted_style_sheets: ?Env.JsObject = null,
|
adopted_style_sheets: ?js.JsObject = null,
|
||||||
|
|
||||||
pub const Mode = enum {
|
pub const Mode = enum {
|
||||||
open,
|
open,
|
||||||
@@ -45,7 +45,7 @@ pub const ShadowRoot = struct {
|
|||||||
return Element.toInterface(self.host);
|
return Element.toInterface(self.host);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_adoptedStyleSheets(self: *ShadowRoot, page: *Page) !Env.JsObject {
|
pub fn get_adoptedStyleSheets(self: *ShadowRoot, page: *Page) !js.JsObject {
|
||||||
if (self.adopted_style_sheets) |obj| {
|
if (self.adopted_style_sheets) |obj| {
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
@@ -55,7 +55,7 @@ pub const ShadowRoot = struct {
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_adoptedStyleSheets(self: *ShadowRoot, sheets: Env.JsObject) !void {
|
pub fn set_adoptedStyleSheets(self: *ShadowRoot, sheets: js.JsObject) !void {
|
||||||
self.adopted_style_sheets = try sheets.persist();
|
self.adopted_style_sheets = try sheets.persist();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,12 +18,11 @@
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
|
const js = @import("../js/js.zig");
|
||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
const parser = @import("../netsurf.zig");
|
const parser = @import("../netsurf.zig");
|
||||||
const iterator = @import("../iterator/iterator.zig");
|
const iterator = @import("../iterator/iterator.zig");
|
||||||
|
|
||||||
const Function = @import("../env.zig").Function;
|
|
||||||
const JsObject = @import("../env.zig").JsObject;
|
|
||||||
const DOMException = @import("exceptions.zig").DOMException;
|
const DOMException = @import("exceptions.zig").DOMException;
|
||||||
|
|
||||||
pub const Interfaces = .{
|
pub const Interfaces = .{
|
||||||
@@ -137,10 +136,10 @@ pub const DOMTokenList = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO handle thisArg
|
// TODO handle thisArg
|
||||||
pub fn _forEach(self: *parser.TokenList, cbk: Function, this_arg: JsObject) !void {
|
pub fn _forEach(self: *parser.TokenList, cbk: js.Function, this_arg: js.JsObject) !void {
|
||||||
var entries = _entries(self);
|
var entries = _entries(self);
|
||||||
while (try entries._next()) |entry| {
|
while (try entries._next()) |entry| {
|
||||||
var result: Function.Result = undefined;
|
var result: js.Function.Result = undefined;
|
||||||
cbk.tryCallWithThis(void, this_arg, .{ entry.@"1", entry.@"0", self }, &result) catch {
|
cbk.tryCallWithThis(void, this_arg, .{ entry.@"1", entry.@"0", self }, &result) catch {
|
||||||
log.debug(.user_script, "callback error", .{
|
log.debug(.user_script, "callback error", .{
|
||||||
.err = result.exception,
|
.err = result.exception,
|
||||||
|
|||||||
@@ -17,10 +17,10 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const js = @import("../js/js.zig");
|
||||||
const parser = @import("../netsurf.zig");
|
const parser = @import("../netsurf.zig");
|
||||||
|
|
||||||
const NodeFilter = @import("node_filter.zig");
|
const NodeFilter = @import("node_filter.zig");
|
||||||
const Env = @import("../env.zig").Env;
|
|
||||||
const Node = @import("node.zig").Node;
|
const Node = @import("node.zig").Node;
|
||||||
const NodeUnion = @import("node.zig").Union;
|
const NodeUnion = @import("node.zig").Union;
|
||||||
|
|
||||||
@@ -30,20 +30,20 @@ pub const TreeWalker = struct {
|
|||||||
current_node: *parser.Node,
|
current_node: *parser.Node,
|
||||||
what_to_show: u32,
|
what_to_show: u32,
|
||||||
filter: ?TreeWalkerOpts,
|
filter: ?TreeWalkerOpts,
|
||||||
filter_func: ?Env.Function,
|
filter_func: ?js.Function,
|
||||||
|
|
||||||
// One of the few cases where null and undefined resolve to different default.
|
// One of the few cases where null and undefined resolve to different default.
|
||||||
// We need the raw JsObject so that we can probe the tri state:
|
// We need the raw JsObject so that we can probe the tri state:
|
||||||
// null, undefined or i32.
|
// null, undefined or i32.
|
||||||
pub const WhatToShow = Env.JsObject;
|
pub const WhatToShow = js.JsObject;
|
||||||
|
|
||||||
pub const TreeWalkerOpts = union(enum) {
|
pub const TreeWalkerOpts = union(enum) {
|
||||||
function: Env.Function,
|
function: js.Function,
|
||||||
object: struct { acceptNode: Env.Function },
|
object: struct { acceptNode: js.Function },
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn init(node: *parser.Node, what_to_show_: ?WhatToShow, filter: ?TreeWalkerOpts) !TreeWalker {
|
pub fn init(node: *parser.Node, what_to_show_: ?WhatToShow, filter: ?TreeWalkerOpts) !TreeWalker {
|
||||||
var filter_func: ?Env.Function = null;
|
var filter_func: ?js.Function = null;
|
||||||
|
|
||||||
if (filter) |f| {
|
if (filter) |f| {
|
||||||
filter_func = switch (f) {
|
filter_func = switch (f) {
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
|
|
||||||
const Env = @import("../env.zig").Env;
|
|
||||||
const Page = @import("../page.zig").Page;
|
const Page = @import("../page.zig").Page;
|
||||||
|
|
||||||
// https://encoding.spec.whatwg.org/#interface-textdecoder
|
// https://encoding.spec.whatwg.org/#interface-textdecoder
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
const Env = @import("../env.zig").Env;
|
const js = @import("../js/js.zig");
|
||||||
|
|
||||||
// https://encoding.spec.whatwg.org/#interface-textencoder
|
// https://encoding.spec.whatwg.org/#interface-textencoder
|
||||||
const TextEncoder = @This();
|
const TextEncoder = @This();
|
||||||
@@ -31,7 +31,7 @@ pub fn get_encoding(_: *const TextEncoder) []const u8 {
|
|||||||
return "utf-8";
|
return "utf-8";
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _encode(_: *const TextEncoder, v: []const u8) !Env.TypedArray(u8) {
|
pub fn _encode(_: *const TextEncoder, v: []const u8) !js.TypedArray(u8) {
|
||||||
// Ensure the input is a valid utf-8
|
// Ensure the input is a valid utf-8
|
||||||
// It seems chrome accepts invalid utf-8 sequence.
|
// It seems chrome accepts invalid utf-8 sequence.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
|
|
||||||
const Page = @import("page.zig").Page;
|
|
||||||
const js = @import("../runtime/js.zig");
|
|
||||||
const generate = @import("../runtime/generate.zig");
|
|
||||||
|
|
||||||
const WebApis = struct {
|
|
||||||
// Wrapped like this for debug ergonomics.
|
|
||||||
// When we create our Env, a few lines down, we define it as:
|
|
||||||
// pub const Env = js.Env(*Page, WebApis);
|
|
||||||
//
|
|
||||||
// If there's a compile time error witht he Env, it's type will be readable,
|
|
||||||
// i.e.: runtime.js.Env(*browser.env.Page, browser.env.WebApis)
|
|
||||||
//
|
|
||||||
// But if we didn't wrap it in the struct, like we once didn't, and defined
|
|
||||||
// env as:
|
|
||||||
// pub const Env = js.Env(*Page, Interfaces);
|
|
||||||
//
|
|
||||||
// Because Interfaces is an anynoumous type, it doesn't have a friendly name
|
|
||||||
// and errors would be something like:
|
|
||||||
// runtime.js.Env(*browser.Page, .{...A HUNDRED TYPES...})
|
|
||||||
pub const Interfaces = generate.Tuple(.{
|
|
||||||
@import("crypto/crypto.zig").Crypto,
|
|
||||||
@import("console/console.zig").Console,
|
|
||||||
@import("css/css.zig").Interfaces,
|
|
||||||
@import("cssom/cssom.zig").Interfaces,
|
|
||||||
@import("dom/dom.zig").Interfaces,
|
|
||||||
@import("dom/shadow_root.zig").ShadowRoot,
|
|
||||||
@import("encoding/encoding.zig").Interfaces,
|
|
||||||
@import("events/event.zig").Interfaces,
|
|
||||||
@import("html/html.zig").Interfaces,
|
|
||||||
@import("iterator/iterator.zig").Interfaces,
|
|
||||||
@import("storage/storage.zig").Interfaces,
|
|
||||||
@import("url/url.zig").Interfaces,
|
|
||||||
@import("xhr/xhr.zig").Interfaces,
|
|
||||||
@import("xhr/form_data.zig").Interfaces,
|
|
||||||
@import("xhr/File.zig"),
|
|
||||||
@import("xmlserializer/xmlserializer.zig").Interfaces,
|
|
||||||
@import("fetch/fetch.zig").Interfaces,
|
|
||||||
@import("streams/streams.zig").Interfaces,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const JsThis = Env.JsThis;
|
|
||||||
pub const JsObject = Env.JsObject;
|
|
||||||
pub const Function = Env.Function;
|
|
||||||
pub const Promise = Env.Promise;
|
|
||||||
pub const PromiseResolver = Env.PromiseResolver;
|
|
||||||
|
|
||||||
pub const Env = js.Env(*Page, WebApis);
|
|
||||||
pub const Global = @import("html/window.zig").Window;
|
|
||||||
@@ -16,9 +16,10 @@
|
|||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
const js = @import("../js/js.zig");
|
||||||
const parser = @import("../netsurf.zig");
|
const parser = @import("../netsurf.zig");
|
||||||
const Event = @import("event.zig").Event;
|
const Event = @import("event.zig").Event;
|
||||||
const JsObject = @import("../env.zig").JsObject;
|
|
||||||
const netsurf = @import("../netsurf.zig");
|
const netsurf = @import("../netsurf.zig");
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#interface-customevent
|
// https://dom.spec.whatwg.org/#interface-customevent
|
||||||
@@ -27,13 +28,13 @@ pub const CustomEvent = struct {
|
|||||||
pub const union_make_copy = true;
|
pub const union_make_copy = true;
|
||||||
|
|
||||||
proto: parser.Event,
|
proto: parser.Event,
|
||||||
detail: ?JsObject,
|
detail: ?js.JsObject,
|
||||||
|
|
||||||
const CustomEventInit = struct {
|
const CustomEventInit = struct {
|
||||||
bubbles: bool = false,
|
bubbles: bool = false,
|
||||||
cancelable: bool = false,
|
cancelable: bool = false,
|
||||||
composed: bool = false,
|
composed: bool = false,
|
||||||
detail: ?JsObject = null,
|
detail: ?js.JsObject = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn constructor(event_type: []const u8, opts_: ?CustomEventInit) !CustomEvent {
|
pub fn constructor(event_type: []const u8, opts_: ?CustomEventInit) !CustomEvent {
|
||||||
@@ -53,7 +54,7 @@ pub const CustomEvent = struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_detail(self: *CustomEvent) ?JsObject {
|
pub fn get_detail(self: *CustomEvent) ?js.JsObject {
|
||||||
return self.detail;
|
return self.detail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +65,7 @@ pub const CustomEvent = struct {
|
|||||||
event_type: []const u8,
|
event_type: []const u8,
|
||||||
can_bubble: bool,
|
can_bubble: bool,
|
||||||
cancelable: bool,
|
cancelable: bool,
|
||||||
maybe_detail: ?JsObject,
|
maybe_detail: ?js.JsObject,
|
||||||
) !void {
|
) !void {
|
||||||
// This function can only be called after the constructor has called.
|
// This function can only be called after the constructor has called.
|
||||||
// So we assume proto is initialized already by constructor.
|
// So we assume proto is initialized already by constructor.
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ const Allocator = std.mem.Allocator;
|
|||||||
|
|
||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
const parser = @import("../netsurf.zig");
|
const parser = @import("../netsurf.zig");
|
||||||
const generate = @import("../../runtime/generate.zig");
|
const generate = @import("../js/generate.zig");
|
||||||
|
|
||||||
const Page = @import("../page.zig").Page;
|
const Page = @import("../page.zig").Page;
|
||||||
const Node = @import("../dom/node.zig").Node;
|
const Node = @import("../dom/node.zig").Node;
|
||||||
@@ -219,18 +219,17 @@ pub const Event = struct {
|
|||||||
pub const EventHandler = struct {
|
pub const EventHandler = struct {
|
||||||
once: bool,
|
once: bool,
|
||||||
capture: bool,
|
capture: bool,
|
||||||
callback: Function,
|
callback: js.Function,
|
||||||
node: parser.EventNode,
|
node: parser.EventNode,
|
||||||
listener: *parser.EventListener,
|
listener: *parser.EventListener,
|
||||||
|
|
||||||
const Env = @import("../env.zig").Env;
|
const js = @import("../js/js.zig");
|
||||||
const Function = Env.Function;
|
|
||||||
|
|
||||||
pub const Listener = union(enum) {
|
pub const Listener = union(enum) {
|
||||||
function: Function,
|
function: js.Function,
|
||||||
object: Env.JsObject,
|
object: js.JsObject,
|
||||||
|
|
||||||
pub fn callback(self: Listener, target: *parser.EventTarget) !?Function {
|
pub fn callback(self: Listener, target: *parser.EventTarget) !?js.Function {
|
||||||
return switch (self) {
|
return switch (self) {
|
||||||
.function => |func| try func.withThis(target),
|
.function => |func| try func.withThis(target),
|
||||||
.object => |obj| blk: {
|
.object => |obj| blk: {
|
||||||
@@ -331,7 +330,7 @@ pub const EventHandler = struct {
|
|||||||
fn handle(node: *parser.EventNode, event: *parser.Event) void {
|
fn handle(node: *parser.EventNode, event: *parser.Event) void {
|
||||||
const ievent = Event.toInterface(event);
|
const ievent = Event.toInterface(event);
|
||||||
const self: *EventHandler = @fieldParentPtr("node", node);
|
const self: *EventHandler = @fieldParentPtr("node", node);
|
||||||
var result: Function.Result = undefined;
|
var result: js.Function.Result = undefined;
|
||||||
self.callback.tryCall(void, .{ievent}, &result) catch {
|
self.callback.tryCall(void, .{ievent}, &result) catch {
|
||||||
log.debug(.user_script, "callback error", .{
|
log.debug(.user_script, "callback error", .{
|
||||||
.err = result.exception,
|
.err = result.exception,
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const js = @import("../js/js.zig");
|
||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
const URL = @import("../../url.zig").URL;
|
const URL = @import("../../url.zig").URL;
|
||||||
const Page = @import("../page.zig").Page;
|
const Page = @import("../page.zig").Page;
|
||||||
@@ -24,8 +25,6 @@ const Page = @import("../page.zig").Page;
|
|||||||
const iterator = @import("../iterator/iterator.zig");
|
const iterator = @import("../iterator/iterator.zig");
|
||||||
|
|
||||||
const v8 = @import("v8");
|
const v8 = @import("v8");
|
||||||
const Env = @import("../env.zig").Env;
|
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/Headers
|
// https://developer.mozilla.org/en-US/docs/Web/API/Headers
|
||||||
const Headers = @This();
|
const Headers = @This();
|
||||||
|
|
||||||
@@ -69,7 +68,7 @@ pub const HeadersInit = union(enum) {
|
|||||||
// Headers
|
// Headers
|
||||||
headers: *Headers,
|
headers: *Headers,
|
||||||
// Mappings
|
// Mappings
|
||||||
object: Env.JsObject,
|
object: js.JsObject,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn constructor(_init: ?HeadersInit, page: *Page) !Headers {
|
pub fn constructor(_init: ?HeadersInit, page: *Page) !Headers {
|
||||||
@@ -159,7 +158,7 @@ pub fn _entries(self: *const Headers) HeadersEntryIterable {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _forEach(self: *Headers, callback_fn: Env.Function, this_arg: ?Env.JsObject) !void {
|
pub fn _forEach(self: *Headers, callback_fn: js.Function, this_arg: ?js.JsObject) !void {
|
||||||
var iter = self.headers.iterator();
|
var iter = self.headers.iterator();
|
||||||
|
|
||||||
const cb = if (this_arg) |this| try callback_fn.withThis(this) else callback_fn;
|
const cb = if (this_arg) |this| try callback_fn.withThis(this) else callback_fn;
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const js = @import("../js/js.zig");
|
||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
|
|
||||||
const URL = @import("../../url.zig").URL;
|
const URL = @import("../../url.zig").URL;
|
||||||
@@ -27,7 +28,6 @@ const Http = @import("../../http/Http.zig");
|
|||||||
const ReadableStream = @import("../streams/ReadableStream.zig");
|
const ReadableStream = @import("../streams/ReadableStream.zig");
|
||||||
|
|
||||||
const v8 = @import("v8");
|
const v8 = @import("v8");
|
||||||
const Env = @import("../env.zig").Env;
|
|
||||||
|
|
||||||
const Headers = @import("Headers.zig");
|
const Headers = @import("Headers.zig");
|
||||||
const HeadersInit = @import("Headers.zig").HeadersInit;
|
const HeadersInit = @import("Headers.zig").HeadersInit;
|
||||||
@@ -241,7 +241,7 @@ pub fn _clone(self: *Request) !Request {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _bytes(self: *Response, page: *Page) !Env.Promise {
|
pub fn _bytes(self: *Response, page: *Page) !js.Promise {
|
||||||
if (self.body_used) {
|
if (self.body_used) {
|
||||||
return error.TypeError;
|
return error.TypeError;
|
||||||
}
|
}
|
||||||
@@ -253,7 +253,7 @@ pub fn _bytes(self: *Response, page: *Page) !Env.Promise {
|
|||||||
return resolver.promise();
|
return resolver.promise();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _json(self: *Response, page: *Page) !Env.Promise {
|
pub fn _json(self: *Response, page: *Page) !js.Promise {
|
||||||
if (self.body_used) {
|
if (self.body_used) {
|
||||||
return error.TypeError;
|
return error.TypeError;
|
||||||
}
|
}
|
||||||
@@ -280,7 +280,7 @@ pub fn _json(self: *Response, page: *Page) !Env.Promise {
|
|||||||
return resolver.promise();
|
return resolver.promise();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _text(self: *Response, page: *Page) !Env.Promise {
|
pub fn _text(self: *Response, page: *Page) !js.Promise {
|
||||||
if (self.body_used) {
|
if (self.body_used) {
|
||||||
return error.TypeError;
|
return error.TypeError;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const js = @import("../js/js.zig");
|
||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
|
|
||||||
const v8 = @import("v8");
|
const v8 = @import("v8");
|
||||||
@@ -29,7 +30,6 @@ const ReadableStream = @import("../streams/ReadableStream.zig");
|
|||||||
const Headers = @import("Headers.zig");
|
const Headers = @import("Headers.zig");
|
||||||
const HeadersInit = @import("Headers.zig").HeadersInit;
|
const HeadersInit = @import("Headers.zig").HeadersInit;
|
||||||
|
|
||||||
const Env = @import("../env.zig").Env;
|
|
||||||
const Mime = @import("../mime.zig").Mime;
|
const Mime = @import("../mime.zig").Mime;
|
||||||
const Page = @import("../page.zig").Page;
|
const Page = @import("../page.zig").Page;
|
||||||
|
|
||||||
@@ -165,12 +165,12 @@ pub fn _clone(self: *const Response) !Response {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _bytes(self: *Response, page: *Page) !Env.Promise {
|
pub fn _bytes(self: *Response, page: *Page) !js.Promise {
|
||||||
if (self.body_used) {
|
if (self.body_used) {
|
||||||
return error.TypeError;
|
return error.TypeError;
|
||||||
}
|
}
|
||||||
|
|
||||||
const resolver = Env.PromiseResolver{
|
const resolver = js.PromiseResolver{
|
||||||
.js_context = page.main_context,
|
.js_context = page.main_context,
|
||||||
.resolver = v8.PromiseResolver.init(page.main_context.v8_context),
|
.resolver = v8.PromiseResolver.init(page.main_context.v8_context),
|
||||||
};
|
};
|
||||||
@@ -180,7 +180,7 @@ pub fn _bytes(self: *Response, page: *Page) !Env.Promise {
|
|||||||
return resolver.promise();
|
return resolver.promise();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _json(self: *Response, page: *Page) !Env.Promise {
|
pub fn _json(self: *Response, page: *Page) !js.Promise {
|
||||||
if (self.body_used) {
|
if (self.body_used) {
|
||||||
return error.TypeError;
|
return error.TypeError;
|
||||||
}
|
}
|
||||||
@@ -207,7 +207,7 @@ pub fn _json(self: *Response, page: *Page) !Env.Promise {
|
|||||||
return resolver.promise();
|
return resolver.promise();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _text(self: *Response, page: *Page) !Env.Promise {
|
pub fn _text(self: *Response, page: *Page) !js.Promise {
|
||||||
if (self.body_used) {
|
if (self.body_used) {
|
||||||
return error.TypeError;
|
return error.TypeError;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
|
|
||||||
const Env = @import("../env.zig").Env;
|
const js = @import("../js/js.zig");
|
||||||
const Page = @import("../page.zig").Page;
|
const Page = @import("../page.zig").Page;
|
||||||
|
|
||||||
const Http = @import("../../http/Http.zig");
|
const Http = @import("../../http/Http.zig");
|
||||||
@@ -45,7 +45,7 @@ pub const Interfaces = .{
|
|||||||
pub const FetchContext = struct {
|
pub const FetchContext = struct {
|
||||||
page: *Page,
|
page: *Page,
|
||||||
arena: std.mem.Allocator,
|
arena: std.mem.Allocator,
|
||||||
promise_resolver: Env.PersistentPromiseResolver,
|
promise_resolver: js.PersistentPromiseResolver,
|
||||||
|
|
||||||
method: Http.Method,
|
method: Http.Method,
|
||||||
url: []const u8,
|
url: []const u8,
|
||||||
@@ -111,7 +111,7 @@ pub const FetchContext = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/Window/fetch
|
// https://developer.mozilla.org/en-US/docs/Web/API/Window/fetch
|
||||||
pub fn fetch(input: RequestInput, options: ?RequestInit, page: *Page) !Env.Promise {
|
pub fn fetch(input: RequestInput, options: ?RequestInit, page: *Page) !js.Promise {
|
||||||
const arena = page.arena;
|
const arena = page.arena;
|
||||||
|
|
||||||
const req = try Request.constructor(input, options, page);
|
const req = try Request.constructor(input, options, page);
|
||||||
|
|||||||
@@ -17,9 +17,9 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const js = @import("../js/js.zig");
|
||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
const parser = @import("../netsurf.zig");
|
const parser = @import("../netsurf.zig");
|
||||||
const Env = @import("../env.zig").Env;
|
|
||||||
const Page = @import("../page.zig").Page;
|
const Page = @import("../page.zig").Page;
|
||||||
const EventTarget = @import("../dom/event_target.zig").EventTarget;
|
const EventTarget = @import("../dom/event_target.zig").EventTarget;
|
||||||
|
|
||||||
@@ -113,7 +113,7 @@ pub const AbortSignal = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const ThrowIfAborted = union(enum) {
|
const ThrowIfAborted = union(enum) {
|
||||||
exception: Env.Exception,
|
exception: js.Exception,
|
||||||
undefined: void,
|
undefined: void,
|
||||||
};
|
};
|
||||||
pub fn _throwIfAborted(self: *const AbortSignal, page: *Page) ThrowIfAborted {
|
pub fn _throwIfAborted(self: *const AbortSignal, page: *Page) ThrowIfAborted {
|
||||||
|
|||||||
@@ -17,7 +17,8 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const parser = @import("../netsurf.zig");
|
const parser = @import("../netsurf.zig");
|
||||||
const Env = @import("../env.zig").Env;
|
const js = @import("../js/js.zig");
|
||||||
|
|
||||||
const Page = @import("../page.zig").Page;
|
const Page = @import("../page.zig").Page;
|
||||||
|
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
@@ -26,7 +27,7 @@ const DataSet = @This();
|
|||||||
|
|
||||||
element: *parser.Element,
|
element: *parser.Element,
|
||||||
|
|
||||||
pub fn named_get(self: *const DataSet, name: []const u8, _: *bool, page: *Page) !Env.UndefinedOr([]const u8) {
|
pub fn named_get(self: *const DataSet, name: []const u8, _: *bool, page: *Page) !js.UndefinedOr([]const u8) {
|
||||||
const normalized_name = try normalize(page.call_arena, name);
|
const normalized_name = try normalize(page.call_arena, name);
|
||||||
if (try parser.elementGetAttribute(self.element, normalized_name)) |value| {
|
if (try parser.elementGetAttribute(self.element, normalized_name)) |value| {
|
||||||
return .{ .value = value };
|
return .{ .value = value };
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
|
|
||||||
const Env = @import("../env.zig").Env;
|
const js = @import("../js/js.zig");
|
||||||
const Page = @import("../page.zig").Page;
|
const Page = @import("../page.zig").Page;
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#the-history-interface
|
// https://html.spec.whatwg.org/multipage/nav-history-apis.html#the-history-interface
|
||||||
@@ -67,11 +67,11 @@ pub fn set_scrollRestoration(self: *History, mode: []const u8) void {
|
|||||||
self.scroll_restoration = ScrollRestorationMode.fromString(mode) orelse self.scroll_restoration;
|
self.scroll_restoration = ScrollRestorationMode.fromString(mode) orelse self.scroll_restoration;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_state(self: *History, page: *Page) !?Env.Value {
|
pub fn get_state(self: *History, page: *Page) !?js.Value {
|
||||||
if (self.current) |curr| {
|
if (self.current) |curr| {
|
||||||
const entry = self.stack.items[curr];
|
const entry = self.stack.items[curr];
|
||||||
if (entry.state) |state| {
|
if (entry.state) |state| {
|
||||||
const value = try Env.Value.fromJson(page.main_context, state);
|
const value = try js.Value.fromJson(page.main_context, state);
|
||||||
return value;
|
return value;
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
@@ -113,7 +113,7 @@ fn _dispatchPopStateEvent(state: ?[]const u8, page: *Page) !void {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _pushState(self: *History, state: Env.JsObject, _: ?[]const u8, _url: ?[]const u8, page: *Page) !void {
|
pub fn _pushState(self: *History, state: js.JsObject, _: ?[]const u8, _url: ?[]const u8, page: *Page) !void {
|
||||||
const arena = page.session.arena;
|
const arena = page.session.arena;
|
||||||
|
|
||||||
const json = try state.toJson(arena);
|
const json = try state.toJson(arena);
|
||||||
@@ -123,7 +123,7 @@ pub fn _pushState(self: *History, state: Env.JsObject, _: ?[]const u8, _url: ?[]
|
|||||||
self.current = self.stack.items.len - 1;
|
self.current = self.stack.items.len - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _replaceState(self: *History, state: Env.JsObject, _: ?[]const u8, _url: ?[]const u8, page: *Page) !void {
|
pub fn _replaceState(self: *History, state: js.JsObject, _: ?[]const u8, _url: ?[]const u8, page: *Page) !void {
|
||||||
const arena = page.session.arena;
|
const arena = page.session.arena;
|
||||||
|
|
||||||
if (self.current) |curr| {
|
if (self.current) |curr| {
|
||||||
@@ -199,9 +199,9 @@ pub const PopStateEvent = struct {
|
|||||||
|
|
||||||
// `hasUAVisualTransition` is not implemented. It isn't baseline so this is okay.
|
// `hasUAVisualTransition` is not implemented. It isn't baseline so this is okay.
|
||||||
|
|
||||||
pub fn get_state(self: *const PopStateEvent, page: *Page) !?Env.Value {
|
pub fn get_state(self: *const PopStateEvent, page: *Page) !?js.Value {
|
||||||
if (self.state) |state| {
|
if (self.state) |state| {
|
||||||
const value = try Env.Value.fromJson(page.main_context, state);
|
const value = try js.Value.fromJson(page.main_context, state);
|
||||||
return value;
|
return value;
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -18,9 +18,9 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
|
|
||||||
|
const js = @import("../js/js.zig");
|
||||||
const parser = @import("../netsurf.zig");
|
const parser = @import("../netsurf.zig");
|
||||||
const generate = @import("../../runtime/generate.zig");
|
const generate = @import("../js/generate.zig");
|
||||||
const Env = @import("../env.zig").Env;
|
|
||||||
const Page = @import("../page.zig").Page;
|
const Page = @import("../page.zig").Page;
|
||||||
|
|
||||||
const urlStitch = @import("../../url.zig").URL.stitch;
|
const urlStitch = @import("../../url.zig").URL.stitch;
|
||||||
@@ -1000,22 +1000,22 @@ pub const HTMLScriptElement = struct {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_onload(self: *parser.Script, page: *Page) !?Env.Function {
|
pub fn get_onload(self: *parser.Script, page: *Page) !?js.Function {
|
||||||
const state = page.getNodeState(@ptrCast(@alignCast(self))) orelse return null;
|
const state = page.getNodeState(@ptrCast(@alignCast(self))) orelse return null;
|
||||||
return state.onload;
|
return state.onload;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_onload(self: *parser.Script, function: ?Env.Function, page: *Page) !void {
|
pub fn set_onload(self: *parser.Script, function: ?js.Function, page: *Page) !void {
|
||||||
const state = try page.getOrCreateNodeState(@ptrCast(@alignCast(self)));
|
const state = try page.getOrCreateNodeState(@ptrCast(@alignCast(self)));
|
||||||
state.onload = function;
|
state.onload = function;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_onerror(self: *parser.Script, page: *Page) !?Env.Function {
|
pub fn get_onerror(self: *parser.Script, page: *Page) !?js.Function {
|
||||||
const state = page.getNodeState(@ptrCast(@alignCast(self))) orelse return null;
|
const state = page.getNodeState(@ptrCast(@alignCast(self))) orelse return null;
|
||||||
return state.onerror;
|
return state.onerror;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_onerror(self: *parser.Script, function: ?Env.Function, page: *Page) !void {
|
pub fn set_onerror(self: *parser.Script, function: ?js.Function, page: *Page) !void {
|
||||||
const state = try page.getOrCreateNodeState(@ptrCast(@alignCast(self)));
|
const state = try page.getOrCreateNodeState(@ptrCast(@alignCast(self)));
|
||||||
state.onerror = function;
|
state.onerror = function;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
const Env = @import("../env.zig").Env;
|
const js = @import("../js/js.zig");
|
||||||
const parser = @import("../netsurf.zig");
|
const parser = @import("../netsurf.zig");
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/ErrorEvent
|
// https://developer.mozilla.org/en-US/docs/Web/API/ErrorEvent
|
||||||
@@ -28,14 +28,14 @@ pub const ErrorEvent = struct {
|
|||||||
filename: []const u8,
|
filename: []const u8,
|
||||||
lineno: i32,
|
lineno: i32,
|
||||||
colno: i32,
|
colno: i32,
|
||||||
@"error": ?Env.JsObject,
|
@"error": ?js.JsObject,
|
||||||
|
|
||||||
const ErrorEventInit = struct {
|
const ErrorEventInit = struct {
|
||||||
message: []const u8 = "",
|
message: []const u8 = "",
|
||||||
filename: []const u8 = "",
|
filename: []const u8 = "",
|
||||||
lineno: i32 = 0,
|
lineno: i32 = 0,
|
||||||
colno: i32 = 0,
|
colno: i32 = 0,
|
||||||
@"error": ?Env.JsObject = null,
|
@"error": ?js.JsObject = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn constructor(event_type: []const u8, opts: ?ErrorEventInit) !ErrorEvent {
|
pub fn constructor(event_type: []const u8, opts: ?ErrorEventInit) !ErrorEvent {
|
||||||
@@ -72,7 +72,7 @@ pub const ErrorEvent = struct {
|
|||||||
return self.colno;
|
return self.colno;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_error(self: *const ErrorEvent) Env.UndefinedOr(Env.JsObject) {
|
pub fn get_error(self: *const ErrorEvent) js.UndefinedOr(js.JsObject) {
|
||||||
if (self.@"error") |e| {
|
if (self.@"error") |e| {
|
||||||
return .{ .value = e };
|
return .{ .value = e };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,8 @@
|
|||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
const js = @import("../js/js.zig");
|
||||||
const parser = @import("../netsurf.zig");
|
const parser = @import("../netsurf.zig");
|
||||||
const Function = @import("../env.zig").Function;
|
|
||||||
const EventTarget = @import("../dom/event_target.zig").EventTarget;
|
const EventTarget = @import("../dom/event_target.zig").EventTarget;
|
||||||
|
|
||||||
// https://drafts.csswg.org/cssom-view/#the-mediaquerylist-interface
|
// https://drafts.csswg.org/cssom-view/#the-mediaquerylist-interface
|
||||||
@@ -39,7 +39,7 @@ pub const MediaQueryList = struct {
|
|||||||
return self.media;
|
return self.media;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _addListener(_: *const MediaQueryList, _: Function) void {}
|
pub fn _addListener(_: *const MediaQueryList, _: js.Function) void {}
|
||||||
|
|
||||||
pub fn _removeListener(_: *const MediaQueryList, _: Function) void {}
|
pub fn _removeListener(_: *const MediaQueryList, _: js.Function) void {}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -18,9 +18,9 @@
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
|
const js = @import("../js/js.zig");
|
||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
const parser = @import("../netsurf.zig");
|
const parser = @import("../netsurf.zig");
|
||||||
const Env = @import("../env.zig").Env;
|
|
||||||
const Page = @import("../page.zig").Page;
|
const Page = @import("../page.zig").Page;
|
||||||
|
|
||||||
const Navigator = @import("navigator.zig").Navigator;
|
const Navigator = @import("navigator.zig").Navigator;
|
||||||
@@ -37,8 +37,6 @@ const domcss = @import("../dom/css.zig");
|
|||||||
const Css = @import("../css/css.zig").Css;
|
const Css = @import("../css/css.zig").Css;
|
||||||
const EventHandler = @import("../events/event.zig").EventHandler;
|
const EventHandler = @import("../events/event.zig").EventHandler;
|
||||||
|
|
||||||
const Function = Env.Function;
|
|
||||||
|
|
||||||
const v8 = @import("v8");
|
const v8 = @import("v8");
|
||||||
const Request = @import("../fetch/Request.zig");
|
const Request = @import("../fetch/Request.zig");
|
||||||
const fetchFn = @import("../fetch/fetch.zig").fetch;
|
const fetchFn = @import("../fetch/fetch.zig").fetch;
|
||||||
@@ -70,7 +68,7 @@ pub const Window = struct {
|
|||||||
css: Css = .{},
|
css: Css = .{},
|
||||||
scroll_x: u32 = 0,
|
scroll_x: u32 = 0,
|
||||||
scroll_y: u32 = 0,
|
scroll_y: u32 = 0,
|
||||||
onload_callback: ?Function = null,
|
onload_callback: ?js.Function = null,
|
||||||
|
|
||||||
pub fn create(target: ?[]const u8, navigator: ?Navigator) !Window {
|
pub fn create(target: ?[]const u8, navigator: ?Navigator) !Window {
|
||||||
var fbs = std.io.fixedBufferStream("");
|
var fbs = std.io.fixedBufferStream("");
|
||||||
@@ -101,12 +99,12 @@ pub const Window = struct {
|
|||||||
self.storage_shelf = shelf;
|
self.storage_shelf = shelf;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _fetch(_: *Window, input: Request.RequestInput, options: ?Request.RequestInit, page: *Page) !Env.Promise {
|
pub fn _fetch(_: *Window, input: Request.RequestInput, options: ?Request.RequestInit, page: *Page) !js.Promise {
|
||||||
return fetchFn(input, options, page);
|
return fetchFn(input, options, page);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `onload_callback`.
|
/// Returns `onload_callback`.
|
||||||
pub fn get_onload(self: *const Window) ?Function {
|
pub fn get_onload(self: *const Window) ?js.Function {
|
||||||
return self.onload_callback;
|
return self.onload_callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,7 +256,7 @@ pub const Window = struct {
|
|||||||
return &self.css;
|
return &self.css;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _requestAnimationFrame(self: *Window, cbk: Function, page: *Page) !u32 {
|
pub fn _requestAnimationFrame(self: *Window, cbk: js.Function, page: *Page) !u32 {
|
||||||
return self.createTimeout(cbk, 5, page, .{
|
return self.createTimeout(cbk, 5, page, .{
|
||||||
.animation_frame = true,
|
.animation_frame = true,
|
||||||
.name = "animationFrame",
|
.name = "animationFrame",
|
||||||
@@ -270,11 +268,11 @@ pub const Window = struct {
|
|||||||
_ = self.timers.remove(id);
|
_ = self.timers.remove(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _setTimeout(self: *Window, cbk: Function, delay: ?u32, params: []Env.JsObject, page: *Page) !u32 {
|
pub fn _setTimeout(self: *Window, cbk: js.Function, delay: ?u32, params: []js.JsObject, page: *Page) !u32 {
|
||||||
return self.createTimeout(cbk, delay, page, .{ .args = params, .name = "setTimeout" });
|
return self.createTimeout(cbk, delay, page, .{ .args = params, .name = "setTimeout" });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _setInterval(self: *Window, cbk: Function, delay: ?u32, params: []Env.JsObject, page: *Page) !u32 {
|
pub fn _setInterval(self: *Window, cbk: js.Function, delay: ?u32, params: []js.JsObject, page: *Page) !u32 {
|
||||||
return self.createTimeout(cbk, delay, page, .{ .repeat = true, .args = params, .name = "setInterval" });
|
return self.createTimeout(cbk, delay, page, .{ .repeat = true, .args = params, .name = "setInterval" });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,11 +284,11 @@ pub const Window = struct {
|
|||||||
_ = self.timers.remove(id);
|
_ = self.timers.remove(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _queueMicrotask(self: *Window, cbk: Function, page: *Page) !u32 {
|
pub fn _queueMicrotask(self: *Window, cbk: js.Function, page: *Page) !u32 {
|
||||||
return self.createTimeout(cbk, 0, page, .{ .name = "queueMicrotask" });
|
return self.createTimeout(cbk, 0, page, .{ .name = "queueMicrotask" });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _setImmediate(self: *Window, cbk: Function, page: *Page) !u32 {
|
pub fn _setImmediate(self: *Window, cbk: js.Function, page: *Page) !u32 {
|
||||||
return self.createTimeout(cbk, 0, page, .{ .name = "setImmediate" });
|
return self.createTimeout(cbk, 0, page, .{ .name = "setImmediate" });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,7 +296,7 @@ pub const Window = struct {
|
|||||||
_ = self.timers.remove(id);
|
_ = self.timers.remove(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _matchMedia(_: *const Window, media: Env.String) !MediaQueryList {
|
pub fn _matchMedia(_: *const Window, media: js.String) !MediaQueryList {
|
||||||
return .{
|
return .{
|
||||||
.matches = false, // TODO?
|
.matches = false, // TODO?
|
||||||
.media = media.string,
|
.media = media.string,
|
||||||
@@ -322,12 +320,12 @@ pub const Window = struct {
|
|||||||
|
|
||||||
const CreateTimeoutOpts = struct {
|
const CreateTimeoutOpts = struct {
|
||||||
name: []const u8,
|
name: []const u8,
|
||||||
args: []Env.JsObject = &.{},
|
args: []js.JsObject = &.{},
|
||||||
repeat: bool = false,
|
repeat: bool = false,
|
||||||
animation_frame: bool = false,
|
animation_frame: bool = false,
|
||||||
low_priority: bool = false,
|
low_priority: bool = false,
|
||||||
};
|
};
|
||||||
fn createTimeout(self: *Window, cbk: Function, delay_: ?u32, page: *Page, opts: CreateTimeoutOpts) !u32 {
|
fn createTimeout(self: *Window, cbk: js.Function, delay_: ?u32, page: *Page, opts: CreateTimeoutOpts) !u32 {
|
||||||
const delay = delay_ orelse 0;
|
const delay = delay_ orelse 0;
|
||||||
if (self.timers.count() > 512) {
|
if (self.timers.count() > 512) {
|
||||||
return error.TooManyTimeout;
|
return error.TooManyTimeout;
|
||||||
@@ -347,9 +345,9 @@ pub const Window = struct {
|
|||||||
errdefer _ = self.timers.remove(timer_id);
|
errdefer _ = self.timers.remove(timer_id);
|
||||||
|
|
||||||
const args = opts.args;
|
const args = opts.args;
|
||||||
var persisted_args: []Env.JsObject = &.{};
|
var persisted_args: []js.JsObject = &.{};
|
||||||
if (args.len > 0) {
|
if (args.len > 0) {
|
||||||
persisted_args = try page.arena.alloc(Env.JsObject, args.len);
|
persisted_args = try page.arena.alloc(js.JsObject, args.len);
|
||||||
for (args, persisted_args) |a, *ca| {
|
for (args, persisted_args) |a, *ca| {
|
||||||
ca.* = try a.persist();
|
ca.* = try a.persist();
|
||||||
}
|
}
|
||||||
@@ -476,13 +474,13 @@ const TimerCallback = struct {
|
|||||||
repeat: ?u32,
|
repeat: ?u32,
|
||||||
|
|
||||||
// The JavaScript callback to execute
|
// The JavaScript callback to execute
|
||||||
cbk: Function,
|
cbk: js.Function,
|
||||||
|
|
||||||
animation_frame: bool = false,
|
animation_frame: bool = false,
|
||||||
|
|
||||||
window: *Window,
|
window: *Window,
|
||||||
|
|
||||||
args: []Env.JsObject = &.{},
|
args: []js.JsObject = &.{},
|
||||||
|
|
||||||
fn run(ctx: *anyopaque) ?u32 {
|
fn run(ctx: *anyopaque) ?u32 {
|
||||||
const self: *TimerCallback = @ptrCast(@alignCast(ctx));
|
const self: *TimerCallback = @ptrCast(@alignCast(ctx));
|
||||||
@@ -496,7 +494,7 @@ const TimerCallback = struct {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var result: Function.Result = undefined;
|
var result: js.Function.Result = undefined;
|
||||||
|
|
||||||
var call: anyerror!void = undefined;
|
var call: anyerror!void = undefined;
|
||||||
if (self.animation_frame) {
|
if (self.animation_frame) {
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ test "generate: Union" {
|
|||||||
const value = Union(.{ Astruct, Bstruct, .{Cstruct} });
|
const value = Union(.{ Astruct, Bstruct, .{Cstruct} });
|
||||||
const ti = @typeInfo(value).@"union";
|
const ti = @typeInfo(value).@"union";
|
||||||
try std.testing.expectEqual(3, ti.fields.len);
|
try std.testing.expectEqual(3, ti.fields.len);
|
||||||
try std.testing.expectEqualStrings("*runtime.generate.test.generate: Union.Astruct.Other", @typeName(ti.fields[0].type));
|
try std.testing.expectEqualStrings("*browser.js.generate.test.generate: Union.Astruct.Other", @typeName(ti.fields[0].type));
|
||||||
try std.testing.expectEqualStrings(ti.fields[0].name, "Astruct");
|
try std.testing.expectEqualStrings(ti.fields[0].name, "Astruct");
|
||||||
try std.testing.expectEqual(*Bstruct, ti.fields[1].type);
|
try std.testing.expectEqual(*Bstruct, ti.fields[1].type);
|
||||||
try std.testing.expectEqualStrings(ti.fields[1].name, "Bstruct");
|
try std.testing.expectEqualStrings(ti.fields[1].name, "Bstruct");
|
||||||
4331
src/browser/js/js.zig
Normal file
4331
src/browser/js/js.zig
Normal file
File diff suppressed because it is too large
Load Diff
@@ -23,7 +23,6 @@ const Allocator = std.mem.Allocator;
|
|||||||
|
|
||||||
const Dump = @import("dump.zig");
|
const Dump = @import("dump.zig");
|
||||||
const State = @import("State.zig");
|
const State = @import("State.zig");
|
||||||
const Env = @import("env.zig").Env;
|
|
||||||
const Mime = @import("mime.zig").Mime;
|
const Mime = @import("mime.zig").Mime;
|
||||||
const Session = @import("session.zig").Session;
|
const Session = @import("session.zig").Session;
|
||||||
const Renderer = @import("renderer.zig").Renderer;
|
const Renderer = @import("renderer.zig").Renderer;
|
||||||
@@ -35,6 +34,7 @@ const ScriptManager = @import("ScriptManager.zig");
|
|||||||
const SlotChangeMonitor = @import("SlotChangeMonitor.zig");
|
const SlotChangeMonitor = @import("SlotChangeMonitor.zig");
|
||||||
const HTMLDocument = @import("html/document.zig").HTMLDocument;
|
const HTMLDocument = @import("html/document.zig").HTMLDocument;
|
||||||
|
|
||||||
|
const js = @import("js/js.zig");
|
||||||
const URL = @import("../url.zig").URL;
|
const URL = @import("../url.zig").URL;
|
||||||
|
|
||||||
const log = @import("../log.zig");
|
const log = @import("../log.zig");
|
||||||
@@ -74,7 +74,7 @@ pub const Page = struct {
|
|||||||
|
|
||||||
// Our JavaScript context for this specific page. This is what we use to
|
// Our JavaScript context for this specific page. This is what we use to
|
||||||
// execute any JavaScript
|
// execute any JavaScript
|
||||||
main_context: *Env.JsContext,
|
main_context: *js.JsContext,
|
||||||
|
|
||||||
// indicates intention to navigate to another page on the next loop execution.
|
// indicates intention to navigate to another page on the next loop execution.
|
||||||
delayed_navigation: bool = false,
|
delayed_navigation: bool = false,
|
||||||
@@ -143,7 +143,7 @@ pub const Page = struct {
|
|||||||
.main_context = undefined,
|
.main_context = undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.main_context = try session.executor.createJsContext(&self.window, self, &self.script_manager, true, Env.GlobalMissingCallback.init(&self.polyfill_loader));
|
self.main_context = try session.executor.createJsContext(&self.window, self, &self.script_manager, true, js.GlobalMissingCallback.init(&self.polyfill_loader));
|
||||||
try polyfill.preload(self.arena, self.main_context);
|
try polyfill.preload(self.arena, self.main_context);
|
||||||
|
|
||||||
try self.scheduler.add(self, runMicrotasks, 5, .{ .name = "page.microtasks" });
|
try self.scheduler.add(self, runMicrotasks, 5, .{ .name = "page.microtasks" });
|
||||||
@@ -276,7 +276,7 @@ pub const Page = struct {
|
|||||||
var timer = try std.time.Timer.start();
|
var timer = try std.time.Timer.start();
|
||||||
var ms_remaining = wait_ms;
|
var ms_remaining = wait_ms;
|
||||||
|
|
||||||
var try_catch: Env.TryCatch = undefined;
|
var try_catch: js.TryCatch = undefined;
|
||||||
try_catch.init(self.main_context);
|
try_catch.init(self.main_context);
|
||||||
defer try_catch.deinit();
|
defer try_catch.deinit();
|
||||||
|
|
||||||
|
|||||||
@@ -19,9 +19,9 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
|
const js = @import("../js/js.zig");
|
||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const Env = @import("../env.zig").Env;
|
|
||||||
|
|
||||||
pub const Loader = struct {
|
pub const Loader = struct {
|
||||||
state: enum { empty, loading } = .empty,
|
state: enum { empty, loading } = .empty,
|
||||||
@@ -30,8 +30,8 @@ pub const Loader = struct {
|
|||||||
webcomponents: bool = false,
|
webcomponents: bool = false,
|
||||||
} = .{},
|
} = .{},
|
||||||
|
|
||||||
fn load(self: *Loader, comptime name: []const u8, source: []const u8, js_context: *Env.JsContext) void {
|
fn load(self: *Loader, comptime name: []const u8, source: []const u8, js_context: *js.JsContext) void {
|
||||||
var try_catch: Env.TryCatch = undefined;
|
var try_catch: js.TryCatch = undefined;
|
||||||
try_catch.init(js_context);
|
try_catch.init(js_context);
|
||||||
defer try_catch.deinit();
|
defer try_catch.deinit();
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ pub const Loader = struct {
|
|||||||
@field(self.done, name) = true;
|
@field(self.done, name) = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn missing(self: *Loader, name: []const u8, js_context: *Env.JsContext) bool {
|
pub fn missing(self: *Loader, name: []const u8, js_context: *js.JsContext) bool {
|
||||||
// Avoid recursive calls during polyfill loading.
|
// Avoid recursive calls during polyfill loading.
|
||||||
if (self.state == .loading) {
|
if (self.state == .loading) {
|
||||||
return false;
|
return false;
|
||||||
@@ -82,8 +82,8 @@ pub const Loader = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn preload(allocator: Allocator, js_context: *Env.JsContext) !void {
|
pub fn preload(allocator: Allocator, js_context: *js.JsContext) !void {
|
||||||
var try_catch: Env.TryCatch = undefined;
|
var try_catch: js.TryCatch = undefined;
|
||||||
try_catch.init(js_context);
|
try_catch.init(js_context);
|
||||||
defer try_catch.deinit();
|
defer try_catch.deinit();
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ const std = @import("std");
|
|||||||
|
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
const Env = @import("env.zig").Env;
|
const js = @import("js/js.zig");
|
||||||
const Page = @import("page.zig").Page;
|
const Page = @import("page.zig").Page;
|
||||||
const Browser = @import("browser.zig").Browser;
|
const Browser = @import("browser.zig").Browser;
|
||||||
const NavigateOpts = @import("page.zig").NavigateOpts;
|
const NavigateOpts = @import("page.zig").NavigateOpts;
|
||||||
@@ -50,7 +50,7 @@ pub const Session = struct {
|
|||||||
// page and start another.
|
// page and start another.
|
||||||
transfer_arena: Allocator,
|
transfer_arena: Allocator,
|
||||||
|
|
||||||
executor: Env.ExecutionWorld,
|
executor: js.ExecutionWorld,
|
||||||
storage_shed: storage.Shed,
|
storage_shed: storage.Shed,
|
||||||
cookie_jar: storage.CookieJar,
|
cookie_jar: storage.CookieJar,
|
||||||
|
|
||||||
|
|||||||
@@ -17,10 +17,10 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const js = @import("../js/js.zig");
|
||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
|
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const Env = @import("../env.zig").Env;
|
|
||||||
const Page = @import("../page.zig").Page;
|
const Page = @import("../page.zig").Page;
|
||||||
|
|
||||||
const ReadableStream = @This();
|
const ReadableStream = @This();
|
||||||
@@ -31,26 +31,26 @@ const State = union(enum) {
|
|||||||
readable,
|
readable,
|
||||||
closed: ?[]const u8,
|
closed: ?[]const u8,
|
||||||
cancelled: ?[]const u8,
|
cancelled: ?[]const u8,
|
||||||
errored: Env.JsObject,
|
errored: js.JsObject,
|
||||||
};
|
};
|
||||||
|
|
||||||
// This promise resolves when a stream is canceled.
|
// This promise resolves when a stream is canceled.
|
||||||
cancel_resolver: Env.PersistentPromiseResolver,
|
cancel_resolver: js.PersistentPromiseResolver,
|
||||||
closed_resolver: Env.PersistentPromiseResolver,
|
closed_resolver: js.PersistentPromiseResolver,
|
||||||
reader_resolver: ?Env.PersistentPromiseResolver = null,
|
reader_resolver: ?js.PersistentPromiseResolver = null,
|
||||||
|
|
||||||
locked: bool = false,
|
locked: bool = false,
|
||||||
state: State = .readable,
|
state: State = .readable,
|
||||||
|
|
||||||
cancel_fn: ?Env.Function = null,
|
cancel_fn: ?js.Function = null,
|
||||||
pull_fn: ?Env.Function = null,
|
pull_fn: ?js.Function = null,
|
||||||
|
|
||||||
strategy: QueueingStrategy,
|
strategy: QueueingStrategy,
|
||||||
queue: std.ArrayListUnmanaged(Chunk) = .empty,
|
queue: std.ArrayListUnmanaged(Chunk) = .empty,
|
||||||
|
|
||||||
pub const Chunk = union(enum) {
|
pub const Chunk = union(enum) {
|
||||||
// the order matters, sorry.
|
// the order matters, sorry.
|
||||||
uint8array: Env.TypedArray(u8),
|
uint8array: js.TypedArray(u8),
|
||||||
string: []const u8,
|
string: []const u8,
|
||||||
|
|
||||||
pub fn dupe(self: Chunk, allocator: Allocator) !Chunk {
|
pub fn dupe(self: Chunk, allocator: Allocator) !Chunk {
|
||||||
@@ -91,14 +91,14 @@ pub const ReadableStreamReadResult = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const UnderlyingSource = struct {
|
const UnderlyingSource = struct {
|
||||||
start: ?Env.Function = null,
|
start: ?js.Function = null,
|
||||||
pull: ?Env.Function = null,
|
pull: ?js.Function = null,
|
||||||
cancel: ?Env.Function = null,
|
cancel: ?js.Function = null,
|
||||||
type: ?[]const u8 = null,
|
type: ?[]const u8 = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
const QueueingStrategy = struct {
|
const QueueingStrategy = struct {
|
||||||
size: ?Env.Function = null,
|
size: ?js.Function = null,
|
||||||
high_water_mark: u32 = 1,
|
high_water_mark: u32 = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -146,7 +146,7 @@ pub fn get_locked(self: *const ReadableStream) bool {
|
|||||||
return self.locked;
|
return self.locked;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _cancel(self: *ReadableStream, reason: ?[]const u8, page: *Page) !Env.Promise {
|
pub fn _cancel(self: *ReadableStream, reason: ?[]const u8, page: *Page) !js.Promise {
|
||||||
if (self.locked) {
|
if (self.locked) {
|
||||||
return error.TypeError;
|
return error.TypeError;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,10 +17,10 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const js = @import("../js/js.zig");
|
||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
|
|
||||||
const Page = @import("../page.zig").Page;
|
const Page = @import("../page.zig").Page;
|
||||||
const Env = @import("../env.zig").Env;
|
|
||||||
|
|
||||||
const ReadableStream = @import("./ReadableStream.zig");
|
const ReadableStream = @import("./ReadableStream.zig");
|
||||||
const ReadableStreamReadResult = @import("./ReadableStream.zig").ReadableStreamReadResult;
|
const ReadableStreamReadResult = @import("./ReadableStream.zig").ReadableStreamReadResult;
|
||||||
@@ -69,7 +69,7 @@ pub fn _enqueue(self: *ReadableStreamDefaultController, chunk: ReadableStream.Ch
|
|||||||
try self.stream.pullIf();
|
try self.stream.pullIf();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _error(self: *ReadableStreamDefaultController, err: Env.JsObject) !void {
|
pub fn _error(self: *ReadableStreamDefaultController, err: js.JsObject) !void {
|
||||||
self.stream.state = .{ .errored = err };
|
self.stream.state = .{ .errored = err };
|
||||||
|
|
||||||
if (self.stream.reader_resolver) |*rr| {
|
if (self.stream.reader_resolver) |*rr| {
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
|
const js = @import("../js/js.zig");
|
||||||
const log = @import("../../log.zig");
|
const log = @import("../../log.zig");
|
||||||
const Env = @import("../env.zig").Env;
|
|
||||||
const Page = @import("../page.zig").Page;
|
const Page = @import("../page.zig").Page;
|
||||||
const ReadableStream = @import("./ReadableStream.zig");
|
const ReadableStream = @import("./ReadableStream.zig");
|
||||||
const ReadableStreamReadResult = @import("./ReadableStream.zig").ReadableStreamReadResult;
|
const ReadableStreamReadResult = @import("./ReadableStream.zig").ReadableStreamReadResult;
|
||||||
@@ -32,15 +32,15 @@ pub fn constructor(stream: *ReadableStream) ReadableStreamDefaultReader {
|
|||||||
return .{ .stream = stream };
|
return .{ .stream = stream };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_closed(self: *const ReadableStreamDefaultReader) Env.Promise {
|
pub fn get_closed(self: *const ReadableStreamDefaultReader) js.Promise {
|
||||||
return self.stream.closed_resolver.promise();
|
return self.stream.closed_resolver.promise();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _cancel(self: *ReadableStreamDefaultReader, reason: ?[]const u8, page: *Page) !Env.Promise {
|
pub fn _cancel(self: *ReadableStreamDefaultReader, reason: ?[]const u8, page: *Page) !js.Promise {
|
||||||
return try self.stream._cancel(reason, page);
|
return try self.stream._cancel(reason, page);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn _read(self: *const ReadableStreamDefaultReader, page: *Page) !Env.Promise {
|
pub fn _read(self: *const ReadableStreamDefaultReader, page: *Page) !js.Promise {
|
||||||
const stream = self.stream;
|
const stream = self.stream;
|
||||||
|
|
||||||
switch (stream.state) {
|
switch (stream.state) {
|
||||||
|
|||||||
@@ -19,8 +19,8 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
|
const js = @import("../js/js.zig");
|
||||||
const parser = @import("../netsurf.zig");
|
const parser = @import("../netsurf.zig");
|
||||||
const Env = @import("../env.zig").Env;
|
|
||||||
const Page = @import("../page.zig").Page;
|
const Page = @import("../page.zig").Page;
|
||||||
const FormData = @import("../xhr/form_data.zig").FormData;
|
const FormData = @import("../xhr/form_data.zig").FormData;
|
||||||
|
|
||||||
@@ -261,7 +261,7 @@ pub const URLSearchParams = struct {
|
|||||||
const URLSearchParamsOpts = union(enum) {
|
const URLSearchParamsOpts = union(enum) {
|
||||||
qs: []const u8,
|
qs: []const u8,
|
||||||
form_data: *const FormData,
|
form_data: *const FormData,
|
||||||
js_obj: Env.JsObject,
|
js_obj: js.JsObject,
|
||||||
};
|
};
|
||||||
pub fn constructor(opts_: ?URLSearchParamsOpts, page: *Page) !URLSearchParams {
|
pub fn constructor(opts_: ?URLSearchParamsOpts, page: *Page) !URLSearchParams {
|
||||||
const opts = opts_ orelse return .{ .entries = .{} };
|
const opts = opts_ orelse return .{ .entries = .{} };
|
||||||
|
|||||||
@@ -17,9 +17,7 @@
|
|||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const js = @import("../js/js.zig");
|
||||||
const Env = @import("../env.zig").Env;
|
|
||||||
const Function = Env.Function;
|
|
||||||
|
|
||||||
const EventTarget = @import("../dom/event_target.zig").EventTarget;
|
const EventTarget = @import("../dom/event_target.zig").EventTarget;
|
||||||
const EventHandler = @import("../events/event.zig").EventHandler;
|
const EventHandler = @import("../events/event.zig").EventHandler;
|
||||||
@@ -33,20 +31,20 @@ pub const XMLHttpRequestEventTarget = struct {
|
|||||||
// Extend libdom event target for pure zig struct.
|
// Extend libdom event target for pure zig struct.
|
||||||
base: parser.EventTargetTBase = parser.EventTargetTBase{ .internal_target_type = .xhr },
|
base: parser.EventTargetTBase = parser.EventTargetTBase{ .internal_target_type = .xhr },
|
||||||
|
|
||||||
onloadstart_cbk: ?Function = null,
|
onloadstart_cbk: ?js.Function = null,
|
||||||
onprogress_cbk: ?Function = null,
|
onprogress_cbk: ?js.Function = null,
|
||||||
onabort_cbk: ?Function = null,
|
onabort_cbk: ?js.Function = null,
|
||||||
onload_cbk: ?Function = null,
|
onload_cbk: ?js.Function = null,
|
||||||
ontimeout_cbk: ?Function = null,
|
ontimeout_cbk: ?js.Function = null,
|
||||||
onloadend_cbk: ?Function = null,
|
onloadend_cbk: ?js.Function = null,
|
||||||
onreadystatechange_cbk: ?Function = null,
|
onreadystatechange_cbk: ?js.Function = null,
|
||||||
|
|
||||||
fn register(
|
fn register(
|
||||||
self: *XMLHttpRequestEventTarget,
|
self: *XMLHttpRequestEventTarget,
|
||||||
alloc: std.mem.Allocator,
|
alloc: std.mem.Allocator,
|
||||||
typ: []const u8,
|
typ: []const u8,
|
||||||
listener: EventHandler.Listener,
|
listener: EventHandler.Listener,
|
||||||
) !?Function {
|
) !?js.Function {
|
||||||
const target = @as(*parser.EventTarget, @ptrCast(self));
|
const target = @as(*parser.EventTarget, @ptrCast(self));
|
||||||
|
|
||||||
// The only time this can return null if the listener is already
|
// The only time this can return null if the listener is already
|
||||||
@@ -69,25 +67,25 @@ pub const XMLHttpRequestEventTarget = struct {
|
|||||||
try parser.eventTargetRemoveEventListener(et, typ, lst.?, false);
|
try parser.eventTargetRemoveEventListener(et, typ, lst.?, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_onloadstart(self: *XMLHttpRequestEventTarget) ?Function {
|
pub fn get_onloadstart(self: *XMLHttpRequestEventTarget) ?js.Function {
|
||||||
return self.onloadstart_cbk;
|
return self.onloadstart_cbk;
|
||||||
}
|
}
|
||||||
pub fn get_onprogress(self: *XMLHttpRequestEventTarget) ?Function {
|
pub fn get_onprogress(self: *XMLHttpRequestEventTarget) ?js.Function {
|
||||||
return self.onprogress_cbk;
|
return self.onprogress_cbk;
|
||||||
}
|
}
|
||||||
pub fn get_onabort(self: *XMLHttpRequestEventTarget) ?Function {
|
pub fn get_onabort(self: *XMLHttpRequestEventTarget) ?js.Function {
|
||||||
return self.onabort_cbk;
|
return self.onabort_cbk;
|
||||||
}
|
}
|
||||||
pub fn get_onload(self: *XMLHttpRequestEventTarget) ?Function {
|
pub fn get_onload(self: *XMLHttpRequestEventTarget) ?js.Function {
|
||||||
return self.onload_cbk;
|
return self.onload_cbk;
|
||||||
}
|
}
|
||||||
pub fn get_ontimeout(self: *XMLHttpRequestEventTarget) ?Function {
|
pub fn get_ontimeout(self: *XMLHttpRequestEventTarget) ?js.Function {
|
||||||
return self.ontimeout_cbk;
|
return self.ontimeout_cbk;
|
||||||
}
|
}
|
||||||
pub fn get_onloadend(self: *XMLHttpRequestEventTarget) ?Function {
|
pub fn get_onloadend(self: *XMLHttpRequestEventTarget) ?js.Function {
|
||||||
return self.onloadend_cbk;
|
return self.onloadend_cbk;
|
||||||
}
|
}
|
||||||
pub fn get_onreadystatechange(self: *XMLHttpRequestEventTarget) ?Function {
|
pub fn get_onreadystatechange(self: *XMLHttpRequestEventTarget) ?js.Function {
|
||||||
return self.onreadystatechange_cbk;
|
return self.onreadystatechange_cbk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,18 +21,17 @@ const Allocator = std.mem.Allocator;
|
|||||||
const json = std.json;
|
const json = std.json;
|
||||||
|
|
||||||
const log = @import("../log.zig");
|
const log = @import("../log.zig");
|
||||||
|
const js = @import("../browser/js/js.zig");
|
||||||
|
const polyfill = @import("../browser/polyfill/polyfill.zig");
|
||||||
|
|
||||||
const App = @import("../app.zig").App;
|
const App = @import("../app.zig").App;
|
||||||
const Env = @import("../browser/env.zig").Env;
|
|
||||||
const Browser = @import("../browser/browser.zig").Browser;
|
const Browser = @import("../browser/browser.zig").Browser;
|
||||||
const Session = @import("../browser/session.zig").Session;
|
const Session = @import("../browser/session.zig").Session;
|
||||||
const Page = @import("../browser/page.zig").Page;
|
const Page = @import("../browser/page.zig").Page;
|
||||||
const Inspector = @import("../browser/env.zig").Env.Inspector;
|
|
||||||
const Incrementing = @import("../id.zig").Incrementing;
|
const Incrementing = @import("../id.zig").Incrementing;
|
||||||
const Notification = @import("../notification.zig").Notification;
|
const Notification = @import("../notification.zig").Notification;
|
||||||
const InterceptState = @import("domains/fetch.zig").InterceptState;
|
const InterceptState = @import("domains/fetch.zig").InterceptState;
|
||||||
|
|
||||||
const polyfill = @import("../browser/polyfill/polyfill.zig");
|
|
||||||
|
|
||||||
pub const URL_BASE = "chrome://newtab/";
|
pub const URL_BASE = "chrome://newtab/";
|
||||||
pub const LOADER_ID = "LOADERID24DD2FD56CF1EF33C965C79C";
|
pub const LOADER_ID = "LOADERID24DD2FD56CF1EF33C965C79C";
|
||||||
|
|
||||||
@@ -329,7 +328,7 @@ pub fn BrowserContext(comptime CDP_T: type) type {
|
|||||||
node_registry: Node.Registry,
|
node_registry: Node.Registry,
|
||||||
node_search_list: Node.Search.List,
|
node_search_list: Node.Search.List,
|
||||||
|
|
||||||
inspector: Inspector,
|
inspector: js.Inspector,
|
||||||
isolated_worlds: std.ArrayListUnmanaged(IsolatedWorld),
|
isolated_worlds: std.ArrayListUnmanaged(IsolatedWorld),
|
||||||
|
|
||||||
http_proxy_changed: bool = false,
|
http_proxy_changed: bool = false,
|
||||||
@@ -661,7 +660,7 @@ pub fn BrowserContext(comptime CDP_T: type) type {
|
|||||||
/// An object id is unique across all contexts, different object ids can refer to the same Node in different contexts.
|
/// An object id is unique across all contexts, different object ids can refer to the same Node in different contexts.
|
||||||
const IsolatedWorld = struct {
|
const IsolatedWorld = struct {
|
||||||
name: []const u8,
|
name: []const u8,
|
||||||
executor: Env.ExecutionWorld,
|
executor: js.ExecutionWorld,
|
||||||
grant_universal_access: bool,
|
grant_universal_access: bool,
|
||||||
|
|
||||||
// Polyfill loader for the isolated world.
|
// Polyfill loader for the isolated world.
|
||||||
@@ -695,7 +694,7 @@ const IsolatedWorld = struct {
|
|||||||
page,
|
page,
|
||||||
null,
|
null,
|
||||||
false,
|
false,
|
||||||
Env.GlobalMissingCallback.init(&self.polyfill_loader),
|
js.GlobalMissingCallback.init(&self.polyfill_loader),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,11 +19,12 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
const log = @import("log.zig");
|
const log = @import("log.zig");
|
||||||
|
const js = @import("browser/js/js.zig");
|
||||||
|
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const ArenaAllocator = std.heap.ArenaAllocator;
|
const ArenaAllocator = std.heap.ArenaAllocator;
|
||||||
|
|
||||||
const App = @import("app.zig").App;
|
const App = @import("app.zig").App;
|
||||||
const Env = @import("browser/env.zig").Env;
|
|
||||||
const Browser = @import("browser/browser.zig").Browser;
|
const Browser = @import("browser/browser.zig").Browser;
|
||||||
const TestHTTPServer = @import("TestHTTPServer.zig");
|
const TestHTTPServer = @import("TestHTTPServer.zig");
|
||||||
|
|
||||||
@@ -123,7 +124,7 @@ fn run(
|
|||||||
_ = page.wait(2000);
|
_ = page.wait(2000);
|
||||||
|
|
||||||
const js_context = page.main_context;
|
const js_context = page.main_context;
|
||||||
var try_catch: Env.TryCatch = undefined;
|
var try_catch: js.TryCatch = undefined;
|
||||||
try_catch.init(js_context);
|
try_catch.init(js_context);
|
||||||
defer try_catch.deinit();
|
defer try_catch.deinit();
|
||||||
|
|
||||||
|
|||||||
4344
src/runtime/js.zig
4344
src/runtime/js.zig
File diff suppressed because it is too large
Load Diff
@@ -1,295 +0,0 @@
|
|||||||
// Copyright (C) 2023-2024 Lightpanda (Selecy SAS)
|
|
||||||
//
|
|
||||||
// Francis Bouvier <francis@lightpanda.io>
|
|
||||||
// Pierre Tachoire <pierre@lightpanda.io>
|
|
||||||
//
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Affero General Public License as
|
|
||||||
// published by the Free Software Foundation, either version 3 of the
|
|
||||||
// License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Affero General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
const std = @import("std");
|
|
||||||
const Allocator = std.mem.Allocator;
|
|
||||||
|
|
||||||
const MyList = struct {
|
|
||||||
items: []u8,
|
|
||||||
|
|
||||||
pub fn constructor(elem1: u8, elem2: u8, elem3: u8, state: State) MyList {
|
|
||||||
var items = state.arena.alloc(u8, 3) catch unreachable;
|
|
||||||
items[0] = elem1;
|
|
||||||
items[1] = elem2;
|
|
||||||
items[2] = elem3;
|
|
||||||
return .{ .items = items };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _first(self: *const MyList) u8 {
|
|
||||||
return self.items[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _symbol_iterator(self: *const MyList) IterableU8 {
|
|
||||||
return IterableU8.init(self.items);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const MyVariadic = struct {
|
|
||||||
member: u8,
|
|
||||||
|
|
||||||
pub fn constructor() MyVariadic {
|
|
||||||
return .{ .member = 0 };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _len(_: *const MyVariadic, variadic: []bool) u64 {
|
|
||||||
return @as(u64, variadic.len);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _first(_: *const MyVariadic, _: []const u8, variadic: []bool) bool {
|
|
||||||
return variadic[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _last(_: *const MyVariadic, variadic: []bool) bool {
|
|
||||||
return variadic[variadic.len - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _empty(_: *const MyVariadic, _: []bool) bool {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _myListLen(_: *const MyVariadic, variadic: []*const MyList) u8 {
|
|
||||||
return @as(u8, @intCast(variadic.len));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _myListFirst(_: *const MyVariadic, variadic: []*const MyList) ?u8 {
|
|
||||||
if (variadic.len == 0) return null;
|
|
||||||
return variadic[0]._first();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const MyErrorUnion = struct {
|
|
||||||
pub fn constructor(is_err: bool) !MyErrorUnion {
|
|
||||||
if (is_err) return error.MyError;
|
|
||||||
return .{};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_withoutError(_: *const MyErrorUnion) !u8 {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_withError(_: *const MyErrorUnion) !u8 {
|
|
||||||
return error.MyError;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_withoutError(_: *const MyErrorUnion, _: bool) !void {}
|
|
||||||
|
|
||||||
pub fn set_withError(_: *const MyErrorUnion, _: bool) !void {
|
|
||||||
return error.MyError;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _funcWithoutError(_: *const MyErrorUnion) !void {}
|
|
||||||
|
|
||||||
pub fn _funcWithError(_: *const MyErrorUnion) !void {
|
|
||||||
return error.MyError;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const MyException = struct {
|
|
||||||
err: ErrorSet,
|
|
||||||
|
|
||||||
const errorNames = [_][]const u8{
|
|
||||||
"MyCustomError",
|
|
||||||
};
|
|
||||||
const errorMsgs = [_][]const u8{
|
|
||||||
"Some custom message.",
|
|
||||||
};
|
|
||||||
fn errorStrings(comptime i: usize) []const u8 {
|
|
||||||
return errorNames[0] ++ ": " ++ errorMsgs[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
// interface definition
|
|
||||||
|
|
||||||
pub const ErrorSet = error{
|
|
||||||
MyCustomError,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn init(_: Allocator, err: anyerror, _: []const u8) !MyException {
|
|
||||||
return .{ .err = @as(ErrorSet, @errorCast(err)) };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_name(self: *const MyException) []const u8 {
|
|
||||||
return switch (self.err) {
|
|
||||||
ErrorSet.MyCustomError => errorNames[0],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_message(self: *const MyException) []const u8 {
|
|
||||||
return switch (self.err) {
|
|
||||||
ErrorSet.MyCustomError => errorMsgs[0],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _toString(self: *const MyException) []const u8 {
|
|
||||||
return switch (self.err) {
|
|
||||||
ErrorSet.MyCustomError => errorStrings(0),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const MyTypeWithException = struct {
|
|
||||||
pub const Exception = MyException;
|
|
||||||
|
|
||||||
pub fn constructor() MyTypeWithException {
|
|
||||||
return .{};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _withoutError(_: *const MyTypeWithException) MyException.ErrorSet!void {}
|
|
||||||
|
|
||||||
pub fn _withError(_: *const MyTypeWithException) MyException.ErrorSet!void {
|
|
||||||
return MyException.ErrorSet.MyCustomError;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _superSetError(_: *const MyTypeWithException) !void {
|
|
||||||
return MyException.ErrorSet.MyCustomError;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _outOfMemory(_: *const MyTypeWithException) !void {
|
|
||||||
return error.OutOfMemory;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const MyUnionType = struct {
|
|
||||||
pub const Choices = union(enum) {
|
|
||||||
color: []const u8,
|
|
||||||
number: usize,
|
|
||||||
boolean: bool,
|
|
||||||
obj1: *MyList,
|
|
||||||
obj2: MyUnionType,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn constructor() MyUnionType {
|
|
||||||
return .{};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _choices(_: *const MyUnionType, u: Choices) Choices {
|
|
||||||
return switch (u) {
|
|
||||||
.color => .{ .color = "nice" },
|
|
||||||
.number => |n| .{ .number = n + 10 },
|
|
||||||
.boolean => |b| .{ .boolean = !b },
|
|
||||||
.obj1 => |l| .{ .number = l.items.len },
|
|
||||||
.obj2 => .{ .color = "meta" },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const IterableU8 = Iterable(u8);
|
|
||||||
|
|
||||||
pub fn Iterable(comptime T: type) type {
|
|
||||||
return struct {
|
|
||||||
const Self = @This();
|
|
||||||
|
|
||||||
items: []T,
|
|
||||||
index: usize = 0,
|
|
||||||
|
|
||||||
pub fn init(items: []T) Self {
|
|
||||||
return .{ .items = items };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const Return = struct {
|
|
||||||
value: ?T,
|
|
||||||
done: bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn _next(self: *Self) Return {
|
|
||||||
if (self.items.len > self.index) {
|
|
||||||
const val = self.items[self.index];
|
|
||||||
self.index += 1;
|
|
||||||
return .{ .value = val, .done = false };
|
|
||||||
} else {
|
|
||||||
return .{ .value = null, .done = true };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const State = struct {
|
|
||||||
arena: Allocator,
|
|
||||||
};
|
|
||||||
|
|
||||||
const testing = @import("testing.zig");
|
|
||||||
test "JS: complex types" {
|
|
||||||
var arena = std.heap.ArenaAllocator.init(testing.allocator);
|
|
||||||
defer arena.deinit();
|
|
||||||
|
|
||||||
var runner = try testing.Runner(State, void, .{
|
|
||||||
MyList,
|
|
||||||
IterableU8,
|
|
||||||
MyVariadic,
|
|
||||||
MyErrorUnion,
|
|
||||||
MyException,
|
|
||||||
MyTypeWithException,
|
|
||||||
MyUnionType,
|
|
||||||
}).init(.{ .arena = arena.allocator() }, {});
|
|
||||||
|
|
||||||
defer runner.deinit();
|
|
||||||
|
|
||||||
try runner.testCases(&.{
|
|
||||||
.{ "let myList = new MyList(1, 2, 3);", "undefined" },
|
|
||||||
.{ "myList.first();", "1" },
|
|
||||||
.{ "let iter = myList[Symbol.iterator]();", "undefined" },
|
|
||||||
.{ "iter.next().value;", "1" },
|
|
||||||
.{ "iter.next().value;", "2" },
|
|
||||||
.{ "iter.next().value;", "3" },
|
|
||||||
.{ "iter.next().done;", "true" },
|
|
||||||
.{ "let arr = Array.from(myList);", "undefined" },
|
|
||||||
.{ "arr.length;", "3" },
|
|
||||||
.{ "arr[0];", "1" },
|
|
||||||
}, .{});
|
|
||||||
|
|
||||||
try runner.testCases(&.{
|
|
||||||
.{ "let myVariadic = new MyVariadic();", "undefined" },
|
|
||||||
.{ "myVariadic.len(true, false, true)", "3" },
|
|
||||||
.{ "myVariadic.first('a_str', true, false, true, false)", "true" },
|
|
||||||
.{ "myVariadic.last(true, false)", "false" },
|
|
||||||
.{ "myVariadic.empty()", "true" },
|
|
||||||
.{ "myVariadic.myListLen(myList)", "1" },
|
|
||||||
.{ "myVariadic.myListFirst(myList)", "1" },
|
|
||||||
}, .{});
|
|
||||||
|
|
||||||
try runner.testCases(&.{
|
|
||||||
.{ "var myErrorCstr = ''; try {new MyErrorUnion(true)} catch (error) {myErrorCstr = error}; myErrorCstr", "Error: MyError" },
|
|
||||||
.{ "let myErrorUnion = new MyErrorUnion(false);", "undefined" },
|
|
||||||
.{ "myErrorUnion.withoutError", "0" },
|
|
||||||
.{ "var myErrorGetter = ''; try {myErrorUnion.withError} catch (error) {myErrorGetter = error}; myErrorGetter", "Error: MyError" },
|
|
||||||
.{ "myErrorUnion.withoutError = true", "true" },
|
|
||||||
.{ "var myErrorSetter = ''; try {myErrorUnion.withError = true} catch (error) {myErrorSetter = error}; myErrorSetter", "Error: MyError" },
|
|
||||||
.{ "myErrorUnion.funcWithoutError()", "undefined" },
|
|
||||||
.{ "var myErrorFunc = ''; try {myErrorUnion.funcWithError()} catch (error) {myErrorFunc = error}; myErrorFunc", "Error: MyError" },
|
|
||||||
}, .{});
|
|
||||||
|
|
||||||
try runner.testCases(&.{
|
|
||||||
.{ "MyException.prototype.__proto__ === Error.prototype", "true" },
|
|
||||||
.{ "let myTypeWithException = new MyTypeWithException();", "undefined" },
|
|
||||||
.{ "myTypeWithException.withoutError()", "undefined" },
|
|
||||||
.{ "var myCustomError = ''; try {myTypeWithException.withError()} catch (error) {myCustomError = error}", "MyCustomError: Some custom message." },
|
|
||||||
.{ "myCustomError instanceof MyException", "true" },
|
|
||||||
.{ "myCustomError instanceof Error", "true" },
|
|
||||||
.{ "var mySuperError = ''; try {myTypeWithException.superSetError()} catch (error) {mySuperError = error}", "MyCustomError: Some custom message." },
|
|
||||||
.{ "var oomError = ''; try {myTypeWithException.outOfMemory()} catch (error) {oomError = error}; oomError", "Error: out of memory" },
|
|
||||||
}, .{});
|
|
||||||
|
|
||||||
try runner.testCases(&.{
|
|
||||||
.{ "var mut = new MyUnionType()", "undefined" },
|
|
||||||
.{ "mut.choices(3)", "13" },
|
|
||||||
.{ "mut.choices('blue')", "nice" },
|
|
||||||
.{ "mut.choices(true)", "false" },
|
|
||||||
.{ "mut.choices(false)", "true" },
|
|
||||||
.{ "mut.choices(mut)", "meta" },
|
|
||||||
.{ "mut.choices(myList)", "3" },
|
|
||||||
}, .{});
|
|
||||||
}
|
|
||||||
@@ -1,275 +0,0 @@
|
|||||||
// Copyright (C) 2023-2024 Lightpanda (Selecy SAS)
|
|
||||||
//
|
|
||||||
// Francis Bouvier <francis@lightpanda.io>
|
|
||||||
// Pierre Tachoire <pierre@lightpanda.io>
|
|
||||||
//
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Affero General Public License as
|
|
||||||
// published by the Free Software Foundation, either version 3 of the
|
|
||||||
// License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Affero General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
const std = @import("std");
|
|
||||||
const Allocator = std.mem.Allocator;
|
|
||||||
|
|
||||||
pub const Other = struct {
|
|
||||||
val: u8,
|
|
||||||
|
|
||||||
fn init(val: u8) Other {
|
|
||||||
return .{ .val = val };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _val(self: *const Other) u8 {
|
|
||||||
return self.val;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const OtherUnion = union(enum) {
|
|
||||||
Other: Other,
|
|
||||||
Bool: bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const MyObject = struct {
|
|
||||||
val: bool,
|
|
||||||
|
|
||||||
pub fn constructor(do_set: bool) MyObject {
|
|
||||||
return .{
|
|
||||||
.val = do_set,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn named_get(_: *const MyObject, name: []const u8, has_value: *bool) ?OtherUnion {
|
|
||||||
if (std.mem.eql(u8, name, "a")) {
|
|
||||||
has_value.* = true;
|
|
||||||
return .{ .Other = .{ .val = 4 } };
|
|
||||||
}
|
|
||||||
if (std.mem.eql(u8, name, "c")) {
|
|
||||||
has_value.* = true;
|
|
||||||
return .{ .Bool = true };
|
|
||||||
}
|
|
||||||
has_value.* = false;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_val(self: *const MyObject) bool {
|
|
||||||
return self.val;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_val(self: *MyObject, val: bool) void {
|
|
||||||
self.val = val;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const MyAPI = struct {
|
|
||||||
pub fn constructor() MyAPI {
|
|
||||||
return .{};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _obj(_: *const MyAPI) !MyObject {
|
|
||||||
return MyObject.constructor(true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const Parent = packed struct {
|
|
||||||
parent_id: i32 = 0,
|
|
||||||
|
|
||||||
pub fn get_parent(self: *const Parent) i32 {
|
|
||||||
return self.parent_id;
|
|
||||||
}
|
|
||||||
pub fn set_parent(self: *Parent, id: i32) void {
|
|
||||||
self.parent_id = id;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const Middle = struct {
|
|
||||||
pub const prototype = *Parent;
|
|
||||||
|
|
||||||
middle_id: i32 = 0,
|
|
||||||
_padding_1: u8 = 0,
|
|
||||||
_padding_2: u8 = 1,
|
|
||||||
_padding_3: u8 = 2,
|
|
||||||
proto: Parent,
|
|
||||||
|
|
||||||
pub fn constructor() Middle {
|
|
||||||
return .{
|
|
||||||
.middle_id = 0,
|
|
||||||
.proto = .{ .parent_id = 0 },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_middle(self: *const Middle) i32 {
|
|
||||||
return self.middle_id;
|
|
||||||
}
|
|
||||||
pub fn set_middle(self: *Middle, id: i32) void {
|
|
||||||
self.middle_id = id;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const Child = struct {
|
|
||||||
pub const prototype = *Middle;
|
|
||||||
|
|
||||||
child_id: i32 = 0,
|
|
||||||
_padding_1: u8 = 0,
|
|
||||||
proto: Middle,
|
|
||||||
|
|
||||||
pub fn constructor() Child {
|
|
||||||
return .{
|
|
||||||
.child_id = 0,
|
|
||||||
.proto = .{ .middle_id = 0, .proto = .{ .parent_id = 0 } },
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_child(self: *const Child) i32 {
|
|
||||||
return self.child_id;
|
|
||||||
}
|
|
||||||
pub fn set_child(self: *Child, id: i32) void {
|
|
||||||
self.child_id = id;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const MiddlePtr = packed struct {
|
|
||||||
pub const prototype = *Parent;
|
|
||||||
|
|
||||||
middle_id: i32 = 0,
|
|
||||||
_padding_1: u8 = 0,
|
|
||||||
_padding_2: u8 = 1,
|
|
||||||
_padding_3: u8 = 2,
|
|
||||||
proto: *Parent,
|
|
||||||
|
|
||||||
pub fn constructor(state: State) !MiddlePtr {
|
|
||||||
const parent = try state.arena.create(Parent);
|
|
||||||
parent.* = .{ .parent_id = 0 };
|
|
||||||
return .{
|
|
||||||
.middle_id = 0,
|
|
||||||
.proto = parent,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_middle(self: *const MiddlePtr) i32 {
|
|
||||||
return self.middle_id;
|
|
||||||
}
|
|
||||||
pub fn set_middle(self: *MiddlePtr, id: i32) void {
|
|
||||||
self.middle_id = id;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const ChildPtr = packed struct {
|
|
||||||
pub const prototype = *MiddlePtr;
|
|
||||||
|
|
||||||
child_id: i32 = 0,
|
|
||||||
_padding_1: u8 = 0,
|
|
||||||
_padding_2: u8 = 1,
|
|
||||||
proto: *MiddlePtr,
|
|
||||||
|
|
||||||
pub fn constructor(state: State) !ChildPtr {
|
|
||||||
const parent = try state.arena.create(Parent);
|
|
||||||
const middle = try state.arena.create(MiddlePtr);
|
|
||||||
|
|
||||||
parent.* = .{ .parent_id = 0 };
|
|
||||||
middle.* = .{ .middle_id = 0, .proto = parent };
|
|
||||||
return .{
|
|
||||||
.child_id = 0,
|
|
||||||
.proto = middle,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_child(self: *const ChildPtr) i32 {
|
|
||||||
return self.child_id;
|
|
||||||
}
|
|
||||||
pub fn set_child(self: *ChildPtr, id: i32) void {
|
|
||||||
self.child_id = id;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const State = struct {
|
|
||||||
arena: Allocator,
|
|
||||||
};
|
|
||||||
|
|
||||||
const testing = @import("testing.zig");
|
|
||||||
test "JS: object types" {
|
|
||||||
var arena = std.heap.ArenaAllocator.init(testing.allocator);
|
|
||||||
defer arena.deinit();
|
|
||||||
|
|
||||||
var runner = try testing.Runner(State, void, .{
|
|
||||||
Other,
|
|
||||||
MyObject,
|
|
||||||
MyAPI,
|
|
||||||
Parent,
|
|
||||||
Middle,
|
|
||||||
Child,
|
|
||||||
MiddlePtr,
|
|
||||||
ChildPtr,
|
|
||||||
}).init(.{ .arena = arena.allocator() }, {});
|
|
||||||
|
|
||||||
defer runner.deinit();
|
|
||||||
|
|
||||||
// v8 has 3 default "own" properties
|
|
||||||
const own_base = "3";
|
|
||||||
|
|
||||||
try runner.testCases(&.{
|
|
||||||
.{ "Object.getOwnPropertyNames(MyObject).length;", own_base },
|
|
||||||
.{ "let myObj = new MyObject(true);", "undefined" },
|
|
||||||
// check object property
|
|
||||||
.{ "myObj.a.val()", "4" },
|
|
||||||
.{ "myObj.b", "undefined" },
|
|
||||||
.{ "Object.getOwnPropertyNames(myObj).length;", "0" },
|
|
||||||
|
|
||||||
// check if setter (pointer) still works
|
|
||||||
.{ "myObj.val", "true" },
|
|
||||||
.{ "myObj.val = false", "false" },
|
|
||||||
.{ "myObj.val", "false" },
|
|
||||||
|
|
||||||
.{ "let myObj2 = new MyObject(false);", "undefined" },
|
|
||||||
.{ "myObj2.c", "true" },
|
|
||||||
}, .{});
|
|
||||||
|
|
||||||
try runner.testCases(&.{
|
|
||||||
.{ "let myAPI = new MyAPI();", "undefined" },
|
|
||||||
.{ "let myObjIndirect = myAPI.obj();", "undefined" },
|
|
||||||
// check object property
|
|
||||||
.{ "myObjIndirect.a.val()", "4" },
|
|
||||||
}, .{});
|
|
||||||
|
|
||||||
try runner.testCases(&.{
|
|
||||||
.{ "let m1 = new Middle();", null },
|
|
||||||
.{ "m1.middle = 2", null },
|
|
||||||
.{ "m1.parent = 3", null },
|
|
||||||
.{ "m1.middle", "2" },
|
|
||||||
.{ "m1.parent", "3" },
|
|
||||||
}, .{});
|
|
||||||
|
|
||||||
try runner.testCases(&.{
|
|
||||||
.{ "let c1 = new Child();", null },
|
|
||||||
.{ "c1.child = 1", null },
|
|
||||||
.{ "c1.middle = 2", null },
|
|
||||||
.{ "c1.parent = 3", null },
|
|
||||||
.{ "c1.child", "1" },
|
|
||||||
.{ "c1.middle", "2" },
|
|
||||||
.{ "c1.parent", "3" },
|
|
||||||
}, .{});
|
|
||||||
|
|
||||||
try runner.testCases(&.{
|
|
||||||
.{ "let m2 = new MiddlePtr();", null },
|
|
||||||
.{ "m2.middle = 2", null },
|
|
||||||
.{ "m2.parent = 3", null },
|
|
||||||
.{ "m2.middle", "2" },
|
|
||||||
.{ "m2.parent", "3" },
|
|
||||||
}, .{});
|
|
||||||
|
|
||||||
try runner.testCases(&.{
|
|
||||||
.{ "let c2 = new ChildPtr();", null },
|
|
||||||
.{ "c2.child = 1", null },
|
|
||||||
.{ "c2.middle = 2", null },
|
|
||||||
.{ "c2.parent = 3", null },
|
|
||||||
.{ "c2.child", "1" },
|
|
||||||
.{ "c2.middle", "2" },
|
|
||||||
.{ "c2.parent", "3" },
|
|
||||||
}, .{});
|
|
||||||
}
|
|
||||||
@@ -1,352 +0,0 @@
|
|||||||
// Copyright (C) 2023-2024 Lightpanda (Selecy SAS)
|
|
||||||
//
|
|
||||||
// Francis Bouvier <francis@lightpanda.io>
|
|
||||||
// Pierre Tachoire <pierre@lightpanda.io>
|
|
||||||
//
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Affero General Public License as
|
|
||||||
// published by the Free Software Foundation, either version 3 of the
|
|
||||||
// License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Affero General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
// TODO: use functions instead of "fake" struct once we handle function API generation
|
|
||||||
|
|
||||||
const Runner = testing.Runner(void, void, .{Primitives});
|
|
||||||
const Env = Runner.Env;
|
|
||||||
|
|
||||||
const Primitives = struct {
|
|
||||||
pub fn constructor() Primitives {
|
|
||||||
return .{};
|
|
||||||
}
|
|
||||||
|
|
||||||
// List of bytes (string)
|
|
||||||
pub fn _checkString(_: *const Primitives, v: []u8) []u8 {
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Integers signed
|
|
||||||
|
|
||||||
pub fn _checkI32(_: *const Primitives, v: i32) i32 {
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _checkI64(_: *const Primitives, v: i64) i64 {
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Integers unsigned
|
|
||||||
|
|
||||||
pub fn _checkU32(_: *const Primitives, v: u32) u32 {
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _checkU64(_: *const Primitives, v: u64) u64 {
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Floats
|
|
||||||
|
|
||||||
pub fn _checkF32(_: *const Primitives, v: f32) f32 {
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _checkF64(_: *const Primitives, v: f64) f64 {
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bool
|
|
||||||
pub fn _checkBool(_: *const Primitives, v: bool) bool {
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Undefined
|
|
||||||
// TODO: there is a bug with this function
|
|
||||||
// void paramater does not work => avoid for now
|
|
||||||
// pub fn _checkUndefined(_: *const Primitives, v: void) void {
|
|
||||||
// return v;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Null
|
|
||||||
pub fn _checkNullEmpty(_: *const Primitives, v: ?u32) bool {
|
|
||||||
return (v == null);
|
|
||||||
}
|
|
||||||
pub fn _checkNullNotEmpty(_: *const Primitives, v: ?u32) bool {
|
|
||||||
return (v != null);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optionals
|
|
||||||
pub fn _checkOptional(_: *const Primitives, _: ?u8, v: u8, _: ?u8, _: ?u8) u8 {
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
pub fn _checkNonOptional(_: *const Primitives, v: u8) u8 {
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
pub fn _checkOptionalReturn(_: *const Primitives) ?bool {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
pub fn _checkOptionalReturnNull(_: *const Primitives) ?bool {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
pub fn _checkOptionalReturnString(_: *const Primitives) ?[]const u8 {
|
|
||||||
return "ok";
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _echoString(_: *const Primitives, a: []const u8) []const u8 {
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _echoStringZ(_: *const Primitives, a: [:0]const u8) []const u8 {
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _int8(_: *const Primitives, arr: []i8) void {
|
|
||||||
for (arr) |*a| {
|
|
||||||
a.* -= @intCast(arr.len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _uint8(_: *const Primitives, arr: []u8) void {
|
|
||||||
for (arr) |*a| {
|
|
||||||
a.* += @intCast(arr.len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _returnEmptyUint8(_: *const Primitives) Env.TypedArray(u8) {
|
|
||||||
return .{ .values = &.{} };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _returnUint8(_: *const Primitives) Env.TypedArray(u8) {
|
|
||||||
return .{ .values = &.{ 10, 20, 250 } };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _returnInt8(_: *const Primitives) Env.TypedArray(i8) {
|
|
||||||
return .{ .values = &.{ 10, -20, -120 } };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _returnUint16(_: *const Primitives) Env.TypedArray(u16) {
|
|
||||||
return .{ .values = &.{ 10, 200, 2050 } };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _returnInt16(_: *const Primitives) Env.TypedArray(i16) {
|
|
||||||
return .{ .values = &.{ 10, -420, 0 } };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _returnUint32(_: *const Primitives) Env.TypedArray(u32) {
|
|
||||||
return .{ .values = &.{ 10, 2444343, 43432432 } };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _returnInt32(_: *const Primitives) Env.TypedArray(i32) {
|
|
||||||
return .{ .values = &.{ 10, -20, -495929123 } };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _returnUint64(_: *const Primitives) Env.TypedArray(u64) {
|
|
||||||
return .{ .values = &.{ 10, 495812375924, 0 } };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _returnInt64(_: *const Primitives) Env.TypedArray(i64) {
|
|
||||||
return .{ .values = &.{ 10, -49283838122, -2 } };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _returnFloat32(_: *const Primitives) Env.TypedArray(f32) {
|
|
||||||
return .{ .values = &.{ 1.1, -200.035, 0.0003 } };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _returnFloat64(_: *const Primitives) Env.TypedArray(f64) {
|
|
||||||
return .{ .values = &.{ 8881.22284, -4928.3838122, -0.00004 } };
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _int16(_: *const Primitives, arr: []i16) void {
|
|
||||||
for (arr) |*a| {
|
|
||||||
a.* -= @intCast(arr.len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _uint16(_: *const Primitives, arr: []u16) void {
|
|
||||||
for (arr) |*a| {
|
|
||||||
a.* += @intCast(arr.len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _int32(_: *const Primitives, arr: []i32) void {
|
|
||||||
for (arr) |*a| {
|
|
||||||
a.* -= @intCast(arr.len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _uint32(_: *const Primitives, arr: []u32) void {
|
|
||||||
for (arr) |*a| {
|
|
||||||
a.* += @intCast(arr.len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _int64(_: *const Primitives, arr: []i64) void {
|
|
||||||
for (arr) |*a| {
|
|
||||||
a.* -= @intCast(arr.len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn _uint64(_: *const Primitives, arr: []u64) void {
|
|
||||||
for (arr) |*a| {
|
|
||||||
a.* += @intCast(arr.len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const testing = @import("testing.zig");
|
|
||||||
test "JS: primitive types" {
|
|
||||||
var runner = try Runner.init({}, {});
|
|
||||||
defer runner.deinit();
|
|
||||||
|
|
||||||
// constructor
|
|
||||||
try runner.testCases(&.{
|
|
||||||
.{ "let p = new Primitives();", "undefined" },
|
|
||||||
}, .{});
|
|
||||||
|
|
||||||
// JS <> Native translation of primitive types
|
|
||||||
try runner.testCases(&.{
|
|
||||||
.{ "p.checkString('ok ascii') === 'ok ascii';", "true" },
|
|
||||||
.{ "p.checkString('ok emoji 🚀') === 'ok emoji 🚀';", "true" },
|
|
||||||
.{ "p.checkString('ok chinese 鿍') === 'ok chinese 鿍';", "true" },
|
|
||||||
|
|
||||||
// String (JS liberal cases)
|
|
||||||
.{ "p.checkString(1) === '1';", "true" },
|
|
||||||
.{ "p.checkString(null) === 'null';", "true" },
|
|
||||||
.{ "p.checkString(undefined) === 'undefined';", "true" },
|
|
||||||
|
|
||||||
// Integers
|
|
||||||
|
|
||||||
// signed
|
|
||||||
.{ "const min_i32 = -2147483648", "undefined" },
|
|
||||||
.{ "p.checkI32(min_i32) === min_i32;", "true" },
|
|
||||||
.{ "p.checkI32(min_i32-1) === min_i32-1;", "false" },
|
|
||||||
.{ "try { p.checkI32(9007199254740995n) } catch(e) { e instanceof TypeError; }", "true" },
|
|
||||||
|
|
||||||
// unsigned
|
|
||||||
.{ "const max_u32 = 4294967295", "undefined" },
|
|
||||||
.{ "p.checkU32(max_u32) === max_u32;", "true" },
|
|
||||||
.{ "p.checkU32(max_u32+1) === max_u32+1;", "false" },
|
|
||||||
|
|
||||||
// int64 (with BigInt)
|
|
||||||
.{ "const big_int = 9007199254740995n", "undefined" },
|
|
||||||
.{ "p.checkI64(big_int) === big_int", "true" },
|
|
||||||
.{ "p.checkU64(big_int) === big_int;", "true" },
|
|
||||||
.{ "p.checkI64(0) === 0;", "true" },
|
|
||||||
.{ "p.checkI64(-1) === -1;", "true" },
|
|
||||||
.{ "p.checkU64(0) === 0;", "true" },
|
|
||||||
|
|
||||||
// Floats
|
|
||||||
// use round 2 decimals for float to ensure equality
|
|
||||||
.{ "const r = function(x) {return Math.round(x * 100) / 100};", "undefined" },
|
|
||||||
.{ "const double = 10.02;", "undefined" },
|
|
||||||
.{ "r(p.checkF32(double)) === double;", "true" },
|
|
||||||
.{ "r(p.checkF64(double)) === double;", "true" },
|
|
||||||
|
|
||||||
// Bool
|
|
||||||
.{ "p.checkBool(true);", "true" },
|
|
||||||
.{ "p.checkBool(false);", "false" },
|
|
||||||
.{ "p.checkBool(0);", "false" },
|
|
||||||
.{ "p.checkBool(1);", "true" },
|
|
||||||
|
|
||||||
// Bool (JS liberal cases)
|
|
||||||
.{ "p.checkBool(null);", "false" },
|
|
||||||
.{ "p.checkBool(undefined);", "false" },
|
|
||||||
|
|
||||||
// Undefined
|
|
||||||
// see TODO on Primitives.checkUndefined
|
|
||||||
// .{ "p.checkUndefined(undefined) === undefined;", "true" },
|
|
||||||
|
|
||||||
// Null
|
|
||||||
.{ "p.checkNullEmpty(null);", "true" },
|
|
||||||
.{ "p.checkNullEmpty(undefined);", "true" },
|
|
||||||
.{ "p.checkNullNotEmpty(1);", "true" },
|
|
||||||
|
|
||||||
// Optional
|
|
||||||
.{ "p.checkOptional(null, 3);", "3" },
|
|
||||||
.{ "p.checkNonOptional();", "TypeError" },
|
|
||||||
.{ "p.checkOptionalReturn() === true;", "true" },
|
|
||||||
.{ "p.checkOptionalReturnNull() === null;", "true" },
|
|
||||||
.{ "p.checkOptionalReturnString() === 'ok';", "true" },
|
|
||||||
|
|
||||||
// strings
|
|
||||||
.{ "p.echoString('over 9000!');", "over 9000!" },
|
|
||||||
.{ "p.echoStringZ('Teg');", "Teg" },
|
|
||||||
}, .{});
|
|
||||||
|
|
||||||
// typed arrays
|
|
||||||
try runner.testCases(&.{
|
|
||||||
.{ "let empty_arr = new Int8Array([]);", "undefined" },
|
|
||||||
.{ "p.int8(empty_arr)", "undefined" },
|
|
||||||
.{ "empty_arr;", "" },
|
|
||||||
|
|
||||||
.{ "let arr_i8 = new Int8Array([-10, -20, -30]);", "undefined" },
|
|
||||||
.{ "p.int8(arr_i8)", "undefined" },
|
|
||||||
.{ "arr_i8;", "-13,-23,-33" },
|
|
||||||
|
|
||||||
.{ "let arr_u8 = new Uint8Array([10, 20, 30]);", "undefined" },
|
|
||||||
.{ "p.uint8(arr_u8)", "undefined" },
|
|
||||||
.{ "arr_u8;", "13,23,33" },
|
|
||||||
|
|
||||||
.{ "let arr_i16 = new Int16Array([-1000, -2000, -3000]);", "undefined" },
|
|
||||||
.{ "p.int16(arr_i16)", "undefined" },
|
|
||||||
.{ "arr_i16;", "-1003,-2003,-3003" },
|
|
||||||
|
|
||||||
.{ "let arr_u16 = new Uint16Array([1000, 2000, 3000]);", "undefined" },
|
|
||||||
.{ "p.uint16(arr_u16)", "undefined" },
|
|
||||||
.{ "arr_u16;", "1003,2003,3003" },
|
|
||||||
|
|
||||||
.{ "let arr_i32 = new Int32Array([-1000000, -2000000, -3000000]);", "undefined" },
|
|
||||||
.{ "p.int32(arr_i32)", "undefined" },
|
|
||||||
.{ "arr_i32;", "-1000003,-2000003,-3000003" },
|
|
||||||
|
|
||||||
.{ "let arr_u32 = new Uint32Array([1000000, 2000000, 3000000]);", "undefined" },
|
|
||||||
.{ "p.uint32(arr_u32)", "undefined" },
|
|
||||||
.{ "arr_u32;", "1000003,2000003,3000003" },
|
|
||||||
|
|
||||||
.{ "let arr_i64 = new BigInt64Array([-1000000000n, -2000000000n, -3000000000n]);", "undefined" },
|
|
||||||
.{ "p.int64(arr_i64)", "undefined" },
|
|
||||||
.{ "arr_i64;", "-1000000003,-2000000003,-3000000003" },
|
|
||||||
|
|
||||||
.{ "let arr_u64 = new BigUint64Array([1000000000n, 2000000000n, 3000000000n]);", "undefined" },
|
|
||||||
.{ "p.uint64(arr_u64)", "undefined" },
|
|
||||||
.{ "arr_u64;", "1000000003,2000000003,3000000003" },
|
|
||||||
|
|
||||||
.{ "try { p.int8(arr_u8) } catch(e) { e instanceof TypeError; }", "true" },
|
|
||||||
.{ "try { p.intu8(arr_i8) } catch(e) { e instanceof TypeError; }", "true" },
|
|
||||||
.{ "try { p.intu8(arr_u32) } catch(e) { e instanceof TypeError; }", "true" },
|
|
||||||
|
|
||||||
.{ "try { p.int16(arr_u8) } catch(e) { e instanceof TypeError; }", "true" },
|
|
||||||
.{ "try { p.intu16(arr_i16) } catch(e) { e instanceof TypeError; }", "true" },
|
|
||||||
.{ "try { p.int16(arr_i64) } catch(e) { e instanceof TypeError; }", "true" },
|
|
||||||
|
|
||||||
.{ "try { p.int32(arr_u32) } catch(e) { e instanceof TypeError; }", "true" },
|
|
||||||
.{ "try { p.intu32(arr_i32) } catch(e) { e instanceof TypeError; }", "true" },
|
|
||||||
.{ "try { p.intu32(arr_u32) } catch(e) { e instanceof TypeError; }", "true" },
|
|
||||||
|
|
||||||
.{ "try { p.int64(arr_u64) } catch(e) { e instanceof TypeError; }", "true" },
|
|
||||||
.{ "try { p.intu64(arr_i64) } catch(e) { e instanceof TypeError; }", "true" },
|
|
||||||
.{ "try { p.intu64(arr_u32) } catch(e) { e instanceof TypeError; }", "true" },
|
|
||||||
|
|
||||||
.{ "p.returnEmptyUint8()", "" },
|
|
||||||
.{ "p.returnUint8()", "10,20,250" },
|
|
||||||
.{ "p.returnInt8()", "10,-20,-120" },
|
|
||||||
.{ "p.returnUint16()", "10,200,2050" },
|
|
||||||
.{ "p.returnInt16()", "10,-420,0" },
|
|
||||||
.{ "p.returnUint32()", "10,2444343,43432432" },
|
|
||||||
.{ "p.returnInt32()", "10,-20,-495929123" },
|
|
||||||
.{ "p.returnUint64()", "10,495812375924,0" },
|
|
||||||
.{ "p.returnInt64()", "10,-49283838122,-2" },
|
|
||||||
.{ "p.returnFloat32()", "1.100000023841858,-200.03500366210938,0.0003000000142492354" },
|
|
||||||
.{ "p.returnFloat64()", "8881.22284,-4928.3838122,-0.00004" },
|
|
||||||
}, .{});
|
|
||||||
|
|
||||||
try runner.testCases(&.{
|
|
||||||
.{ "'foo\\\\:bar'", "foo\\:bar" },
|
|
||||||
}, .{});
|
|
||||||
}
|
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
// Copyright (C) 2023-2024 Lightpanda (Selecy SAS)
|
|
||||||
//
|
|
||||||
// Francis Bouvier <francis@lightpanda.io>
|
|
||||||
// Pierre Tachoire <pierre@lightpanda.io>
|
|
||||||
//
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Affero General Public License as
|
|
||||||
// published by the Free Software Foundation, either version 3 of the
|
|
||||||
// License, or (at your option) any later version.
|
|
||||||
//
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Affero General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
|
||||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
const std = @import("std");
|
|
||||||
const js = @import("js.zig");
|
|
||||||
const base = @import("../testing.zig");
|
|
||||||
const generate = @import("generate.zig");
|
|
||||||
|
|
||||||
pub const allocator = std.testing.allocator;
|
|
||||||
|
|
||||||
// Very similar to the JSRunner in src/testing.zig, but it isn't tied to the
|
|
||||||
// browser.Env or the *Page state
|
|
||||||
pub fn Runner(comptime State: type, comptime Global: type, comptime types: anytype) type {
|
|
||||||
const AdjustedTypes = if (Global == void) generate.Tuple(.{ types, DefaultGlobal }) else types;
|
|
||||||
|
|
||||||
return struct {
|
|
||||||
env: *Env,
|
|
||||||
js_context: *Env.JsContext,
|
|
||||||
executor: Env.ExecutionWorld,
|
|
||||||
|
|
||||||
pub const Env = js.Env(State, struct {
|
|
||||||
pub const Interfaces = AdjustedTypes;
|
|
||||||
});
|
|
||||||
|
|
||||||
const Self = @This();
|
|
||||||
|
|
||||||
pub fn init(state: State, global: Global) !*Self {
|
|
||||||
const self = try allocator.create(Self);
|
|
||||||
errdefer allocator.destroy(self);
|
|
||||||
|
|
||||||
self.env = try Env.init(allocator, &base.test_app.platform, .{});
|
|
||||||
errdefer self.env.deinit();
|
|
||||||
|
|
||||||
self.executor = try self.env.newExecutionWorld();
|
|
||||||
errdefer self.executor.deinit();
|
|
||||||
|
|
||||||
self.js_context = try self.executor.createJsContext(
|
|
||||||
if (Global == void) &default_global else global,
|
|
||||||
state,
|
|
||||||
null,
|
|
||||||
true,
|
|
||||||
null,
|
|
||||||
);
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deinit(self: *Self) void {
|
|
||||||
self.executor.deinit();
|
|
||||||
self.env.deinit();
|
|
||||||
allocator.destroy(self);
|
|
||||||
}
|
|
||||||
|
|
||||||
const RunOpts = struct {};
|
|
||||||
pub const Case = std.meta.Tuple(&.{ []const u8, ?[]const u8 });
|
|
||||||
pub fn testCases(self: *Self, cases: []const Case, _: RunOpts) !void {
|
|
||||||
for (cases, 0..) |case, i| {
|
|
||||||
var try_catch: Env.TryCatch = undefined;
|
|
||||||
try_catch.init(self.js_context);
|
|
||||||
defer try_catch.deinit();
|
|
||||||
|
|
||||||
const value = self.js_context.exec(case.@"0", null) catch |err| {
|
|
||||||
if (try try_catch.err(allocator)) |msg| {
|
|
||||||
defer allocator.free(msg);
|
|
||||||
if (isExpectedTypeError(case.@"1", msg)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
std.debug.print("{s}\n\nCase: {d}\n{s}\n", .{ msg, i + 1, case.@"0" });
|
|
||||||
}
|
|
||||||
return err;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (case.@"1") |expected| {
|
|
||||||
const actual = try value.toString(allocator);
|
|
||||||
defer allocator.free(actual);
|
|
||||||
if (std.mem.eql(u8, expected, actual) == false) {
|
|
||||||
std.debug.print("Expected:\n{s}\n\nGot:\n{s}\n\nCase: {d}\n{s}\n", .{ expected, actual, i + 1, case.@"0" });
|
|
||||||
return error.UnexpectedResult;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn isExpectedTypeError(expected_: ?[]const u8, msg: []const u8) bool {
|
|
||||||
const expected = expected_ orelse return false;
|
|
||||||
|
|
||||||
if (!std.mem.eql(u8, expected, "TypeError")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return std.mem.startsWith(u8, msg, "TypeError: ");
|
|
||||||
}
|
|
||||||
|
|
||||||
var default_global = DefaultGlobal{};
|
|
||||||
const DefaultGlobal = struct {};
|
|
||||||
@@ -37,7 +37,7 @@ pub fn reset() void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const App = @import("app.zig").App;
|
const App = @import("app.zig").App;
|
||||||
const Env = @import("browser/env.zig").Env;
|
const js = @import("browser/js/js.zig");
|
||||||
const Browser = @import("browser/browser.zig").Browser;
|
const Browser = @import("browser/browser.zig").Browser;
|
||||||
const Session = @import("browser/session.zig").Session;
|
const Session = @import("browser/session.zig").Session;
|
||||||
const parser = @import("browser/netsurf.zig");
|
const parser = @import("browser/netsurf.zig");
|
||||||
@@ -396,7 +396,7 @@ pub fn htmlRunner(file: []const u8) !void {
|
|||||||
page.arena = @import("root").tracking_allocator;
|
page.arena = @import("root").tracking_allocator;
|
||||||
|
|
||||||
const js_context = page.main_context;
|
const js_context = page.main_context;
|
||||||
var try_catch: Env.TryCatch = undefined;
|
var try_catch: js.TryCatch = undefined;
|
||||||
try_catch.init(js_context);
|
try_catch.init(js_context);
|
||||||
defer try_catch.deinit();
|
defer try_catch.deinit();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user