Skip to content

Conversation

@CGQAQ
Copy link
Contributor

@CGQAQ CGQAQ commented Dec 26, 2025

This PR changes how we drive style calculations. Before this PR, the style calculation was unstable and could be unexpectedly erratic.

Summary by CodeRabbit

  • New Features

    • Added style update mechanism for better CSS rendering synchronization with frame updates
    • Enhanced CSS variable normalization with proper handling of CSS-wide keywords (inherit, unset)
    • Improved API for scroll controller access in overflow handling
  • Bug Fixes

    • Fixed CSS style calculations for display:none subtrees during invalidation
    • Corrected element geometry method results (getBoundingClientRect, getClientRects) with automatic style updates
    • Improved physical padding property precedence over logical padding
  • Tests

    • Added comprehensive CSS invalidation and style engine unit tests

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link

vercel bot commented Dec 26, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
use-case Ready Ready Preview, Comment Dec 28, 2025 6:12pm

@coderabbitai
Copy link

coderabbitai bot commented Dec 26, 2025

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

This PR introduces comprehensive style update and idle state management across the rendering pipeline. Changes include idle state tracking in ExecutingContext, DOM-geometry-triggered style updates in binding operations, display-none invalidation flags on elements, frame-scheduled style updates from Dart, HTML parsing fragment support, and CSS variable normalization improvements.

Changes

Cohort / File(s) Summary
Idle State Tracking
bridge/core/executing_context.h, bridge/core/executing_context.cc, bridge/bindings/qjs/qjs_function.cc, bridge/bindings/qjs/script_promise_resolver.cc, bridge/core/frame/frame_request_callback_collection.cc, bridge/core/frame/script_idle_task_controller.cc
Added isIdle() / SetIsIdle(bool) accessors and MarkNeedsStyleUpdateInMicrotask() to ExecutingContext. Integrated idle state transitions into JS invocation paths (QJSFunction, promises, frame callbacks, idle tasks) and DrainMicrotasks flow.
DOM Geometry Style Updates
bridge/core/binding_object.cc, bridge/core/dom/element.cc, bridge/core/frame/window_or_worker_global_scope.cc
Added pre-invocation style updates for DOM geometry methods (getBoundingClientRect, getClientRects) and properties in binding operations. Called UpdateStyleForThisDocument within mutation scope when Blink enabled.
Display-None Invalidation
bridge/core/dom/element.h, bridge/core/dom/element.cc, bridge/core/css/pending_invalidations.cc
Added IsDisplayNoneForStyleInvalidation() / SetDisplayNoneForStyleInvalidation(bool) accessors to Element; replaced computed style checks with this flag in invalidation scheduling. Updated attribute and style handling in Element.
StyleEngine & Invalidation
bridge/core/css/style_engine.h, bridge/core/css/style_engine.cc, bridge/core/dom/document.h, bridge/core/dom/document.cc
Added GetPendingNodeInvalidations() accessors to StyleEngine; implemented display-none flag computation in style recalc; normalized empty CSS variable values to space; added reentrancy guard in Document::UpdateStyleForThisDocument.
HTML Parser Fragment Support
bridge/core/html/parser/html_parser.cc
Refactored parsing into parseDocument() and parseFragment() helpers; added fragmentContextFor() to determine Gumbo context; introduced append_gumbo_child() and traverse_fragment_root() for robust fragment tree traversal with improved error handling.
Style Update Bridge API
bridge/include/webf_bridge.h, bridge/webf_bridge.cc, bridge/core/page.h
Exported updateStyleForThisDocument(void* page) C function; added page-level TryBeginUpdateStyleForThisDocument() / EndUpdateStyleForThisDocument() / IsUpdateStyleForThisDocumentInProgress() for concurrent-safe in-progress tracking.
CSS Invalidation Tests
bridge/core/css/invalidation/invalidation_set_test.cc, bridge/core/css/invalidation/pending_invalidations_test.cc, bridge/test/css_unittests.cmake
Added comprehensive unit tests for InvalidationSet backing types, element/subtree invalidation logic, self-invalidation propagation, and PendingInvalidations scheduling behavior.
Dart Bridge Binding
webf/lib/src/bridge/to_native.dart, integration_tests/lib/bridge/from_native.dart, integration_tests/lib/webf_tester.dart, integration_tests/lib/playground.dart
Added native typedef and wrapper for updateStyleForThisDocument(Pointer<Void> page) returning bool; updated test context registration to pass Pointer<Void> instead of double contextId.
Frame Style Update Scheduling
webf/lib/src/launcher/view_controller.dart
Added _scheduleBlinkStyleUpdateForNextFrame() to queue style updates for next frame; integrated into flushPendingCommandsPerFrame() to synchronize Blink style updates with frame processing.
CSS Variable & Property Handling
webf/lib/src/css/variable.dart, webf/lib/src/css/style_declaration.dart, webf/lib/src/css/style_property.dart
Added CSS-wide keyword (inherit/unset) handling in setCSSVariable with storage clearing; normalized custom property values in setProperty; enhanced background shorthand to parse and apply origin/clip box tokens.
CSS Overflow & Layout
webf/lib/src/css/overflow.dart, webf/lib/src/css/padding.dart
Changed scrollControllerX/Y from fields to abstract getters in ElementOverflowMixin; adjusted paddingLeft/Right getters to prioritize explicit physical padding.
Element Widget & Event Tracking
webf/lib/src/dom/element_widget_adapter.dart
Added _isOnScreen state tracking to ElementAdapterMixin; de-duplicated onScreen/offScreen event enqueueing and updated state before event dispatch.
Integration Tests & Specs
integration_tests/specs/blink/css1/box_properties/padding_left.ts, integration_tests/specs/css/css-text-mixin/text_comprehensive_test.ts, use_cases/src/pages/FeatureCatalogPage.tsx
Added font-family setup in padding test; formatting adjustments in text comprehensive test; added "Responsive Design" entry to feature catalog.

Sequence Diagram(s)

sequenceDiagram
    participant Frame as Frame (Flutter)
    participant VC as ViewController
    participant Bridge as webf_bridge
    participant Page as WebFPage
    participant EC as ExecutingContext
    participant Doc as Document
    participant SE as StyleEngine
    participant MM as Microtask Manager

    Frame->>VC: flushPendingCommandsPerFrame()
    VC->>VC: _scheduleBlinkStyleUpdateForNextFrame()
    VC->>Bridge: updateStyleForThisDocument(page)
    Bridge->>Page: TryBeginUpdateStyleForThisDocument()
    alt Update Not In Progress
        Page-->>Bridge: true
        Bridge->>EC: verify idle & Blink enabled
        alt Context Valid & Idle
            Bridge->>Bridge: Post JS callback
            Bridge->>Bridge: Nested lambda executes
            Bridge->>Doc: UpdateStyleForThisDocument()
            rect rgb(220, 240, 255)
                Note over Doc,SE: Mutation Scope
                Doc->>SE: Recalc styles
                SE->>SE: Compute display-none flags
                SE->>SE: Normalize CSS variables
            end
            Bridge->>MM: Queue UI finish command
            Bridge->>Page: EndUpdateStyleForThisDocument()
            Page-->>Bridge: (cleared flag)
        else Context Invalid or Not Idle
            Bridge->>Page: EndUpdateStyleForThisDocument()
            Page-->>Bridge: (cleared flag)
        end
    else Update Already In Progress
        Page-->>Bridge: false (skipped)
    end
    VC->>VC: Continue frame flush
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • feat: Use vsync to drive style calculations #777 — Directly modifies idle-state tracking (ExecutingContext::SetIsIdle) and microtask-related control flow in the same core files and functions (QJSFunction::Invoke, ScriptPromiseResolver, frame callbacks, ExecutingContext).

Poem

🐰 A CSS cascade so fine,
Idle states now intertwine,
Styles update frame-by-frame,
Display-none flags stake their claim!
Fragment parsing blooms anew,

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.98% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly relates to the main objective of the PR: switching to use vsync to drive style calculations, which aligns with the comprehensive changes made to timing and idle state management across the codebase.

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 30b1491 and 1e9fc13.

⛔ Files ignored due to path filters (7)
  • integration_tests/snapshots/blink/css1/box_properties/padding_left.ts.f039ce881.png is excluded by !**/*.png
  • integration_tests/snapshots/css/css-flexbox/relayout-align.ts.6eab38941.png is excluded by !**/*.png
  • integration_tests/snapshots/css/css-inline/bidirectional-text.ts.921af8581.png is excluded by !**/*.png
  • integration_tests/snapshots/css/css-variables/variable-declaration-45.html.6172c1901.png is excluded by !**/*.png
  • integration_tests/snapshots/css/css-variables/variable-declaration-47.html.feb731161.png is excluded by !**/*.png
  • integration_tests/snapshots/css/css-variables/variable-declaration-57.html.889f7f911.png is excluded by !**/*.png
  • integration_tests/snapshots/css/css-variables/variable-declaration-58.html.e5a37f891.png is excluded by !**/*.png
📒 Files selected for processing (34)
  • bridge/bindings/qjs/qjs_function.cc
  • bridge/bindings/qjs/script_promise_resolver.cc
  • bridge/core/binding_object.cc
  • bridge/core/css/invalidation/invalidation_set_test.cc
  • bridge/core/css/invalidation/pending_invalidations.cc
  • bridge/core/css/invalidation/pending_invalidations_test.cc
  • bridge/core/css/style_engine.cc
  • bridge/core/css/style_engine.h
  • bridge/core/dom/document.cc
  • bridge/core/dom/document.h
  • bridge/core/dom/element.cc
  • bridge/core/dom/element.h
  • bridge/core/dom/frame_request_callback_collection.cc
  • bridge/core/executing_context.cc
  • bridge/core/executing_context.h
  • bridge/core/frame/script_idle_task_controller.cc
  • bridge/core/frame/window_or_worker_global_scope.cc
  • bridge/core/html/parser/html_parser.cc
  • bridge/core/page.h
  • bridge/include/webf_bridge.h
  • bridge/test/css_unittests.cmake
  • bridge/webf_bridge.cc
  • integration_tests/lib/bridge/from_native.dart
  • integration_tests/lib/playground.dart
  • integration_tests/lib/webf_tester.dart
  • integration_tests/specs/blink/css1/box_properties/padding_left.ts
  • integration_tests/specs/css/css-text-mixin/text_comprehensive_test.ts
  • use_cases/src/pages/FeatureCatalogPage.tsx
  • webf/lib/src/bridge/to_native.dart
  • webf/lib/src/css/overflow.dart
  • webf/lib/src/css/padding.dart
  • webf/lib/src/css/style_declaration.dart
  • webf/lib/src/css/style_property.dart
  • webf/lib/src/css/variable.dart

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
bridge/test/css_unittests.cmake (1)

80-80: Remove duplicate commented test discovery call for clarity.

Lines 108–109 contain a commented duplicate of the gtest_discover_tests() call and include(GoogleTest) from lines 79–80. Remove these commented lines to avoid confusion.

🧹 Nitpick comments (9)
bridge/core/html/parser/html_parser.cc (2)

302-410: Consider extracting shared node-handling logic to reduce duplication.

The append_gumbo_child lambda duplicates most of the child-handling logic from traverseHTML (lines 138-234). Both handle ELEMENT, TEXT, WHITESPACE, COMMENT, and CDATA nodes with nearly identical code.

Consider extracting a shared helper to handle individual GumboNode conversion, which both traverseHTML and the fragment flattening logic can call. This would improve maintainability and reduce the risk of divergence.


235-235: Stale comment: comments are now handled.

The comment states "Ignore other node types (comments, etc.)" but comments are explicitly handled at lines 210-221. Consider updating to reflect what's actually being ignored (e.g., GUMBO_NODE_DOCUMENT, GUMBO_NODE_TEMPLATE).

webf/lib/src/bridge/binding_object.dart (1)

386-400: Consider adding scroll-related geometry properties.

The layout-dependent property set covers offset and client dimensions but may be missing scroll-related properties like scrollWidth, scrollHeight, scrollLeft, and scrollTop, which also depend on layout calculations.

const Set<String> _layoutDependentBindingProperties = <String>{
  'offsetLeft',
  'offsetTop',
  'offsetWidth',
  'offsetHeight',
  'clientLeft',
  'clientTop',
  'clientWidth',
  'clientHeight',
+ 'scrollLeft',
+ 'scrollTop',
+ 'scrollWidth',
+ 'scrollHeight',
};

Based on coding guidelines for Dart code.

bridge/core/dom/element.cc (2)

139-167: Consider extracting the duplicated style-update pattern.

The pre-binding style update logic (lines 140-147) is identical to getBoundingClientRect (lines 117-124). This could be extracted into a helper method to reduce duplication.

🔎 Suggested helper extraction
+void Element::EnsureStyleUpdatedForLayout() {
+  ExecutingContext* context = GetExecutingContext();
+  if (context && context->isBlinkEnabled()) {
+    Document* doc = context->document();
+    if (doc) {
+      MemberMutationScope mutation_scope{context};
+      doc->UpdateStyleForThisDocument();
+    }
+  }
+}

 BoundingClientRect* Element::getBoundingClientRect(ExceptionState& exception_state) {
-  ExecutingContext* context = GetExecutingContext();
-  if (context && context->isBlinkEnabled()) {
-    Document* doc = context->document();
-    if (doc) {
-      MemberMutationScope mutation_scope{context};
-      doc->UpdateStyleForThisDocument();
-    }
-  }
+  EnsureStyleUpdatedForLayout();

   NativeValue result = InvokeBindingMethod(

1058-1063: Clarify the purpose of normalizing empty CSS variable values to a single space.

The code converts empty value_string to " " for CSS variables. This appears to be a workaround for the Dart side handling of var() declarations. A brief comment explaining why this normalization is necessary would improve maintainability.

🔎 Suggested documentation
         CSSPropertyID id = property.Id();
         AtomicString prop_name = property.Name().ToAtomicString();
         String value_string = inline_style->GetPropertyValueWithHint(prop_name, i);
+        // CSS custom properties (variables) with empty values must be normalized
+        // to a single space to ensure proper var() handling on the Dart side.
+        // An empty string would be treated as "invalid" rather than "initial".
         if (id == CSSPropertyID::kVariable && value_string.IsEmpty()) {
           value_string = String(" ");
         }
bridge/core/css/invalidation/pending_invalidations_test.cc (1)

127-254: Consider reducing the debug trace verbosity or extracting it.

The build_debug_trace lambda spans ~130 lines and performs extensive style resolution and inspection. While valuable for debugging failures, this could:

  1. Be extracted to a shared test utility if used elsewhere
  2. Be conditionally compiled or gated behind a verbose flag
  3. Include only the most essential diagnostics

The trace does full style cascade resolution (CollectAllRules, StyleCascade, ExportWinningPropertySet) which is heavy for a test assertion helper.

bridge/core/dom/element.h (1)

423-428: Clarify the dual-path attribute checking logic.

The updated hasAttributes() checks both Attributes() (from element_data_) and the separate attributes_ member. This mirrors the pattern in HasAttributeIgnoringNamespace.

Consider adding a brief comment explaining why both paths are necessary (e.g., Blink-style vs legacy attribute storage).

🔎 Suggested documentation
 inline bool Element::hasAttributes() const {
+  // Check both Blink-style element data attributes and legacy ElementAttributes.
+  // The former is used for CSS selector matching; the latter for DOM API compatibility.
   if (!Attributes().IsEmpty()) {
     return true;
   }
   return attributes_ != nullptr && attributes_->hasAttributes();
 }
bridge/core/executing_context.h (1)

201-203: Idle-state flag wiring is straightforward; consider thread-safety constraints

The new isIdle() / SetIsIdle() accessors and is_idle_ member are simple and consistent. This is fine as long as all reads/writes happen on the JS thread, like the rest of the non-atomic flags here.

If there’s any chance SetIsIdle() is invoked off the JS thread (e.g., from dispatcher callbacks on other threads), consider making is_idle_ an std::atomic<bool> for clarity and safety.

Please verify (by grepping the .cc files) that all SetIsIdle call sites run on the JS thread or behind PostToJs, and adjust to std::atomic<bool> if not. -->

Also applies to: 298-300

bridge/core/css/style_engine.cc (1)

1165-1171: Display:none tracking and CSS variable normalization look correct; consider de-duplicating helper logic

  • Computing display_none_for_invalidation from the final display value and storing it via SetDisplayNoneForStyleInvalidation in both subtree and element-only recalc paths is consistent and gives the invalidation layer accurate per-element information about local display: none.
  • The normalization if (id == CSSPropertyID::kVariable && value_string.IsEmpty()) value_string = " "; is applied uniformly for element styles and pseudo styles, avoiding empty-string payloads for custom properties across the bridge.

The behavior is sound; the only small nit is that the kVariable normalization snippet is repeated several times. If this evolves further, you might want a tiny helper like NormalizeCustomPropertyValue(id, value_string) to keep the logic centralized.

-->

Also applies to: 1205-1223, 1373-1380, 1479-1485, 1517-1523, 1613-1616, 1667-1673

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4d4513a and b1dfe36.

⛔ Files ignored due to path filters (5)
  • integration_tests/snapshots/blink/css1/box_properties/padding_left.ts.f039ce881.png is excluded by !**/*.png
  • integration_tests/snapshots/css/css-flexbox/relayout-align.ts.6eab38941.png is excluded by !**/*.png
  • integration_tests/snapshots/css/css-variables/variable-declaration-45.html.6172c1901.png is excluded by !**/*.png
  • integration_tests/snapshots/css/css-variables/variable-declaration-57.html.889f7f911.png is excluded by !**/*.png
  • integration_tests/snapshots/css/css-variables/variable-declaration-58.html.e5a37f891.png is excluded by !**/*.png
