Skip to content

Commit

Permalink
impl #309 observe font face set changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Yuyz0112 committed Sep 16, 2020
1 parent 412f6ca commit 2440701
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 4 deletions.
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -58,6 +58,7 @@
"typescript": "^3.9.5"
},
"dependencies": {
"@types/css-font-loading-module": "0.0.4",
"@xstate/fsm": "^1.4.0",
"mitt": "^1.1.3",
"pako": "^1.0.11",
Expand Down
6 changes: 4 additions & 2 deletions scripts/repl.ts
Expand Up @@ -95,7 +95,8 @@ function getCode(): string {
window.__IS_RECORDING__ = true
rrweb.record({
emit: event => window._replLog(event),
recordCanvas: true
recordCanvas: true,
collectFonts: true
});
`);
page.on('framenavigated', async () => {
Expand All @@ -105,7 +106,8 @@ function getCode(): string {
window.__IS_RECORDING__ = true
rrweb.record({
emit: event => window._replLog(event),
recordCanvas: true
recordCanvas: true,
collectFonts: true
});
`);
}
Expand Down
12 changes: 12 additions & 0 deletions src/record/index.ts
Expand Up @@ -42,6 +42,7 @@ function record<T = eventWithTime>(
sampling = {},
mousemoveWait,
recordCanvas = false,
collectFonts = false,
} = options;
// runtime checks for user options
if (!emit) {
Expand Down Expand Up @@ -256,12 +257,23 @@ function record<T = eventWithTime>(
},
}),
),
fontCb: (p) =>
wrappedEmit(
wrapEvent({
type: EventType.IncrementalSnapshot,
data: {
source: IncrementalSource.Font,
...p,
},
}),
),
blockClass,
ignoreClass,
maskInputOptions,
inlineStylesheet,
sampling,
recordCanvas,
collectFonts,
},
hooks,
),
Expand Down
62 changes: 62 additions & 0 deletions src/record/observer.ts
@@ -1,4 +1,5 @@
import { INode, MaskInputOptions } from 'rrweb-snapshot';
import { FontFaceDescriptors, FontFaceSet } from 'css-font-loading-module';
import {
mirror,
throttle,
Expand Down Expand Up @@ -32,6 +33,8 @@ import {
MediaInteractions,
SamplingStrategy,
canvasMutationCallback,
fontCallback,
fontParam,
} from '../types';
import MutationBuffer from './mutation';

Expand Down Expand Up @@ -432,6 +435,56 @@ function initCanvasMutationObserver(
};
}

function initFontObserver(cb: fontCallback): listenerHandler {
const handlers: listenerHandler[] = [];

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

const originalFontFace = FontFace;
// tslint:disable-next-line: no-any
(window as any).FontFace = function FontFace(
family: string,
source: string | ArrayBufferView,
descriptors?: FontFaceDescriptors,
) {
const fontFace = new originalFontFace(family, source, descriptors);
fontMap.set(fontFace, {
family,
buffer: typeof source !== 'string',
descriptors,
fontSource:
typeof source === 'string'
? source
: // tslint:disable-next-line: no-any
JSON.stringify(Array.from(new Uint8Array(source as any))),
});
return fontFace;
};

const restoreHandler = patch(document.fonts, 'add', function (original) {
return function (this: FontFaceSet, fontFace: FontFace) {
setTimeout(() => {
const p = fontMap.get(fontFace);
if (p) {
cb(p);
fontMap.delete(fontFace);
}
}, 0);
return original.apply(this, [fontFace]);
};
});

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

This comment has been minimized.

Copy link
@eoghanmurray

eoghanmurray Sep 27, 2021

Contributor

Is this a typo? Should be FontFace?

This comment has been minimized.

Copy link
@Yuyz0112

Yuyz0112 Sep 29, 2021

Author Member

my bad, fixed in fe43860

});
handlers.push(restoreHandler);

return () => {
handlers.forEach((h) => h());
};
}

