Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into defined-pseudo-class
Browse files Browse the repository at this point in the history
  • Loading branch information
YunFeng0817 committed Nov 5, 2023
2 parents 811f56e + 40f484d commit 11be49a
Show file tree
Hide file tree
Showing 15 changed files with 86 additions and 38 deletions.
5 changes: 5 additions & 0 deletions .changeset/gold-apples-joke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'rrweb': patch
---

ref: Avoid unnecessary cloning of objects or arrays
5 changes: 5 additions & 0 deletions .changeset/mighty-bulldogs-begin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rrweb/web-extension': patch
---

Update `vite.config.ts` to account for all potential entry types.
5 changes: 5 additions & 0 deletions .changeset/moody-dots-refuse.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'rrweb': patch
---

use WeakMap for faster attributeCursor lookup while processing attribute mutations
5 changes: 5 additions & 0 deletions .changeset/witty-kids-talk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rrweb/web-extension': patch
---

🐞 fix(web-extension): beforeunload logic
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -226,5 +226,10 @@ In addition to adding integration tests and unit tests, rrweb also provides a RE
<img style="padding: 8px" alt="Intercept, Modify, Record & Replay HTTP Requests." width="195px" src="https://github.com/requestly/requestly/assets/16779465/652552db-c867-44cb-9bb5-94a2026e04ca">
</a>
</td>
<td align="center">
<a href="https://gleap.io" target="_blank">
<img style="padding: 8px" alt="In-app bug reporting & customer feedback platform." width="195px" src="https://assets-global.website-files.com/6506f3f29c68b1724807619d/6506f56010237164c6306591_GleapLogo.svg">
</a>
</td>
</tr>
</table>
2 changes: 1 addition & 1 deletion packages/rrweb/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export {
IncrementalSource,
MouseInteractions,
ReplayerEvents,
type eventWithTime
type eventWithTime,
} from '@rrweb/types';