📒 Files selected for processing (33)
  • bridge/bindings/qjs/qjs_function.cc
  • bridge/bindings/qjs/script_promise_resolver.cc
  • bridge/core/binding_object.cc
  • bridge/core/css/invalidation/invalidation_set_test.cc
  • bridge/core/css/invalidation/pending_invalidations.cc
  • bridge/core/css/invalidation/pending_invalidations_test.cc
  • bridge/core/css/style_engine.cc
  • bridge/core/css/style_engine.h
  • bridge/core/dom/document.cc
  • bridge/core/dom/document.h
  • bridge/core/dom/element.cc
  • bridge/core/dom/element.h
  • bridge/core/dom/frame_request_callback_collection.cc
  • bridge/core/executing_context.cc
  • bridge/core/executing_context.h
  • bridge/core/frame/script_idle_task_controller.cc
  • bridge/core/html/parser/html_parser.cc
  • bridge/core/page.h
  • bridge/include/webf_bridge.h
  • bridge/polyfill/src/test/index.js
  • bridge/test/css_unittests.cmake
  • bridge/webf_bridge.cc
  • integration_tests/lib/bridge/from_native.dart
  • integration_tests/lib/playground.dart
  • integration_tests/lib/webf_tester.dart
  • integration_tests/specs/blink/css1/box_properties/padding_left.ts
  • integration_tests/specs/css/css-text-mixin/text_comprehensive_test.ts
  • integration_tests/specs/css/css-text-mixin/text_effects_test.ts
  • webf/lib/src/bridge/binding_object.dart
  • webf/lib/src/bridge/to_native.dart
  • webf/lib/src/css/style_declaration.dart
  • webf/lib/src/dom/element_widget_adapter.dart
  • webf/lib/src/launcher/view_controller.dart
🧰 Additional context used
📓 Path-based instructions (9)
bridge/**/*.{cc,cpp,h,hpp}

📄 CodeRabbit inference engine (bridge/CLAUDE.md)

bridge/**/*.{cc,cpp,h,hpp}: C++ code should follow Chromium style (.clang-format) with C++17 standard, 120 character column limit, and 2-space indentation
Use WEBF_EXPORT_C macro for exporting C functions to Dart FFI
In FFI contexts, use Dart_Handle instead of Handle for type compatibility
For C++ FFI function naming: use GetObjectPropertiesFromDart for C++ exports, NativeGetObjectPropertiesFunc for Dart typedefs, and GetObjectPropertiesFunc for Dart functions
Lambda signatures in C++ must match expected function signatures to avoid FFI type mismatches
Choose power-of-2 buffer sizes (512, 1024, 2048) for ring buffer implementation, with smaller sizes for DEBUG_BUILD, MOBILE constraints, and larger sizes for DESKTOP performance

Files:

  • bridge/include/webf_bridge.h
  • bridge/core/css/invalidation/pending_invalidations.cc
  • bridge/core/dom/document.cc
  • bridge/core/executing_context.cc
  • bridge/core/frame/script_idle_task_controller.cc
  • bridge/core/css/invalidation/pending_invalidations_test.cc
  • bridge/core/css/style_engine.cc
  • bridge/core/html/parser/html_parser.cc
  • bridge/core/executing_context.h
  • bridge/webf_bridge.cc
  • bridge/core/dom/element.h
  • bridge/core/dom/frame_request_callback_collection.cc
  • bridge/core/page.h
  • bridge/bindings/qjs/script_promise_resolver.cc
  • bridge/core/dom/document.h
  • bridge/core/binding_object.cc
  • bridge/core/css/style_engine.h
  • bridge/bindings/qjs/qjs_function.cc
  • bridge/core/css/invalidation/invalidation_set_test.cc
  • bridge/core/dom/element.cc
bridge/**/*.{h,hpp}

📄 CodeRabbit inference engine (bridge/CLAUDE.md)

bridge/**/*.{h,hpp}: Ring buffer command structure should use enum Type : uint8_t for command types with union for type-specific data to ensure type-safe and cache-friendly command handling
Ring buffer implementation should use alignas(64) for atomic head and tail pointers, std::atomic<size_t> for thread-safe synchronization, and power-of-2 buffer sizes enforced with static_assert

Files:

  • bridge/include/webf_bridge.h
  • bridge/core/executing_context.h
  • bridge/core/dom/element.h
  • bridge/core/page.h
  • bridge/core/dom/document.h
  • bridge/core/css/style_engine.h
bridge/**/*.{cc,h}

📄 CodeRabbit inference engine (AGENTS.md)

C++ code in bridge module must use C++17 standard with 2-space indentation, 120 column limit, and follow Chromium style guide as defined in .clang-format

bridge/**/*.{cc,h}: Use RAII patterns in C++ where possible for resource management
Use PostToJs for executing operations on the JS thread in FFI
Use PostToDart for returning results to Dart isolate
Avoid PostToJsSync synchronous execution when possible

C++ bridge code must use 2-space indent, 120 column line limit, and follow Chromium style via .clang-format

Files:

  • bridge/include/webf_bridge.h
  • bridge/core/css/invalidation/pending_invalidations.cc
  • bridge/core/dom/document.cc
  • bridge/core/executing_context.cc
  • bridge/core/frame/script_idle_task_controller.cc
  • bridge/core/css/invalidation/pending_invalidations_test.cc
  • bridge/core/css/style_engine.cc
  • bridge/core/html/parser/html_parser.cc
  • bridge/core/executing_context.h
  • bridge/webf_bridge.cc
  • bridge/core/dom/element.h
  • bridge/core/dom/frame_request_callback_collection.cc
  • bridge/core/page.h
  • bridge/bindings/qjs/script_promise_resolver.cc
  • bridge/core/dom/document.h
  • bridge/core/binding_object.cc
  • bridge/core/css/style_engine.h
  • bridge/bindings/qjs/qjs_function.cc
  • bridge/core/css/invalidation/invalidation_set_test.cc
  • bridge/core/dom/element.cc
{bridge/**/*.{cc,h},webf/**/*.dart}

📄 CodeRabbit inference engine (CLAUDE.md)

Document memory ownership clearly in FFI implementations

Files:

  • bridge/include/webf_bridge.h
  • bridge/core/css/invalidation/pending_invalidations.cc
  • bridge/core/dom/document.cc
  • bridge/core/executing_context.cc
  • bridge/core/frame/script_idle_task_controller.cc
  • webf/lib/src/launcher/view_controller.dart
  • bridge/core/css/invalidation/pending_invalidations_test.cc
  • bridge/core/css/style_engine.cc
  • webf/lib/src/dom/element_widget_adapter.dart
  • bridge/core/html/parser/html_parser.cc
  • bridge/core/executing_context.h
  • bridge/webf_bridge.cc
  • bridge/core/dom/element.h
  • bridge/core/dom/frame_request_callback_collection.cc
  • bridge/core/page.h
  • bridge/bindings/qjs/script_promise_resolver.cc
  • bridge/core/dom/document.h
  • webf/lib/src/bridge/binding_object.dart
  • bridge/core/binding_object.cc
  • bridge/core/css/style_engine.h
  • bridge/bindings/qjs/qjs_function.cc
  • webf/lib/src/css/style_declaration.dart
  • webf/lib/src/bridge/to_native.dart
  • bridge/core/css/invalidation/invalidation_set_test.cc
  • bridge/core/dom/element.cc
bridge/**/*.{cc,cpp}

📄 CodeRabbit inference engine (bridge/CLAUDE.md)

bridge/**/*.{cc,cpp}: For async FFI operations, use Dart_NewPersistentHandle_DL to keep Dart objects alive, convert back with Dart_HandleFromPersistent_DL before use, and always call Dart_DeletePersistentHandle_DL after the async operation completes
For string handling in FFI, copy strings that might be freed using std::string(const_char_ptr), and use toNativeUtf8() with proper memory deallocation
For async callbacks with potential errors, always provide error path in callbacks (e.g., callback(object, nullptr)), handle cancellation cases in async operations, and propagate errors through callback parameters rather than exceptions
For thread-safe error reporting in FFI, copy error messages before crossing thread boundaries using std::string to ensure string lifetime, and consider error callbacks separate from result callbacks
Avoid PostToJsSync when threads may interdepend to prevent synchronous deadlocks in FFI communication
Ensure callback functions aren't invoked after context destruction to prevent use-after-free errors in FFI async operations
Implement ring buffer overflow handling with metrics and alerts to monitor command buffer capacity
Process multiple UI commands per frame in a loop with a MAX_COMMANDS_PER_FRAME limit to balance responsiveness and performance
Pin threads to cores for optimal cache usage in ring buffer operations by setting CPU affinity for UI threads
Use PostToJs for executing operations on the JS thread from other threads, PostToDart for returning results to Dart isolate, and avoid PostToJsSync to prevent deadlocks

Files:

  • bridge/core/css/invalidation/pending_invalidations.cc
  • bridge/core/dom/document.cc
  • bridge/core/executing_context.cc
  • bridge/core/frame/script_idle_task_controller.cc
  • bridge/core/css/invalidation/pending_invalidations_test.cc
  • bridge/core/css/style_engine.cc
  • bridge/core/html/parser/html_parser.cc
  • bridge/webf_bridge.cc
  • bridge/core/dom/frame_request_callback_collection.cc
  • bridge/bindings/qjs/script_promise_resolver.cc
  • bridge/core/binding_object.cc
  • bridge/bindings/qjs/qjs_function.cc
  • bridge/core/css/invalidation/invalidation_set_test.cc
  • bridge/core/dom/element.cc
bridge/core/**

📄 CodeRabbit inference engine (bridge/AGENTS.md)

Core bridge code should be located in bridge/core/ directory

Files:

  • bridge/core/css/invalidation/pending_invalidations.cc
  • bridge/core/dom/document.cc
  • bridge/core/executing_context.cc
  • bridge/core/frame/script_idle_task_controller.cc
  • bridge/core/css/invalidation/pending_invalidations_test.cc
  • bridge/core/css/style_engine.cc
  • bridge/core/html/parser/html_parser.cc
  • bridge/core/executing_context.h
  • bridge/core/dom/element.h
  • bridge/core/dom/frame_request_callback_collection.cc
  • bridge/core/page.h
  • bridge/core/dom/document.h
  • bridge/core/binding_object.cc
  • bridge/core/css/style_engine.h
  • bridge/core/css/invalidation/invalidation_set_test.cc
  • bridge/core/dom/element.cc
integration_tests/specs/**/*.ts

📄 CodeRabbit inference engine (integration_tests/CLAUDE.md)

integration_tests/specs/**/*.ts: Place tests in appropriate directories under specs/ (css/, dom/, or window/)
Use TypeScript (.ts extension) for test files
Use done() callback for async tests
Use snapshot() for visual regression tests to capture current rendering
Use simulateClick with coordinates for hit testing tests
Test assets should reference files in assets/ directory
Use fdescribe() instead of describe() to run only specific test specs (Jasmine feature)
Use fit() instead of it() to run only specific test cases
Snapshots are stored as images for comparison and failed snapshots generate diff images
The max width of testing window is 340px
Test specs will always pass if there are no existing snapshots
Group related tests in describe blocks
Each test should be independent
Remove created elements after tests (test cleanup)
Use clear, descriptive test names
Test behavior, not implementation
Include edge cases and error conditions in tests
Batch DOM operations to minimize reflows
Use async/await and proper async patterns for asynchronous operations in tests
Measure operations using performance.now() for timing in performance-critical tests

Files:

  • integration_tests/specs/blink/css1/box_properties/padding_left.ts
  • integration_tests/specs/css/css-text-mixin/text_effects_test.ts
  • integration_tests/specs/css/css-text-mixin/text_comprehensive_test.ts
webf/**/*.dart

📄 CodeRabbit inference engine (webf/CLAUDE.md)

webf/**/*.dart: Follow rules in webf/analysis_options.yaml for Dart code style
Use single quotes for strings in Dart code
File names must use snake_case in Dart
Class names must use PascalCase in Dart
Variables and functions must use camelCase in Dart
Prefer final fields when applicable in Dart code
Lines should be max 120 characters in Dart code
Always free allocated memory in Dart FFI using malloc.free() for toNativeUtf8() allocations
Free FFI allocated memory in finally blocks to ensure cleanup on exceptions
Track ownership of allocated pointers in FFI callbacks
Free NativeValue pointers after converting with fromNativeValue in FFI code
Document memory ownership clearly in FFI async callbacks
Implement WidgetElement to create custom Flutter widgets integrated into WebF's DOM tree
Register custom WidgetElements using WidgetElementRegistry.register(tagName, builder)
Override buildWidget(BuildContext context) method in WidgetElement to build the Flutter widget
Call updateWidget() when attributes change in WidgetElement implementations
Dispose controllers and subscriptions in WidgetElement for memory management
Follow W3C event standards when dispatching events from WidgetElement
Minimize widget rebuilds in WidgetElement for performance optimization
Implement ARIA attributes in WidgetElement when applicable for accessibility

Dart code in webf module must follow naming conventions: snake_case for file names, PascalCase for classes, and camelCase for class members

webf/**/*.dart: Always free allocated memory in Dart FFI
Use malloc.free() for toNativeUtf8() allocations in Dart FFI
Track pointer ownership in callbacks within Dart FFI

Files:

  • webf/lib/src/launcher/view_controller.dart
  • webf/lib/src/dom/element_widget_adapter.dart
  • webf/lib/src/bridge/binding_object.dart
  • webf/lib/src/css/style_declaration.dart
  • webf/lib/src/bridge/to_native.dart
webf/lib/src/css/**/*.dart

📄 CodeRabbit inference engine (webf/CLAUDE.md)

Use CSSRenderStyle for style computation and storage in Dart CSS code

Files:

  • webf/lib/src/css/style_declaration.dart
🧠 Learnings (65)
📓 Common learnings
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/lib/src/css/**/*.dart : Use CSSRenderStyle for style computation and storage in Dart CSS code
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/**/*.dart : Minimize widget rebuilds in WidgetElement for performance optimization
Learnt from: CR
Repo: openwebf/webf PR: 0
File: bridge/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:15.946Z
Learning: Applies to bridge/**/*.{cc,cpp} : Use PostToJs for executing operations on the JS thread from other threads, PostToDart for returning results to Dart isolate, and avoid PostToJsSync to prevent deadlocks
Learnt from: CR
Repo: openwebf/webf PR: 0
File: integration_tests/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:27.888Z
Learning: Applies to integration_tests/specs/**/*.ts : Batch DOM operations to minimize reflows
📚 Learning: 2025-12-08T23:28:11.651Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-08T23:28:11.651Z
Learning: Applies to webf/test/**/*.dart : Dart/Flutter widget and unit tests must be placed in `webf/test/` and use `WebFWidgetTestUtils` and `pumpAndSettle()` where needed

Applied to files:

  • integration_tests/lib/webf_tester.dart
  • integration_tests/lib/playground.dart
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/test/**/*_test.dart : Use WebFWidgetTestUtils.prepareWidgetTest() to test HTML/CSS rendering in widget unit tests

Applied to files:

  • integration_tests/lib/webf_tester.dart
  • integration_tests/lib/playground.dart
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/test/**/*_test.dart : Call setupTest() in setUpAll() method for one-time setup in unit tests

Applied to files:

  • integration_tests/lib/webf_tester.dart
  • integration_tests/lib/playground.dart
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/test/**/*_test.dart : Use mock bundles from test/src/foundation/mock_bundle.dart for testing in unit tests

Applied to files:

  • integration_tests/lib/webf_tester.dart
  • webf/lib/src/bridge/binding_object.dart
📚 Learning: 2025-12-08T23:28:11.651Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-08T23:28:11.651Z
Learning: Applies to webf/integration_test/**/*.dart : Dart/Flutter integration tests must be placed in `webf/integration_test/` directory

Applied to files:

  • integration_tests/lib/webf_tester.dart
  • integration_tests/lib/playground.dart
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/test/**/*_test.dart : When testing with WebFController, wait for initialization with: await controller.controlledInitCompleter.future

Applied to files:

  • integration_tests/lib/webf_tester.dart
  • integration_tests/lib/playground.dart
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Use widget unit tests to verify rendering changes with: cd webf && flutter test test/src/rendering/

Applied to files:

  • integration_tests/lib/webf_tester.dart
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/integration_tests/specs/**/*.dart : Use snapshot tests in integration_tests/specs/ for visual regression testing with await snapshot()

Applied to files:

  • integration_tests/lib/webf_tester.dart
  • integration_tests/lib/playground.dart
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/test/**/*_test.dart : Access render objects in tests to verify layout calculations

Applied to files:

  • integration_tests/lib/webf_tester.dart
  • integration_tests/specs/css/css-text-mixin/text_comprehensive_test.ts
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Run Flutter dart tests with: cd webf && flutter test

Applied to files:

  • integration_tests/lib/webf_tester.dart
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/lib/bridge.dart : lib/bridge.dart contains FFI bindings to C++ bridge

Applied to files:

  • integration_tests/lib/webf_tester.dart
  • bridge/include/webf_bridge.h
  • integration_tests/lib/bridge/from_native.dart
  • bridge/webf_bridge.cc
  • integration_tests/lib/playground.dart
  • webf/lib/src/bridge/binding_object.dart
  • bridge/bindings/qjs/qjs_function.cc
  • webf/lib/src/bridge/to_native.dart
📚 Learning: 2025-12-13T16:32:47.644Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T16:32:47.644Z
Learning: Applies to bridge/**/*.{cc,h} : Use `PostToDart` for returning results to Dart isolate

Applied to files:

  • integration_tests/lib/webf_tester.dart
  • bridge/include/webf_bridge.h
  • integration_tests/lib/bridge/from_native.dart
  • bridge/webf_bridge.cc
  • integration_tests/lib/playground.dart
  • webf/lib/src/bridge/binding_object.dart
  • bridge/core/binding_object.cc
  • webf/lib/src/bridge/to_native.dart
📚 Learning: 2025-12-08T23:27:15.946Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: bridge/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:15.946Z
Learning: Applies to bridge/**/*.{cc,cpp,h,hpp} : Use `WEBF_EXPORT_C` macro for exporting C functions to Dart FFI

Applied to files:

  • bridge/include/webf_bridge.h
  • bridge/webf_bridge.cc
  • webf/lib/src/bridge/binding_object.dart
  • webf/lib/src/bridge/to_native.dart
📚 Learning: 2025-12-13T16:32:47.644Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T16:32:47.644Z
Learning: Applies to {bridge/**/*.{cc,h},webf/**/*.dart} : Document memory ownership clearly in FFI implementations

Applied to files:

  • bridge/include/webf_bridge.h
  • integration_tests/lib/bridge/from_native.dart
  • bridge/webf_bridge.cc
  • webf/lib/src/bridge/to_native.dart
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/lib/src/css/**/*.dart : Use CSSRenderStyle for style computation and storage in Dart CSS code

Applied to files:

  • bridge/include/webf_bridge.h
  • webf/lib/src/launcher/view_controller.dart
  • bridge/core/css/style_engine.cc
  • bridge/core/binding_object.cc
  • webf/lib/src/css/style_declaration.dart
  • webf/lib/src/bridge/to_native.dart
  • bridge/core/dom/element.cc
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/**/*.dart : Call updateWidget() when attributes change in WidgetElement implementations

Applied to files:

  • bridge/include/webf_bridge.h
  • webf/lib/src/dom/element_widget_adapter.dart
  • webf/lib/src/bridge/binding_object.dart
  • bridge/core/binding_object.cc
  • webf/lib/src/bridge/to_native.dart
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/**/*.dart : Document memory ownership clearly in FFI async callbacks

Applied to files:

  • bridge/include/webf_bridge.h
  • integration_tests/lib/playground.dart
  • webf/lib/src/bridge/binding_object.dart
  • bridge/core/binding_object.cc
  • webf/lib/src/bridge/to_native.dart
📚 Learning: 2025-12-08T23:27:15.946Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: bridge/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:15.946Z
Learning: Applies to bridge/**/*.{cc,cpp,h,hpp} : For C++ FFI function naming: use `GetObjectPropertiesFromDart` for C++ exports, `NativeGetObjectPropertiesFunc` for Dart typedefs, and `GetObjectPropertiesFunc` for Dart functions

Applied to files:

  • bridge/include/webf_bridge.h
  • integration_tests/lib/bridge/from_native.dart
  • webf/lib/src/bridge/binding_object.dart
  • webf/lib/src/bridge/to_native.dart
📚 Learning: 2025-12-08T23:27:41.357Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: scripts/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:41.357Z
Learning: Applies to scripts/bridge/core/**/*.d.ts : Transform WebF-specific type annotations: `DartImpl<T>` → `T`, `StaticMember<T>` → `T`, `StaticMethod<T>` → `T`, `SupportAsync<T>` → generates both sync and async variants, `DependentsOnLayout<T>` → `T`

Applied to files:

  • bridge/include/webf_bridge.h
  • bridge/webf_bridge.cc
  • webf/lib/src/bridge/binding_object.dart
  • webf/lib/src/bridge/to_native.dart
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: No build needed for Dart-only changes in webf/

Applied to files:

  • bridge/include/webf_bridge.h
  • webf/lib/src/bridge/binding_object.dart
  • webf/lib/src/bridge/to_native.dart
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: DOM element implementations are located in lib/src/dom/

Applied to files:

  • bridge/core/css/invalidation/pending_invalidations.cc
📚 Learning: 2025-12-13T16:32:47.644Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T16:32:47.644Z
Learning: Applies to bridge/**/*.{cc,h} : Avoid `PostToJsSync` synchronous execution when possible

Applied to files:

  • bridge/core/executing_context.cc
  • bridge/webf_bridge.cc
  • bridge/core/dom/frame_request_callback_collection.cc
  • bridge/bindings/qjs/script_promise_resolver.cc
📚 Learning: 2025-12-08T23:27:15.946Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: bridge/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:15.946Z
Learning: Applies to bridge/**/*.{cc,cpp} : Avoid `PostToJsSync` when threads may interdepend to prevent synchronous deadlocks in FFI communication

Applied to files:

  • bridge/core/executing_context.cc
  • bridge/core/frame/script_idle_task_controller.cc
  • bridge/webf_bridge.cc
  • bridge/core/dom/frame_request_callback_collection.cc
  • bridge/core/page.h
  • bridge/bindings/qjs/script_promise_resolver.cc
  • bridge/bindings/qjs/qjs_function.cc
📚 Learning: 2025-12-08T23:27:15.946Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: bridge/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:15.946Z
Learning: Applies to bridge/**/*.{cc,cpp} : Use PostToJs for executing operations on the JS thread from other threads, PostToDart for returning results to Dart isolate, and avoid PostToJsSync to prevent deadlocks

Applied to files:

  • bridge/core/executing_context.cc
  • bridge/webf_bridge.cc
  • webf/lib/src/bridge/binding_object.dart
  • bridge/bindings/qjs/qjs_function.cc
📚 Learning: 2025-12-08T23:27:15.946Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: bridge/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:15.946Z
Learning: Applies to bridge/**/*.{cc,cpp} : Ensure callback functions aren't invoked after context destruction to prevent use-after-free errors in FFI async operations

Applied to files:

  • bridge/core/frame/script_idle_task_controller.cc
  • bridge/core/dom/frame_request_callback_collection.cc
📚 Learning: 2025-12-08T23:27:27.888Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: integration_tests/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:27.888Z
Learning: Applies to integration_tests/specs/**/*.ts : Test behavior, not implementation

Applied to files:

  • integration_tests/specs/blink/css1/box_properties/padding_left.ts
  • integration_tests/specs/css/css-text-mixin/text_comprehensive_test.ts
📚 Learning: 2025-12-08T23:27:27.888Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: integration_tests/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:27.888Z
Learning: Applies to integration_tests/specs/**/*.ts : Batch DOM operations to minimize reflows

Applied to files:

  • integration_tests/specs/blink/css1/box_properties/padding_left.ts
  • bridge/polyfill/src/test/index.js
  • integration_tests/specs/css/css-text-mixin/text_effects_test.ts
📚 Learning: 2025-12-08T23:27:27.888Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: integration_tests/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:27.888Z
Learning: Applies to integration_tests/specs/**/*.ts : Place tests in appropriate directories under `specs/` (css/, dom/, or window/)

Applied to files:

  • integration_tests/specs/blink/css1/box_properties/padding_left.ts
  • integration_tests/specs/css/css-text-mixin/text_comprehensive_test.ts
📚 Learning: 2025-12-08T23:27:27.888Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: integration_tests/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:27.888Z
Learning: Applies to integration_tests/specs/**/*.ts : The max width of testing window is 340px

Applied to files:

  • integration_tests/specs/blink/css1/box_properties/padding_left.ts
📚 Learning: 2025-12-08T23:27:27.888Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: integration_tests/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:27.888Z
Learning: Applies to integration_tests/specs/**/*.ts : Remove created elements after tests (test cleanup)

Applied to files:

  • integration_tests/specs/blink/css1/box_properties/padding_left.ts
  • bridge/polyfill/src/test/index.js
📚 Learning: 2025-12-08T23:27:15.946Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: bridge/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:15.946Z
Learning: Applies to bridge/**/*.{cc,cpp,h,hpp} : In FFI contexts, use `Dart_Handle` instead of `Handle` for type compatibility

Applied to files:

  • integration_tests/lib/bridge/from_native.dart
  • integration_tests/lib/playground.dart
📚 Learning: 2025-12-08T23:27:15.946Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: bridge/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:15.946Z
Learning: Applies to bridge/**/*.{cc,cpp} : For async FFI operations, use `Dart_NewPersistentHandle_DL` to keep Dart objects alive, convert back with `Dart_HandleFromPersistent_DL` before use, and always call `Dart_DeletePersistentHandle_DL` after the async operation completes

Applied to files:

  • integration_tests/lib/bridge/from_native.dart
  • webf/lib/src/bridge/binding_object.dart
📚 Learning: 2025-12-13T16:32:47.644Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T16:32:47.644Z
Learning: Applies to webf/**/*.dart : Track pointer ownership in callbacks within Dart FFI

Applied to files:

  • integration_tests/lib/bridge/from_native.dart
  • integration_tests/lib/playground.dart
  • webf/lib/src/bridge/binding_object.dart
  • bridge/core/binding_object.cc
  • bridge/bindings/qjs/qjs_function.cc
  • webf/lib/src/bridge/to_native.dart
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/**/*.dart : Track ownership of allocated pointers in FFI callbacks

Applied to files:

  • integration_tests/lib/bridge/from_native.dart
  • integration_tests/lib/playground.dart
  • webf/lib/src/bridge/binding_object.dart
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/**/*.dart : Free NativeValue pointers after converting with fromNativeValue in FFI code

Applied to files:

  • integration_tests/lib/bridge/from_native.dart
📚 Learning: 2025-12-13T16:32:47.644Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T16:32:47.644Z
Learning: Applies to webf/**/*.dart : Use `malloc.free()` for `toNativeUtf8()` allocations in Dart FFI

Applied to files:

  • integration_tests/lib/bridge/from_native.dart
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/**/*.dart : Always free allocated memory in Dart FFI using malloc.free() for toNativeUtf8() allocations

Applied to files:

  • integration_tests/lib/bridge/from_native.dart
📚 Learning: 2025-12-13T16:32:47.644Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T16:32:47.644Z
Learning: Applies to webf/**/*.dart : Always free allocated memory in Dart FFI

Applied to files:

  • integration_tests/lib/bridge/from_native.dart
📚 Learning: 2025-12-08T23:28:11.651Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-08T23:28:11.651Z
Learning: Applies to bridge/test/**/*.{cc,h} : Bridge unit tests must be added under `bridge/test/` and use Google Test framework

Applied to files:

  • bridge/core/css/invalidation/pending_invalidations_test.cc
  • bridge/test/css_unittests.cmake
  • bridge/core/css/invalidation/invalidation_set_test.cc
📚 Learning: 2025-12-08T23:27:15.946Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: bridge/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:15.946Z
Learning: Applies to bridge/test/**/*.{cc,cpp} : Add bridge unit test files to `bridge/test/` directory and use Google Test macros: `TEST()`, `EXPECT_EQ()`, etc. Tests are automatically discovered by CMake

Applied to files:

  • bridge/core/css/invalidation/pending_invalidations_test.cc
  • bridge/test/css_unittests.cmake
  • bridge/core/css/invalidation/invalidation_set_test.cc
📚 Learning: 2025-12-21T14:42:52.627Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: bridge/AGENTS.md:0-0
Timestamp: 2025-12-21T14:42:52.627Z
Learning: Applies to bridge/test/**/*.{cc,h} : Bridge unit tests must use GoogleTest framework, keep tests small and behavior-focused, and mirror source paths under `bridge/test/`

Applied to files:

  • bridge/core/css/invalidation/pending_invalidations_test.cc
  • bridge/test/css_unittests.cmake
  • bridge/core/css/invalidation/invalidation_set_test.cc
📚 Learning: 2025-12-08T23:28:11.651Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-08T23:28:11.651Z
Learning: Applies to bridge/**/*.{cc,h} : C++ code in bridge module must use C++17 standard with 2-space indentation, 120 column limit, and follow Chromium style guide as defined in `.clang-format`

Applied to files:

  • bridge/core/css/invalidation/pending_invalidations_test.cc
  • bridge/webf_bridge.cc
  • bridge/core/css/invalidation/invalidation_set_test.cc
  • bridge/core/dom/element.cc
📚 Learning: 2025-12-21T14:42:52.627Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: bridge/AGENTS.md:0-0
Timestamp: 2025-12-21T14:42:52.627Z
Learning: Applies to bridge/**/*.{cc,h} : C++ bridge code must use 2-space indent, 120 column line limit, and follow Chromium style via `.clang-format`

Applied to files:

  • bridge/core/css/invalidation/pending_invalidations_test.cc
  • bridge/webf_bridge.cc
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/**/*.dart : Minimize widget rebuilds in WidgetElement for performance optimization

Applied to files:

  • webf/lib/src/dom/element_widget_adapter.dart
  • bridge/core/binding_object.cc
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/**/*.dart : Follow W3C event standards when dispatching events from WidgetElement

Applied to files:

  • webf/lib/src/dom/element_widget_adapter.dart
  • bridge/core/binding_object.cc
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/**/*.dart : Implement ARIA attributes in WidgetElement when applicable for accessibility

Applied to files:

  • webf/lib/src/dom/element_widget_adapter.dart
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/**/*.dart : Implement WidgetElement to create custom Flutter widgets integrated into WebF's DOM tree

Applied to files:

  • webf/lib/src/dom/element_widget_adapter.dart
  • webf/lib/src/bridge/binding_object.dart
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/**/*.dart : Dispose controllers and subscriptions in WidgetElement for memory management

Applied to files:

  • webf/lib/src/dom/element_widget_adapter.dart
📚 Learning: 2025-12-08T23:27:15.946Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: bridge/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:15.946Z
Learning: Applies to bridge/**/*.{cc,cpp,h,hpp} : C++ code should follow Chromium style (.clang-format) with C++17 standard, 120 character column limit, and 2-space indentation

Applied to files:

  • bridge/webf_bridge.cc
  • bridge/core/dom/element.cc
📚 Learning: 2025-12-13T16:32:47.644Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T16:32:47.644Z
Learning: Applies to bridge/**/*.{cc,h} : Use `PostToJs` for executing operations on the JS thread in FFI

Applied to files:

  • bridge/webf_bridge.cc
  • bridge/core/dom/frame_request_callback_collection.cc
  • bridge/bindings/qjs/qjs_function.cc
📚 Learning: 2025-12-08T23:27:41.357Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: scripts/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:41.357Z
Learning: Applies to scripts/bridge/polyfill/**/*.{ts,tsx,d.ts} : Include a reference to `webf.d.ts` in polyfill type generation for accessing core types like `EventTarget`

Applied to files:

  • bridge/webf_bridge.cc
📚 Learning: 2025-12-08T23:27:41.357Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: scripts/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:41.357Z
Learning: Applies to scripts/bridge/core/**/*.d.ts : Create a `webf` namespace containing all type exports from merged bridge core types

Applied to files:

  • bridge/webf_bridge.cc
📚 Learning: 2025-12-08T23:27:27.888Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: integration_tests/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:27.888Z
Learning: Applies to integration_tests/specs/**/*.ts : Measure operations using `performance.now()` for timing in performance-critical tests

Applied to files:

  • bridge/polyfill/src/test/index.js
📚 Learning: 2025-12-08T23:27:27.888Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: integration_tests/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:27.888Z
Learning: Applies to integration_tests/specs/**/*.ts : Use `snapshot()` for visual regression tests to capture current rendering

Applied to files:

  • bridge/polyfill/src/test/index.js
  • integration_tests/specs/css/css-text-mixin/text_effects_test.ts
📚 Learning: 2025-12-08T23:27:27.888Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: integration_tests/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:27.888Z
Learning: Applies to integration_tests/specs/**/*.ts : Use `fdescribe()` instead of `describe()` to run only specific test specs (Jasmine feature)

Applied to files:

  • bridge/polyfill/src/test/index.js
📚 Learning: 2025-12-08T23:27:15.946Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: bridge/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:15.946Z
Learning: Applies to bridge/**/*.{cc,cpp} : For async callbacks with potential errors, always provide error path in callbacks (e.g., `callback(object, nullptr)`), handle cancellation cases in async operations, and propagate errors through callback parameters rather than exceptions

Applied to files:

  • bridge/core/dom/frame_request_callback_collection.cc
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/lib/src/rendering/**/*.dart : Use RenderBoxModel as base class for layout in Dart rendering code

Applied to files:

  • webf/lib/src/bridge/binding_object.dart
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/**/*.dart : Free FFI allocated memory in finally blocks to ensure cleanup on exceptions

Applied to files:

  • webf/lib/src/bridge/binding_object.dart
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/**/*.dart : Follow rules in webf/analysis_options.yaml for Dart code style

Applied to files:

  • bridge/core/binding_object.cc
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/**/*.{cpp,h,hpp} : Use RAII patterns in C++ where possible for memory management

Applied to files:

  • bridge/bindings/qjs/qjs_function.cc
📚 Learning: 2025-12-08T23:27:27.888Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: integration_tests/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:27.888Z
Learning: Applies to integration_tests/specs/**/*.ts : Include edge cases and error conditions in tests

Applied to files:

  • integration_tests/specs/css/css-text-mixin/text_comprehensive_test.ts
📚 Learning: 2025-12-08T23:27:27.888Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: integration_tests/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:27.888Z
Learning: Applies to integration_tests/specs/**/*.ts : Use clear, descriptive test names

Applied to files:

  • integration_tests/specs/css/css-text-mixin/text_comprehensive_test.ts
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: CSS property implementations are located in lib/src/css/

Applied to files:

  • webf/lib/src/css/style_declaration.dart
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/**/*.dart : Variables and functions must use camelCase in Dart

Applied to files:

  • webf/lib/src/css/style_declaration.dart
🧬 Code graph analysis (8)
bridge/include/webf_bridge.h (1)
bridge/webf_bridge.cc (2)
  • updateStyleForThisDocument (309-363)
  • updateStyleForThisDocument (309-309)
bridge/core/dom/document.cc (1)
bridge/core/dom/document.h (1)
  • update_style_for_this_document_in_progress_ (277-289)
bridge/core/html/parser/html_parser.cc (1)
integration_tests/scripts/html_loader.js (1)
  • root (141-141)
bridge/core/executing_context.h (2)
bridge/core/dom/document.h (1)
  • bool (278-279)
bridge/core/page.h (1)
  • bool (144-144)
bridge/core/dom/element.h (1)
bridge/core/dom/element.cc (2)
  • Attributes (76-81)
  • Attributes (76-76)
bridge/core/page.h (1)
bridge/core/dom/document.h (2)
  • update_style_for_this_document_in_progress_ (277-289)
  • bool (278-279)
bridge/core/css/style_engine.h (1)
bridge/core/css/invalidation/pending_invalidations.h (1)
  • PendingInvalidations (106-131)
bridge/core/dom/element.cc (2)
bridge/core/dom/element.h (1)
  • GetElementData (365-365)
bridge/core/css/style_engine.cc (2)
  • id (83-83)
  • id (83-83)
🪛 GitHub Actions: Run Code Linter
bridge/test/css_unittests.cmake

[error] 67-67: CMake configuration failed: No SOURCES given to target 'webf_css_unittests' while running 'cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON .'

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: build_windows_bridge (Debug)
  • GitHub Check: build_bridge
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (rust)
  • GitHub Check: Analyze (c-cpp)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
bridge/core/executing_context.cc (1)

188-204: Ensure SetIsIdle(false) is always paired with a path back to idle

Right now several eval error paths set the context non‑idle and then return before DrainMicrotasks() (which calls SetIsIdle(true)), leaving isIdle() stuck at false and effectively blocking vsync‑driven style updates:

  • EvaluateJavaScript(const char* …, uint8_t** parsed_bytecodes, …) bytecode path when JS_Eval(..., COMPILE_ONLY) returns an exception.
  • EvaluateModule(...) in both bytecode and non‑bytecode paths when the compile step fails.
  • EvaluateByteCode(...) when JS_ReadObject returns an exception.

Also, SetIsIdle(false) is currently placed before the 100MB size check in the JS and bytecode eval paths, so a size error can leave the context marked busy even though no script ran.

To avoid contexts getting permanently “non‑idle”:

  • Move SetIsIdle(false) after the size‑limit guards so purely‑validation failures never touch idle state.
  • In all branches that return immediately after HandleException(...) on a compiled script/module/bytecode failure, call DrainMicrotasks() (or at least SetIsIdle(true)) before returning so the idle flag is restored even on errors.

For example:

-  JSValue byte_object =
-      JS_Eval(script_state_.ctx(), code, code_len, sourceURL, JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY);
-
-  if (JS_IsException(byte_object)) {
-    HandleException(&byte_object);
-    return false;
-  }
+  JSValue byte_object =
+      JS_Eval(script_state_.ctx(), code, code_len, sourceURL, JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY);
+
+  if (JS_IsException(byte_object)) {
+    HandleException(&byte_object);
+    DrainMicrotasks();  // Will call SetIsIdle(true)
+    return false;
+  }

and similarly for the other early‑return sites, plus moving SetIsIdle(false) below size checks in the eval entry points.

Also applies to: 295-347, 380-431, 546-551

bridge/core/css/style_engine.cc (1)

1203-1221: Fix uses of value_string before declaration in pseudo‑style emission

In two pseudo‑style loops, value_string is checked for emptiness before it has been declared/initialized, which will not compile and would be undefined behavior even if it did:

  • RecalcStyleForSubtreeemit_pseudo_if_any lambda: if (id == CSSPropertyID::kVariable && value_string.IsEmpty()) precedes the String value_string = … declaration.
  • RecalcStyleForElementOnlysend_pseudo_for lambda (second one): same pattern.

The normalization to a single‑space placeholder for empty CSS variable values should run after you’ve obtained value_string. For example:

