diff --git a/wp-includes/blocks.php b/wp-includes/blocks.php index 8472c7e092..56410779fe 100644 --- a/wp-includes/blocks.php +++ b/wp-includes/blocks.php @@ -2404,11 +2404,32 @@ function parse_blocks( $content ) { * @return string Updated post content. */ function do_blocks( $content ) { - $blocks = parse_blocks( $content ); - $output = ''; + $blocks = parse_blocks( $content ); + $top_level_block_count = count( $blocks ); + $output = ''; - foreach ( $blocks as $block ) { - $output .= render_block( $block ); + /** + * Parsed blocks consist of a list of top-level blocks. Those top-level + * blocks may themselves contain nested inner blocks. However, every + * top-level block is rendered independently, meaning there are no data + * dependencies between them. + * + * Ideally, therefore, the parser would only need to parse one complete + * top-level block at a time, render it, and move on. Unfortunately, this + * is not possible with {@see \parse_blocks()} because it must parse the + * entire given document at once. + * + * While the current implementation prevents this optimization, it’s still + * possible to reduce the peak memory use when calls to `render_block()` + * on those top-level blocks are memory-heavy (which many of them are). + * By setting each parsed block to `NULL` after rendering it, any memory + * allocated during the render will be freed and reused for the next block. + * Before making this change, that memory was retained and would lead to + * out-of-memory crashes for certain posts that now run with this change. + */ + for ( $i = 0; $i < $top_level_block_count; $i++ ) { + $output .= render_block( $blocks[ $i ] ); + $blocks[ $i ] = null; } // If there are blocks in this content, we shouldn't run wpautop() on it later. diff --git a/wp-includes/version.php b/wp-includes/version.php index 3130973e27..5b7c77f1f2 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -16,7 +16,7 @@ * * @global string $wp_version */ -$wp_version = '6.8.2-alpha-60434'; +$wp_version = '6.8.2-alpha-60435'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.