Automattic / Automattic/node-canvas

canvas.Image should call onload asynchronously when src is set

Open
#2,264 6 comments 0 reactions 0 assignees View on GitHub
Bug
Dominant language
JavaScript
Stars
10.7k
Forks
1.2k
Avg merge
4d 8h
Merged PRs (30d)
1

Description

## Issue or Feature

The `Image` implementation lacks an `onload` call (at least based on https://github.com/Automattic/node-canvas/blob/master/lib/image.js), making it impossible to use it "the normal way" where the onload is our signal that image data is available and now we can do something with that data.

(`onload` on the HTML side = incredibly bad, do not use. `onload` on the JS side: unfortunately still extremely necessary for `Image`, `WebSocket`, etc. etc. it never went away in JS land and we kept reinforcing it by introducing new object types that kept the `onload` and `onerror` pattern firmly alive right up to today =S)

## Steps to Reproduce

```js
const IN_BROWSER = !!globalThis.document;

let Image = globalThis.Image;
let createCanvas = (w, h) => {
const cvs = globalThis.document.createElement(`canvas`);
cvs.width = w;
cvs.heigh = h;
return cvs;
};

if (!IN_BROWSER) {
const { createCanvas as create, Image as ImageClass } = await import(`canvas`);
createCanvas = create;
Image = ImageClass;
}

const img = new Image();
img.src = "./some/path.png";
img.onload = () => {
// actually do things here, because we like idempotent code that just runs,
// irrespective of whether it's in the browser or Node.js
const myCanvas = createCanvas(...);
};
```
The above code won't actually do anything for `node-canvas` (but will run perfectly fine in the browser) because the shimmed `Image` has no code to trigger the `onload` "callback".

## Suggested fix

Add an `onload` property with getter/setter:

```js
Object.defineProperty(Image.prototype, 'onload', {
get: function() { return this._onload },
set: function(fn) {
this._onload = fn;
if (this.src) fn();
}
);
```
And update `setSource` to something like

```js
function setSource (img, src, origSrc) {
SetSource.call(img, src)
img._originalSource = origSrc
img._onload?.()
}
```

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.