mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-12-15 15:58:57 +00:00
call AttributeChangedCallback on upgrade
This commit is contained in:
@@ -215,14 +215,12 @@ pub fn addFromElement(self: *ScriptManager, script_element: *Element.Html.Script
|
||||
.url = remote_url orelse page.url,
|
||||
.mode = blk: {
|
||||
if (source == .@"inline") {
|
||||
// inline modules are deferred, all other inline scripts have a
|
||||
// normal execution flow
|
||||
break :blk if (kind == .module) .@"defer" else .normal;
|
||||
break :blk .normal;
|
||||
}
|
||||
if (element.getAttributeSafe("async") != null) {
|
||||
break :blk .async;
|
||||
}
|
||||
if (element.getAttributeSafe("defer") != null) {
|
||||
if (kind == .module or element.getAttributeSafe("defer") != null) {
|
||||
break :blk .@"defer";
|
||||
}
|
||||
break :blk .normal;
|
||||
|
||||
@@ -122,13 +122,16 @@
|
||||
testing.expectEqual(0, callbackCalls.length);
|
||||
|
||||
customElements.define('upgrade-attr-element', UpgradeAttrElement);
|
||||
testing.expectEqual(0, callbackCalls.length);
|
||||
|
||||
el.setAttribute('existing', 'after-upgrade');
|
||||
testing.expectEqual(1, callbackCalls.length);
|
||||
testing.expectEqual('existing', callbackCalls[0].name);
|
||||
testing.expectEqual('before-upgrade', callbackCalls[0].oldValue);
|
||||
testing.expectEqual('after-upgrade', callbackCalls[0].newValue);
|
||||
testing.expectEqual(null, callbackCalls[0].oldValue);
|
||||
testing.expectEqual('before-upgrade', callbackCalls[0].newValue);
|
||||
|
||||
el.setAttribute('existing', 'after-upgrade');
|
||||
testing.expectEqual(2, callbackCalls.length);
|
||||
testing.expectEqual('existing', callbackCalls[1].name);
|
||||
testing.expectEqual('before-upgrade', callbackCalls[1].oldValue);
|
||||
testing.expectEqual('after-upgrade', callbackCalls[1].newValue);
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -151,4 +151,34 @@
|
||||
customElements.upgrade(elem);
|
||||
testing.expectEqual(1, alreadyUpgradedCalled);
|
||||
}
|
||||
|
||||
{
|
||||
let attributeChangedCalls = [];
|
||||
|
||||
class UpgradeWithAttrs extends HTMLElement {
|
||||
static get observedAttributes() {
|
||||
return ['data-foo', 'data-bar'];
|
||||
}
|
||||
|
||||
attributeChangedCallback(name, oldValue, newValue) {
|
||||
attributeChangedCalls.push({ name, oldValue, newValue });
|
||||
}
|
||||
}
|
||||
|
||||
const container = document.createElement('div');
|
||||
container.innerHTML = '<upgrade-with-attrs data-foo="hello" data-bar="world"></upgrade-with-attrs>';
|
||||
document.body.appendChild(container);
|
||||
|
||||
testing.expectEqual(0, attributeChangedCalls.length);
|
||||
|
||||
customElements.define('upgrade-with-attrs', UpgradeWithAttrs);
|
||||
|
||||
testing.expectEqual(2, attributeChangedCalls.length);
|
||||
testing.expectEqual('data-foo', attributeChangedCalls[0].name);
|
||||
testing.expectEqual(null, attributeChangedCalls[0].oldValue);
|
||||
testing.expectEqual('hello', attributeChangedCalls[0].newValue);
|
||||
testing.expectEqual('data-bar', attributeChangedCalls[1].name);
|
||||
testing.expectEqual(null, attributeChangedCalls[1].oldValue);
|
||||
testing.expectEqual('world', attributeChangedCalls[1].newValue);
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -18,10 +18,13 @@
|
||||
|
||||
const std = @import("std");
|
||||
const log = @import("../../log.zig");
|
||||
|
||||
const js = @import("../js/js.zig");
|
||||
const Page = @import("../Page.zig");
|
||||
const Element = @import("Element.zig");
|
||||
|
||||
const Node = @import("Node.zig");
|
||||
const Element = @import("Element.zig");
|
||||
const Custom = @import("element/html/Custom.zig");
|
||||
const CustomElementDefinition = @import("CustomElementDefinition.zig");
|
||||
|
||||
const CustomElementRegistry = @This();
|
||||
@@ -119,8 +122,6 @@ fn upgradeNode(self: *CustomElementRegistry, node: *Node, page: *Page) !void {
|
||||
}
|
||||
|
||||
fn upgradeElement(self: *CustomElementRegistry, element: *Element, page: *Page) !void {
|
||||
const Custom = @import("element/html/Custom.zig");
|
||||
|
||||
const custom = element.is(Custom) orelse {
|
||||
return Custom.checkAndAttachBuiltIn(element, page);
|
||||
};
|
||||
@@ -133,7 +134,7 @@ fn upgradeElement(self: *CustomElementRegistry, element: *Element, page: *Page)
|
||||
try upgradeCustomElement(custom, definition, page);
|
||||
}
|
||||
|
||||
fn upgradeCustomElement(custom: *@import("element/html/Custom.zig"), definition: *CustomElementDefinition, page: *Page) !void {
|
||||
fn upgradeCustomElement(custom: *Custom, definition: *CustomElementDefinition, page: *Page) !void {
|
||||
custom._definition = definition;
|
||||
|
||||
// Reset callback flags since this is a fresh upgrade
|
||||
@@ -151,6 +152,15 @@ fn upgradeCustomElement(custom: *@import("element/html/Custom.zig"), definition:
|
||||
return error.CustomElementUpgradeFailed;
|
||||
};
|
||||
|
||||
// Invoke attributeChangedCallback for existing observed attributes
|
||||
var attr_it = custom.asElement().attributeIterator();
|
||||
while (attr_it.next()) |attr| {
|
||||
const name = attr._name.str();
|
||||
if (definition.isAttributeObserved(name)) {
|
||||
custom.invokeAttributeChangedCallback(name, null, attr._value.str(), page);
|
||||
}
|
||||
}
|
||||
|
||||
if (node.isConnected()) {
|
||||
custom.invokeConnectedCallback(page);
|
||||
}
|
||||
|
||||
@@ -272,9 +272,9 @@ pub fn setClassName(self: *Element, value: []const u8, page: *Page) !void {
|
||||
return self.setAttributeSafe("class", value, page);
|
||||
}
|
||||
|
||||
pub fn attributeIterator(self: *Element) Attribute.Iterator {
|
||||
pub fn attributeIterator(self: *Element) Attribute.InnerIterator {
|
||||
const attributes = self._attributes orelse return .{};
|
||||
return attributes.iterator(self);
|
||||
return attributes.iterator();
|
||||
}
|
||||
|
||||
pub fn getAttribute(self: *const Element, name: []const u8, page: *Page) !?[]const u8 {
|
||||
|
||||
@@ -54,6 +54,7 @@ _history: History,
|
||||
_storage_bucket: *storage.Bucket,
|
||||
_on_load: ?js.Function = null,
|
||||
_on_error: ?js.Function = null, // TODO: invoke on error?
|
||||
_on_unhandled_rejection: ?js.Function = null, // TODO: invoke on error
|
||||
_location: *Location,
|
||||
_timer_id: u30 = 0,
|
||||
_timers: std.AutoHashMapUnmanaged(u32, *ScheduleCallback) = .{},
|
||||
@@ -143,6 +144,18 @@ pub fn setOnError(self: *Window, cb_: ?js.Function) !void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getOnUnhandledRejection(self: *const Window) ?js.Function {
|
||||
return self._on_unhandled_rejection;
|
||||
}
|
||||
|
||||
pub fn setOnUnhandledRejection(self: *Window, cb_: ?js.Function) !void {
|
||||
if (cb_) |cb| {
|
||||
self._on_unhandled_rejection = cb;
|
||||
} else {
|
||||
self._on_unhandled_rejection = null;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fetch(_: *const Window, input: Fetch.Input, page: *Page) !js.Promise {
|
||||
return Fetch.init(input, page);
|
||||
}
|
||||
@@ -390,6 +403,7 @@ pub const JsApi = struct {
|
||||
pub const customElements = bridge.accessor(Window.getCustomElements, null, .{ .cache = "customElements" });
|
||||
pub const onload = bridge.accessor(Window.getOnLoad, Window.setOnLoad, .{});
|
||||
pub const onerror = bridge.accessor(Window.getOnError, Window.getOnError, .{});
|
||||
pub const onunhandledrejection = bridge.accessor(Window.getOnUnhandledRejection, Window.setOnUnhandledRejection, .{});
|
||||
pub const fetch = bridge.function(Window.fetch, .{});
|
||||
pub const queueMicrotask = bridge.function(Window.queueMicrotask, .{});
|
||||
pub const setTimeout = bridge.function(Window.setTimeout, .{});
|
||||
|
||||
@@ -29,6 +29,7 @@ const Request = @import("Request.zig");
|
||||
const Response = @import("Response.zig");
|
||||
|
||||
const Allocator = std.mem.Allocator;
|
||||
const IS_DEBUG = @import("builtin").mode == .Debug;
|
||||
|
||||
const Fetch = @This();
|
||||
|
||||
@@ -54,6 +55,10 @@ pub fn init(input: Input, page: *Page) !js.Promise {
|
||||
const http_client = page._session.browser.http_client;
|
||||
const headers = try http_client.newHeaders();
|
||||
|
||||
if (comptime IS_DEBUG) {
|
||||
log.debug(.http, "fetch", .{ .url = request._url });
|
||||
}
|
||||
|
||||
try http_client.request(.{
|
||||
.ctx = fetch,
|
||||
.url = request._url,
|
||||
|
||||
@@ -19,8 +19,6 @@
|
||||
const std = @import("std");
|
||||
const js = @import("../../js/js.zig");
|
||||
|
||||
const IS_DEBUG = @import("builtin").mode == .Debug;
|
||||
|
||||
const log = @import("../../../log.zig");
|
||||
const Http = @import("../../../http/Http.zig");
|
||||
|
||||
@@ -32,6 +30,7 @@ const EventTarget = @import("../EventTarget.zig");
|
||||
const XMLHttpRequestEventTarget = @import("XMLHttpRequestEventTarget.zig");
|
||||
|
||||
const Allocator = std.mem.Allocator;
|
||||
const IS_DEBUG = @import("builtin").mode == .Debug;
|
||||
|
||||
const XMLHttpRequest = @This();
|
||||
_page: *Page,
|
||||
|
||||
Reference in New Issue
Block a user