rrdom (#613)
* create rrdom package * test(rrdom): add unit tests for polyfill.ts * fix(rrweb snapshot): type check errors Errors are caused by the declaration similarity of @types/mocha and @types/jest if we install both of them in the whole project. * Set tagNames to upper case by default This mirrors the `Element.tagName` implementation: ``` For DOM trees which represent HTML documents, the returned tag name is always in the canonical upper-case form. For example, tagName called on a <div> element returns "DIV". ``` https://developer.mozilla.org/en-US/docs/Web/API/Element/tagName * Add workspace file * VSCode settings for rrdom tests * Add basic test for RRDocument * Only setup jest tests for rrdom * mock Node type and Event type for nodejs environment * test(rrdom): add snapshot for document.test.ts * fix issue of nwsapi import and add unit tests for rrdom * fix: querySelectorAll returns nothing when querying elements with ids and classNames * fix: error of unit test for Event polyfill Since Event class is built in nodejs after v15.0.0 * add a dummy implementation of canvas * add style element support * add unit test for style element Co-authored-by: Justin Halsall <Juice10@users.noreply.github.com>
This commit is contained in:
87
packages/rrdom/src/polyfill.ts
Normal file
87
packages/rrdom/src/polyfill.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
import { RRDocument, RRNode } from './document-nodejs';
|
||||
|
||||
/**
|
||||
* Polyfill the performance for nodejs.
|
||||
*/
|
||||
export function polyfillPerformance() {
|
||||
if (typeof window !== 'undefined' || 'performance' in global) return;
|
||||
((global as Window & typeof globalThis)
|
||||
.performance as unknown) = require('perf_hooks').performance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Polyfill requestAnimationFrame and cancelAnimationFrame for nodejs.
|
||||
*/
|
||||
export function polyfillRAF() {
|
||||
if (typeof window !== 'undefined' || 'requestAnimationFrame' in global)
|
||||
return;
|
||||
|
||||
const FPS = 60,
|
||||
INTERVAL = 1_000 / FPS;
|
||||
let timeoutHandle: NodeJS.Timeout | null = null,
|
||||
rafCount = 0,
|
||||
requests = Object.create(null);
|
||||
|
||||
function onFrameTimer() {
|
||||
const currentRequests = requests;
|
||||
requests = Object.create(null);
|
||||
timeoutHandle = null;
|
||||
Object.keys(currentRequests).forEach(function (id) {
|
||||
const request = currentRequests[id];
|
||||
if (request) request(Date.now());
|
||||
});
|
||||
}
|
||||
|
||||
function requestAnimationFrame(callback: (timestamp: number) => void) {
|
||||
const cbHandle = ++rafCount;
|
||||
requests[cbHandle] = callback;
|
||||
if (timeoutHandle === null)
|
||||
timeoutHandle = setTimeout(onFrameTimer, INTERVAL);
|
||||
return cbHandle;
|
||||
}
|
||||
|
||||
function cancelAnimationFrame(handleId: number) {
|
||||
delete requests[handleId];
|
||||
if (Object.keys(requests).length === 0 && timeoutHandle !== null) {
|
||||
clearTimeout(timeoutHandle);
|
||||
timeoutHandle = null;
|
||||
}
|
||||
}
|
||||
|
||||
(global as Window &
|
||||
typeof globalThis).requestAnimationFrame = requestAnimationFrame;
|
||||
(global as Window &
|
||||
typeof globalThis).cancelAnimationFrame = cancelAnimationFrame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to polyfill Event type.
|
||||
* The implementation of Event so far is empty because rrweb doesn't strongly depend on it in nodejs mode.
|
||||
* Note: The Event class is available through the global object from nodejs v15.0.0.
|
||||
*/
|
||||
export function polyfillEvent() {
|
||||
if (typeof Event !== 'undefined') return;
|
||||
(global.Event as unknown) = function () {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Polyfill Node type with RRNode for nodejs.
|
||||
*/
|
||||
export function polyfillNode() {
|
||||
if (typeof Node !== 'undefined') return;
|
||||
(global.Node as unknown) = RRNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Polyfill document object with RRDocument for nodejs.
|
||||
*/
|
||||
export function polyfillDocument() {
|
||||
if (typeof document !== 'undefined') return;
|
||||
const rrdom = new RRDocument();
|
||||
(() => {
|
||||
rrdom.appendChild(rrdom.createElement('html'));
|
||||
rrdom.documentElement.appendChild(rrdom.createElement('head'));
|
||||
rrdom.documentElement.appendChild(rrdom.createElement('body'));
|
||||
})();
|
||||
global.document = (rrdom as unknown) as Document;
|
||||
}
|
||||
Reference in New Issue
Block a user