mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-12-16 08:18:59 +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,
|
.url = remote_url orelse page.url,
|
||||||
.mode = blk: {
|
.mode = blk: {
|
||||||
if (source == .@"inline") {
|
if (source == .@"inline") {
|
||||||
// inline modules are deferred, all other inline scripts have a
|
break :blk .normal;
|
||||||
// normal execution flow
|
|
||||||
break :blk if (kind == .module) .@"defer" else .normal;
|
|
||||||
}
|
}
|
||||||
if (element.getAttributeSafe("async") != null) {
|
if (element.getAttributeSafe("async") != null) {
|
||||||
break :blk .async;
|
break :blk .async;
|
||||||
}
|
}
|
||||||
if (element.getAttributeSafe("defer") != null) {
|
if (kind == .module or element.getAttributeSafe("defer") != null) {
|
||||||
break :blk .@"defer";
|
break :blk .@"defer";
|
||||||
}
|
}
|
||||||
break :blk .normal;
|
break :blk .normal;
|
||||||
|
|||||||
@@ -122,13 +122,16 @@
|
|||||||
testing.expectEqual(0, callbackCalls.length);
|
testing.expectEqual(0, callbackCalls.length);
|
||||||
|
|
||||||
customElements.define('upgrade-attr-element', UpgradeAttrElement);
|
customElements.define('upgrade-attr-element', UpgradeAttrElement);
|
||||||
testing.expectEqual(0, callbackCalls.length);
|
|
||||||
|
|
||||||
el.setAttribute('existing', 'after-upgrade');
|
|
||||||
testing.expectEqual(1, callbackCalls.length);
|
testing.expectEqual(1, callbackCalls.length);
|
||||||
testing.expectEqual('existing', callbackCalls[0].name);
|
testing.expectEqual('existing', callbackCalls[0].name);
|
||||||
testing.expectEqual('before-upgrade', callbackCalls[0].oldValue);
|
testing.expectEqual(null, callbackCalls[0].oldValue);
|
||||||
testing.expectEqual('after-upgrade', callbackCalls[0].newValue);
|
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);
|
customElements.upgrade(elem);
|
||||||
testing.expectEqual(1, alreadyUpgradedCalled);
|
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>
|
</script>
|
||||||
|
|||||||
@@ -18,10 +18,13 @@
|
|||||||
|
|
||||||
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 js = @import("../js/js.zig");
|
||||||
const Page = @import("../Page.zig");
|
const Page = @import("../Page.zig");
|
||||||
const Element = @import("Element.zig");
|
|
||||||
const Node = @import("Node.zig");
|
const Node = @import("Node.zig");
|
||||||
|
const Element = @import("Element.zig");
|
||||||
|
const Custom = @import("element/html/Custom.zig");
|
||||||
const CustomElementDefinition = @import("CustomElementDefinition.zig");
|
const CustomElementDefinition = @import("CustomElementDefinition.zig");
|
||||||
|
|
||||||
const CustomElementRegistry = @This();
|
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 {
|
fn upgradeElement(self: *CustomElementRegistry, element: *Element, page: *Page) !void {
|
||||||
const Custom = @import("element/html/Custom.zig");
|
|
||||||
|
|
||||||
const custom = element.is(Custom) orelse {
|
const custom = element.is(Custom) orelse {
|
||||||
return Custom.checkAndAttachBuiltIn(element, page);
|
return Custom.checkAndAttachBuiltIn(element, page);
|
||||||
};
|
};
|
||||||
@@ -133,7 +134,7 @@ fn upgradeElement(self: *CustomElementRegistry, element: *Element, page: *Page)
|
|||||||
try upgradeCustomElement(custom, definition, 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;
|
custom._definition = definition;
|
||||||
|
|
||||||
// Reset callback flags since this is a fresh upgrade
|
// 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;
|
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()) {
|
if (node.isConnected()) {
|
||||||
custom.invokeConnectedCallback(page);
|
custom.invokeConnectedCallback(page);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -272,9 +272,9 @@ pub fn setClassName(self: *Element, value: []const u8, page: *Page) !void {
|
|||||||
return self.setAttributeSafe("class", value, page);
|
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 .{};
|
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 {
|
pub fn getAttribute(self: *const Element, name: []const u8, page: *Page) !?[]const u8 {
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ _history: History,
|
|||||||
_storage_bucket: *storage.Bucket,
|
_storage_bucket: *storage.Bucket,
|
||||||
_on_load: ?js.Function = null,
|
_on_load: ?js.Function = null,
|
||||||
_on_error: ?js.Function = null, // TODO: invoke on error?
|
_on_error: ?js.Function = null, // TODO: invoke on error?
|
||||||
|
_on_unhandled_rejection: ?js.Function = null, // TODO: invoke on error
|
||||||
_location: *Location,
|
_location: *Location,
|
||||||
_timer_id: u30 = 0,
|
_timer_id: u30 = 0,
|
||||||
_timers: std.AutoHashMapUnmanaged(u32, *ScheduleCallback) = .{},
|
_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 {
|
pub fn fetch(_: *const Window, input: Fetch.Input, page: *Page) !js.Promise {
|
||||||
return Fetch.init(input, page);
|
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 customElements = bridge.accessor(Window.getCustomElements, null, .{ .cache = "customElements" });
|
||||||
pub const onload = bridge.accessor(Window.getOnLoad, Window.setOnLoad, .{});
|
pub const onload = bridge.accessor(Window.getOnLoad, Window.setOnLoad, .{});
|
||||||
pub const onerror = bridge.accessor(Window.getOnError, Window.getOnError, .{});
|
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 fetch = bridge.function(Window.fetch, .{});
|
||||||
pub const queueMicrotask = bridge.function(Window.queueMicrotask, .{});
|
pub const queueMicrotask = bridge.function(Window.queueMicrotask, .{});
|
||||||
pub const setTimeout = bridge.function(Window.setTimeout, .{});
|
pub const setTimeout = bridge.function(Window.setTimeout, .{});
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ const Request = @import("Request.zig");
|
|||||||
const Response = @import("Response.zig");
|
const Response = @import("Response.zig");
|
||||||
|
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
|
const IS_DEBUG = @import("builtin").mode == .Debug;
|
||||||
|
|
||||||
const Fetch = @This();
|
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 http_client = page._session.browser.http_client;
|
||||||
const headers = try http_client.newHeaders();
|
const headers = try http_client.newHeaders();
|
||||||
|
|
||||||
|
if (comptime IS_DEBUG) {
|
||||||
|
log.debug(.http, "fetch", .{ .url = request._url });
|
||||||
|
}
|
||||||
|
|
||||||
try http_client.request(.{
|
try http_client.request(.{
|
||||||
.ctx = fetch,
|
.ctx = fetch,
|
||||||
.url = request._url,
|
.url = request._url,
|
||||||
|
|||||||
@@ -19,8 +19,6 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const js = @import("../../js/js.zig");
|
const js = @import("../../js/js.zig");
|
||||||
|
|
||||||
const IS_DEBUG = @import("builtin").mode == .Debug;
|
|
||||||
|
|
||||||
const log = @import("../../../log.zig");
|
const log = @import("../../../log.zig");
|
||||||
const Http = @import("../../../http/Http.zig");
|
const Http = @import("../../../http/Http.zig");
|
||||||
|
|
||||||
@@ -32,6 +30,7 @@ const EventTarget = @import("../EventTarget.zig");
|
|||||||
const XMLHttpRequestEventTarget = @import("XMLHttpRequestEventTarget.zig");
|
const XMLHttpRequestEventTarget = @import("XMLHttpRequestEventTarget.zig");
|
||||||
|
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
|
const IS_DEBUG = @import("builtin").mode == .Debug;
|
||||||
|
|
||||||
const XMLHttpRequest = @This();
|
const XMLHttpRequest = @This();
|
||||||
_page: *Page,
|
_page: *Page,
|
||||||
|
|||||||
Reference in New Issue
Block a user