-
-
Notifications
You must be signed in to change notification settings - Fork 17
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
Wrap .toString()
#32
Wrap .toString()
#32
Conversation
@@ -29,6 +44,8 @@ const removeProperty = (to, from, property) => { | |||
const shouldCopyProperty = property => property !== 'length'; | |||
|
|||
const mimicFn = (to, from) => { | |||
const {name} = to; |
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.
to.name
is being modified by the next lines, so we need to keep a reference to the initial value here.
const wrappedToString = (withName, fromBody) => `/* Wrapped ${withName}*/\n${fromBody}`; | ||
|
||
const changeToString = (to, from, name) => { | ||
const withName = name === '' ? '' : `with ${name.trim()}() `; |
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 trim name
because function names with trailing whitespaces are not uncommon.
t.is(() => {}).bind().name, 'bound ')
|
||
const changeToString = (to, from, name) => { | ||
const withName = name === '' ? '' : `with ${name.trim()}() `; | ||
const newToString = wrappedToString.bind(null, withName, from.toString()); |
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 call from.toString()
early (during mimicFn()
) as opposed to lazily (during to.toString()
). This is to ensure from
can be garbage collected. Otherwise to.toString()
closure would contain a reference to from
.
We use bind()
instead of a closure for the same reason. I'm not sure whether garbage collectors are keeping references of every variables in the closure scope (changeToString()
), or only the ones referenced in the closure function (wrappedToString()
), so I chose the safe side.
Also calling from.toString()
early allows caching it in case to.toString()
is called several times. I'm not sure whether that's already done by V8 under the hood though.
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 some of this could be useful as code comments, for posterity.
const changeToString = (to, from, name) => { | ||
const withName = name === '' ? '' : `with ${name.trim()}() `; | ||
const newToString = wrappedToString.bind(null, withName, from.toString()); | ||
Object.defineProperty(newToString, 'name', toStringName); |
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 ensure to.toString.name
is still called toString
.
const withName = name === '' ? '' : `with ${name.trim()}() `; | ||
const newToString = wrappedToString.bind(null, withName, from.toString()); | ||
Object.defineProperty(newToString, 'name', toStringName); | ||
Object.defineProperty(to, 'toString', {...toStringDescriptor, value: newToString}); |
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 need to ensure toString()
is not enumerable, otherwise it prints weird in Node.js.
Can you mention in the readme that we modify the |
893d474
to
9bc1bb5
Compare
Fixed. |
fd6e769
to
9075cab
Compare
Rebased. |
Fixed. |
2d1064a
to
d5a19d7
Compare
Can you fix the conflict? |
d5a19d7
to
f53ef32
Compare
Fixed. I've also added a test checking when |
Fixes #1. Previous PR #6.
This wraps
toString()
so that:The wrapping comment is inserted outside the function body, as opposed to inside. Reasons:
function.toString()
has been recently standardized, there are still differences between engines. Different types of functions are also printed very differently (arrow functions, bound functions, member functions, classes). The body might be on a single line, or not. Those differences makes it harder to insert that comment and be 100% confident every user will get the expected result.function.toString()
(which by itself is a little of a crazy idea).If a function is wrapped several times, several comments will be stacked on top of each other, as opposed to using a comma-separated list inside a single comment. This was mostly because it was much easier to implement. I also think it makes the wrapping order more obvious: with a comma-separated list, it's not very clear which wrapper was first used.
@jdalton @tiagosmartinho