bun icon indicating copy to clipboard operation
bun copied to clipboard

Support `node-canvas`

Open robobun opened this issue 2 years ago • 22 comments

node-canvas does not currently work with Bun as it relies on some v8-specific APIs in Node

We may eventually implement these: https://github.com/oven-sh/bun/issues/3110

Or perhaps it would be easier to upstream a fix

This also blocks jsdom

robobun avatar Sep 20 '23 22:09 robobun

Related to https://github.com/oven-sh/bun/issues/3110

Original issue:


Hello! I've installed canvas on my project and seem to be getting errors whenever I use it. I created a repository with the bare code required to create the error.

Code:

import * as canvas from "canvas";

(async () => {
    canvas.loadImage("https://static.bunnycdn.ru/i/cache/images/3/37/375e7fdc580766874948e5bf678e2a8a.jpg").then((image) => {
        console.log("Loaded!");

        const c = canvas.createCanvas(image.width, image.height);
        const context = c.getContext('2d');
        context.drawImage(image, 0, 0);
    })
});

Error:

error: Cannot find module "../build/Release/canvas.node" from "/Users/eltik/Documents/Coding/Bun-canvas/node_modules/canvas/lib/bindings.js"
error: script "start" exited with code 1 (SIGHUP)

Repository: https://github.com/Eltik/Bun-canvas

Originally reported on Discord: Incompatibility with Canvas

colinhacks avatar Sep 20 '23 22:09 colinhacks

Having the same issue in my Nuxt application, when I try to deserialise my imageDataUrl on the API server

SalahEddin avatar Oct 26 '23 12:10 SalahEddin

I have been playing around with Bun since about 1.0.2 and node-canvas is a package I use extensively for generating server side charts through Chart.js. For modules that do not require canvas, Bun is great and I love being able to run Typescript modules directly without transpiling. But most of the projects are Chart.js based. I understand there are two issues with node-canvas support but the one I run into is the lack of support for the node_module_register API entry point. The other issues reported is related to the npm registry and a background update.

Whobeu avatar Dec 26 '23 15:12 Whobeu

Any update on this? facing the same error

bun --watch index.ts
error: Cannot find module "../build/Release/canvas.node" from "/Users/harpreetsingh/Projects/imageoptimizer/node_modules/canvas/lib/bindings.js"

siinghd avatar Jan 07 '24 16:01 siinghd

I have the same error with just installed canvas: CleanShot 2024-01-27 at 13 05 19

medzhidov avatar Jan 27 '24 07:01 medzhidov

Are there any working alternatives in the mean time?

btakita avatar Feb 06 '24 04:02 btakita

Facing same issue on Bun using ascii-art package

andres-carvajal avatar Feb 08 '24 17:02 andres-carvajal

+1 here. support for canvas is the last holdout for us to adopt bun install in @faire's frontend monorepo.

chriskrogh avatar Feb 14 '24 02:02 chriskrogh

FWIW there is canvaskit-wasm.

btakita avatar Feb 14 '24 05:02 btakita

FWIW there is canvaskit-wasm.

some of our modules (including jsdom) try to link canvas without actually depending on it. is there a way to get them to link canvaskit-wasm instead of canvas? if not, I think we need to wait for support

chriskrogh avatar Feb 14 '24 15:02 chriskrogh

@chriskrogh Would assigning the canvas api from canvis-kit onto globalThis work?

btakita avatar Feb 14 '24 21:02 btakita

@chriskrogh Would assigning the canvas api from canvis-kit onto globalThis work?

I'm not sure when I would do that? this issue arises early on in the installation process and aborts bun install entirely (node_modules aren't generated)

chriskrogh avatar Feb 20 '24 18:02 chriskrogh

When are we gonna have this?

shimizudev avatar May 25 '24 11:05 shimizudev

I think I'm hitting the same thing, I have a project that works with node and when I try to use bun instead I get:

╰─(base) ⠠⠵ bun run  src/scripts/process_scenes.ts --loop                                                     on master|✚2-29…5
bun: symbol lookup error: /home/arthur/dev/ai/manga/node_modules/opencv4nodejs/build/Release/opencv4nodejs.node: undefined symbol: node_module_register

Is this the correct issue to report this / follow, or should I file a separate issue ?

Thanks.

arthurwolf avatar May 26 '24 18:05 arthurwolf

is this likely to be resolved soon?

hushoca avatar May 31 '24 20:05 hushoca

and this error?

root@celestrox:~/celestrox/backend# bun run ./src/server.ts bun: symbol lookup error: /root/celestrox/backend/node_modules/cpu-features/build/Release/cpufeatures.node: undefined symbol: node_module_register

alexdsgmoura avatar Jun 14 '24 14:06 alexdsgmoura

I got the same error trying to move to Bun. I have several projects with C Bidings libs, It would be awesome to have this support.

blueonrails avatar Jun 14 '24 17:06 blueonrails

Bun recode of my API currently halted because of this issue :(

aidendotgg avatar Jun 14 '24 21:06 aidendotgg

For anyone looking for an alternative, I was able to use @napi-rs/canvas. It was basically a drag and drop replacement other than a few lines.

aidendotgg avatar Jun 15 '24 03:06 aidendotgg

Thank you, @ignSKRRRTT!

Got a puzzle game image generator that I could not continue work on until this was figured out.

maietta avatar Jun 15 '24 04:06 maietta

This is blocked on #4290 or https://github.com/Automattic/node-canvas/pull/2235 (node-canvas 3.0), whichever happens first

As of node-canvas v2.11.2, here are the list of symbols we would need to implement in order to support this version:

  • Nan::ObjectWrap::WeakCallback(v8::WeakCallbackInfo<Nan::ObjectWrap> const&)
  • node::Buffer::Copy(v8::Isolate*, char const*, unsigned long)
  • node::Buffer::Data(v8::Local<v8::Object>)
  • node::Buffer::HasInstance(v8::Local<v8::Value>)
  • node::Buffer::Length(v8::Local<v8::Object>)
  • node::Buffer::New(v8::Isolate*, char*, unsigned long, void (*)(char*, void*), void*)
  • node::Buffer::New(v8::Isolate*, char*, unsigned long)
  • node::EmitAsyncDestroy(v8::Isolate*, node::async_context)
  • node::EmitAsyncInit(v8::Isolate*, v8::Local<v8::Object>, v8::Local<v8::String>, double)
  • node::ErrnoException(v8::Isolate*, int, char const*, char const*, char const*)
  • node::MakeCallback(v8::Isolate*, v8::Local<v8::Object>, v8::Local<v8::Function>, int, v8::Local<v8::Value>*, node::async_context)
  • uv_default_loop
  • uv_queue_work
  • v8::api_internal::ClearWeak(unsigned long*)
  • v8::api_internal::DisposeGlobal(unsigned long*)
  • v8::api_internal::FromJustIsNothing()
  • v8::api_internal::GlobalizeReference(v8::internal::Isolate*, unsigned long)
  • v8::api_internal::MakeWeak(unsigned long*, void*, void (*)(v8::WeakCallbackInfo<void> const&), v8::WeakCallbackType)
  • v8::api_internal::ToLocalEmpty()
  • v8::Array::Length() const
  • v8::Array::New(v8::Isolate*, int)
  • v8::ArrayBuffer::GetBackingStore()
  • v8::ArrayBuffer::New(v8::Isolate*, unsigned long)
  • v8::ArrayBufferView::Buffer()
  • v8::ArrayBufferView::ByteLength()
  • v8::ArrayBufferView::ByteOffset()
  • v8::BackingStore::Data() const
  • v8::Context::GetIsolate()
  • v8::Context::Global()
  • v8::Date::ValueOf() const
  • v8::EscapableHandleScopeBase::EscapableHandleScopeBase(v8::Isolate*)
  • v8::EscapableHandleScopeBase::EscapeSlot(unsigned long*)
  • v8::Exception::Error(v8::Local<v8::String>, v8::Local<v8::Value>)
  • v8::Exception::RangeError(v8::Local<v8::String>, v8::Local<v8::Value>)
  • v8::Exception::TypeError(v8::Local<v8::String>, v8::Local<v8::Value>)
  • v8::External::New(v8::Isolate*, void*)
  • v8::External::Value() const
  • v8::Float64Array::New(v8::Local<v8::ArrayBuffer>, unsigned long, unsigned long)
  • v8::Function::Call(v8::Local<v8::Context>, v8::Local<v8::Value>, int, v8::Local<v8::Value>*)
  • v8::Function::New(v8::Local<v8::Context>, void (*)(v8::FunctionCallbackInfo<v8::Value> const&), v8::Local<v8::Value>, int, v8::ConstructorBehavior, v8::SideEffectType)
  • v8::Function::NewInstance(v8::Local<v8::Context>, int, v8::Local<v8::Value>*) const
  • v8::FunctionTemplate::GetFunction(v8::Local<v8::Context>)
  • v8::FunctionTemplate::HasInstance(v8::Local<v8::Value>)
  • v8::FunctionTemplate::InstanceTemplate()
  • v8::FunctionTemplate::New(v8::Isolate*, void (*)(v8::FunctionCallbackInfo<v8::Value> const&), v8::Local<v8::Value>, v8::Local<v8::Signature>, int, v8::ConstructorBehavior, v8::SideEffectType, v8::CFunction const*, unsigned short, unsigned short, unsigned short)
  • v8::FunctionTemplate::PrototypeTemplate()
  • v8::FunctionTemplate::SetClassName(v8::Local<v8::String>)
  • v8::HandleScope::~HandleScope()
  • v8::HandleScope::~HandleScope()
  • v8::HandleScope::CreateHandle(v8::internal::Isolate*, unsigned long)
  • v8::HandleScope::HandleScope(v8::Isolate*)
  • v8::Integer::New(v8::Isolate*, int)
  • v8::Integer::NewFromUnsigned(v8::Isolate*, unsigned int)
  • v8::internal::IsolateFromNeverReadOnlySpaceObject(unsigned long)
  • v8::Isolate::AdjustAmountOfExternalAllocatedMemory(long long)
  • v8::Isolate::GetCurrent()
  • v8::Isolate::GetCurrentContext()
  • v8::Isolate::ThrowException(v8::Local<v8::Value>)
  • v8::Number::New(v8::Isolate*, double)
  • v8::Object::Get(v8::Local<v8::Context>, unsigned int)
  • v8::Object::Get(v8::Local<v8::Context>, v8::Local<v8::Value>)
  • v8::Object::InternalFieldCount() const
  • v8::Object::New(v8::Isolate*)
  • v8::Object::Set(v8::Local<v8::Context>, v8::Local<v8::Value>, v8::Local<v8::Value>)
  • v8::Object::SetAlignedPointerInInternalField(int, void*)
  • v8::Object::SetInternalField(int, v8::Local<v8::Data>)
  • v8::Object::SlowGetAlignedPointerFromInternalField(int)
  • v8::Object::SlowGetInternalField(int)
  • v8::ObjectTemplate::New(v8::Isolate*, v8::Local<v8::FunctionTemplate>)
  • v8::ObjectTemplate::NewInstance(v8::Local<v8::Context>)
  • v8::ObjectTemplate::SetAccessor(v8::Local<v8::Name>, void (*)(v8::Local<v8::Name>, v8::PropertyCallbackInfo<v8::Value> const&), void (*)(v8::Local<v8::Name>, v8::Local<v8::Value>, v8::PropertyCallbackInfo<void> const&), v8::Local<v8::Value>, v8::PropertyAttribute, v8::SideEffectType, v8::SideEffectType)
  • v8::ObjectTemplate::SetInternalFieldCount(int)
  • v8::Signature::New(v8::Isolate*, v8::Local<v8::FunctionTemplate>)
  • v8::String::Length() const
  • v8::String::NewFromUtf8(v8::Isolate*, char const*, v8::NewStringType, int)
  • v8::String::WriteUtf8(v8::Isolate*, char*, int, int*, int) const
  • v8::Template::Set(v8::Local<v8::Name>, v8::Local<v8::Data>, v8::PropertyAttribute)
  • v8::TryCatch::~TryCatch()
  • v8::TryCatch::HasCaught() const
  • v8::TryCatch::ReThrow()
  • v8::TryCatch::TryCatch(v8::Isolate*)
  • v8::TypedArray::Length()
  • v8::Uint16Array::New(v8::Local<v8::ArrayBuffer>, unsigned long, unsigned long)
  • v8::Uint8ClampedArray::New(v8::Local<v8::ArrayBuffer>, unsigned long, unsigned long)
  • v8::Value::BooleanValue(v8::Isolate*) const
  • v8::Value::InstanceOf(v8::Local<v8::Context>, v8::Local<v8::Object>)
  • v8::Value::Int32Value(v8::Local<v8::Context>) const
  • v8::Value::IsArray() const
  • v8::Value::IsArrayBufferView() const
  • v8::Value::IsBoolean() const
  • v8::Value::IsDate() const
  • v8::Value::IsFunction() const
  • v8::Value::IsNumber() const
  • v8::Value::IsObject() const
  • v8::Value::IsUint16Array() const
  • v8::Value::IsUint32() const
  • v8::Value::IsUint8ClampedArray() const
  • v8::Value::NumberValue(v8::Local<v8::Context>) const
  • v8::Value::StrictEquals(v8::Local<v8::Value>) const
  • v8::Value::ToInt32(v8::Local<v8::Context>) const
  • v8::Value::ToObject(v8::Local<v8::Context>) const
  • v8::Value::ToString(v8::Local<v8::Context>) const
  • v8::Value::ToUint32(v8::Local<v8::Context>) const
  • v8::Value::Uint32Value(v8::Local<v8::Context>) const

Jarred-Sumner avatar Jul 15 '24 18:07 Jarred-Sumner

It is gonna take a year to implement all these

shimizudev avatar Jul 16 '24 04:07 shimizudev

I have the same error with just installed canvas: CleanShot 2024-01-27 at 13 05 19

got the same error, July 31st error: Cannot find module "../build/Release/canvas.node" from "/home/farquaad/xxx/xxx/xxx/node_modules/canvas/lib/bindings.js"

LordFarquaadtheCreator avatar Jul 31 '24 19:07 LordFarquaadtheCreator

Hi @robobun the module that you mean is canvas, not node-canvas, so it's not bun add node-canvas@next but bun add canvas@next

Sayrix avatar Aug 29 '24 17:08 Sayrix

Hi @robobun the module that you mean is canvas, not node-canvas, so it's not bun add node-canvas@next but bun add canvas@next

Thanks! It helps.

longlin10086 avatar Nov 08 '24 11:11 longlin10086

bun add canvas@next is successful, but when I bun ./server.js, I got error below:

error: Cannot find module '../build/Release/canvas.node' from 'E:\Projects\xxx\xxx\node_modules\canvas\lib\bindings.js'

Bun v1.2.19 (Windows x64)

And, yes, there is not any file in folder node_modules\canvas\build\Release.

Riant avatar Nov 24 '25 07:11 Riant