Skip to content

An OffscreenCanvas could not be cloned because it was not transferred. #2848

@arsenpellumbi

Description

@arsenpellumbi

Stencil version:

 @stencil/core@latest

I'm submitting a:

[x] bug report
[ ] feature request
[ ] support request => Please do not submit support requests here, use one of these channels: https://stencil-worldwide.herokuapp.com/ or https://forum.ionicframework.com/

Current behavior:

Trying to transfer the OffscreenCanvas from main thread to a web-worker using StencilJS web-worker proxy. This prevents from using web-gl in web-workers.

Error:
cv-canvas-3469fcdb.js:65 Uncaught (in promise) DOMException: Failed to execute 'postMessage' on 'Worker': An OffscreenCanvas could not be cloned because it was not transferred.

Expected behavior:

All transfarable objects should be transferred as well, not only ArrayBuffers.
(https://developer.mozilla.org/en-US/docs/Web/API/Transferable)

Steps to reproduce:

Create a web-worker containing a simple method that accepts an OffscreenCanvas object as parameter.
Create a component that contains a canvas in its DOM. In componentDidLoad() event, call the web-worker method sending the OffscreenCanvas from canvas. It will give an error.

Related code:
Component: canvas.tsx

import { Component, h, State } from '@stencil/core';
import { init } from './web-gl.worker.ts';

@Component({
  tag: 'cv-canvas',
  styleUrl: 'cv-canvas.scss',
  shadow: true,
})
export class CvCanvas {
  canvas: HTMLCanvasElement;

  componentDidLoad() {
    const offscreenCanvas = this.canvas.transferControlToOffscreen();
    init(offscreenCanvas);
  }

  render() {
    return (
      <canvas ref={el => this.canvas = el} style={{"width": `${window.innerWidth}px`, "height": `${window.innerHeight - 120}px`, "top": "120px", "position": "fixed"}}></canvas>
    );
  }

}

Web-Worker: web-gl.worker.ts

let canvas: OffscreenCanvas;

export const init = async (offscrenCanvas: OffscreenCanvas) => {
  canvas = offscrenCanvas;
  return canvas;
};

Other information:

Error happens in worker-plugin.ts.

    const postMessage = (w) => (
      w.postMessage(
        [workerMsgId, pendingId, exportedMethod, args],
        args.filter(a => a instanceof ArrayBuffer)
      )
    );

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions