Repository: flutter
Issue: [Accessibility]: Trying to open a custom widget throws node.parent == null || !node.parent!.isPartOfNodeMerging || node.isMergedIntoParent': is not true
Labels: framework,a: accessibility,f: gestures,has reproducible steps,P2,found in release: 3.0,found in release: 3.1,team-accessibility,triaged-accessibility

I was created the custom widget used to show the children based on row and column count and the widget is interact-able. It makes exception while place the widget inside the popup menu item when accessibility enabled.

## Steps to Reproduce

1. Run the below sample with accessibility enabled
2. Exception will show

<details>
  <summary>Exception</summary>

```
The following assertion was thrown during a scheduler callback:
'package:flutter/src/semantics/semantics.dart': Failed assertion: line 2651 pos 16: 'node.parent == null || !node.parent!.isPartOfNodeMerging || node.isMergedIntoParent': is not true.


Either the assertion indicates an error in the framework itself, or we should provide substantially more information in this error message to help you determine and fix the underlying cause.
In either case, please report this assertion by filing a bug on GitHub:
  https://github.com/flutter/flutter/issues/new?template=2_bug.md

When the exception was thrown, this was the stack: 
#2      SemanticsOwner.sendSemanticsUpdate (package:flutter/src/semantics/semantics.dart:2651:16)
#3      PipelineOwner.flushSemantics (package:flutter/src/rendering/object.dart:1082:24)
#4      RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:468:21)
#5      WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:876:13)
#6      RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:329:5)

```
</details>

<details>
  <summary>Sample Code</summary>

