Commit Graph

46 Commits

Author SHA1 Message Date
Eoghan Murray
d57cae3d51 Move mutation processing into it's own class (#223)
* Move mutation processing into it's own object.

This should stand on it's own as a refactor, but is intended as a basis
for exposing the new MutationBuffer object to further outside control e.g.
to 'mute' or batch up mutation emission when the page becomes inactive
from a https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API
point of view

* The `processMutations` function needed to be bound to the `mutationBuffer` object, as otherwise `this` referred to the `MutationObserver` object itself

* Neglected to add this output of `npm run typings`

* Get around the binding problem by using Arrow function expressions

* Prettier formatting
2026-04-01 12:00:00 +08:00
Rifaudeen
4bb0bdb180 added custom-event emitter to replayer (#219) 2026-04-01 12:00:00 +08:00
yz-yu
43be602816 mutation observer v2 (#206)
There are some long-term issues in rrweb's mutation observer.

A scenario cause problem:
A list of DOM node: n1, n2, n3, n4, n5
Steps of modifying the nodes:
  1. remove n1, n2, n3, n4 sequentially
  2. append n4, n3, n2, n1 after n5 sequentially
Then we got the added node data like this:
  (id: n4, prev: null, next: n3  )
  (id: n3, prev: n4,   next: n2  )
  (id: n2, prev: n3,   next: n1  )
  (id: n1, prev: n2,   next: null)
The problem comes when we try to replay the first add node datum.
Since its prev node is null, we rely on its next sibling n3. But
n3 was not present at this moment, and in previous code, we fallback
to append n4 to the last of its parent node.

The solution is to defer the append of elements that missing
siblings. But it is also hard to tell which node is the first one
that needs to be appended.

Take a step back and rethink the design of the mutation observer,
we've found there are two implementations make things complicated.
1. We set the id to -1 when we seeing some nodes are not serialized yet.
2. We record both previous sibling and next sibling to determine the
position of the node.
But we can do better!
First, we can put nodes with un-serialized siblings
to a queue, and try to add it again later. Then we can just record the next
sibling as 'the single truth' so we can be sure which node is the last
one of its parent.

This patch has implemented the new observer strategy. Data recorded with
the new observer should no longer have any node with id -1. But for
compatibility consideration, we still keep some replayer code that helps
solve legacy data.
2026-04-01 12:00:00 +08:00
yz-yu
dcad6ff922 Packer (#172)
* introduce pako and add general packer interface

* add tests for packer

* use function API instead of class API for better tree shaking support

* refcatoring the rollup bundle config
2026-04-01 12:00:00 +08:00
Yanzhen Yu
329c790194 add trigger focus option to replayer, which may helps integration into other apps 2026-04-01 12:00:00 +08:00
David Cramer
3a0e829884 Add observers for stylesheet mutations (#177)
* hack together stylesheet observer

* Add test coverage for insertRule/deleteRule on stylesheets

* Add new observers

* update patch based on changes to master

* Functioning event recording

* Remove print statements

* Fix ID usage and mark add vs remove

* Correct type

Co-authored-by: Jon Perl <perl.jonathan@gmail.com>
2026-04-01 12:00:00 +08:00
Yanzhen Yu
5bfc2c704a impl media interactions recording
close #159
close #72
listen to HTMLMediaElement's play/pause events, and replay them
by programmatically play and pause the target element.
2026-04-01 12:00:00 +08:00
Yanzhen Yu
d0c31bb4cf close #153 emit event when it being casted 2026-04-01 12:00:00 +08:00
mpstv
84de337040 Try add configurable threshold for events throttling (#147) 2026-04-01 12:00:00 +08:00
yz-yu
1afc0b7527 add hooks API (#132) 2026-04-01 12:00:00 +08:00
Yanzhen Yu
3a5e9271d5 close #84 set mousemoveData's source by event source 2026-04-01 12:00:00 +08:00
Yanzhen Yu
d92a946926 impl #81 custom event
This is the record side impl of custom event, according to the
issue, we may also add first-class support for the custom event
tag like display color labels in the replayer-ui.
2026-04-01 12:00:00 +08:00
肉肉肉肉
338da11e35 new feature: add custom style in replayer (#87)
* new feature: add custom style in replayer

* concat style rules for loop
2026-04-01 12:00:00 +08:00
Yanzhen Yu
94ca07d45d fix#71 fix touch event listener and throttle touch move callback 2026-04-01 12:00:00 +08:00
Sebastian Jakob
2502913883 Option to mask inputs (#80)
* Option to mask inputs

Added option 'maskAllInputs' to replace all user inputs with an Asterisk.

* Update types.d.ts
2026-04-01 12:00:00 +08:00
Yanzhen Yu
57df28de2f remove mitt typings namesapce 2026-04-01 12:00:00 +08:00
yz-yu
689840d237 start to support live mode (#73)
1. add a liveMode flag to config, when liveMode is set, the timer
will keep running even though all the actions casted
2. add a public method addEvent, which will cast newly added event
in sync
3. move mouse in sync mode with the latest position info
2026-04-01 12:00:00 +08:00
Yanzhen Yu
f312ecbadc add the inline stylesheet option when recording 2026-04-01 12:00:00 +08:00
Yanzhen Yu
503987c583 fix #62 accept RegExp type block class config 2026-04-01 12:00:00 +08:00
Yanzhen Yu
32c33f3ce8 move browser related APIs into runtime 2026-04-01 12:00:00 +08:00
Yanzhen Yu
d1b32e6e9d impl #23 add custom privacy selectors 2026-04-01 12:00:00 +08:00
Yanzhen Yu
153035f4b0 turn some warning message into debug message 2026-04-01 12:00:00 +08:00
Yanzhen Yu
e2bc867b2e move all events to an enum and update guide 2026-04-01 12:00:00 +08:00
yz-yu
ca61d6b19e fix remove node observer and check on the result of getNode (#43)
* check removed node and its parent before collect

* add more more checks on the result of getNode
2026-04-01 12:00:00 +08:00
yz-yu
081781d1ca add checkout config to recorder (#36)
* add checkout config to recorder

* add test cases for checkout feature and extract assertSnapshot method
2026-04-01 12:00:00 +08:00
Yanzhen Yu
21465e785f resolve #13 add warning messages when target is not found 2026-04-01 12:00:00 +08:00
Yanzhen Yu
73983e7e78 add skipInactive option
Skip inactive time is an important and useful feature. We consider
user interaction events as active, and check next user interaction
event after apply incremental snapshot.
If next user interaction event has a time gap larger than the
threshold, we will set a dynamic speed value which will skip the
inactive time interval in about 5 seconds.
2026-04-01 12:00:00 +08:00
Yanzhen Yu
0995b7a6d3 basic impl of wait for stylesheet loaded 2026-04-01 12:00:00 +08:00
edwardwu
05530551df resolve #4 Improve timer's performance by storing all callbacks in an array (#5) 2026-04-01 12:00:00 +08:00
Yanzhen Yu
cbe80dbd2e also resolve missing previous node 2026-04-01 12:00:00 +08:00
Yanzhen Yu
b7bf5f5fe3 Fix add node logic with missingNextNodeMap
This patch include a breaking change to the recorder's event data.

We used to consider mirror.getId will always return the id of the
target node because we keep serialize every node. But if we call
mirror.getId before serialization then bug happened. This could
happen when we get nextId of newly added nodes if its next sibling
was also newly added.
So we have to return -1 as the id of node which was not serialized
and when we building added nodes in the replayer we should handle
this.

For example, nodes el1, el2 were added together and el1's nextId
will be -1 since el2 was not serialized at that moment. Now we
call el1 as a 'missing next node' and not append it into the DOM
tree after building, instead we store it in a missingNextNodeMap.
After a added node in the same mutation was successfully appened
we will check whether it has a previous id and the id was pointed
to some nodes in the map, if so, we will insert that node before
it and delete the node from map.
2026-04-01 12:00:00 +08:00
Yanzhen Yu
7a57784daf Implement #2: simulate hover event 2026-04-01 12:00:00 +08:00
Yanzhen Yu
609f51a26a add a has method to mirror for checking whether an id is in the map 2026-04-01 12:00:00 +08:00
Yanzhen Yu
aa3e2f02ed rewrite mutation observer handler with lazy child list calculation 2026-04-01 12:00:00 +08:00
Yanzhen Yu
487f1d0c9a add meta event and fix childList observer, also update related replayer 2026-04-01 12:00:00 +08:00
Yanzhen Yu
eb56afa59f export more props of replayer to the UI 2026-04-01 12:00:00 +08:00
Yanzhen Yu
e040ae76c5 align id map by skip extra added nodes 2026-04-01 12:00:00 +08:00
Yanzhen Yu
4446e27899 fix scroll value and record viewport when loaded 2026-04-01 12:00:00 +08:00
Yanzhen Yu
41b9861fbf improve record method and bump 0.2.0 2026-04-01 12:00:00 +08:00
Yanzhen Yu
c96052d8a4 add input event observer and hook the value setter 2026-04-01 12:00:00 +08:00
Yanzhen Yu
ad2ac811a3 serialize newly added nodes and update id node map when childList changed 2026-04-01 12:00:00 +08:00
Yanzhen Yu
ee4fc3ce7e add scroll and viewport resize observers 2026-04-01 12:00:00 +08:00
Yanzhen Yu
7078ce2f2a add mouse interactions observer 2026-04-01 12:00:00 +08:00
Yanzhen Yu
61312a0ad0 add mouse movement observer 2026-04-01 12:00:00 +08:00
Yanzhen Yu
d2175eae87 change observed mutations into serializable records 2026-04-01 12:00:00 +08:00
Yanzhen Yu
e2fbecea96 init the repo and integrate rrweb-snapshot 2026-04-01 12:00:00 +08:00