From 8d8087d0d30ad3db47d06540f96a234285d50626 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=93=E5=87=8C?= Date: Mon, 29 Nov 2021 11:36:37 +0800 Subject: [PATCH 1/9] fix: sliver child when not attached not to flushPendingProperties --- kraken/lib/src/css/overflow.dart | 5 ++++- kraken/lib/src/css/style_declaration.dart | 9 ++++++++- kraken/lib/src/dom/elements/head.dart | 1 + 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/kraken/lib/src/css/overflow.dart b/kraken/lib/src/css/overflow.dart index c8bd91249b..a327a70e2e 100644 --- a/kraken/lib/src/css/overflow.dart +++ b/kraken/lib/src/css/overflow.dart @@ -217,7 +217,10 @@ mixin ElementOverflowMixin on ElementBase { } void scrollingContentBoxStyleListener(String property, String? original, String present) { - RenderLayoutBox scrollingContentBox = (renderBoxModel as RenderLayoutBox).renderScrollingContent!; + RenderLayoutBox? scrollingContentBox = (renderBoxModel as RenderLayoutBox).renderScrollingContent; + // Sliver content has no multi scroll content box. + if (scrollingContentBox == null) return; + RenderStyle scrollingContentRenderStyle = scrollingContentBox.renderStyle; switch (property) { diff --git a/kraken/lib/src/css/style_declaration.dart b/kraken/lib/src/css/style_declaration.dart index 09864ecbc7..6a153535e4 100644 --- a/kraken/lib/src/css/style_declaration.dart +++ b/kraken/lib/src/css/style_declaration.dart @@ -367,7 +367,14 @@ class CSSStyleDeclaration { } void flushPendingProperties() { - if (target?.parentNode?.renderer == null) return; + Element? _target = target; + // If style target element not exists, no need to do flush operation. + if (_target == null) return; + // If target's renderer has created, but not adopted by a parent, + // in most cases it's a sliver child orphan, should not flush styles. + if (_target.renderer?.parent == null) return; + // If target's parent element has no renderer attached, no need to flush. + if (_target.parentNode?.isRendererAttached == false) return; // Display change from none to other value that the renderBoxModel is null. if (_pendingProperties.containsKey(DISPLAY) && target!.isConnected) { diff --git a/kraken/lib/src/dom/elements/head.dart b/kraken/lib/src/dom/elements/head.dart index f4cd8a8ece..1fb059d517 100644 --- a/kraken/lib/src/dom/elements/head.dart +++ b/kraken/lib/src/dom/elements/head.dart @@ -131,6 +131,7 @@ class StyleElement extends Element { type = value.toString().toLowerCase().trim(); } } + @override void connectedCallback() { if (type == _CSS_MIME) { From 784aa119ef91357ddc2af8511bfd6e2edd35265a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=93=E5=87=8C?= Date: Mon, 29 Nov 2021 15:12:42 +0800 Subject: [PATCH 2/9] fix: positioned child in sliver list --- kraken/lib/src/css/positioned.dart | 13 ++++++----- kraken/lib/src/dom/element.dart | 1 - kraken/lib/src/rendering/box_model.dart | 2 +- kraken/lib/src/rendering/flex.dart | 30 ++++++++++++++----------- 4 files changed, 26 insertions(+), 20 deletions(-) diff --git a/kraken/lib/src/css/positioned.dart b/kraken/lib/src/css/positioned.dart index 3932227c3c..a3b9ce0363 100644 --- a/kraken/lib/src/css/positioned.dart +++ b/kraken/lib/src/css/positioned.dart @@ -31,13 +31,16 @@ BoxSizeType? _getChildHeightSizeType(RenderBox child) { // RenderPositionHolder may be affected by overflow: scroller offset. // We need to reset these offset to keep positioned elements render at their original position. +// @NOTE: Attention that renderObjects in tree may not all subtype of RenderBoxModel, use `is` to identify. Offset? _getRenderPositionHolderScrollOffset(RenderPositionPlaceholder holder, RenderObject root) { - RenderBoxModel? parent = holder.parent as RenderBoxModel?; - while (parent != null && parent != root) { - if (parent.clipX || parent.clipY) { - return Offset(parent.scrollLeft, parent.scrollTop); + AbstractNode? current = holder.parent; + while (current != null && current != root) { + if (current is RenderBoxModel) { + if (current.clipX || current.clipY) { + return Offset(current.scrollLeft, current.scrollTop); + } } - parent = parent.parent as RenderBoxModel?; + current = current.parent; } return null; } diff --git a/kraken/lib/src/dom/element.dart b/kraken/lib/src/dom/element.dart index 4b06742a5e..72180d1be0 100644 --- a/kraken/lib/src/dom/element.dart +++ b/kraken/lib/src/dom/element.dart @@ -501,7 +501,6 @@ class Element extends Node // Detach renderBoxModel from original parent. _detachRenderBoxModel(_renderBoxModel); - _updateRenderBoxModel(); _addToContainingBlock(after: previousSibling); diff --git a/kraken/lib/src/rendering/box_model.dart b/kraken/lib/src/rendering/box_model.dart index b4f21eb906..1517d0021e 100644 --- a/kraken/lib/src/rendering/box_model.dart +++ b/kraken/lib/src/rendering/box_model.dart @@ -551,7 +551,7 @@ class RenderLayoutBox extends RenderBoxModel super.dispose(); stickyChildren.clear(); - _paintingOrder = null; + _paintingOrder = null; } } diff --git a/kraken/lib/src/rendering/flex.dart b/kraken/lib/src/rendering/flex.dart index 2b9b52721c..ffd4625b47 100644 --- a/kraken/lib/src/rendering/flex.dart +++ b/kraken/lib/src/rendering/flex.dart @@ -920,19 +920,23 @@ class RenderFlexLayout extends RenderLayoutBox { childNodeId = child.hashCode; } - if (child is RenderPositionPlaceholder && isPlaceholderPositioned(child)) { - RenderBoxModel realDisplayedBox = child.positioned!; - // Flutter only allow access size of direct children, so cannot use realDisplayedBox.size - Size realDisplayedBoxSize = - realDisplayedBox.getBoxSize(realDisplayedBox.contentSize); - double realDisplayedBoxWidth = realDisplayedBoxSize.width; - double realDisplayedBoxHeight = realDisplayedBoxSize.height; - childConstraints = BoxConstraints( - minWidth: realDisplayedBoxWidth, - maxWidth: realDisplayedBoxWidth, - minHeight: realDisplayedBoxHeight, - maxHeight: realDisplayedBoxHeight, - ); + if (isPlaceholderPositioned(child)) { + RenderBoxModel realDisplayedBox = (child as RenderPositionPlaceholder).positioned!; + if (realDisplayedBox.hasSize) { + // Flutter only allow access size of direct children, so cannot use realDisplayedBox.size + Size realDisplayedBoxSize = + realDisplayedBox.getBoxSize(realDisplayedBox.contentSize); + double realDisplayedBoxWidth = realDisplayedBoxSize.width; + double realDisplayedBoxHeight = realDisplayedBoxSize.height; + childConstraints = BoxConstraints( + minWidth: realDisplayedBoxWidth, + maxWidth: realDisplayedBoxWidth, + minHeight: realDisplayedBoxHeight, + maxHeight: realDisplayedBoxHeight, + ); + } else { + childConstraints = BoxConstraints(); + } } else if (child is RenderBoxModel) { childConstraints = child.getConstraints(); } else if (child is RenderTextBox) { From 56dfab3f68f7aff7901484d948fc868309c5ed8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=93=E5=87=8C?= Date: Mon, 29 Nov 2021 16:28:58 +0800 Subject: [PATCH 3/9] test: add test case for positioned child in sliver. --- integration_tests/specs/css/css-display/sliver.ts | 13 +++++++++++++ kraken/lib/src/css/display.dart | 4 ++-- kraken/lib/src/css/style_declaration.dart | 3 --- kraken/lib/src/dom/element.dart | 5 +++++ 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/integration_tests/specs/css/css-display/sliver.ts b/integration_tests/specs/css/css-display/sliver.ts index da7093e96a..193dbdf77f 100644 --- a/integration_tests/specs/css/css-display/sliver.ts +++ b/integration_tests/specs/css/css-display/sliver.ts @@ -199,4 +199,17 @@ describe('display sliver', () => { await simulateClick(50, 20); // Will trigger done. }); + + it('sliver child with none-static position not throw errors', () => { + var container = createSliverBasicCase(); + var firstChild = container.firstChild; // should be element. + firstChild.style.position = 'relative'; + + var innerChild = document.createElement('div'); + innerChild.appendChild(document.createTextNode('helloworld')); + innerChild.style.position = 'relative'; + innerChild.style.top = innerChild.style.left = '15px'; + firstChild?.appendChild(innerChild); + await snapshot(); + }); }); diff --git a/kraken/lib/src/css/display.dart b/kraken/lib/src/css/display.dart index 36b38969e6..0cb592983e 100644 --- a/kraken/lib/src/css/display.dart +++ b/kraken/lib/src/css/display.dart @@ -14,7 +14,7 @@ enum CSSDisplay { flex, inlineFlex, - sliver, // @TODO temp name. + sliver, none } @@ -26,7 +26,7 @@ mixin CSSDisplayMixin on RenderStyleBase { set display(CSSDisplay value) { if (_display != value) { _display = value; - + // Display effect the stacking context. RenderBoxModel? parentRenderer = (this as RenderStyle).parent?.renderBoxModel; if (parentRenderer is RenderLayoutBox) { diff --git a/kraken/lib/src/css/style_declaration.dart b/kraken/lib/src/css/style_declaration.dart index 6a153535e4..f984dbd27e 100644 --- a/kraken/lib/src/css/style_declaration.dart +++ b/kraken/lib/src/css/style_declaration.dart @@ -370,9 +370,6 @@ class CSSStyleDeclaration { Element? _target = target; // If style target element not exists, no need to do flush operation. if (_target == null) return; - // If target's renderer has created, but not adopted by a parent, - // in most cases it's a sliver child orphan, should not flush styles. - if (_target.renderer?.parent == null) return; // If target's parent element has no renderer attached, no need to flush. if (_target.parentNode?.isRendererAttached == false) return; diff --git a/kraken/lib/src/dom/element.dart b/kraken/lib/src/dom/element.dart index 72180d1be0..9b42a851e7 100644 --- a/kraken/lib/src/dom/element.dart +++ b/kraken/lib/src/dom/element.dart @@ -477,6 +477,11 @@ class Element extends Node RenderBoxModel _renderBoxModel = renderBoxModel!; CSSPositionType currentPosition = renderStyle.position; + // If renderer itself not attached, no need to re-attach it. + if (!_renderBoxModel.attached) { + return; + } + // Remove fixed children before convert to non repaint boundary renderObject if (currentPosition != CSSPositionType.fixed) { _removeFixedChild(_renderBoxModel, elementManager.viewportElement._renderLayoutBox!); From 43214cde105a214391b4dc01921a063b2e795705 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=93=E5=87=8C?= Date: Mon, 29 Nov 2021 17:38:37 +0800 Subject: [PATCH 4/9] fix: test case await need async --- integration_tests/specs/css/css-display/sliver.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration_tests/specs/css/css-display/sliver.ts b/integration_tests/specs/css/css-display/sliver.ts index 193dbdf77f..22985be835 100644 --- a/integration_tests/specs/css/css-display/sliver.ts +++ b/integration_tests/specs/css/css-display/sliver.ts @@ -200,7 +200,7 @@ describe('display sliver', () => { await simulateClick(50, 20); // Will trigger done. }); - it('sliver child with none-static position not throw errors', () => { + it('sliver child with none-static position not throw errors', async () => { var container = createSliverBasicCase(); var firstChild = container.firstChild; // should be element. firstChild.style.position = 'relative'; From ec547528faaf0c6ea2b887abc3ce5515ed9c8346 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=93=E5=87=8C?= Date: Tue, 30 Nov 2021 15:31:21 +0800 Subject: [PATCH 5/9] fix: test cases --- integration_tests/specs/window/global.ts | 3 ++- kraken/lib/src/css/style_declaration.dart | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/integration_tests/specs/window/global.ts b/integration_tests/specs/window/global.ts index 6329c8ab92..85fb17804b 100644 --- a/integration_tests/specs/window/global.ts +++ b/integration_tests/specs/window/global.ts @@ -1,4 +1,4 @@ -describe('windowisglobal', () => { +describe('window', () => { it('window equal to globalThis', () => { expect(window).toBe(globalThis as any); }); @@ -7,6 +7,7 @@ describe('windowisglobal', () => { // @ts-ignore expect(typeof window.kraken).toBe('object'); }); + it('equal to this', () => { function f() { // @ts-ignore diff --git a/kraken/lib/src/css/style_declaration.dart b/kraken/lib/src/css/style_declaration.dart index f984dbd27e..05d910fc52 100644 --- a/kraken/lib/src/css/style_declaration.dart +++ b/kraken/lib/src/css/style_declaration.dart @@ -371,10 +371,10 @@ class CSSStyleDeclaration { // If style target element not exists, no need to do flush operation. if (_target == null) return; // If target's parent element has no renderer attached, no need to flush. - if (_target.parentNode?.isRendererAttached == false) return; + if (_target.parentNode?.renderer == null) return; // Display change from none to other value that the renderBoxModel is null. - if (_pendingProperties.containsKey(DISPLAY) && target!.isConnected) { + if (_pendingProperties.containsKey(DISPLAY) && _target.isConnected) { String? prevValue = _properties[DISPLAY]; String currentValue = _pendingProperties[DISPLAY]!; _properties[DISPLAY] = currentValue; @@ -382,7 +382,7 @@ class CSSStyleDeclaration { _emitPropertyChanged(DISPLAY, prevValue, currentValue); } - RenderBoxModel? renderBoxModel = target!.renderBoxModel; + RenderBoxModel? renderBoxModel = _target.renderBoxModel; if (_pendingProperties.isEmpty || renderBoxModel == null) { return; } From df165c097566a4461eccc372a0606712503fdaa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=93=E5=87=8C?= Date: Tue, 30 Nov 2021 16:47:31 +0800 Subject: [PATCH 6/9] fix: Root element creation should flush after renderobject attached. --- kraken/lib/src/css/style_declaration.dart | 4 +-- kraken/lib/src/dom/element.dart | 6 +++- kraken/lib/src/rendering/flex.dart | 41 +++++++++++------------ 3 files changed, 26 insertions(+), 25 deletions(-) diff --git a/kraken/lib/src/css/style_declaration.dart b/kraken/lib/src/css/style_declaration.dart index 05d910fc52..85297bcbe6 100644 --- a/kraken/lib/src/css/style_declaration.dart +++ b/kraken/lib/src/css/style_declaration.dart @@ -370,8 +370,8 @@ class CSSStyleDeclaration { Element? _target = target; // If style target element not exists, no need to do flush operation. if (_target == null) return; - // If target's parent element has no renderer attached, no need to flush. - if (_target.parentNode?.renderer == null) return; + // If target has no renderer attached, skip flush. + if (!_target.isRendererAttached) return; // Display change from none to other value that the renderBoxModel is null. if (_pendingProperties.containsKey(DISPLAY) && _target.isConnected) { diff --git a/kraken/lib/src/dom/element.dart b/kraken/lib/src/dom/element.dart index ffaa6fcf23..6bff618716 100644 --- a/kraken/lib/src/dom/element.dart +++ b/kraken/lib/src/dom/element.dart @@ -192,7 +192,11 @@ class Element extends Node RenderBox? after; if (previousRenderBoxModel != null) { parentRenderBox = previousRenderBoxModel.parent as RenderBox?; - after = (previousRenderBoxModel.parentData as ContainerParentDataMixin?)?.previousSibling; + + if (previousRenderBoxModel.parentData is ContainerParentDataMixin) { + after = (previousRenderBoxModel.parentData as ContainerParentDataMixin).previousSibling; + } + _detachRenderBoxModel(previousRenderBoxModel); if (parentRenderBox != null) { diff --git a/kraken/lib/src/rendering/flex.dart b/kraken/lib/src/rendering/flex.dart index fb897be109..29b0b8dbaa 100644 --- a/kraken/lib/src/rendering/flex.dart +++ b/kraken/lib/src/rendering/flex.dart @@ -667,7 +667,7 @@ class RenderFlexLayout extends RenderLayoutBox { // Layout placeholder of positioned element(absolute/fixed) in new layer if (child is RenderBoxModel && childParentData.isPositioned) { CSSPositionedLayout.layoutPositionedChild(this, child); - } else if (child is RenderPositionPlaceholder && isPlaceholderPositioned(child)) { + } else if (child is RenderPositionPlaceholder && _isPlaceholderPositioned(child)) { _layoutChildren(child); } @@ -716,19 +716,6 @@ class RenderFlexLayout extends RenderLayoutBox { didLayout(); } - - bool isPlaceholderPositioned(RenderObject child) { - if (child is RenderPositionPlaceholder) { - RenderBoxModel realDisplayedBox = child.positioned!; - RenderLayoutParentData parentData = - realDisplayedBox.parentData as RenderLayoutParentData; - if (parentData.isPositioned) { - return true; - } - } - return false; - } - /// There are 4 stages when layouting children /// 1. Layout children in flow order to calculate flex lines according to its constaints and flex-wrap property /// 2. Relayout children according to flex-grow and flex-shrink factor @@ -906,7 +893,7 @@ class RenderFlexLayout extends RenderLayoutBox { // Exclude positioned placeholder renderObject when layout non placeholder object // and positioned renderObject if (placeholderChild == null && - (isPlaceholderPositioned(child) || childParentData!.isPositioned)) { + (_isPlaceholderPositioned(child) || childParentData!.isPositioned)) { child = childParentData!.nextSibling; continue; } @@ -920,12 +907,11 @@ class RenderFlexLayout extends RenderLayoutBox { childNodeId = child.hashCode; } - if (isPlaceholderPositioned(child)) { - RenderBoxModel realDisplayedBox = (child as RenderPositionPlaceholder).positioned!; - if (realDisplayedBox.hasSize) { + if (_isPlaceholderPositioned(child)) { + RenderBoxModel positionedBox = (child as RenderPositionPlaceholder).positioned!; + if (positionedBox.hasSize) { // Flutter only allow access size of direct children, so cannot use realDisplayedBox.size - Size realDisplayedBoxSize = - realDisplayedBox.getBoxSize(realDisplayedBox.contentSize); + Size realDisplayedBoxSize = positionedBox.getBoxSize(positionedBox.contentSize); double realDisplayedBoxWidth = realDisplayedBoxSize.width; double realDisplayedBoxHeight = realDisplayedBoxSize.height; childConstraints = BoxConstraints( @@ -1349,7 +1335,7 @@ class RenderFlexLayout extends RenderLayoutBox { // Whether child is positioned placeholder or positioned renderObject bool isChildPositioned = placeholderChild == null && - (isPlaceholderPositioned(child) || childParentData!.isPositioned); + (_isPlaceholderPositioned(child) || childParentData!.isPositioned); // Whether child cross size should be changed based on cross axis alignment change bool isCrossSizeChanged = false; @@ -2012,7 +1998,7 @@ class RenderFlexLayout extends RenderLayoutBox { // Exclude positioned placeholder renderObject when layout non placeholder object // and positioned renderObject if (placeholderChild == null && - (isPlaceholderPositioned(child) || childParentData!.isPositioned)) { + (_isPlaceholderPositioned(child) || childParentData!.isPositioned)) { child = childParentData!.nextSibling; continue; } @@ -2500,6 +2486,17 @@ class RenderFlexLayout extends RenderLayoutBox { properties .add(DiagnosticsProperty('flexWrap', renderStyle.flexWrap)); } + + static bool _isPlaceholderPositioned(RenderObject child) { + if (child is RenderPositionPlaceholder) { + RenderBoxModel realDisplayedBox = child.positioned!; + RenderLayoutParentData parentData = realDisplayedBox.parentData as RenderLayoutParentData; + if (parentData.isPositioned) { + return true; + } + } + return false; + } } // Render flex layout with self repaint boundary. From 50df3c138de1c6d6a7f310f913a9ea649121a027 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=93=E5=87=8C?= Date: Tue, 30 Nov 2021 16:47:41 +0800 Subject: [PATCH 7/9] fix: Root element creation should flush after renderobject attached. --- kraken/lib/src/dom/elements/html.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kraken/lib/src/dom/elements/html.dart b/kraken/lib/src/dom/elements/html.dart index a4943ae1d5..fca82b0029 100644 --- a/kraken/lib/src/dom/elements/html.dart +++ b/kraken/lib/src/dom/elements/html.dart @@ -41,6 +41,8 @@ class HTMLElement extends Element { super.attachTo(parent); if (renderBoxModel != null) { elementManager.viewport.child = renderBoxModel!; + // Flush pending style immediately. + style.flushPendingProperties(); } } From 43a8a6083d9921278c0e70f6a6e21626e6fe63fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=93=E5=87=8C?= Date: Tue, 30 Nov 2021 17:08:48 +0800 Subject: [PATCH 8/9] fix: Root element creation should flush after renderobject attached. --- kraken/lib/src/dom/element.dart | 5 ----- 1 file changed, 5 deletions(-) diff --git a/kraken/lib/src/dom/element.dart b/kraken/lib/src/dom/element.dart index 6bff618716..c60973aa11 100644 --- a/kraken/lib/src/dom/element.dart +++ b/kraken/lib/src/dom/element.dart @@ -481,11 +481,6 @@ class Element extends Node RenderBoxModel _renderBoxModel = renderBoxModel!; CSSPositionType currentPosition = renderStyle.position; - // If renderer itself not attached, no need to re-attach it. - if (!_renderBoxModel.attached) { - return; - } - // Remove fixed children before convert to non repaint boundary renderObject if (currentPosition != CSSPositionType.fixed) { _removeFixedChild(_renderBoxModel, elementManager.viewportElement._renderLayoutBox!); From 2c8f0e74f1deea75c65f0537f18571c06e4888f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8D=93=E5=87=8C?= Date: Tue, 30 Nov 2021 19:39:07 +0800 Subject: [PATCH 9/9] fix: sliver child. --- kraken/lib/src/css/style_declaration.dart | 8 ++++-- kraken/lib/src/dom/element.dart | 34 ++++++++++++----------- kraken/lib/src/dom/elements/html.dart | 3 ++ kraken/lib/src/dom/sliver_manager.dart | 10 +++---- 4 files changed, 30 insertions(+), 25 deletions(-) diff --git a/kraken/lib/src/css/style_declaration.dart b/kraken/lib/src/css/style_declaration.dart index 85297bcbe6..e01389de05 100644 --- a/kraken/lib/src/css/style_declaration.dart +++ b/kraken/lib/src/css/style_declaration.dart @@ -370,11 +370,10 @@ class CSSStyleDeclaration { Element? _target = target; // If style target element not exists, no need to do flush operation. if (_target == null) return; - // If target has no renderer attached, skip flush. - if (!_target.isRendererAttached) return; // Display change from none to other value that the renderBoxModel is null. - if (_pendingProperties.containsKey(DISPLAY) && _target.isConnected) { + if (_pendingProperties.containsKey(DISPLAY) && _target.isConnected && + _target.parentElement?.renderStyle.display != CSSDisplay.sliver) { String? prevValue = _properties[DISPLAY]; String currentValue = _pendingProperties[DISPLAY]!; _properties[DISPLAY] = currentValue; @@ -382,6 +381,9 @@ class CSSStyleDeclaration { _emitPropertyChanged(DISPLAY, prevValue, currentValue); } + // If target has no renderer attached, no need to flush. + if (!_target.isRendererAttached) return; + RenderBoxModel? renderBoxModel = _target.renderBoxModel; if (_pendingProperties.isEmpty || renderBoxModel == null) { return; diff --git a/kraken/lib/src/dom/element.dart b/kraken/lib/src/dom/element.dart index c60973aa11..af7a946a35 100644 --- a/kraken/lib/src/dom/element.dart +++ b/kraken/lib/src/dom/element.dart @@ -188,10 +188,10 @@ class Element extends Node RenderBox? previousRenderBoxModel = renderBoxModel; if (nextRenderBoxModel != previousRenderBoxModel) { - RenderBox? parentRenderBox; + RenderObject? parentRenderObject; RenderBox? after; if (previousRenderBoxModel != null) { - parentRenderBox = previousRenderBoxModel.parent as RenderBox?; + parentRenderObject = previousRenderBoxModel.parent as RenderObject?; if (previousRenderBoxModel.parentData is ContainerParentDataMixin) { after = (previousRenderBoxModel.parentData as ContainerParentDataMixin).previousSibling; @@ -199,8 +199,8 @@ class Element extends Node _detachRenderBoxModel(previousRenderBoxModel); - if (parentRenderBox != null) { - _attachRenderBoxModel(parentRenderBox, nextRenderBoxModel, after: after); + if (parentRenderObject != null) { + _attachRenderBoxModel(parentRenderObject, nextRenderBoxModel, after: after); } } renderBoxModel = nextRenderBoxModel; @@ -579,7 +579,10 @@ class Element extends Node void attachTo(Node parent, {RenderBox? after}) { _applyStyle(style); - willAttachRenderer(); + // @NOTE: Sliver should not create renderer here. + if (parentElement?.renderStyle.display != CSSDisplay.sliver) { + willAttachRenderer(); + } if (renderer != null) { // HTML element override attachTo method to attach renderObject to viewportBox. @@ -802,28 +805,27 @@ class Element extends Node // Update renderBoxModel. _updateRenderBoxModel(); // Attach renderBoxModel to parent if change from `display: none` to other values. - if (renderBoxModel!.parent == null) { + if (!isRendererAttached && parentElement != null && parentElement!.isRendererAttached) { _addToContainingBlock(after: previousSibling?.renderer); ensureChildAttached(); } } - void _attachRenderBoxModel(RenderBox parentRenderBox, RenderBox renderBox, {RenderObject? after, bool isLast = false}) { + void _attachRenderBoxModel(RenderObject parentRenderObject, RenderBox renderBox, {RenderObject? after, bool isLast = false}) { if (isLast) { assert(after == null); } - if (parentRenderBox is RenderObjectWithChildMixin) { // RenderViewportBox - (parentRenderBox as RenderObjectWithChildMixin).child = renderBox; - } else if (parentRenderBox is ContainerRenderObjectMixin) { // RenderLayoutBox or RenderSliverList + if (parentRenderObject is RenderObjectWithChildMixin) { // RenderViewportBox + parentRenderObject.child = renderBox; + } else if (parentRenderObject is ContainerRenderObjectMixin) { // RenderLayoutBox or RenderSliverList // Should attach to renderScrollingContent if it is scrollable. - if (parentRenderBox is RenderLayoutBox) { - parentRenderBox = parentRenderBox.renderScrollingContent ?? parentRenderBox; + if (parentRenderObject is RenderLayoutBox) { + parentRenderObject = parentRenderObject.renderScrollingContent ?? parentRenderObject; } if (isLast) { - after = (parentRenderBox as ContainerRenderObjectMixin).lastChild; + after = parentRenderObject.lastChild; } - (parentRenderBox as ContainerRenderObjectMixin).insert(renderBox, after: after); - + parentRenderObject.insert(renderBox, after: after); } } @@ -1708,7 +1710,7 @@ bool _hasIntersectionObserverEvent(Map eventHandlers) { eventHandlers.containsKey('intersectionchange'); } -void _detachRenderBoxModel(RenderBox renderBox) { +void _detachRenderBoxModel(RenderObject renderBox) { if (renderBox.parent == null) return; // Remove reference from parent diff --git a/kraken/lib/src/dom/elements/html.dart b/kraken/lib/src/dom/elements/html.dart index fca82b0029..0d51f1d93f 100644 --- a/kraken/lib/src/dom/elements/html.dart +++ b/kraken/lib/src/dom/elements/html.dart @@ -64,4 +64,7 @@ class HTMLElement extends Element { @override String get tagName => HTML; + + @override + bool get isRendererAttached => true; } diff --git a/kraken/lib/src/dom/sliver_manager.dart b/kraken/lib/src/dom/sliver_manager.dart index 72ce6f5d79..4307175e7b 100644 --- a/kraken/lib/src/dom/sliver_manager.dart +++ b/kraken/lib/src/dom/sliver_manager.dart @@ -49,11 +49,6 @@ class RenderSliverElementChildManager implements RenderSliverBoxChildManager { childNode.willAttachRenderer(); RenderBox? child; - - if (childNode is Element) { - childNode.style.flushPendingProperties(); - } - if (childNode is Node) { child = childNode.renderer; } else { @@ -68,8 +63,11 @@ class RenderSliverElementChildManager implements RenderSliverBoxChildManager { _sliverListLayout.insertSliverChild(child, after: after); } + if (childNode is Element) { + childNode.style.flushPendingProperties(); + } + childNode.didAttachRenderer(); - childNode.ensureChildAttached(); } RenderBox _createEmptyRenderObject() {