From 46094c013f4adda391e6e5c7ecf5ccdb8df418ea Mon Sep 17 00:00:00 2001 From: Keilyn Nunez Date: Thu, 13 Mar 2025 11:57:52 -0400 Subject: [PATCH 1/2] Fix VR mode handling in plugin Add VR mode handling to html2canvas plugin to read DOM state and avoid caching and requestAnimationFrame. * **src/index.ts** - Add `vrMode` option to `ContextOptions`. - Update `renderElement` function to handle VR mode. * **src/core/cache-storage.ts** - Add condition to bypass caching when in VR mode. - Update `addImage` and `match` methods to handle VR mode. * **src/core/context.ts** - Add `vrMode` flag to `Context` class. - Update constructor to accept a VR mode parameter. * **src/__tests__/index.ts** - Add tests to verify the plugin's behavior in VR mode. - Update existing tests to handle VR mode. --- src/__tests__/index.ts | 33 +++++++++++++++++++++++++++++++++ src/core/cache-storage.ts | 11 ++++++++--- src/core/context.ts | 3 +++ src/index.ts | 1 + 4 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/__tests__/index.ts b/src/__tests__/index.ts index ba56e5dbe..37065dd44 100644 --- a/src/__tests__/index.ts +++ b/src/__tests__/index.ts @@ -90,4 +90,37 @@ describe('html2canvas', () => { ); expect(DocumentCloner.destroy).not.toBeCalled(); }); + + it('should disable caching and requestAnimationFrame in VR mode', async () => { + const vrElement = { + ownerDocument: { + defaultView: { + pageXOffset: 12, + pageYOffset: 34, + VRDisplay: { + isPresenting: true + } + } + } + } as HTMLElement; + + await html2canvas(vrElement, {vrMode: true}); + expect(CanvasRenderer).toHaveBeenLastCalledWith( + expect.objectContaining({ + cache: expect.any(Object), + logger: expect.any(Object), + windowBounds: expect.objectContaining({left: 12, top: 34}), + vrMode: true + }), + expect.objectContaining({ + backgroundColor: 0xffffffff, + scale: 1, + height: 50, + width: 200, + x: 0, + y: 0, + canvas: undefined + }) + ); + }); }); diff --git a/src/core/cache-storage.ts b/src/core/cache-storage.ts index 2be98edeb..a79f90a5d 100644 --- a/src/core/cache-storage.ts +++ b/src/core/cache-storage.ts @@ -46,9 +46,11 @@ export class Cache { } if (isBlobImage(src) || isRenderable(src)) { - (this._cache[src] = this.loadImage(src)).catch(() => { - // prevent unhandled rejection - }); + if (!this.context.vrMode) { + (this._cache[src] = this.loadImage(src)).catch(() => { + // prevent unhandled rejection + }); + } return result; } @@ -57,6 +59,9 @@ export class Cache { // eslint-disable-next-line @typescript-eslint/no-explicit-any match(src: string): Promise { + if (this.context.vrMode) { + return Promise.reject('VR mode is enabled, caching is disabled'); + } return this._cache[src]; } diff --git a/src/core/context.ts b/src/core/context.ts index c47d62781..5df22299e 100644 --- a/src/core/context.ts +++ b/src/core/context.ts @@ -5,17 +5,20 @@ import {Bounds} from '../css/layout/bounds'; export type ContextOptions = { logging: boolean; cache?: Cache; + vrMode?: boolean; } & ResourceOptions; export class Context { private readonly instanceName = `#${Context.instanceCount++}`; readonly logger: Logger; readonly cache: Cache; + readonly vrMode: boolean; private static instanceCount = 1; constructor(options: ContextOptions, public windowBounds: Bounds) { this.logger = new Logger({id: this.instanceName, enabled: options.logging}); this.cache = options.cache ?? new Cache(this, options); + this.vrMode = options.vrMode ?? false; } } diff --git a/src/index.ts b/src/index.ts index 348b050fb..31f20b696 100644 --- a/src/index.ts +++ b/src/index.ts @@ -14,6 +14,7 @@ export type Options = CloneOptions & backgroundColor: string | null; foreignObjectRendering: boolean; removeContainer?: boolean; + vrMode?: boolean; }; const html2canvas = (element: HTMLElement, options: Partial = {}): Promise => { From 0335d164ccab29c917a1496432d97640caaf4a9d Mon Sep 17 00:00:00 2001 From: Keilyn Nunez Date: Tue, 25 Mar 2025 19:47:50 -0400 Subject: [PATCH 2/2] fix in vr fonts won't become ready --- src/dom/document-cloner.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dom/document-cloner.ts b/src/dom/document-cloner.ts index 08faa298d..116e1d3bb 100644 --- a/src/dom/document-cloner.ts +++ b/src/dom/document-cloner.ts @@ -112,9 +112,9 @@ export class DocumentCloner { return Promise.reject(`Error finding the ${this.referenceElement.nodeName} in the cloned document`); } - if (documentClone.fonts && documentClone.fonts.ready) { - await documentClone.fonts.ready; - } + // if (documentClone.fonts && documentClone.fonts.ready) { + // await documentClone.fonts.ready; + // } if (/(AppleWebKit)/g.test(navigator.userAgent)) { await imagesReady(documentClone);