Anyhow... Lets tackle some error messages.
Btw, can't move the call to getContext to the front because if we return null we can't have the canvas initialized to webgl as it still needs to be able to provide other contexts like 2d. i.e.
Code: Select all
// Native behaviour. Assume webgl disabled from about:config. We perform these two consecutive calls:
canvas.getContext("webgl") -> null
canvas.getContext("2d") -> 2d context
// Assume webgl enabled.
canvas.getContext("webgl") -> webgl context
canvas.getContext("2d") -> null
Different types of errors I have encountered:
Code: Select all
TypeError: 'getContext' called on an object that does not implement interface HTMLCanvasElement. HTMLCanvasElement.prototype.getContext()
TypeError: HTMLCanvasElement.getContext: At least 1 argument required, but only 0 passed canvas.getContext()
TypeError: getContext is not a constructor new canvas.getContext
webglHook.js:
Code: Select all
function modifyGetContext(scope, env) {
let dispatchEvent = EventTarget.prototype.dispatchEvent;
let { Event } = scope;
for (let canvas of ["HTMLCanvasElement", "OffscreenCanvas"]) {
if (!(canvas in scope)) continue;
const getContext = scope[canvas].prototype.getContext;
const handler = cloneInto({
apply: function(targetObj, thisArg, argumentsList) {
if (thisArg instanceof HTMLCanvasElement && /webgl/i.test(argumentsList[0])) {
let target = canvas === "HTMLCanvasElement" && document.contains(thisArg) ? thisArg : scope;
env.port.postMessage("webgl", target);
return null;
}
return getContext.call(thisArg, ...argumentsList);
}
}, scope, {cloneFunctions: true});
const proxy = new scope.Proxy(getContext, handler);
scope[canvas].prototype.getContext = proxy;
}
}
Generating the error in the exported function for the right scope works around this, but there is no way to make the error message completely correct as the message should contain the line that is executed and this info is not available in the exported function. e.g.
Code: Select all
new canvas.getContext -> TypeError: canvas.getContext is not a constructor
new windows.canvas.getContext -> TypeError: windows.canvas.getContext is not a constructor
Also HTMLCanvasElement.prototype.getContext.length is now 1 as it should be.
Oh! Does line "let target = canvas === "HTMLCanvasElement" && document.contains(thisArg) ? thisArg : scope;" have some planned use? postMessage does not appear to use the target for anything.