diff --git a/src/browser/tests/css/stylesheet.html b/src/browser/tests/css/stylesheet.html
index abc1ed92..ec14f4fc 100644
--- a/src/browser/tests/css/stylesheet.html
+++ b/src/browser/tests/css/stylesheet.html
@@ -205,3 +205,54 @@
testing.expectEqual('', style.getPropertyPriority('content'));
}
+
+
+
+
diff --git a/src/browser/webapi/css/CSSStyleDeclaration.zig b/src/browser/webapi/css/CSSStyleDeclaration.zig
index 8380b6f3..5f61c607 100644
--- a/src/browser/webapi/css/CSSStyleDeclaration.zig
+++ b/src/browser/webapi/css/CSSStyleDeclaration.zig
@@ -33,10 +33,26 @@ _properties: std.DoublyLinkedList = .{},
_is_computed: bool = false,
pub fn init(element: ?*Element, is_computed: bool, page: *Page) !*CSSStyleDeclaration {
- return page._factory.create(CSSStyleDeclaration{
+ const self = try page._factory.create(CSSStyleDeclaration{
._element = element,
._is_computed = is_computed,
});
+
+ // Parse the element's existing style attribute into _properties so that
+ // subsequent JS reads and writes see all CSS properties, not just newly
+ // added ones. Computed styles have no inline attribute to parse.
+ if (!is_computed) {
+ if (element) |el| {
+ if (el.getAttributeSafe(comptime .wrap("style"))) |attr_value| {
+ var it = CssParser.parseDeclarationsList(attr_value);
+ while (it.next()) |declaration| {
+ try self.setPropertyImpl(declaration.name, declaration.value, declaration.important, page);
+ }
+ }
+ }
+ }
+
+ return self;
}
pub fn length(self: *const CSSStyleDeclaration) u32 {
@@ -76,15 +92,8 @@ pub fn getPropertyPriority(self: *const CSSStyleDeclaration, property_name: []co
}
pub fn setProperty(self: *CSSStyleDeclaration, property_name: []const u8, value: []const u8, priority_: ?[]const u8, page: *Page) !void {
- if (value.len == 0) {
- _ = try self.removeProperty(property_name, page);
- return;
- }
-
- const normalized = normalizePropertyName(property_name, &page.buf);
- const priority = priority_ orelse "";
-
// Validate priority
+ const priority = priority_ orelse "";
const important = if (priority.len > 0) blk: {
if (!std.ascii.eqlIgnoreCase(priority, "important")) {
return;
@@ -92,6 +101,19 @@ pub fn setProperty(self: *CSSStyleDeclaration, property_name: []const u8, value:
break :blk true;
} else false;
+ try self.setPropertyImpl(property_name, value, important, page);
+
+ try self.syncStyleAttribute(page);
+}
+
+fn setPropertyImpl(self: *CSSStyleDeclaration, property_name: []const u8, value: []const u8, important: bool, page: *Page) !void {
+ if (value.len == 0) {
+ _ = try self.removePropertyImpl(property_name, page);
+ return;
+ }
+
+ const normalized = normalizePropertyName(property_name, &page.buf);
+
// Find existing property
if (self.findProperty(normalized)) |existing| {
existing._value = try String.init(page.arena, value, .{});
@@ -110,6 +132,12 @@ pub fn setProperty(self: *CSSStyleDeclaration, property_name: []const u8, value:
}
pub fn removeProperty(self: *CSSStyleDeclaration, property_name: []const u8, page: *Page) ![]const u8 {
+ const result = try self.removePropertyImpl(property_name, page);
+ try self.syncStyleAttribute(page);
+ return result;
+}
+
+fn removePropertyImpl(self: *CSSStyleDeclaration, property_name: []const u8, page: *Page) ![]const u8 {
const normalized = normalizePropertyName(property_name, &page.buf);
const prop = self.findProperty(normalized) orelse return "";
@@ -121,12 +149,21 @@ pub fn removeProperty(self: *CSSStyleDeclaration, property_name: []const u8, pag
return old_value;
}
+// Serialize current properties back to the element's style attribute so that
+// DOM serialization (outerHTML, getAttribute) reflects JS-modified styles.
+fn syncStyleAttribute(self: *CSSStyleDeclaration, page: *Page) !void {
+ const element = self._element orelse return;
+ const css_text = try self.getCssText(page);
+ try element.setAttributeSafe(comptime .wrap("style"), .wrap(css_text), page);
+}
+
pub fn getFloat(self: *const CSSStyleDeclaration, page: *Page) []const u8 {
return self.getPropertyValue("float", page);
}
pub fn setFloat(self: *CSSStyleDeclaration, value_: ?[]const u8, page: *Page) !void {
- return self.setProperty("float", value_ orelse "", null, page);
+ try self.setPropertyImpl("float", value_ orelse "", false, page);
+ try self.syncStyleAttribute(page);
}
pub fn getCssText(self: *const CSSStyleDeclaration, page: *Page) ![]const u8 {
@@ -153,9 +190,9 @@ pub fn setCssText(self: *CSSStyleDeclaration, text: []const u8, page: *Page) !vo
// Parse and set new properties
var it = CssParser.parseDeclarationsList(text);
while (it.next()) |declaration| {
- const priority: ?[]const u8 = if (declaration.important) "important" else null;
- try self.setProperty(declaration.name, declaration.value, priority, page);
+ try self.setPropertyImpl(declaration.name, declaration.value, declaration.important, page);
}
+ try self.syncStyleAttribute(page);
}
pub fn format(self: *const CSSStyleDeclaration, writer: *std.Io.Writer) !void {