-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Self-nested blocks causing infinite recursion and crashing the editor #66090
Comments
Thanks for the report. As for Self-nested block, it seems that the problem can be solved by checking that the parents are not the same block: diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js
index a81d88de33..7409e88dbf 100644
--- a/packages/block-editor/src/store/selectors.js
+++ b/packages/block-editor/src/store/selectors.js
@@ -1584,7 +1584,8 @@ const isBlockVisibleInTheInserter = ( state, blockNameOrType ) => {
if ( !! blockType.parent?.length ) {
return blockType.parent.some(
( name ) =>
- isBlockVisibleInTheInserter( state, name ) ||
+ ( blockName !== name &&
+ isBlockVisibleInTheInserter( state, name ) ) ||
// Exception for blocks with post-content parent,
// the root level is often consider as "core/post-content".
// This exception should only apply to the post editor ideally though. However, I still don't have a good idea of how to deal with Circular-nested blocks. |
@t-hamano, something like this could work, although it's not a very clean solution: --- a/packages/block-editor/src/store/selectors.js
+++ b/packages/block-editor/src/store/selectors.js
@@ -1554,7 +1554,7 @@ export function getTemplateLock( state, rootClientId ) {
*
* @return {boolean} Whether the given block type is allowed to be inserted.
*/
-const isBlockVisibleInTheInserter = ( state, blockNameOrType ) => {
+const isBlockVisibleInTheInserter = ( state, blockNameOrType, checkedBlocks = new Set() ) => {
let blockType;
let blockName;
if ( blockNameOrType && 'object' === typeof blockNameOrType ) {
@@ -1579,11 +1579,17 @@ const isBlockVisibleInTheInserter = ( state, blockNameOrType ) => {
return false;
}
+ if ( checkedBlocks.has( blockName ) ) {
+ return false;
+ }
+
+ checkedBlocks.add( blockName );
+
// If parent blocks are not visible, child blocks should be hidden too.
if ( !! blockType.parent?.length ) {
return blockType.parent.some(
( name ) =>
- isBlockVisibleInTheInserter( state, name ) ||
+ isBlockVisibleInTheInserter( state, name, checkedBlocks ) ||
// Exception for blocks with post-content parent,
// the root level is often consider as "core/post-content".
// This exception should only apply to the post editor ideally though. Edit: Updated the diff slightly. |
That looks like a good approach. Anyone for a PR? |
I can handle this and will raise the PR shortly. |
Can we check the circular nesting and self-nesting at the time of registration, If circular nesting or self-nesting occurs, can we prevent block registration and throw a console error? |
Good question. I guess we should try to get clarity about whether "circular nesting" is desired or not? Curious @yuliyan how you're using that at the moment? |
Blocks that are self-nested or circularly nested can never be used in the first place. For example, if a block can only be added within itself, that condition will never occur. In the case of circular nesting, both blocks would be deadlocked. We will implement two solutions: if the parent has its own block name or if there’s a single block in circular nesting, we will stop the registration. For other cases, the previously provided solution will be applied. |
@youknowriad, I've discovered the issue while troubleshooting an editor crash caused by a block As for the "circular nesting" - I don't currently use such blocks, but I thought it was also a possible use case.
@SH4LIN, in my examples in the issue description, the self-nested block allows to also be nested in another block that's supposedly visible, e.g. This is probably an edge case, but we had such block that was working prior to 19.4.0. |
That seems like a valid use-case indeed. Thanks @yuliyan |
So yes, in your example, the given solution would work. However, if for some reason a developer mistakenly adds the parent attribute with its own block name, we should prevent registration and log a 'doing it wrong' error in the console. |
I agree - I doesn't make sense to have a parent attribute with just the block's own name. |
Here is the PR of the fix - #66121 |
Description
With the changes in #65700, self-nested or circular-nested blocks could cause infinite recursion resulting in crashing the editor.
cc: @youknowriad
Step-by-step reproduction instructions
Note that if a visible parent block comes first, e.g.
[ 'core/group', 'test/self-nested-block-2' ]
instead of[ 'test/self-nested-block-2', 'core/group' ]
, the infinite recursion will not occur.Screenshots, screen recording, code snippet
No response
Environment info
Please confirm that you have searched existing issues in the repo.
Please confirm that you have tested with all plugins deactivated except Gutenberg.
The text was updated successfully, but these errors were encountered: