From 865c0b5fdcaf474dc11749884b1e9b2bcc454001 Mon Sep 17 00:00:00 2001 From: Justin Halsall Date: Fri, 13 Aug 2021 18:31:43 +0200 Subject: [PATCH 1/4] fix typo --- docs/observer.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/observer.md b/docs/observer.md index 20417b42c6..aed6cf4ee2 100644 --- a/docs/observer.md +++ b/docs/observer.md @@ -1,4 +1,5 @@ # Incremental snapshots + After completing a full snapshot, we need to record events that change the state. Right now, rrweb records the following events (we will expand upon this): @@ -18,9 +19,11 @@ Right now, rrweb records the following events (we will expand upon this): - Input ## Mutation Observer + Since we don't execute any JavaScript during replay, we instead need to record all changes scripts make to the document. Consider this example: + > User clicks a button. A dropdown menu appears. User selects the first item. The dropdown menu disappears. During replay, the dropdown menu does not automatically appear after the "click button" is executed, because the original JavaScript is not part of the recording. Thus, we need to record the creation of the dropdown menu DOM nodes, the selection of the first item, and subsequent deletion of the dropdown menu DOM nodes. This is the most difficult part. @@ -33,9 +36,10 @@ The first thing to understand is that MutationObserver uses a **Bulk Asynchronou This mechanism is not problematic for normal use, because we do not only have the mutation record, but we can also directly access the DOM object of the mutated node as well as any parent, child and sibling nodes. -However in rrweb, since we have a serialization process, we need more sophisticated soluation to be able to deal with various scenarios. +However in rrweb, since we have a serialization process, we need more sophisticated solution to be able to deal with various scenarios. ### Add node + For example, the following two operations generate the same DOM structure, but produce a different set of mutation records: ``` @@ -63,32 +67,40 @@ We already introduced in the [serialization design document](./serialization.md) As you can see, since we have delayed serialization of the newly added nodes, all mutation records also need to be processed first, and only then the new nodes can be de-duplicated without causing trouble. ### Remove node + When processing mutation records, we may encounter a removed node that has not yet been serialized. That indicates that it is a newly added node, and the "add node" mutation record is also somewhere in the mutation records we received. We label these nodes as "dropped nodes". There are two cases we need to handle here: + 1. Since the node was removed already, there is no need to replay it, and thus we remove it from the newly added node pool. 2. This also applies to descendants of the dropped node, thus when processing newly added nodes we need to check if it has a dropped node as an ancestor. ### Attribute change + Although MutationObserver is an asynchronous batch callback, we can still assume that the time interval between mutations occurring in a callback is extremely short, so we can optimize the size of the incremental snapshot by overwriting some data when recording the DOM property changes. For example, resizing a `