Skip to content

Commit 33711ad

Browse files
committed
fix: always use native Proxy
1 parent 253168e commit 33711ad

File tree

3 files changed

+30
-3
lines changed

3 files changed

+30
-3
lines changed

packages/rrweb/src/record/observer.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
isBlocked,
1919
legacy_isTouchEvent,
2020
StyleSheetMirror,
21-
nowTimestamp,
21+
nowTimestamp
2222
} from '../utils';
2323
import { patch } from '@rrweb/utils';
2424
import type { observerParam, MutationBufferParam } from '../types';
@@ -54,10 +54,12 @@ import type {
5454
} from '@rrweb/types';
5555
import MutationBuffer from './mutation';
5656
import { callbackWrapper } from './error-handler';
57-
import dom, { mutationObserverCtor } from '@rrweb/utils';
57+
import dom, { mutationObserverCtor, getUntaintedProxy } from '@rrweb/utils';
5858

5959
export const mutationBuffers: MutationBuffer[] = [];
6060

61+
const Proxy = getUntaintedProxy();
62+
6163
// Event.path is non-standard and used in some older browsers
6264
type NonStandardEvent = Omit<Event, 'composedPath'> & {
6365
path: EventTarget[];

packages/rrweb/src/utils.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {
1919
nativeSetTimeout,
2020
} from 'rrweb-snapshot';
2121
import { RRNode, RRIFrameElement, BaseRRNode } from 'rrdom';
22-
import dom from '@rrweb/utils';
22+
import dom, { getUntaintedProxy } from '@rrweb/utils';
2323

2424
function getWindow(documentOrWindow: Document | IWindow): IWindow {
2525
const defaultView = (documentOrWindow as Document).defaultView;
@@ -73,7 +73,9 @@ export let _mirror: DeprecatedMirror = {
7373
console.error(DEPARTED_MIRROR_ACCESS_WARNING);
7474
},
7575
};
76+
7677
if (typeof window !== 'undefined' && window.Proxy && window.Reflect) {
78+
const Proxy = getUntaintedProxy();
7779
_mirror = new Proxy(_mirror, {
7880
get(target, prop, receiver) {
7981
if (prop === 'map') {

packages/utils/src/index.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,29 @@ export function mutationObserverCtor(): (typeof MutationObserver)['prototype']['
239239
return getUntaintedPrototype('MutationObserver').constructor;
240240
}
241241

242+
// Some libraries (i.e. jsPDF v1.1.135) override window.Proxy with their own implementation
243+
// Try to pull a clean implementation from a newly created iframe
244+
export function getUntaintedProxy(): ProxyConstructor {
245+
let Proxy = window.Proxy;
246+
try {
247+
if (
248+
typeof window.Proxy !== 'function' ||
249+
!window.Proxy?.toString().includes('[native code]')
250+
) {
251+
const cleanFrame = document.createElement('iframe');
252+
cleanFrame.style.display = 'none';
253+
document.documentElement.appendChild(cleanFrame);
254+
Proxy =
255+
(cleanFrame.contentWindow as Window & { Proxy: typeof Proxy })?.Proxy ||
256+
window.Proxy;
257+
document.documentElement.removeChild(cleanFrame);
258+
}
259+
} catch (err) {
260+
console.debug('Unable to get untainted Proxy from iframe', err);
261+
}
262+
return Proxy;
263+
}
264+
242265
// copy from https://github.com/getsentry/sentry-javascript/blob/b2109071975af8bf0316d3b5b38f519bdaf5dc15/packages/utils/src/object.ts
243266
export function patch(
244267
source: { [key: string]: any },

0 commit comments

Comments
 (0)