9 Commits 28d5d982ce ... 743f8a3a0a

Tác giả SHA1 Thông báo Ngày
  Andrew Kaster 743f8a3a0a CMake: Add macro to wrap C++ command line definitions for swiftc 1 tuần trước cách đây
  Andrew Kaster 8fd81c3338 LibGC+LibWeb+LibJS: Remove workaround for Swift boolean bitfield issue 1 tuần trước cách đây
  Tim Ledbetter e73438e82c LibWeb: Clamp grayscale, invert, filter and opacity filter values to 1 1 tuần trước cách đây
  Tim Ledbetter e5f21b2f9c LibWeb: Set blur filter radius to 0px if omitted 1 tuần trước cách đây
  Tim Ledbetter 2ee86d1e18 LibWeb: Set hue-rotate angle to 0 degrees if omitted 1 tuần trước cách đây
  Tim Ledbetter 61f76c7ec5 LibWeb: Set color filter value to 1 if omitted 1 tuần trước cách đây
  Tim Ledbetter 46411295d6 LibWeb: Serialize drop-shadow filter properties in canonical order 1 tuần trước cách đây
  Jess 83e46b3728 LibRegex: Fix crash when parse result exceeds max cache size 1 tuần trước cách đây
  Jelle Raaijmakers 99df80f81e LibWeb: Only apply box offset if the box is not already the ancestor 1 tuần trước cách đây
27 tập tin đã thay đổi với 391 bổ sung121 xóa
  1. 1 5
      Libraries/LibGC/CMakeLists.txt
  2. 3 10
      Libraries/LibGC/Cell.h
  3. 3 3
      Libraries/LibJS/Runtime/Shape.h
  4. 4 0
      Libraries/LibJS/Tests/builtins/RegExp/RegExp.js
  5. 17 6
      Libraries/LibRegex/RegexMatcher.cpp
  6. 11 11
      Libraries/LibWeb/Bindings/PlatformObject.h
  7. 1 1
      Libraries/LibWeb/CMakeLists.txt
  8. 7 1
      Libraries/LibWeb/CSS/Parser/PropertyParsing.cpp
  9. 4 4
      Libraries/LibWeb/CSS/StyleInvalidation.h
  10. 26 41
      Libraries/LibWeb/CSS/StyleValues/FilterValueListStyleValue.cpp
  11. 3 3
      Libraries/LibWeb/CSS/StyleValues/FilterValueListStyleValue.h
  12. 10 10
      Libraries/LibWeb/DOM/Element.h
  13. 13 15
      Libraries/LibWeb/Layout/FormattingContext.cpp
  14. 0 1
      Libraries/LibWeb/Layout/FormattingContext.h
  15. 2 0
      Libraries/LibWeb/Layout/LayoutState.h
  16. 6 6
      Libraries/LibWeb/Painting/Paintable.h
  17. 9 0
      Meta/CMake/common_compile_options.cmake
  18. 1 1
      Meta/CMake/fontconfig.cmake
  19. 1 1
      Meta/CMake/lagom_compile_options.cmake
  20. 1 1
      Meta/CMake/vulkan.cmake
  21. 0 1
      Tests/LibGC/CMakeLists.txt
  22. 19 0
      Tests/LibWeb/Layout/expected/block-and-inline/float-inside-margin-auto-container.txt
  23. 23 0
      Tests/LibWeb/Layout/input/block-and-inline/float-inside-margin-auto-container.html
  24. 40 0
      Tests/LibWeb/Text/expected/wpt-import/css/filter-effects/parsing/filter-computed.txt
  25. 45 0
      Tests/LibWeb/Text/expected/wpt-import/css/filter-effects/parsing/filter-parsing-valid.txt
  26. 68 0
      Tests/LibWeb/Text/input/wpt-import/css/filter-effects/parsing/filter-computed.html
  27. 73 0
      Tests/LibWeb/Text/input/wpt-import/css/filter-effects/parsing/filter-parsing-valid.html

+ 1 - 5
Libraries/LibGC/CMakeLists.txt

@@ -20,9 +20,5 @@ if (ENABLE_SWIFT)
         Heap+Swift.swift
     )
     target_link_libraries(LibGC PRIVATE AK)
-
-    # FIXME: https://github.com/swiftlang/swift/issues/80182
-    target_compile_options(LibGC PUBLIC $<$<COMPILE_LANGUAGE:C,CXX>:-DLIBGC_WORKAROUND_BOOL_BITFIELD>
-                                        SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xcc -DLIBGC_WORKAROUND_BOOL_BITFIELD>)
-    add_swift_target_properties(LibGC LAGOM_LIBRARIES AK COMPILE_DEFINITIONS LIBGC_WORKAROUND_BOOL_BITFIELD)
+    add_swift_target_properties(LibGC LAGOM_LIBRARIES AK)
 endif()

+ 3 - 10
Libraries/LibGC/Cell.h

@@ -28,13 +28,6 @@ namespace GC {
 #    define IGNORE_GC
 #endif
 
-// https://github.com/swiftlang/swift/issues/80182
-#if defined(LIBGC_WORKAROUND_BOOL_BITFIELD)
-#    define BOOL_BITFIELD
-#else
-#    define BOOL_BITFIELD : 1
-#endif
-
 #define GC_CELL(class_, base_class)                \
 public:                                            \
     using Base = base_class;                       \
@@ -195,9 +188,9 @@ protected:
     void set_overrides_must_survive_garbage_collection(bool b) { m_overrides_must_survive_garbage_collection = b; }
 
 private:
-    bool m_mark BOOL_BITFIELD { false };
-    bool m_overrides_must_survive_garbage_collection BOOL_BITFIELD { false };
-    State m_state BOOL_BITFIELD { State::Live };
+    bool m_mark : 1 { false };
+    bool m_overrides_must_survive_garbage_collection : 1 { false };
+    State m_state : 1 { State::Live };
 } SWIFT_UNSAFE_REFERENCE;
 
 }

