Skip to content

fix(core): block plugins on custom tags were laid out at 0x0 and never painted - #22

Merged
vietnguyentuan2019 merged 1 commit into
mainfrom
fix/block-plugin-custom-tags
Oct 3, 2026
Merged

vietnguyentuan2019 merged 1 commit into
mainfrom
fix/block-plugin-custom-tags

Conversation

@vietnguyentuan2019

Copy link
Copy Markdown
Contributor

Problem

Found by running the demo app for the 1.11.0 release check: the Plugin API demo logged Layout Warning: More child widgets than fragments. Node: info-box and (on inspection) <info-box> / <rating> rendered as nothing.

A custom tag (<info-box>, <x-badge>) has no UA display style, so the HTML adapters build it as an InlineNode. _handleInlineNode only consulted the inline plugin tags, so a registered block plugin on such a tag never reached _tokenizeBlockPlugin: the widget was built, linked to no fragment, laid out at 0x0 and never painted. Only tags that were already block (figure, div) worked — which is what the old tests used.

Reproduced on clean main (probe: SizedBox(height: 40, ColoredBox(amber)) as a block plugin on <x-a> → size 0x0, 0 amber pixels).

Fix

A registered block tag is handled as a block whatever its node type (_handleInlineNode checks _blockPluginTags first). 9 lines in render_hyper_box_layout.dart.

Why the old tests missed it

They hand-built BlockNode(tagName: 'figure'), or asserted findsOneWidget, which a 0x0 widget satisfies. The new tests (test/block_plugin_custom_tag_test.dart) assert size, position between the neighbouring paragraphs, painted pixels, stacking, virtualized mode, that the plugin owns its children, and that unregistered and inline plugins are unaffected.

Verification

  • 7 new tests; mutation-checked (removing the fix fails 4 of them).
  • Full suite on this branch: 2451 pass. Analyze and format clean.

Not a regression: present on main / 1.10.0. Candidate for the next release.

…r painted

A custom tag (<info-box>, <x-badge>) has no UA display style, so the HTML
adapters build it as an InlineNode. _handleInlineNode only consulted the
inline plugin tags, so a registered BLOCK plugin on such a tag never reached
_tokenizeBlockPlugin: its widget was built, linked to no fragment, sized 0x0
and not painted ('More child widgets than fragments' in debug).

A registered block tag is now handled as a block whatever its node type.

The existing plugin tests hand-built BlockNodes or asserted findsOneWidget,
which a 0x0 widget satisfies. The new tests assert size, position between the
neighbouring paragraphs, painted pixels, stacking, virtualized mode, that the
plugin owns its children, and that unregistered and inline plugins are
unaffected.
@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

⚠️ Layout Regression — Budget exceeded (informational)

Fixture Budget (ms) Median (ms) P95 (ms)
❌ simple_paragraph 8 17 29
❌ mixed_inline 10 15 18
❌ float_layout 12 16 25
❌ table_20_rows 14 46 61
✅ cjk_ruby 14 10 12
❌ large_article 16 40 64

One or more fixtures exceeded the 16 ms budget.

Flutter 3.41.5 · ubuntu-22.04

Informational, does not block merge: CI runners use software
rendering and are 2-3x slower than the devices the budgets are
calibrated for. Compare against the base branch; if a fixture
regressed relative to it, profile with:

flutter test benchmark/layout_regression.dart --reporter expanded

and check _performLineLayout / _buildCharacterMapping for
any new O(N²) or O(N log N) paths introduced in this PR.

vietnguyentuan2019 added a commit that referenced this pull request Oct 3, 2026
…r, :root fix, block plugins on custom tags

release: 1.11.0 — dark mode text color, body/html color, :root fix (#20), block plugins on custom tags (#22), docs fixes
@vietnguyentuan2019
vietnguyentuan2019 merged commit 709ef79 into main Oct 3, 2026
9 checks passed
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.

1 participant