function mergeHooks(o: observerParam, hooks: hooksParam) {
const {
mutationCb,
Expand All @@ -443,6 +496,7 @@ function mergeHooks(o: observerParam, hooks: hooksParam) {
mediaInteractionCb,
styleSheetRuleCb,
canvasMutationCb,
fontCb,
} = o;
o.mutationCb = (...p: Arguments<mutationCallBack>) => {
if (hooks.mutation) {
Expand Down Expand Up @@ -498,6 +552,12 @@ function mergeHooks(o: observerParam, hooks: hooksParam) {
}
canvasMutationCb(...p);
};
o.fontCb = (...p: Arguments<fontCallback>) => {
if (hooks.font) {
hooks.font(...p);
}
fontCb(...p);
};
}

export default function initObservers(
Expand Down Expand Up @@ -539,6 +599,7 @@ export default function initObservers(
const canvasMutationObserver = o.recordCanvas
? initCanvasMutationObserver(o.canvasMutationCb, o.blockClass)
: () => {};
const fontObserver = o.collectFonts ? initFontObserver(o.fontCb) : () => {};

return () => {
mutationObserver.disconnect();
Expand All @@ -550,5 +611,6 @@ export default function initObservers(
mediaInteractionHandler();
styleSheetObserver();
canvasMutationObserver();
fontObserver();
};
}
16 changes: 16 additions & 0 deletions src/replay/index.ts
Expand Up @@ -813,6 +813,22 @@ export class Replayer {
} catch (error) {
this.warnCanvasMutationFailed(d, d.id, error);
}
break;
}
case IncrementalSource.Font: {
try {
const fontFace = new FontFace(
d.family,
d.buffer ? new Uint8Array(JSON.parse(d.fontSource)) : d.fontSource,
d.descriptors,
);
this.iframe.contentDocument?.fonts.add(fontFace);
} catch (error) {
if (this.config.showWarning) {
console.warn(error);
}
}
break;
}
default:
}
Expand Down
22 changes: 21 additions & 1 deletion src/types.ts
Expand Up @@ -5,6 +5,7 @@ import {
MaskInputOptions,
} from 'rrweb-snapshot';
import { PackFn, UnpackFn } from './packer/base';
import { FontFaceDescriptors } from 'css-font-loading-module';

export enum EventType {
DomContentLoaded,
Expand Down Expand Up @@ -71,6 +72,7 @@ export enum IncrementalSource {
MediaInteraction,
StyleSheetRule,
CanvasMutation,
Font,
}

export type mutationData = {
Expand Down Expand Up @@ -111,6 +113,10 @@ export type canvasMutationData = {
source: IncrementalSource.CanvasMutation;
} & canvasMutationParam;

export type fontData = {
source: IncrementalSource.Font;
} & fontParam;

export type incrementalData =
| mutationData
| mousemoveData
Expand All @@ -120,7 +126,8 @@ export type incrementalData =
| inputData
| mediaInteractionData
| styleSheetRuleData
| canvasMutationData;
| canvasMutationData
| fontData;

export type event =
| domContentLoadedEvent
Expand Down Expand Up @@ -172,6 +179,7 @@ export type recordOptions<T> = {
packFn?: PackFn;
sampling?: SamplingStrategy;
recordCanvas?: boolean;
collectFonts?: boolean;
// departed, please use sampling options
mousemoveWait?: number;
};
Expand All @@ -190,8 +198,10 @@ export type observerParam = {
inlineStylesheet: boolean;
styleSheetRuleCb: styleSheetRuleCallback;
canvasMutationCb: canvasMutationCallback;
fontCb: fontCallback;
sampling: SamplingStrategy;
recordCanvas: boolean;
collectFonts: boolean;
};

export type hooksParam = {
Expand All @@ -204,6 +214,7 @@ export type hooksParam = {
mediaInteaction?: mediaInteractionCallback;
styleSheetRule?: styleSheetRuleCallback;
canvasMutation?: canvasMutationCallback;
font?: fontCallback;
};

// https://dom.spec.whatwg.org/#interface-mutationrecord
Expand Down Expand Up @@ -328,6 +339,15 @@ export type canvasMutationParam = {
setter?: true;
};

export type fontParam = {
family: string;
fontSource: string;
buffer: boolean;
descriptors?: FontFaceDescriptors;
};

export type fontCallback = (p: fontParam) => void;

export type viewportResizeDimention = {
width: number;
height: number;
Expand Down
6 changes: 5 additions & 1 deletion tsconfig.json
Expand Up @@ -14,5 +14,9 @@
},
"compileOnSave": true,
"exclude": ["test"],
"include": ["src", "test.d.ts"]
"include": [
"src",
"test.d.ts",
"node_modules/@types/css-font-loading-module/index.d.ts"
]
}

0 comments on commit 2440701

Please sign in to comment.