Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Make the hidden class instance static
  • Loading branch information
sirreal committed Aug 21, 2025
commit 7bd16b538e9623d5a670ded89e934050f3726ed8
77 changes: 40 additions & 37 deletions src/wp-includes/class-wp-block.php
Original file line number Diff line number Diff line change
Expand Up @@ -463,49 +463,52 @@ private function replace_html( string $block_content, string $attribute_name, $s
}

private static function get_block_bindings_processor( string $block_content ) {
$internal_processor_class = new class('', WP_HTML_Processor::CONSTRUCTOR_UNLOCK_CODE) extends WP_HTML_Processor {
private $output = '';
private $end_of_flushed = 0;

public function build() {
return $this->output . substr( $this->get_updated_html(), $this->end_of_flushed );
}

/**
* Replace the rich text content between a tag opener and matching closer.
*
* When stopped on a tag opener, replace the content enclosed by it and its
* matching closer with the provided rich text.
*
* @param string $rich_text The rich text to replace the original content with.
* @return bool True on success.
*/
public function replace_rich_text( $rich_text ) {
if ( $this->is_tag_closer() ) {
return false;
static $internal_processor_class = null;
Copy link

@dmsnell dmsnell Aug 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’m assuming this was done as an optimization; if so, it’s pointless because anonymous classes are static in PHP anyway. At parse time it will create a separate class with a generated name and then when instantiating it or calling a static method on it, PHP calls from the generated class instead of some dynamic variable dispatch as the code suggests.

<?php

$c = new class () {
    public function speak() { return __CLASS__; }
    public static function name() { return __CLASS__; }
};

echo $c->speak() . PHP_EOL;
echo $c::name() . PHP_EOL;
class@anonymous/in/1H8Jo:3$0
class@anonymous/in/1H8Jo:3$0
VLD output
Finding entry points
Branch analysis from position: 0
1 jumps found. (Code = 62) Position 1 = -2
filename:       /in/1H8Jo
function name:  (null)
number of ops:  14
compiled vars:  !0 = $c
line      #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
    3     0  E >   DECLARE_ANON_CLASS                                
          1        NEW                                              $2      $1
          2        DO_FCALL                                      0          
          3        ASSIGN                                                   !0, $2
    8     4        INIT_METHOD_CALL                                         !0, 'speak'
          5        DO_FCALL                                      0  $5      
          6        CONCAT                                           ~6      $5, '%0A'
          7        ECHO                                                     ~6
    9     8        FETCH_CLASS                                   0  $7      !0
          9        INIT_STATIC_METHOD_CALL                                  $7, 'name'
         10        DO_FCALL                                      0  $8      
         11        CONCAT                                           ~9      $8, '%0A'
         12        ECHO                                                     ~9
   10    13      > RETURN                                                   1

Class class@anonymous:
Function speak:
Finding entry points
Branch analysis from position: 0
1 jumps found. (Code = 62) Position 1 = -2
filename: /in/1H8Jo
function name: speak
number of ops: 2
compiled vars: none
line #* E I O op fetch ext return operands

4     0  E > > RETURN                                                   'class%40anonymous%00%2Fin%2F1H8Jo%3A3%240'
      1*     > RETURN                                                   null

End of function speak

Function name:
Finding entry points
Branch analysis from position: 0
1 jumps found. (Code = 62) Position 1 = -2
filename: /in/1H8Jo
function name: name
number of ops: 2
compiled vars: none
line #* E I O op fetch ext return operands

5     0  E > > RETURN                                                   'class%40anonymous%00%2Fin%2F1H8Jo%3A3%240'
      1*     > RETURN                                                   null

End of function name

End of class class@anonymous.

so assigning it to a static variable does nothing but duplicate it.

if ( null === $internal_processor_class ) {
$internal_processor_class = new class('', WP_HTML_Processor::CONSTRUCTOR_UNLOCK_CODE) extends WP_HTML_Processor {
private $output = '';
private $end_of_flushed = 0;

public function build() {
return $this->output . substr( $this->get_updated_html(), $this->end_of_flushed );
}

$depth = $this->get_current_depth();
/**
* Replace the rich text content between a tag opener and matching closer.
*
* When stopped on a tag opener, replace the content enclosed by it and its
* matching closer with the provided rich text.
*
* @param string $rich_text The rich text to replace the original content with.
* @return bool True on success.
*/
public function replace_rich_text( $rich_text ) {
if ( $this->is_tag_closer() ) {
return false;
}

$this->set_bookmark( '_wp_block_bindings_tag_opener' );
// The bookmark names are prefixed with `_` so the key below has an extra `_`.
$bm = $this->bookmarks['__wp_block_bindings_tag_opener'];
$this->output .= substr( $this->get_updated_html(), $this->end_of_flushed, $bm->start + $bm->length );
$this->output .= $rich_text;
$this->release_bookmark( '_wp_block_bindings_tag_opener' );
$depth = $this->get_current_depth();

// Find matching tag closer.
while ( $this->next_token() && $this->get_current_depth() >= $depth ) {
}
$this->set_bookmark( '_wp_block_bindings_tag_opener' );
// The bookmark names are prefixed with `_` so the key below has an extra `_`.
$bm = $this->bookmarks['__wp_block_bindings_tag_opener'];
$this->output .= substr( $this->get_updated_html(), $this->end_of_flushed, $bm->start + $bm->length );
$this->output .= $rich_text;
$this->release_bookmark( '_wp_block_bindings_tag_opener' );

$this->set_bookmark( '_wp_block_bindings_tag_closer' );
$bm = $this->bookmarks['__wp_block_bindings_tag_closer'];
$this->end_of_flushed = $bm->start;
$this->release_bookmark( '_wp_block_bindings_tag_closer' );
// Find matching tag closer.
while ( $this->next_token() && $this->get_current_depth() >= $depth ) {
}

return true;
}
};
$this->set_bookmark( '_wp_block_bindings_tag_closer' );
$bm = $this->bookmarks['__wp_block_bindings_tag_closer'];
$this->end_of_flushed = $bm->start;
$this->release_bookmark( '_wp_block_bindings_tag_closer' );

return true;
}
};
}

return $internal_processor_class::create_fragment( $block_content );
}
Expand Down