diff --git a/src/browser/tests/mutation_observer/css_noop.html b/src/browser/tests/mutation_observer/css_noop.html
new file mode 100644
index 000000000..95b687d7b
--- /dev/null
+++ b/src/browser/tests/mutation_observer/css_noop.html
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/browser/webapi/css/CSSStyleDeclaration.zig b/src/browser/webapi/css/CSSStyleDeclaration.zig
index 65f04b4d3..012c50ae8 100644
--- a/src/browser/webapi/css/CSSStyleDeclaration.zig
+++ b/src/browser/webapi/css/CSSStyleDeclaration.zig
@@ -166,9 +166,9 @@ pub fn setProperty(self: *CSSStyleDeclaration, property_name: []const u8, value:
break :blk true;
} else false;
- try self.setPropertyImpl(property_name, value, important, frame);
-
- try self.syncStyleAttribute(frame);
+ if (try self.setPropertyImpl(property_name, value, important, frame)) {
+ try self.syncStyleAttribute(frame);
+ }
}
/// Apply one declaration parsed from a `style=` block. Unlike the imperative
@@ -181,7 +181,7 @@ fn applyParsedDeclaration(self: *CSSStyleDeclaration, declaration: CssParser.Dec
if (existing._important) return;
}
}
- try self.setPropertyImpl(declaration.name, declaration.value, declaration.important, frame);
+ _ = try self.setPropertyImpl(declaration.name, declaration.value, declaration.important, frame);
}
fn initOwnedString(allocator: Allocator, value: []const u8) !String {
@@ -190,10 +190,9 @@ fn initOwnedString(allocator: Allocator, value: []const u8) !String {
return String.wrap(try allocator.dupe(u8, value));
}
-fn setPropertyImpl(self: *CSSStyleDeclaration, property_name: []const u8, value: []const u8, important: bool, frame: *Frame) !void {
+fn setPropertyImpl(self: *CSSStyleDeclaration, property_name: []const u8, value: []const u8, important: bool, frame: *Frame) !bool {
if (value.len == 0) {
- _ = try self.removePropertyImpl(property_name, frame);
- return;
+ return (try self.removePropertyImpl(property_name, frame)) != null;
}
const normalized = normalizePropertyName(property_name, &frame.buf);
@@ -203,12 +202,13 @@ fn setPropertyImpl(self: *CSSStyleDeclaration, property_name: []const u8, value:
// Find existing property
if (self.findProperty(.wrap(normalized))) |existing| {
+ if (existing._value.eql(.wrap(normalized_value)) and existing._important == important) return false;
const allocator = frame._factory.storageAllocator();
const new_value = try initOwnedString(allocator, normalized_value);
existing._value.deinit(allocator);
existing._value = new_value;
existing._important = important;
- return;
+ return true;
}
// Create new property
@@ -219,20 +219,21 @@ fn setPropertyImpl(self: *CSSStyleDeclaration, property_name: []const u8, value:
._important = important,
});
self._properties.append(&prop._node);
+ return true;
}
pub fn removeProperty(self: *CSSStyleDeclaration, property_name: []const u8, frame: *Frame) ![]const u8 {
if (self._is_computed) {
return error.NoModificationAllowed;
}
- const result = try self.removePropertyImpl(property_name, frame);
+ const result = (try self.removePropertyImpl(property_name, frame)) orelse return "";
try self.syncStyleAttribute(frame);
return result;
}
-fn removePropertyImpl(self: *CSSStyleDeclaration, property_name: []const u8, frame: *Frame) ![]const u8 {
+fn removePropertyImpl(self: *CSSStyleDeclaration, property_name: []const u8, frame: *Frame) !?[]const u8 {
const normalized = normalizePropertyName(property_name, &frame.buf);
- const prop = self.findProperty(.wrap(normalized)) orelse return "";
+ const prop = self.findProperty(.wrap(normalized)) orelse return null;
// the value might not be on the heap (it could be inlined in the small string
// optimization), so we need to dupe it.
@@ -287,8 +288,9 @@ fn setFloat(self: *CSSStyleDeclaration, value_: ?[]const u8, frame: *Frame) !voi
if (self._is_computed) {
return error.NoModificationAllowed;
}
- try self.setPropertyImpl("float", value_ orelse "", false, frame);
- try self.syncStyleAttribute(frame);
+ if (try self.setPropertyImpl("float", value_ orelse "", false, frame)) {
+ try self.syncStyleAttribute(frame);
+ }
}
fn getCssText(self: *const CSSStyleDeclaration, frame: *Frame) ![]const u8 {
@@ -990,10 +992,10 @@ test "CSS property value storage is reused" {
var style = CSSStyleDeclaration{};
defer style.clearProperties(frame);
- try style.setPropertyImpl("transform", "translate3d(1px,0,0)", false, frame);
+ try testing.expect(try style.setPropertyImpl("transform", "translate3d(1px,0,0)", false, frame));
const first_ptr = style.findProperty(comptime .wrap("transform")).?._value.suffix.ptr;
- try style.setPropertyImpl("transform", "translate3d(2px,0,0)", false, frame);
- try style.setPropertyImpl("transform", "translate3d(3px,0,0)", false, frame);
+ try testing.expect(try style.setPropertyImpl("transform", "translate3d(2px,0,0)", false, frame));
+ try testing.expect(try style.setPropertyImpl("transform", "translate3d(3px,0,0)", false, frame));
const property = style.findProperty(comptime .wrap("transform")).?;
try testing.expectEqual(first_ptr, property._value.suffix.ptr);