From 77a9c2667f9d5f2764e2ce55fde851e5a142d7c5 Mon Sep 17 00:00:00 2001 From: David Arenas Date: Fri, 15 Dec 2023 11:24:41 +0100 Subject: [PATCH] Interactivity API: fix namespaces in nested interactive regions (#57029) * Add failing test * Turn namespaces into a stack inside `toVdom` * Add changelog entry --- .../interactive-blocks/tovdom-islands/render.php | 12 ++++++++++++ packages/interactivity/CHANGELOG.md | 4 ++++ packages/interactivity/src/vdom.js | 10 +++++++--- test/e2e/specs/interactivity/tovdom-islands.spec.ts | 7 +++++++ 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/packages/e2e-tests/plugins/interactive-blocks/tovdom-islands/render.php b/packages/e2e-tests/plugins/interactive-blocks/tovdom-islands/render.php index 7b1bc6513977b..1f53ca1331a37 100644 --- a/packages/e2e-tests/plugins/interactive-blocks/tovdom-islands/render.php +++ b/packages/e2e-tests/plugins/interactive-blocks/tovdom-islands/render.php @@ -68,4 +68,16 @@ + + + +
+
+
+ + The directive above should keep the `tovdom-island` namespace, + so this message should not be visible. + +
+
diff --git a/packages/interactivity/CHANGELOG.md b/packages/interactivity/CHANGELOG.md index ce90835dda23d..8c03cfc314efe 100644 --- a/packages/interactivity/CHANGELOG.md +++ b/packages/interactivity/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Bug Fix + +- Fix namespaces when there are nested interactive regions. ([#57029](https://github.com/WordPress/gutenberg/pull/57029)) + ## 3.1.0 (2023-12-13) ## 3.0.0 (2023-11-29) diff --git a/packages/interactivity/src/vdom.js b/packages/interactivity/src/vdom.js index b1342ac271a8e..860a3149e6ffd 100644 --- a/packages/interactivity/src/vdom.js +++ b/packages/interactivity/src/vdom.js @@ -10,7 +10,8 @@ import { directivePrefix as p } from './constants'; const ignoreAttr = `data-${ p }-ignore`; const islandAttr = `data-${ p }-interactive`; const fullPrefix = `data-${ p }-`; -let namespace = null; +const namespaces = []; +const currentNamespace = () => namespaces[ namespaces.length - 1 ] ?? null; // Regular expression for directive parsing. const directiveParser = new RegExp( @@ -79,7 +80,7 @@ export function toVdom( root ) { } catch ( e ) {} if ( n === islandAttr ) { island = true; - namespace = value?.namespace ?? null; + namespaces.push( value?.namespace ?? null ); } else { directives.push( [ n, ns, value ] ); } @@ -107,7 +108,7 @@ export function toVdom( root ) { directiveParser.exec( name ); if ( ! obj[ prefix ] ) obj[ prefix ] = []; obj[ prefix ].push( { - namespace: ns ?? namespace, + namespace: ns ?? currentNamespace(), value, suffix, } ); @@ -127,6 +128,9 @@ export function toVdom( root ) { treeWalker.parentNode(); } + // Restore previous namespace. + if ( island ) namespaces.pop(); + return [ h( node.localName, props, children ) ]; } diff --git a/test/e2e/specs/interactivity/tovdom-islands.spec.ts b/test/e2e/specs/interactivity/tovdom-islands.spec.ts index fcc7c6081077a..257b0a0fc94b8 100644 --- a/test/e2e/specs/interactivity/tovdom-islands.spec.ts +++ b/test/e2e/specs/interactivity/tovdom-islands.spec.ts @@ -55,4 +55,11 @@ test.describe( 'toVdom - islands', () => { ); await expect( el ).toBeHidden(); } ); + + test( 'islands should recover their namespace if an inner island has changed it', async ( { + page, + } ) => { + const el = page.getByTestId( 'directive after different namespace' ); + await expect( el ).toBeHidden(); + } ); } );