```dart

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

void main() => runApp(PickerSample());

class PickerSample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: PickerSampleWidget(),
    );
  }
}

class PickerSampleWidget extends StatefulWidget {
  @override
  _PickerSampleWidgetState createState() => _PickerSampleWidgetState();
}

class _PickerSampleWidgetState extends State<PickerSampleWidget> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: PopupMenuButton<int>(
            icon: Icon(Icons.calendar_today),
            itemBuilder: (BuildContext context) {
              return List.generate(1, (index) {
                return PopupMenuItem<int>(
                  value: index,
                  child: Container(
                    width: 250,
                    height: 250,
                    child: CustomWidget(),
                  ),
                );
              });
            }),
      ),
      body: Container(
          alignment: Alignment.center, child: Text('Popup menu button')),
    );
  }
}

class CustomWidget extends StatefulWidget {
  @override
  _CustomWidgetState createState() => _CustomWidgetState();
}

class _CustomWidgetState extends State<CustomWidget> {
  int _selectedIndex = -1;

  @override
  Widget build(BuildContext context) {
    final double width = MediaQuery.of(context).size.width;
    final double height = MediaQuery.of(context).size.height;
    return GestureDetector(
        behavior: HitTestBehavior.translucent,
        onTapUp: (TapUpDetails details) {
          final double xPosition = details.localPosition.dx;
          final double yPosition = details.localPosition.dy;
          final double viewWidth = width / 10;
          final double viewHeight = height / 5;
          final int row = yPosition ~/ viewHeight;
          final int column = xPosition ~/ viewWidth;
          setState(() {
            _selectedIndex = (row * 10) + column;
          });
        },
        child: Container(
          child: _MultiChildRenderObjectWidget(
            rowCount: 5,
            columnCount: 10,
            children: List.generate(50, (index) {
              return Container(
                color: _selectedIndex == index ? Colors.red : null,
                child: Center(
                    child: Text(
                  '$index',
                  style: Theme.of(context).textTheme.subtitle1,
                )),
              );
            }),
          ),
        ));
  }
}

class _MultiChildRenderObjectWidget extends MultiChildRenderObjectWidget {
  _MultiChildRenderObjectWidget(
      {this.rowCount,
      this.columnCount,
      List<Widget> children = const <Widget>[]})
      : super(children: children);

  final int rowCount;
  final int columnCount;

  @override
  _MultiChildRenderObject createRenderObject(BuildContext context) {
    return _MultiChildRenderObject(rowCount, columnCount);
  }

  @override
  void updateRenderObject(
      BuildContext context, _MultiChildRenderObject renderObject) {
    renderObject
      ..rowCount = rowCount
      ..columnCount = columnCount;
  }
}

class _ParentData extends ContainerBoxParentData<RenderBox> {}

class _MultiChildRenderObject extends RenderBox
    with ContainerRenderObjectMixin<RenderBox, _ParentData> {
  _MultiChildRenderObject(this._rowCount, this._columnCount);

  int _rowCount;

  int get rowCount => _rowCount;

  set rowCount(int value) {
    if (_rowCount == value) {
      return;
    }

    _rowCount = value;
    markNeedsLayout();
  }

  int _columnCount;

  int get columnCount => _columnCount;

  set columnCount(int value) {
    if (_columnCount == value) {
      return;
    }

    _columnCount = value;
    markNeedsLayout();
  }

  @override
  void setupParentData(covariant RenderObject child) {
    if (child.parentData is! _ParentData) {
      child.parentData = _ParentData();
    }
  }

  @override
  void performLayout() {
    final Size widgetSize = constraints.biggest;
    size = Size(widgetSize.width, widgetSize.height);
    RenderBox child = firstChild;
    if (child == null) {
      return;
    }

    final double cellWidth = size.width / _columnCount;
    final double cellHeight = size.height / _rowCount;
    while (child != null) {
      child.layout(constraints.copyWith(
          minHeight: cellHeight,
          maxHeight: cellHeight,
          minWidth: cellWidth,
          maxWidth: cellWidth));
      child = childAfter(child);
    }
  }

  @override
  void paint(PaintingContext context, Offset offset) {
    final double cellWidth = size.width / _columnCount;
    final double cellHeight = size.height / _rowCount;
    RenderBox child = firstChild;
    if (child == null) {
      return;
    }

    double xPosition = offset.dx, yPosition = offset.dy;
    while (child != null) {
      if (xPosition + 1 >= size.width) {
        xPosition = offset.dx;
        yPosition += cellHeight;
      }

      child.paint(context, Offset(xPosition, yPosition));
      child = childAfter(child);
      xPosition += cellWidth;
    }
  }

  @override
  void describeSemanticsConfiguration(SemanticsConfiguration config) {
    super.describeSemanticsConfiguration(config);
    config.isSemanticBoundary = true;
  }

  @override
  void assembleSemanticsNode(
    SemanticsNode node,
    SemanticsConfiguration config,
    Iterable<SemanticsNode> children,
  ) {
    final List<CustomPainterSemantics> semantics = <CustomPainterSemantics>[];
    final double cellWidth = size.width / _columnCount;
    final double cellHeight = size.height / _rowCount;
    RenderBox child = firstChild;
    if (child == null) {
      return;
    }

    double xPosition = 0, yPosition = 0;
    int index = 0;
    while (child != null) {
      if (xPosition + 1 >= size.width) {
        xPosition = 0;
        yPosition += cellHeight;
      }

      semantics.add(CustomPainterSemantics(
        rect: Rect.fromLTWH(xPosition, yPosition, cellWidth, cellHeight),
        properties: SemanticsProperties(
          label: index.toString(),
          textDirection: TextDirection.ltr,
        ),
      ));
      child = childAfter(child);
      index++;
      xPosition += cellWidth;
    }

    final List<SemanticsNode> semanticsNodes = <SemanticsNode>[];
    for (int i = 0; i < semantics.length; i++) {
      final CustomPainterSemantics currentSemantics = semantics[i];
      final SemanticsNode newChild = SemanticsNode(key: currentSemantics.key);

      final SemanticsProperties properties = currentSemantics.properties;
      final SemanticsConfiguration config = SemanticsConfiguration();
      if (properties.label != null) {
        config.label = properties.label;
      }
      if (properties.textDirection != null) {
        config.textDirection = properties.textDirection;
      }

      newChild.updateWith(
        config: config,
        // As of now CustomPainter does not support multiple tree levels.
        childrenInInversePaintOrder: const <SemanticsNode>[],
      );

      newChild
        ..rect = currentSemantics.rect
        ..transform = currentSemantics.transform
        ..tags = currentSemantics.tags;

      semanticsNodes.add(newChild);
    }

    final List<SemanticsNode> finalChildren = <SemanticsNode>[];
    finalChildren.addAll(semanticsNodes);
    finalChildren.addAll(children);
    super.assembleSemanticsNode(node, config, finalChildren);
  }
}

```

</details>

**Expected results:** 

- Sample will run without making crash.

**Actual results:** 

- Sample makes crash.