From 7eefc3323390c59bf6d4f923749526831572ef1a Mon Sep 17 00:00:00 2001 From: Dmitry Ivakhnenko Date: Mon, 4 Jul 2022 08:08:22 +0300 Subject: [PATCH] fix: skip empty text instance creation in jsx conditions (#1604) Co-authored-by: diegomura --- .changeset/mean-pots-allow.md | 5 ++ packages/renderer/src/renderer.js | 27 +++++++--- packages/renderer/tests/orphanTexts.test.js | 48 ++++++++++++++++++ ...-texts-test-js-renderer-boolean-1-snap.png | Bin 0 -> 3787 bytes ...s-test-js-renderer-empty-string-1-snap.png | Bin 0 -> 3787 bytes ...-texts-test-js-renderer-numbers-1-snap.png | Bin 0 -> 3787 bytes ...n-texts-test-js-renderer-string-1-snap.png | Bin 0 -> 3787 bytes ...han-texts-test-js-renderer-zero-1-snap.png | Bin 0 -> 3787 bytes 8 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 .changeset/mean-pots-allow.md create mode 100644 packages/renderer/tests/orphanTexts.test.js create mode 100644 packages/renderer/tests/snapshots/orphan-texts-test-js-renderer-boolean-1-snap.png create mode 100644 packages/renderer/tests/snapshots/orphan-texts-test-js-renderer-empty-string-1-snap.png create mode 100644 packages/renderer/tests/snapshots/orphan-texts-test-js-renderer-numbers-1-snap.png create mode 100644 packages/renderer/tests/snapshots/orphan-texts-test-js-renderer-string-1-snap.png create mode 100644 packages/renderer/tests/snapshots/orphan-texts-test-js-renderer-zero-1-snap.png diff --git a/.changeset/mean-pots-allow.md b/.changeset/mean-pots-allow.md new file mode 100644 index 000000000..027f21b80 --- /dev/null +++ b/.changeset/mean-pots-allow.md @@ -0,0 +1,5 @@ +--- +'@react-pdf/renderer': patch +--- + +fix: skip empty text instance creation in jsx conditions diff --git a/packages/renderer/src/renderer.js b/packages/renderer/src/renderer.js index ffb2973a3..5a69d3220 100644 --- a/packages/renderer/src/renderer.js +++ b/packages/renderer/src/renderer.js @@ -11,6 +11,23 @@ import propsEqual from './utils/propsEqual'; const emptyObject = {}; +const appendChild = (parentInstance, child) => { + const isParentText = parentInstance.type === 'TEXT'; + const isChildTextInstance = child.type === 'TEXT_INSTANCE'; + const isOrphanTextInstance = isChildTextInstance && !isParentText; + + // Ignore orphan text instances. + // Caused by cases such as <>{name && {name}} + if (isOrphanTextInstance) { + console.warn( + `Invalid '${child.value}' string child outside component`, + ); + return; + } + + parentInstance.children.push(child); +}; + const createRenderer = ({ onChange = () => {} }) => { return ReactFiberReconciler({ schedulePassiveEffects, @@ -23,9 +40,7 @@ const createRenderer = ({ onChange = () => {} }) => { warnsIfNotActing: false, - appendInitialChild(parentInstance, child) { - parentInstance.children.push(child); - }, + appendInitialChild: appendChild, createInstance(type, { style, children, ...props }) { return { @@ -83,15 +98,13 @@ const createRenderer = ({ onChange = () => {} }) => { useSyncScheduling: true, - appendChild(parentInstance, child) { - parentInstance.children.push(child); - }, + appendChild, appendChildToContainer(parentInstance, child) { if (parentInstance.type === 'ROOT') { parentInstance.document = child; } else { - parentInstance.children.push(child); + appendChild(parentInstance, child); } }, diff --git a/packages/renderer/tests/orphanTexts.test.js b/packages/renderer/tests/orphanTexts.test.js new file mode 100644 index 000000000..7969006ca --- /dev/null +++ b/packages/renderer/tests/orphanTexts.test.js @@ -0,0 +1,48 @@ +/* eslint-disable react/jsx-curly-brace-presence */ +import React from 'react'; +import { Text, Document, Page } from '@react-pdf/primitives'; +import renderToImage from './renderComponent'; + +const emptyString = ''; + +const mount = async children => { + const image = await renderToImage( + + {children} + , + ); + + return image; +}; + +describe('renderer', () => { + test('empty string', async () => { + const image = await mount(<>{emptyString && {emptyString}}); + + expect(image).toMatchImageSnapshot(); + }); + + test('string', async () => { + const image = await mount(<>{'text' || text}); + + expect(image).toMatchImageSnapshot(); + }); + + test('boolean', async () => { + const image = await mount(<>{true || text}); + + expect(image).toMatchImageSnapshot(); + }); + + test('zero', async () => { + const image = await mount(<>{0 && text}); + + expect(image).toMatchImageSnapshot(); + }); + + test('numbers', async () => { + const image = await mount(<>{10 || text}); + + expect(image).toMatchImageSnapshot(); + }); +}); diff --git a/packages/renderer/tests/snapshots/orphan-texts-test-js-renderer-boolean-1-snap.png b/packages/renderer/tests/snapshots/orphan-texts-test-js-renderer-boolean-1-snap.png new file mode 100644 index 0000000000000000000000000000000000000000..d3d4c83d6e6e057be7aef652eaab80d1fd55e2ae GIT binary patch literal 3787 zcmeAS@N?(olHy`uVBq!ia0y~yUhE&XXd+i|a0R@2r8!r7Vw<}ZNZ%Of=kbdpV8Fq#P6aSYnFdR62Mufp3VHwa+ zV^#)%8JY|Y2YeVASkkx{6byjYG|psV;22dh8ZM)WVKkGBmJFlC;b=86S~re12u2%9 pqpicyR`Y0AVYGjQqu+Rtt-+tGPlw}zGq88c;OXk;vd$@?2>@Xn0lxqM literal 0 HcmV?d00001 diff --git a/packages/renderer/tests/snapshots/orphan-texts-test-js-renderer-empty-string-1-snap.png b/packages/renderer/tests/snapshots/orphan-texts-test-js-renderer-empty-string-1-snap.png new file mode 100644 index 0000000000000000000000000000000000000000..d3d4c83d6e6e057be7aef652eaab80d1fd55e2ae GIT binary patch literal 3787 zcmeAS@N?(olHy`uVBq!ia0y~yUhE&XXd+i|a0R@2r8!r7Vw<}ZNZ%Of=kbdpV8Fq#P6aSYnFdR62Mufp3VHwa+ zV^#)%8JY|Y2YeVASkkx{6byjYG|psV;22dh8ZM)WVKkGBmJFlC;b=86S~re12u2%9 pqpicyR`Y0AVYGjQqu+Rtt-+tGPlw}zGq88c;OXk;vd$@?2>@Xn0lxqM literal 0 HcmV?d00001 diff --git a/packages/renderer/tests/snapshots/orphan-texts-test-js-renderer-numbers-1-snap.png b/packages/renderer/tests/snapshots/orphan-texts-test-js-renderer-numbers-1-snap.png new file mode 100644 index 0000000000000000000000000000000000000000..d3d4c83d6e6e057be7aef652eaab80d1fd55e2ae GIT binary patch literal 3787 zcmeAS@N?(olHy`uVBq!ia0y~yUhE&XXd+i|a0R@2r8!r7Vw<}ZNZ%Of=kbdpV8Fq#P6aSYnFdR62Mufp3VHwa+ zV^#)%8JY|Y2YeVASkkx{6byjYG|psV;22dh8ZM)WVKkGBmJFlC;b=86S~re12u2%9 pqpicyR`Y0AVYGjQqu+Rtt-+tGPlw}zGq88c;OXk;vd$@?2>@Xn0lxqM literal 0 HcmV?d00001 diff --git a/packages/renderer/tests/snapshots/orphan-texts-test-js-renderer-string-1-snap.png b/packages/renderer/tests/snapshots/orphan-texts-test-js-renderer-string-1-snap.png new file mode 100644 index 0000000000000000000000000000000000000000..d3d4c83d6e6e057be7aef652eaab80d1fd55e2ae GIT binary patch literal 3787 zcmeAS@N?(olHy`uVBq!ia0y~yUhE&XXd+i|a0R@2r8!r7Vw<}ZNZ%Of=kbdpV8Fq#P6aSYnFdR62Mufp3VHwa+ zV^#)%8JY|Y2YeVASkkx{6byjYG|psV;22dh8ZM)WVKkGBmJFlC;b=86S~re12u2%9 pqpicyR`Y0AVYGjQqu+Rtt-+tGPlw}zGq88c;OXk;vd$@?2>@Xn0lxqM literal 0 HcmV?d00001 diff --git a/packages/renderer/tests/snapshots/orphan-texts-test-js-renderer-zero-1-snap.png b/packages/renderer/tests/snapshots/orphan-texts-test-js-renderer-zero-1-snap.png new file mode 100644 index 0000000000000000000000000000000000000000..d3d4c83d6e6e057be7aef652eaab80d1fd55e2ae GIT binary patch literal 3787 zcmeAS@N?(olHy`uVBq!ia0y~yUhE&XXd+i|a0R@2r8!r7Vw<}ZNZ%Of=kbdpV8Fq#P6aSYnFdR62Mufp3VHwa+ zV^#)%8JY|Y2YeVASkkx{6byjYG|psV;22dh8ZM)WVKkGBmJFlC;b=86S~re12u2%9 pqpicyR`Y0AVYGjQqu+Rtt-+tGPlw}zGq88c;OXk;vd$@?2>@Xn0lxqM literal 0 HcmV?d00001