question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

screenschot.getCanvas("perspective"): Script terminated by timeout on firefox

See original GitHub issue

Description: When trying to take screenshot from one scene, firefox reports a termination by timeout.

I’m using AR.js with Aframe.

Debugging logs (where $0 is the scene):

Some cookies are misusing the recommended “SameSite“ attribute 3
Use of the motion sensor is deprecated. webvr-polyfill.js:2292:11
No DPDB device match. webvr-polyfill.js:1963:10
Failed to recalculate device parameters. webvr-polyfill.js:1915:12
Using fallback Android device measurements. webvr-polyfill.js:1699:14
A-Frame Version: 1.0.4 (Date 2020-02-05, Commit #2b359246) index.js:92:8
three Version (https://github.com/supermedium/three.js): ^0.111.6 index.js:93:8
WebVR Polyfill Version: ^0.10.10 index.js:95:8
asm.js type error: Disabled by debugger aframe-ar.js
webvr-polyfill: Invalid timestamps detected: non-monotonic timestamp from devicemotion webvr-polyfill.js:669:14
THREE.WebGLRenderer: OES_texture_float_linear extension not supported. three.js:15943:13
No DPDB device match. webvr-polyfill.js:1963:10
Failed to recalculate device parameters. webvr-polyfill.js:1915:12
AR.js 3.3.1 - trackingBackend: artoolkit aframe-ar.js:3994:10
THREE.WebGLRenderer: EXT_texture_filter_anisotropic extension not supported. three.js:15943:13
ARjs.Anchor - changeMatrixMode: modelViewMatrix / markersAreaEnabled: false aframe-ar.js:3528:10
THREEx.ArMarkerControls: 'markersAreaEnabled' is not a property of this material. aframe-ar.js:2023:13
THREEx.ArMarkerControls: 'minConfidence' parameter is undefined. aframe-ar.js:2016:13
*** Camera Parameter resized from 640, 480. *** aframe-ar.js:2:23009
Allocated videoFrameSize 307200 aframe-ar.js:2:23009
Use of mozImageSmoothingEnabled is deprecated. Please use the unprefixed imageSmoothingEnabled property instead. aframe-ar.js:2608:8
Pattern detection mode set to 4. aframe-ar.js:2:23009
Pattern ratio size set to 0.500000. aframe-ar.js:2:23009
$0.components.screenshot.getCanvas("perspective")
webvr-polyfill: Invalid timestamps detected: Timestamp from devicemotion outside expected range. webvr-polyfill.js:669:14
Script terminated by timeout at:
flipPixelsVertically@https://aframe.io/releases/1.0.4/aframe.min.js:859:3957
renderCapture@https://aframe.io/releases/1.0.4/aframe.min.js:859:3723
getCanvas@https://aframe.io/releases/1.0.4/aframe.min.js:859:3266
@debugger eval code:1:26
screenshot.js:234:22
undefined

Image (where $0 is the scene): image

From the link provided, you can just click on the middle button to take a screenshot.

  • A-Frame Version: 1.0.4
  • Platform / Device: Firefox 83.1.0 / Android
  • Reproducible Code Snippet or URL: https://aquele.cafe

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
RickStanleycommented, Jan 6, 2021

From https://github.com/mozilla-mobile/fenix/issues/17058 :

Though it is still an issue in 84.1.2, I’ve updated the code that provides the screenshot without errors, for my use case.

Since I’ve solved my issue and updated the production code, I’m going to close this. If the FF Fenix team want to have a reproducible code, I can provide a zip file containing the old version.

The current code doesn’t improve the performance, it still takes a considerable amount of time, compared to other browsers, to process the image.

Working code for F.F. Fenix 83+ (Android 9)

Here’s a walkthrough if anyone stumble on this issue:

  1. Copy the code that flips the image vertically and put it in a inline Worker:
const flipper = (() => {
    const flipPixelsVertically = (msg) => {
        const {pixelsBuffer, width, height} = msg.data;
        const pixels = new Uint8Array(pixelsBuffer);
        const flippedPixels = pixels.slice(0);
        for (let x = 0; x < width; ++x) {
            for (let y = 0; y < height; ++y) {
                flippedPixels[x * 4 + y * width * 4] = pixels[x * 4 + (height - y) * width * 4];
                flippedPixels[x * 4 + 1 + y * width * 4] = pixels[x * 4 + 1 + (height - y) * width * 4];
                flippedPixels[x * 4 + 2 + y * width * 4] = pixels[x * 4 + 2 + (height - y) * width * 4];
                flippedPixels[x * 4 + 3 + y * width * 4] = pixels[x * 4 + 3 + (height - y) * width * 4];
            }
        }
        self.postMessage(flippedPixels.buffer, [flippedPixels.buffer]);
    };

    const blob = new Blob(['self.onmessage = ', flipPixelsVertically.toString()], { type: 'text/javascript' });
    const workerURL = URL.createObjectURL(blob);

    return new Worker(workerURL);
})();
  1. Copy the getCanvas method, applying some changes (hopefully the changes are obvious):
// `this` is the scene component.
const screenshotComponent = this.el.components.screenshot;
let isVREnabled;

const flipScreenshotPixelsVertically = () => {
  // Save the state.
  isVREnabled = this.el.renderer.xr.enabled;
  this.el.renderer.xr.enabled = false;

  screenshotComponent.quad.visible = false;

  const camera = this.data.camera ? this.data.camera.components.camera.camera : this.el.camera;
  const [width, height] = [screenshotComponent.data.width, screenshotComponent.data.height];
  const autoClear = this.el.renderer.autoClear;
  const renderer = this.el.renderer;
  // Create rendering target and buffer to store the read pixels.
  const output = screenshotComponent.getRenderTarget(width, height);
  const pixels = new Uint8Array(4 * width * height);
  // Resize quad, camera, and canvas.
  screenshotComponent.resize(width, height);
  // Render scene to render target.
  renderer.autoClear = true;
  renderer.clear();
  renderer.setRenderTarget(output);
  renderer.render(this.el.object3D, camera);
  renderer.autoClear = autoClear;
  // Read image pizels back.
  renderer.readRenderTargetPixels(output, 0, 0, width, height, pixels);
  renderer.setRenderTarget(null);

  // send to the inline worker.
  flipper.postMessage({ pixelsBuffer: pixels.buffer, width, height }, [pixels.buffer]);

  // wait for the message.
  return new Promise((resolve) => {
    flipper.onmessage = msg => {
      const imageData = new ImageData(new Uint8ClampedArray(msg.data), screenshotComponent.data.width, screenshotComponent.data.height);
      // Hide quad after projecting the image.
      screenshotComponent.quad.visible = false;
      // Copy pixels into canvas.
      screenshotComponent.ctx.putImageData(imageData, 0, 0);
      this.el.renderer.xr.enabled = isVREnabled;
      resolve();
    }
  });
};
  1. Use where it is needed. Example:
async function screenshotOnClick() {
    await flipScreenshotPixelsVertically();

   //... your code.
}
0reactions
RickStanleycommented, Nov 26, 2020

If it works in all browsers except Firefox it looks like a browser bug. Flipping the image is an expensive operation. Maybe some issue with Firefox memory management on mobile.

Yes, I agree. I was going to close this issue with a similar statement.

Sorry about the noise and thanks.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Stop connection timeouts from happening - want the page to ...
I run multiple tab that monitor various tools. These pages refresh themselves. The pages have to wait for each other to finish before...
Read more >
Take screenshots on Firefox - Mozilla Support
To take a screenshot: Right-clickHold down the control key while you click on an empty part of the page and select Take Screenshot....
Read more >
How can I adjust the Timeout setting? | Firefox Support Forum
I'm running some OBIEE reports in Firefox that by nature do take a long time to run. One of my local Tech Support...
Read more >
335058 - script timeout too small in firefox - Bugzilla@Mozilla
Does this actually happen with the extension-manager JS? I haven't seen it in quite some time and have tested operations with 100+ extensions...
Read more >
Taking screenshots — Firefox Source Docs documentation
Taking screenshots¶. You can use the Developer Tools to take a screenshot of the entire page, or of a single element in the...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found