Commit Graph

232 Commits

Author SHA1 Message Date
Yanzhen Yu
f555baa4ac impl #530, observe drag event and replay as mousemove 2026-04-01 12:00:00 +08:00
John Pham
a295f72ed0 Don't rebuildFullSnapshot if it's the first run (#532)
* Don't rebuildFullSnapshot if it's the first run

* Fix typo
2026-04-01 12:00:00 +08:00
Yanzhen Yu
3e8cacbb95 fix #531 use getRootNode with precheck 2026-04-01 12:00:00 +08:00
Yanzhen Yu
0e688bba0c impl shadow DOM manager
part of #38
1. observe DOM mutations in shadow DOM
2. rebuild DOM mutations in shadow DOM
2026-04-01 12:00:00 +08:00
Lucky Feng
66c7c8f028 fix: inaccurate mouse position (#522)
1. Position of mouse was inaccurate when replaying and this PR will fix it.
2. Fix the bug that if one nested iframe has a scale transform and the position of mouse was inaccurate as well.
2026-04-01 12:00:00 +08:00
Lucky Feng
016a5020fc fix: errors of replaying iframe records (#520)
* fix: errors of replaying iframe records

error1:
HierarchyRequestError: Failed to execute 'appendChild' on 'Node': Nodes of type '#document' may not be inserted inside nodes of type '#document-fragment'.
code: parent.appendChild(target)

error2:
Uncaught DOMException: Failed to execute 'appendChild' on 'Node': Only one element on document allowed.
code: parent.appendChild(target);

* improve the comment for bugfix
2026-04-01 12:00:00 +08:00
Yakko Majuri
fcbc0e4b43 Handle event undefined in initMoveObserver (#515) 2026-04-01 12:00:00 +08:00
Yanzhen Yu
b621011c56 add an experiment config to set max speed in fast forward 2026-04-01 12:00:00 +08:00
Yanzhen Yu
5e42ddc1cb impl #507 export takeFullSnapshot as a public API 2026-04-01 12:00:00 +08:00
Yanzhen Yu
2ee3926f25 fix lint errors 2026-04-01 12:00:00 +08:00
Yanzhen Yu
4ed82274ae close #491 check whether link node is head 2026-04-01 12:00:00 +08:00
Yanzhen Yu
36d52f8faf close #501 do not count attach iframe event in checkout 2026-04-01 12:00:00 +08:00
Province Innovation
eeac998959 Added mousemoveCallback threshold option to sampling config. (#492)
* Added mousemoveCallback threshold option to sampling config.

* Added mousemoveCallback to definitions file.
2026-04-01 12:00:00 +08:00
Yanzhen Yu
ab819bf338 start impl rrdom 2026-04-01 12:00:00 +08:00
Eoghan Murray
27bc40ac03 remove debugging warning (#486)
I can't see a reason for the warning here so believe it's a debugging statement that crept in?
2026-04-01 12:00:00 +08:00
yz-yu
33f0ac5cfe Impl record iframe (#481)
* Impl record iframe

* iframe observe

* temp: add bundle file to git

* update bundle

* update with pick

* update bundle

* fix fragment map remove

* feat: add an option to determine whether to pause CSS animation when playback is paused (#428)

set pauseAnimation to true by default

* fix: elements would lose some states like scroll position because of "virtual parent" optimization (#427)

* fix: elements would lose some state like scroll position because of "virtual parent" optimization

* refactor: the bugfix code

bug: elements would lose some state like scroll position because of "virtual parent" optimization

* fix: an error occured at applyMutation(remove nodes part)

error message:
Uncaught (in promise) DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node

* pick fixes

* revert ignore file

* re-impl iframe record

* re-impl iframe replay

* code housekeeping

* move multi layer dimension calculation to replay side

* update test cases

* teardown test server

* upgrade rrweb-snapshot with iframe load timeout

Co-authored-by: Lucky Feng <yun.feng@smartx.com>
2026-04-01 12:00:00 +08:00
Karl-Aksel Puulmann
b99e843e2a Fix RangeError: Maximum call stack size exceeded (#479)
Saw this line cause issues in production, causing the following error:

```
RangeError Maximum call stack size exceeded
```

I believe this is caused by javascript engine max argument length - see note from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply#using_apply_and_built-in_functions

> The consequences of applying a function with too many arguments (that is, more than tens of thousands of arguments) varies across engines. (The JavaScriptCore engine has hard-coded argument limit of 65536.
2026-04-01 12:00:00 +08:00
Yanzhen Yu
25d23bdc35 read __rrMutationObserver from window 2026-04-01 12:00:00 +08:00
Eoghan Murray
9f3f4d15f2 Discovered that the common case of mouse movement or scrolling happening during takeFullSnapshot was causing mutations to be immediately emitted, contrary to the goal of https://github.com/rrweb-io/rrweb/pull/385 (#470) 2026-04-01 12:00:00 +08:00
Yanzhen Yu
faa2ec79fa fix #469 try to get original MutationObserver
We found Angular's zone module will patch MutationObserver which
make the browser hang in some scenarios.
Reference: angular/angular#26948
2026-04-01 12:00:00 +08:00
Yanzhen Yu
57f15ddc02 fix #460 ignore added node that are not in document anymore 2026-04-01 12:00:00 +08:00
Yanzhen Yu
bc6e6101d3 clean addList when meet a corner case 2026-04-01 12:00:00 +08:00
Yanzhen Yu
d79ad0b8c3 let mouse tail duration respect timer speed 2026-04-01 12:00:00 +08:00
Yanzhen Yu
175c98d1ae fix #452 check isBlocked on add mutation's target 2026-04-01 12:00:00 +08:00
Eoghan Murray
efa806a81b Protect against generation of no-change viewport resize events. (#454)
I noticed 8 or 10 of these events being generated in a multi-tab browsing session on Chrome 87.0 on Win10.  I'm speculating they were generated as a side effect of changing tabs but I can't recreate
2026-04-01 12:00:00 +08:00
Jarosław Salwa
ac25796753 Scroll replayer iframe on firstFullsnapshot (#451) 2026-04-01 12:00:00 +08:00
101arrowz
30026bb8f5 Update to fflate (#448)
* Update to fflate

* Update docs, bundler config
2026-04-01 12:00:00 +08:00
Lucky Feng
bc36b505df fix: sometimes currentTime is smaller than the totalTime when player is finished (#445)
plus: fix the problem that sometimes return value of getCurrentTime() is negative
2026-04-01 12:00:00 +08:00
Krzysztof Grziwok
987d58ba35 Catch Security Errors in styleSheet rules (#437) 2026-04-01 12:00:00 +08:00
Lucky Feng
9d2db86d5a feat: enable rrweb to record and replay log messages in console (#424)
* wip: working on rrweb logger

* wip: can record and replay some simple log

* wip: can record and replay log's stack

* wip: try to serialize object

* wip: record and replay console logger

hijack all of the console functions.
add listener to thrown errors

* wip: record and replay console logger
add limit to the max number of log records

* feat: enable rrweb to record and replay log messages in console

this is the implementation of new feature request(issue #234)

here are a few points of description.
1. users need to set recordLog option in rrweb.record's parameter to record log messages.  The log recorder is off by default.
2. support recording and replaying all kinds of console functions. But the reliability of them should be tested more
3. the stringify function in  stringify.ts needs improvement. e.g. robustness, handler for cyclical structures and better support for more kinds of object
4. we can replay the log messages in a simulated html console like LogRocket by implementing the interface "ReplayLogger" in the future

* improve: the stringify function

1. handle cyclical structures
2. add stringify option to limit the length of result
3. handle function type

* refactor: simplify the type definition of ReplayLogger
2026-04-01 12:00:00 +08:00
Yanzhen Yu
519aa8d424 pick #286 allow short cut for slim DOM options 2026-04-01 12:00:00 +08:00
Yanzhen Yu
2628cee609 fix type error of slim DOM options 2026-04-01 12:00:00 +08:00
Yanzhen Yu
ec5b7a4635 pick #286, export slim DOM options 2026-04-01 12:00:00 +08:00
Yanzhen Yu
e9a5aeed06 expose blockSelector as a public option 2026-04-01 12:00:00 +08:00
Yanzhen Yu
528b8373a0 upgrade to rrweb-snapshot v1.0 2026-04-01 12:00:00 +08:00
Lucky Feng
10f79eeba4 style: delete a useless constant 2026-04-01 12:00:00 +08:00
Lucky Feng
5ad550c0db fix: elements would lose some states like scroll position because of "virtual parent" optimization (#427)
* fix: elements would lose some state like scroll position because of "virtual parent" optimization

* refactor: the bugfix code

bug: elements would lose some state like scroll position because of "virtual parent" optimization

* fix: an error occured at applyMutation(remove nodes part)

error message:
Uncaught (in promise) DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node
2026-04-01 12:00:00 +08:00
Lucky Feng
d7da4c289c feat: add an option to determine whether to pause CSS animation when playback is paused (#428)
set pauseAnimation to true by default
2026-04-01 12:00:00 +08:00
Lucky Feng
14ed8ad1e6 fix: applyScroll function doesn't work in sync mode(play at a specific time) (#426)
applyScroll function should be called after all of new nodes mounted on dom
2026-04-01 12:00:00 +08:00
Eoghan Murray
8833d3c7ce Ensure animations don't continue playing when we've paused playback (#417) 2026-04-01 12:00:00 +08:00
Yaozu Lv
4c9fc8ce70 Add record option maskInputFn for custom mask input function (#409) 2026-04-01 12:00:00 +08:00
Eoghan Murray
4726500979 Allow .on to be chained directly after the constructor so that event handling for the first full snapshot can be added straight after constructor. See #216 (#416) 2026-04-01 12:00:00 +08:00
踩坑小王子
13b8a69213 feat: enable to change the config of mouse tail while playing (#410)
fix a potential bug: handleResize function might change the display style of mouseTail
2026-04-01 12:00:00 +08:00
Yanzhen Yu
8607cb6071 Release 0.9.9 2026-04-01 12:00:00 +08:00
Yanzhen Yu
f8c0643eb8 fix serializeNodeWithId args 2026-04-01 12:00:00 +08:00
Yanzhen Yu
e797ecf820 upgrade rrweb-snapshot 2026-04-01 12:00:00 +08:00
Yanzhen Yu
4137985b01 optimize the append queue algorithm
Loop the append queue has been proved to be very inefficient, and
some times lead to N^2 time complexity.

Especially when some abnormal data could not be appended into the
real DOM, will make a dead loop.

Previously we use a 5000ms time out to handle this, which is not
user-friendly and not explicitly.

In this patch, we transform the queue into a tree data structure,
which reflects the layout of real DOM. With the tree data structure,
we can find whether there are dangling nodes that need to be dropped.
Also, the iteration will be much more efficient.

There is still a 500ms time out to avoid a dead loop, but should not
be called in expected scenarios.
2026-04-01 12:00:00 +08:00
Yanzhen Yu
f511425d7e ignore removed move set 2026-04-01 12:00:00 +08:00
Justin Halsall
455c4d76f4 Add support for StylesheetRule in document fragment (#293)
* add failing test

* add stylesheet to dom to manipulate the rules

* cleanup
2026-04-01 12:00:00 +08:00
Eoghan Murray
70fe32b5d2 Suspend mutations during snapshot (#385)
* The `processMutations` function needed to be bound to the `mutationBuffer` object, as otherwise `this` referred to the `MutationObserver` object itself

* Enable external pausing of mutation buffer emissions

 - no automatic pausing based on e.g. pageVisibility yet, assuming such a thing is desirable
   https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API
 - user code has to call new API method `freezePage` e.g. when page is hidden or after a timeout
 - automatically unpauses when the next user initiated event occurs
   (am assuming everything that isn't a mutation event counts as 'user initiated'
   either way think this is the correct thing to do until I see a counterexample
   of an event that shouldn't cause the mutations to be unbufferred)

* Avoid a build up of duplicate `adds` by delaying pushing to adds until emission time

* Need to export freezePage in order to use it from rrweb.min.js

* Add a test to check if mutations can be turned off with the `freezePage` method

* I noticed out of order ids (in terms of a DOM walk) in a FullSnapshot.  A DOM mutation was executed against the mirror asynchronously before it could be fully processed. This would lead to a situation in replay where a mutation is executed against a DOM tree that already has the mutation applied. This changeset fixes that by freezing any mutations until the snapshot is completed.

* Remove attribute modifications from a mutation event that were incorrect in that they were repeating the attributes of those nodes present in the 'adds' array of the same mutation

* I've manually verified that this empty text node is actually removed when the dropdown is opened:

document.getElementById('select2-results-1').childNodes
NodeList(2) [li.select2-results-dept-0.select2-result.select2-result-selectable.select2-highlighted, li.select2-results-dept-0.select2-result.select2-result-selectable]

and also that it is not reinstated after the second `await page.click('.select2-container');`

* Rearrange when removal happens in order to satisfy tests. I'm also reverting a recent test change (2600fe7) so that tests pass after this rearrangement; I believe that test change to still be the correct way of doing it, but maybe it is not strictly important that there are extra mutations on attributes of just added nodes

* As mutations are now paused during FullSnapshots, we shouldn't be counting this as a 'user emission'. We automatically emit mutations after unpause anyway ('emit anything queued up now')

* Ensure that we clear arrays before emitting, as the mutation could have the side effect of triggering a FullSnapshot (checkoutEveryNth), which would otherwise re-trigger emission of same mutation (through the new pause/fullsnapshot/mutationemit/unpause process)

* Don't let the programattic pausing during TakeFullSnapshot accidentally unpause a manual call to the API method `freezePage`

* Rename paused -> frozen for consistency and change to use getter/setter access methods
2026-04-01 12:00:00 +08:00