From 934262f4e2ade443b48424d0fff3743bbde33081 Mon Sep 17 00:00:00 2001 From: Kelly Wallach Date: Wed, 18 Oct 2023 14:50:16 -0400 Subject: [PATCH 01/66] perf: only call createHTMLDocument when it is needed --- packages/rrweb/src/record/mutation.ts | 56 +++++++++++++-------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/packages/rrweb/src/record/mutation.ts b/packages/rrweb/src/record/mutation.ts index 80943d96ab..6b237b3e58 100644 --- a/packages/rrweb/src/record/mutation.ts +++ b/packages/rrweb/src/record/mutation.ts @@ -1,36 +1,36 @@ +import type { + Optional, + addedNodeMutation, + attributeCursor, + mutationRecord, + removedNodeMutation, + textCursor, +} from '@rrweb/types'; import { - serializeNodeWithId, - transformAttribute, IGNORED_NODE, + Mirror, + getInputType, ignoreAttribute, + isNativeShadowDom, isShadowRoot, - needMaskingText, maskInputValue, - Mirror, - isNativeShadowDom, - getInputType, + needMaskingText, + serializeNodeWithId, toLowerCase, + transformAttribute, } from 'rrweb-snapshot'; -import type { observerParam, MutationBufferParam } from '../types'; -import type { - mutationRecord, - textCursor, - attributeCursor, - removedNodeMutation, - addedNodeMutation, - Optional, -} from '@rrweb/types'; +import type { MutationBufferParam, observerParam } from '../types'; import { - isBlocked, + closestElementOfNode, + getShadowHost, + hasShadowRoot, + inDom, isAncestorRemoved, + isBlocked, isIgnored, isSerialized, - hasShadowRoot, isSerializedIframe, isSerializedStylesheet, - inDom, - getShadowHost, - closestElementOfNode, } from '../utils'; type DoubleLinkedListNode = { @@ -498,14 +498,6 @@ export default class MutationBuffer { if (isIgnored(m.target, this.mirror)) { return; } - let unattachedDoc; - try { - // avoid upsetting original document from a Content Security point of view - unattachedDoc = document.implementation.createHTMLDocument(); - } catch (e) { - // fallback to more direct method - unattachedDoc = this.doc; - } switch (m.type) { case 'characterData': { const value = m.target.textContent; @@ -599,6 +591,14 @@ export default class MutationBuffer { value, ); if (attributeName === 'style') { + let unattachedDoc; + try { + // avoid upsetting original document from a Content Security point of view + unattachedDoc = document.implementation.createHTMLDocument(); + } catch (e) { + // fallback to more direct method + unattachedDoc = this.doc; + } const old = unattachedDoc.createElement('span'); if (m.oldValue) { old.setAttribute('style', m.oldValue); From 9dae066dbd20fe034140be82c13d0312cfe1140f Mon Sep 17 00:00:00 2001 From: Kelly Wallach Date: Wed, 18 Oct 2023 14:57:01 -0400 Subject: [PATCH 02/66] Create popular-spies-fetch.md --- .changeset/popular-spies-fetch.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/popular-spies-fetch.md diff --git a/.changeset/popular-spies-fetch.md b/.changeset/popular-spies-fetch.md new file mode 100644 index 0000000000..b1482644eb --- /dev/null +++ b/.changeset/popular-spies-fetch.md @@ -0,0 +1,5 @@ +--- +"rrweb": patch +--- + +perf: only call createHTMLDocument when it is needed From 7e43b8501d220cc2d9e3653ce178e3deb5af16ef Mon Sep 17 00:00:00 2001 From: kwalker3690 Date: Wed, 18 Oct 2023 18:59:57 +0000 Subject: [PATCH 03/66] Apply formatting changes --- .changeset/popular-spies-fetch.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/popular-spies-fetch.md b/.changeset/popular-spies-fetch.md index b1482644eb..6f2eaccb5b 100644 --- a/.changeset/popular-spies-fetch.md +++ b/.changeset/popular-spies-fetch.md @@ -1,5 +1,5 @@ --- -"rrweb": patch +'rrweb': patch --- perf: only call createHTMLDocument when it is needed From dbc22b924972cb562f05899784bc5c15d9e0e36c Mon Sep 17 00:00:00 2001 From: Jesse Wang Date: Wed, 18 Oct 2023 13:19:06 -0700 Subject: [PATCH 04/66] feat: skip through inactive periods instead of fast forward --- packages/rrweb/src/replay/index.ts | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/packages/rrweb/src/replay/index.ts b/packages/rrweb/src/replay/index.ts index aac84c2783..c356ba2c5e 100644 --- a/packages/rrweb/src/replay/index.ts +++ b/packages/rrweb/src/replay/index.ts @@ -679,10 +679,6 @@ export class Replayer { // do not check skip in sync return; } - if (event === this.nextUserInteractionEvent) { - this.nextUserInteractionEvent = null; - this.backToNormal(); - } if (this.config.skipInactive && !this.nextUserInteractionEvent) { for (const _event of this.service.state.context.events) { if (_event.timestamp <= event.timestamp) { @@ -704,14 +700,8 @@ export class Replayer { const skipTime = // eslint-disable-next-line @typescript-eslint/no-non-null-assertion this.nextUserInteractionEvent.delay! - event.delay!; - const payload = { - speed: Math.min( - Math.round(skipTime / SKIP_TIME_INTERVAL), - this.config.maxSpeed, - ), - }; - this.speedService.send({ type: 'FAST_FORWARD', payload }); - this.emitter.emit(ReplayerEvents.SkipStart, payload); + this.play(this.getCurrentTime() + skipTime) + this.nextUserInteractionEvent = null; } } }; From 78be9bbb0973cec007c120c40bf89a096498a13d Mon Sep 17 00:00:00 2001 From: jxiwang Date: Wed, 18 Oct 2023 20:22:12 +0000 Subject: [PATCH 05/66] Apply formatting changes --- packages/rrweb/src/replay/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rrweb/src/replay/index.ts b/packages/rrweb/src/replay/index.ts index c356ba2c5e..f4e8a6542a 100644 --- a/packages/rrweb/src/replay/index.ts +++ b/packages/rrweb/src/replay/index.ts @@ -700,7 +700,7 @@ export class Replayer { const skipTime = // eslint-disable-next-line @typescript-eslint/no-non-null-assertion this.nextUserInteractionEvent.delay! - event.delay!; - this.play(this.getCurrentTime() + skipTime) + this.play(this.getCurrentTime() + skipTime); this.nextUserInteractionEvent = null; } } From 3e5af934c999479ab0e7d1a82ce6b3a427d4e528 Mon Sep 17 00:00:00 2001 From: Kelly Wallach Date: Fri, 20 Oct 2023 15:49:19 -0400 Subject: [PATCH 06/66] Update package.json --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index e6669ce15c..99b66d4fa9 100644 --- a/package.json +++ b/package.json @@ -2,18 +2,18 @@ "description": "record and replay the web", "repository": { "type": "git", - "url": "git+ssh://git@github.com/rrweb-io/rrweb.git" + "url": "git+ssh://git@github.com/amplitude/rrweb.git" }, "keywords": [ "rrweb" ], - "author": "yanzhen@smartx.com", + "author": "Amplitude Inc", "license": "MIT", "bugs": { - "url": "https://github.com/rrweb-io/rrweb/issues" + "url": "https://github.com/amplitude/rrweb/issues" }, "private": true, - "homepage": "https://github.com/rrweb-io/rrweb#readme", + "homepage": "https://github.com/amplitude/rrweb#readme", "workspaces": [ "packages/*" ], From b5be3a66a210185b77e8c9fe3686be705354c145 Mon Sep 17 00:00:00 2001 From: Kelly Wallach Date: Mon, 23 Oct 2023 13:31:17 -0400 Subject: [PATCH 07/66] Updating references to repo and author --- .changeset/config.json | 2 +- packages/rrdom-nodejs/package.json | 2 +- packages/rrdom/package.json | 2 +- packages/rrvideo/package.json | 4 ++-- packages/rrweb-player/package.json | 10 +++++----- packages/rrweb-snapshot/package.json | 10 +++++----- packages/rrweb/package.json | 10 +++++----- packages/types/package.json | 8 ++++---- 8 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.changeset/config.json b/.changeset/config.json index 962e9799b0..809aedbfdb 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -1,6 +1,6 @@ { "$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json", - "changelog": ["@changesets/changelog-github", { "repo": "rrweb-io/rrweb" }], + "changelog": ["@changesets/changelog-github", { "repo": "amplitude/rrweb" }], "commit": false, "fixed": [ [ diff --git a/packages/rrdom-nodejs/package.json b/packages/rrdom-nodejs/package.json index 58aad4a681..6edbd703a0 100644 --- a/packages/rrdom-nodejs/package.json +++ b/packages/rrdom-nodejs/package.json @@ -1,5 +1,5 @@ { - "name": "rrdom-nodejs", + "name": "@amplitude/rrdom-nodejs", "version": "2.0.0-alpha.11", "scripts": { "dev": "rollup -c -w", diff --git a/packages/rrdom/package.json b/packages/rrdom/package.json index f7122da917..b7fa09659c 100644 --- a/packages/rrdom/package.json +++ b/packages/rrdom/package.json @@ -1,5 +1,5 @@ { - "name": "rrdom", + "name": "@amplitude/rrdom", "version": "2.0.0-alpha.11", "homepage": "https://github.com/rrweb-io/rrweb/tree/main/packages/rrdom#readme", "license": "MIT", diff --git a/packages/rrvideo/package.json b/packages/rrvideo/package.json index 5472c8981a..e11c39fba2 100644 --- a/packages/rrvideo/package.json +++ b/packages/rrvideo/package.json @@ -1,5 +1,5 @@ { - "name": "rrvideo", + "name": "@amplitude/rrvideo", "version": "2.0.0-alpha.11", "description": "transform rrweb session into video", "main": "build/index.js", @@ -17,7 +17,7 @@ "check-types": "tsc -noEmit", "prepublish": "yarn build" }, - "author": "yanzhen@smartx.com", + "author": "Amplitude Inc", "license": "MIT", "devDependencies": { "@types/fs-extra": "11.0.1", diff --git a/packages/rrweb-player/package.json b/packages/rrweb-player/package.json index f545256267..9ef55cd0b1 100644 --- a/packages/rrweb-player/package.json +++ b/packages/rrweb-player/package.json @@ -1,5 +1,5 @@ { - "name": "rrweb-player", + "name": "@amplitude/rrweb-player", "version": "2.0.0-alpha.11", "devDependencies": { "@rollup/plugin-commonjs": "^22.0.0", @@ -48,15 +48,15 @@ "type": "module", "repository": { "type": "git", - "url": "git+https://github.com/rrweb-io/rrweb.git" + "url": "git+https://github.com/amplitude/rrweb.git" }, "keywords": [ "rrweb" ], - "author": "yanzhen@smartx.com", + "author": "Amplitude Inc", "license": "MIT", "bugs": { - "url": "https://github.com/rrweb-io/rrweb/issues" + "url": "https://github.com/amplitude/rrweb/issues" }, - "homepage": "https://github.com/rrweb-io/rrweb#readme" + "homepage": "https://github.com/amplitude/rrweb#readme" } diff --git a/packages/rrweb-snapshot/package.json b/packages/rrweb-snapshot/package.json index 00b2a98f35..dab076ae88 100644 --- a/packages/rrweb-snapshot/package.json +++ b/packages/rrweb-snapshot/package.json @@ -1,5 +1,5 @@ { - "name": "rrweb-snapshot", + "name": "@amplitude/rrweb-snapshot", "version": "2.0.0-alpha.11", "description": "rrweb's component to take a snapshot of DOM, aka DOM serializer", "scripts": { @@ -18,7 +18,7 @@ "type": "module", "repository": { "type": "git", - "url": "git+https://github.com/rrweb-io/rrweb.git" + "url": "git+https://github.com/amplitude/rrweb.git" }, "keywords": [ "rrweb", @@ -35,12 +35,12 @@ "es", "typings" ], - "author": "yanzhen@smartx.com", + "author": "Amplitude Inc", "license": "MIT", "bugs": { - "url": "https://github.com/rrweb-io/rrweb/issues" + "url": "https://github.com/amplitude/rrweb/issues" }, - "homepage": "https://github.com/rrweb-io/rrweb/tree/master/packages/rrweb-snapshot#readme", + "homepage": "https://github.com/amplitude/rrweb/tree/master/packages/rrweb-snapshot#readme", "devDependencies": { "@types/chai": "^4.1.4", "@types/jest": "^27.0.2", diff --git a/packages/rrweb/package.json b/packages/rrweb/package.json index a95f60f380..47a2920e13 100644 --- a/packages/rrweb/package.json +++ b/packages/rrweb/package.json @@ -1,5 +1,5 @@ { - "name": "rrweb", + "name": "@amplitude/rrweb", "version": "2.0.0-alpha.11", "description": "record and replay the web", "scripts": { @@ -26,7 +26,7 @@ "type": "module", "repository": { "type": "git", - "url": "git+ssh://git@github.com/rrweb-io/rrweb.git" + "url": "git+ssh://git@github.com/amplitude/rrweb.git" }, "keywords": [ "rrweb" @@ -42,12 +42,12 @@ "es", "typings" ], - "author": "yanzhen@smartx.com", + "author": "Amplitude", "license": "MIT", "bugs": { - "url": "https://github.com/rrweb-io/rrweb/issues" + "url": "https://github.com/amplitude/rrweb/issues" }, - "homepage": "https://github.com/rrweb-io/rrweb#readme", + "homepage": "https://github.com/amplitude/rrweb#readme", "devDependencies": { "@rollup/plugin-node-resolve": "^13.1.3", "@types/chai": "^4.1.6", diff --git a/packages/types/package.json b/packages/types/package.json index d3d376e0f2..efa7cc74a5 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,5 +1,5 @@ { - "name": "@rrweb/types", + "name": "@amplitude/rrweb-types", "version": "2.0.0-alpha.11", "publishConfig": { "access": "public" @@ -15,13 +15,13 @@ "prepublish": "npm run build", "lint": "yarn eslint src/**/*.ts" }, - "homepage": "https://github.com/rrweb-io/rrweb/tree/main/packages/@rrweb/types#readme", + "homepage": "https://github.com/amplitude/rrweb/tree/main/packages/@rrweb/types#readme", "bugs": { - "url": "https://github.com/rrweb-io/rrweb/issues" + "url": "https://github.com/amplitude/rrweb/issues" }, "repository": { "type": "git", - "url": "git+https://github.com/rrweb-io/rrweb.git" + "url": "git+https://github.com/amplitude/rrweb.git" }, "license": "MIT", "type": "module", From 2de2b45a7142afb6d2da649ecb46ef360b2357c8 Mon Sep 17 00:00:00 2001 From: Kelly Wallach Date: Mon, 23 Oct 2023 14:20:38 -0400 Subject: [PATCH 08/66] Update changeset config --- .changeset/config.json | 16 ++++++++-------- packages/rrweb/package.json | 2 +- packages/web-extension/package.json | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.changeset/config.json b/.changeset/config.json index 809aedbfdb..298e61e2b3 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -4,14 +4,14 @@ "commit": false, "fixed": [ [ - "rrweb", - "rrweb-snapshot", - "rrdom", - "rrdom-nodejs", - "rrweb-player", - "@rrweb/types", - "@rrweb/web-extension", - "rrvideo" + "@amplitude/rrweb", + "@amplitude/rrweb-snapshot", + "@amplitude/rrdom", + "@amplitude/rrdom-nodejs", + "@amplitude/rrweb-player", + "@amplitude/rrweb-types", + "@amplitude/rrweb-web-extension", + "@amplitude/rrvideo" ] ], "linked": [], diff --git a/packages/rrweb/package.json b/packages/rrweb/package.json index 47a2920e13..66c31edfa6 100644 --- a/packages/rrweb/package.json +++ b/packages/rrweb/package.json @@ -42,7 +42,7 @@ "es", "typings" ], - "author": "Amplitude", + "author": "Amplitude Inc", "license": "MIT", "bugs": { "url": "https://github.com/amplitude/rrweb/issues" diff --git a/packages/web-extension/package.json b/packages/web-extension/package.json index eb87e818ba..ea6d0cc359 100644 --- a/packages/web-extension/package.json +++ b/packages/web-extension/package.json @@ -1,9 +1,9 @@ { - "name": "@rrweb/web-extension", + "name": "@amplitude/rrweb-web-extension", "private": true, "version": "2.0.0-alpha.11", "description": "The web extension of rrweb which helps to run rrweb on any website out of box", - "author": "rrweb-io", + "author": "Amplitude Inc", "license": "MIT", "scripts": { "dev:chrome": "cross-env TARGET_BROWSER=chrome vite dev", From 8cecb09bd48e3de3393926e17ae6ac896cd0e2a5 Mon Sep 17 00:00:00 2001 From: Kelly Wallach Date: Mon, 23 Oct 2023 15:49:21 -0400 Subject: [PATCH 09/66] Resetting changeset state --- .changeset/attribute-text-reductions.md | 5 -- .changeset/brave-numbers-joke.md | 2 - .changeset/calm-bulldogs-speak.md | 2 - .changeset/calm-oranges-sin.md | 5 -- .changeset/chatty-cherries-train.md | 5 -- .changeset/clean-plants-play.md | 9 --- .changeset/clean-shrimps-lay.md | 7 --- .changeset/cold-eyes-hunt.md | 8 --- .changeset/controller-finish-flag.md | 6 -- .changeset/cuddly-readers-warn.md | 2 - .changeset/curvy-apples-lay.md | 6 -- .changeset/date-now-guard.md | 5 -- .changeset/eight-terms-hunt.md | 5 -- .changeset/empty-bikes-cheer.md | 2 - .changeset/fair-dragons-greet.md | 2 - .changeset/fast-chefs-smell.md | 5 -- .changeset/few-turkeys-reflect.md | 2 - .changeset/five-peas-lay.md | 2 - .changeset/forty-elephants-attack.md | 2 - .changeset/fresh-cars-impress.md | 2 - .changeset/fresh-spoons-drive.md | 5 -- .changeset/gold-terms-look.md | 5 -- .changeset/grumpy-ways-own.md | 7 --- .changeset/itchy-dryers-double.md | 8 --- .changeset/khaki-dots-bathe.md | 2 - .changeset/large-ants-prove.md | 6 -- .changeset/lazy-toes-confess.md | 5 -- .changeset/little-radios-thank.md | 5 -- .changeset/little-suits-leave.md | 6 -- .changeset/loud-seals-raise.md | 6 -- .changeset/lovely-pears-cross.md | 5 -- .changeset/lovely-students-boil.md | 6 -- .changeset/mean-tips-impress.md | 5 -- .changeset/mighty-frogs-sparkle.md | 2 - .changeset/nervous-buses-pump.md | 5 -- .changeset/nervous-mirrors-perform.md | 6 -- .changeset/nervous-poets-grin.md | 9 --- .changeset/nervous-tables-travel.md | 6 -- .changeset/new-snakes-call.md | 6 -- .changeset/nice-pugs-reply.md | 5 -- .changeset/old-dryers-hide.md | 5 -- .changeset/polite-olives-wave.md | 5 -- .changeset/popular-spies-fetch.md | 5 -- .changeset/pre.json | 81 +++---------------------- .changeset/pretty-plums-rescue.md | 5 -- .changeset/pretty-schools-remember.md | 5 -- .changeset/proud-experts-jam.md | 5 -- .changeset/real-masks-explode.md | 5 -- .changeset/real-trains-switch.md | 6 -- .changeset/rich-crews-protect.md | 2 - .changeset/rich-jars-remember.md | 5 -- .changeset/serious-ants-juggle.md | 10 --- .changeset/sixty-impalas-laugh.md | 5 -- .changeset/small-olives-arrive.md | 5 -- .changeset/smooth-poems-bake.md | 5 -- .changeset/stupid-ghosts-help.md | 5 -- .changeset/swift-dancers-rest.md | 6 -- .changeset/swift-peas-film.md | 6 -- .changeset/thirty-baboons-punch.md | 5 -- .changeset/tidy-yaks-joke.md | 5 -- .changeset/tiny-buckets-love.md | 5 -- .changeset/tiny-chairs-build.md | 7 --- .changeset/tricky-panthers-guess.md | 5 -- .changeset/twenty-lies-switch.md | 49 --------------- .changeset/twenty-planets-repeat.md | 2 - .changeset/violet-melons-itch.md | 5 -- .changeset/violet-zebras-cry.md | 5 -- .changeset/yellow-mails-cheat.md | 8 --- .changeset/young-timers-grow.md | 5 -- 69 files changed, 9 insertions(+), 457 deletions(-) delete mode 100644 .changeset/attribute-text-reductions.md delete mode 100644 .changeset/brave-numbers-joke.md delete mode 100644 .changeset/calm-bulldogs-speak.md delete mode 100644 .changeset/calm-oranges-sin.md delete mode 100644 .changeset/chatty-cherries-train.md delete mode 100644 .changeset/clean-plants-play.md delete mode 100644 .changeset/clean-shrimps-lay.md delete mode 100644 .changeset/cold-eyes-hunt.md delete mode 100644 .changeset/controller-finish-flag.md delete mode 100644 .changeset/cuddly-readers-warn.md delete mode 100644 .changeset/curvy-apples-lay.md delete mode 100644 .changeset/date-now-guard.md delete mode 100644 .changeset/eight-terms-hunt.md delete mode 100644 .changeset/empty-bikes-cheer.md delete mode 100644 .changeset/fair-dragons-greet.md delete mode 100644 .changeset/fast-chefs-smell.md delete mode 100644 .changeset/few-turkeys-reflect.md delete mode 100644 .changeset/five-peas-lay.md delete mode 100644 .changeset/forty-elephants-attack.md delete mode 100644 .changeset/fresh-cars-impress.md delete mode 100644 .changeset/fresh-spoons-drive.md delete mode 100644 .changeset/gold-terms-look.md delete mode 100644 .changeset/grumpy-ways-own.md delete mode 100644 .changeset/itchy-dryers-double.md delete mode 100644 .changeset/khaki-dots-bathe.md delete mode 100644 .changeset/large-ants-prove.md delete mode 100644 .changeset/lazy-toes-confess.md delete mode 100644 .changeset/little-radios-thank.md delete mode 100644 .changeset/little-suits-leave.md delete mode 100644 .changeset/loud-seals-raise.md delete mode 100644 .changeset/lovely-pears-cross.md delete mode 100644 .changeset/lovely-students-boil.md delete mode 100644 .changeset/mean-tips-impress.md delete mode 100644 .changeset/mighty-frogs-sparkle.md delete mode 100644 .changeset/nervous-buses-pump.md delete mode 100644 .changeset/nervous-mirrors-perform.md delete mode 100644 .changeset/nervous-poets-grin.md delete mode 100644 .changeset/nervous-tables-travel.md delete mode 100644 .changeset/new-snakes-call.md delete mode 100644 .changeset/nice-pugs-reply.md delete mode 100644 .changeset/old-dryers-hide.md delete mode 100644 .changeset/polite-olives-wave.md delete mode 100644 .changeset/popular-spies-fetch.md delete mode 100644 .changeset/pretty-plums-rescue.md delete mode 100644 .changeset/pretty-schools-remember.md delete mode 100644 .changeset/proud-experts-jam.md delete mode 100644 .changeset/real-masks-explode.md delete mode 100644 .changeset/real-trains-switch.md delete mode 100644 .changeset/rich-crews-protect.md delete mode 100644 .changeset/rich-jars-remember.md delete mode 100644 .changeset/serious-ants-juggle.md delete mode 100644 .changeset/sixty-impalas-laugh.md delete mode 100644 .changeset/small-olives-arrive.md delete mode 100644 .changeset/smooth-poems-bake.md delete mode 100644 .changeset/stupid-ghosts-help.md delete mode 100644 .changeset/swift-dancers-rest.md delete mode 100644 .changeset/swift-peas-film.md delete mode 100644 .changeset/thirty-baboons-punch.md delete mode 100644 .changeset/tidy-yaks-joke.md delete mode 100644 .changeset/tiny-buckets-love.md delete mode 100644 .changeset/tiny-chairs-build.md delete mode 100644 .changeset/tricky-panthers-guess.md delete mode 100644 .changeset/twenty-lies-switch.md delete mode 100644 .changeset/twenty-planets-repeat.md delete mode 100644 .changeset/violet-melons-itch.md delete mode 100644 .changeset/violet-zebras-cry.md delete mode 100644 .changeset/yellow-mails-cheat.md delete mode 100644 .changeset/young-timers-grow.md diff --git a/.changeset/attribute-text-reductions.md b/.changeset/attribute-text-reductions.md deleted file mode 100644 index 648e0d81b9..0000000000 --- a/.changeset/attribute-text-reductions.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'rrweb': patch ---- - -Don't include redundant data from text/attribute mutations on just-added nodes diff --git a/.changeset/brave-numbers-joke.md b/.changeset/brave-numbers-joke.md deleted file mode 100644 index a845151cc8..0000000000 --- a/.changeset/brave-numbers-joke.md +++ /dev/null @@ -1,2 +0,0 @@ ---- ---- diff --git a/.changeset/calm-bulldogs-speak.md b/.changeset/calm-bulldogs-speak.md deleted file mode 100644 index a845151cc8..0000000000 --- a/.changeset/calm-bulldogs-speak.md +++ /dev/null @@ -1,2 +0,0 @@ ---- ---- diff --git a/.changeset/calm-oranges-sin.md b/.changeset/calm-oranges-sin.md deleted file mode 100644 index a1449698e4..0000000000 --- a/.changeset/calm-oranges-sin.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'rrweb': patch ---- - -fix: Fix checking for `patchTarget` in `initAdoptedStyleSheetObserver` diff --git a/.changeset/chatty-cherries-train.md b/.changeset/chatty-cherries-train.md deleted file mode 100644 index 18c275f073..0000000000 --- a/.changeset/chatty-cherries-train.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'rrweb': patch ---- - -Fix the statement which is getting changed by Microbundle diff --git a/.changeset/clean-plants-play.md b/.changeset/clean-plants-play.md deleted file mode 100644 index 809dae8d86..0000000000 --- a/.changeset/clean-plants-play.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'rrweb': patch -'@rrweb/types': patch ---- - -Compact style mutation fixes and improvements - -- fixes when style updates contain a 'var()' on a shorthand property #1246 -- further ensures that style mutations are compact by reverting to string method if it is shorter diff --git a/.changeset/clean-shrimps-lay.md b/.changeset/clean-shrimps-lay.md deleted file mode 100644 index 01c2d6b73b..0000000000 --- a/.changeset/clean-shrimps-lay.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'rrweb': patch ---- - -feat: Add `ignoreSelector` option - -Similar to ignoreClass, but accepts a CSS selector so that you can use any CSS selector. diff --git a/.changeset/cold-eyes-hunt.md b/.changeset/cold-eyes-hunt.md deleted file mode 100644 index ac3a8be10d..0000000000 --- a/.changeset/cold-eyes-hunt.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'rrdom': patch ---- - -Fix: rrdom bugs - -1. Fix a bug in the diff algorithm. -2. Omit the 'srcdoc' attribute of iframes to avoid overwriting content. diff --git a/.changeset/controller-finish-flag.md b/.changeset/controller-finish-flag.md deleted file mode 100644 index 567e5db44e..0000000000 --- a/.changeset/controller-finish-flag.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'rrweb-player': patch -'rrweb': patch ---- - -Reset the finished flag in Controller `goto` instead of `handleProgressClick` so that it is properly handled if `goto` is called directly. diff --git a/.changeset/cuddly-readers-warn.md b/.changeset/cuddly-readers-warn.md deleted file mode 100644 index a845151cc8..0000000000 --- a/.changeset/cuddly-readers-warn.md +++ /dev/null @@ -1,2 +0,0 @@ ---- ---- diff --git a/.changeset/curvy-apples-lay.md b/.changeset/curvy-apples-lay.md deleted file mode 100644 index 9072a2ad25..0000000000 --- a/.changeset/curvy-apples-lay.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'rrweb-snapshot': patch -'rrweb': patch ---- - -Extend to run fixBrowserCompatibilityIssuesInCSS over inline stylesheets diff --git a/.changeset/date-now-guard.md b/.changeset/date-now-guard.md deleted file mode 100644 index 2e0ac5e711..0000000000 --- a/.changeset/date-now-guard.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'rrweb': patch ---- - -Guard against presence of older 3rd party javascript libraries which redefine Date.now() diff --git a/.changeset/eight-terms-hunt.md b/.changeset/eight-terms-hunt.md deleted file mode 100644 index f5dc1d0eb9..0000000000 --- a/.changeset/eight-terms-hunt.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'rrweb': patch ---- - -Fix: Switch from virtual dom to real dom before rebuilding fullsnapshot diff --git a/.changeset/empty-bikes-cheer.md b/.changeset/empty-bikes-cheer.md deleted file mode 100644 index a845151cc8..0000000000 --- a/.changeset/empty-bikes-cheer.md +++ /dev/null @@ -1,2 +0,0 @@ ---- ---- diff --git a/.changeset/fair-dragons-greet.md b/.changeset/fair-dragons-greet.md deleted file mode 100644 index a845151cc8..0000000000 --- a/.changeset/fair-dragons-greet.md +++ /dev/null @@ -1,2 +0,0 @@ ---- ---- diff --git a/.changeset/fast-chefs-smell.md b/.changeset/fast-chefs-smell.md deleted file mode 100644 index 34125c4ef1..0000000000 --- a/.changeset/fast-chefs-smell.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'rrweb': patch ---- - -Fix: [#1178](https://github.com/rrweb-io/rrweb/issues/1178) remove warning related to worker_threads while building diff --git a/.changeset/few-turkeys-reflect.md b/.changeset/few-turkeys-reflect.md deleted file mode 100644 index a845151cc8..0000000000 --- a/.changeset/few-turkeys-reflect.md +++ /dev/null @@ -1,2 +0,0 @@ ---- ---- diff --git a/.changeset/five-peas-lay.md b/.changeset/five-peas-lay.md deleted file mode 100644 index a845151cc8..0000000000 --- a/.changeset/five-peas-lay.md +++ /dev/null @@ -1,2 +0,0 @@ ---- ---- diff --git a/.changeset/forty-elephants-attack.md b/.changeset/forty-elephants-attack.md deleted file mode 100644 index a845151cc8..0000000000 --- a/.changeset/forty-elephants-attack.md +++ /dev/null @@ -1,2 +0,0 @@ ---- ---- diff --git a/.changeset/fresh-cars-impress.md b/.changeset/fresh-cars-impress.md deleted file mode 100644 index a845151cc8..0000000000 --- a/.changeset/fresh-cars-impress.md +++ /dev/null @@ -1,2 +0,0 @@ ---- ---- diff --git a/.changeset/fresh-spoons-drive.md b/.changeset/fresh-spoons-drive.md deleted file mode 100644 index b99410373c..0000000000 --- a/.changeset/fresh-spoons-drive.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'rrweb': patch ---- - -Fix: processed-node-manager is created even in the environment that doesn't need a recorder diff --git a/.changeset/gold-terms-look.md b/.changeset/gold-terms-look.md deleted file mode 100644 index 4ad333341c..0000000000 --- a/.changeset/gold-terms-look.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'rrweb': patch ---- - -perf: optimize performance of the DoubleLinkedList get diff --git a/.changeset/grumpy-ways-own.md b/.changeset/grumpy-ways-own.md deleted file mode 100644 index f34169219a..0000000000 --- a/.changeset/grumpy-ways-own.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'rrweb-snapshot': patch ---- - -Fix: CSS transitions are incorrectly being applied upon rebuild in Firefox. Presumably FF doesn't finished parsing the styles in time, and applies e.g. a default margin:0 to elements which have a non-zero margin set in CSS, along with a transition on them. - -Related bug report to Firefox: https://bugzilla.mozilla.org/show_bug.cgi?id=1816672​ diff --git a/.changeset/itchy-dryers-double.md b/.changeset/itchy-dryers-double.md deleted file mode 100644 index 67fc6f6e36..0000000000 --- a/.changeset/itchy-dryers-double.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'rrweb-player': patch -'rrweb-snapshot': patch -'rrweb': patch -'@rrweb/types': patch ---- - -Upgrade all projects to typescript 4.9.5 diff --git a/.changeset/khaki-dots-bathe.md b/.changeset/khaki-dots-bathe.md deleted file mode 100644 index a845151cc8..0000000000 --- a/.changeset/khaki-dots-bathe.md +++ /dev/null @@ -1,2 +0,0 @@ ---- ---- diff --git a/.changeset/large-ants-prove.md b/.changeset/large-ants-prove.md deleted file mode 100644 index 9c7681beb3..0000000000 --- a/.changeset/large-ants-prove.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'rrweb-snapshot': patch -'rrweb': patch ---- - -Fix: Make relative path detection in stylesheet URLs to detect more types of URL protocols when inlining stylesheets. diff --git a/.changeset/lazy-toes-confess.md b/.changeset/lazy-toes-confess.md deleted file mode 100644 index f3e159a61e..0000000000 --- a/.changeset/lazy-toes-confess.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'rrvideo': patch ---- - -Refactor: Improve the video quality and add a progress bar for the CLI tool diff --git a/.changeset/little-radios-thank.md b/.changeset/little-radios-thank.md deleted file mode 100644 index ea9c3f609d..0000000000 --- a/.changeset/little-radios-thank.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'rrweb': patch ---- - -Guard against redefinition of Date.now by third party libraries which are also present on a page alongside rrweb diff --git a/.changeset/little-suits-leave.md b/.changeset/little-suits-leave.md deleted file mode 100644 index a1252eadb8..0000000000 --- a/.changeset/little-suits-leave.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'rrweb': minor -'@rrweb/types': minor ---- - -click events now include a `.pointerType` attribute which distinguishes between ['pen', 'mouse' and 'touch' events](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/pointerType). There is no new PenDown/PenUp events, but these can be detected with a MouseDown/MouseUp + pointerType=pen diff --git a/.changeset/loud-seals-raise.md b/.changeset/loud-seals-raise.md deleted file mode 100644 index fb7309d243..0000000000 --- a/.changeset/loud-seals-raise.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'rrweb-snapshot': patch -'rrweb': patch ---- - -Fix duplicated shadow doms diff --git a/.changeset/lovely-pears-cross.md b/.changeset/lovely-pears-cross.md deleted file mode 100644 index edf88c50fd..0000000000 --- a/.changeset/lovely-pears-cross.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rrweb/web-extension': patch ---- - -Add rrweb browser extension diff --git a/.changeset/lovely-students-boil.md b/.changeset/lovely-students-boil.md deleted file mode 100644 index 9c710bf1c6..0000000000 --- a/.changeset/lovely-students-boil.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'rrweb-snapshot': patch -'rrweb': patch ---- - -fix: Ensure attributes are lowercased when checking diff --git a/.changeset/mean-tips-impress.md b/.changeset/mean-tips-impress.md deleted file mode 100644 index b6b0022117..0000000000 --- a/.changeset/mean-tips-impress.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'rrweb': patch ---- - -perf: optimize the performance of record in processMutation phase diff --git a/.changeset/mighty-frogs-sparkle.md b/.changeset/mighty-frogs-sparkle.md deleted file mode 100644 index a845151cc8..0000000000 --- a/.changeset/mighty-frogs-sparkle.md +++ /dev/null @@ -1,2 +0,0 @@ ---- ---- diff --git a/.changeset/nervous-buses-pump.md b/.changeset/nervous-buses-pump.md deleted file mode 100644 index 49b7617159..0000000000 --- a/.changeset/nervous-buses-pump.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'rrweb': patch ---- - -fix: Resize and MediaInteraction events repeat generated after the iframe appeared diff --git a/.changeset/nervous-mirrors-perform.md b/.changeset/nervous-mirrors-perform.md deleted file mode 100644 index 46cf31fef8..0000000000 --- a/.changeset/nervous-mirrors-perform.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'rrweb-snapshot': patch -'rrweb': patch ---- - -Perf: Avoid creation of intermediary array when iterating over style rules diff --git a/.changeset/nervous-poets-grin.md b/.changeset/nervous-poets-grin.md deleted file mode 100644 index 084e1c5524..0000000000 --- a/.changeset/nervous-poets-grin.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'rrdom': patch -'rrdom-nodejs': patch -'rrweb': patch -'rrweb-player': patch -'rrweb-snapshot': patch ---- - -Refactor all suffix of bundled scripts with commonjs module from 'js' to cjs [#1087](https://github.com/rrweb-io/rrweb/pull/1087). diff --git a/.changeset/nervous-tables-travel.md b/.changeset/nervous-tables-travel.md deleted file mode 100644 index d190cbe89f..0000000000 --- a/.changeset/nervous-tables-travel.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'rrweb-snapshot': minor -'rrweb': minor ---- - -feat: Extends maskInputFn to pass the HTMLElement to the deciding function diff --git a/.changeset/new-snakes-call.md b/.changeset/new-snakes-call.md deleted file mode 100644 index c5b9e2a68e..0000000000 --- a/.changeset/new-snakes-call.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'rrweb-snapshot': minor -'rrweb': minor ---- - -feat: Ensure password inputs remain masked when switching input type diff --git a/.changeset/nice-pugs-reply.md b/.changeset/nice-pugs-reply.md deleted file mode 100644 index 04c655a67e..0000000000 --- a/.changeset/nice-pugs-reply.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'rrweb': patch ---- - -fix: Ensure getting the type of inputs works diff --git a/.changeset/old-dryers-hide.md b/.changeset/old-dryers-hide.md deleted file mode 100644 index 1b3e3399b0..0000000000 --- a/.changeset/old-dryers-hide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'rrweb-snapshot': minor ---- - -feat: Ignore `autoplay` attribute on video/audio elements diff --git a/.changeset/polite-olives-wave.md b/.changeset/polite-olives-wave.md deleted file mode 100644 index 1d3e5987f3..0000000000 --- a/.changeset/polite-olives-wave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'rrweb': patch ---- - -Add 'recordDOM' config option to turn off recording of DOM (making recordings unreplayable). Specialist use case e.g. only heatmap click/scroll recording diff --git a/.changeset/popular-spies-fetch.md b/.changeset/popular-spies-fetch.md deleted file mode 100644 index 6f2eaccb5b..0000000000 --- a/.changeset/popular-spies-fetch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'rrweb': patch ---- - -perf: only call createHTMLDocument when it is needed diff --git a/.changeset/pre.json b/.changeset/pre.json index 067c4ae386..18311ff014 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -2,77 +2,14 @@ "mode": "pre", "tag": "alpha", "initialVersions": { - "rrdom": "0.1.7", - "rrdom-nodejs": "0.1.7", - "rrweb": "2.0.0-alpha.4", - "rrweb-player": "1.0.0-alpha.4", - "rrweb-snapshot": "2.0.0-alpha.4", - "@rrweb/types": "2.0.0-alpha.4", - "@rrweb/web-extension": "2.0.0-alpha.4", - "rrvideo": "2.0.0-alpha.6" + "@amplitude/rrweb": "2.0.0-alpha.11", + "@amplitude/rrweb-snapshot": "2.0.0-alpha.11", + "@amplitude/rrdom": "2.0.0-alpha.11", + "@amplitude/rrdom-nodejs": "2.0.0-alpha.11", + "@amplitude/rrweb-player": "2.0.0-alpha.11", + "@amplitude/rrweb-types": "2.0.0-alpha.11", + "@amplitude/rrweb-web-extension": "2.0.0-alpha.11", + "@amplitude/rrvideo": "2.0.0-alpha.11" }, - "changesets": [ - "attribute-text-reductions", - "brave-numbers-joke", - "calm-bulldogs-speak", - "chatty-cherries-train", - "clean-plants-play", - "clean-shrimps-lay", - "cold-eyes-hunt", - "controller-finish-flag", - "curvy-apples-lay", - "date-now-guard", - "eight-terms-hunt", - "empty-bikes-cheer", - "fair-dragons-greet", - "fast-chefs-smell", - "few-turkeys-reflect", - "five-peas-lay", - "forty-elephants-attack", - "fresh-cars-impress", - "fresh-spoons-drive", - "gold-terms-look", - "grumpy-ways-own", - "itchy-dryers-double", - "khaki-dots-bathe", - "large-ants-prove", - "lazy-toes-confess", - "little-radios-thank", - "little-suits-leave", - "loud-seals-raise", - "lovely-pears-cross", - "lovely-students-boil", - "mean-tips-impress", - "mighty-frogs-sparkle", - "nervous-buses-pump", - "nervous-poets-grin", - "nervous-tables-travel", - "new-snakes-call", - "nice-pugs-reply", - "old-dryers-hide", - "pretty-plums-rescue", - "pretty-schools-remember", - "proud-experts-jam", - "real-masks-explode", - "real-trains-switch", - "rich-crews-protect", - "rich-jars-remember", - "serious-ants-juggle", - "sixty-impalas-laugh", - "small-olives-arrive", - "smooth-poems-bake", - "stupid-ghosts-help", - "swift-peas-film", - "thirty-baboons-punch", - "tidy-yaks-joke", - "tiny-buckets-love", - "tiny-chairs-build", - "tricky-panthers-guess", - "twenty-lies-switch", - "twenty-planets-repeat", - "violet-melons-itch", - "violet-zebras-cry", - "yellow-mails-cheat", - "young-timers-grow" - ] + "changesets": [] } diff --git a/.changeset/pretty-plums-rescue.md b/.changeset/pretty-plums-rescue.md deleted file mode 100644 index a360088cfa..0000000000 --- a/.changeset/pretty-plums-rescue.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'rrweb': minor ---- - -feat: Allow to pass `errorHandler` as record option diff --git a/.changeset/pretty-schools-remember.md b/.changeset/pretty-schools-remember.md deleted file mode 100644 index 920125d15e..0000000000 --- a/.changeset/pretty-schools-remember.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'rrweb-snapshot': patch ---- - -Improve: Add try catch to snapshot.ts 's masking text function. Fixes [#1118](https://github.com/rrweb-io/rrweb/issues/1118). diff --git a/.changeset/proud-experts-jam.md b/.changeset/proud-experts-jam.md deleted file mode 100644 index fa60839bb9..0000000000 --- a/.changeset/proud-experts-jam.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'rrweb': patch ---- - -For a mutation which removes a node, reduce the number of spurious warnings to take into account that an anscestor (rather than just a parent) may have been just removed diff --git a/.changeset/real-masks-explode.md b/.changeset/real-masks-explode.md deleted file mode 100644 index 6703435454..0000000000 --- a/.changeset/real-masks-explode.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'rrdom': patch ---- - -Fix: If RRNode appends a single child twice, children of the node will become an infinite link list. diff --git a/.changeset/real-trains-switch.md b/.changeset/real-trains-switch.md deleted file mode 100644 index 71de446836..0000000000 --- a/.changeset/real-trains-switch.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'rrdom': patch -'rrweb': patch ---- - -Fix: improve rrdom robustness [#1091](https://github.com/rrweb-io/rrweb/pull/1091). diff --git a/.changeset/rich-crews-protect.md b/.changeset/rich-crews-protect.md deleted file mode 100644 index a845151cc8..0000000000 --- a/.changeset/rich-crews-protect.md +++ /dev/null @@ -1,2 +0,0 @@ ---- ---- diff --git a/.changeset/rich-jars-remember.md b/.changeset/rich-jars-remember.md deleted file mode 100644 index efa613f772..0000000000 --- a/.changeset/rich-jars-remember.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'rrweb-snapshot': patch ---- - -Add workaround for Chrome/Edge CSS `@import` escaping bug: https://bugs.chromium.org/p/chromium/issues/detail?id=1472259 diff --git a/.changeset/serious-ants-juggle.md b/.changeset/serious-ants-juggle.md deleted file mode 100644 index e475e12267..0000000000 --- a/.changeset/serious-ants-juggle.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -'rrdom': major -'rrdom-nodejs': major -'rrweb': patch ---- - -Refactor: Improve performance by 80% in a super large benchmark case. - -1. Refactor: change the data structure of childNodes from array to linked list -2. Improve the performance of the "contains" function. New algorithm will reduce the complexity from O(n) to O(logn) diff --git a/.changeset/sixty-impalas-laugh.md b/.changeset/sixty-impalas-laugh.md deleted file mode 100644 index 95d8d26362..0000000000 --- a/.changeset/sixty-impalas-laugh.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'rrweb': patch ---- - -Only apply touch-active styling on flush diff --git a/.changeset/small-olives-arrive.md b/.changeset/small-olives-arrive.md deleted file mode 100644 index 36bacbc168..0000000000 --- a/.changeset/small-olives-arrive.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'rrweb-snapshot': patch ---- - -Fix: [#1172](https://github.com/rrweb-io/rrweb/issues/1172) don't replace original onload function of Images diff --git a/.changeset/smooth-poems-bake.md b/.changeset/smooth-poems-bake.md deleted file mode 100644 index 9d4fac8ff6..0000000000 --- a/.changeset/smooth-poems-bake.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'rrweb-player': patch ---- - -Fix `player.getMirror`, `player.playRange`, `player.$set` types in rrwebPlayer diff --git a/.changeset/stupid-ghosts-help.md b/.changeset/stupid-ghosts-help.md deleted file mode 100644 index efc09cd873..0000000000 --- a/.changeset/stupid-ghosts-help.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'rrweb': patch ---- - -Fix: isCheckout is missed in all fullsnapshot events diff --git a/.changeset/swift-dancers-rest.md b/.changeset/swift-dancers-rest.md deleted file mode 100644 index bcedf6c875..0000000000 --- a/.changeset/swift-dancers-rest.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'rrweb-snapshot': minor -'rrweb': minor ---- - -Extends maskTextFn to pass the HTMLElement to the deciding function diff --git a/.changeset/swift-peas-film.md b/.changeset/swift-peas-film.md deleted file mode 100644 index 058b1412e3..0000000000 --- a/.changeset/swift-peas-film.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'rrweb-snapshot': patch -'rrweb': patch ---- - -fix: Explicitly handle `null` attribute values diff --git a/.changeset/thirty-baboons-punch.md b/.changeset/thirty-baboons-punch.md deleted file mode 100644 index 1dd1c36fad..0000000000 --- a/.changeset/thirty-baboons-punch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'rrweb-snapshot': patch ---- - -Fix CSS rules captured in Safari diff --git a/.changeset/tidy-yaks-joke.md b/.changeset/tidy-yaks-joke.md deleted file mode 100644 index bcd476a850..0000000000 --- a/.changeset/tidy-yaks-joke.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'rrweb': patch ---- - -Fix: outdated ':hover' styles can't be removed from iframes or shadow doms diff --git a/.changeset/tiny-buckets-love.md b/.changeset/tiny-buckets-love.md deleted file mode 100644 index 1f67b3f465..0000000000 --- a/.changeset/tiny-buckets-love.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'rrweb': patch ---- - -Handle case where `event` is null/undefined diff --git a/.changeset/tiny-chairs-build.md b/.changeset/tiny-chairs-build.md deleted file mode 100644 index 0e76e26814..0000000000 --- a/.changeset/tiny-chairs-build.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'rrweb': patch ---- - -Canvas FPS recording: override `preserveDrawingBuffer: true` on canvas creation. -Canvas replay: fix flickering canvas elemenrs. -Canvas FPS recording: fix bug that wipes webgl(2) canvas backgrounds while recording. diff --git a/.changeset/tricky-panthers-guess.md b/.changeset/tricky-panthers-guess.md deleted file mode 100644 index 3dfadbaed3..0000000000 --- a/.changeset/tricky-panthers-guess.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'rrvideo': patch ---- - -Refactor: Move rrvideo to rrweb's monorepo diff --git a/.changeset/twenty-lies-switch.md b/.changeset/twenty-lies-switch.md deleted file mode 100644 index de44679861..0000000000 --- a/.changeset/twenty-lies-switch.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -'rrweb': patch ---- - -Add missing change logs manually. In the next version, all change logs will be generated automatically. - -- [`a220835`](https://github.com/rrweb-io/rrweb/commit/a220835eeb81ca4f294682e060d46c8853720d7f) [#1053](https://github.com/rrweb-io/rrweb/pull/1053) Thanks [@Juice10](https://github.com/Juice10)! - Fix: Post message can break cross origin iframe recording. - -- [`7e8dcdb`](https://github.com/rrweb-io/rrweb/commit/7e8dcdb11dc5dfefcdd19ff5e13ec9d8b5c24dcc) [#1063](https://github.com/rrweb-io/rrweb/pull/1063) Thanks [@lele0108](https://github.com/lele0108)! - Fix: muted false -> true not being set. - -- [`b655361`](https://github.com/rrweb-io/rrweb/commit/b655361a5f0d50a053fcd0e5c823b8494c33b89c) [#1067](https://github.com/rrweb-io/rrweb/pull/1067) Thanks [@mydea](https://github.com/mydea)! - Export recordOptions type. - -- [`36b44e1`](https://github.com/rrweb-io/rrweb/commit/36b44e104b91fc74c3e69684111240cd23105340) [#1042](https://github.com/rrweb-io/rrweb/pull/1042) Thanks [@wfk007](https://github.com/wfk007)! - Fix: Failed to execute insertBefore on Node. - -- [`44e92cb`](https://github.com/rrweb-io/rrweb/commit/44e92cbff981c36e754dfcb9a184eae9e7292ecf) [#1058](https://github.com/rrweb-io/rrweb/pull/1058) Thanks [@mydea](https://github.com/mydea)! - Handle errors when observing iframes. - -- [`729b8bf`](https://github.com/rrweb-io/rrweb/commit/729b8bf38c8c7f2e1b22b4e0f7cab14f0807bc74) [#1083](https://github.com/rrweb-io/rrweb/pull/1083) Thanks [@Juice10](https://github.com/Juice10)! - Fix: Catch iframe manager & fix formatting issues. - -- [`03821d9`](https://github.com/rrweb-io/rrweb/commit/03821d9b9fa0513e6e373881d43102ceb9388340) [#1083](https://github.com/rrweb-io/rrweb/pull/1083) Thanks [@eoghanmurray](https://github.com/eoghanmurray)! - Harmonize on a single getWindowScroll - -- [`d08913d`](https://github.com/rrweb-io/rrweb/commit/d08913d0dc506dbf119e94686fe5f01c415316c9) [#1086](https://github.com/rrweb-io/rrweb/pull/1086) Thanks [@YunFeng0817](https://github.com/YunFeng0817)! - Fix: missed adopted style sheets of shadow doms in checkout full snapshot. - -- [`66abe17`](https://github.com/rrweb-io/rrweb/commit/66abe17832dbb23b3948af1c394f9a02caccc17b) [#1032](https://github.com/rrweb-io/rrweb/pull/1032) Thanks [@dbseel](https://github.com/dbseel)! - Fix: isBlocked throws on invalid HTML element. - -- [`07aa1b2`](https://github.com/rrweb-io/rrweb/commit/07aa1b2807da5a9a1db678ebc3ff59320a300d06) [#1049](https://github.com/rrweb-io/rrweb/pull/1049) Thanks [@Juice10](https://github.com/Juice10)! - Fix: shadow dom bugs. - -- [`57a2e14`](https://github.com/rrweb-io/rrweb/commit/57a2e140ea419f7790b1672529f21dfe2261b52b) [#1088](https://github.com/rrweb-io/rrweb/pull/1088) Thanks [@mydea](https://github.com/mydea)! - Fix: Guard against missing window.CSSStyleSheet. - -- [`fc82869`](https://github.com/rrweb-io/rrweb/commit/fc828694099b87b4d811e6b651a7bb4c7499b896) [#1093](https://github.com/rrweb-io/rrweb/pull/1093) Thanks [@YunFeng0817](https://github.com/YunFeng0817)! - Fix: cross origin iframe bugs. - -- [`a77e302`](https://github.com/rrweb-io/rrweb/commit/a77e30217893e63f8025c73afc3ac1ba294d7761) [#1104](https://github.com/rrweb-io/rrweb/pull/1104) Thanks [@jlalmes](https://github.com/jlalmes)! - [console-plugin] Feat: Record unhandled rejection event. - -- [`25a4f5a`](https://github.com/rrweb-io/rrweb/commit/25a4f5ab6c7311f2e8e5e1a4d232c2820adf910e) [#1115](https://github.com/rrweb-io/rrweb/pull/1115) Thanks [@Juice10](https://github.com/Juice10)! - Fix: Don't trigger Finish event when in liveMode. - -- [`cb15800`](https://github.com/rrweb-io/rrweb/commit/cb1580008d04b0bc5c5d4ebec0e2e79899faaeb6) [#1106](https://github.com/rrweb-io/rrweb/pull/1106) Thanks [@mydea](https://github.com/mydea)! - Fix: Ensure CSS support is checked more robustly. - -- [`0732618`](https://github.com/rrweb-io/rrweb/commit/07326182f9750646771918481f116b946a17c2a9) [#1100](https://github.com/rrweb-io/rrweb/pull/1100) Thanks [@YunFeng0817](https://github.com/YunFeng0817)! - Fix: wrong rootId value in special iframes. - -- [`3caa25e`](https://github.com/rrweb-io/rrweb/commit/3caa25ed9b19954c98775f22d5fa47233fa3d1db) [#1098](https://github.com/rrweb-io/rrweb/pull/1098) Thanks [@eoghanmurray](https://github.com/eoghanmurray)! - Refactor: Don't have requestAnimationFrame looping in background for Live Mode. - -- [`3a26e36`](https://github.com/rrweb-io/rrweb/commit/3a26e36f6f625c0391c7e6d3f1050660adfccc4f) [#1092](https://github.com/rrweb-io/rrweb/pull/1092) Thanks [@YunFeng0817](https://github.com/YunFeng0817)! - Fix: regression of issue: ShadowHost can't be a string (issue 941) - -- [`07d22e7`](https://github.com/rrweb-io/rrweb/commit/07d22e7cd999a48e7371aaef1b979574bb746500) [#1111](https://github.com/rrweb-io/rrweb/pull/1111) Thanks [@YunFeng0817](https://github.com/YunFeng0817)! - Feat: enable to customize logger in the replayer. - -- [`0627d4d`](https://github.com/rrweb-io/rrweb/commit/0627d4df7cc76cde7babbd37ab8e3da5810fb51d) [#1109](https://github.com/rrweb-io/rrweb/pull/1109) Thanks [@YunFeng0817](https://github.com/YunFeng0817)! - Feat: add option to record on DOMContentLoaded event. - -- [`174b9ac`](https://github.com/rrweb-io/rrweb/commit/174b9ac066565b8c065f40f0303189f10c7c4efb) [#1112](https://github.com/rrweb-io/rrweb/pull/1112) Thanks [@YunFeng0817](https://github.com/YunFeng0817)! - Fix: mutation Failed to execute 'insertBefore' on 'Node': Only one doctype on document allowed. - -- [`5a1e5e9`](https://github.com/rrweb-io/rrweb/commit/5a1e5e919e3f8bef48d142115c0afd5706a442b5) [#1119](https://github.com/rrweb-io/rrweb/pull/1119) Thanks [@Juice10](https://github.com/Juice10)! - Feat: Automate NPM package releases. diff --git a/.changeset/twenty-planets-repeat.md b/.changeset/twenty-planets-repeat.md deleted file mode 100644 index a845151cc8..0000000000 --- a/.changeset/twenty-planets-repeat.md +++ /dev/null @@ -1,2 +0,0 @@ ---- ---- diff --git a/.changeset/violet-melons-itch.md b/.changeset/violet-melons-itch.md deleted file mode 100644 index af7f60957f..0000000000 --- a/.changeset/violet-melons-itch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'rrweb': patch ---- - -fix: Recursive logging bug with console recording diff --git a/.changeset/violet-zebras-cry.md b/.changeset/violet-zebras-cry.md deleted file mode 100644 index 5f4c5244c8..0000000000 --- a/.changeset/violet-zebras-cry.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'rrweb': patch ---- - -Trigger mouse movement and hover with mouse up and mouse down events when replayer.pause(...) is called. diff --git a/.changeset/yellow-mails-cheat.md b/.changeset/yellow-mails-cheat.md deleted file mode 100644 index 2894696782..0000000000 --- a/.changeset/yellow-mails-cheat.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'rrweb': patch ---- - -Fix: some websites rebuild imcomplete - -1. Some websites, addedSet in emit function is not empty, but the result converted from Array.from is empty. -2. Some websites polyfill classList functions of HTML elements. Their implementation may throw errors and cause the snapshot to fail. I add try-catch statements to make the code robust. diff --git a/.changeset/young-timers-grow.md b/.changeset/young-timers-grow.md deleted file mode 100644 index 4c710b3d3b..0000000000 --- a/.changeset/young-timers-grow.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'rrweb': patch ---- - -For users of userTriggeredOnInput setting: also set userTriggered to false on Input attribute modifications; this was previously empty this variant of IncrementalSource.Input From 2dd990cbcfbaf5e552816379115608a9762e1b45 Mon Sep 17 00:00:00 2001 From: Kelly Wallach Date: Mon, 23 Oct 2023 15:57:42 -0400 Subject: [PATCH 10/66] Add our changesets --- .changeset/octopus-orange.md | 5 ++++ .changeset/popular-spies-fetch.md | 5 ++++ yarn.lock | 48 ++++++++++++++++++++++++++++++- 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 .changeset/octopus-orange.md create mode 100644 .changeset/popular-spies-fetch.md diff --git a/.changeset/octopus-orange.md b/.changeset/octopus-orange.md new file mode 100644 index 0000000000..4282061958 --- /dev/null +++ b/.changeset/octopus-orange.md @@ -0,0 +1,5 @@ +--- +'rrweb': patch +--- + +feat: skip through inactive periods instead of fast forward diff --git a/.changeset/popular-spies-fetch.md b/.changeset/popular-spies-fetch.md new file mode 100644 index 0000000000..6f2eaccb5b --- /dev/null +++ b/.changeset/popular-spies-fetch.md @@ -0,0 +1,5 @@ +--- +'rrweb': patch +--- + +perf: only call createHTMLDocument when it is needed diff --git a/yarn.lock b/yarn.lock index 34c29fb6fe..b347ea7a0c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3058,6 +3058,13 @@ estree-walker "^2.0.2" picomatch "^2.3.1" +"@rrweb/types@^2.0.0-alpha.11": + version "2.0.0-alpha.11" + resolved "https://registry.yarnpkg.com/@rrweb/types/-/types-2.0.0-alpha.11.tgz#30730ac4b619a698d910f391992be8682286b8c8" + integrity sha512-8ccocIkT5J/bfNRQY85qR/g6p5YQFpgFO2cMt4+Ex7w31Lq0yqZBRaoYEsawQKpLrn5KOHkdn2UTUrna7WMQuA== + dependencies: + rrweb-snapshot "^2.0.0-alpha.11" + "@rushstack/node-core-library@3.59.0": version "3.59.0" resolved "https://registry.yarnpkg.com/@rushstack/node-core-library/-/node-core-library-3.59.0.tgz#f04db22575a242c30114b4723ba0580b6f2d8c85" @@ -5522,10 +5529,15 @@ csso@^4.0.2: dependencies: css-tree "^1.1.2" -cssom@^0.4.4, cssom@^0.5.0, "cssom@https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz": +cssom@^0.4.4, "cssom@https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz": version "0.6.0" resolved "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz#ed298055b97cbddcdeb278f904857629dec5e0e1" +cssom@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.5.0.tgz#d254fa92cd8b6fbd83811b9fbaed34663cc17c36" + integrity sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw== + cssom@~0.3.6: version "0.3.8" resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" @@ -13060,6 +13072,40 @@ rollup@~2.78.0: optionalDependencies: fsevents "~2.3.2" +rrdom@^2.0.0-alpha.11: + version "2.0.0-alpha.11" + resolved "https://registry.yarnpkg.com/rrdom/-/rrdom-2.0.0-alpha.11.tgz#4f0ca9ecbf22afd317e759762a354350cd4d9986" + integrity sha512-U37m0t4jTz63wnVRcOQ5qFzSTrI5RdNgeXnHAha2Fmh9+1K+XuCx421a8D1wZk3WcDc2sFz/04FVdM0OD2caHg== + dependencies: + rrweb-snapshot "^2.0.0-alpha.11" + +rrweb-player@^2.0.0-alpha.11: + version "2.0.0-alpha.11" + resolved "https://registry.yarnpkg.com/rrweb-player/-/rrweb-player-2.0.0-alpha.11.tgz#fa3676b81253c7d09147c5a32c05b1efa1b14d4b" + integrity sha512-l4PV5RvZ31TqbT3BhgNFmYgI7863xHlqqI+eItXnHmsmwc4JMBig0sq7/JnH8Z7tTnd6lJUgU2lZ8YfY29sKaw== + dependencies: + "@tsconfig/svelte" "^1.0.0" + rrweb "^2.0.0-alpha.11" + +rrweb-snapshot@^2.0.0-alpha.11: + version "2.0.0-alpha.11" + resolved "https://registry.yarnpkg.com/rrweb-snapshot/-/rrweb-snapshot-2.0.0-alpha.11.tgz#5ce031181ac1ac182ce6706369f77824e2bea17a" + integrity sha512-N0dzeJA2VhrlSOadkKwCVmV/DuNOwBH+Lhx89hAf9PQK4lCS8AP4AaylhqUdZOYHqwVjqsYel/uZ4hN79vuLhw== + +rrweb@^2.0.0-alpha.11: + version "2.0.0-alpha.11" + resolved "https://registry.yarnpkg.com/rrweb/-/rrweb-2.0.0-alpha.11.tgz#1f8a1944e20fd5f3ddc11634a25df2f3832914d7" + integrity sha512-vJ2gNvF+pUG9C2aaau7iSNqhWBSc4BwtUO4FpegOtDObuH4PIaxNJOlgHz82+WxKr9XPm93ER0LqmNpy0KYdKg== + dependencies: + "@rrweb/types" "^2.0.0-alpha.11" + "@types/css-font-loading-module" "0.0.7" + "@xstate/fsm" "^1.4.0" + base64-arraybuffer "^1.0.1" + fflate "^0.4.4" + mitt "^3.0.0" + rrdom "^2.0.0-alpha.11" + rrweb-snapshot "^2.0.0-alpha.11" + run-async@^2.4.0: version "2.4.1" resolved "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz" From 7f0338ada3e0035ba2ba2028ab523510b8d91b14 Mon Sep 17 00:00:00 2001 From: Kelly Wallach Date: Mon, 23 Oct 2023 15:59:49 -0400 Subject: [PATCH 11/66] Fix package name --- .changeset/octopus-orange.md | 2 +- .changeset/popular-spies-fetch.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.changeset/octopus-orange.md b/.changeset/octopus-orange.md index 4282061958..d69b608582 100644 --- a/.changeset/octopus-orange.md +++ b/.changeset/octopus-orange.md @@ -1,5 +1,5 @@ --- -'rrweb': patch +'@amplitude/rrweb': patch --- feat: skip through inactive periods instead of fast forward diff --git a/.changeset/popular-spies-fetch.md b/.changeset/popular-spies-fetch.md index 6f2eaccb5b..419c43dced 100644 --- a/.changeset/popular-spies-fetch.md +++ b/.changeset/popular-spies-fetch.md @@ -1,5 +1,5 @@ --- -'rrweb': patch +'@amplitude/rrweb': patch --- perf: only call createHTMLDocument when it is needed From a5a7fb73f948deb7281baae971fd2fe2e01dc233 Mon Sep 17 00:00:00 2001 From: Kelly Wallach Date: Tue, 24 Oct 2023 10:54:39 -0400 Subject: [PATCH 12/66] Updating package references and tests --- lerna.json | 3 + packages/rrdom-nodejs/package.json | 6 +- packages/rrdom-nodejs/src/document-nodejs.ts | 10 +- .../rrdom-nodejs/test/document-nodejs.test.ts | 4 +- packages/rrdom-nodejs/tsconfig.json | 9 +- packages/rrdom/package.json | 4 +- packages/rrdom/rollup.config.js | 4 +- packages/rrdom/src/diff.ts | 30 ++--- packages/rrdom/src/document.ts | 6 +- packages/rrdom/src/index.ts | 32 ++--- packages/rrdom/test/diff.test.ts | 34 +++--- packages/rrdom/test/document.test.ts | 4 +- packages/rrdom/test/virtual-dom.test.ts | 10 +- packages/rrdom/tsconfig.json | 9 +- packages/rrvideo/package.json | 8 +- packages/rrvideo/src/cli.ts | 6 +- packages/rrvideo/src/index.ts | 6 +- packages/rrvideo/test/events/example.ts | 4 +- packages/rrvideo/tsconfig.json | 8 +- packages/rrweb-player/package.json | 4 +- packages/rrweb-player/src/Controller.svelte | 8 +- packages/rrweb-player/src/Player.svelte | 4 +- packages/rrweb-player/src/main.ts | 2 +- packages/rrweb-player/src/utils.ts | 8 +- packages/rrweb-player/tsconfig.json | 4 +- packages/rrweb-player/typings/index.d.ts | 8 +- packages/rrweb-snapshot/test/utils.test.ts | 2 +- packages/rrweb/package.json | 8 +- packages/rrweb/src/index.ts | 8 +- packages/rrweb/src/packer/base.ts | 2 +- packages/rrweb/src/packer/unpack.ts | 4 +- .../src/plugins/canvas-webrtc/record/index.ts | 7 +- .../src/plugins/canvas-webrtc/replay/index.ts | 4 +- .../rrweb/src/plugins/console/record/index.ts | 6 +- .../rrweb/src/plugins/console/replay/index.ts | 6 +- .../src/plugins/sequential-id/record/index.ts | 2 +- .../src/plugins/sequential-id/replay/index.ts | 4 +- .../src/record/cross-origin-iframe-mirror.ts | 2 +- packages/rrweb/src/record/iframe-manager.ts | 8 +- packages/rrweb/src/record/index.ts | 50 ++++---- packages/rrweb/src/record/mutation.ts | 18 +-- packages/rrweb/src/record/observer.ts | 74 ++++++------ .../rrweb/src/record/observers/canvas/2d.ts | 3 +- .../record/observers/canvas/canvas-manager.ts | 18 +-- .../src/record/observers/canvas/canvas.ts | 8 +- .../record/observers/canvas/serialize-args.ts | 2 +- .../src/record/observers/canvas/webgl.ts | 4 +- .../rrweb/src/record/shadow-dom-manager.ts | 14 +-- .../rrweb/src/record/stylesheet-manager.ts | 9 +- .../workers/image-bitmap-data-url-worker.ts | 6 +- packages/rrweb/src/replay/canvas/2d.ts | 2 +- .../src/replay/canvas/deserialize-args.ts | 2 +- packages/rrweb/src/replay/canvas/index.ts | 6 +- packages/rrweb/src/replay/canvas/webgl.ts | 2 +- packages/rrweb/src/replay/index.ts | 114 +++++++++--------- packages/rrweb/src/replay/machine.ts | 12 +- packages/rrweb/src/replay/timer.ts | 6 +- packages/rrweb/src/types.ts | 34 +++--- packages/rrweb/src/utils.ts | 26 ++-- .../rrweb/test/benchmark/dom-mutation.test.ts | 4 +- .../benchmark/replay-fast-forward.test.ts | 6 +- packages/rrweb/test/e2e/webgl.test.ts | 14 +-- .../adopted-style-sheet-modification.ts | 4 +- .../rrweb/test/events/adopted-style-sheet.ts | 4 +- .../rrweb/test/events/canvas-in-iframe.ts | 4 +- .../rrweb/test/events/document-replacement.ts | 4 +- packages/rrweb/test/events/hover.ts | 2 +- .../test/events/iframe-shadowdom-hover.ts | 4 +- packages/rrweb/test/events/iframe.ts | 4 +- packages/rrweb/test/events/input.ts | 4 +- packages/rrweb/test/events/ordering.ts | 4 +- packages/rrweb/test/events/scroll.ts | 4 +- packages/rrweb/test/events/selection.ts | 4 +- packages/rrweb/test/events/shadow-dom.ts | 4 +- .../test/events/style-sheet-rule-events.ts | 4 +- .../test/events/style-sheet-text-mutation.ts | 4 +- packages/rrweb/test/integration.test.ts | 16 +-- packages/rrweb/test/machine.test.ts | 2 +- packages/rrweb/test/packer.test.ts | 2 +- packages/rrweb/test/record.test.ts | 20 +-- .../test/record/cross-origin-iframes.test.ts | 16 +-- .../rrweb/test/record/error-handler.test.ts | 10 +- packages/rrweb/test/record/webgl.test.ts | 16 +-- .../test/replay/preload-all-images.test.ts | 8 +- .../rrweb/test/replay/webgl-mutation.test.ts | 4 +- packages/rrweb/test/replayer.test.ts | 32 ++--- packages/rrweb/test/utils.ts | 18 +-- packages/rrweb/tsconfig.json | 4 +- packages/types/package.json | 10 +- packages/types/src/index.ts | 8 +- packages/types/tsconfig.json | 13 +- packages/web-extension/package.json | 8 +- .../web-extension/src/background/index.ts | 4 +- packages/web-extension/src/content/index.ts | 14 +-- packages/web-extension/src/content/inject.ts | 6 +- packages/web-extension/src/pages/Player.tsx | 6 +- packages/web-extension/src/types.ts | 2 +- packages/web-extension/src/utils/recording.ts | 4 +- packages/web-extension/src/utils/storage.ts | 2 +- packages/web-extension/tsconfig.json | 14 ++- yarn.lock | 41 ------- 101 files changed, 543 insertions(+), 523 deletions(-) diff --git a/lerna.json b/lerna.json index cfec287607..3c8f913582 100644 --- a/lerna.json +++ b/lerna.json @@ -1,4 +1,7 @@ { + "packages": [ + "packages/*" + ], "version": "independent", "npmClient": "yarn", "useWorkspaces": true, diff --git a/packages/rrdom-nodejs/package.json b/packages/rrdom-nodejs/package.json index 6edbd703a0..b157522848 100644 --- a/packages/rrdom-nodejs/package.json +++ b/packages/rrdom-nodejs/package.json @@ -45,11 +45,11 @@ "ts-jest": "^27.1.3" }, "dependencies": { + "@amplitude/rrdom": "^2.0.0-alpha.11", + "@amplitude/rrweb-snapshot": "^2.0.0-alpha.11", "cssom": "^0.5.0", "cssstyle": "^2.3.0", - "nwsapi": "^2.2.0", - "rrdom": "^2.0.0-alpha.11", - "rrweb-snapshot": "^2.0.0-alpha.11" + "nwsapi": "^2.2.0" }, "browserslist": [ "supports es6-class" diff --git a/packages/rrdom-nodejs/src/document-nodejs.ts b/packages/rrdom-nodejs/src/document-nodejs.ts index 1d13970d34..1e42cee24b 100644 --- a/packages/rrdom-nodejs/src/document-nodejs.ts +++ b/packages/rrdom-nodejs/src/document-nodejs.ts @@ -1,7 +1,4 @@ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ -import { NodeType as RRNodeType } from 'rrweb-snapshot'; -import type { NWSAPI } from 'nwsapi'; -import type { CSSStyleDeclaration as CSSStyleDeclarationType } from 'cssstyle'; import { BaseRRCDATASectionImpl, BaseRRCommentImpl, @@ -11,10 +8,13 @@ import { BaseRRMediaElementImpl, BaseRRNode, BaseRRTextImpl, + CSSStyleDeclaration, ClassList, IRRDocument, - CSSStyleDeclaration, -} from 'rrdom'; +} from '@amplitude/rrdom'; +import { NodeType as RRNodeType } from '@amplitude/rrweb-snapshot'; +import type { CSSStyleDeclaration as CSSStyleDeclarationType } from 'cssstyle'; +import type { NWSAPI } from 'nwsapi'; // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires const nwsapi = require('nwsapi'); // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires diff --git a/packages/rrdom-nodejs/test/document-nodejs.test.ts b/packages/rrdom-nodejs/test/document-nodejs.test.ts index ba3c6144d8..b310291cce 100644 --- a/packages/rrdom-nodejs/test/document-nodejs.test.ts +++ b/packages/rrdom-nodejs/test/document-nodejs.test.ts @@ -1,9 +1,10 @@ /** * @jest-environment jsdom */ +import { buildFromDom } from '@amplitude/rrdom'; +import { NodeType as RRNodeType } from '@amplitude/rrweb-snapshot'; import * as fs from 'fs'; import * as path from 'path'; -import { NodeType as RRNodeType } from 'rrweb-snapshot'; import { RRCanvasElement, RRCDATASection, @@ -16,7 +17,6 @@ import { RRStyleElement, RRText, } from '../src/document-nodejs'; -import { buildFromDom } from 'rrdom'; describe('RRDocument for nodejs environment', () => { describe('RRDocument API', () => { diff --git a/packages/rrdom-nodejs/tsconfig.json b/packages/rrdom-nodejs/tsconfig.json index 0c2f119853..88f7b03681 100644 --- a/packages/rrdom-nodejs/tsconfig.json +++ b/packages/rrdom-nodejs/tsconfig.json @@ -10,13 +10,18 @@ "sourceMap": true, "rootDir": "src", "outDir": "build", - "lib": ["es6", "dom"], + "lib": [ + "es6", + "dom" + ], "skipLibCheck": true, "declaration": true, "importsNotUsedAsValues": "error" }, "compileOnSave": true, - "exclude": ["test"], + "exclude": [ + "test" + ], "include": [ "src", "test.d.ts", diff --git a/packages/rrdom/package.json b/packages/rrdom/package.json index b7fa09659c..e19cea4c72 100644 --- a/packages/rrdom/package.json +++ b/packages/rrdom/package.json @@ -31,8 +31,8 @@ "url": "https://github.com/rrweb-io/rrweb/issues" }, "devDependencies": { + "@amplitude/rrweb-types": "^2.0.0-alpha.11", "@rollup/plugin-commonjs": "^20.0.0", - "@rrweb/types": "^2.0.0-alpha.11", "@types/jest": "^27.4.1", "@types/puppeteer": "^5.4.4", "@typescript-eslint/eslint-plugin": "^5.23.0", @@ -47,6 +47,6 @@ "ts-jest": "^27.1.3" }, "dependencies": { - "rrweb-snapshot": "^2.0.0-alpha.11" + "@amplitude/rrweb-snapshot": "^2.0.0-alpha.11" } } diff --git a/packages/rrdom/rollup.config.js b/packages/rrdom/rollup.config.js index 5bd346673f..7c95b9db8d 100644 --- a/packages/rrdom/rollup.config.js +++ b/packages/rrdom/rollup.config.js @@ -1,5 +1,5 @@ -import resolve from '@rollup/plugin-node-resolve'; import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; import { terser } from 'rollup-plugin-terser'; import typescript from 'rollup-plugin-typescript2'; import webWorkerLoader from 'rollup-plugin-web-worker-loader'; @@ -24,7 +24,7 @@ const basePlugins = [ const baseConfigs = [ { input: './src/index.ts', - name: pkg.name, + name: 'rrdom', path: pkg.name, }, ]; diff --git a/packages/rrdom/src/diff.ts b/packages/rrdom/src/diff.ts index f37f298106..3438cb79ed 100644 --- a/packages/rrdom/src/diff.ts +++ b/packages/rrdom/src/diff.ts @@ -1,16 +1,25 @@ import { - NodeType as RRNodeType, Mirror as NodeMirror, + NodeType as RRNodeType, elementNode, -} from 'rrweb-snapshot'; +} from '@amplitude/rrweb-snapshot'; import type { - canvasMutationData, canvasEventWithTime, + canvasMutationData, inputData, scrollData, styleDeclarationData, styleSheetRuleData, -} from '@rrweb/types'; +} from '@amplitude/rrweb-types'; +import type { + Mirror, + RRCanvasElement, + RRDocument, + RRElement, + RRIFrameElement, + RRMediaElement, + RRStyleElement, +} from '.'; import type { IRRCDATASection, IRRComment, @@ -19,15 +28,6 @@ import type { IRRNode, IRRText, } from './document'; -import type { - RRCanvasElement, - RRElement, - RRIFrameElement, - RRMediaElement, - RRStyleElement, - RRDocument, - Mirror, -} from '.'; const NAMESPACES: Record = { svg: 'http://www.w3.org/2000/svg', @@ -88,11 +88,11 @@ export type ReplayerHandler = { data: styleDeclarationData | styleSheetRuleData, styleSheet: CSSStyleSheet, ) => void; - // Similar to the `afterAppend` callback in the `rrweb-snapshot` package. It's a postorder traversal of the newly appended nodes. + // Similar to the `afterAppend` callback in the `@amplitude/rrweb-snapshot` package. It's a postorder traversal of the newly appended nodes. afterAppend?(node: Node, id: number): void; }; -// A set contains newly appended nodes. It's used to make sure the afterAppend callback can iterate newly appended nodes in the same traversal order as that in the `rrweb-snapshot` package. +// A set contains newly appended nodes. It's used to make sure the afterAppend callback can iterate newly appended nodes in the same traversal order as that in the `@amplitude/rrweb-snapshot` package. let createdNodeSet: WeakSet | null = null; /** diff --git a/packages/rrdom/src/document.ts b/packages/rrdom/src/document.ts index a053009a76..8a9a3c3b2e 100644 --- a/packages/rrdom/src/document.ts +++ b/packages/rrdom/src/document.ts @@ -1,5 +1,5 @@ -import { NodeType as RRNodeType } from 'rrweb-snapshot'; -import { parseCSSText, camelize, toCSSText } from './style'; +import { NodeType as RRNodeType } from '@amplitude/rrweb-snapshot'; +import { camelize, parseCSSText, toCSSText } from './style'; export interface IRRNode { parentElement: IRRNode | null; parentNode: IRRNode | null; @@ -308,7 +308,7 @@ export function BaseRRDocumentImpl< } /** - * Adhoc implementation for setting xhtml namespace in rebuilt.ts (rrweb-snapshot). + * Adhoc implementation for setting xhtml namespace in rebuilt.ts (@amplitude/rrweb-snapshot). * There are two lines used this function: * 1. doc.write('\') * 2. doc.write('\') diff --git a/packages/rrdom/src/index.ts b/packages/rrdom/src/index.ts index eeddb03e1c..e345ce73bd 100644 --- a/packages/rrdom/src/index.ts +++ b/packages/rrdom/src/index.ts @@ -1,22 +1,21 @@ -import { - NodeType as RRNodeType, - createMirror as createNodeMirror, -} from 'rrweb-snapshot'; import type { - Mirror as NodeMirror, IMirror, + Mirror as NodeMirror, serializedNodeWithId, -} from 'rrweb-snapshot'; +} from '@amplitude/rrweb-snapshot'; +import { + NodeType as RRNodeType, + createMirror as createNodeMirror, +} from '@amplitude/rrweb-snapshot'; import type { - canvasMutationData, canvasEventWithTime, + canvasMutationData, inputData, scrollData, - styleSheetRuleData, styleDeclarationData, -} from '@rrweb/types'; + styleSheetRuleData, +} from '@amplitude/rrweb-types'; import { - BaseRRNode as RRNode, BaseRRCDATASectionImpl, BaseRRCommentImpl, BaseRRDocumentImpl, @@ -24,13 +23,14 @@ import { BaseRRElementImpl, BaseRRMediaElementImpl, BaseRRTextImpl, + IRRComment, IRRDocument, + IRRDocumentType, IRRElement, IRRNode, - NodeType, - IRRDocumentType, IRRText, - IRRComment, + NodeType, + BaseRRNode as RRNode, } from './document'; export class RRDocument extends BaseRRDocumentImpl(RRNode) { @@ -198,7 +198,7 @@ type RRElementType = K extends keyof RRElementTagNameMap ? RRElementTagNameMap[K] : RRElement; function getValidTagName(element: HTMLElement): string { - // https://github.com/rrweb-io/rrweb-snapshot/issues/56 + // https://github.com/rrweb-io/@amplitude/rrweb-snapshot/issues/56 if (element instanceof HTMLFormElement) { return 'FORM'; } @@ -338,7 +338,7 @@ export function createMirror(): Mirror { return new Mirror(); } -// based on Mirror from rrweb-snapshots +// based on Mirror from @amplitude/rrweb-snapshots export class Mirror implements IMirror { private idNodeMap: Map = new Map(); private nodeMetaMap: WeakMap = new WeakMap(); @@ -483,5 +483,5 @@ function walk(node: IRRNode, mirror: IMirror, blankSpace: string) { export { RRNode }; -export { diff, createOrGetNode, ReplayerHandler } from './diff'; +export { ReplayerHandler, createOrGetNode, diff } from './diff'; export * from './document'; diff --git a/packages/rrdom/test/diff.test.ts b/packages/rrdom/test/diff.test.ts index 3f18a6ee7e..0efc928f07 100644 --- a/packages/rrdom/test/diff.test.ts +++ b/packages/rrdom/test/diff.test.ts @@ -1,38 +1,38 @@ /** * @jest-environment jsdom */ -import * as path from 'path'; -import * as puppeteer from 'puppeteer'; +import { Replayer } from '@amplitude/rrweb'; import { + Mirror as NodeMirror, NodeType as RRNodeType, - serializedNodeWithId, createMirror, - Mirror as NodeMirror, -} from 'rrweb-snapshot'; + serializedNodeWithId, +} from '@amplitude/rrweb-snapshot'; +import type { + canvasMutationData, + eventWithTime, + styleDeclarationData, + styleSheetRuleData, +} from '@amplitude/rrweb-types'; +import { EventType, IncrementalSource } from '@amplitude/rrweb-types'; +import * as path from 'path'; +import * as puppeteer from 'puppeteer'; import { - buildFromDom, - getDefaultSN, - Mirror as RRNodeMirror, RRDocument, RRMediaElement, + Mirror as RRNodeMirror, + buildFromDom, + getDefaultSN, printRRDom, } from '../src'; import { + ReplayerHandler, createOrGetNode, diff, - ReplayerHandler, nodeMatching, sameNodeType, } from '../src/diff'; import type { IRRElement, IRRNode } from '../src/document'; -import { Replayer } from 'rrweb'; -import type { - eventWithTime, - canvasMutationData, - styleDeclarationData, - styleSheetRuleData, -} from '@rrweb/types'; -import { EventType, IncrementalSource } from '@rrweb/types'; import { compileTSCode } from './utils'; const elementSn = { diff --git a/packages/rrdom/test/document.test.ts b/packages/rrdom/test/document.test.ts index 38a35e505f..eba6e199c3 100644 --- a/packages/rrdom/test/document.test.ts +++ b/packages/rrdom/test/document.test.ts @@ -1,7 +1,7 @@ /** * @jest-environment jsdom */ -import { NodeType as RRNodeType } from 'rrweb-snapshot'; +import { NodeType as RRNodeType } from '@amplitude/rrweb-snapshot'; import { BaseRRDocumentImpl, BaseRRDocumentTypeImpl, @@ -371,7 +371,7 @@ describe('Basic RRDocument implementation', () => { expect(node.childNodes.length).toEqual(0); }); - it('can cover the usage of write() in rrweb-snapshot', () => { + it('can cover the usage of write() in @amplitude/rrweb-snapshot', () => { const node = new RRDocument(); node.write( '', diff --git a/packages/rrdom/test/virtual-dom.test.ts b/packages/rrdom/test/virtual-dom.test.ts index b99aca5ae4..59ccfa7fc9 100644 --- a/packages/rrdom/test/virtual-dom.test.ts +++ b/packages/rrdom/test/virtual-dom.test.ts @@ -1,10 +1,6 @@ /** * @jest-environment jsdom */ -import * as fs from 'fs'; -import * as path from 'path'; -import * as puppeteer from 'puppeteer'; -import { JSDOM } from 'jsdom'; import { cdataNode, commentNode, @@ -15,7 +11,11 @@ import { NodeType, NodeType as RRNodeType, textNode, -} from 'rrweb-snapshot'; +} from '@amplitude/rrweb-snapshot'; +import * as fs from 'fs'; +import { JSDOM } from 'jsdom'; +import * as path from 'path'; +import * as puppeteer from 'puppeteer'; import { buildFromDom, buildFromNode, diff --git a/packages/rrdom/tsconfig.json b/packages/rrdom/tsconfig.json index 450e56e151..ed182cbd3f 100644 --- a/packages/rrdom/tsconfig.json +++ b/packages/rrdom/tsconfig.json @@ -10,7 +10,10 @@ "sourceMap": true, "rootDir": "src", "outDir": "build", - "lib": ["es6", "dom"], + "lib": [ + "es6", + "dom" + ], "skipLibCheck": true, "declaration": true, "importsNotUsedAsValues": "error" @@ -24,7 +27,9 @@ } ], "compileOnSave": true, - "exclude": ["test"], + "exclude": [ + "test" + ], "include": [ "src", "../rrweb/src/record/workers/workers.d.ts", diff --git a/packages/rrvideo/package.json b/packages/rrvideo/package.json index e11c39fba2..f0743e9f9a 100644 --- a/packages/rrvideo/package.json +++ b/packages/rrvideo/package.json @@ -20,19 +20,19 @@ "author": "Amplitude Inc", "license": "MIT", "devDependencies": { + "@amplitude/rrweb": "^2.0.0-alpha.11", "@types/fs-extra": "11.0.1", "@types/jest": "^27.4.1", "@types/minimist": "^1.2.1", "@types/node": "^18.15.11", "jest": "^27.5.1", - "ts-jest": "^27.1.3", - "@rrweb/types": "^2.0.0-alpha.11" + "ts-jest": "^27.1.3" }, "dependencies": { + "@amplitude/rrweb-player": "^2.0.0-alpha.11", "@open-tech-world/cli-progress-bar": "^2.0.2", "fs-extra": "^11.1.1", "minimist": "^1.2.5", - "playwright": "^1.32.1", - "rrweb-player": "^2.0.0-alpha.11" + "playwright": "^1.32.1" } } diff --git a/packages/rrvideo/src/cli.ts b/packages/rrvideo/src/cli.ts index 600c531a23..904f4592b0 100644 --- a/packages/rrvideo/src/cli.ts +++ b/packages/rrvideo/src/cli.ts @@ -1,9 +1,9 @@ #!/usr/bin/env node +import type { RRwebPlayerOptions } from '@amplitude/rrweb-player'; +import { ProgressBar } from '@open-tech-world/cli-progress-bar'; import * as fs from 'fs'; -import * as path from 'path'; import minimist from 'minimist'; -import { ProgressBar } from '@open-tech-world/cli-progress-bar'; -import type { RRwebPlayerOptions } from 'rrweb-player'; +import * as path from 'path'; import { transformToVideo } from './index'; const argv = minimist(process.argv.slice(2)); diff --git a/packages/rrvideo/src/index.ts b/packages/rrvideo/src/index.ts index 0909746929..7e07f20fcd 100644 --- a/packages/rrvideo/src/index.ts +++ b/packages/rrvideo/src/index.ts @@ -1,11 +1,11 @@ +import type { RRwebPlayerOptions } from '@amplitude/rrweb-player'; +import { EventType, eventWithTime } from '@amplitude/rrweb-types'; import * as fs from 'fs-extra'; import * as path from 'path'; import { chromium } from 'playwright'; -import { EventType, eventWithTime } from '@rrweb/types'; -import type { RRwebPlayerOptions } from 'rrweb-player'; const rrwebScriptPath = path.resolve( - require.resolve('rrweb-player'), + require.resolve('@amplitude/rrweb-player'), '../../dist/index.js', ); const rrwebStylePath = path.resolve(rrwebScriptPath, '../style.css'); diff --git a/packages/rrvideo/test/events/example.ts b/packages/rrvideo/test/events/example.ts index 00701fd6ca..fb6470e082 100644 --- a/packages/rrvideo/test/events/example.ts +++ b/packages/rrvideo/test/events/example.ts @@ -1,5 +1,5 @@ -import { EventType, IncrementalSource } from '@rrweb/types'; -import type { eventWithTime } from '@rrweb/types'; +import type { eventWithTime } from '@amplitude/rrweb-types'; +import { EventType, IncrementalSource } from '@amplitude/rrweb-types'; const now = Date.now(); const events: eventWithTime[] = [ diff --git a/packages/rrvideo/tsconfig.json b/packages/rrvideo/tsconfig.json index 95955dda4a..e6f37d525d 100644 --- a/packages/rrvideo/tsconfig.json +++ b/packages/rrvideo/tsconfig.json @@ -16,13 +16,17 @@ "skipLibCheck": true, "forceConsistentCasingInFileNames": true }, - "exclude": ["build", "node_modules", "test"], + "exclude": [ + "build", + "node_modules", + "test" + ], "references": [ { "path": "../rrweb-player" }, { - "path": "../types" + "path": "../rrweb" } ] } diff --git a/packages/rrweb-player/package.json b/packages/rrweb-player/package.json index 9ef55cd0b1..c709a70484 100644 --- a/packages/rrweb-player/package.json +++ b/packages/rrweb-player/package.json @@ -2,9 +2,9 @@ "name": "@amplitude/rrweb-player", "version": "2.0.0-alpha.11", "devDependencies": { + "@amplitude/rrweb-types": "^2.0.0-alpha.11", "@rollup/plugin-commonjs": "^22.0.0", "@rollup/plugin-node-resolve": "^13.2.1", - "@rrweb/types": "^2.0.0-alpha.11", "@types/offscreencanvas": "^2019.6.4", "eslint-config-google": "^0.14.0", "eslint-plugin-svelte3": "^4.0.0", @@ -24,7 +24,7 @@ }, "dependencies": { "@tsconfig/svelte": "^1.0.0", - "rrweb": "^2.0.0-alpha.11" + "@amplitude/rrweb": "^2.0.0-alpha.11" }, "scripts": { "build": "rollup -c", diff --git a/packages/rrweb-player/src/Controller.svelte b/packages/rrweb-player/src/Controller.svelte index 5a352e6dd0..25270f2cdd 100644 --- a/packages/rrweb-player/src/Controller.svelte +++ b/packages/rrweb-player/src/Controller.svelte @@ -1,11 +1,11 @@ diff --git a/packages/rrweb-snapshot/test/snapshot.test.ts b/packages/rrweb-snapshot/test/snapshot.test.ts index 75d635e0c0..aa4bb428ee 100644 --- a/packages/rrweb-snapshot/test/snapshot.test.ts +++ b/packages/rrweb-snapshot/test/snapshot.test.ts @@ -7,7 +7,7 @@ import { serializeNodeWithId, _isBlockedElement, } from '../src/snapshot'; -import { serializedNodeWithId } from '../src/types'; +import { serializedNodeWithId, elementNode } from '../src/types'; import { Mirror } from '../src/utils'; describe('absolute url to stylesheet', () => { @@ -218,3 +218,42 @@ describe('scrollTop/scrollLeft', () => { }); }); }); + +describe('form', () => { + const serializeNode = (node: Node): serializedNodeWithId | null => { + return serializeNodeWithId(node, { + doc: document, + mirror: new Mirror(), + blockClass: 'blockblock', + blockSelector: null, + maskTextClass: 'maskmask', + maskTextSelector: null, + skipChild: false, + inlineStylesheet: true, + maskTextFn: undefined, + maskInputFn: undefined, + slimDOMOptions: {}, + newlyAddedElement: false, + }); + }; + + const render = (html: string): HTMLTextAreaElement => { + document.write(html); + return document.querySelector('textarea')!; + }; + + it('should record textarea values once', () => { + const el = render(``); + const sel = serializeNode(el) as elementNode; + + // we serialize according to where the DOM stores the value, not how + // the HTML stores it (this is so that maskInputValue can work over + // inputs/textareas/selects in a uniform way) + expect(sel).toMatchObject({ + attributes: { + value: 'Lorem ipsum', + }, + }); + expect(sel?.childNodes).toEqual([]); // shouldn't be stored in childNodes while in transit + }); +}); diff --git a/packages/rrweb/package.json b/packages/rrweb/package.json index 4cf598d0ee..49a3647b96 100644 --- a/packages/rrweb/package.json +++ b/packages/rrweb/package.json @@ -12,6 +12,7 @@ "test": "yarn test:headless", "test:watch": "yarn test:headless -- --watch", "test:update": "yarn test:headless -- --updateSnapshot", + "retest:update": "PUPPETEER_HEADLESS=true yarn retest -- --updateSnapshot", "repl": "yarn bundle:browser && node scripts/repl.js", "live-stream": "yarn bundle:browser && node scripts/stream.js", "dev": "yarn bundle:browser --watch", diff --git a/packages/rrweb/src/record/mutation.ts b/packages/rrweb/src/record/mutation.ts index 1bbe39354e..369320cdd3 100644 --- a/packages/rrweb/src/record/mutation.ts +++ b/packages/rrweb/src/record/mutation.ts @@ -283,7 +283,11 @@ export default class MutationBuffer { return nextId; }; const pushAdd = (n: Node) => { - if (!n.parentNode || !inDom(n)) { + if ( + !n.parentNode || + !inDom(n) || + (n.parentNode as Element).tagName === 'TEXTAREA' + ) { return; } const parentId = isShadowRoot(n.parentNode) @@ -433,10 +437,17 @@ export default class MutationBuffer { const payload = { texts: this.texts - .map((text) => ({ - id: this.mirror.getId(text.node), - value: text.value, - })) + .map((text) => { + const n = text.node; + if ((n.parentNode as Element).tagName === 'TEXTAREA') { + // the node is being ignored as it isn't in the mirror, so shift mutation to attributes on parent textarea + this.genTextAreaValueMutation(n.parentNode as HTMLTextAreaElement); + } + return { + id: this.mirror.getId(n), + value: text.value, + }; + }) // no need to include them on added elements, as they have just been serialized with up to date attribubtes .filter((text) => !addedIds.has(text.id)) // text mutation's id was not in the mirror map means the target node has been removed @@ -494,6 +505,24 @@ export default class MutationBuffer { this.mutationCb(payload); }; + private genTextAreaValueMutation = (textarea: HTMLTextAreaElement) => { + let item = this.attributeMap.get(textarea); + if (!item) { + item = { + node: textarea, + attributes: {}, + styleDiff: {}, + _unchangedStyles: {}, + }; + this.attributes.push(item); + this.attributeMap.set(textarea, item); + } + item.attributes.value = Array.from( + textarea.childNodes, + (cn) => cn.textContent || '', + ).join(''); + }; + private processMutation = (m: mutationRecord) => { if (isIgnored(m.target, this.mirror)) { return; @@ -637,6 +666,12 @@ export default class MutationBuffer { if (isBlocked(m.target, this.blockClass, this.blockSelector, true)) return; + if ((m.target as Element).tagName === 'TEXTAREA') { + // children would be ignored in genAdds as they aren't in the mirror + this.genTextAreaValueMutation(m.target as HTMLTextAreaElement); + return; // any removedNodes won't have been in mirror either + } + m.addedNodes.forEach((n) => this.genAdds(n, m.target)); m.removedNodes.forEach((n) => { const nodeId = this.mirror.getId(n); diff --git a/packages/rrweb/src/replay/index.ts b/packages/rrweb/src/replay/index.ts index cc6f1348ab..863c41176e 100644 --- a/packages/rrweb/src/replay/index.ts +++ b/packages/rrweb/src/replay/index.ts @@ -1554,6 +1554,8 @@ export class Replayer { const childNodeArray = Array.isArray(parent.childNodes) ? parent.childNodes : Array.from(parent.childNodes); + // This should be redundant now as we are either recording the value or the childNode, and not both + // keeping around for backwards compatibility with old bad double data, see // https://github.com/rrweb-io/rrweb/issues/745 // parent is textarea, will only keep one child node as the value @@ -1751,10 +1753,24 @@ export class Replayer { // for safe } } - (target as Element | RRElement).setAttribute( - attributeName, - value, - ); + if (attributeName === 'value' && target.nodeName === 'TEXTAREA') { + // this may or may not have an effect on the value property (which is what is displayed) + // depending on whether the textarea has been modified by the user yet + // TODO: replaceChildNodes is not available in RRDom + const textarea = target as TNode; + textarea.childNodes.forEach((c) => + textarea.removeChild(c as TNode), + ); + const tn = target.ownerDocument?.createTextNode(value); + if (tn) { + textarea.appendChild(tn as TNode); + } + } else { + (target as Element | RRElement).setAttribute( + attributeName, + value, + ); + } } catch (error) { this.warn( 'An error occurred may due to the checkout feature.', diff --git a/packages/rrweb/test/__snapshots__/integration.test.ts.snap b/packages/rrweb/test/__snapshots__/integration.test.ts.snap index e320254111..a9ceeba5ee 100644 --- a/packages/rrweb/test/__snapshots__/integration.test.ts.snap +++ b/packages/rrweb/test/__snapshots__/integration.test.ts.snap @@ -2031,8 +2031,22 @@ exports[`record integration tests can record form interactions 1`] = ` }, { \\"type\\": 3, - \\"textContent\\": \\"\\\\n \\", + \\"textContent\\": \\"\\\\n \\", \\"id\\": 61 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"textarea\\", + \\"attributes\\": { + \\"value\\": \\"pre value\\" + }, + \\"childNodes\\": [], + \\"id\\": 62 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 63 } ], \\"id\\": 18 @@ -2040,7 +2054,7 @@ exports[`record integration tests can record form interactions 1`] = ` { \\"type\\": 3, \\"textContent\\": \\"\\\\n \\\\n \\", - \\"id\\": 62 + \\"id\\": 64 }, { \\"type\\": 2, @@ -2050,15 +2064,15 @@ exports[`record integration tests can record form interactions 1`] = ` { \\"type\\": 3, \\"textContent\\": \\"SCRIPT_PLACEHOLDER\\", - \\"id\\": 64 + \\"id\\": 66 } ], - \\"id\\": 63 + \\"id\\": 65 }, { \\"type\\": 3, \\"textContent\\": \\"\\\\n \\\\n \\\\n\\\\n\\", - \\"id\\": 65 + \\"id\\": 67 } ], \\"id\\": 16 @@ -3574,6 +3588,270 @@ exports[`record integration tests can record style changes compactly and preserv ]" `; +exports[`record integration tests can record textarea mutations correctly 1`] = ` +"[ + { + \\"type\\": 0, + \\"data\\": {} + }, + { + \\"type\\": 1, + \\"data\\": {} + }, + { + \\"type\\": 4, + \\"data\\": { + \\"href\\": \\"about:blank\\", + \\"width\\": 1920, + \\"height\\": 1080 + } + }, + { + \\"type\\": 2, + \\"data\\": { + \\"node\\": { + \\"type\\": 0, + \\"childNodes\\": [ + { + \\"type\\": 1, + \\"name\\": \\"html\\", + \\"publicId\\": \\"\\", + \\"systemId\\": \\"\\", + \\"id\\": 2 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"html\\", + \\"attributes\\": { + \\"lang\\": \\"en\\" + }, + \\"childNodes\\": [ + { + \\"type\\": 2, + \\"tagName\\": \\"head\\", + \\"attributes\\": {}, + \\"childNodes\\": [ + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 5 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"meta\\", + \\"attributes\\": { + \\"charset\\": \\"UTF-8\\" + }, + \\"childNodes\\": [], + \\"id\\": 6 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 7 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"meta\\", + \\"attributes\\": { + \\"name\\": \\"viewport\\", + \\"content\\": \\"width=device-width, initial-scale=1.0\\" + }, + \\"childNodes\\": [], + \\"id\\": 8 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 9 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"title\\", + \\"attributes\\": {}, + \\"childNodes\\": [ + { + \\"type\\": 3, + \\"textContent\\": \\"Empty\\", + \\"id\\": 11 + } + ], + \\"id\\": 10 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 12 + } + ], + \\"id\\": 4 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 13 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"body\\", + \\"attributes\\": {}, + \\"childNodes\\": [ + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 15 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"div\\", + \\"attributes\\": { + \\"id\\": \\"one\\" + }, + \\"childNodes\\": [], + \\"id\\": 16 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\\\n \\", + \\"id\\": 17 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"script\\", + \\"attributes\\": {}, + \\"childNodes\\": [ + { + \\"type\\": 3, + \\"textContent\\": \\"SCRIPT_PLACEHOLDER\\", + \\"id\\": 19 + } + ], + \\"id\\": 18 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\\\n \\\\n\\\\n\\", + \\"id\\": 20 + } + ], + \\"id\\": 14 + } + ], + \\"id\\": 3 + } + ], + \\"id\\": 1 + }, + \\"initialOffset\\": { + \\"left\\": 0, + \\"top\\": 0 + } + } + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 0, + \\"texts\\": [], + \\"attributes\\": [], + \\"removes\\": [], + \\"adds\\": [ + { + \\"parentId\\": 14, + \\"nextId\\": null, + \\"node\\": { + \\"type\\": 2, + \\"tagName\\": \\"textarea\\", + \\"attributes\\": { + \\"value\\": \\"pre value\\" + }, + \\"childNodes\\": [], + \\"id\\": 21 + } + } + ] + } + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 0, + \\"texts\\": [], + \\"attributes\\": [ + { + \\"id\\": 21, + \\"attributes\\": { + \\"value\\": \\"ok\\" + } + } + ], + \\"removes\\": [], + \\"adds\\": [] + } + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 0, + \\"texts\\": [], + \\"attributes\\": [ + { + \\"id\\": 21, + \\"attributes\\": { + \\"value\\": \\"ok3\\" + } + } + ], + \\"removes\\": [], + \\"adds\\": [] + } + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 2, + \\"type\\": 5, + \\"id\\": 21 + } + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 5, + \\"text\\": \\"1ok3\\", + \\"isChecked\\": false, + \\"id\\": 21 + } + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 0, + \\"texts\\": [], + \\"attributes\\": [ + { + \\"id\\": 21, + \\"attributes\\": { + \\"value\\": \\"ignore\\" + } + } + ], + \\"removes\\": [], + \\"adds\\": [] + } + }, + { + \\"type\\": 3, + \\"data\\": { + \\"source\\": 5, + \\"text\\": \\"12ok3\\", + \\"isChecked\\": false, + \\"id\\": 21 + } + } +]" +`; + exports[`record integration tests can use maskInputOptions to configure which type of inputs should be masked 1`] = ` "[ { @@ -4001,8 +4279,22 @@ exports[`record integration tests can use maskInputOptions to configure which ty }, { \\"type\\": 3, - \\"textContent\\": \\"\\\\n \\", + \\"textContent\\": \\"\\\\n \\", \\"id\\": 61 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"textarea\\", + \\"attributes\\": { + \\"value\\": \\"pre value\\" + }, + \\"childNodes\\": [], + \\"id\\": 62 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 63 } ], \\"id\\": 18 @@ -4010,7 +4302,7 @@ exports[`record integration tests can use maskInputOptions to configure which ty { \\"type\\": 3, \\"textContent\\": \\"\\\\n \\\\n \\", - \\"id\\": 62 + \\"id\\": 64 }, { \\"type\\": 2, @@ -4020,15 +4312,15 @@ exports[`record integration tests can use maskInputOptions to configure which ty { \\"type\\": 3, \\"textContent\\": \\"SCRIPT_PLACEHOLDER\\", - \\"id\\": 64 + \\"id\\": 66 } ], - \\"id\\": 63 + \\"id\\": 65 }, { \\"type\\": 3, \\"textContent\\": \\"\\\\n \\\\n \\\\n\\\\n\\", - \\"id\\": 65 + \\"id\\": 67 } ], \\"id\\": 16 @@ -5993,8 +6285,22 @@ exports[`record integration tests should mask inputs via function call 1`] = ` }, { \\"type\\": 3, - \\"textContent\\": \\"\\\\n \\", + \\"textContent\\": \\"\\\\n \\", \\"id\\": 61 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"textarea\\", + \\"attributes\\": { + \\"value\\": \\"*********\\" + }, + \\"childNodes\\": [], + \\"id\\": 62 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 63 } ], \\"id\\": 18 @@ -6002,7 +6308,7 @@ exports[`record integration tests should mask inputs via function call 1`] = ` { \\"type\\": 3, \\"textContent\\": \\"\\\\n \\\\n \\", - \\"id\\": 62 + \\"id\\": 64 }, { \\"type\\": 2, @@ -6012,15 +6318,15 @@ exports[`record integration tests should mask inputs via function call 1`] = ` { \\"type\\": 3, \\"textContent\\": \\"SCRIPT_PLACEHOLDER\\", - \\"id\\": 64 + \\"id\\": 66 } ], - \\"id\\": 63 + \\"id\\": 65 }, { \\"type\\": 3, \\"textContent\\": \\"\\\\n \\\\n \\\\n\\\\n\\", - \\"id\\": 65 + \\"id\\": 67 } ], \\"id\\": 16 @@ -9680,8 +9986,22 @@ exports[`record integration tests should not record input values if maskAllInput }, { \\"type\\": 3, - \\"textContent\\": \\"\\\\n \\", + \\"textContent\\": \\"\\\\n \\", \\"id\\": 61 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"textarea\\", + \\"attributes\\": { + \\"value\\": \\"*********\\" + }, + \\"childNodes\\": [], + \\"id\\": 62 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 63 } ], \\"id\\": 18 @@ -9689,7 +10009,7 @@ exports[`record integration tests should not record input values if maskAllInput { \\"type\\": 3, \\"textContent\\": \\"\\\\n \\\\n \\", - \\"id\\": 62 + \\"id\\": 64 }, { \\"type\\": 2, @@ -9699,15 +10019,15 @@ exports[`record integration tests should not record input values if maskAllInput { \\"type\\": 3, \\"textContent\\": \\"SCRIPT_PLACEHOLDER\\", - \\"id\\": 64 + \\"id\\": 66 } ], - \\"id\\": 63 + \\"id\\": 65 }, { \\"type\\": 3, \\"textContent\\": \\"\\\\n \\\\n \\\\n\\\\n\\", - \\"id\\": 65 + \\"id\\": 67 } ], \\"id\\": 16 @@ -13389,8 +13709,22 @@ exports[`record integration tests should record input userTriggered values if us }, { \\"type\\": 3, - \\"textContent\\": \\"\\\\n \\", + \\"textContent\\": \\"\\\\n \\", \\"id\\": 61 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"textarea\\", + \\"attributes\\": { + \\"value\\": \\"pre value\\" + }, + \\"childNodes\\": [], + \\"id\\": 62 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"id\\": 63 } ], \\"id\\": 18 @@ -13398,7 +13732,7 @@ exports[`record integration tests should record input userTriggered values if us { \\"type\\": 3, \\"textContent\\": \\"\\\\n \\\\n \\", - \\"id\\": 62 + \\"id\\": 64 }, { \\"type\\": 2, @@ -13408,15 +13742,15 @@ exports[`record integration tests should record input userTriggered values if us { \\"type\\": 3, \\"textContent\\": \\"SCRIPT_PLACEHOLDER\\", - \\"id\\": 64 + \\"id\\": 66 } ], - \\"id\\": 63 + \\"id\\": 65 }, { \\"type\\": 3, \\"textContent\\": \\"\\\\n \\\\n \\\\n\\\\n\\", - \\"id\\": 65 + \\"id\\": 67 } ], \\"id\\": 16 diff --git a/packages/rrweb/test/events/bad-textarea.ts b/packages/rrweb/test/events/bad-textarea.ts new file mode 100644 index 0000000000..ad2a6ebb63 --- /dev/null +++ b/packages/rrweb/test/events/bad-textarea.ts @@ -0,0 +1,81 @@ +import { EventType, IncrementalSource } from '@rrweb/types'; +import type { eventWithTime } from '@rrweb/types'; + +const now = Date.now(); +const events: eventWithTime[] = [ + { + type: EventType.DomContentLoaded, + data: {}, + timestamp: now, + }, + { + type: EventType.Load, + data: {}, + timestamp: now + 50, + }, + { + type: EventType.Meta, + data: { + href: 'http://localhost', + width: 1000, + height: 800, + }, + timestamp: now + 50, + }, + // full snapshot: + { + data: { + node: { + id: 1, + type: 0, + childNodes: [ + { id: 2, name: 'html', type: 1, publicId: '', systemId: '' }, + { + id: 3, + type: 2, + tagName: 'html', + attributes: { lang: 'en' }, + childNodes: [ + { + id: 4, + type: 2, + tagName: 'head', + attributes: {}, + childNodes: [], + }, + { + id: 5, + type: 2, + tagName: 'body', + attributes: {}, + childNodes: [ + { + id: 6, + type: 2, + tagName: 'textarea', + attributes: { + value: 'this value is used for replay', + }, + childNodes: [ + { + type: 3, + textContent: + 'this value is IGNORED for replay (but was present as a duplicte in legacy recordings)', + id: 7, + }, + ], + }, + ], + }, + ], + }, + ], + }, + initialOffset: { top: 0, left: 0 }, + }, + type: EventType.FullSnapshot, + timestamp: now + 50, + }, +]; + +export default events; diff --git a/packages/rrweb/test/html/form.html b/packages/rrweb/test/html/form.html index 9125e983fa..8480259fe0 100644 --- a/packages/rrweb/test/html/form.html +++ b/packages/rrweb/test/html/form.html @@ -33,6 +33,7 @@ + diff --git a/packages/rrweb/test/integration.test.ts b/packages/rrweb/test/integration.test.ts index cf2710d12e..6fd3e66360 100644 --- a/packages/rrweb/test/integration.test.ts +++ b/packages/rrweb/test/integration.test.ts @@ -105,6 +105,69 @@ describe('record integration tests', function (this: ISuite) { assertSnapshot(snapshots); }); + it('can record textarea mutations correctly', async () => { + const page: puppeteer.Page = await browser.newPage(); + await page.goto('about:blank'); + await page.setContent(getHtml.call(this, 'empty.html')); + + await waitForRAF(page); // ensure mutations aren't included in fullsnapshot + + await page.evaluate(() => { + const ta = document.createElement('textarea'); + ta.innerText = 'pre value'; + document.body.append(ta); + }); + await page.evaluate(() => { + const t = document.querySelector('textarea') as HTMLTextAreaElement; + t.innerText = 'ok'; // this mutation should be recorded + }); + await page.evaluate(() => { + const t = document.querySelector('textarea') as HTMLTextAreaElement; + (t.childNodes[0] as Text).appendData('3'); // this mutation is also valid + }); + + await page.type('textarea', '1'); // types (inserts) at index 0, in front of existing text + + await page.evaluate(() => { + const t = document.querySelector('textarea') as HTMLTextAreaElement; + // user has typed so childNode content should now be ignored + (t.childNodes[0] as Text).data = 'igno'; + (t.childNodes[0] as Text).appendData('re'); + // this mutation is currently emitted, and shows up in snapshot + // but we will check that it doesn't have any effect on the value + // there is nothing explicit in rrweb which enforces this, but this test may protect against + // a future change where a mutation on a textarea incorrectly updates the .value + }); + + await page.type('textarea', '2'); // cursor is at index 1 + + const snapshots = (await page.evaluate( + 'window.snapshots', + )) as eventWithTime[]; + assertSnapshot(snapshots); + + // check after each mutation and text input + const replayTextareaValues = await page.evaluate(` + const { Replayer } = rrweb; + const replayer = new Replayer(window.snapshots); + const vals = []; + window.snapshots.filter((e)=>e.data.attributes || e.data.source === 5).forEach((e)=>{ + replayer.pause((e.timestamp - window.snapshots[0].timestamp)+1); + let ts = replayer.iframe.contentDocument.querySelector('textarea'); + vals.push((e.data.source === 0 ? 'Mutation' : 'User') + ':' + ts.value); + }); + vals; + `); + expect(replayTextareaValues).toEqual([ + 'Mutation:pre value', + 'Mutation:ok', + 'Mutation:ok3', + 'User:1ok3', + 'Mutation:1ok3', // if this gets set to 'ignore', it's an error, as the 'user' has modified the textarea + 'User:12ok3', + ]); + }); + it('can record childList mutations', async () => { const page: puppeteer.Page = await browser.newPage(); await page.goto('about:blank'); diff --git a/packages/rrweb/test/record/__snapshots__/cross-origin-iframes.test.ts.snap b/packages/rrweb/test/record/__snapshots__/cross-origin-iframes.test.ts.snap index 07d4f53363..a296b53be8 100644 --- a/packages/rrweb/test/record/__snapshots__/cross-origin-iframes.test.ts.snap +++ b/packages/rrweb/test/record/__snapshots__/cross-origin-iframes.test.ts.snap @@ -1586,9 +1586,25 @@ exports[`cross origin iframes form.html should map input events correctly 1`] = }, { \\"type\\": 3, - \\"textContent\\": \\"\\\\n \\", + \\"textContent\\": \\"\\\\n \\", \\"rootId\\": 11, \\"id\\": 73 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"textarea\\", + \\"attributes\\": { + \\"value\\": \\"pre value\\" + }, + \\"childNodes\\": [], + \\"rootId\\": 11, + \\"id\\": 74 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"rootId\\": 11, + \\"id\\": 75 } ], \\"rootId\\": 11, @@ -1598,7 +1614,7 @@ exports[`cross origin iframes form.html should map input events correctly 1`] = \\"type\\": 3, \\"textContent\\": \\"\\\\n \\\\n\\\\n\\", \\"rootId\\": 11, - \\"id\\": 74 + \\"id\\": 76 } ], \\"rootId\\": 11, @@ -2583,9 +2599,25 @@ exports[`cross origin iframes form.html should map scroll events correctly 1`] = }, { \\"type\\": 3, - \\"textContent\\": \\"\\\\n \\", + \\"textContent\\": \\"\\\\n \\", \\"rootId\\": 11, \\"id\\": 73 + }, + { + \\"type\\": 2, + \\"tagName\\": \\"textarea\\", + \\"attributes\\": { + \\"value\\": \\"pre value\\" + }, + \\"childNodes\\": [], + \\"rootId\\": 11, + \\"id\\": 74 + }, + { + \\"type\\": 3, + \\"textContent\\": \\"\\\\n \\", + \\"rootId\\": 11, + \\"id\\": 75 } ], \\"rootId\\": 11, @@ -2595,7 +2627,7 @@ exports[`cross origin iframes form.html should map scroll events correctly 1`] = \\"type\\": 3, \\"textContent\\": \\"\\\\n \\\\n\\\\n\\", \\"rootId\\": 11, - \\"id\\": 74 + \\"id\\": 76 } ], \\"rootId\\": 11, From 8cb959c1bf745c0a0e94bd49f0bbda40cccbbe07 Mon Sep 17 00:00:00 2001 From: Michael Dellanoce Date: Fri, 3 Nov 2023 18:03:59 -0400 Subject: [PATCH 66/66] perf(rrweb): attribute mutation optimization (#1343) --- .changeset/moody-dots-refuse.md | 5 +++++ packages/rrweb/src/record/mutation.ts | 7 ++++--- .../rrweb/test/benchmark/dom-mutation.test.ts | 6 ++++++ .../benchmark-dom-mutation-attributes.html | 21 +++++++++++++++++++ 4 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 .changeset/moody-dots-refuse.md create mode 100644 packages/rrweb/test/html/benchmark-dom-mutation-attributes.html diff --git a/.changeset/moody-dots-refuse.md b/.changeset/moody-dots-refuse.md new file mode 100644 index 0000000000..32270da384 --- /dev/null +++ b/.changeset/moody-dots-refuse.md @@ -0,0 +1,5 @@ +--- +'rrweb': patch +--- + +use WeakMap for faster attributeCursor lookup while processing attribute mutations diff --git a/packages/rrweb/src/record/mutation.ts b/packages/rrweb/src/record/mutation.ts index 369320cdd3..e6d686af54 100644 --- a/packages/rrweb/src/record/mutation.ts +++ b/packages/rrweb/src/record/mutation.ts @@ -142,6 +142,7 @@ export default class MutationBuffer { private texts: textCursor[] = []; private attributes: attributeCursor[] = []; + private attributeMap = new WeakMap(); private removes: removedNodeMutation[] = []; private mapRemoves: Node[] = []; @@ -496,6 +497,7 @@ export default class MutationBuffer { // reset this.texts = []; this.attributes = []; + this.attributeMap = new WeakMap(); this.removes = []; this.addedSet = new Set(); this.movedSet = new Set(); @@ -575,9 +577,7 @@ export default class MutationBuffer { return; } - let item: attributeCursor | undefined = this.attributes.find( - (a) => a.node === m.target, - ); + let item = this.attributeMap.get(m.target); if ( target.tagName === 'IFRAME' && attributeName === 'src' && @@ -599,6 +599,7 @@ export default class MutationBuffer { _unchangedStyles: {}, }; this.attributes.push(item); + this.attributeMap.set(m.target, item); } // Keep this property on inputs that used to be password inputs diff --git a/packages/rrweb/test/benchmark/dom-mutation.test.ts b/packages/rrweb/test/benchmark/dom-mutation.test.ts index c1cb403e3f..4bf3109e2c 100644 --- a/packages/rrweb/test/benchmark/dom-mutation.test.ts +++ b/packages/rrweb/test/benchmark/dom-mutation.test.ts @@ -42,6 +42,12 @@ const suites: Array< eval: 'window.workload()', times: 5, }, + { + title: 'modify attributes on 10000 DOM nodes', + html: 'benchmark-dom-mutation-attributes.html', + eval: 'window.workload()', + times: 10, + }, ]; function avg(v: number[]): number { diff --git a/packages/rrweb/test/html/benchmark-dom-mutation-attributes.html b/packages/rrweb/test/html/benchmark-dom-mutation-attributes.html new file mode 100644 index 0000000000..3d00b26b4d --- /dev/null +++ b/packages/rrweb/test/html/benchmark-dom-mutation-attributes.html @@ -0,0 +1,21 @@ + + + +