-
-
Notifications
You must be signed in to change notification settings - Fork 85
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
Replace instanceof
checks to work across color.js sources
#605
Conversation
Instead of relying solely on `instanceof` to check if an argument is an instance of some class (eg. Color or ColorSpace), also checks the name of the constructors of the instance to see if any of them have the same name as the target class. This method isn't perfect, but it should work well enough given that it seems unlikely for a user of color.js to define their own unrelated class whose name conflicts with the library.
✅ Deploy Preview for colorjs ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
Forgot to remove this after debugging.
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.
Hey, thanks so much for working on this!
I love the idea of a generic isInstance()
factory! Do we still need the public-facing APIs? Not sure we have authors that need to check if an object is a ColorSpace or a Format (I'd wager in most cases ColorSpace.get()
would suffice). It seems more useful for Color
since it does more than the instance check, though even there a static isColor()
could be misconstrued as to also account for parseable color strings.
Since the API needs some more discussion, can we skip the public-facing APIs for now and just use private const
s in each corresponding module? It seems in most cases the instanceof
check is in the same module as the class it's checking, with one exception that can actually be refactored to a string check.
@@ -37,7 +37,7 @@ export default function getColor (color, options) { | |||
// Object fixup | |||
let space = color.space || color.spaceId; | |||
|
|||
if (!(space instanceof ColorSpace)) { | |||
if (!ColorSpace.isColorSpace(space)) { | |||
// Convert string id to color space object | |||
color.space = ColorSpace.get(space); |
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.
We could actually refactor this check to check if space
is a string.
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.
the util.isString()
is "slow" and came up as a hotspot when I was running the texel benchmarks so I don't think we should add an additional call to isString()
.
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.
Oh interesting. Maybe just typeof space === "string"
then?
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.
Changed in 0123830
Or actually — not use a const at all. Instead of Though wait a second, why are we generating functions at all? There is no one-time work that we are saving that way, it's literally function currying, that users of this function can do with |
src/color.js
Outdated
static isColorInstance = util.isInstance(this); | ||
|
||
static isColor (arg) { | ||
return Color.isColorInstance(arg) || Array.isArray(arg?.coords); |
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 think the second part of the check should test to see if arg
conforms to the PlainColorObject
interface.
src/color.d.ts
Outdated
@@ -159,6 +159,10 @@ declare class Color extends SpaceAccessors implements PlainColorObject { | |||
| Record<string, DefineFunctionHybrid> | |||
): void; | |||
|
|||
static isColorInstance (arg: any): arg is Color; | |||
|
|||
static isColor (arg: any): arg is (Color | { coords: Coords }); |
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.
static isColor (arg: any): arg is (Color | { coords: Coords }); | |
static isColor (arg: any): arg is (Color | PlainColorObject); |
I'm not convinced we need the static If we think it may be useful then I think we should add a standalone function that checks to see if an object conforms to the |
I wrote But if it's unlikely that developers would need to use these static methods, then I'd be fine with rewriting isInstance to just be a regular function with two parameters. |
Yeah, I think for now let's punt the static methods and just use |
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.
LGTM
Checks if the space is a string instead of checking if it's not a `ColorSpace` instance.
Is this ready for a re-review? Also, could you please add an entry to the changelog in the same PR? |
Should be ready now
Done! |
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.
LGTM, see comments on changelog. Thank you!
Co-authored-by: Lea Verou <lea@verou.me>
Closes #602
Instead of relying solely on
instanceof
to check if an argument is an instance of some class (eg. Color or ColorSpace), also checks the name of the constructors of the instance to see if any of them have the same name as the target class.This method isn't perfect, but it should work well enough given that it seems unlikely for a user of color.js to define their own unrelated class whose name conflicts with the library.
I'm open to changing this way of checking inheritance if anybody has better ideas.