Skip to content

Conversation

@sethfowler-datadog
Copy link
Contributor

Motivation

The current DOM serialization algorithm encodes two specific DOM attributes as boolean values:

  • The checked attribute found in <input type="checkbox"> and <input type="radio">.
  • The selected attribute found in <option selected>.

I'd like to avoid this special case handling in the new DOM serialization algorithm. Instead, I'd like to encode these attributes as strings, just like all other attributes. Since these are boolean attributes, the standard string encoding for the value is:

  • { selected: '' } (the empty string) for true. (e.g. <option selected>)
  • {} (no value recorded) for false. (e.g. <option>)

This is exactly the transformation that the session replay player already applies to boolean-valued attributes, so the result will be the same at playback time. Indeed, handling things this way is less work on both ends! The existing player will just work with this approach.

I'd like to take this opportunity to very slightly change the behavior of <option selected>, resolving an issue that was discovered when building the test suite added in #3994. Currently, there's a very particular circumstance where we do the wrong thing. The problematic situation is when an <option> element is masked, and:

  • It has a selected DOM attribute.
  • The value of of its selected property is false. (Because the user has selected another <option> since page load, perhaps.)

In this situation, we will add the selected DOM attribute to the element's list of attributes. Then, we will see that the selected property is false. We won't update the element's list of attributes, intending to omit the selected property, but because the selected property from the DOM is already there, we'll end up serializing it and including it in the element's attribute list in the recording. This is wrong both from a privacy perspective (we shouldn't capture this attribute on masked elements) and because it could cause us to show the wrong <option> as selected at replay time.

The fix is always delete selected from the element's list of attributes if the selected property is false. This aligns with what we do for checked, so in addition to fixing this bug, it ends up simplifying the tests and reducing the number of different attribute serialization behaviors we need to reason about.

Changes

Following the plan above, this PR:

  • Changes our encoding for checked and selected. Now, the attribute value is the empty string when these attributes are logically true, and the attributes are not recorded when they are logically false.
  • Adjusts the code for each so they follow a consistent pattern: if the element is not masked and the attribute is logically true, it's added to the attribute list; otherwise, it's deleted. This fixes the selected bug described above.
  • Narrows the types for serializeDOMAttributes() and related functions, since they can no longer produce boolean values.
  • Updates the tests to capture the new behavior.

Test instructions

It's enough to visit a page with an HTML <select> dropdown, a set of checkbox inputs, or a set of radio button inputs, and look at the generated session replay using the browser SDK extension. We should continue to show the correct checked or selected item after the change.

Checklist

  • Tested locally
  • Tested on staging
  • Added unit tests for this change.
  • Added e2e/integration tests for this change.

@sethfowler-datadog sethfowler-datadog requested a review from a team as a code owner December 4, 2025 18:12
Copy link
Contributor

@BeltranBulbarellaDD BeltranBulbarellaDD left a comment

Choose a reason for hiding this comment

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

LGTM and it works as expected!

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.

3 participants