From ba0a3320c878c36a9a3cc27660ca0b9b3d89facd Mon Sep 17 00:00:00 2001 From: Ella <4710635+ellatrix@users.noreply.github.com> Date: Mon, 10 Jul 2023 21:05:46 +0200 Subject: [PATCH] Iframe: avoid asset parsing & fix script localisation (#52405) * Iframe: avoid asset parsing & fix script localisation * Add e2e test for script localisation --- .../src/components/iframe/index.js | 63 +++++-------------- .../plugins/iframed-enqueue-block-assets.php | 13 ++++ .../iframed-enqueue-block-assets/script.js | 3 + .../iframed-equeue-block-assets.test.js | 7 +++ 4 files changed, 39 insertions(+), 47 deletions(-) create mode 100644 packages/e2e-tests/plugins/iframed-enqueue-block-assets/script.js diff --git a/packages/block-editor/src/components/iframe/index.js b/packages/block-editor/src/components/iframe/index.js index 4d4521eae3581..afe403af0aa39 100644 --- a/packages/block-editor/src/components/iframe/index.js +++ b/packages/block-editor/src/components/iframe/index.js @@ -11,7 +11,6 @@ import { createPortal, forwardRef, useMemo, - useReducer, useEffect, } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; @@ -78,29 +77,6 @@ function bubbleEvents( doc ) { } } -function useParsedAssets( html ) { - return useMemo( () => { - const doc = document.implementation.createHTMLDocument( '' ); - doc.body.innerHTML = html; - return Array.from( doc.body.children ); - }, [ html ] ); -} - -async function loadScript( head, { id, src } ) { - return new Promise( ( resolve, reject ) => { - const script = head.ownerDocument.createElement( 'script' ); - script.id = id; - if ( src ) { - script.src = src; - script.onload = () => resolve(); - script.onerror = () => reject(); - } else { - resolve(); - } - head.appendChild( script ); - } ); -} - function Iframe( { contentRef, children, @@ -112,21 +88,22 @@ function Iframe( { forwardedRef: ref, ...props } ) { - const assets = useSelect( + const { styles = '', scripts = '' } = useSelect( ( select ) => select( blockEditorStore ).getSettings().__unstableResolvedAssets, [] ); - const [ , forceRender ] = useReducer( () => ( {} ) ); const [ iframeDocument, setIframeDocument ] = useState(); const [ bodyClasses, setBodyClasses ] = useState( [] ); const compatStyles = useCompatibilityStyles(); - const scripts = useParsedAssets( assets?.scripts ); const clearerRef = useBlockSelectionClearer(); const [ before, writingFlowRef, after ] = useWritingFlow(); const [ contentResizeListener, { height: contentHeight } ] = useResizeObserver(); const setRef = useRefEffect( ( node ) => { + node._load = () => { + setIframeDocument( node.contentDocument ); + }; let iFrameDocument; // Prevent the default browser action for files dropped outside of dropzones. function preventFileDropDefault( event ) { @@ -138,7 +115,6 @@ function Iframe( { iFrameDocument = contentDocument; bubbleEvents( contentDocument ); - setIframeDocument( contentDocument ); clearerRef( documentElement ); // Ideally ALL classes that are added through get_body_class should @@ -154,7 +130,6 @@ function Iframe( { ); contentDocument.dir = ownerDocument.dir; - documentElement.removeChild( contentDocument.body ); for ( const compatStyle of compatStyles ) { if ( contentDocument.getElementById( compatStyle.id ) ) { @@ -199,35 +174,29 @@ function Iframe( { }; }, [] ); - const headRef = useRefEffect( ( element ) => { - scripts - .reduce( - ( promise, script ) => - promise.then( () => loadScript( element, script ) ), - Promise.resolve() - ) - .finally( () => { - // When script are loaded, re-render blocks to allow them - // to initialise. - forceRender(); - } ); - }, [] ); const disabledRef = useDisabled( { isDisabled: ! readonly } ); const bodyRef = useMergeRefs( [ contentRef, clearerRef, writingFlowRef, disabledRef, - headRef, ] ); // Correct doctype is required to enable rendering in standards // mode. Also preload the styles to avoid a flash of unstyled // content. - const html = - '' + - '' + - ( assets?.styles ?? '' ); + const html = ` + + + + + ${ styles } + ${ scripts } + + + + +`; const [ src, cleanup ] = useMemo( () => { const _src = URL.createObjectURL( diff --git a/packages/e2e-tests/plugins/iframed-enqueue-block-assets.php b/packages/e2e-tests/plugins/iframed-enqueue-block-assets.php index ad98354dd45dc..3f24a6e25cfcb 100644 --- a/packages/e2e-tests/plugins/iframed-enqueue-block-assets.php +++ b/packages/e2e-tests/plugins/iframed-enqueue-block-assets.php @@ -17,5 +17,18 @@ static function() { filemtime( plugin_dir_path( __FILE__ ) . 'iframed-enqueue-block-assets/style.css' ) ); wp_add_inline_style( 'iframed-enqueue-block-assets', 'body{padding:20px!important}' ); + wp_enqueue_script( + 'iframed-enqueue-block-assets-script', + plugin_dir_url( __FILE__ ) . 'iframed-enqueue-block-assets/script.js', + array(), + filemtime( plugin_dir_path( __FILE__ ) . 'iframed-enqueue-block-assets/script.js' ) + ); + wp_localize_script( + 'iframed-enqueue-block-assets-script', + 'iframedEnqueueBlockAssetsL10n', + array( + 'test' => 'Iframed Enqueue Block Assets!', + ) + ); } ); diff --git a/packages/e2e-tests/plugins/iframed-enqueue-block-assets/script.js b/packages/e2e-tests/plugins/iframed-enqueue-block-assets/script.js new file mode 100644 index 0000000000000..f0eddd65c70eb --- /dev/null +++ b/packages/e2e-tests/plugins/iframed-enqueue-block-assets/script.js @@ -0,0 +1,3 @@ +window.addEventListener( 'load', () => { + document.body.dataset.iframedEnqueueBlockAssetsL10n = window.iframedEnqueueBlockAssetsL10n.test; +} ); diff --git a/packages/e2e-tests/specs/editor/plugins/iframed-equeue-block-assets.test.js b/packages/e2e-tests/specs/editor/plugins/iframed-equeue-block-assets.test.js index c1bd26fe1c761..c29af593abb12 100644 --- a/packages/e2e-tests/specs/editor/plugins/iframed-equeue-block-assets.test.js +++ b/packages/e2e-tests/specs/editor/plugins/iframed-equeue-block-assets.test.js @@ -32,6 +32,7 @@ describe( 'iframed inline styles', () => { } ); it( 'should load styles added through enqueue_block_assets', async () => { + await page.waitForSelector( 'iframe[name="editor-canvas"]' ); // Check stylesheet. expect( await getComputedStyle( canvas(), 'body', 'background-color' ) @@ -40,5 +41,11 @@ describe( 'iframed inline styles', () => { expect( await getComputedStyle( canvas(), 'body', 'padding' ) ).toBe( '20px' ); + + expect( + await canvas().evaluate( () => ( { ...document.body.dataset } ) ) + ).toEqual( { + iframedEnqueueBlockAssetsL10n: 'Iframed Enqueue Block Assets!', + } ); } ); } );