Library throws strings instead of error objects
This is pretty bad because it makes it impossible to trace errors.
I think it would be a relatively easy fix here https://github.com/UrielCh/opencv4nodejs/blob/master/cc/native-node-utils/TryCatch.h#L32 unfortunately my CPP game is terrible and I've never worked on any CPP node modules.
Repro: new (require('@u4/opencv4nodejs').Mat)().getDataAsArray()
Thank you for pointing out the file that needs correction. I'm currently facing homelessness, so I'll address that once I've resolved this pressing issue.
Hey, I hope you're doing better, I'm interested in contributing, would you be able to provide some pointers on how to resolve this issue? Right now our workaround looks like this:
// Manually patch all opencv.* opencv.Mat/Contour.prototype.* methods to not throw strings
import * as cv from 'opencv4nodejs';
export class OpenCVWrappedError extends Error {
public override name = 'OpenCVWrappedError';
public constructor(
message: string,
public readonly functionName: string
) {
super(`${functionName}: ${message}`);
}
}
const patchNoThrowString = (obj: Record<string, unknown>) => {
for (const [key, value] of Object.entries(obj)) {
// ignore what is likely classes
if (
typeof value !== 'function' ||
key[0]!.toUpperCase() === key[0] ||
!!Object.keys(value.prototype as object).length
) {
continue;
}
// eslint-disable-next-line unicorn/prefer-ternary
if (key.endsWith('Async')) {
// we specifically use a different name, `jest` in it's infinite wisdom resets js modules but NOT native modules
// which leads to opencv loading multiple times but not it's bindings
// further it relies on `.prototype.constructor.name` being present thus this function cannot be async...
// eslint-disable-next-line @typescript-eslint/promise-function-async
obj[key] = function asyncProxy(...args: unknown[]) {
// eslint-disable-next-line @typescript-eslint/return-await
return (value as (...args: unknown[]) => Promise<unknown>)
.call(this, ...args)
.catch((error: unknown) => {
if (typeof error === 'string') {
throw new OpenCVWrappedError(error, key);
}
throw error;
});
};
} else {
obj[key] = function proxy(...args: unknown[]): unknown {
try {
return value.call(this, ...args) as unknown;
} catch (error) {
if (typeof error === 'string') {
throw new OpenCVWrappedError(error, key);
}
throw error;
}
};
}
}
};
// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports
patchNoThrowString(require('opencv4nodejs') as Record<string, unknown>);
patchNoThrowString(cv.Mat.prototype as unknown as Record<string, unknown>);
patchNoThrowString(cv.Contour.prototype as unknown as Record<string, unknown>);