Make WordPress Core


Ignore:
Timestamp:
10/17/2025 02:33:53 PM (5 months ago)
Author:
luisherranz
Message:

Interactivity API: Support lazy-loaded derived state props.

Serialize on the server the paths of derived state closures accessed during directive processing and include them in the serialized data. During the Interactivity API hydration, if a directive reads one of those paths before its JavaScript getter is available, keep the server-rendered value intact instead of replacing it with undefined.

props darerodz.
Fixes #63898.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/interactivity-api/wpInteractivityAPI-wp-each.php

    r58594 r60953  
    8989                '<span data-wp-text="myPlugin::context.item"></span>' .
    9090            '</template>' .
    91             '<span data-wp-each-child data-wp-text="myPlugin::context.item">1</span>' .
    92             '<span data-wp-each-child data-wp-text="myPlugin::context.item">2</span>' .
     91            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.item">1</span>' .
     92            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.item">2</span>' .
    9393            '<div id="after-wp-each" data-wp-bind--id="myPlugin::state.after">Text</div>';
    9494        $new      = $this->interactivity->process_directives( $original );
     
    141141                    '<span data-wp-bind--id="myPlugin::context.id" data-wp-text="myPlugin::context.item"></span>' .
    142142                '</template>' .
    143                 '<span data-wp-each-child id="some-id" data-wp-bind--id="myPlugin::context.id" data-wp-text="myPlugin::context.item">1</span>' .
    144                 '<span data-wp-each-child id="some-id" data-wp-bind--id="myPlugin::context.id" data-wp-text="myPlugin::context.item">2</span>' .
     143                '<span data-wp-each-child="myPlugin::state.list" id="some-id" data-wp-bind--id="myPlugin::context.id" data-wp-text="myPlugin::context.item">1</span>' .
     144                '<span data-wp-each-child="myPlugin::state.list" id="some-id" data-wp-bind--id="myPlugin::context.id" data-wp-text="myPlugin::context.item">2</span>' .
    145145                '<div id="after-wp-each" data-wp-bind--id="myPlugin::context.after" data-wp-text="myPlugin::context.item">New text</div>' .
    146146            '</div>';
     
    169169                    '<span data-wp-text="myPlugin::context.item"></span>' .
    170170                '</template>' .
    171                 '<span data-wp-each-child data-wp-text="myPlugin::context.item">1</span>' .
    172                 '<span data-wp-each-child data-wp-text="myPlugin::context.item">2</span>' .
     171                '<span data-wp-each-child="myPlugin::context.list" data-wp-text="myPlugin::context.item">1</span>' .
     172                '<span data-wp-each-child="myPlugin::context.list" data-wp-text="myPlugin::context.item">2</span>' .
    173173                '<div id="after-wp-each" data-wp-bind--id="myPlugin::state.after">Text</div>' .
    174174            '</div>';
     
    197197                    '<span data-wp-text="context.item"></span>' .
    198198                '</template>' .
    199                 '<span data-wp-each-child data-wp-text="context.item">1</span>' .
    200                 '<span data-wp-each-child data-wp-text="context.item">2</span>' .
     199                '<span data-wp-each-child="myPlugin::state.list" data-wp-text="context.item">1</span>' .
     200                '<span data-wp-each-child="myPlugin::state.list" data-wp-text="context.item">2</span>' .
    201201                '<div id="after-wp-each" data-wp-bind--id="state.after">Text</div>' .
    202202            '</div>';
     
    224224                '<span data-wp-text="myPlugin::context.item"></span>' .
    225225            '</template>' .
    226             '<span data-wp-each-child data-wp-text="myPlugin::context.item">1</span>' .
    227             '<span data-wp-each-child data-wp-text="myPlugin::context.item">1</span>' .
    228             '<span data-wp-each-child data-wp-text="myPlugin::context.item">2</span>' .
    229             '<span data-wp-each-child data-wp-text="myPlugin::context.item">2</span>' .
     226            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.item">1</span>' .
     227            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.item">1</span>' .
     228            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.item">2</span>' .
     229            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.item">2</span>' .
    230230            '<div id="after-wp-each" data-wp-bind--id="myPlugin::state.after">Text</div>';
    231231        $new      = $this->interactivity->process_directives( $original );
     
    252252                '<img data-wp-bind--id="myPlugin::context.item">' .
    253253            '</template>' .
    254             '<img data-wp-each-child id="1" data-wp-bind--id="myPlugin::context.item">' .
    255             '<img data-wp-each-child id="1" data-wp-bind--id="myPlugin::context.item">' .
    256             '<img data-wp-each-child id="2" data-wp-bind--id="myPlugin::context.item">' .
    257             '<img data-wp-each-child id="2" data-wp-bind--id="myPlugin::context.item">' .
     254            '<img data-wp-each-child="myPlugin::state.list" id="1" data-wp-bind--id="myPlugin::context.item">' .
     255            '<img data-wp-each-child="myPlugin::state.list" id="1" data-wp-bind--id="myPlugin::context.item">' .
     256            '<img data-wp-each-child="myPlugin::state.list" id="2" data-wp-bind--id="myPlugin::context.item">' .
     257            '<img data-wp-each-child="myPlugin::state.list" id="2" data-wp-bind--id="myPlugin::context.item">' .
    258258            '<div id="after-wp-each" data-wp-bind--id="myPlugin::state.after">Text</div>';
    259259        $new      = $this->interactivity->process_directives( $original );
     
    281281                '<span data-wp-text="myPlugin::context.item"></span>' .
    282282            '</template>' .
    283             '<img data-wp-each-child id="1" data-wp-bind--id="myPlugin::context.item">' .
    284             '<span data-wp-each-child data-wp-text="myPlugin::context.item">1</span>' .
    285             '<img data-wp-each-child id="2" data-wp-bind--id="myPlugin::context.item">' .
    286             '<span data-wp-each-child data-wp-text="myPlugin::context.item">2</span>' .
     283            '<img data-wp-each-child="myPlugin::state.list" id="1" data-wp-bind--id="myPlugin::context.item">' .
     284            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.item">1</span>' .
     285            '<img data-wp-each-child="myPlugin::state.list" id="2" data-wp-bind--id="myPlugin::context.item">' .
     286            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.item">2</span>' .
    287287            '<div id="after-wp-each" data-wp-bind--id="myPlugin::state.after">Text</div>';
    288288        $new      = $this->interactivity->process_directives( $original );
     
    311311                '</div>' .
    312312            '</template>' .
    313             '<div data-wp-each-child id="1" data-wp-bind--id="myPlugin::context.item">' .
     313            '<div data-wp-each-child="myPlugin::state.list" id="1" data-wp-bind--id="myPlugin::context.item">' .
    314314                'id: <span data-wp-text="myPlugin::context.item">1</span>' .
    315315            '</div>' .
    316             '<div data-wp-each-child id="2" data-wp-bind--id="myPlugin::context.item">' .
     316            '<div data-wp-each-child="myPlugin::state.list" id="2" data-wp-bind--id="myPlugin::context.item">' .
    317317                'id: <span data-wp-text="myPlugin::context.item">2</span>' .
    318318            '</div>' .
     
    356356                '<span data-wp-text="myPlugin::context.item.name"></span>' .
    357357            '</template>' .
    358             '<span data-wp-each-child data-wp-text="myPlugin::context.item.id">1</span>' .
    359             '<span data-wp-each-child data-wp-text="myPlugin::context.item.name">one</span>' .
    360             '<span data-wp-each-child data-wp-text="myPlugin::context.item.id">2</span>' .
    361             '<span data-wp-each-child data-wp-text="myPlugin::context.item.name">two</span>' .
     358            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.item.id">1</span>' .
     359            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.item.name">one</span>' .
     360            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.item.id">2</span>' .
     361            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.item.name">two</span>' .
    362362            '<div id="after-wp-each" data-wp-bind--id="myPlugin::state.after">Text</div>';
    363363        $new      = $this->interactivity->process_directives( $original );
     
    382382                '<span data-wp-text="myPlugin::context.myitem"></span>' .
    383383            '</template>' .
    384             '<span data-wp-each-child data-wp-text="myPlugin::context.myitem">1</span>' .
    385             '<span data-wp-each-child data-wp-text="myPlugin::context.myitem">2</span>' .
     384            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.myitem">1</span>' .
     385            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.myitem">2</span>' .
    386386            '<div id="after-wp-each" data-wp-bind--id="myPlugin::state.after">Text</div>';
    387387        $new      = $this->interactivity->process_directives( $original );
     
    407407                '<span data-wp-text="myPlugin::context.myItem"></span>' .
    408408            '</template>' .
    409             '<span data-wp-each-child data-wp-text="myPlugin::context.myItem">1</span>' .
    410             '<span data-wp-each-child data-wp-text="myPlugin::context.myItem">2</span>' .
     409            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.myItem">1</span>' .
     410            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.myItem">2</span>' .
    411411            '<div id="after-wp-each" data-wp-bind--id="myPlugin::state.after">Text</div>';
    412412        $new      = $this->interactivity->process_directives( $original );
     
    474474                '</template>' .
    475475            '</template>' .
    476             '<span data-wp-each-child data-wp-text="myPlugin::context.item1">1</span>' .
    477             '<template data-wp-each-child data-wp-each--item2="myPlugin::state.list2">' .
     476            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.item1">1</span>' .
     477            '<template data-wp-each-child="myPlugin::state.list" data-wp-each--item2="myPlugin::state.list2">' .
    478478                '<span data-wp-text="myPlugin::context.item2"></span>' .
    479479            '</template>' .
    480             '<span data-wp-each-child data-wp-text="myPlugin::context.item2">3</span>' .
    481             '<span data-wp-each-child data-wp-text="myPlugin::context.item2">4</span>' .
    482             '<span data-wp-each-child data-wp-text="myPlugin::context.item1">2</span>' .
    483             '<template data-wp-each-child data-wp-each--item2="myPlugin::state.list2">' .
     480            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.item2">3</span>' .
     481            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.item2">4</span>' .
     482            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.item1">2</span>' .
     483            '<template data-wp-each-child="myPlugin::state.list" data-wp-each--item2="myPlugin::state.list2">' .
    484484                '<span data-wp-text="myPlugin::context.item2"></span>' .
    485485            '</template>' .
    486             '<span data-wp-each-child data-wp-text="myPlugin::context.item2">3</span>' .
    487             '<span data-wp-each-child data-wp-text="myPlugin::context.item2">4</span>' .
     486            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.item2">3</span>' .
     487            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.item2">4</span>' .
    488488            '<div id="after-wp-each" data-wp-bind--id="myPlugin::state.after">Text</div>';
    489489        $new      = $this->interactivity->process_directives( $original );
     
    516516                '</template>' .
    517517            '</template>' .
    518             '<template data-wp-each-child data-wp-each--item2="myPlugin::state.list2">' .
     518            '<template data-wp-each-child="myPlugin::state.list" data-wp-each--item2="myPlugin::state.list2">' .
    519519                '<span data-wp-text="myPlugin::context.item1"></span>' .
    520520                '<span data-wp-text="myPlugin::context.item2"></span>' .
    521521            '</template>' .
    522             '<span data-wp-each-child data-wp-text="myPlugin::context.item1">1</span>' .
    523             '<span data-wp-each-child data-wp-text="myPlugin::context.item2">3</span>' .
    524             '<span data-wp-each-child data-wp-text="myPlugin::context.item1">1</span>' .
    525             '<span data-wp-each-child data-wp-text="myPlugin::context.item2">4</span>' .
    526             '<template data-wp-each-child data-wp-each--item2="myPlugin::state.list2">' .
     522            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.item1">1</span>' .
     523            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.item2">3</span>' .
     524            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.item1">1</span>' .
     525            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.item2">4</span>' .
     526            '<template data-wp-each-child="myPlugin::state.list" data-wp-each--item2="myPlugin::state.list2">' .
    527527                '<span data-wp-text="myPlugin::context.item1"></span>' .
    528528                '<span data-wp-text="myPlugin::context.item2"></span>' .
    529529            '</template>' .
    530             '<span data-wp-each-child data-wp-text="myPlugin::context.item1">2</span>' .
    531             '<span data-wp-each-child data-wp-text="myPlugin::context.item2">3</span>' .
    532             '<span data-wp-each-child data-wp-text="myPlugin::context.item1">2</span>' .
    533             '<span data-wp-each-child data-wp-text="myPlugin::context.item2">4</span>' .
     530            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.item1">2</span>' .
     531            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.item2">3</span>' .
     532            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.item1">2</span>' .
     533            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.item2">4</span>' .
    534534            '<div id="after-wp-each" data-wp-bind--id="myPlugin::state.after">Text</div>';
    535535        $new      = $this->interactivity->process_directives( $original );
     
    560560                '</template>' .
    561561            '</template>' .
    562             '<template data-wp-each-child data-wp-each--number="myPlugin::context.list">' .
     562            '<template data-wp-each-child="myPlugin::state.list2" data-wp-each--number="myPlugin::context.list">' .
    563563                '<span data-wp-text="myPlugin::context.number"></span>' .
    564564            '</template>' .
    565             '<span data-wp-each-child data-wp-text="myPlugin::context.number">1</span>' .
    566             '<span data-wp-each-child data-wp-text="myPlugin::context.number">2</span>' .
    567             '<template data-wp-each-child data-wp-each--number="myPlugin::context.list">' .
     565            '<span data-wp-each-child="myPlugin::state.list2" data-wp-text="myPlugin::context.number">1</span>' .
     566            '<span data-wp-each-child="myPlugin::state.list2" data-wp-text="myPlugin::context.number">2</span>' .
     567            '<template data-wp-each-child="myPlugin::state.list2" data-wp-each--number="myPlugin::context.list">' .
    568568                '<span data-wp-text="myPlugin::context.number"></span>' .
    569569            '</template>' .
    570             '<span data-wp-each-child data-wp-text="myPlugin::context.number">3</span>' .
    571             '<span data-wp-each-child data-wp-text="myPlugin::context.number">4</span>' .
     570            '<span data-wp-each-child="myPlugin::state.list2" data-wp-text="myPlugin::context.number">3</span>' .
     571            '<span data-wp-each-child="myPlugin::state.list2" data-wp-text="myPlugin::context.number">4</span>' .
    572572            '<div id="after-wp-each" data-wp-bind--id="myPlugin::state.after">Text</div>';
    573573        $new      = $this->interactivity->process_directives( $original );
     
    672672                '<span data-wp-text="myPlugin::context.item"></span>' .
    673673            '</template>' .
    674             '<span data-wp-each-child data-wp-text="myPlugin::context.item">1</span>' .
    675             '<span data-wp-each-child data-wp-text="myPlugin::context.item">2</span>' .
    676             '<div data-wp-bind--id="myPlugin::state.after">Text</div>';
    677         $expected = '' .
    678             '<template data-wp-each="myPlugin::state.list">' .
    679                 '<span data-wp-text="myPlugin::context.item"></span>' .
    680             '</template>' .
    681             '<span data-wp-each-child data-wp-text="myPlugin::context.item">1</span>' .
    682             '<span data-wp-each-child data-wp-text="myPlugin::context.item">2</span>' .
     674            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.item">1</span>' .
     675            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.item">2</span>' .
     676            '<div data-wp-bind--id="myPlugin::state.after">Text</div>';
     677        $expected = '' .
     678            '<template data-wp-each="myPlugin::state.list">' .
     679                '<span data-wp-text="myPlugin::context.item"></span>' .
     680            '</template>' .
     681            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.item">1</span>' .
     682            '<span data-wp-each-child="myPlugin::state.list" data-wp-text="myPlugin::context.item">2</span>' .
    683683            '<div id="after-wp-each" data-wp-bind--id="myPlugin::state.after">Text</div>';
    684684        $new      = $this->interactivity->process_directives( $original );
Note: See TracChangeset for help on using the changeset viewer.