Skip to content

Commit b8826e3

Browse files
authored
Merge pull request #129 from cdata/master
Add support for main thread OffscreenCanvas
2 parents 691ec31 + e5877d5 commit b8826e3

File tree

2 files changed

+43
-22
lines changed

2 files changed

+43
-22
lines changed

src/backend/spies/canvasSpy.ts

+14-3
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ import { Observable } from "../../shared/utils/observable";
22
import { OriginFunctionHelper } from "../utils/originFunctionHelper";
33
import { IContextInformation } from "../types/contextInformation";
44

5+
type CanvasConstructor = (new() => HTMLCanvasElement) | (new(...args: any[]) => OffscreenCanvas);
6+
57
export class CanvasSpy {
68
public readonly onContextRequested: Observable<IContextInformation>;
79

8-
constructor(private readonly canvas?: HTMLCanvasElement) {
10+
constructor(private readonly canvas?: HTMLCanvasElement | OffscreenCanvas) {
911
this.onContextRequested = new Observable<IContextInformation>();
1012
this.init();
1113
}
@@ -15,10 +17,14 @@ export class CanvasSpy {
1517
// tslint:disable-next-line
1618
const self = this;
1719

18-
const getContextSpied = function (this: HTMLCanvasElement) {
20+
const getContextSpied = function (this: HTMLCanvasElement | OffscreenCanvas) {
21+
const OriginalCanvasConstructor: CanvasConstructor = this instanceof HTMLCanvasElement ?
22+
HTMLCanvasElement :
23+
OffscreenCanvas;
24+
1925
const context = (self.canvas) ?
2026
OriginFunctionHelper.executeOriginFunction(this, "getContext", arguments) :
21-
OriginFunctionHelper.executePrototypeOriginFunction(this, HTMLCanvasElement, "getContext", arguments);
27+
OriginFunctionHelper.executePrototypeOriginFunction(this, OriginalCanvasConstructor, "getContext", arguments);
2228

2329
if (arguments.length > 0 && arguments[0] === "2d") {
2430
return context;
@@ -47,6 +53,11 @@ export class CanvasSpy {
4753
else {
4854
OriginFunctionHelper.storePrototypeOriginFunction(HTMLCanvasElement, "getContext");
4955
(HTMLCanvasElement as any).prototype.getContext = getContextSpied;
56+
57+
if (typeof OffscreenCanvas !== "undefined") {
58+
OriginFunctionHelper.storePrototypeOriginFunction(OffscreenCanvas, "getContext");
59+
(OffscreenCanvas as any).prototype.getContext = getContextSpied;
60+
}
5061
}
5162
}
5263
}

src/spector.ts

+29-19
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { CaptureMenu } from "./embeddedFrontend/captureMenu/captureMenu";
1313
import { ResultView } from "./embeddedFrontend/resultView/resultView";
1414

1515
export interface IAvailableContext {
16-
readonly canvas: HTMLCanvasElement;
16+
readonly canvas: HTMLCanvasElement | OffscreenCanvas;
1717
readonly contextSpy: ContextSpy;
1818
}
1919

@@ -22,8 +22,12 @@ export const EmbeddedFrontend = {
2222
ResultView,
2323
};
2424

25+
interface IAnnotatedOffscreenCanvas extends OffscreenCanvas {
26+
__spector_context_type?: string;
27+
}
28+
2529
export class Spector {
26-
public static getFirstAvailable3dContext(canvas: HTMLCanvasElement): WebGLRenderingContexts {
30+
public static getFirstAvailable3dContext(canvas: HTMLCanvasElement | OffscreenCanvas): WebGLRenderingContexts {
2731
// Custom detection to run in the extension.
2832
return this.tryGetContextFromHelperField(canvas) ||
2933
this.tryGetContextFromCanvas(canvas, "webgl") ||
@@ -32,19 +36,25 @@ export class Spector {
3236
this.tryGetContextFromCanvas(canvas, "experimental-webgl2");
3337
}
3438

35-
private static tryGetContextFromHelperField(canvas: HTMLCanvasElement): WebGLRenderingContexts {
36-
const type = canvas.getAttribute("__spector_context_type");
39+
private static tryGetContextFromHelperField(canvas: HTMLCanvasElement | OffscreenCanvas): WebGLRenderingContexts {
40+
const type: string|void = canvas instanceof HTMLCanvasElement ?
41+
canvas.getAttribute("__spector_context_type") :
42+
(canvas as IAnnotatedOffscreenCanvas).__spector_context_type;
43+
3744
if (type) {
3845
return this.tryGetContextFromCanvas(canvas, type);
3946
}
4047

4148
return undefined;
4249
}
4350

44-
private static tryGetContextFromCanvas(canvas: HTMLCanvasElement, type: string): WebGLRenderingContexts {
51+
private static tryGetContextFromCanvas(canvas: HTMLCanvasElement | OffscreenCanvas, type: string): WebGLRenderingContexts {
4552
let context: WebGLRenderingContexts;
4653
try {
47-
context = canvas.getContext(type) as WebGLRenderingContexts;
54+
// Cast canvas to any because lib.dom.d.ts types are not suitably
55+
// general to allow for custom canvas context types that are
56+
// potentially specified by __spector_context_type:
57+
context = (canvas as any).getContext(type) as WebGLRenderingContexts;
4858
}
4959
catch (e) {
5060
// Nothing to do here, canvas has not been found.;
@@ -208,7 +218,7 @@ export class Spector {
208218
this.canvasSpy.onContextRequested.add(this.spyContext, this);
209219
}
210220

211-
public spyCanvas(canvas: HTMLCanvasElement): void {
221+
public spyCanvas(canvas: HTMLCanvasElement | OffscreenCanvas): void {
212222
if (this.canvasSpy) {
213223
this.onErrorInternal("Already spying canvas.");
214224
return;
@@ -222,7 +232,7 @@ export class Spector {
222232
return this.getAvailableContexts();
223233
}
224234

225-
public captureCanvas(canvas: HTMLCanvasElement,
235+
public captureCanvas(canvas: HTMLCanvasElement | OffscreenCanvas,
226236
commandCount = 0,
227237
quickCapture: boolean = false): void {
228238

@@ -245,7 +255,7 @@ export class Spector {
245255
commandCount = 0,
246256
quickCapture: boolean = false): void {
247257

248-
let contextSpy = this.getAvailableContextSpyByCanvas(context.canvas as HTMLCanvasElement);
258+
let contextSpy = this.getAvailableContextSpyByCanvas(context.canvas as HTMLCanvasElement | OffscreenCanvas);
249259

250260
if (!contextSpy) {
251261
if ((context as WebGL2RenderingContext).getIndexedParameter) {
@@ -266,7 +276,7 @@ export class Spector {
266276
contextSpy.onMaxCommand.add(this.stopCapture, this);
267277

268278
this.contexts.push({
269-
canvas: contextSpy.context.canvas as HTMLCanvasElement,
279+
canvas: contextSpy.context.canvas as HTMLCanvasElement | OffscreenCanvas,
270280
contextSpy,
271281
});
272282
}
@@ -314,26 +324,26 @@ export class Spector {
314324
}
315325
}
316326

317-
public captureNextFrame(obj: HTMLCanvasElement | WebGLRenderingContexts,
327+
public captureNextFrame(obj: HTMLCanvasElement | OffscreenCanvas | WebGLRenderingContexts,
318328
quickCapture: boolean = false): void {
319329

320-
if (obj instanceof HTMLCanvasElement) {
330+
if (obj instanceof HTMLCanvasElement || (self.OffscreenCanvas && obj instanceof OffscreenCanvas)) {
321331
this.captureCanvas(obj, 0, quickCapture);
322332
}
323333
else {
324-
this.captureContext(obj, 0, quickCapture);
334+
this.captureContext(obj as WebGLRenderingContexts, 0, quickCapture);
325335
}
326336
}
327337

328-
public startCapture(obj: HTMLCanvasElement | WebGLRenderingContexts,
338+
public startCapture(obj: HTMLCanvasElement | OffscreenCanvas | WebGLRenderingContexts,
329339
commandCount: number,
330340
quickCapture: boolean = false): void {
331341

332-
if (obj instanceof HTMLCanvasElement) {
342+
if (obj instanceof HTMLCanvasElement || (self.OffscreenCanvas && obj instanceof OffscreenCanvas)) {
333343
this.captureCanvas(obj, commandCount, quickCapture);
334344
}
335345
else {
336-
this.captureContext(obj, commandCount, quickCapture);
346+
this.captureContext(obj as WebGLRenderingContexts, commandCount, quickCapture);
337347
}
338348
}
339349

@@ -397,7 +407,7 @@ export class Spector {
397407
}
398408

399409
private spyContext(contextInformation: IContextInformation) {
400-
let contextSpy = this.getAvailableContextSpyByCanvas(contextInformation.context.canvas as HTMLCanvasElement);
410+
let contextSpy = this.getAvailableContextSpyByCanvas(contextInformation.context.canvas as HTMLCanvasElement | OffscreenCanvas);
401411
if (!contextSpy) {
402412
contextSpy = new ContextSpy({
403413
context: contextInformation.context,
@@ -408,15 +418,15 @@ export class Spector {
408418
contextSpy.onMaxCommand.add(this.stopCapture, this);
409419

410420
this.contexts.push({
411-
canvas: contextSpy.context.canvas as HTMLCanvasElement,
421+
canvas: contextSpy.context.canvas as HTMLCanvasElement | OffscreenCanvas,
412422
contextSpy,
413423
});
414424
}
415425

416426
contextSpy.spy();
417427
}
418428

419-
private getAvailableContextSpyByCanvas(canvas: HTMLCanvasElement): ContextSpy {
429+
private getAvailableContextSpyByCanvas(canvas: HTMLCanvasElement | OffscreenCanvas): ContextSpy {
420430
for (const availableContext of this.contexts) {
421431
if (availableContext.canvas === canvas) {
422432
return availableContext.contextSpy;

0 commit comments

Comments
 (0)