-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
adjust checking for internal and public errors #153
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
on a second thought, symbols might not be the best fit here. will write a comment to explain
src/errors/InternalError.ts
Outdated
export class InternalError<T = ErrorDetails> extends Error { | ||
readonly [Symbol.for(INTERNAL_ERROR_SYMBOL_KEY)] = true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Problem with using a symbol here is that it might make the implementation more fragile than intended.
Imagine that node-core 11 throws an error somewhere deep in your dependencies, and your app is using node-core 12. those will be two separate imports, and each will have their own Symbol instance, so errors from one node-core version will no longer be recognized as errors from another node-core version.
plain string field would work better here. it will have worse encapsulation, but it's unlikely to cause any real issues
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't feel like having a plain text field would change anything about backward compatibility. This new field would be only available in node-code v12 so the same problem as for symbol.
The only difference between the Symbol and plain text is that Symbol won't be serialized in the case of JSON.stringify(err)
or it won't be iterable with Object.entries(err)
so that it will behave the same as node-core v11.
I think that instead, we should adjust how we check if the error is internal or not so we might still support the old way of checking for it like
return isError(error) && (error[Symbol.for(INTERNAL_ERROR_SYMBOL_KEY)] === true || error.name === 'InternalError')
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've done a naive test, and within same realm, indeed, Symbol.for
is using a global registry, so we receive same symbol for the same string, and everything works as expected.
Tomorrow I'll setup a test with separate realms and see if it still doesn't break.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've already tested it:
import { createContext, runInContext } from 'node:vm';
import { isNativeError } from 'node:util/types'
const errContext = {};
createContext(errContext);
const errResult = runInContext(`new Error('Unknown')`, errContext);
console.log(errResult instanceof Error) // false
console.log(isNativeError(errResult)) // true
const symbolContext = {};
createContext(symbolContext);
const symbolResult = runInContext(`Symbol.for('ANY')`, errContext);
console.log(symbolResult === Symbol.for('ANY')) // true
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reproduction for the problem: lokalise/node-service-template#761
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will test more later, but adjusting this later should be a pretty minor non-breaking change
Changes
Please describe
Checklist
major
,minor
,patch
orskip-release