+ 3 - 3
Libraries/LibJS/Runtime/Shape.h

@@ -142,9 +142,9 @@ private:
     PropertyAttributes m_attributes { 0 };
     TransitionType m_transition_type { TransitionType::Invalid };
 
-    bool m_dictionary BOOL_BITFIELD { false };
-    bool m_cacheable BOOL_BITFIELD { true };
-    bool m_is_prototype_shape BOOL_BITFIELD { false };
+    bool m_dictionary : 1 { false };
+    bool m_cacheable : 1 { true };
+    bool m_is_prototype_shape : 1 { false };
 };
 
 }

+ 4 - 0
Libraries/LibJS/Tests/builtins/RegExp/RegExp.js

@@ -77,3 +77,7 @@ test("v flag should enable unicode mode", () => {
     const re = new RegExp("a\\u{10FFFF}", "v");
     expect(re.test("a\u{10FFFF}")).toBe(true);
 });
+
+test("parsing a large bytestring shouldn't crash", () => {
+    RegExp(new Uint8Array(0x40000));
+});

+ 17 - 6
Libraries/LibRegex/RegexMatcher.cpp

@@ -48,6 +48,20 @@ static size_t s_cached_bytecode_size = 0;
 
 static constexpr auto MaxRegexCachedBytecodeSize = 1 * MiB;
 
+template<class Parser>
+static void cache_parse_result(regex::Parser::Result const& result, CacheKey<Parser> const& key)
+{
+    auto bytecode_size = result.bytecode.size() * sizeof(ByteCodeValueType);
+    if (bytecode_size > MaxRegexCachedBytecodeSize)
+        return;
+
+    while (bytecode_size + s_cached_bytecode_size<Parser> > MaxRegexCachedBytecodeSize)
+        s_cached_bytecode_size<Parser> -= s_parser_cache<Parser>.take_first().bytecode.size() * sizeof(ByteCodeValueType);
+
+    s_parser_cache<Parser>.set(key, result);
+    s_cached_bytecode_size<Parser> += bytecode_size;
+}
+
 template<class Parser>
 Regex<Parser>::Regex(ByteString pattern, typename ParserTraits<Parser>::OptionsType regex_options)
     : pattern_value(move(pattern))
@@ -61,12 +75,9 @@ Regex<Parser>::Regex(ByteString pattern, typename ParserTraits<Parser>::OptionsT
         parser_result = parser.parse();
 
         run_optimization_passes();
-        if (parser_result.error == regex::Error::NoError) {
-            while (parser_result.bytecode.size() * sizeof(ByteCodeValueType) + s_cached_bytecode_size<Parser> > MaxRegexCachedBytecodeSize)
-                s_cached_bytecode_size<Parser> -= s_parser_cache<Parser>.take_first().bytecode.size() * sizeof(ByteCodeValueType);
-            s_parser_cache<Parser>.set({ pattern_value, regex_options }, parser_result);
-            s_cached_bytecode_size<Parser> += parser_result.bytecode.size() * sizeof(ByteCodeValueType);
-        }
+
+        if (parser_result.error == regex::Error::NoError)
+            cache_parse_result<Parser>(parser_result, { pattern_value, regex_options });
     }
 
     if (parser_result.error == regex::Error::NoError)

+ 11 - 11
Libraries/LibWeb/Bindings/PlatformObject.h

@@ -49,17 +49,17 @@ protected:
     explicit PlatformObject(JS::Object& prototype, MayInterfereWithIndexedPropertyAccess = MayInterfereWithIndexedPropertyAccess::No);
 
     struct LegacyPlatformObjectFlags {
-        u16 supports_indexed_properties BOOL_BITFIELD = false;
-        u16 supports_named_properties BOOL_BITFIELD = false;
-        u16 has_indexed_property_setter BOOL_BITFIELD = false;
-        u16 has_named_property_setter BOOL_BITFIELD = false;
-        u16 has_named_property_deleter BOOL_BITFIELD = false;
-        u16 has_legacy_unenumerable_named_properties_interface_extended_attribute BOOL_BITFIELD = false;
-        u16 has_legacy_override_built_ins_interface_extended_attribute BOOL_BITFIELD = false;
-        u16 has_global_interface_extended_attribute BOOL_BITFIELD = false;
-        u16 indexed_property_setter_has_identifier BOOL_BITFIELD = false;
-        u16 named_property_setter_has_identifier BOOL_BITFIELD = false;
-        u16 named_property_deleter_has_identifier BOOL_BITFIELD = false;
+        u16 supports_indexed_properties : 1 = false;
+        u16 supports_named_properties : 1 = false;
+        u16 has_indexed_property_setter : 1 = false;
+        u16 has_named_property_setter : 1 = false;
+        u16 has_named_property_deleter : 1 = false;
+        u16 has_legacy_unenumerable_named_properties_interface_extended_attribute : 1 = false;
+        u16 has_legacy_override_built_ins_interface_extended_attribute : 1 = false;
+        u16 has_global_interface_extended_attribute : 1 = false;
+        u16 indexed_property_setter_has_identifier : 1 = false;
+        u16 named_property_setter_has_identifier : 1 = false;
+        u16 named_property_deleter_has_identifier : 1 = false;
     };
     Optional<LegacyPlatformObjectFlags> m_legacy_platform_object_flags = {};
 

+ 1 - 1
Libraries/LibWeb/CMakeLists.txt

@@ -1007,5 +1007,5 @@ if (ENABLE_SWIFT)
         HTML/Parser/SpeculativeHTMLParser.swift
     )
     target_link_libraries(LibWeb PRIVATE AK Collections)
-    add_swift_target_properties(LibWeb LAGOM_LIBRARIES AK LibGfx LibGC COMPILE_DEFINITIONS LIBGC_WORKAROUND_BOOL_BITFIELD)
+    add_swift_target_properties(LibWeb LAGOM_LIBRARIES AK LibGfx LibGC)
 endif()

+ 7 - 1
Libraries/LibWeb/CSS/Parser/PropertyParsing.cpp

@@ -4432,8 +4432,14 @@ RefPtr<CSSStyleValue> Parser::parse_filter_value_list_value(TokenStream<Componen
                     return {};
                 if (amount->is_number() && amount->number().value() < 0)
                     return {};
+                if (first_is_one_of(filter_token, FilterToken::Grayscale, FilterToken::Invert, FilterToken::Opacity, FilterToken::Sepia)) {
+                    if (amount->is_percentage() && amount->percentage().value() > 100)
+                        amount = Percentage { 100 };
+                    if (amount->is_number() && amount->number().value() > 1)
+                        amount = Number { Number::Type::Integer, 1.0 };
+                }
             }
-            return if_no_more_tokens_return(FilterOperation::Color { filter_token_to_operation(filter_token), amount });
+            return if_no_more_tokens_return(FilterOperation::Color { filter_token_to_operation(filter_token), amount.value_or(Number { Number::Type::Integer, 1 }) });
         }
     };
 

+ 4 - 4
Libraries/LibWeb/CSS/StyleInvalidation.h

@@ -11,10 +11,10 @@
 namespace Web::CSS {
 
 struct RequiredInvalidationAfterStyleChange {
-    bool repaint BOOL_BITFIELD { false };
-    bool rebuild_stacking_context_tree BOOL_BITFIELD { false };
-    bool relayout BOOL_BITFIELD { false };
-    bool rebuild_layout_tree BOOL_BITFIELD { false };
+    bool repaint : 1 { false };
+    bool rebuild_stacking_context_tree : 1 { false };
+    bool relayout : 1 { false };
+    bool rebuild_layout_tree : 1 { false };
 
     void operator|=(RequiredInvalidationAfterStyleChange const& other)
     {

+ 26 - 41
Libraries/LibWeb/CSS/StyleValues/FilterValueListStyleValue.cpp

@@ -15,40 +15,29 @@ namespace Web::CSS {
 
 float FilterOperation::Blur::resolved_radius(Layout::Node const& node) const
 {
-    if (radius.has_value())
-        return radius->resolved({ .length_resolution_context = Length::ResolutionContext::for_layout_node(node) })->to_px(node).to_float();
-
-    // Default value when omitted is 0px.
-    return 0;
+    return radius.resolved({ .length_resolution_context = Length::ResolutionContext::for_layout_node(node) })->to_px(node).to_float();
 }
 
 float FilterOperation::HueRotate::angle_degrees(Layout::Node const& node) const
 {
-    // Default value when omitted is 0deg.
-    if (!angle.has_value())
-        return 0.0f;
-    return angle->visit([&](AngleOrCalculated const& a) { return a.resolved({ .length_resolution_context = Length::ResolutionContext::for_layout_node(node) })->to_degrees(); }, [&](Zero) { return 0.0; });
+    return angle.visit([&](AngleOrCalculated const& a) { return a.resolved({ .length_resolution_context = Length::ResolutionContext::for_layout_node(node) })->to_degrees(); }, [&](Zero) { return 0.0; });
 }
 
 float FilterOperation::Color::resolved_amount() const
 {
-    // Default value when omitted is 1.
-    if (!amount.has_value())
-        return 1;
-
-    if (amount->is_number())
-        return amount->number().value();
+    if (amount.is_number())
+        return amount.number().value();
 
-    if (amount->is_percentage())
-        return amount->percentage().as_fraction();
+    if (amount.is_percentage())
+        return amount.percentage().as_fraction();
 
-    if (amount->is_calculated()) {
+    if (amount.is_calculated()) {
         CalculationResolutionContext context {};
-        if (amount->calculated()->resolves_to_number())
-            return amount->calculated()->resolve_number(context).value();
+        if (amount.calculated()->resolves_to_number())
+            return amount.calculated()->resolve_number(context).value();
 
-        if (amount->calculated()->resolves_to_percentage())
-            return amount->calculated()->resolve_percentage(context)->as_fraction();
+        if (amount.calculated()->resolves_to_percentage())
+            return amount.calculated()->resolve_percentage(context)->as_fraction();
     }
 
     VERIFY_NOT_REACHED();
@@ -63,31 +52,27 @@ String FilterValueListStyleValue::to_string(SerializationMode) const
             builder.append(' ');
         filter_function.visit(
             [&](FilterOperation::Blur const& blur) {
-                builder.append("blur("sv);
-                if (blur.radius.has_value())
-                    builder.append(blur.radius->to_string());
+                builder.appendff("blur({}"sv, blur.radius.to_string());
             },
             [&](FilterOperation::DropShadow const& drop_shadow) {
-                builder.appendff("drop-shadow({} {}"sv,
-                    drop_shadow.offset_x, drop_shadow.offset_y);
-                if (drop_shadow.radius.has_value())
-                    builder.appendff(" {}", drop_shadow.radius->to_string());
+                builder.appendff("drop-shadow("sv);
                 if (drop_shadow.color.has_value()) {
-                    builder.append(' ');
                     serialize_a_srgb_value(builder, *drop_shadow.color);
+                    builder.append(' ');
                 }
+                builder.appendff("{} {}", drop_shadow.offset_x, drop_shadow.offset_y);
+                if (drop_shadow.radius.has_value())
+                    builder.appendff(" {}", drop_shadow.radius->to_string());
             },
             [&](FilterOperation::HueRotate const& hue_rotate) {
                 builder.append("hue-rotate("sv);
-                if (hue_rotate.angle.has_value()) {
-                    hue_rotate.angle->visit(
-                        [&](Angle const& angle) {
-                            return builder.append(angle.to_string());
-                        },
-                        [&](auto&) {
-                            return builder.append('0');
-                        });
-                }
+                hue_rotate.angle.visit(
+                    [&](Angle const& angle) {
+                        builder.append(angle.to_string());
+                    },
+                    [&](auto&) {
+                        builder.append("0deg"sv);
+                    });
             },
             [&](FilterOperation::Color const& color) {
                 builder.appendff("{}(",
@@ -111,8 +96,8 @@ String FilterValueListStyleValue::to_string(SerializationMode) const
                             VERIFY_NOT_REACHED();
                         }
                     }());
-                if (color.amount.has_value())
-                    builder.append(color.amount->to_string());
+
+                builder.append(color.amount.to_string());
             });
         builder.append(')');
         first = false;

+ 3 - 3
Libraries/LibWeb/CSS/StyleValues/FilterValueListStyleValue.h

@@ -21,7 +21,7 @@ namespace Web::CSS {
 namespace FilterOperation {
 
 struct Blur {
-    Optional<LengthOrCalculated> radius;
+    LengthOrCalculated radius { Length::make_px(0) };
     float resolved_radius(Layout::Node const&) const;
     bool operator==(Blur const&) const = default;
 };
@@ -39,14 +39,14 @@ struct HueRotate {
         bool operator==(Zero const&) const = default;
     };
     using AngleOrZero = Variant<AngleOrCalculated, Zero>;
-    Optional<AngleOrZero> angle;
+    AngleOrZero angle { Angle::make_degrees(0) };
     float angle_degrees(Layout::Node const&) const;
     bool operator==(HueRotate const&) const = default;
 };
 
 struct Color {
     Gfx::ColorFilter::Type operation;
-    Optional<NumberPercentage> amount {};
+    NumberPercentage amount { Number { Number::Type::Integer, 1.0 } };
     float resolved_amount() const;
     bool operator==(Color const&) const = default;
 };

+ 10 - 10
Libraries/LibWeb/DOM/Element.h

@@ -553,16 +553,16 @@ private:
 
     Array<CSSPixelPoint, 3> m_scroll_offset;
 
-    bool m_in_top_layer BOOL_BITFIELD { false };
-    bool m_rendered_in_top_layer BOOL_BITFIELD { false };
-    bool m_style_uses_css_custom_properties BOOL_BITFIELD { false };
-    bool m_affected_by_has_pseudo_class_in_subject_position BOOL_BITFIELD { false };
-    bool m_affected_by_has_pseudo_class_in_non_subject_position BOOL_BITFIELD { false };
-    bool m_affected_by_direct_sibling_combinator BOOL_BITFIELD { false };
-    bool m_affected_by_indirect_sibling_combinator BOOL_BITFIELD { false };
-    bool m_affected_by_first_or_last_child_pseudo_class BOOL_BITFIELD { false };
-    bool m_affected_by_nth_child_pseudo_class BOOL_BITFIELD { false };
-    bool m_affected_by_has_pseudo_class_with_relative_selector_that_has_sibling_combinator BOOL_BITFIELD { false };
+    bool m_in_top_layer : 1 { false };
+    bool m_rendered_in_top_layer : 1 { false };
+    bool m_style_uses_css_custom_properties : 1 { false };
+    bool m_affected_by_has_pseudo_class_in_subject_position : 1 { false };
+    bool m_affected_by_has_pseudo_class_in_non_subject_position : 1 { false };
+    bool m_affected_by_direct_sibling_combinator : 1 { false };
+    bool m_affected_by_indirect_sibling_combinator : 1 { false };
+    bool m_affected_by_first_or_last_child_pseudo_class : 1 { false };
+    bool m_affected_by_nth_child_pseudo_class : 1 { false };
+    bool m_affected_by_has_pseudo_class_with_relative_selector_that_has_sibling_combinator : 1 { false };
 
     size_t m_sibling_invalidation_distance { 0 };
 

+ 13 - 15
Libraries/LibWeb/Layout/FormattingContext.cpp

@@ -1182,10 +1182,9 @@ void FormattingContext::compute_height_for_absolutely_positioned_non_replaced_el
 
 CSSPixelRect FormattingContext::content_box_rect_in_static_position_ancestor_coordinate_space(Box const& box, Box const& ancestor_box) const
 {
-    auto rect = content_box_rect(box);
-    if (&box == &ancestor_box)
-        return rect;
-    for (auto const* current = box.static_position_containing_block(); current; current = current->static_position_containing_block()) {
+    auto box_used_values = m_state.get(box);
+    CSSPixelRect rect = { { 0, 0 }, box_used_values.content_size() };
+    for (auto const* current = &box; current; current = current->static_position_containing_block()) {
         if (current == &ancestor_box)
             return rect;
         auto const& current_state = m_state.get(*current);
@@ -1761,7 +1760,7 @@ bool FormattingContext::can_skip_is_anonymous_text_run(Box& box)
 CSSPixelRect FormattingContext::absolute_content_rect(Box const& box) const
 {
     auto const& box_state = m_state.get(box);
-    CSSPixelRect rect { box_state.offset, { box_state.content_width(), box_state.content_height() } };
+    CSSPixelRect rect { box_state.offset, box_state.content_size() };
     for (auto* block = box_state.containing_block_used_values(); block; block = block->containing_block_used_values())
         rect.translate_by(block->offset);
     return rect;
@@ -1825,10 +1824,13 @@ CSSPixels FormattingContext::box_baseline(Box const& box) const
     return box_state.margin_box_height();
 }
 
-CSSPixelRect FormattingContext::margin_box_rect(LayoutState::UsedValues const& used_values) const
+[[nodiscard]] static CSSPixelRect margin_box_rect(LayoutState::UsedValues const& used_values)
 {
     return {
-        used_values.offset.translated(-used_values.margin_box_left(), -used_values.margin_box_top()),
+        {
+            -used_values.margin_box_left(),
+            -used_values.margin_box_top(),
+        },
         {
             used_values.margin_box_left() + used_values.content_width() + used_values.margin_box_right(),
             used_values.margin_box_top() + used_values.content_height() + used_values.margin_box_bottom(),
@@ -1843,15 +1845,13 @@ CSSPixelRect FormattingContext::content_box_rect(Box const& box) const
 
 CSSPixelRect FormattingContext::content_box_rect(LayoutState::UsedValues const& used_values) const
 {
-    return CSSPixelRect { used_values.offset, { used_values.content_width(), used_values.content_height() } };
+    return CSSPixelRect { used_values.offset, used_values.content_size() };
 }
 
 CSSPixelRect FormattingContext::content_box_rect_in_ancestor_coordinate_space(LayoutState::UsedValues const& used_values, Box const& ancestor_box) const
 {
-    auto rect = content_box_rect(used_values);
-    if (&used_values.node() == &ancestor_box)
-        return rect;
-    for (auto const* current = used_values.containing_block_used_values(); current; current = current->containing_block_used_values()) {
+    CSSPixelRect rect = { { 0, 0 }, used_values.content_size() };
+    for (auto const* current = &used_values; current; current = current->containing_block_used_values()) {
         if (&current->node() == &ancestor_box)
             return rect;
         rect.translate_by(current->offset);
@@ -1863,9 +1863,7 @@ CSSPixelRect FormattingContext::content_box_rect_in_ancestor_coordinate_space(La
 CSSPixelRect FormattingContext::margin_box_rect_in_ancestor_coordinate_space(LayoutState::UsedValues const& used_values, Box const& ancestor_box) const
 {
     auto rect = margin_box_rect(used_values);
-    if (&used_values.node() == &ancestor_box)
-        return rect;
-    for (auto const* current = used_values.containing_block_used_values(); current; current = current->containing_block_used_values()) {
+    for (auto const* current = &used_values; current; current = current->containing_block_used_values()) {
         if (&current->node() == &ancestor_box)
             return rect;
         rect.translate_by(current->offset);

+ 0 - 1
Libraries/LibWeb/Layout/FormattingContext.h

@@ -82,7 +82,6 @@ public:
 
     [[nodiscard]] CSSPixelRect absolute_content_rect(Box const&) const;
     [[nodiscard]] CSSPixelRect margin_box_rect_in_ancestor_coordinate_space(Box const&, Box const& ancestor_box) const;
-    [[nodiscard]] CSSPixelRect margin_box_rect(LayoutState::UsedValues const&) const;
     [[nodiscard]] CSSPixelRect margin_box_rect_in_ancestor_coordinate_space(LayoutState::UsedValues const&, Box const& ancestor_box) const;
     [[nodiscard]] CSSPixelRect content_box_rect(Box const&) const;
     [[nodiscard]] CSSPixelRect content_box_rect(LayoutState::UsedValues const&) const;

+ 2 - 0
Libraries/LibWeb/Layout/LayoutState.h

@@ -67,6 +67,8 @@ struct LayoutState {
         void set_content_width(CSSPixels);
         void set_content_height(CSSPixels);
 
+        CSSPixelSize content_size() const { return { content_width(), content_height() }; }
+
         void set_indefinite_content_width();
         void set_indefinite_content_height();
 

+ 6 - 6
Libraries/LibWeb/Painting/Paintable.h

@@ -168,12 +168,12 @@ private:
 
     SelectionState m_selection_state { SelectionState::None };
 
-    bool m_positioned BOOL_BITFIELD { false };
-    bool m_fixed_position BOOL_BITFIELD { false };
-    bool m_sticky_position BOOL_BITFIELD { false };
-    bool m_absolutely_positioned BOOL_BITFIELD { false };
-    bool m_floating BOOL_BITFIELD { false };
-    bool m_inline BOOL_BITFIELD { false };
+    bool m_positioned : 1 { false };
+    bool m_fixed_position : 1 { false };
+    bool m_sticky_position : 1 { false };
+    bool m_absolutely_positioned : 1 { false };
+    bool m_floating : 1 { false };
+    bool m_inline : 1 { false };
 };
 
 inline DOM::Node* HitTestResult::dom_node()

+ 9 - 0
Meta/CMake/common_compile_options.cmake

@@ -14,6 +14,15 @@ macro(add_cxx_compile_options)
   add_compile_options($<$<COMPILE_LANGUAGE:C,CXX,ASM>:${args}>)
 endmacro()
 
+macro(add_cxx_compile_definitions)
+  set(args "")
+  foreach(arg ${ARGN})
+    string(APPEND args ${arg}$<SEMICOLON>)
+    add_compile_options("SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xcc -D${arg}>")
+  endforeach()
+  add_compile_definitions($<$<COMPILE_LANGUAGE:C,CXX,ASM>:${args}>)
+endmacro()
+
 macro(add_cxx_link_options)
   set(args "")
   foreach(arg ${ARGN})

+ 1 - 1
Meta/CMake/fontconfig.cmake

@@ -3,5 +3,5 @@ include_guard()
 if (NOT APPLE AND NOT ANDROID)
     find_package(Fontconfig REQUIRED)
     set(HAS_FONTCONFIG ON CACHE BOOL "" FORCE)
-    add_compile_definitions(USE_FONTCONFIG=1)
+    add_cxx_compile_definitions(USE_FONTCONFIG=1)
 endif()

+ 1 - 1
Meta/CMake/lagom_compile_options.cmake

@@ -18,7 +18,7 @@ if (NOT WIN32)
 endif()
 
 if (LINUX)
-    add_compile_definitions(_FILE_OFFSET_BITS=64)
+    add_cxx_compile_definitions(_FILE_OFFSET_BITS=64)
 endif()
 
 if (APPLE)

+ 1 - 1
Meta/CMake/vulkan.cmake

@@ -5,6 +5,6 @@ if (NOT APPLE)
     find_package(Vulkan QUIET)
     if (VulkanHeaders_FOUND AND Vulkan_FOUND)
         set(HAS_VULKAN ON CACHE BOOL "" FORCE)
-        add_compile_definitions(USE_VULKAN=1)
+        add_cxx_compile_definitions(USE_VULKAN=1)
     endif()
 endif()

+ 0 - 1
Tests/LibGC/CMakeLists.txt

@@ -19,7 +19,6 @@ if (ENABLE_SWIFT)
 
     add_swift_target_properties(TestGCSwift
         LAGOM_LIBRARIES AK LibGC
-        COMPILE_DEFINITIONS LIBGC_WORKAROUND_BOOL_BITFIELD
         COMPILE_OPTIONS ${testing_compile_options} -enable-experimental-feature Extern
     )
     add_test(NAME TestGCSwift COMMAND TestGCSwift)

+ 19 - 0
Tests/LibWeb/Layout/expected/block-and-inline/float-inside-margin-auto-container.txt

@@ -0,0 +1,19 @@
+Viewport <#document> at (0,0) content-size 800x600 children: not-inline
+  BlockContainer <html> at (0,0) content-size 800x316 [BFC] children: not-inline
+    BlockContainer <body> at (8,8) content-size 784x300 children: not-inline
+      BlockContainer <div.a> at (300,8) content-size 200x300 [BFC] children: inline
+        TextNode <#text>
+        BlockContainer <div.b.g> at (300,8) content-size 150x150 floating [BFC] children: not-inline
+        TextNode <#text>
+        BlockContainer <div.b.r> at (300,158) content-size 150x150 floating [BFC] children: not-inline
+        TextNode <#text>
+      BlockContainer <(anonymous)> at (8,308) content-size 784x0 children: inline
+        TextNode <#text>
+
+ViewportPaintable (Viewport<#document>) [0,0 800x600]
+  PaintableWithLines (BlockContainer<HTML>) [0,0 800x316]
+    PaintableWithLines (BlockContainer<BODY>) [8,8 784x300]
+      PaintableWithLines (BlockContainer<DIV>.a) [300,8 200x300]
+        PaintableWithLines (BlockContainer<DIV>.b.g) [300,8 150x150]
+        PaintableWithLines (BlockContainer<DIV>.b.r) [300,158 150x150]
+      PaintableWithLines (BlockContainer(anonymous)) [8,308 784x0]

+ 23 - 0
Tests/LibWeb/Layout/input/block-and-inline/float-inside-margin-auto-container.html

@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<style>
+.a {
+    margin: auto;
+    overflow: auto;
+    width: 200px;
+}
+.b {
+    height: 150px;
+    float: left;
+    width: 150px;
+}
+.g {
+    background-color: green;
+}
+.r {
+    background-color: red;
+}
+</style>
+<div class="a">
+    <div class="b g"></div>
+    <div class="b r"></div>
+</div>

+ 40 - 0
Tests/LibWeb/Text/expected/wpt-import/css/filter-effects/parsing/filter-computed.txt

@@ -0,0 +1,40 @@
+Harness status: OK
+
+Found 34 tests
+
+22 Pass
+12 Fail
+Pass	Property filter value 'none'
+Pass	Property filter value 'blur(100px)'
+Pass	Property filter value 'blur()'
+Pass	Property filter value 'brightness(0)'
+Fail	Property filter value 'brightness(300%)'
+Pass	Property filter value 'brightness()'
+Pass	Property filter value 'contrast(0)'
+Fail	Property filter value 'contrast(300%)'
+Pass	Property filter value 'contrast()'
+Fail	Property filter value 'drop-shadow(1px 2px)'
+Pass	Property filter value 'drop-shadow(rgb(4, 5, 6) 1px 2px 0px)'
+Fail	Property filter value 'grayscale(50%)'
+Fail	Property filter value 'grayscale(calc(50%))'
+Pass	Property filter value 'grayscale(2)'
+Fail	Property filter value 'grayscale(calc(2))'
+Pass	Property filter value 'grayscale()'
+Fail	Property filter value 'hue-rotate(90deg)'
+Pass	Property filter value 'hue-rotate()'
+Pass	Property filter value 'invert(0)'
+Fail	Property filter value 'invert(100%)'
+Pass	Property filter value 'invert(2)'
+Pass	Property filter value 'invert()'
+Pass	Property filter value 'opacity(0)'
+Fail	Property filter value 'opacity(100%)'
+Pass	Property filter value 'opacity(2)'
+Pass	Property filter value 'opacity()'
+Pass	Property filter value 'saturate(0)'
+Fail	Property filter value 'saturate(300%)'
+Pass	Property filter value 'saturate()'
+Pass	Property filter value 'sepia(0)'
+Fail	Property filter value 'sepia(100%)'
+Pass	Property filter value 'sepia(2)'
+Pass	Property filter value 'sepia()'
+Fail	Property filter value 'blur(10px) url("https://www.example.com/picture.svg#f") contrast(20) brightness(30)'

+ 45 - 0
Tests/LibWeb/Text/expected/wpt-import/css/filter-effects/parsing/filter-parsing-valid.txt

@@ -0,0 +1,45 @@
+Harness status: OK
+
+Found 39 tests
+
+35 Pass
+4 Fail
+Pass	e.style['filter'] = "none" should set the property value
+Pass	e.style['filter'] = "blur(100px)" should set the property value
+Pass	e.style['filter'] = "blur(0)" should set the property value
+Pass	e.style['filter'] = "blur()" should set the property value
+Pass	e.style['filter'] = "brightness(0)" should set the property value
+Pass	e.style['filter'] = "brightness(300%)" should set the property value
+Pass	e.style['filter'] = "brightness()" should set the property value
+Pass	e.style['filter'] = "contrast(0)" should set the property value
+Pass	e.style['filter'] = "contrast(300%)" should set the property value
+Pass	e.style['filter'] = "contrast()" should set the property value
+Pass	e.style['filter'] = "drop-shadow(1px 2px)" should set the property value
+Pass	e.style['filter'] = "drop-shadow(1px 2px 3px)" should set the property value
+Pass	e.style['filter'] = "drop-shadow(0 0 0)" should set the property value
+Pass	e.style['filter'] = "drop-shadow(rgb(4, 5, 6) 1px 2px)" should set the property value
+Pass	e.style['filter'] = "drop-shadow(1px 2px rgb(4, 5, 6))" should set the property value
+Pass	e.style['filter'] = "drop-shadow(rgba(4, 5, 6, 0.75) 1px 2px 3px)" should set the property value
+Pass	e.style['filter'] = "grayscale(0)" should set the property value
+Pass	e.style['filter'] = "grayscale(300%)" should set the property value
+Pass	e.style['filter'] = "grayscale(calc(300%))" should set the property value
+Pass	e.style['filter'] = "grayscale(calc(101% * sign(1em - 1px)))" should set the property value
+Pass	e.style['filter'] = "grayscale()" should set the property value
+Fail	e.style['filter'] = "hue-rotate(90deg)" should set the property value
+Pass	e.style['filter'] = "hue-rotate(0)" should set the property value
+Pass	e.style['filter'] = "hue-rotate()" should set the property value
+Pass	e.style['filter'] = "invert(0)" should set the property value
+Pass	e.style['filter'] = "invert(300%)" should set the property value
+Pass	e.style['filter'] = "invert()" should set the property value
+Pass	e.style['filter'] = "opacity(0)" should set the property value
+Pass	e.style['filter'] = "opacity(300%)" should set the property value
+Pass	e.style['filter'] = "opacity()" should set the property value
+Pass	e.style['filter'] = "saturate(0)" should set the property value
+Pass	e.style['filter'] = "saturate(300%)" should set the property value
+Pass	e.style['filter'] = "saturate()" should set the property value
+Pass	e.style['filter'] = "sepia(0)" should set the property value
+Pass	e.style['filter'] = "sepia(300%)" should set the property value
+Pass	e.style['filter'] = "sepia()" should set the property value
+Fail	e.style['filter'] = "url(picture.svg#f)" should set the property value
+Fail	e.style['filter'] = "url(\"https://www.example.com/picture.svg#f\")" should set the property value
+Fail	e.style['filter'] = "blur(10px) url(\"picture.svg#f\") contrast(20) brightness(30)" should set the property value

+ 68 - 0
Tests/LibWeb/Text/input/wpt-import/css/filter-effects/parsing/filter-computed.html

@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Filter Effects Module Level 1: getComputedStyle().filter</title>
+<link rel="author" title="Eric Willigers" href="mailto:ericwilligers@chromium.org">
+<link rel="help" href="https://drafts.fxtf.org/filter-effects/#FilterProperty">
+<meta name="assert" content="filter supports omitted arguments'.">
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="../../../css/support/computed-testcommon.js"></script>
+</head>
+<body>
+<style>
+  #target {
+    color: lime;
+  }
+</style>
+<div id="target"></div>
+<script>
+test_computed_value("filter", "none");
+
+test_computed_value("filter", "blur(100px)");
+test_computed_value("filter", "blur()", "blur(0px)");
+
+test_computed_value("filter", "brightness(0)");
+test_computed_value("filter", "brightness(300%)", "brightness(3)");
+test_computed_value("filter", "brightness()", "brightness(1)");
+
+test_computed_value("filter", "contrast(0)");
+test_computed_value("filter", "contrast(300%)", "contrast(3)");
+test_computed_value("filter", "contrast()", "contrast(1)");
+
+test_computed_value("filter", "drop-shadow(1px 2px)", "drop-shadow(rgb(0, 255, 0) 1px 2px 0px)");
+test_computed_value("filter", "drop-shadow(rgb(4, 5, 6) 1px 2px 0px)");
+
+test_computed_value("filter", "grayscale(50%)", "grayscale(0.5)");
+test_computed_value("filter", "grayscale(calc(50%))", "grayscale(0.5)");
+test_computed_value("filter", "grayscale(2)", "grayscale(1)");
+test_computed_value("filter", "grayscale(calc(2))", "grayscale(1)");
+test_computed_value("filter", "grayscale()", "grayscale(1)");
+
+test_computed_value("filter", "hue-rotate(90deg)");
+test_computed_value("filter", "hue-rotate()", "hue-rotate(0deg)");
+
+test_computed_value("filter", "invert(0)");
+test_computed_value("filter", "invert(100%)", "invert(1)");
+test_computed_value("filter", "invert(2)", "invert(1)");
+test_computed_value("filter", "invert()", "invert(1)");
+
+test_computed_value("filter", "opacity(0)");
+test_computed_value("filter", "opacity(100%)", "opacity(1)");
+test_computed_value("filter", "opacity(2)", "opacity(1)");
+test_computed_value("filter", "opacity()", "opacity(1)");
+
+test_computed_value("filter", "saturate(0)");
+test_computed_value("filter", "saturate(300%)", "saturate(3)");
+test_computed_value("filter", "saturate()", "saturate(1)");
+
+test_computed_value("filter", "sepia(0)");
+test_computed_value("filter", "sepia(100%)", "sepia(1)");
+test_computed_value("filter", "sepia(2)", "sepia(1)");
+test_computed_value("filter", "sepia()", "sepia(1)");
+
+test_computed_value("filter", 'blur(10px) url("https://www.example.com/picture.svg#f") contrast(20) brightness(30)');
+</script>
+</body>
+</html>

+ 73 - 0
Tests/LibWeb/Text/input/wpt-import/css/filter-effects/parsing/filter-parsing-valid.html

@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Filter Effects Module Level 1: parsing filter with valid values</title>
+<link rel="author" title="Eric Willigers" href="mailto:ericwilligers@chromium.org">
+<link rel="help" href="https://drafts.fxtf.org/filter-effects/#FilterProperty">
+<meta name="assert" content="filter supports the full grammar 'none | <filter-function-list>'.">
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="../../../css/support/parsing-testcommon.js"></script>
+</head>
+<body>
+<script>
+test_valid_value("filter", "none");
+
+test_valid_value("filter", "blur(100px)");
+test_valid_value("filter", "blur(0)", "blur(0px)");
+test_valid_value("filter", "blur()", ["blur()", "blur(0px)"]);
+
+test_valid_value("filter", "brightness(0)");
+test_valid_value("filter", "brightness(300%)");
+test_valid_value("filter", "brightness()", ["brightness()", "brightness(1)"]);
+
+test_valid_value("filter", "contrast(0)");
+test_valid_value("filter", "contrast(300%)");
+test_valid_value("filter", "contrast()", ["contrast()", "contrast(1)"]);
+
+test_valid_value("filter", "drop-shadow(1px 2px)");
+test_valid_value("filter", "drop-shadow(1px 2px 3px)");
+test_valid_value("filter", "drop-shadow(0 0 0)", "drop-shadow(0px 0px 0px)");
+// https://github.com/w3c/fxtf-drafts/issues/240
+test_valid_value("filter", "drop-shadow(rgb(4, 5, 6) 1px 2px)");
+test_valid_value("filter", "drop-shadow(1px 2px rgb(4, 5, 6))", "drop-shadow(rgb(4, 5, 6) 1px 2px)");
+test_valid_value("filter", "drop-shadow(rgba(4, 5, 6, 0.75) 1px 2px 3px)");
+
+test_valid_value("filter", "grayscale(0)");
+test_valid_value("filter", "grayscale(300%)", "grayscale(100%)");
+test_valid_value("filter", "grayscale(calc(300%))");
+test_valid_value("filter", "grayscale(calc(101% * sign(1em - 1px)))");
+test_valid_value("filter", "grayscale()", ["grayscale()", "grayscale(1)"]);
+
+test_valid_value("filter", "hue-rotate(90deg)");
+test_valid_value("filter", "hue-rotate(0)", "hue-rotate(0deg)"); // https://github.com/w3c/fxtf-drafts/issues/228
+test_valid_value("filter", "hue-rotate()", ["hue-rotate()", "hue-rotate(0deg)"]);
+
+test_valid_value("filter", "invert(0)");
+test_valid_value("filter", "invert(300%)", "invert(100%)");
+test_valid_value("filter", "invert()", ["invert()", "invert(1)"]);
+
+test_valid_value("filter", "opacity(0)");
+test_valid_value("filter", "opacity(300%)", "opacity(100%)");
+test_valid_value("filter", "opacity()", ["opacity()", "opacity(1)"]);
+
+test_valid_value("filter", "saturate(0)");
+test_valid_value("filter", "saturate(300%)");
+test_valid_value("filter", "saturate()", ["saturate()", "saturate(1)"]);
+
+test_valid_value("filter", "sepia(0)");
+test_valid_value("filter", "sepia(300%)", "sepia(100%)");
+test_valid_value("filter", "sepia()", ["sepia()", "sepia(1)"]);
+
+// Edge serializes url(...) without quotes. Blink/WebKit and Firefox use quotes.
+test_valid_value("filter", "url(picture.svg#f)", ['url("picture.svg#f")', 'url(picture.svg#f)']);
+
+test_valid_value("filter", 'url("https://www.example.com/picture.svg#f")',
+  ['url("https://www.example.com/picture.svg#f")', 'url(https://www.example.com/picture.svg#f)']);
+
+test_valid_value("filter", 'blur(10px) url("picture.svg#f") contrast(20) brightness(30)',
+  ['blur(10px) url("picture.svg#f") contrast(20) brightness(30)', 'blur(10px) url(picture.svg#f) contrast(20) brightness(30)']);
+</script>
+</body>
+</html>