mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-07-31 01:36:15 -04:00
Merge branch 'main' into perf/skip-inline-style-alloc
This commit is contained in:
@@ -93,7 +93,7 @@ fn handleConnection(self: *TestHTTPServer, conn: std.net.Server.Connection) !voi
|
||||
error.BrokenPipe => {},
|
||||
else => {
|
||||
std.debug.print("test http error '{s}': {}\n", .{ req.head.target, err });
|
||||
try req.respond("server error", .{ .status = .internal_server_error });
|
||||
req.respond("server error", .{ .status = .internal_server_error }) catch {};
|
||||
},
|
||||
}
|
||||
return;
|
||||
|
||||
@@ -875,6 +875,15 @@ fn getInlineStyleProperty(el: *Element, property_name: String, frame: *Frame) ?*
|
||||
return style.asCSSStyleDeclaration().findProperty(property_name);
|
||||
}
|
||||
|
||||
/// Resolved value of an element's inline `style=` declaration for `property_name`,
|
||||
/// or null when the element has no such declaration. Reads the element's parsed
|
||||
/// inline style (the same source `el.style` exposes), so `getComputedStyle` and
|
||||
/// `el.style` agree on inline values instead of resolving them independently.
|
||||
pub fn inlineStyleValue(self: *StyleManager, el: *Element, property_name: String) ?[]const u8 {
|
||||
const property = getInlineStyleProperty(el, property_name, self.frame) orelse return null;
|
||||
return property._value.str();
|
||||
}
|
||||
|
||||
const testing = @import("../testing.zig");
|
||||
test "StyleManager: computeSpecificity: element selector" {
|
||||
// div -> (0, 0, 1)
|
||||
|
||||
@@ -198,3 +198,30 @@
|
||||
testing.expectEqual('1', divStyle.opacity);
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="computedStyleInline">
|
||||
{
|
||||
const div = document.createElement('div');
|
||||
div.style.cssText = 'text-transform: uppercase; font-weight: 700; color: rgb(1, 2, 3)';
|
||||
document.body.appendChild(div);
|
||||
|
||||
const cs = window.getComputedStyle(div);
|
||||
testing.expectEqual('uppercase', cs.getPropertyValue('text-transform'));
|
||||
testing.expectEqual('700', cs.getPropertyValue('font-weight'));
|
||||
testing.expectEqual('rgb(1, 2, 3)', cs.getPropertyValue('color'));
|
||||
testing.expectEqual('rgb(1, 2, 3)', div.style.getPropertyValue('color'));
|
||||
testing.expectEqual('', cs.getPropertyValue('letter-spacing'));
|
||||
|
||||
const plainDiv = document.createElement('div');
|
||||
document.body.appendChild(plainDiv);
|
||||
testing.expectEqual('block', window.getComputedStyle(plainDiv).getPropertyValue('display'));
|
||||
|
||||
// A normal declaration must not override an earlier !important one, and the
|
||||
// computed and inline (el.style) paths must agree on the resolved value.
|
||||
const impDiv = document.createElement('div');
|
||||
impDiv.setAttribute('style', 'color: red !important; color: blue');
|
||||
document.body.appendChild(impDiv);
|
||||
testing.expectEqual('red', window.getComputedStyle(impDiv).getPropertyValue('color'));
|
||||
testing.expectEqual('red', impDiv.style.getPropertyValue('color'));
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -49,7 +49,7 @@ pub fn init(element: ?*Element, is_computed: bool, frame: *Frame) !*CSSStyleDecl
|
||||
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, frame);
|
||||
try self.applyParsedDeclaration(declaration, frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -96,6 +96,11 @@ pub fn getPropertyValue(self: *const CSSStyleDeclaration, property_name: []const
|
||||
const prop = self.findProperty(wrapped) orelse {
|
||||
// Only return default values for computed styles
|
||||
if (self._is_computed) {
|
||||
if (self._element) |element| {
|
||||
// Resolve inline `style=` declarations through the element's
|
||||
// parsed inline style, so computed values match `el.style`.
|
||||
if (frame._style_manager.inlineStyleValue(element, wrapped)) |value| return value;
|
||||
}
|
||||
return getDefaultPropertyValue(self, wrapped);
|
||||
}
|
||||
return "";
|
||||
@@ -124,6 +129,19 @@ pub fn setProperty(self: *CSSStyleDeclaration, property_name: []const u8, value:
|
||||
try self.syncStyleAttribute(frame);
|
||||
}
|
||||
|
||||
/// Apply one declaration parsed from a `style=` block. Unlike the imperative
|
||||
/// setProperty path, within a single declaration block a normal declaration must
|
||||
/// not override an earlier !important one (CSS cascade precedence).
|
||||
fn applyParsedDeclaration(self: *CSSStyleDeclaration, declaration: CssParser.Declaration, frame: *Frame) !void {
|
||||
if (!declaration.important) {
|
||||
const normalized = normalizePropertyName(declaration.name, &frame.buf);
|
||||
if (self.findProperty(.wrap(normalized))) |existing| {
|
||||
if (existing._important) return;
|
||||
}
|
||||
}
|
||||
try self.setPropertyImpl(declaration.name, declaration.value, declaration.important, frame);
|
||||
}
|
||||
|
||||
fn setPropertyImpl(self: *CSSStyleDeclaration, property_name: []const u8, value: []const u8, important: bool, frame: *Frame) !void {
|
||||
if (value.len == 0) {
|
||||
_ = try self.removePropertyImpl(property_name, frame);
|
||||
@@ -207,7 +225,7 @@ pub fn setCssText(self: *CSSStyleDeclaration, text: []const u8, frame: *Frame) !
|
||||
// Parse and set new properties
|
||||
var it = CssParser.parseDeclarationsList(text);
|
||||
while (it.next()) |declaration| {
|
||||
try self.setPropertyImpl(declaration.name, declaration.value, declaration.important, frame);
|
||||
try self.applyParsedDeclaration(declaration, frame);
|
||||
}
|
||||
try self.syncStyleAttribute(frame);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user