-
Notifications
You must be signed in to change notification settings - Fork 55
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
Add ability to compare functions #114
Comments
Hi! Thanks for opening the issue. Comparing JS functions by string is a bit risky for reasons of closure/scopes. E.g., a contrived, but simplified example: let x;
{
const val = "hi";
x = () => val;
}
let y;
{
const val = "ho";
y = () => val;
}
console.log("===", x === y); // => false
console.log("=== called", x() === y()); // => false
console.log("toString", x.toString() === y.toString()); // => true I'm also looking at the other "classic deep equals" libraries like lodash Thoughts? Oh, and if we do decide this is the right course forward, the proper way to do this would be to try and open upstream in fast-deep-equal first and then bring in here (but they're a bit behind). |
My PoV on this is if the same inline function is composed twice they should come out as equivalent. If there’s any change to the content of the function at all it shouldn’t be considered equal |
Yeah, so the problem is we can't easily introspect if values and scope change the actual content or determine if functions are "pure" (which would allow this type of comparison). In our case here Put another way, all of the existing comparisons unequivocally never produce a spurious |
Actually I’d argue they are the same because they’d reference the same scope variable |
Yeah, but they're different scopes (which can happen in like different objects, etc. that are broadly different) and most importantly produce different rendered results which is that a fast equality check is meant to protect you against (a Put another way, in my contrived example |
We need some sort of handling for functions though, otherwise this library is kinda useless for JSX with inline arrow functions (likely to be a common thing.) I know it’s not perfect but it should cover most common cases |
Hmmm... I do wonder if maybe there's some option of like "allow unsafe function string comparison" or even a custom comparator fn we could take to allow end users to control their own destiny (enable the functionality and then police their own code for safe usage...) |
I would advise against this as it's unsafe by default as @ryan-roemer suggested. It wouldn't be ideal for the library to be broken-by-default, but might be okay to allow people to opt into unsafe behavior. Here's a more realistic React example demonstrating this: import { useCallback, useState } from "react";
export default function Counter() {
const [counter, setCounter] = useState(0);
return (
<>
<Button onClick={() => setCounter((value) => value + 1)}>+</button>
<Button onClick={() => setCounter((value) => value - 1)}>-</button>
<Button onClick={() => alert(`Value: ${counter}`)}>Get value</button>
</>
);
} (Pretend In the case of the In theory you could parse the function to see whether there are any non-local variable references within it (references like In addition to the non-local reference issue, this would likely also break anyone using higher-order functions, as even if you changed a function-value-parameter to another one that has a different e.g. const handleClick = createClickHandler(flag ? doThis : doThat); If you imagine what the
Thus even if If we do add an option to opt into this, I'd recommend making the danger very clear in documentation and naming, prefixing it with |
useEvent is attempting to solve this problem another way, but it's not here, yet. You could introduce an option – I would vote for Also keep in mind you would need to use const a = () => 'a';
// Misleading
const b = () => 'b';
b.toString = () => '() => \'a\'';
// Malicious
const c => runMaliciousCode();
c.toString = () => '() => \'a\''; |
Perhaps using
Function.toString()
, just need to verify that two functions are the same through non-reference equality means since a lot of people write inline anonymous functions these daysThe text was updated successfully, but these errors were encountered: