Skip to content

Commit 9329b16

Browse files
author
ci_lynx
committed
[Testing] CQ-CQ-700075-59167-59382-stoup
1 parent aee600b commit 9329b16

File tree

11 files changed

+279
-6
lines changed

11 files changed

+279
-6
lines changed

core/renderer/dom/element_manager.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -989,6 +989,8 @@ void ElementManager::SetConfig(const std::shared_ptr<PageConfig> &config) {
989989
{.enable_native_schedule_create_view_async =
990990
config_->GetEnableNativeScheduleCreateViewAsyncAsBool()});
991991
}
992+
enable_property_based_simple_style_ =
993+
config_->GetEnablePropertyBasedSimpleStyle();
992994
}
993995
}
994996

core/renderer/dom/element_manager.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,9 @@ class ElementManager : public ElementContextDelegate {
659659

660660
virtual bool IsDomTreeEnabled() { return dom_tree_enabled_; }
661661
bool GetEnableZIndex() { return config_ && config_->GetEnableZIndex(); }
662+
bool EnablePropertyBasedSimpleStyle() const {
663+
return enable_property_based_simple_style_;
664+
}
662665

663666
void InsertDirtyContext(BaseElementContainer *stacking_context) {
664667
dirty_stacking_contexts_.insert(stacking_context);
@@ -1306,6 +1309,7 @@ class ElementManager : public ElementContextDelegate {
13061309
bool enable_fiber_element_memory_reporter_{false};
13071310
bool enable_layout_in_element_mode_{false};
13081311
bool enable_fragment_layer_render_{false};
1312+
bool enable_property_based_simple_style_{false};
13091313

13101314
bool has_viewport_ready_{false};
13111315
bool is_memory_collecting_{false};

core/renderer/dom/fiber/fiber_element.cc

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#include "core/renderer/dom/fiber/wrapper_element.h"
4545
#include "core/renderer/dom/fragment/fragment.h"
4646
#include "core/renderer/dom/list_component_info.h"
47+
#include "core/renderer/dom/style_resolver.h"
4748
#include "core/renderer/dom/vdom/radon/node_select_options.h"
4849
#include "core/renderer/dom/vdom/radon/node_selector.h"
4950
#include "core/renderer/page_proxy.h"
@@ -456,6 +457,11 @@ void FiberElement::SetStyleObjects(
456457
MarkDirty(kDirtyForceUpdate | kDirtyStyleObjects);
457458
}
458459

460+
void FiberElement::UpdateSimpleStyles(tasm::StyleMap &&style_map) {
461+
parsed_styles_map_ = std::move(style_map);
462+
UpdateSimpleStyles(parsed_styles_map_);
463+
}
464+
459465
void FiberElement::UpdateSimpleStyles(const tasm::StyleMap &style_map) {
460466
std::for_each(
461467
style_map.begin(), style_map.end(), [this](const auto &pair) -> void {
@@ -1492,9 +1498,16 @@ ParallelFlushReturn FiberElement::PrepareForCreateOrUpdate() {
14921498

14931499
if (dirty_ & kDirtyStyleObjects) {
14941500
TRACE_EVENT(LYNX_TRACE_CATEGORY, "FiberElement::HandleStyleObjects");
1495-
StyleResolver::ResolveStyleObjects(
1496-
last_style_objects_ ? last_style_objects_.get() : nullptr,
1497-
style_objects_ ? style_objects_.get() : nullptr, this);
1501+
if (element_manager_->EnablePropertyBasedSimpleStyle()) {
1502+
StyleResolver::ResolveStyleObjectsBasedOnExistingMap(
1503+
parsed_styles_map_, style_objects_ ? style_objects_.get() : nullptr,
1504+
this);
1505+
} else {
1506+
StyleResolver::ResolveStyleObjects(
1507+
last_style_objects_ ? last_style_objects_.get() : nullptr,
1508+
style_objects_ ? style_objects_.get() : nullptr, this);
1509+
}
1510+
14981511
// Animation and Direction should be handled here
14991512
dirty_ &= ~kDirtyStyleObjects;
15001513
} else {

core/renderer/dom/fiber/fiber_element.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,9 @@ class FiberElement : public Element,
565565
* @param style_map A constant reference to a tasm::StyleMap containing the
566566
* styles to be updated.
567567
*/
568-
void UpdateSimpleStyles(const tasm::StyleMap& style_map) override final;
568+
void UpdateSimpleStyles(const tasm::StyleMap& style_map) final;
569+
570+
void UpdateSimpleStyles(tasm::StyleMap&& style_map) final;
569571

570572
/**
571573
* @brief Reset the simple style associated with the specified CSS property

core/renderer/dom/style_resolver.cc

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@
44

55
#include "core/renderer/dom/style_resolver.h"
66

7-
#include <algorithm>
87
#include <utility>
98

109
#include "base/include/algorithm.h"
1110
#include "base/include/log/logging.h"
1211
#include "base/trace/native/trace_event.h"
12+
#include "core/renderer/css/css_property.h"
1313
#include "core/renderer/css/css_sheet.h"
14+
#include "core/renderer/css/css_value.h"
1415
#include "core/renderer/css/parser/css_string_parser.h"
1516
#include "core/renderer/dom/element.h"
1617
#include "core/renderer/dom/fiber/fiber_element.h"
@@ -140,6 +141,49 @@ void StyleResolver::ResolveStyleObjects(style::StyleObject** old_ptr,
140141
}
141142
}
142143

144+
void StyleResolver::ResolveStyleObjectsBasedOnExistingMap(
145+
const tasm::StyleMap& old_dcl_style, style::StyleObject** new_ptr,
146+
style::SimpleStyleNode* target) {
147+
// Early return if no new style objects and no existing styles
148+
if (!new_ptr && old_dcl_style.empty()) {
149+
return;
150+
}
151+
152+
// Reserve space to avoid reallocations - estimate based on old + new
153+
// properties
154+
tasm::StyleMap resolved_property;
155+
const size_t estimated_size = old_dcl_style.size() + (new_ptr ? 8 : 0);
156+
resolved_property.reserve(estimated_size);
157+
158+
// Merge all properties from new style objects
159+
if (new_ptr) {
160+
for (auto** it = new_ptr; *it; ++it) {
161+
(*it)->FromBinary();
162+
resolved_property.merge((*it)->Properties());
163+
}
164+
}
165+
166+
// Update target only if we have resolved properties
167+
if (!resolved_property.empty()) {
168+
// Update to new style object.
169+
// Reset any properties from old_dcl_style that don't exist in the new
170+
// styles
171+
for (const auto& [property_id, value] : old_dcl_style) {
172+
if (!resolved_property.contains(property_id)) {
173+
target->ResetSimpleStyle(property_id);
174+
}
175+
}
176+
177+
target->UpdateSimpleStyles(std::move(resolved_property));
178+
179+
} else {
180+
// Reset every styles, since the new styleObject array is empty.
181+
for (const auto& [property_id, value] : old_dcl_style) {
182+
target->ResetSimpleStyle(property_id);
183+
}
184+
}
185+
}
186+
143187
ElementManager* StyleResolver::manager() const {
144188
return element()->element_manager();
145189
}

core/renderer/dom/style_resolver.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "base/include/vector.h"
1414
#include "core/base/lynx_export.h"
1515
#include "core/renderer/css/css_fragment.h"
16+
#include "core/renderer/css/css_property.h"
1617
#include "core/renderer/css/css_selector_constants.h"
1718
#include "core/renderer/css/css_variable_handler.h"
1819
#include "core/renderer/css/dynamic_css_styles_manager.h"
@@ -61,6 +62,10 @@ class StyleResolver {
6162
style::StyleObject** new_ptr,
6263
style::SimpleStyleNode* target);
6364

65+
static void ResolveStyleObjectsBasedOnExistingMap(
66+
const tasm::StyleMap& old_dcl_style, style::StyleObject** new_ptr,
67+
style::SimpleStyleNode* target);
68+
6469
private:
6570
enum class PseudoClassType { kFocus, kHover, kActive };
6671

core/renderer/dom/style_resolver_unittest.cc

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#include "core/renderer/dom/element_manager.h"
1414
#include "core/renderer/dom/fiber/component_element.h"
1515
#include "core/renderer/dom/fiber/view_element.h"
16+
#include "core/renderer/simple_styling/simple_style_node.h"
17+
#include "core/renderer/simple_styling/style_object.h"
1618
#include "core/renderer/tasm/react/testing/mock_painting_context.h"
1719
#include "core/shell/tasm_operation_queue.h"
1820
#include "core/shell/testing/mock_tasm_delegate.h"
@@ -29,6 +31,42 @@ static constexpr double kDefaultPhysicalPixelsPerLayoutUnit = 1.f;
2931

3032
using namespace css;
3133

34+
// Mock implementation of SimpleStyleNode for testing
35+
class MockSimpleStyleNode : public lynx::style::SimpleStyleNode {
36+
public:
37+
MockSimpleStyleNode() = default;
38+
~MockSimpleStyleNode() override = default;
39+
40+
void SetStyleObjects(std::unique_ptr<lynx::style::StyleObject*,
41+
lynx::style::StyleObjectArrayDeleter>
42+
style_object) override {
43+
// Not needed for this test
44+
}
45+
46+
void UpdateSimpleStyles(const tasm::StyleMap& style_map) override {
47+
current_styles_ = style_map;
48+
}
49+
50+
void UpdateSimpleStyles(tasm::StyleMap&& style_map) override {
51+
current_styles_ = std::move(style_map);
52+
}
53+
54+
void ResetSimpleStyle(tasm::CSSPropertyID id) override {
55+
current_styles_.erase(id);
56+
}
57+
58+
// Helper method to get current styles for verification
59+
const tasm::StyleMap& GetCurrentStyles() const { return current_styles_; }
60+
61+
// Helper method to check if a property exists
62+
bool HasProperty(tasm::CSSPropertyID id) const {
63+
return current_styles_.find(id) != current_styles_.end();
64+
}
65+
66+
private:
67+
tasm::StyleMap current_styles_;
68+
};
69+
3270
class CSSPatchingTest : public ::testing::Test {
3371
public:
3472
CSSPatchingTest() {}
@@ -394,6 +432,145 @@ TEST_F(CSSPatchingTest, CSSSelectorDescendantSelectorScope) {
394432
EXPECT_EQ(new_value.GetPattern(), CSSValuePattern::PX);
395433
EXPECT_EQ(new_value.AsNumber(), 20);
396434
}
435+
436+
TEST_F(CSSPatchingTest, ResolveStyleObjectsBasedOnExistingMap_EmptyOldAndNew) {
437+
// Test case: Both old and new style maps are empty
438+
tasm::StyleMap old_dcl_style;
439+
MockSimpleStyleNode target;
440+
target.UpdateSimpleStyles(old_dcl_style);
441+
442+
StyleResolver resolver;
443+
resolver.ResolveStyleObjectsBasedOnExistingMap(old_dcl_style, nullptr,
444+
&target);
445+
446+
EXPECT_TRUE(target.GetCurrentStyles().empty());
447+
}
448+
449+
TEST_F(CSSPatchingTest, ResolveStyleObjectsBasedOnExistingMap_OnlyOldStyles) {
450+
// Test case: Only old styles exist, new styles are null
451+
tasm::StyleMap old_dcl_style;
452+
old_dcl_style[CSSPropertyID::kPropertyIDFontSize] =
453+
CSSValue::MakePlainString("16px");
454+
old_dcl_style[CSSPropertyID::kPropertyIDColor] =
455+
CSSValue::MakePlainString("red");
456+
457+
MockSimpleStyleNode target;
458+
target.UpdateSimpleStyles(old_dcl_style);
459+
460+
StyleResolver resolver;
461+
resolver.ResolveStyleObjectsBasedOnExistingMap(old_dcl_style, nullptr,
462+
&target);
463+
464+
// All old styles should be reset since new styles are null
465+
EXPECT_TRUE(target.GetCurrentStyles().empty());
466+
}
467+
468+
TEST_F(CSSPatchingTest, ResolveStyleObjectsBasedOnExistingMap_OnlyNewStyles) {
469+
// Test case: Only new styles exist, old styles are empty
470+
tasm::StyleMap old_dcl_style;
471+
472+
// Create new style objects
473+
tasm::StyleMap new_style_map1;
474+
new_style_map1[CSSPropertyID::kPropertyIDFontSize] =
475+
CSSValue::MakePlainString("18px");
476+
477+
tasm::StyleMap new_style_map2;
478+
new_style_map2[CSSPropertyID::kPropertyIDColor] =
479+
CSSValue::MakePlainString("blue");
480+
new_style_map2[CSSPropertyID::kPropertyIDWidth] =
481+
CSSValue::MakePlainString("100px");
482+
483+
auto style_obj1 =
484+
fml::MakeRefCounted<lynx::style::StyleObject>(new_style_map1);
485+
auto style_obj2 =
486+
fml::MakeRefCounted<lynx::style::StyleObject>(new_style_map2);
487+
488+
lynx::style::StyleObject* new_ptr[] = {style_obj1.get(), style_obj2.get(),
489+
nullptr};
490+
491+
MockSimpleStyleNode target;
492+
target.UpdateSimpleStyles(old_dcl_style);
493+
494+
StyleResolver resolver;
495+
resolver.ResolveStyleObjectsBasedOnExistingMap(old_dcl_style, new_ptr,
496+
&target);
497+
498+
// All new styles should be applied
499+
EXPECT_TRUE(target.HasProperty(CSSPropertyID::kPropertyIDFontSize));
500+
EXPECT_TRUE(target.HasProperty(CSSPropertyID::kPropertyIDColor));
501+
EXPECT_TRUE(target.HasProperty(CSSPropertyID::kPropertyIDWidth));
502+
EXPECT_EQ(target.GetCurrentStyles().size(), 3u);
503+
}
504+
505+
TEST_F(CSSPatchingTest,
506+
ResolveStyleObjectsBasedOnExistingMap_OverlappingStyles) {
507+
// Test case: Both old and new styles exist with some overlapping properties
508+
tasm::StyleMap old_dcl_style;
509+
old_dcl_style[CSSPropertyID::kPropertyIDFontSize] =
510+
CSSValue::MakePlainString("16px");
511+
old_dcl_style[CSSPropertyID::kPropertyIDColor] =
512+
CSSValue::MakePlainString("red");
513+
old_dcl_style[CSSPropertyID::kPropertyIDHeight] =
514+
CSSValue::MakePlainString("50px");
515+
516+
// Create new style objects - font-size overlaps, color is new, height is not
517+
// in new styles
518+
tasm::StyleMap new_style_map1;
519+
new_style_map1[CSSPropertyID::kPropertyIDFontSize] =
520+
CSSValue::MakePlainString("18px"); // Overrides old
521+
522+
tasm::StyleMap new_style_map2;
523+
new_style_map2[CSSPropertyID::kPropertyIDColor] =
524+
CSSValue::MakePlainString("blue"); // Updates existing
525+
new_style_map2[CSSPropertyID::kPropertyIDWidth] =
526+
CSSValue::MakePlainString("100px"); // New property
527+
528+
auto style_obj1 =
529+
fml::MakeRefCounted<lynx::style::StyleObject>(new_style_map1);
530+
auto style_obj2 =
531+
fml::MakeRefCounted<lynx::style::StyleObject>(new_style_map2);
532+
533+
lynx::style::StyleObject* new_ptr[] = {style_obj1.get(), style_obj2.get(),
534+
nullptr};
535+
536+
MockSimpleStyleNode target;
537+
target.UpdateSimpleStyles(old_dcl_style);
538+
539+
StyleResolver resolver;
540+
resolver.ResolveStyleObjectsBasedOnExistingMap(old_dcl_style, new_ptr,
541+
&target);
542+
543+
// Check that overlapping properties are updated, new properties are added,
544+
// and old ones are reset
545+
EXPECT_TRUE(target.HasProperty(CSSPropertyID::kPropertyIDFontSize));
546+
EXPECT_TRUE(target.HasProperty(CSSPropertyID::kPropertyIDColor));
547+
EXPECT_TRUE(target.HasProperty(CSSPropertyID::kPropertyIDWidth));
548+
EXPECT_FALSE(
549+
target.HasProperty(CSSPropertyID::kPropertyIDHeight)); // Should be reset
550+
EXPECT_EQ(target.GetCurrentStyles().size(), 3u);
551+
}
552+
553+
TEST_F(CSSPatchingTest, ResolveStyleObjectsBasedOnExistingMap_EmptyNewStyles) {
554+
// Test case: Old styles exist, but new styles array is empty (not null)
555+
tasm::StyleMap old_dcl_style;
556+
old_dcl_style[CSSPropertyID::kPropertyIDFontSize] =
557+
CSSValue::MakePlainString("16px");
558+
old_dcl_style[CSSPropertyID::kPropertyIDColor] =
559+
CSSValue::MakePlainString("red");
560+
561+
// Empty new styles array (nullptr terminated)
562+
lynx::style::StyleObject* new_ptr[] = {nullptr};
563+
564+
MockSimpleStyleNode target;
565+
target.UpdateSimpleStyles(old_dcl_style);
566+
567+
StyleResolver resolver;
568+
resolver.ResolveStyleObjectsBasedOnExistingMap(old_dcl_style, new_ptr,
569+
&target);
570+
571+
// All old styles should be reset since new styles are empty
572+
EXPECT_TRUE(target.GetCurrentStyles().empty());
573+
}
397574
} // namespace testing
398575
} // namespace tasm
399576
} // namespace lynx

core/renderer/simple_styling/simple_style_node.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
#include <memory>
99

10-
#include "base/include/fml/memory/ref_counted.h"
10+
#include "base/include/fml/memory/ref_ptr.h"
1111
#include "core/renderer/css/css_property.h"
1212

1313
namespace lynx::style {
@@ -22,6 +22,7 @@ class SimpleStyleNode {
2222
virtual void SetStyleObjects(
2323
std::unique_ptr<StyleObject*, StyleObjectArrayDeleter> style_object) = 0;
2424
virtual void UpdateSimpleStyles(const tasm::StyleMap& style_map) = 0;
25+
virtual void UpdateSimpleStyles(tasm::StyleMap&& style_map) = 0;
2526
virtual void ResetSimpleStyle(tasm::CSSPropertyID id) = 0;
2627
};
2728
} // namespace lynx::style

core/template_bundle/template_codec/binary_decoder/lynx_config.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1691,3 +1691,11 @@ enableCSSInlineVariables:
16911691
- DECODE
16921692
author: 'pilipala195'
16931693
since: '3.6'
1694+
enablePropertyBasedSimpleStyle:
1695+
description: SimpleStyle mode will incrementally update styles based on properties if this config set to TRUE. Otherwise it will incrementally update based on StyleObjects. The StyleObject based updating has a better performance but not allow StyleObjects bound to the same elememnt has intersect properties.
1696+
defaultValue: 'false'
1697+
valueType: bool
1698+
readSettings: false
1699+
readNative: false
1700+
author: 'zhongyr'
1701+
since: '3.5'

0 commit comments

Comments
 (0)