export type { recordOptions } from './types';
Expand Down
7 changes: 4 additions & 3 deletions packages/rrweb/src/record/mutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ export default class MutationBuffer {

private texts: textCursor[] = [];
private attributes: attributeCursor[] = [];
private attributeMap = new WeakMap<Node, attributeCursor>();
private removes: removedNodeMutation[] = [];
private mapRemoves: Node[] = [];

Expand Down Expand Up @@ -485,6 +486,7 @@ export default class MutationBuffer {
// reset
this.texts = [];
this.attributes = [];
this.attributeMap = new WeakMap<Node, attributeCursor>();
this.removes = [];
this.addedSet = new Set<Node>();
this.movedSet = new Set<Node>();
Expand Down Expand Up @@ -554,9 +556,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' &&
Expand All @@ -578,6 +578,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
Expand Down
32 changes: 11 additions & 21 deletions packages/rrweb/src/record/observer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -406,15 +406,6 @@ function initViewportResizeObserver(
return on('resize', updateDimension, win);
}

function wrapEventWithUserTriggeredFlag(
v: inputValue,
enable: boolean,
): inputValue {
const value = { ...v };
if (!enable) delete value.userTriggered;
return value;
}

export const INPUT_TAGS = ['INPUT', 'TEXTAREA', 'SELECT'];
const lastInputValueMap: WeakMap<EventTarget, inputValue> = new WeakMap();
function initInputObserver({
Expand Down Expand Up @@ -478,10 +469,9 @@ function initInputObserver({
}
cbWithDedup(
target,
callbackWrapper(wrapEventWithUserTriggeredFlag)(
{ text, isChecked, userTriggered },
userTriggeredOnInput,
),
userTriggeredOnInput
? { text, isChecked, userTriggered }
: { text, isChecked },
);
// if a radio was checked
// the other radios with the same name attribute will be unchecked.
Expand All @@ -491,16 +481,12 @@ function initInputObserver({
.querySelectorAll(`input[type="radio"][name="${name}"]`)
.forEach((el) => {
if (el !== target) {
const text = (el as HTMLInputElement).value;
cbWithDedup(
el,
callbackWrapper(wrapEventWithUserTriggeredFlag)(
{
text: (el as HTMLInputElement).value,
isChecked: !isChecked,
userTriggered: false,
},
userTriggeredOnInput,
),
userTriggeredOnInput
? { text, isChecked: !isChecked, userTriggered: false }
: { text, isChecked: !isChecked },
);
}
});
Expand Down Expand Up @@ -1340,9 +1326,13 @@ export function initObservers(
const inputHandler = initInputObserver(o);
const mediaInteractionHandler = initMediaInteractionObserver(o);

// eslint-disable-next-line @typescript-eslint/no-empty-function
let styleSheetObserver = () => {};
// eslint-disable-next-line @typescript-eslint/no-empty-function
let adoptedStyleSheetObserver = () => {};
// eslint-disable-next-line @typescript-eslint/no-empty-function
let styleDeclarationObserver = () => {};
// eslint-disable-next-line @typescript-eslint/no-empty-function
let fontObserver = () => {};
if (o.recordDOM) {
styleSheetObserver = initStyleSheetObserver(o, { win: currentWindow });
Expand Down
2 changes: 1 addition & 1 deletion packages/rrweb/src/record/observers/canvas/2d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export default function initCanvas2DMutationObserver(
// Using setTimeout as toDataURL can be heavy
// and we'd rather not block the main thread
setTimeout(() => {
const recordArgs = serializeArgs([...args], win, this);
const recordArgs = serializeArgs(args, win, this);
cb(this.canvas, {
type: CanvasContext['2D'],
property: prop,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ export const serializeArgs = (
win: IWindow,
ctx: RenderingContext,
) => {
return [...args].map((arg) => serializeArg(arg, win, ctx));
return args.map((arg) => serializeArg(arg, win, ctx));
};

export const isInstanceOfWebGLObject = (
Expand Down
2 changes: 1 addition & 1 deletion packages/rrweb/src/record/observers/canvas/webgl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ function patchGLPrototype(
'tagName' in this.canvas &&
!isBlocked(this.canvas, blockClass, blockSelector, true)
) {
const recordArgs = serializeArgs([...args], win, this);
const recordArgs = serializeArgs(args, win, this);
const mutation: canvasMutationWithType = {
type,
property: prop,
Expand Down
6 changes: 6 additions & 0 deletions packages/rrweb/test/benchmark/dom-mutation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
21 changes: 21 additions & 0 deletions packages/rrweb/test/html/benchmark-dom-mutation-attributes.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<html>
<body></body>
<script>
function init() {
const count = 10000;
for (let i = 0; i < count; ++i) {
const div = document.createElement('div');
document.body.appendChild(div);
}
}

init();

window.workload = () => {
const divs = document.getElementsByTagName('div');
for (let div of divs) {
div.classList.add('foo');
}
};
</script>
</html>
2 changes: 1 addition & 1 deletion packages/web-extension/src/content/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,8 @@ async function initMainPage() {

// Before unload pages, cache the new events in the local storage.
window.addEventListener('beforeunload', (event) => {
if (!newEvents.length) return;
event.preventDefault();
if (newEvents.length === 0) return;
void Browser.storage.local.set({
[LocalDataKey.bufferedEvents]: bufferedEvents.concat(newEvents),
});
Expand Down
23 changes: 14 additions & 9 deletions packages/web-extension/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
import {
defineConfig,
LibraryFormats,
LibraryOptions,
PluginOption,
} from 'vite';
import { defineConfig, LibraryFormats, PluginOption } from 'vite';
import webExtension, { readJsonFile } from 'vite-plugin-web-extension';
import zip from 'vite-plugin-zip-pack';
import * as path from 'path';
Expand All @@ -17,9 +12,19 @@ function useSpecialFormat(
return {
name: 'use-special-format',
config(config) {
const shouldUse = entriesToUse.includes(
(config.build?.lib as LibraryOptions)?.entry,
);
// entry can be string | string[] | {[entryAlias: string]: string}
const entry = config.build?.lib && config.build.lib.entry;
let shouldUse = false;

if (typeof entry === 'string') {
shouldUse = entriesToUse.includes(entry);
} else if (Array.isArray(entry)) {
shouldUse = entriesToUse.some((e) => entry.includes(e));
} else if (entry && typeof entry === 'object') {
const entryKeys = Object.keys(entry);
shouldUse = entriesToUse.some((e) => entryKeys.includes(e));
}

if (shouldUse) {
config.build = config.build ?? {};
// @ts-expect-error: lib needs to be an object, forcing it.
Expand Down

0 comments on commit 11be49a

Please sign in to comment.