Skip to content

Commit 3eb7c8d

Browse files
DAreRodzartemiomorales
authored andcommitted
Interactivity API: fix namespaces in nested interactive regions (#57029)
* Add failing test * Turn namespaces into a stack inside `toVdom` * Add changelog entry
1 parent 58473bd commit 3eb7c8d

File tree

4 files changed

+30
-3
lines changed

4 files changed

+30
-3
lines changed

packages/e2e-tests/plugins/interactive-blocks/tovdom-islands/render.php

+12
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,16 @@
6868
</div>
6969
</div>
7070
</div>
71+
72+
73+
74+
<div data-wp-interactive='{ "namespace": "tovdom-islands" }'>
75+
<div data-wp-interactive='{ "namespace": "something-new" }'></div>
76+
<div data-wp-show-mock="state.falseValue">
77+
<span data-testid="directive after different namespace">
78+
The directive above should keep the `tovdom-island` namespace,
79+
so this message should not be visible.
80+
</span>
81+
</div>
82+
</div>
7183
</div>

packages/interactivity/CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## Unreleased
44

5+
### Bug Fix
6+
7+
- Fix namespaces when there are nested interactive regions. ([#57029](https://github.com/WordPress/gutenberg/pull/57029))
8+
59
## 3.1.0 (2023-12-13)
610

711
## 3.0.0 (2023-11-29)

packages/interactivity/src/vdom.js

+7-3
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ import { directivePrefix as p } from './constants';
1010
const ignoreAttr = `data-${ p }-ignore`;
1111
const islandAttr = `data-${ p }-interactive`;
1212
const fullPrefix = `data-${ p }-`;
13-
let namespace = null;
13+
const namespaces = [];
14+
const currentNamespace = () => namespaces[ namespaces.length - 1 ] ?? null;
1415

1516
// Regular expression for directive parsing.
1617
const directiveParser = new RegExp(
@@ -79,7 +80,7 @@ export function toVdom( root ) {
7980
} catch ( e ) {}
8081
if ( n === islandAttr ) {
8182
island = true;
82-
namespace = value?.namespace ?? null;
83+
namespaces.push( value?.namespace ?? null );
8384
} else {
8485
directives.push( [ n, ns, value ] );
8586
}
@@ -107,7 +108,7 @@ export function toVdom( root ) {
107108
directiveParser.exec( name );
108109
if ( ! obj[ prefix ] ) obj[ prefix ] = [];
109110
obj[ prefix ].push( {
110-
namespace: ns ?? namespace,
111+
namespace: ns ?? currentNamespace(),
111112
value,
112113
suffix,
113114
} );
@@ -127,6 +128,9 @@ export function toVdom( root ) {
127128
treeWalker.parentNode();
128129
}
129130

131+
// Restore previous namespace.
132+
if ( island ) namespaces.pop();
133+
130134
return [ h( node.localName, props, children ) ];
131135
}
132136

test/e2e/specs/interactivity/tovdom-islands.spec.ts

+7
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,11 @@ test.describe( 'toVdom - islands', () => {
5555
);
5656
await expect( el ).toBeHidden();
5757
} );
58+
59+
test( 'islands should recover their namespace if an inner island has changed it', async ( {
60+
page,
61+
} ) => {
62+
const el = page.getByTestId( 'directive after different namespace' );
63+
await expect( el ).toBeHidden();
64+
} );
5865
} );

0 commit comments

Comments
 (0)