-
Notifications
You must be signed in to change notification settings - Fork 47.3k
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
Enforce no boolean or string constructors #9082
Enforce no boolean or string constructors #9082
Conversation
What's the motivation here? Also we should be wary that |
|
Good point. I'll add a clarification to the error message. |
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 really care. I tend to think that the constructors are a little more readable but I'm not opposed to this if y'all want it.
The reason "someone could override" is interesting is because it makes it harder for VMs and static compilers to assume that it is not overridden. The String symbol thing is something to vary about, but generally it would be a bad thing to convert a String to a symbol for things like |
What about |
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.
Don't feel strongly about this. Slightly prefer the !!bool
or '' + thing
syntax anyway.
Oops forget about Number. I'll add that, too. |
I prefer |
@@ -167,7 +167,8 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>( | |||
callback === null || typeof callback === 'function', | |||
'render(...): Expected the last optional `callback` argument to be a ' + | |||
'function. Instead received: %s.', | |||
String(callback) | |||
// $FlowFixMe - Intentional cast to 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.
Is there a way to tell Flow it's intentional, or do we plan to leave these here?
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'll ask the Flow folks
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.
Why are we casting this to a string anyway?
It would be better to let the warning printer cast it to a string, so that it can choose how to visualize it. E.g. imagine console.error('warning', obj)
in devtools prints this nicer with an option to expand etc.
@@ -1034,7 +1034,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P, | |||
function hasCapturedError(fiber : Fiber) : boolean { | |||
// TODO: capturedErrors should store the boundary instance, to avoid needing | |||
// to check the alternate. | |||
return Boolean( | |||
return !!( |
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.
Isn't this already a boolean?
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.
Yeah, I think it was written that way originally because capturedErrors !== null
was just capturedErrors
, and when it was null the whole expression would evaluate to null unless it was coerced. I'll change it.
@@ -1043,7 +1043,7 @@ module.exports = function<T, P, I, TI, PI, C, CX, PL>(config : HostConfig<T, P, | |||
function isFailedBoundary(fiber : Fiber) : boolean { | |||
// TODO: failedBoundaries should store the boundary instance, to avoid | |||
// needing to check the alternate. | |||
return Boolean( | |||
return !!( |
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.
Same question.
c05b7f7
to
b963396
Compare
I'm curious, couldn't this be done as a post-process build step instead? (if people prefer the syntax) |
Seems easier to enforce than forget and be surprised by output. |
@@ -470,7 +470,8 @@ function commitCallbacks(finishedWork : Fiber, queue : UpdateQueue, context : mi | |||
typeof callback === 'function', | |||
'Invalid argument passed as callback. Expected a function. Instead ' + | |||
'received: %s', | |||
String(callback) | |||
// $FlowFixMe - Intentional cast to string | |||
'' + callback |
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.
Same here.
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.
Same here what?
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 nvm I see your comment above
@@ -47,7 +47,8 @@ if (__DEV__) { | |||
'%s(...): Expected the last optional `callback` argument to be a ' + | |||
'function. Instead received: %s.', | |||
callerName, | |||
String(callback) | |||
// $FlowFixMe - Intentional cast to string | |||
'' + callback |
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.
And here.
@@ -117,7 +117,8 @@ function coerceRef(current: Fiber | null, element: ReactElement) { | |||
|
|||
function throwOnInvalidObjectType(returnFiber : Fiber, newChild : Object) { | |||
if (returnFiber.type !== 'textarea') { | |||
const childrenString = String(newChild); | |||
// $FlowFixMe - Intentional cast to string | |||
const childrenString = '' + newChild; |
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.
Seems like this isn't even used when this is a plain Object.
@@ -19,7 +19,8 @@ function validateCallback(callback: ?Function) { | |||
!callback || typeof callback === 'function', | |||
'Invalid argument passed as callback. Expected a function. Instead ' + | |||
'received: %s', | |||
String(callback) | |||
// $FlowFixMe - Intentional cast to string | |||
'' + callback |
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.
Shouldn't need to cast to string neither.
It seems to me that all these Flow errors should not be using string coercion anyway. Seems simple enough to fix. |
Ok I'll submit a follow up |
FYI, the To avoid similar problems, I just submitted #22064 to change React's use of This PR encouraged this
Feel free to answer over in #22064. |
`''.concat(value)` violates current Flow definitons that require args to concat to be strings only, even though the MDN docs and ES spec allow args to be any type. See facebook/flow#8728. To avoid depending on a change to Flow, this commit changes `''.concat(value)` to `String(value)` and removes the lint rule that prohibits use of String(value). This rule was added in facebook#9082. The other rules in that PR (for Boolean and Number constructors) are not changed in this commit, only the rule for String. If it's decided that using `concat` is better, simply omit this commit and use the previous one instead.
First commit adds a new ESLint rule that errors when Boolean and String constructors are used. Second commit fixes the codebase to adhere to the new rule.