Proposed fix for both pseudo‑style loops
@@ RecalcStyleForSubtree → emit_pseudo_if_any
-            for (unsigned i = 0; i < pseudo_set->PropertyCount(); ++i) {
-              auto prop = pseudo_set->PropertyAt(i);
-              CSSPropertyID id = prop.Id();
-              if (id == CSSPropertyID::kInvalid) {
-                continue;
-              }
-              const auto* value_ptr = prop.Value();
-              if (!value_ptr || !(*value_ptr)) {
-                continue;
-              }
-              if (id == CSSPropertyID::kVariable && value_string.IsEmpty()) {
-                value_string = String(" ");
-              }
-              AtomicString prop_name = prop.Name().ToAtomicString();
-              String value_string = pseudo_set->GetPropertyValueWithHint(prop_name, i);
+            for (unsigned i = 0; i < pseudo_set->PropertyCount(); ++i) {
+              auto prop = pseudo_set->PropertyAt(i);
+              CSSPropertyID id = prop.Id();
+              if (id == CSSPropertyID::kInvalid) {
+                continue;
+              }
+              const auto* value_ptr = prop.Value();
+              if (!value_ptr || !(*value_ptr)) {
+                continue;
+              }
+              AtomicString prop_name = prop.Name().ToAtomicString();
+              String value_string = pseudo_set->GetPropertyValueWithHint(prop_name, i);
               if (value_string.IsNull()) {
                 value_string = (*value_ptr)->CssTextForSerialization();
               }
+              if (id == CSSPropertyID::kVariable && value_string.IsEmpty()) {
+                value_string = String(" ");
+              }
@@ RecalcStyleForElementOnly → send_pseudo_for (second instance)
-          for (unsigned i = 0; i < pseudo_set->PropertyCount(); ++i) {
-            auto prop = pseudo_set->PropertyAt(i);
-            CSSPropertyID id = prop.Id();
-            if (id == CSSPropertyID::kInvalid) {
-              continue;
-            }
-            const auto* value_ptr = prop.Value();
-            if (!value_ptr || !(*value_ptr)) {
-              continue;
-            }
-            if (id == CSSPropertyID::kVariable && value_string.IsEmpty()) {
-              value_string = String(" ");
-            }
-            AtomicString prop_name = prop.Name().ToAtomicString();
-            String value_string = pseudo_set->GetPropertyValueWithHint(prop_name, i);
+          for (unsigned i = 0; i < pseudo_set->PropertyCount(); ++i) {
+            auto prop = pseudo_set->PropertyAt(i);
+            CSSPropertyID id = prop.Id();
+            if (id == CSSPropertyID::kInvalid) {
+              continue;
+            }
+            const auto* value_ptr = prop.Value();
+            if (!value_ptr || !(*value_ptr)) {
+              continue;
+            }
+            AtomicString prop_name = prop.Name().ToAtomicString();
+            String value_string = pseudo_set->GetPropertyValueWithHint(prop_name, i);
             if (value_string.IsNull()) {
               value_string = (*value_ptr)->CssTextForSerialization();
             }
+            if (id == CSSPropertyID::kVariable && value_string.IsEmpty()) {
+              value_string = String(" ");
+            }

This preserves the intended placeholder behavior while fixing the compile‑time error.

Also applies to: 1689-1696

♻️ Duplicate comments (1)
bridge/bindings/qjs/script_promise_resolver.cc (1)

54-54: Change SetIsIdle(true) to SetIsIdle(false) before promise callback execution.

The pattern across the codebase is consistent: SetIsIdle(false) is set before executing any JS callbacks (e.g., QJSFunction::Invoke, FrameRequestCallbackCollection::Fire, ScriptIdleTaskController::Fire), then SetIsIdle(true) after completion via DrainMicrotasks().

At line 54, SetIsIdle(true) is set before JS_Call, which is semantically incorrect—the context is not idle while executing the promise resolve/reject callbacks. Change to SetIsIdle(false) to match other callback execution patterns.

🧹 Nitpick comments (5)
bridge/core/html/parser/html_parser.cc (2)

302-410: Consider extracting common element creation logic to reduce duplication.

The append_gumbo_child lambda duplicates significant logic from traverseHTML() (lines 138-196 for elements, 198-233 for text/comment/CDATA). Both segments perform identical operations: tag name extraction, namespace-aware element creation, exception handling, attribute parsing, and child traversal.

This duplication creates maintenance overhead—bug fixes or enhancements must be applied in multiple locations.

💡 Refactoring approach

Consider extracting the common element-creation and child-handling logic into separate static helper functions:

// Extract element creation logic
static Element* createElementFromGumbo(
    ExecutingContext* context,
    GumboNode* child,
    ExceptionState& exception_state) {
  // Lines 307-334 logic here
  // Returns nullptr on failure
}

// Extract child appending logic
static bool appendGumboNodeChild(
    ContainerNode* parent,
    GumboNode* child,
    ExecutingContext* context) {
  // Current lambda body here
}

Then both append_gumbo_child and the element handling in traverseHTML can call these shared helpers, ensuring consistent behavior and reducing the risk of divergence.


302-410: Consider extracting the lambda to a static helper function.

This 108-line lambda handles multiple node types and includes substantial logic. Extracting it to a static function would improve readability, testability, and allow reuse without capturing context variables.

💡 Suggested extraction
static bool appendGumboNodeChild(
    ContainerNode* parent,
    GumboNode* child,
    ExecutingContext* context) {
  // Current lambda body
}

Then call it from both the lambda location and potentially from other parsing contexts.

integration_tests/specs/blink/css1/box_properties/padding_left.ts (1)

154-156: Font-family set for rendering consistency.

Setting fontFamily to 'Times' before the snapshot ensures consistent baseline rendering for the list items. This is a good practice for visual regression tests.

Consider whether other tests in this file would benefit from the same font-family setup for cross-platform consistency.

integration_tests/lib/webf_tester.dart (1)

31-31: Consider using late for testContext.

Since testContext is initialized before use in onControllerInit (line 48) and used non-null (line 49), consider declaring it as late Pointer<Void> testContext; instead of nullable to better express the initialization contract.

webf/lib/src/bridge/binding_object.dart (1)

386-427: Layout‑aware flush before geometry binding calls

The _layoutDependentBindingProperties / _layoutDependentBindingMethods filters plus _shouldFlushLayoutForBindingCall and _flushFlutterLayoutIfSafe give a targeted layout flush only for geometry‑sensitive calls and only in safe scheduler phases, which is a good balance between correctness and overhead. Please just double‑check that all entry points into _invokeBindingMethodFromNativeImpl occur when SchedulerBinding/RendererBinding are already initialized, as a call very early in app startup could otherwise trip their instance accessors.

Also applies to: 442-444

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5b42bf5 and 2d4a1c6.

⛔ Files ignored due to path filters (3)
  • integration_tests/snapshots/blink/css1/box_properties/padding_left.ts.f039ce881.png is excluded by !**/*.png
  • integration_tests/snapshots/css/css-flexbox/relayout-align.ts.6eab38941.png is excluded by !**/*.png
  • integration_tests/snapshots/css/css-variables/variable-declaration-57.html.889f7f911.png is excluded by !**/*.png
📒 Files selected for processing (32)
  • bridge/bindings/qjs/qjs_function.cc
  • bridge/bindings/qjs/script_promise_resolver.cc
  • bridge/core/binding_object.cc
  • bridge/core/css/invalidation/invalidation_set_test.cc
  • bridge/core/css/invalidation/pending_invalidations.cc
  • bridge/core/css/invalidation/pending_invalidations_test.cc
  • bridge/core/css/style_engine.cc
  • bridge/core/css/style_engine.h
  • bridge/core/dom/document.cc
  • bridge/core/dom/document.h
  • bridge/core/dom/element.cc
  • bridge/core/dom/element.h
  • bridge/core/dom/frame_request_callback_collection.cc
  • bridge/core/executing_context.cc
  • bridge/core/executing_context.h
  • bridge/core/frame/script_idle_task_controller.cc
  • bridge/core/html/parser/html_parser.cc
  • bridge/core/page.h
  • bridge/include/webf_bridge.h
  • bridge/polyfill/src/test/index.js
  • bridge/test/css_unittests.cmake
  • bridge/webf_bridge.cc
  • integration_tests/lib/bridge/from_native.dart
  • integration_tests/lib/playground.dart
  • integration_tests/lib/webf_tester.dart
  • integration_tests/specs/blink/css1/box_properties/padding_left.ts
  • integration_tests/specs/css/css-text-mixin/text_comprehensive_test.ts
  • webf/lib/src/bridge/binding_object.dart
  • webf/lib/src/bridge/to_native.dart
  • webf/lib/src/css/style_declaration.dart
  • webf/lib/src/dom/element_widget_adapter.dart
  • webf/lib/src/launcher/view_controller.dart
🚧 Files skipped from review as they are similar to previous changes (13)
  • bridge/core/executing_context.h
  • bridge/core/binding_object.cc
  • bridge/core/css/style_engine.h
  • webf/lib/src/css/style_declaration.dart
  • bridge/core/css/invalidation/pending_invalidations.cc
  • bridge/core/css/invalidation/invalidation_set_test.cc
  • bridge/core/frame/script_idle_task_controller.cc
  • bridge/core/css/invalidation/pending_invalidations_test.cc
  • bridge/test/css_unittests.cmake
  • integration_tests/lib/bridge/from_native.dart
  • webf/lib/src/launcher/view_controller.dart
  • bridge/core/dom/document.h
  • integration_tests/specs/css/css-text-mixin/text_comprehensive_test.ts
🧰 Additional context used
📓 Path-based instructions (8)
webf/**/*.dart

📄 CodeRabbit inference engine (webf/CLAUDE.md)

webf/**/*.dart: Follow rules in webf/analysis_options.yaml for Dart code style
Use single quotes for strings in Dart code
File names must use snake_case in Dart
Class names must use PascalCase in Dart
Variables and functions must use camelCase in Dart
Prefer final fields when applicable in Dart code
Lines should be max 120 characters in Dart code
Always free allocated memory in Dart FFI using malloc.free() for toNativeUtf8() allocations
Free FFI allocated memory in finally blocks to ensure cleanup on exceptions
Track ownership of allocated pointers in FFI callbacks
Free NativeValue pointers after converting with fromNativeValue in FFI code
Document memory ownership clearly in FFI async callbacks
Implement WidgetElement to create custom Flutter widgets integrated into WebF's DOM tree
Register custom WidgetElements using WidgetElementRegistry.register(tagName, builder)
Override buildWidget(BuildContext context) method in WidgetElement to build the Flutter widget
Call updateWidget() when attributes change in WidgetElement implementations
Dispose controllers and subscriptions in WidgetElement for memory management
Follow W3C event standards when dispatching events from WidgetElement
Minimize widget rebuilds in WidgetElement for performance optimization
Implement ARIA attributes in WidgetElement when applicable for accessibility

Dart code in webf module must follow naming conventions: snake_case for file names, PascalCase for classes, and camelCase for class members

webf/**/*.dart: Always free allocated memory in Dart FFI
Use malloc.free() for toNativeUtf8() allocations in Dart FFI
Track pointer ownership in callbacks within Dart FFI

Files:

  • webf/lib/src/bridge/to_native.dart
  • webf/lib/src/bridge/binding_object.dart
  • webf/lib/src/dom/element_widget_adapter.dart
{bridge/**/*.{cc,h},webf/**/*.dart}

📄 CodeRabbit inference engine (CLAUDE.md)

Document memory ownership clearly in FFI implementations

Files:

  • webf/lib/src/bridge/to_native.dart
  • bridge/bindings/qjs/qjs_function.cc
  • bridge/core/dom/element.cc
  • bridge/core/dom/document.cc
  • bridge/core/dom/frame_request_callback_collection.cc
  • bridge/core/page.h
  • bridge/webf_bridge.cc
  • bridge/core/dom/element.h
  • bridge/core/css/style_engine.cc
  • bridge/core/html/parser/html_parser.cc
  • webf/lib/src/bridge/binding_object.dart
  • bridge/include/webf_bridge.h
  • webf/lib/src/dom/element_widget_adapter.dart
  • bridge/bindings/qjs/script_promise_resolver.cc
  • bridge/core/executing_context.cc
bridge/**/*.{cc,cpp,h,hpp}

📄 CodeRabbit inference engine (bridge/CLAUDE.md)

bridge/**/*.{cc,cpp,h,hpp}: C++ code should follow Chromium style (.clang-format) with C++17 standard, 120 character column limit, and 2-space indentation
Use WEBF_EXPORT_C macro for exporting C functions to Dart FFI
In FFI contexts, use Dart_Handle instead of Handle for type compatibility
For C++ FFI function naming: use GetObjectPropertiesFromDart for C++ exports, NativeGetObjectPropertiesFunc for Dart typedefs, and GetObjectPropertiesFunc for Dart functions
Lambda signatures in C++ must match expected function signatures to avoid FFI type mismatches
Choose power-of-2 buffer sizes (512, 1024, 2048) for ring buffer implementation, with smaller sizes for DEBUG_BUILD, MOBILE constraints, and larger sizes for DESKTOP performance

Files:

  • bridge/bindings/qjs/qjs_function.cc
  • bridge/core/dom/element.cc
  • bridge/core/dom/document.cc
  • bridge/core/dom/frame_request_callback_collection.cc
  • bridge/core/page.h
  • bridge/webf_bridge.cc
  • bridge/core/dom/element.h
  • bridge/core/css/style_engine.cc
  • bridge/core/html/parser/html_parser.cc
  • bridge/include/webf_bridge.h
  • bridge/bindings/qjs/script_promise_resolver.cc
  • bridge/core/executing_context.cc
bridge/**/*.{cc,cpp}

📄 CodeRabbit inference engine (bridge/CLAUDE.md)

bridge/**/*.{cc,cpp}: For async FFI operations, use Dart_NewPersistentHandle_DL to keep Dart objects alive, convert back with Dart_HandleFromPersistent_DL before use, and always call Dart_DeletePersistentHandle_DL after the async operation completes
For string handling in FFI, copy strings that might be freed using std::string(const_char_ptr), and use toNativeUtf8() with proper memory deallocation
For async callbacks with potential errors, always provide error path in callbacks (e.g., callback(object, nullptr)), handle cancellation cases in async operations, and propagate errors through callback parameters rather than exceptions
For thread-safe error reporting in FFI, copy error messages before crossing thread boundaries using std::string to ensure string lifetime, and consider error callbacks separate from result callbacks
Avoid PostToJsSync when threads may interdepend to prevent synchronous deadlocks in FFI communication
Ensure callback functions aren't invoked after context destruction to prevent use-after-free errors in FFI async operations
Implement ring buffer overflow handling with metrics and alerts to monitor command buffer capacity
Process multiple UI commands per frame in a loop with a MAX_COMMANDS_PER_FRAME limit to balance responsiveness and performance
Pin threads to cores for optimal cache usage in ring buffer operations by setting CPU affinity for UI threads
Use PostToJs for executing operations on the JS thread from other threads, PostToDart for returning results to Dart isolate, and avoid PostToJsSync to prevent deadlocks

Files:

  • bridge/bindings/qjs/qjs_function.cc
  • bridge/core/dom/element.cc
  • bridge/core/dom/document.cc
  • bridge/core/dom/frame_request_callback_collection.cc
  • bridge/webf_bridge.cc
  • bridge/core/css/style_engine.cc
  • bridge/core/html/parser/html_parser.cc
  • bridge/bindings/qjs/script_promise_resolver.cc
  • bridge/core/executing_context.cc
bridge/**/*.{cc,h}

📄 CodeRabbit inference engine (AGENTS.md)

C++ code in bridge module must use C++17 standard with 2-space indentation, 120 column limit, and follow Chromium style guide as defined in .clang-format

bridge/**/*.{cc,h}: Use RAII patterns in C++ where possible for resource management
Use PostToJs for executing operations on the JS thread in FFI
Use PostToDart for returning results to Dart isolate
Avoid PostToJsSync synchronous execution when possible

C++ bridge code must use 2-space indent, 120 column line limit, and follow Chromium style via .clang-format

Files:

  • bridge/bindings/qjs/qjs_function.cc
  • bridge/core/dom/element.cc
  • bridge/core/dom/document.cc
  • bridge/core/dom/frame_request_callback_collection.cc
  • bridge/core/page.h
  • bridge/webf_bridge.cc
  • bridge/core/dom/element.h
  • bridge/core/css/style_engine.cc
  • bridge/core/html/parser/html_parser.cc
  • bridge/include/webf_bridge.h
  • bridge/bindings/qjs/script_promise_resolver.cc
  • bridge/core/executing_context.cc
bridge/core/**

📄 CodeRabbit inference engine (bridge/AGENTS.md)

Core bridge code should be located in bridge/core/ directory

Files:

  • bridge/core/dom/element.cc
  • bridge/core/dom/document.cc
  • bridge/core/dom/frame_request_callback_collection.cc
  • bridge/core/page.h
  • bridge/core/dom/element.h
  • bridge/core/css/style_engine.cc
  • bridge/core/html/parser/html_parser.cc
  • bridge/core/executing_context.cc
bridge/**/*.{h,hpp}

📄 CodeRabbit inference engine (bridge/CLAUDE.md)

bridge/**/*.{h,hpp}: Ring buffer command structure should use enum Type : uint8_t for command types with union for type-specific data to ensure type-safe and cache-friendly command handling
Ring buffer implementation should use alignas(64) for atomic head and tail pointers, std::atomic<size_t> for thread-safe synchronization, and power-of-2 buffer sizes enforced with static_assert

Files:

  • bridge/core/page.h
  • bridge/core/dom/element.h
  • bridge/include/webf_bridge.h
integration_tests/specs/**/*.ts

📄 CodeRabbit inference engine (integration_tests/CLAUDE.md)

integration_tests/specs/**/*.ts: Place tests in appropriate directories under specs/ (css/, dom/, or window/)
Use TypeScript (.ts extension) for test files
Use done() callback for async tests
Use snapshot() for visual regression tests to capture current rendering
Use simulateClick with coordinates for hit testing tests
Test assets should reference files in assets/ directory
Use fdescribe() instead of describe() to run only specific test specs (Jasmine feature)
Use fit() instead of it() to run only specific test cases
Snapshots are stored as images for comparison and failed snapshots generate diff images
The max width of testing window is 340px
Test specs will always pass if there are no existing snapshots
Group related tests in describe blocks
Each test should be independent
Remove created elements after tests (test cleanup)
Use clear, descriptive test names
Test behavior, not implementation
Include edge cases and error conditions in tests
Batch DOM operations to minimize reflows
Use async/await and proper async patterns for asynchronous operations in tests
Measure operations using performance.now() for timing in performance-critical tests

Files:

  • integration_tests/specs/blink/css1/box_properties/padding_left.ts
🧠 Learnings (44)
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/lib/bridge.dart : lib/bridge.dart contains FFI bindings to C++ bridge

Applied to files:

  • webf/lib/src/bridge/to_native.dart
  • bridge/bindings/qjs/qjs_function.cc
  • integration_tests/lib/webf_tester.dart
  • bridge/webf_bridge.cc
  • integration_tests/lib/playground.dart
  • webf/lib/src/bridge/binding_object.dart
  • bridge/include/webf_bridge.h
📚 Learning: 2025-12-08T23:27:15.946Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: bridge/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:15.946Z
Learning: Applies to bridge/**/*.{cc,cpp,h,hpp} : For C++ FFI function naming: use `GetObjectPropertiesFromDart` for C++ exports, `NativeGetObjectPropertiesFunc` for Dart typedefs, and `GetObjectPropertiesFunc` for Dart functions

Applied to files:

  • webf/lib/src/bridge/to_native.dart
  • webf/lib/src/bridge/binding_object.dart
  • bridge/include/webf_bridge.h
📚 Learning: 2025-12-08T23:27:15.946Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: bridge/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:15.946Z
Learning: Applies to bridge/**/*.{cc,cpp,h,hpp} : Use `WEBF_EXPORT_C` macro for exporting C functions to Dart FFI

Applied to files:

  • webf/lib/src/bridge/to_native.dart
  • bridge/webf_bridge.cc
  • integration_tests/lib/playground.dart
  • webf/lib/src/bridge/binding_object.dart
  • bridge/include/webf_bridge.h
📚 Learning: 2025-12-13T16:32:47.644Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T16:32:47.644Z
Learning: Applies to bridge/**/*.{cc,h} : Use `PostToDart` for returning results to Dart isolate

Applied to files:

  • webf/lib/src/bridge/to_native.dart
  • integration_tests/lib/webf_tester.dart
  • bridge/webf_bridge.cc
  • integration_tests/lib/playground.dart
  • webf/lib/src/bridge/binding_object.dart
  • bridge/include/webf_bridge.h
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/lib/src/css/**/*.dart : Use CSSRenderStyle for style computation and storage in Dart CSS code

Applied to files:

  • webf/lib/src/bridge/to_native.dart
  • bridge/core/dom/element.cc
  • bridge/core/css/style_engine.cc
  • bridge/include/webf_bridge.h
📚 Learning: 2025-12-08T23:27:41.357Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: scripts/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:41.357Z
Learning: Applies to scripts/bridge/core/**/*.d.ts : Transform WebF-specific type annotations: `DartImpl<T>` → `T`, `StaticMember<T>` → `T`, `StaticMethod<T>` → `T`, `SupportAsync<T>` → generates both sync and async variants, `DependentsOnLayout<T>` → `T`

Applied to files:

  • webf/lib/src/bridge/to_native.dart
  • bridge/webf_bridge.cc
  • webf/lib/src/bridge/binding_object.dart
  • bridge/include/webf_bridge.h
📚 Learning: 2025-12-13T16:32:47.644Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T16:32:47.644Z
Learning: Applies to {bridge/**/*.{cc,h},webf/**/*.dart} : Document memory ownership clearly in FFI implementations

Applied to files:

  • webf/lib/src/bridge/to_native.dart
  • bridge/webf_bridge.cc
  • webf/lib/src/bridge/binding_object.dart
  • bridge/include/webf_bridge.h
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/**/*.dart : Document memory ownership clearly in FFI async callbacks

Applied to files:

  • webf/lib/src/bridge/to_native.dart
  • integration_tests/lib/webf_tester.dart
  • integration_tests/lib/playground.dart
  • webf/lib/src/bridge/binding_object.dart
  • bridge/include/webf_bridge.h
📚 Learning: 2025-12-13T16:32:47.644Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T16:32:47.644Z
Learning: Applies to webf/**/*.dart : Track pointer ownership in callbacks within Dart FFI

Applied to files:

  • webf/lib/src/bridge/to_native.dart
  • bridge/bindings/qjs/qjs_function.cc
  • integration_tests/lib/webf_tester.dart
  • integration_tests/lib/playground.dart
  • webf/lib/src/bridge/binding_object.dart
📚 Learning: 2025-12-08T23:27:15.946Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: bridge/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:15.946Z
Learning: Applies to bridge/**/*.{cc,cpp} : Use PostToJs for executing operations on the JS thread from other threads, PostToDart for returning results to Dart isolate, and avoid PostToJsSync to prevent deadlocks

Applied to files:

  • webf/lib/src/bridge/to_native.dart
  • bridge/bindings/qjs/qjs_function.cc
  • bridge/webf_bridge.cc
  • webf/lib/src/bridge/binding_object.dart
  • bridge/bindings/qjs/script_promise_resolver.cc
  • bridge/core/executing_context.cc
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/**/*.dart : Call updateWidget() when attributes change in WidgetElement implementations

Applied to files:

  • webf/lib/src/bridge/to_native.dart
  • bridge/include/webf_bridge.h
  • webf/lib/src/dom/element_widget_adapter.dart
📚 Learning: 2025-12-13T16:32:47.644Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T16:32:47.644Z
Learning: Applies to bridge/**/*.{cc,h} : Use `PostToJs` for executing operations on the JS thread in FFI

Applied to files:

  • bridge/bindings/qjs/qjs_function.cc
  • bridge/webf_bridge.cc
📚 Learning: 2025-12-08T23:27:15.946Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: bridge/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:15.946Z
Learning: Applies to bridge/**/*.{cc,cpp} : Avoid `PostToJsSync` when threads may interdepend to prevent synchronous deadlocks in FFI communication

Applied to files:

  • bridge/bindings/qjs/qjs_function.cc
  • bridge/core/dom/frame_request_callback_collection.cc
  • bridge/core/page.h
  • bridge/webf_bridge.cc
  • bridge/bindings/qjs/script_promise_resolver.cc
  • bridge/core/executing_context.cc
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/**/*.{cpp,h,hpp} : Use RAII patterns in C++ where possible for memory management

Applied to files:

  • bridge/bindings/qjs/qjs_function.cc
📚 Learning: 2025-12-08T23:27:15.946Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: bridge/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:15.946Z
Learning: Applies to bridge/**/*.{cc,cpp,h,hpp} : C++ code should follow Chromium style (.clang-format) with C++17 standard, 120 character column limit, and 2-space indentation

Applied to files:

  • bridge/core/dom/element.cc
  • bridge/webf_bridge.cc
📚 Learning: 2025-12-08T23:28:11.651Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-08T23:28:11.651Z
Learning: Applies to bridge/**/*.{cc,h} : C++ code in bridge module must use C++17 standard with 2-space indentation, 120 column limit, and follow Chromium style guide as defined in `.clang-format`

Applied to files:

  • bridge/core/dom/element.cc
  • bridge/webf_bridge.cc
📚 Learning: 2025-12-08T23:27:15.946Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: bridge/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:15.946Z
Learning: Applies to bridge/**/*.{cc,cpp} : Ensure callback functions aren't invoked after context destruction to prevent use-after-free errors in FFI async operations

Applied to files:

  • bridge/core/dom/frame_request_callback_collection.cc
  • bridge/bindings/qjs/script_promise_resolver.cc
📚 Learning: 2025-12-13T16:32:47.644Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T16:32:47.644Z
Learning: Applies to bridge/**/*.{cc,h} : Avoid `PostToJsSync` synchronous execution when possible

Applied to files:

  • bridge/core/dom/frame_request_callback_collection.cc
  • bridge/bindings/qjs/script_promise_resolver.cc
  • bridge/core/executing_context.cc
📚 Learning: 2025-12-08T23:27:15.946Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: bridge/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:15.946Z
Learning: Applies to bridge/**/*.{cc,cpp} : For async callbacks with potential errors, always provide error path in callbacks (e.g., `callback(object, nullptr)`), handle cancellation cases in async operations, and propagate errors through callback parameters rather than exceptions

Applied to files:

  • bridge/core/dom/frame_request_callback_collection.cc
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/**/*.dart : Track ownership of allocated pointers in FFI callbacks

Applied to files:

  • integration_tests/lib/webf_tester.dart
  • integration_tests/lib/playground.dart
  • webf/lib/src/bridge/binding_object.dart
📚 Learning: 2025-12-08T23:28:11.651Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-08T23:28:11.651Z
Learning: Applies to webf/test/**/*.dart : Dart/Flutter widget and unit tests must be placed in `webf/test/` and use `WebFWidgetTestUtils` and `pumpAndSettle()` where needed

Applied to files:

  • integration_tests/lib/webf_tester.dart
  • integration_tests/lib/playground.dart
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/test/**/*_test.dart : Use WebFWidgetTestUtils.prepareWidgetTest() to test HTML/CSS rendering in widget unit tests

Applied to files:

  • integration_tests/lib/webf_tester.dart
  • integration_tests/lib/playground.dart
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/test/**/*_test.dart : Call setupTest() in setUpAll() method for one-time setup in unit tests

Applied to files:

  • integration_tests/lib/webf_tester.dart
  • integration_tests/lib/playground.dart
📚 Learning: 2025-12-08T23:28:11.651Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-08T23:28:11.651Z
Learning: Applies to webf/integration_test/**/*.dart : Dart/Flutter integration tests must be placed in `webf/integration_test/` directory

Applied to files:

  • integration_tests/lib/webf_tester.dart
  • integration_tests/lib/playground.dart
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Run Flutter dart tests with: cd webf && flutter test

Applied to files:

  • integration_tests/lib/webf_tester.dart
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/test/**/*_test.dart : When testing with WebFController, wait for initialization with: await controller.controlledInitCompleter.future

Applied to files:

  • integration_tests/lib/webf_tester.dart
  • integration_tests/lib/playground.dart
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/test/**/*_test.dart : Access render objects in tests to verify layout calculations

Applied to files:

  • integration_tests/lib/webf_tester.dart
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/test/**/*_test.dart : Use mock bundles from test/src/foundation/mock_bundle.dart for testing in unit tests

Applied to files:

  • integration_tests/lib/webf_tester.dart
  • webf/lib/src/bridge/binding_object.dart
📚 Learning: 2025-12-08T23:27:41.357Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: scripts/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:41.357Z
Learning: Applies to scripts/bridge/polyfill/**/*.{ts,tsx,d.ts} : Include a reference to `webf.d.ts` in polyfill type generation for accessing core types like `EventTarget`

Applied to files:

  • bridge/webf_bridge.cc
📚 Learning: 2025-12-08T23:27:41.357Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: scripts/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:41.357Z
Learning: Applies to scripts/bridge/core/**/*.d.ts : Create a `webf` namespace containing all type exports from merged bridge core types

Applied to files:

  • bridge/webf_bridge.cc
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: No build needed for Dart-only changes in webf/

Applied to files:

  • integration_tests/lib/playground.dart
  • webf/lib/src/bridge/binding_object.dart
  • bridge/include/webf_bridge.h
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Use widget unit tests to verify rendering changes with: cd webf && flutter test test/src/rendering/

Applied to files:

  • integration_tests/lib/playground.dart
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/lib/src/rendering/**/*.dart : Use RenderBoxModel as base class for layout in Dart rendering code

Applied to files:

  • webf/lib/src/bridge/binding_object.dart
📚 Learning: 2025-12-08T23:27:15.946Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: bridge/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:15.946Z
Learning: Applies to bridge/**/*.{cc,cpp} : For async FFI operations, use `Dart_NewPersistentHandle_DL` to keep Dart objects alive, convert back with `Dart_HandleFromPersistent_DL` before use, and always call `Dart_DeletePersistentHandle_DL` after the async operation completes

Applied to files:

  • webf/lib/src/bridge/binding_object.dart
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/**/*.dart : Implement WidgetElement to create custom Flutter widgets integrated into WebF's DOM tree

Applied to files:

  • webf/lib/src/bridge/binding_object.dart
  • webf/lib/src/dom/element_widget_adapter.dart
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/**/*.dart : Free FFI allocated memory in finally blocks to ensure cleanup on exceptions

Applied to files:

  • webf/lib/src/bridge/binding_object.dart
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/**/*.dart : Follow W3C event standards when dispatching events from WidgetElement

Applied to files:

  • webf/lib/src/dom/element_widget_adapter.dart
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/**/*.dart : Minimize widget rebuilds in WidgetElement for performance optimization

Applied to files:

  • webf/lib/src/dom/element_widget_adapter.dart
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/**/*.dart : Implement ARIA attributes in WidgetElement when applicable for accessibility

Applied to files:

  • webf/lib/src/dom/element_widget_adapter.dart
📚 Learning: 2025-12-08T23:27:27.888Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: integration_tests/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:27.888Z
Learning: Applies to integration_tests/specs/**/*.ts : Batch DOM operations to minimize reflows

Applied to files:

  • bridge/polyfill/src/test/index.js
  • integration_tests/specs/blink/css1/box_properties/padding_left.ts
📚 Learning: 2025-12-08T23:27:27.888Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: integration_tests/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:27.888Z
Learning: Applies to integration_tests/specs/**/*.ts : Use `snapshot()` for visual regression tests to capture current rendering

Applied to files:

  • bridge/polyfill/src/test/index.js
📚 Learning: 2025-12-08T23:27:27.888Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: integration_tests/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:27.888Z
Learning: Applies to integration_tests/specs/**/*.ts : Measure operations using `performance.now()` for timing in performance-critical tests

Applied to files:

  • bridge/polyfill/src/test/index.js
📚 Learning: 2025-12-08T23:27:27.888Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: integration_tests/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:27.888Z
Learning: Applies to integration_tests/specs/**/*.ts : Test behavior, not implementation

Applied to files:

  • integration_tests/specs/blink/css1/box_properties/padding_left.ts
📚 Learning: 2025-12-08T23:27:27.888Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: integration_tests/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:27.888Z
Learning: Applies to integration_tests/specs/**/*.ts : Remove created elements after tests (test cleanup)

Applied to files:

  • integration_tests/specs/blink/css1/box_properties/padding_left.ts
🧬 Code graph analysis (6)
bridge/core/dom/element.cc (1)
bridge/core/dom/element.h (1)
  • GetElementData (365-365)
bridge/core/dom/document.cc (1)
bridge/core/dom/document.h (1)
  • update_style_for_this_document_in_progress_ (277-289)
bridge/core/page.h (1)
bridge/core/dom/document.h (2)
  • update_style_for_this_document_in_progress_ (277-289)
  • bool (278-279)
bridge/core/dom/element.h (1)
bridge/core/dom/element.cc (2)
  • Attributes (76-81)
  • Attributes (76-76)
bridge/core/css/style_engine.cc (3)
bridge/core/dom/element.cc (2)
  • id (304-306)
  • id (304-304)
bridge/core/dom/node.h (1)
  • String (109-116)
bridge/foundation/string/wtf_string.h (2)
  • String (23-160)
  • String (42-42)
bridge/include/webf_bridge.h (1)
bridge/webf_bridge.cc (2)
  • updateStyleForThisDocument (309-363)
  • updateStyleForThisDocument (309-309)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: build_windows_bridge (Debug)
  • GitHub Check: Analyze (c-cpp)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (rust)
🔇 Additional comments (29)
bridge/polyfill/src/test/index.js (4)

9-13: LGTM!

The generation counter pattern for invalidating RAF callbacks is a clean approach. The optional chaining with .bind(global) correctly handles environments where requestAnimationFrame may not exist while preserving the proper this context.


25-29: LGTM!

Incrementing the generation counter effectively invalidates all pending RAF callbacks from the previous spec without needing to track individual RAF IDs. The comment clearly documents the intent.


58-72: LGTM!

The wrapper correctly:

  1. Captures the generation synchronously to compare against at callback time
  2. Flushes the sync buffer defensively (with type check) before scheduling
  3. Returns the native RAF ID for cancelAnimationFrame compatibility
  4. Prevents stale callbacks from executing after spec teardown

The synchronous buffer flush before scheduling aligns well with the PR's goal of making style calculations reliable at RAF boundaries.


82-89: LGTM!

The placement of clearAllAnimationFrames() before resetDocumentElement() is correct—pending RAF callbacks from the previous spec are invalidated before the document is rebuilt, preventing them from interacting with the new DOM structure.

bridge/core/html/parser/html_parser.cc (6)

35-37: LGTM!

Clean wrapper function for document parsing. The null return case is properly handled by the caller.


39-44: LGTM!

Proper fragment parsing setup. The hardcoded HTML namespace is appropriate since SVG fragments are handled separately by parseSVG().


274-280: LGTM!

Clean conditional logic for fragment vs. document parsing. The fragment context is properly derived from the root node.


412-442: LGTM!

Correct implementation of fragment root flattening. The lambda properly unwraps Gumbo's synthetic <html>/<head>/<body> wrappers to expose actual fragment content for innerHTML behavior, while maintaining error state across all children.


444-444: LGTM!

Correct conditional dispatch between fragment and document traversal modes.


46-60: GUMBO_TAG_BODY is the appropriate default for all fallback cases.

The function correctly derives the context tag from root_node for recognized element types (including table, select, colgroup). The defaults to GUMBO_TAG_BODY only apply when context derivation fails—the node is null, the local name is empty, or the tag is unrecognized. For these edge cases, GUMBO_TAG_BODY is a reasonable and standard fallback in HTML fragment parsing.

bridge/core/dom/frame_request_callback_collection.cc (1)

24-25: LGTM: Idle state management consistent with callback execution pattern.

Setting the context to non-idle before firing the frame callback aligns with the broader idle-state management introduced in this PR. The subsequent DrainMicrotasks() call (line 33) will properly manage microtask execution after the callback completes.

webf/lib/src/dom/element_widget_adapter.dart (3)

62-62: LGTM: Onscreen state tracking added.

The _isOnScreen flag enables proper deduplication of onscreen/offscreen events, preventing redundant event dispatches during style-driven rebuilds.


107-121: LGTM: Event deduplication logic correctly implemented.

The deduplication logic properly prevents redundant onscreen/offscreen events:

  • Line 114: Early return if already onscreen when enqueuing an onscreen event
  • Line 119: Early return if not onscreen when enqueuing an offscreen event

This aligns with the framework expectation that onscreen/offscreen are one-shot lifecycle notifications per visibility transition.


137-141: LGTM: State transitions occur before event dispatch.

Setting _isOnScreen before dispatching the event is correct—the flag tracks the state being entered, not the completion of dispatch. This enables subsequent enqueueScreenEvent calls to correctly deduplicate before the async dispatch completes.

bridge/core/dom/element.h (2)

233-238: LGTM: Display-none invalidation flag for style optimization.

The new flag enables the style engine to skip descendant invalidations for display:none subtrees, mirroring Blink's optimization pattern. The inline documentation clearly explains the purpose and usage.


423-428: Dual-storage pattern is intentional for legacy compatibility.

The fallback check in hasAttributes() correctly handles the dual-storage design: element_data_ (modern C++ storage) and attributes_ (legacy ElementAttributes wrapper, marked for refactoring). These maintain independent storage (ElementAttributes has an internal std::unordered_map), so both must be checked to accurately reflect the element's attribute state. Methods like setAttribute(), getAttribute(), and removeAttribute() use EnsureElementAttributes() independently, which can populate the legacy storage without necessarily creating element_data_. The divergence is expected and essential for the legacy/modern migration path. Consider adding a code comment documenting this dual-storage relationship if not already present elsewhere.

bridge/bindings/qjs/qjs_function.cc (2)

14-14: LGTM: ExecutingContext header added for idle-state management.


85-86: LGTM: Idle state management for function invocation.

Setting the context to non-idle before JS_Call (line 88) aligns with the broader idle-state management pattern. The subsequent DrainMicrotasks() call (line 90) properly handles microtask execution after the function completes.

integration_tests/lib/webf_tester.dart (1)

49-49: Test context API updated to use opaque pointer.

The test framework API now uses Pointer<Void> testContext instead of double contextId, matching the change in playground.dart. The non-null assertion is safe assuming initTestFramework always succeeds (line 48).

bridge/core/dom/document.cc (1)

35-35: Reentrancy guard for UpdateStyleForThisDocument looks correct

Using update_style_for_this_document_in_progress_ with AutoReset<bool> gives a simple, robust guard against recursive style updates, and the early return keeps the fast path cheap. No issues from a single-threaded Document usage standpoint.

Also applies to: 618-622

bridge/include/webf_bridge.h (1)

139-145: FFI surface for updateStyleForThisDocument is well‑shaped

Export uses WEBF_EXPORT_C, int8_t matches Dart Int8, and the documented 1/0 contract aligns with the C++ implementation and Dart wrapper.

bridge/webf_bridge.cc (1)

8-8: updateStyleForThisDocument orchestration looks good; confirm callback semantics

The new bridge function correctly gates style updates with TryBeginUpdateStyleForThisDocument, validates context/dispatcher, and on the JS thread rechecks context/Blink/idle/document before calling Document::UpdateStyleForThisDocument() under MemberMutationScope, finishing with a kFinishRecordingCommand. The in‑progress flag is only cleared in the completion lambda passed to PostToJsAndCallback, so please confirm that Dispatcher::PostToJsAndCallback always runs that completion callback even when the JS‑thread lambda early‑returns due to failed guards; otherwise the page‑level in‑progress flag could remain stuck true and block future style updates.

Also applies to: 10-10, 309-363

bridge/core/page.h (1)

147-160: Per‑page style‑update in‑progress tracking is implemented correctly

The atomic update_style_for_this_document_in_progress_ plus TryBegin…/End…/Is… accessors give a clear and thread‑safe guard around per‑page style updates, with appropriate acquire/release semantics on the flag.

Also applies to: 171-171

webf/lib/src/bridge/to_native.dart (1)

295-306: Dart FFI binding for updateStyleForThisDocument matches the native API

The typedefs line up with int8_t updateStyleForThisDocument(void* page) and the bool updateStyleForThisDocument(Pointer<Void> page) wrapper provides a simple, idiomatic Dart interface.

bridge/core/css/style_engine.cc (1)

1165-1171: Display‑none tracking and size‑dependent media‑query gating look sound

The new display_none_for_invalidation computation and SetDisplayNoneForStyleInvalidation calls in both subtree and element‑only recalc paths give the element a clear signal for “display:none” when determining invalidation behavior. The media‑query size‑change handling in MediaQueryAffectingValueChanged (TreeScope overload) correctly builds a deterministic snapshot of size‑dependent queries, compares it against the cached results, and only forces a full style/invalidation pass when the set or match results actually change, which should materially reduce unnecessary style work on pure resizes.

Also applies to: 1451-1509, 1954-2090

bridge/core/dom/element.cc (4)

117-124: LGTM! Pre-binding style update pattern is correct.

The addition of Blink-enabled style updates before geometry queries ensures layout is up-to-date. The null checks for context and document are appropriate, and the MemberMutationScope guard properly tracks mutations during the update.


140-147: LGTM! Consistent with getBoundingClientRect pattern.

The same pre-binding style update logic is correctly applied here.


624-624: LGTM! Correct return value.

Returning the actual local_name_ instead of a placeholder is the correct implementation for selector matching.


1082-1082: LGTM! Intentional removal of baseHref dependency.

Setting payload->href to nullptr consistently simplifies the inline style handling and removes the baseHref dependency as described in the PR objectives.

Comment on lines +628 to 645
if (local_name.IsNull() || local_name.empty()) {
return false;
}
for (const Attribute& attribute : GetElementData()->Attributes()) {
if (hint == attribute.LocalName()) {
return true;

if (HasElementData()) {
for (const Attribute& attribute : GetElementData()->Attributes()) {
if (attribute.LocalName() == local_name) {
return true;
}
}
}
*/

if (attributes_ != nullptr) {
ExceptionState exception_state;
return attributes_->hasAttribute(local_name, exception_state);
}

return false;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Search for methods that access both element_data_ and attributes_
rg -n 'element_data_|attributes_' bridge/core/dom/element.cc | head -30

Repository: openwebf/webf

Length of output: 1838


🏁 Script executed:

# Check for attribute synchronization or delegation patterns
rg -B3 -A3 'attributes_->has|HasElementData.*attributes_|element_data_.*Attributes' bridge/core/dom/element.cc

Repository: openwebf/webf

Length of output: 213


🏁 Script executed:

# Look for the initialization and lifecycle of both sources
rg -n 'attributes_ =' bridge/core/dom/element.cc

Repository: openwebf/webf

Length of output: 167


🏁 Script executed:

# Check element.h for how these two members are declared and documented
rg -B2 -A2 'ElementAttributes.*attributes_|ElementData.*element_data_' bridge/core/dom/element.h

Repository: openwebf/webf

Length of output: 668


Dual attribute source pattern is intentional; ensure all code paths maintain synchronization.

The dual-check pattern in HasAttributeIgnoringNamespace is confirmed to be intentional. The method checks element_data_ (primary source) first, then attributes_ (lazily-initialized secondary source) as a fallback. Code like CloneDataFromElement() explicitly synchronizes both sources together via EnsureElementAttributes().CopyWith(), confirming they are meant to coexist.

However, the relationship between these two attribute sources would benefit from explicit comments documenting when and why both exist, and clarifying that all code paths that mutate attributes must keep both sources synchronized to avoid inconsistency.

🤖 Prompt for AI Agents
In bridge/core/dom/element.cc around lines 628 to 645, the dual attribute-source
pattern (element_data_ primary and attributes_ fallback) is intentional but
lacks explanatory comments and a clear instruction for mutators to keep both
sources synchronized; add a concise comment above HasAttributeIgnoringNamespace
(and/or at the Element class attribute section) explaining why both sources
exist, when attributes_ may be null, and that any code path that mutates
attributes must update both sources (use EnsureElementAttributes().CopyWith() /
CloneDataFromElement() or equivalent helper) to maintain consistency; also add a
note referencing the canonical synchronization helpers to guide future changes.

Comment on lines 115 to +116
Pointer<Void> testContext = initTestFramework(contextId);
registerDartTestMethodsToCpp(contextId);
registerDartTestMethodsToCpp(testContext);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cat -n integration_tests/lib/playground.dart | sed -n '110,125p'

Repository: openwebf/webf

Length of output: 817


🏁 Script executed:

rg -n 'initTestFramework|registerDartTestMethodsToCpp|testContext' integration_tests/lib/playground.dart -B2 -A5

Repository: openwebf/webf

Length of output: 614


🏁 Script executed:

# Find initTestFramework and registerDartTestMethodsToCpp definitions
rg -n 'initTestFramework|registerDartTestMethodsToCpp' --type=dart -B2 -A8

Repository: openwebf/webf

Length of output: 4629


🏁 Script executed:

# Check for FFI handle management patterns
rg -n 'Dart_NewPersistentHandle|Dart_DeletePersistentHandle|Pointer<Void>' webf --type=dart --type cpp -A3 -B1 | head -100

Repository: openwebf/webf

Length of output: 8475


🏁 Script executed:

# Check the native implementation of initTestFramework and how it uses the returned pointer
rg -n 'initTestFramework' bridge --type=cpp --type=cc -B5 -A15 | head -80

Repository: openwebf/webf

Length of output: 83


🏁 Script executed:

# Check if testContext is used in callbacks or async operations
rg -n 'testContext|registerDartTestMethodsToCpp' bridge --type=cpp --type=cc -B2 -A5 | head -100

Repository: openwebf/webf

Length of output: 83


🏁 Script executed:

# Look at the broader lifecycle in webf_tester.dart to see if testContext is freed anywhere
rg -n 'testContext|dispose|cleanup' integration_tests/lib/webf_tester.dart -B2 -A3

Repository: openwebf/webf

Length of output: 964


🏁 Script executed:

# Search for initTestFramework in C++ files (correct extension)
find bridge -type f \( -name "*.cpp" -o -name "*.h" -o -name "*.hpp" \) | head -20

Repository: openwebf/webf

Length of output: 833


🏁 Script executed:

# Search for initTestFramework implementation
rg -n 'initTestFramework' bridge -B5 -A15 --type-list

Repository: openwebf/webf

Length of output: 446


🏁 Script executed:

# Try broader search
rg -n 'initTestFramework' bridge -B5 -A15 2>/dev/null | head -100

Repository: openwebf/webf

Length of output: 5949


🏁 Script executed:

# Check if testContext/test framework pointers are freed anywhere
rg -n 'free.*testContext|delete.*testContext|testContext.*free|testContext.*delete' integration_tests --type=dart

Repository: openwebf/webf

Length of output: 39


🏁 Script executed:

# Check if dispose/cleanup in WebFController or view cleans up testContext
rg -n 'dispose|cleanup|testContext' webf/lib/src/launcher/view_controller.dart -B2 -A5 | head -60

Repository: openwebf/webf

Length of output: 2084


🏁 Script executed:

# Check if there's a cleanup function for test framework in the FFI bindings
rg -n 'freeTestFramework|deleteTestContext|cleanup.*Test|Test.*cleanup' integration_tests/lib/bridge -B2 -A3

Repository: openwebf/webf

Length of output: 39


🏁 Script executed:

# Check if testContext cleanup is handled elsewhere
rg -n 'testContext|WebFTestContext' integration_tests --type=dart -B1 -A2

Repository: openwebf/webf

Length of output: 3907


🏁 Script executed:

# Check the full lifecycle in webf_tester.dart dispose method
rg -n 'dispose|deactivate' integration_tests/lib/webf_tester.dart -B3 -A10

Repository: openwebf/webf

Length of output: 631


🏁 Script executed:

# Check if WebFTestContext has a destructor that might be called automatically
rg -n 'WebFTestContext|~WebFTestContext' bridge -B2 -A5

Repository: openwebf/webf

Length of output: 10202


🏁 Script executed:

# Look for any delete/free functions for test context
fd -e h -e hpp bridge | xargs rg -l 'testContext|TestContext' | head -5

Repository: openwebf/webf

Length of output: 90


🏁 Script executed:

# Verify the disposeCallback is called when controller.dispose() is invoked
rg -n 'disposeCallback|dispose' webf/lib/src/launcher/controller.dart -B2 -A3 | head -80

Repository: openwebf/webf

Length of output: 2735


Add cleanup for testContext in playground.dart.

The testContext pointer allocated in initTestFramework must be cleaned up. In playground.dart, the pointer is allocated and registerDartTestMethodsToCpp is called, but executeTest is commented out and there's no corresponding controller.dispose() to trigger cleanup via the disposeCallback. Either uncomment executeTest or ensure the controller is disposed to properly release the test context (the native destructor is called automatically when the WebFPage is destroyed during controller disposal).

🤖 Prompt for AI Agents
In integration_tests/lib/playground.dart around lines 115 to 116, testContext
returned from initTestFramework is not being cleaned up because executeTest is
commented out and controller.dispose() is never called; either uncomment the
executeTest call so the test flow runs and disposes the controller, or
explicitly call controller.dispose() (preferably in a finally block or after
test completion) to trigger the native disposeCallback that frees the
testContext pointer and ensure no native memory leak.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
bridge/core/dom/element.cc (1)

117-124: Consider extracting duplicate pre-binding style update logic.

The same pattern (get context → check Blink enabled → get document → create mutation scope → update style) is duplicated in getClientRects (lines 140-147). This could be extracted into a helper method to reduce duplication and ensure consistent behavior across geometry-querying methods.

🔎 Suggested helper extraction
+void Element::EnsureStyleUpdatedForGeometryQuery() {
+  ExecutingContext* context = GetExecutingContext();
+  if (context && context->isBlinkEnabled()) {
+    Document* doc = context->document();
+    if (doc) {
+      MemberMutationScope mutation_scope{context};
+      doc->UpdateStyleForThisDocument();
+    }
+  }
+}
+
 BoundingClientRect* Element::getBoundingClientRect(ExceptionState& exception_state) {
-  ExecutingContext* context = GetExecutingContext();
-  if (context && context->isBlinkEnabled()) {
-    Document* doc = context->document();
-    if (doc) {
-      MemberMutationScope mutation_scope{context};
-      doc->UpdateStyleForThisDocument();
-    }
-  }
+  EnsureStyleUpdatedForGeometryQuery();
 
   NativeValue result = InvokeBindingMethod(
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2d4a1c6 and 30b1491.

📒 Files selected for processing (3)
  • bridge/core/css/style_engine.cc
  • bridge/core/dom/element.cc
  • use_cases/src/pages/FeatureCatalogPage.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • bridge/core/css/style_engine.cc
🧰 Additional context used
📓 Path-based instructions (5)
bridge/**/*.{cc,cpp,h,hpp}

📄 CodeRabbit inference engine (bridge/CLAUDE.md)

bridge/**/*.{cc,cpp,h,hpp}: C++ code should follow Chromium style (.clang-format) with C++17 standard, 120 character column limit, and 2-space indentation
Use WEBF_EXPORT_C macro for exporting C functions to Dart FFI
In FFI contexts, use Dart_Handle instead of Handle for type compatibility
For C++ FFI function naming: use GetObjectPropertiesFromDart for C++ exports, NativeGetObjectPropertiesFunc for Dart typedefs, and GetObjectPropertiesFunc for Dart functions
Lambda signatures in C++ must match expected function signatures to avoid FFI type mismatches
Choose power-of-2 buffer sizes (512, 1024, 2048) for ring buffer implementation, with smaller sizes for DEBUG_BUILD, MOBILE constraints, and larger sizes for DESKTOP performance

Files:

  • bridge/core/dom/element.cc
bridge/**/*.{cc,cpp}

📄 CodeRabbit inference engine (bridge/CLAUDE.md)

bridge/**/*.{cc,cpp}: For async FFI operations, use Dart_NewPersistentHandle_DL to keep Dart objects alive, convert back with Dart_HandleFromPersistent_DL before use, and always call Dart_DeletePersistentHandle_DL after the async operation completes
For string handling in FFI, copy strings that might be freed using std::string(const_char_ptr), and use toNativeUtf8() with proper memory deallocation
For async callbacks with potential errors, always provide error path in callbacks (e.g., callback(object, nullptr)), handle cancellation cases in async operations, and propagate errors through callback parameters rather than exceptions
For thread-safe error reporting in FFI, copy error messages before crossing thread boundaries using std::string to ensure string lifetime, and consider error callbacks separate from result callbacks
Avoid PostToJsSync when threads may interdepend to prevent synchronous deadlocks in FFI communication
Ensure callback functions aren't invoked after context destruction to prevent use-after-free errors in FFI async operations
Implement ring buffer overflow handling with metrics and alerts to monitor command buffer capacity
Process multiple UI commands per frame in a loop with a MAX_COMMANDS_PER_FRAME limit to balance responsiveness and performance
Pin threads to cores for optimal cache usage in ring buffer operations by setting CPU affinity for UI threads
Use PostToJs for executing operations on the JS thread from other threads, PostToDart for returning results to Dart isolate, and avoid PostToJsSync to prevent deadlocks

Files:

  • bridge/core/dom/element.cc
bridge/**/*.{cc,h}

📄 CodeRabbit inference engine (AGENTS.md)

C++ code in bridge module must use C++17 standard with 2-space indentation, 120 column limit, and follow Chromium style guide as defined in .clang-format

bridge/**/*.{cc,h}: Use RAII patterns in C++ where possible for resource management
Use PostToJs for executing operations on the JS thread in FFI
Use PostToDart for returning results to Dart isolate
Avoid PostToJsSync synchronous execution when possible

C++ bridge code must use 2-space indent, 120 column line limit, and follow Chromium style via .clang-format

Files:

  • bridge/core/dom/element.cc
{bridge/**/*.{cc,h},webf/**/*.dart}

📄 CodeRabbit inference engine (CLAUDE.md)

Document memory ownership clearly in FFI implementations

Files:

  • bridge/core/dom/element.cc
bridge/core/**

📄 CodeRabbit inference engine (bridge/AGENTS.md)

Core bridge code should be located in bridge/core/ directory

Files:

  • bridge/core/dom/element.cc
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
Repo: openwebf/webf PR: 0
File: integration_tests/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:27:27.888Z
Learning: Applies to integration_tests/specs/**/*.ts : Batch DOM operations to minimize reflows
📚 Learning: 2025-12-08T23:28:00.818Z
Learnt from: CR
Repo: openwebf/webf PR: 0
File: webf/CLAUDE.md:0-0
Timestamp: 2025-12-08T23:28:00.818Z
Learning: Applies to webf/lib/src/css/**/*.dart : Use CSSRenderStyle for style computation and storage in Dart CSS code

Applied to files:

  • bridge/core/dom/element.cc
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: build_windows_bridge (Debug)
  • GitHub Check: Analyze (c-cpp)
  • GitHub Check: Analyze (rust)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (5)
use_cases/src/pages/FeatureCatalogPage.tsx (1)

47-47: Catalog item structure and routing are correct.

The /responsive route is properly defined in the router configuration with the corresponding ResponsivePage component, so this catalog entry will navigate correctly.

bridge/core/dom/element.cc (4)

140-147: LGTM - Style update before geometry query.

The pre-binding style update ensures styles are recalculated before querying client rects, which aligns with the PR's goal of vsync-driven style calculations. The duplicate pattern was noted in the previous comment.


623-625: LGTM - Critical fix for selector matching.

Returning the actual local_name_ instead of an empty placeholder is essential for CSS selector matching to work correctly with tag name selectors.


1067-1074: LGTM - CSS variable empty value normalization.

The code correctly handles empty CSS variable values by normalizing them to a single space. The previous critical issue (using value_string before declaration) has been properly addressed - the variable is now declared at line 1068 before the check at line 1072.


1080-1084: No issue found.

The removal of conditional base_href logic is safe. Inline styles resolve relative URLs through the fallback mechanism (baseHref ?? controller.url) on the Dart side, which correctly uses the document's base URL—the appropriate base for inline style properties in the style attribute.

Comment on lines +640 to +643
if (attributes_ != nullptr) {
ExceptionState exception_state;
return attributes_->hasAttribute(local_name, exception_state);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Exception state is created but not checked after use.

The exception_state created at line 641 is passed to hasAttribute but never inspected afterward. If an exception occurs, it will be silently ignored. Consider either checking and handling the exception or using ASSERT_NO_EXCEPTION() if exceptions are not expected here.

🔎 Proposed fix
   if (attributes_ != nullptr) {
-    ExceptionState exception_state;
-    return attributes_->hasAttribute(local_name, exception_state);
+    return attributes_->hasAttribute(local_name, ASSERT_NO_EXCEPTION());
   }

Or if exceptions should be handled:

   if (attributes_ != nullptr) {
     ExceptionState exception_state;
-    return attributes_->hasAttribute(local_name, exception_state);
+    bool result = attributes_->hasAttribute(local_name, exception_state);
+    if (exception_state.HasException()) {
+      return false;
+    }
+    return result;
   }
🤖 Prompt for AI Agents
In bridge/core/dom/element.cc around lines 640 to 643, an ExceptionState is
created and passed into attributes_->hasAttribute(local_name, exception_state)
but the exception_state is never inspected; update the call site to either check
exception_state after the call and handle/report any exception (e.g., return a
sensible default or propagate the error) or, if exceptions are not expected
here, replace the no-op check with ASSERT_NO_EXCEPTION() immediately after the
hasAttribute call to document and enforce that no exception occurred.

@andycall andycall merged commit 9248a45 into main Dec 28, 2025
10 of 12 checks passed
@andycall andycall deleted the feat/vsync branch December 28, 2025 18:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants