Skip to content

Conversation

pauldambra
Copy link
Contributor

@pauldambra pauldambra commented Jun 9, 2025

we had a customer whose SVGs are created with styling provided in CDATA tags
these ended up in replay with empty text content and would throw in the player, making the entire recording unplayable

we should be able to record them, but, for now, at least to not fail when we try to playback

reported here https://posthog.com/questions/error-failed-to-execute-create-cdata-section-on-document
and https://posthoghelp.zendesk.com/agent/tickets/31838

added when using https://anseki.github.io/leader-line/ (which is an archived repo)

that library adds

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" id="leader-line-defs"><style><![CDATA[.leader-line{position:absolute;overflow:visible!important;pointer-events:none!important;font-size:16px}#leader-line-defs{width:0;height:0;position:absolute;left:0;top:0}.leader-line-line-path{fill:none}.leader-line-mask-bg-rect{fill:#fff}.leader-line-caps-mask-anchor,.leader-line-caps-mask-marker-shape{fill:#000}.leader-line-caps-mask-anchor{stroke:#000}.leader-line-caps-mask-line,.leader-line-plugs-face{stroke:transparent}.leader-line-line-mask-shape{stroke:#fff}.leader-line-line-outline-mask-shape{stroke:#000}.leader-line-plug-mask-shape{fill:#fff;stroke:#000}.leader-line-plug-outline-mask-shape{fill:#000;stroke:#fff}.leader-line-areaAnchor{position:absolute;overflow:visible!important}]]></style><defs><circle id="leader-line-disc" cx="0" cy="0" r="5"></circle><rect id="leader-line-square" x="-5" y="-5" width="10" height="10"></rect><polygon id="leader-line-arrow1" points="-8,-8 8,0 -8,8 -5,0"></polygon><polygon id="leader-line-arrow2" points="-4,-8 4,0 -4,8 -7,5 -2,0 -7,-5"></polygon><polygon id="leader-line-arrow3" points="-4,-5 8,0 -4,5"></polygon><g id="leader-line-hand"><path style="fill: #fcfcfc" d="M9.19 11.14h4.75c1.38 0 2.49-1.11 2.49-2.49 0-.51-.15-.98-.41-1.37h1.3c1.38 0 2.49-1.11 2.49-2.49s-1.11-2.53-2.49-2.53h1.02c1.38 0 2.49-1.11 2.49-2.49s-1.11-2.49-2.49-2.49h14.96c1.37 0 2.49-1.11 2.49-2.49s-1.11-2.49-2.49-2.49H16.58C16-9.86 14.28-11.14 9.7-11.14c-4.79 0-6.55 3.42-7.87 4.73H-2.14v13.23h3.68C3.29 9.97 5.47 11.14 9.19 11.14L9.19 11.14Z"></path><path style="fill: black" d="M13.95 12c1.85 0 3.35-1.5 3.35-3.35 0-.17-.02-.34-.04-.51h.07c1.85 0 3.35-1.5 3.35-3.35 0-.79-.27-1.51-.72-2.08 1.03-.57 1.74-1.67 1.74-2.93 0-.59-.16-1.15-.43-1.63h12.04c1.85 0 3.35-1.5 3.35-3.35 0-1.85-1.5-3.35-3.35-3.35H17.2C16.26-10.93 13.91-12 9.7-12 5.36-12 3.22-9.4 1.94-7.84c0 0-.29.33-.5.57-.63 0-3.58 0-3.58 0C-2.61-7.27-3-6.88-3-6.41v13.23c0 .47.39.86.86.86 0 0 2.48 0 3.2 0C2.9 10.73 5.29 12 9.19 12L13.95 12ZM9.19 10.28c-3.46 0-5.33-1.05-6.9-3.87-.15-.27-.44-.44-.75-.44 0 0-1.81 0-2.82 0V-5.55c1.06 0 3.11 0 3.11 0 .25 0 .44-.06.61-.25l.83-.95c1.23-1.49 2.91-3.53 6.43-3.53 3.45 0 4.9.74 5.57 1.72h-4.3c-.48 0-.86.38-.86.86s.39.86.86.86h22.34c.9 0 1.63.73 1.63 1.63 0 .9-.73 1.63-1.63 1.63H15.83c-.48 0-.86.38-.86.86 0 .47.39.86.86.86h2.52c.9 0 1.63.73 1.63 1.63s-.73 1.63-1.63 1.63h-3.12c-.48 0-.86.38-.86.86 0 .47.39.86.86.86h2.11c.88 0 1.63.76 1.63 1.67 0 .9-.73 1.63-1.63 1.63h-3.2c-.48 0-.86.39-.86.86 0 .47.39.86.86.86h1.36c.05.16.09.34.09.51 0 .9-.73 1.63-1.63 1.63C13.95 10.28 9.19 10.28 9.19 10.28Z"></path></g><g id="leader-line-crosshair"><path d="M0-78.97c-43.54 0-78.97 35.43-78.97 78.97 0 43.54 35.43 78.97 78.97 78.97s78.97-35.43 78.97-78.97C78.97-43.54 43.55-78.97 0-78.97ZM76.51-1.21h-9.91v-9.11h-2.43v9.11h-11.45c-.64-28.12-23.38-50.86-51.5-51.5V-64.17h9.11V-66.6h-9.11v-9.91C42.46-75.86 75.86-42.45 76.51-1.21ZM-1.21-30.76h-9.11v2.43h9.11V-4.2c-1.44.42-2.57 1.54-2.98 2.98H-28.33v-9.11h-2.43v9.11H-50.29C-49.65-28-27.99-49.65-1.21-50.29V-30.76ZM-30.76 1.21v9.11h2.43v-9.11H-4.2c.42 1.44 1.54 2.57 2.98 2.98v24.13h-9.11v2.43h9.11v19.53C-27.99 49.65-49.65 28-50.29 1.21H-30.76ZM1.22 30.75h9.11v-2.43h-9.11V4.2c1.44-.42 2.56-1.54 2.98-2.98h24.13v9.11h2.43v-9.11h19.53C49.65 28 28 49.65 1.22 50.29V30.75ZM30.76-1.21v-9.11h-2.43v9.11H4.2c-.42-1.44-1.54-2.56-2.98-2.98V-28.33h9.11v-2.43h-9.11V-50.29C28-49.65 49.65-28 50.29-1.21H30.76ZM-1.21-76.51v9.91h-9.11v2.43h9.11v11.45c-28.12.64-50.86 23.38-51.5 51.5H-64.17v-9.11H-66.6v9.11h-9.91C-75.86-42.45-42.45-75.86-1.21-76.51ZM-76.51 1.21h9.91v9.11h2.43v-9.11h11.45c.64 28.12 23.38 50.86 51.5 51.5v11.45h-9.11v2.43h9.11v9.91C-42.45 75.86-75.86 42.45-76.51 1.21ZM1.22 76.51v-9.91h9.11v-2.43h-9.11v-11.45c28.12-.64 50.86-23.38 51.5-51.5h11.45v9.11h2.43v-9.11h9.91C75.86 42.45 42.45 75.86 1.22 76.51Z"></path><path d="M0 83.58-7.1 96 7.1 96Z"></path><path d="M0-83.58 7.1-96-7.1-96"></path><path d="M83.58 0 96 7.1 96-7.1Z"></path><path d="M-83.58 0-96-7.1-96 7.1Z"></path></g></defs></svg>

which gets recorded as

{
                        "type": 2,
                        "tagName": "svg",
                        "attributes": {
                          "xmlns": "http://www.w3.org/2000/svg",
                          "version": "1.1",
                          "id": "leader-line-defs"
                        },
                        "childNodes": [
                          {
                            "type": 2,
                            "tagName": "style",
                            "attributes": {},
                            "childNodes": [
                              {
                                "type": 4,
                                "textContent": "",
                                "id": 1463
                              }
                            ],
                            "isSVG": true,
                            "id": 1462
                          },
                          {
                            "type": 2,
                            "tagName": "defs",
                            "attributes": {},
                            "childNodes": [
                              {
                                "type": 2,
                                "tagName": "circle",
                                "attributes": {
                                  "id": "leader-line-disc",
                                  "cx": "0",
                                  "cy": "0",
                                  "r": "5"
                                },
                                "childNodes": [],
                                "isSVG": true,
                                "id": 1465
                              },
                              {
                                "type": 2,
                                "tagName": "rect",
                                "attributes": {
                                  "id": "leader-line-square",
                                  "x": "-5",
                                  "y": "-5",
                                  "width": "10",
                                  "height": "10"
                                },
                                "childNodes": [],
                                "isSVG": true,
                                "id": 1466
                              },
                              {
                                "type": 2,
                                "tagName": "polygon",
                                "attributes": {
                                  "id": "leader-line-arrow1",
                                  "points": "-8,-8 8,0 -8,8 -5,0"
                                },
                                "childNodes": [],
                                "isSVG": true,
                                "id": 1467
                              },
                              {
                                "type": 2,
                                "tagName": "polygon",
                                "attributes": {
                                  "id": "leader-line-arrow2",
                                  "points": "-4,-8 4,0 -4,8 -7,5 -2,0 -7,-5"
                                },
                                "childNodes": [],
                                "isSVG": true,
                                "id": 1468
                              },
                              {
                                "type": 2,
                                "tagName": "polygon",
                                "attributes": {
                                  "id": "leader-line-arrow3",
                                  "points": "-4,-5 8,0 -4,5"
                                },
                                "childNodes": [],
                                "isSVG": true,
                                "id": 1469
                              },
                              {
                                "type": 2,
                                "tagName": "g",
                                "attributes": {
                                  "id": "leader-line-hand"
                                },
                                "childNodes": [
                                  {
                                    "type": 2,
                                    "tagName": "path",
                                    "attributes": {
                                      "style": "fill: #fcfcfc",
                                      "d": "M9.19 11.14h4.75c1.38 0 2.49-1.11 2.49-2.49 0-.51-.15-.98-.41-1.37h1.3c1.38 0 2.49-1.11 2.49-2.49s-1.11-2.53-2.49-2.53h1.02c1.38 0 2.49-1.11 2.49-2.49s-1.11-2.49-2.49-2.49h14.96c1.37 0 2.49-1.11 2.49-2.49s-1.11-2.49-2.49-2.49H16.58C16-9.86 14.28-11.14 9.7-11.14c-4.79 0-6.55 3.42-7.87 4.73H-2.14v13.23h3.68C3.29 9.97 5.47 11.14 9.19 11.14L9.19 11.14Z"
                                    },
                                    "childNodes": [],
                                    "isSVG": true,
                                    "id": 1471
                                  },
                                  {
                                    "type": 2,
                                    "tagName": "path",
                                    "attributes": {
                                      "style": "fill: black",
                                      "d": "M13.95 12c1.85 0 3.35-1.5 3.35-3.35 0-.17-.02-.34-.04-.51h.07c1.85 0 3.35-1.5 3.35-3.35 0-.79-.27-1.51-.72-2.08 1.03-.57 1.74-1.67 1.74-2.93 0-.59-.16-1.15-.43-1.63h12.04c1.85 0 3.35-1.5 3.35-3.35 0-1.85-1.5-3.35-3.35-3.35H17.2C16.26-10.93 13.91-12 9.7-12 5.36-12 3.22-9.4 1.94-7.84c0 0-.29.33-.5.57-.63 0-3.58 0-3.58 0C-2.61-7.27-3-6.88-3-6.41v13.23c0 .47.39.86.86.86 0 0 2.48 0 3.2 0C2.9 10.73 5.29 12 9.19 12L13.95 12ZM9.19 10.28c-3.46 0-5.33-1.05-6.9-3.87-.15-.27-.44-.44-.75-.44 0 0-1.81 0-2.82 0V-5.55c1.06 0 3.11 0 3.11 0 .25 0 .44-.06.61-.25l.83-.95c1.23-1.49 2.91-3.53 6.43-3.53 3.45 0 4.9.74 5.57 1.72h-4.3c-.48 0-.86.38-.86.86s.39.86.86.86h22.34c.9 0 1.63.73 1.63 1.63 0 .9-.73 1.63-1.63 1.63H15.83c-.48 0-.86.38-.86.86 0 .47.39.86.86.86h2.52c.9 0 1.63.73 1.63 1.63s-.73 1.63-1.63 1.63h-3.12c-.48 0-.86.38-.86.86 0 .47.39.86.86.86h2.11c.88 0 1.63.76 1.63 1.67 0 .9-.73 1.63-1.63 1.63h-3.2c-.48 0-.86.39-.86.86 0 .47.39.86.86.86h1.36c.05.16.09.34.09.51 0 .9-.73 1.63-1.63 1.63C13.95 10.28 9.19 10.28 9.19 10.28Z"
                                    },
                                    "childNodes": [],
                                    "isSVG": true,
                                    "id": 1472
                                  }
                                ],
                                "isSVG": true,
                                "id": 1470
                              },
                              {
                                "type": 2,
                                "tagName": "g",
                                "attributes": {
                                  "id": "leader-line-crosshair"
                                },
                                "childNodes": [
                                  {
                                    "type": 2,
                                    "tagName": "path",
                                    "attributes": {
                                      "d": "M0-78.97c-43.54 0-78.97 35.43-78.97 78.97 0 43.54 35.43 78.97 78.97 78.97s78.97-35.43 78.97-78.97C78.97-43.54 43.55-78.97 0-78.97ZM76.51-1.21h-9.91v-9.11h-2.43v9.11h-11.45c-.64-28.12-23.38-50.86-51.5-51.5V-64.17h9.11V-66.6h-9.11v-9.91C42.46-75.86 75.86-42.45 76.51-1.21ZM-1.21-30.76h-9.11v2.43h9.11V-4.2c-1.44.42-2.57 1.54-2.98 2.98H-28.33v-9.11h-2.43v9.11H-50.29C-49.65-28-27.99-49.65-1.21-50.29V-30.76ZM-30.76 1.21v9.11h2.43v-9.11H-4.2c.42 1.44 1.54 2.57 2.98 2.98v24.13h-9.11v2.43h9.11v19.53C-27.99 49.65-49.65 28-50.29 1.21H-30.76ZM1.22 30.75h9.11v-2.43h-9.11V4.2c1.44-.42 2.56-1.54 2.98-2.98h24.13v9.11h2.43v-9.11h19.53C49.65 28 28 49.65 1.22 50.29V30.75ZM30.76-1.21v-9.11h-2.43v9.11H4.2c-.42-1.44-1.54-2.56-2.98-2.98V-28.33h9.11v-2.43h-9.11V-50.29C28-49.65 49.65-28 50.29-1.21H30.76ZM-1.21-76.51v9.91h-9.11v2.43h9.11v11.45c-28.12.64-50.86 23.38-51.5 51.5H-64.17v-9.11H-66.6v9.11h-9.91C-75.86-42.45-42.45-75.86-1.21-76.51ZM-76.51 1.21h9.91v9.11h2.43v-9.11h11.45c.64 28.12 23.38 50.86 51.5 51.5v11.45h-9.11v2.43h9.11v9.91C-42.45 75.86-75.86 42.45-76.51 1.21ZM1.22 76.51v-9.91h9.11v-2.43h-9.11v-11.45c28.12-.64 50.86-23.38 51.5-51.5h11.45v9.11h2.43v-9.11h9.91C75.86 42.45 42.45 75.86 1.22 76.51Z"
                                    },
                                    "childNodes": [],
                                    "isSVG": true,
                                    "id": 1474
                                  },
                                  {
                                    "type": 2,
                                    "tagName": "path",
                                    "attributes": {
                                      "d": "M0 83.58-7.1 96 7.1 96Z"
                                    },
                                    "childNodes": [],
                                    "isSVG": true,
                                    "id": 1475
                                  },
                                  {
                                    "type": 2,
                                    "tagName": "path",
                                    "attributes": {
                                      "d": "M0-83.58 7.1-96-7.1-96"
                                    },
                                    "childNodes": [],
                                    "isSVG": true,
                                    "id": 1476
                                  },
                                  {
                                    "type": 2,
                                    "tagName": "path",
                                    "attributes": {
                                      "d": "M83.58 0 96 7.1 96-7.1Z"
                                    },
                                    "childNodes": [],
                                    "isSVG": true,
                                    "id": 1477
                                  },
                                  {
                                    "type": 2,
                                    "tagName": "path",
                                    "attributes": {
                                      "d": "M-83.58 0-96-7.1-96 7.1Z"
                                    },
                                    "childNodes": [],
                                    "isSVG": true,
                                    "id": 1478
                                  }
                                ],
                                "isSVG": true,
                                "id": 1473
                              }
                            ],
                            "isSVG": true,
                            "id": 1464
                          }
                        ],
                        "isSVG": true,
                        "id": 1461
                      },
                      ```

@Copilot Copilot AI review requested due to automatic review settings June 9, 2025 19:28
Copy link

changeset-bot bot commented Jun 9, 2025

⚠️ No Changeset found

Latest commit: 5e04833

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR prevents playback failures caused by empty CDATA sections by returning null instead of creating a CDATA node when the text content is empty.

  • Avoid throwing errors on empty CDATA
  • Add a conditional check to bypass CDATA creation for empty content
Comments suppressed due to low confidence (1)

packages/rrweb-snapshot/src/rebuild.ts:435

  • Ensure that returning null for empty CDATA is safely handled by the calling code. Consider adding a comment or test to verify that null values are appropriately processed to prevent unintended behavior downstream.
if (n.textContent.trim() === '') {

@eoghanmurray
Copy link
Contributor

Do you mean that the content didn't get recorded at all?
Could you provide the for the source so we can create a test case?

return doc.createTextNode(n.textContent);
case NodeType.CDATA:
if (n.textContent.trim() === '') {
return null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest warning here before return

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's no user action though... it's just skipping invalid data

we inject a logger to rrweb playback that swallows logs because it logs so much to the console we've seen it freeze the browser 🙈

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but... if you manage to get a NodeType of CDATA into a recording that has empty text content, the player will throw and you can't playback at all.

so this is IMHO reasonable validation even if it's neater to fix at recording time

Copy link
Contributor

@eoghanmurray eoghanmurray Sep 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's no user action though

The point for me would be to alert a developer who is wondering why the replay doesn't look like the original website

@pauldambra
Copy link
Contributor Author

pauldambra commented Jun 14, 2025 via email

@pauldambra
Copy link
Contributor Author

damn i didn't link our support ticket here either 🫠 PostHog/posthog-rrweb#70

@eoghanmurray
Copy link
Contributor

I tried creating a minimum test case using an XHTML document, but it looks like we would need to do a lot of work to even support xhtml recording. Let me know if anyone is interested in seeing that, but I'd say that's a dead technology.
I'll try again to create an embedded SVG test case shortly.

@eoghanmurray
Copy link
Contributor

Fixed more thoroughly in #1702 - I believe that the <style> element contents would not have been restored at all with this PR alone; also it wasn't the empty string contents that was causing the problem, but the call to createCDATASection was problemmatic as it would never succeed unless we switch to supporting XHTML rebuilding (which nobody wants)

@pauldambra
Copy link
Contributor Author

great... all I was trying to do here was not throw 👍

@pauldambra pauldambra closed this Sep 14, 2025
@eoghanmurray
Copy link
Contributor

Can you review that other commit? You might be able to approve now if we've set up permissions correctly

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants