♻️ [PANA-5947] Convert Change records to V1 records using a VDOM #4165
+4,236
−423
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Motivation
Change records are a new, experimental data format for session replay data that's designed to record the same information in a more compact, more compressible form.
We've already landed support for recording full snapshots as Change records behind an experiment flag. The next step is to introduce support for incremental snapshots, as well. This requires making improvements to a number of different aspects of the recording code. This PR is the third in a series that will work toward the goal of supporting incremental snapshots; for the previous PR, see #4164.
Changes
The existing code compares Change records to V1 records (the old format) by first converting the Change records to V1 records. That code lives in
changeConversions.specHelper.ts. It supports converting full snapshot records from the Change format to the V1 format, but unfortunately, it uses a simple approach that's quite hard to extend to support incremental snapshots.The challenge is that the V1 format includes lots of unnecessary information in its full snapshots -- for example, when a node is removed from the DOM, the V1 data format includes the parent id of the removed node, even though replay does not need this information. Similarly, when a new node is added to the document, the Change format does not necessarily include its parent id, since just the id of the next sibling is enough, but the V1 format always includes both. This means that, if you just look at a Change record representing an incremental snapshot, there is simply not enough information to construct the equivalent V1 incremental snapshot record.
The solution is to replay each Change record as part of the conversion process and construct a VDOM. This VDOM can then be "rendered" to generate the equivalent V1 record at the current point in time. In particular, this PR adds the following files:
ChangeConverterreplaces the code inchangeConversions.specHelper.ts. It's a stateful object now, rather than a function; it owns a VDOM, and replays a series of Change records against that VDOM, generating an equivalent V1 record each time.VDocument,VNode, andVStyleSheetimplement the VDOM. They expose APIs which are somewhat similar to the real DOM. Beyond keeping track of what the virtual document looks like, these objects also make lots of assertions internally, which helps verify that the Change record we're playing back is constructed correctly.StringTableis directly lifted fromchangeConversions.specHelper.ts; it keeps track of the string table which the series of Change records builds up.MutationLogis used to track the mutations made in each Change record -- the set of nodes added and removed, changed attributes, and changed text -- so that we can generate the corresponding V1 record. TheMutationLogis automatically populated when the VDOM is changed.NodeIdRemapperandRenderOptionsare helper types.RenderOptionslets you customize the rendered V1 record output generated byVDocument#render().NodeIdRemapperis used to implement one of those customizations; it lets you take the node ids generated by the V1 serialization algorithm and swap them in during rendering, replacing the node ids assigned by the Change serialization algorithm. This makes it much easier to compare the results.There are lots of tests. Beyond the new tests added in the PR, the change to
serialization.specHelper.tsmake us useChangeConverterinstead of the old code inchangeConversions.specHelper.ts; in turn, this means that a ton of serialization unit tests are also running throughChangeConverternow.With these changes, we'll have the majority of testing infrastructure we'll need in the PR that actually adds support for incremental snapshot
Changerecords. Unbelievably, given how huge this PR is, there's actually a little bit more that we'll add in the next few PRs, but this is the vast majority of the new testing code.Checklist