mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-29 15:13:28 +00:00
xhr: fix ProgressEvent implementation
This commit is contained in:
@@ -13,6 +13,16 @@ const DOMException = @import("../dom/exceptions.zig").DOMException;
|
|||||||
const EventTarget = @import("../dom/event_target.zig").EventTarget;
|
const EventTarget = @import("../dom/event_target.zig").EventTarget;
|
||||||
const EventTargetUnion = @import("../dom/event_target.zig").Union;
|
const EventTargetUnion = @import("../dom/event_target.zig").Union;
|
||||||
|
|
||||||
|
const xhr = @import("../xhr/xhr.zig");
|
||||||
|
|
||||||
|
// Event interfaces
|
||||||
|
pub const Interfaces = generate.Tuple(.{
|
||||||
|
Event,
|
||||||
|
xhr.ProgressEvent,
|
||||||
|
});
|
||||||
|
const Generated = generate.Union.compile(Interfaces);
|
||||||
|
pub const Union = Generated._union;
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#event
|
// https://dom.spec.whatwg.org/#event
|
||||||
pub const Event = struct {
|
pub const Event = struct {
|
||||||
pub const Self = parser.Event;
|
pub const Self = parser.Event;
|
||||||
@@ -28,6 +38,13 @@ pub const Event = struct {
|
|||||||
pub const _AT_TARGET = 2;
|
pub const _AT_TARGET = 2;
|
||||||
pub const _BUBBLING_PHASE = 3;
|
pub const _BUBBLING_PHASE = 3;
|
||||||
|
|
||||||
|
pub fn toInterface(evt: *parser.Event) !Union {
|
||||||
|
return switch (try parser.eventGetInternalType(evt)) {
|
||||||
|
.event => .{ .Event = evt },
|
||||||
|
.progress_event => .{ .ProgressEvent = @as(*xhr.ProgressEvent, @ptrCast(evt)).* },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn constructor(eventType: []const u8, opts: ?EventInit) !*parser.Event {
|
pub fn constructor(eventType: []const u8, opts: ?EventInit) !*parser.Event {
|
||||||
const event = try parser.eventCreate();
|
const event = try parser.eventCreate();
|
||||||
try parser.eventInit(event, eventType, opts orelse EventInit{});
|
try parser.eventInit(event, eventType, opts orelse EventInit{});
|
||||||
@@ -104,13 +121,6 @@ pub const Event = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Event interfaces
|
|
||||||
pub const Interfaces = generate.Tuple(.{
|
|
||||||
Event,
|
|
||||||
});
|
|
||||||
const Generated = generate.Union.compile(Interfaces);
|
|
||||||
pub const Union = Generated._union;
|
|
||||||
|
|
||||||
pub fn testExecFn(
|
pub fn testExecFn(
|
||||||
_: std.mem.Allocator,
|
_: std.mem.Allocator,
|
||||||
js_env: *jsruntime.Env,
|
js_env: *jsruntime.Env,
|
||||||
@@ -200,7 +210,7 @@ pub fn testExecFn(
|
|||||||
try checkCases(js_env, &legacy);
|
try checkCases(js_env, &legacy);
|
||||||
|
|
||||||
var remove = [_]Case{
|
var remove = [_]Case{
|
||||||
.{ .src = "var nb = 0; function cbk(event) { nb ++; }", .ex = "undefined" },
|
.{ .src = "var nb = 0; var evt = null; function cbk(event) { nb ++; evt=event; }", .ex = "undefined" },
|
||||||
.{ .src = "document.addEventListener('count', cbk)", .ex = "undefined" },
|
.{ .src = "document.addEventListener('count', cbk)", .ex = "undefined" },
|
||||||
.{ .src = "document.removeEventListener('count', cbk)", .ex = "undefined" },
|
.{ .src = "document.removeEventListener('count', cbk)", .ex = "undefined" },
|
||||||
.{ .src = "document.dispatchEvent(new Event('count'))", .ex = "true" },
|
.{ .src = "document.dispatchEvent(new Event('count'))", .ex = "true" },
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ const c = @cImport({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const Callback = @import("jsruntime").Callback;
|
const Callback = @import("jsruntime").Callback;
|
||||||
|
const EventToInterface = @import("events/event.zig").Event.toInterface;
|
||||||
|
|
||||||
// Vtable
|
// Vtable
|
||||||
// ------
|
// ------
|
||||||
@@ -449,6 +450,23 @@ pub fn eventPreventDefault(evt: *Event) !void {
|
|||||||
try DOMErr(err);
|
try DOMErr(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn eventGetInternalType(evt: *Event) !EventType {
|
||||||
|
var res: u32 = undefined;
|
||||||
|
const err = c._dom_event_get_internal_type(evt, &res);
|
||||||
|
try DOMErr(err);
|
||||||
|
return @enumFromInt(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn eventSetInternalType(evt: *Event, internal_type: EventType) !void {
|
||||||
|
const err = c._dom_event_set_internal_type(evt, @intFromEnum(internal_type));
|
||||||
|
try DOMErr(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const EventType = enum(u8) {
|
||||||
|
event = 0,
|
||||||
|
progress_event = 1,
|
||||||
|
};
|
||||||
|
|
||||||
// EventHandler
|
// EventHandler
|
||||||
fn event_handler_cbk(data: *anyopaque) *Callback {
|
fn event_handler_cbk(data: *anyopaque) *Callback {
|
||||||
const ptr: *align(@alignOf(*Callback)) anyopaque = @alignCast(data);
|
const ptr: *align(@alignOf(*Callback)) anyopaque = @alignCast(data);
|
||||||
@@ -459,7 +477,14 @@ const event_handler = struct {
|
|||||||
fn handle(event: ?*Event, data: ?*anyopaque) callconv(.C) void {
|
fn handle(event: ?*Event, data: ?*anyopaque) callconv(.C) void {
|
||||||
if (data) |d| {
|
if (data) |d| {
|
||||||
const func = event_handler_cbk(d);
|
const func = event_handler_cbk(d);
|
||||||
func.call(.{event}) catch unreachable;
|
|
||||||
|
if (event) |evt| {
|
||||||
|
func.call(.{
|
||||||
|
EventToInterface(evt) catch unreachable,
|
||||||
|
}) catch unreachable;
|
||||||
|
} else {
|
||||||
|
func.call(.{event}) catch unreachable;
|
||||||
|
}
|
||||||
// NOTE: we can not call func.deinit here
|
// NOTE: we can not call func.deinit here
|
||||||
// b/c the handler can be called several times
|
// b/c the handler can be called several times
|
||||||
// either on this dispatch event or in anoter one
|
// either on this dispatch event or in anoter one
|
||||||
@@ -652,7 +677,12 @@ pub const EventTargetTBase = struct {
|
|||||||
|
|
||||||
pub fn dispatch_event(et: [*c]c.dom_event_target, evt: ?*c.struct_dom_event, res: [*c]bool) callconv(.C) c.dom_exception {
|
pub fn dispatch_event(et: [*c]c.dom_event_target, evt: ?*c.struct_dom_event, res: [*c]bool) callconv(.C) c.dom_exception {
|
||||||
const self = @as(*Self, @ptrCast(et));
|
const self = @as(*Self, @ptrCast(et));
|
||||||
return c._dom_event_target_dispatch(et, &self.eti, evt, c.DOM_BUBBLING_PHASE, res);
|
// Set the event target to the target dispatched.
|
||||||
|
const e = c._dom_event_set_target(evt, et);
|
||||||
|
if (e != c.DOM_NO_ERR) {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
return c._dom_event_target_dispatch(et, &self.eti, evt, c.DOM_AT_TARGET, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_event_listener(et: [*c]c.dom_event_target, t: [*c]c.dom_string, l: ?*c.struct_dom_event_listener, capture: bool) callconv(.C) c.dom_exception {
|
pub fn remove_event_listener(et: [*c]c.dom_event_target, t: [*c]c.dom_string, l: ?*c.struct_dom_event_listener, capture: bool) callconv(.C) c.dom_exception {
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ pub const Interfaces = generate.Tuple(.{
|
|||||||
XMLHttpRequestEventTarget,
|
XMLHttpRequestEventTarget,
|
||||||
XMLHttpRequestUpload,
|
XMLHttpRequestUpload,
|
||||||
XMLHttpRequest,
|
XMLHttpRequest,
|
||||||
ProgressEvent,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
pub const XMLHttpRequestEventTarget = struct {
|
pub const XMLHttpRequestEventTarget = struct {
|
||||||
@@ -144,6 +143,7 @@ pub const ProgressEvent = struct {
|
|||||||
const event = try parser.eventCreate();
|
const event = try parser.eventCreate();
|
||||||
defer parser.eventDestroy(event);
|
defer parser.eventDestroy(event);
|
||||||
try parser.eventInit(event, eventType, .{});
|
try parser.eventInit(event, eventType, .{});
|
||||||
|
try parser.eventSetInternalType(event, .progress_event);
|
||||||
|
|
||||||
const o = opts orelse EventInit{};
|
const o = opts orelse EventInit{};
|
||||||
|
|
||||||
@@ -476,7 +476,6 @@ pub const XMLHttpRequest = struct {
|
|||||||
self.dispatchEvt("readystatechange");
|
self.dispatchEvt("readystatechange");
|
||||||
|
|
||||||
// dispatch a progress event load.
|
// dispatch a progress event load.
|
||||||
self.dispatchEvt("load");
|
|
||||||
self.dispatchProgressEvent("load", .{ .loaded = loaded, .total = total });
|
self.dispatchProgressEvent("load", .{ .loaded = loaded, .total = total });
|
||||||
// dispatch a progress event loadend.
|
// dispatch a progress event loadend.
|
||||||
self.dispatchProgressEvent("loadend", .{ .loaded = loaded, .total = total });
|
self.dispatchProgressEvent("loadend", .{ .loaded = loaded, .total = total });
|
||||||
@@ -585,7 +584,9 @@ pub fn testExecFn(
|
|||||||
// Each case executed waits for all loop callaback calls.
|
// Each case executed waits for all loop callaback calls.
|
||||||
// So the url has been retrieved.
|
// So the url has been retrieved.
|
||||||
.{ .src = "nb", .ex = "1" },
|
.{ .src = "nb", .ex = "1" },
|
||||||
// .{ .src = "evt.__proto__.constructor.name", .ex = "ProgressEvent" },
|
.{ .src = "evt.type", .ex = "load" },
|
||||||
|
.{ .src = "evt.loaded > 0", .ex = "true" },
|
||||||
|
.{ .src = "evt instanceof ProgressEvent", .ex = "true" },
|
||||||
.{ .src = "req.status", .ex = "200" },
|
.{ .src = "req.status", .ex = "200" },
|
||||||
.{ .src = "req.statusText", .ex = "OK" },
|
.{ .src = "req.statusText", .ex = "OK" },
|
||||||
.{ .src = "req.getResponseHeader('Content-Type')", .ex = "text/html; charset=UTF-8" },
|
.{ .src = "req.getResponseHeader('Content-Type')", .ex = "text/html; charset=UTF-8" },
|
||||||
@@ -597,7 +598,12 @@ pub fn testExecFn(
|
|||||||
var progress_event = [_]Case{
|
var progress_event = [_]Case{
|
||||||
.{ .src = "let pevt = new ProgressEvent('foo');", .ex = "undefined" },
|
.{ .src = "let pevt = new ProgressEvent('foo');", .ex = "undefined" },
|
||||||
.{ .src = "pevt.loaded", .ex = "0" },
|
.{ .src = "pevt.loaded", .ex = "0" },
|
||||||
.{ .src = "pevt.__proto__.constructor.name", .ex = "ProgressEvent" },
|
.{ .src = "pevt instanceof ProgressEvent", .ex = "true" },
|
||||||
|
.{ .src = "var nnb = 0; var eevt = null; function ccbk(event) { nnb ++; eevt = event; }", .ex = "undefined" },
|
||||||
|
.{ .src = "document.addEventListener('foo', ccbk)", .ex = "undefined" },
|
||||||
|
.{ .src = "document.dispatchEvent(pevt)", .ex = "true" },
|
||||||
|
.{ .src = "eevt.type", .ex = "foo" },
|
||||||
|
.{ .src = "eevt instanceof ProgressEvent", .ex = "true" },
|
||||||
};
|
};
|
||||||
try checkCases(js_env, &progress_event);
|
try checkCases(js_env, &progress_event);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user