diff --git a/src/browser/css/Parser.zig b/src/browser/css/Parser.zig index 401baecb..53488d96 100644 --- a/src/browser/css/Parser.zig +++ b/src/browser/css/Parser.zig @@ -306,6 +306,7 @@ pub fn parseStylesheet(input: []const u8) RulesIterator { pub const RulesIterator = struct { input: []const u8, stream: TokenStream, + has_skipped_at_rule: bool = false, pub fn init(input: []const u8) RulesIterator { return .{ @@ -358,6 +359,7 @@ pub const RulesIterator = struct { } if (peeked.token == .at_keyword) { + self.has_skipped_at_rule = true; self.skipAtRule(); selector_start = null; selector_end = null; diff --git a/src/browser/webapi/css/CSSStyleSheet.zig b/src/browser/webapi/css/CSSStyleSheet.zig index 52dcbf21..00764d15 100644 --- a/src/browser/webapi/css/CSSStyleSheet.zig +++ b/src/browser/webapi/css/CSSStyleSheet.zig @@ -76,10 +76,11 @@ pub fn insertRule(self: *CSSStyleSheet, rule: []const u8, maybe_index: ?u32, pag const index = maybe_index orelse 0; var it = Parser.parseStylesheet(rule); const parsed_rule = it.next() orelse { - const trimmed = std.mem.trimLeft(u8, rule, &std.ascii.whitespace); - if (std.mem.startsWith(u8, trimmed, "@")) { - // At-rules (like @keyframes) are currently skipped by the parser. - // Returning the index simulates successful insertion without crashing. + if (it.has_skipped_at_rule) { + // Lightpanda currently skips at-rules (e.g., @keyframes, @media) in its + // CSS parser. To prevent JS apps (like Expo/Reanimated) from crashing + // during initialization, we simulate a successful insertion by returning + // the requested index. return index; } return error.SyntaxError;