Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@highlight-run/rrweb",
"version": "0.12.14",
"version": "1.0.7",
"description": "record and replay the web",
"scripts": {
"test": "npm run bundle:browser && cross-env TS_NODE_CACHE=false TS_NODE_FILES=true mocha -r ts-node/register -r ignore-styles -r jsdom-global/register test/**.test.ts",
Expand Down
2 changes: 2 additions & 0 deletions src/record/mutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
removedNodeMutation,
addedNodeMutation,
Mirror,
styleAttributeValue,
} from '../types';
import {
isBlocked,
Expand Down Expand Up @@ -456,6 +457,7 @@ export default class MutationBuffer {
break;
}
case 'attributes': {
const target = m.target as HTMLElement;
let value = (m.target as HTMLElement).getAttribute(m.attributeName!);
if (m.attributeName === 'value') {
value = maskInputValue({
Expand Down
142 changes: 62 additions & 80 deletions src/record/observer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,16 @@ import {
fontParam,
Mirror,
styleDeclarationCallback,
IWindow,
} from '../types';
import MutationBuffer from './mutation';
import { IframeManager } from './iframe-manager';
import { ShadowDomManager } from './shadow-dom-manager';

type WindowWithStoredMutationObserver = Window & {
type WindowWithStoredMutationObserver = IWindow & {
__rrMutationObserver?: MutationObserver;
};
type WindowWithAngularZone = Window & {
type WindowWithAngularZone = IWindow & {
Zone?: {
__symbol__?: (key: string) => string;
};
Expand Down Expand Up @@ -203,44 +204,25 @@ function initMoveObserver(
},
callbackThreshold,
);
// update position for mouse, touch, and drag events (drag event extends mouse event)
function handleUpdatePositionEvent(evt: MouseEvent | TouchEvent) {
const target = getEventTarget(evt);
const { clientX, clientY } = isTouchEvent(evt)
? evt.changedTouches[0]
: evt;
if (!timeBaseline) {
timeBaseline = Date.now();
}
positions.push({
x: clientX,
y: clientY,
id: mirror.getId(target as INode),
timeOffset: Date.now() - timeBaseline,
});
}

// separate call for non-drag events, in case DragEvent is not defined
const updatePosition = throttle<MouseEvent | TouchEvent>(
(evt) => {
handleUpdatePositionEvent(evt);
wrappedCb(
evt instanceof MouseEvent
? IncrementalSource.MouseMove
: IncrementalSource.TouchMove,
);
},
threshold,
{
trailing: false,
},
);
// call for drag events, when DragEvent is defined
const updateDragPosition = throttle<MouseEvent | TouchEvent | DragEvent>(
const updatePosition = throttle<MouseEvent | TouchEvent | DragEvent>(
(evt) => {
handleUpdatePositionEvent(evt);
const target = getEventTarget(evt);
const { clientX, clientY } = isTouchEvent(evt)
? evt.changedTouches[0]
: evt;
if (!timeBaseline) {
timeBaseline = Date.now();
}
positions.push({
x: clientX,
y: clientY,
id: mirror.getId(target as INode),
timeOffset: Date.now() - timeBaseline,
});
// it is possible DragEvent is undefined even on devices
// that support event 'drag'
wrappedCb(
evt instanceof DragEvent
typeof DragEvent !== 'undefined' && evt instanceof DragEvent
? IncrementalSource.Drag
: evt instanceof MouseEvent
? IncrementalSource.MouseMove
Expand All @@ -252,13 +234,10 @@ function initMoveObserver(
trailing: false,
},
);
// it is possible DragEvent is undefined even on devices
// that support event 'drag'
const dragEventDefined = typeof DragEvent !== 'undefined';
const handlers = [
on('mousemove', updatePosition, doc),
on('touchmove', updatePosition, doc),
on('drag', dragEventDefined ? updateDragPosition : updatePosition, doc),
on('drag', updatePosition, doc),
];
return () => {
handlers.forEach((h) => h());
Expand Down Expand Up @@ -518,11 +497,17 @@ function getNestedCSSRulePositions(rule: CSSRule): number[] {
const positions: number[] = [];
function recurse(childRule: CSSRule, pos: number[]) {
if (
isCSSGroupingRuleSupported &&
childRule.parentRule instanceof CSSGroupingRule
(isCSSGroupingRuleSupported &&
childRule.parentRule instanceof CSSGroupingRule) ||
(isCSSMediaRuleSupported &&
childRule.parentRule instanceof CSSMediaRule) ||
(isCSSSupportsRuleSupported &&
childRule.parentRule instanceof CSSSupportsRule) ||
(isCSSConditionRuleSupported &&
childRule.parentRule instanceof CSSConditionRule)
) {
const rules = Array.from(
(childRule.parentRule as CSSGroupingRule).cssRules,
(childRule.parentRule as GroupingCSSRule).cssRules,
);
const index = rules.indexOf(childRule);
pos.unshift(index);
Expand All @@ -538,11 +523,11 @@ function getNestedCSSRulePositions(rule: CSSRule): number[] {

function initStyleSheetObserver(
cb: styleSheetRuleCallback,
win: Window,
win: IWindow,
mirror: Mirror,
): listenerHandler {
const insertRule = (win as any).CSSStyleSheet.prototype.insertRule;
(win as any).CSSStyleSheet.prototype.insertRule = function (
const insertRule = win.CSSStyleSheet.prototype.insertRule;
win.CSSStyleSheet.prototype.insertRule = function (
rule: string,
index?: number,
) {
Expand All @@ -556,8 +541,8 @@ function initStyleSheetObserver(
return insertRule.apply(this, arguments);
};

const deleteRule = (win as any).CSSStyleSheet.prototype.deleteRule;
(win as any).CSSStyleSheet.prototype.deleteRule = function (index: number) {
const deleteRule = win.CSSStyleSheet.prototype.deleteRule;
win.CSSStyleSheet.prototype.deleteRule = function (index: number) {
const id = mirror.getId(this.ownerNode as INode);
if (id !== -1) {
cb({
Expand All @@ -572,26 +557,20 @@ function initStyleSheetObserver(
[key: string]: GroupingCSSRuleTypes;
} = {};
if (isCSSGroupingRuleSupported) {
supportedNestedCSSRuleTypes[
'CSSGroupingRule'
] = (win as any).CSSGroupingRule;
supportedNestedCSSRuleTypes.CSSGroupingRule = win.CSSGroupingRule;
} else {
// Some browsers (Safari) don't support CSSGroupingRule
// https://caniuse.com/?search=cssgroupingrule
// fall back to monkey patching classes that would have inherited from CSSGroupingRule

if (isCSSMediaRuleSupported) {
supportedNestedCSSRuleTypes['CSSMediaRule'] = (win as any).CSSMediaRule;
supportedNestedCSSRuleTypes.CSSMediaRule = win.CSSMediaRule;
}
if (isCSSConditionRuleSupported) {
supportedNestedCSSRuleTypes[
'CSSConditionRule'
] = (win as any).CSSConditionRule;
supportedNestedCSSRuleTypes.CSSConditionRule = win.CSSConditionRule;
}
if (isCSSSupportsRuleSupported) {
supportedNestedCSSRuleTypes[
'CSSSupportsRule'
] = (win as any).CSSSupportsRule;
supportedNestedCSSRuleTypes.CSSSupportsRule = win.CSSSupportsRule;
}
}

Expand Down Expand Up @@ -640,8 +619,8 @@ function initStyleSheetObserver(
});

return () => {
(win as any).CSSStyleSheet.prototype.insertRule = insertRule;
(win as any).CSSStyleSheet.prototype.deleteRule = deleteRule;
win.CSSStyleSheet.prototype.insertRule = insertRule;
win.CSSStyleSheet.prototype.deleteRule = deleteRule;
Object.entries(supportedNestedCSSRuleTypes).forEach(([typeKey, type]) => {
type.prototype.insertRule = unmodifiedFunctions[typeKey].insertRule;
type.prototype.deleteRule = unmodifiedFunctions[typeKey].deleteRule;
Expand All @@ -651,11 +630,11 @@ function initStyleSheetObserver(

function initStyleDeclarationObserver(
cb: styleDeclarationCallback,
win: Window,
win: IWindow,
mirror: Mirror,
): listenerHandler {
const setProperty = (win as any).CSSStyleDeclaration.prototype.setProperty;
(win as any).CSSStyleDeclaration.prototype.setProperty = function (
const setProperty = win.CSSStyleDeclaration.prototype.setProperty;
win.CSSStyleDeclaration.prototype.setProperty = function (
this: CSSStyleDeclaration,
property: string,
value: string,
Expand All @@ -678,9 +657,8 @@ function initStyleDeclarationObserver(
return setProperty.apply(this, arguments);
};

const removeProperty = (win as any).CSSStyleDeclaration.prototype
.removeProperty;
(win as any).CSSStyleDeclaration.prototype.removeProperty = function (
const removeProperty = win.CSSStyleDeclaration.prototype.removeProperty;
win.CSSStyleDeclaration.prototype.removeProperty = function (
this: CSSStyleDeclaration,
property: string,
) {
Expand All @@ -700,8 +678,8 @@ function initStyleDeclarationObserver(
};

return () => {
(win as any).CSSStyleDeclaration.prototype.setProperty = setProperty;
(win as any).CSSStyleDeclaration.prototype.removeProperty = removeProperty;
win.CSSStyleDeclaration.prototype.setProperty = setProperty;
win.CSSStyleDeclaration.prototype.removeProperty = removeProperty;
};
}

Expand Down Expand Up @@ -733,7 +711,7 @@ function initMediaInteractionObserver(

function initCanvasMutationObserver(
cb: canvasMutationCallback,
win: Window,
win: IWindow,
blockClass: blockClass,
mirror: Mirror,
): listenerHandler {
Expand Down Expand Up @@ -814,14 +792,17 @@ function initCanvasMutationObserver(
}

function initFontObserver(cb: fontCallback, doc: Document): listenerHandler {
const win = doc.defaultView;
const win = doc.defaultView as IWindow;
if (!win) {
return () => {};
}

const handlers: listenerHandler[] = [];

const fontMap = new WeakMap<FontFace, fontParam>();

const originalFontFace = (win as any).FontFace;
// tslint:disable-next-line: no-any
(win as any).FontFace = function FontFace(
const originalFontFace = win.FontFace;
win.FontFace = (function FontFace(
family: string,
source: string | ArrayBufferView,
descriptors?: FontFaceDescriptors,
Expand All @@ -838,7 +819,7 @@ function initFontObserver(cb: fontCallback, doc: Document): listenerHandler {
JSON.stringify(Array.from(new Uint8Array(source as any))),
});
return fontFace;
};
} as unknown) as typeof FontFace;

const restoreHandler = patch(doc.fonts, 'add', function (original) {
return function (this: FontFaceSet, fontFace: FontFace) {
Expand All @@ -854,8 +835,7 @@ function initFontObserver(cb: fontCallback, doc: Document): listenerHandler {
});

handlers.push(() => {
// tslint:disable-next-line: no-any
(win as any).FonFace = originalFontFace;
win.FontFace = originalFontFace;
});
handlers.push(restoreHandler);

Expand Down Expand Up @@ -950,6 +930,10 @@ export function initObservers(
o: observerParam,
hooks: hooksParam = {},
): listenerHandler {
const currentWindow = o.doc.defaultView; // basically document.window
if (!currentWindow) {
return () => {};
}
mergeHooks(o, hooks);
const mutationObserver = initMutationObserver(
o.mutationCb,
Expand Down Expand Up @@ -1008,8 +992,6 @@ export function initObservers(
o.mirror,
);

const currentWindow = o.doc.defaultView as Window; // basically document.window

const styleSheetObserver = initStyleSheetObserver(
o.styleSheetRuleCb,
currentWindow,
Expand Down
Loading