From b025b5e6688d8cbf4947accb745b2be64cfeb185 Mon Sep 17 00:00:00 2001 From: Josh Loehr Date: Tue, 19 Sep 2023 18:32:14 -0700 Subject: [PATCH] fix: prevent duplicate child cloning of iframe content --- src/clone-node.ts | 14 ++++++-------- test/resources/iframe/embed.html | 5 +++++ test/resources/iframe/image | 1 + test/resources/iframe/node.html | 6 ++++++ test/spec/iframe.spec.ts | 21 +++++++++++++++++++++ 5 files changed, 39 insertions(+), 8 deletions(-) create mode 100644 test/resources/iframe/embed.html create mode 100644 test/resources/iframe/image create mode 100644 test/resources/iframe/node.html create mode 100644 test/spec/iframe.spec.ts diff --git a/src/clone-node.ts b/src/clone-node.ts index 500ce332..5b57e3e7 100644 --- a/src/clone-node.ts +++ b/src/clone-node.ts @@ -76,11 +76,6 @@ async function cloneChildren( if (isSlotElement(nativeNode) && nativeNode.assignedNodes) { children = toArray(nativeNode.assignedNodes()) - } else if ( - isInstanceOfElement(nativeNode, HTMLIFrameElement) && - nativeNode.contentDocument?.body - ) { - children = toArray(nativeNode.contentDocument.body.childNodes) } else { children = toArray((nativeNode.shadowRoot ?? nativeNode).childNodes) } @@ -133,11 +128,11 @@ function cloneCSSStyle(nativeNode: T, clonedNode: T) { ) { value = 'block' } - + if (name === 'd' && clonedNode.getAttribute('d')) { value = `path(${clonedNode.getAttribute('d')})` } - + targetStyle.setProperty( name, value, @@ -171,7 +166,10 @@ function cloneSelectValue(nativeNode: T, clonedNode: T) { } function decorate(nativeNode: T, clonedNode: T): T { - if (isInstanceOfElement(clonedNode, Element)) { + if ( + isInstanceOfElement(clonedNode, Element) && + !isInstanceOfElement(nativeNode, HTMLIFrameElement) + ) { cloneCSSStyle(nativeNode, clonedNode) clonePseudoElements(nativeNode, clonedNode) cloneInputValue(nativeNode, clonedNode) diff --git a/test/resources/iframe/embed.html b/test/resources/iframe/embed.html new file mode 100644 index 00000000..62844377 --- /dev/null +++ b/test/resources/iframe/embed.html @@ -0,0 +1,5 @@ + + +
Embeddable content
+ + diff --git a/test/resources/iframe/image b/test/resources/iframe/image new file mode 100644 index 00000000..7d48dd69 --- /dev/null +++ b/test/resources/iframe/image @@ -0,0 +1 @@ +data:image/png;base64,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 \ No newline at end of file diff --git a/test/resources/iframe/node.html b/test/resources/iframe/node.html new file mode 100644 index 00000000..e8974be2 --- /dev/null +++ b/test/resources/iframe/node.html @@ -0,0 +1,6 @@ + diff --git a/test/spec/iframe.spec.ts b/test/spec/iframe.spec.ts new file mode 100644 index 00000000..1299b73a --- /dev/null +++ b/test/spec/iframe.spec.ts @@ -0,0 +1,21 @@ +/* eslint-disable promise/no-callback-in-promise */ + +import './setup' +import { bootstrap, renderAndCheck } from './helper' +import { delay } from '../../src/util' + +describe('work with iframe element', () => { + it('should render iframe element', (done) => { + bootstrap('iframe/node.html', undefined, 'iframe/image') + .then(delay(100)) + .then((node) => { + const iframe = node.querySelector('#iframe') as HTMLIFrameElement + return renderAndCheck(node, { + width: parseInt(iframe.width, 10), + height: parseInt(iframe.height, 10), + }) + }) + .then(done) + .catch(done) + }) +})