Skip to content
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

Improve soundness of ReactDOMFiberInput typings #13367

Merged
merged 2 commits into from
Aug 12, 2018

Conversation

philipp-spiess
Copy link
Contributor

@philipp-spiess philipp-spiess commented Aug 11, 2018

This is an attempt in improving the soundness for the safe value cast that was added in #11741. We want this to avoid situations like this one where we need to remember why we have certain type casts. Additionally we can be sure that we only cast safe values to string.

The problem was getSafeValue(). It used the (deprecated) * type to infer the type which resulted in a passing-through of the implicit any of the props Object. So getSafeValue() was effectively returning any.

Once I fixed this, I found out that Flow does not allow concatenating all possible types to a string (e.g "" + false fails in Flow). To fix this as well, I've opted into making the SafeValue type opaque and added a function that can be used to get the string value. This is sound because we know that SafeValue is already checked.

I've verified that the interim function is inlined by the compiler and also looked at a diff of the compiled react-dom bundles to see if I've regressed anything. Seems like we're good.

This is an attempt in improving the soundness for the safe value cast
that was added in facebook#11741. We want this to avoid situations like [this
one](facebook#13362 (comment))
where we need to remember why we have certain type casts. Additionally
we can be sure that we only cast safe values to string.

The problem was `getSafeValue()`. It used the (deprecated) `*` type to
infer the type which resulted in a passing-through of the implicit `any`
of the props `Object`. So `getSafeValue()` was effectively returning
`any`.

Once I fixed this, I found out that Flow does not allow concatenating
all possible types to a string (e.g `"" + false` fails in Flow). To
fix this as well, I've opted into making the SafeValue type opaque and
added a function that can be used to get the string value. This is sound
because we know that SafeValue is already checked.

I've verified that the interim function is inlined by the compiler and
also looked at a diff of the compiled react-dom bundles to see if I've
regressed anything. Seems like we're good.
@pull-bot
Copy link

pull-bot commented Aug 11, 2018

ReactDOM: size: 0.0%, gzip: -0.0%

Details of bundled changes.

Comparing: 725e499...db84bdc

react-dom

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-dom.development.js +0.1% +0.1% 641.27 KB 641.69 KB 150.69 KB 150.81 KB UMD_DEV
react-dom.production.min.js 0.0% -0.0% 96.27 KB 96.27 KB 31.2 KB 31.2 KB UMD_PROD
react-dom.development.js +0.1% +0.1% 637.41 KB 637.83 KB 149.53 KB 149.66 KB NODE_DEV
react-dom.production.min.js 0.0% -0.0% 96.27 KB 96.27 KB 30.78 KB 30.78 KB NODE_PROD
ReactDOM-dev.js +0.1% +0.1% 644.54 KB 644.97 KB 147.76 KB 147.9 KB FB_WWW_DEV
ReactDOM-prod.js 0.0% -0.0% 278.96 KB 278.96 KB 52.26 KB 52.26 KB FB_WWW_PROD
react-dom.profiling.min.js 0.0% -0.0% 97.47 KB 97.47 KB 31.18 KB 31.18 KB NODE_PROFILING

Generated by 🚫 dangerJS

Copy link
Contributor

@nhunzaker nhunzaker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a great change, 👍

@@ -174,13 +177,14 @@ export function updateWrapper(element: Element, props: Object) {
if (props.type === 'number') {
if (
(value === 0 && node.value === '') ||
// We explicitly want to coerce to number here if possible.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Contributor

@aweary aweary left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets make sure we coordinate this with #13362 so that all our input wrappers are consistent.

ReactDOMFiberSelect also uses _wrapperState. Consider using SafeValue there too for consistency?

@raunofreiberg
Copy link
Contributor

raunofreiberg commented Aug 12, 2018

Nice! I've already begun implementing this minor change in #13362. What would be the best way to sync this PR-s changes to #13362. Is merging this branch into my own branch fine or should I just wait until this is merged into master?

@philipp-spiess
Copy link
Contributor Author

philipp-spiess commented Aug 12, 2018

@raunofreiberg Awesome! Let's merge then, your PR should be fine if you already have that change 👍

@philipp-spiess philipp-spiess merged commit 33602d4 into facebook:master Aug 12, 2018
@philipp-spiess philipp-spiess deleted the philipp/typed-input branch August 12, 2018 15:14
@gaearon
Copy link
Collaborator

gaearon commented Aug 12, 2018

Nit: “safe” has security connotations. We want to be careful with naming like this because the reader might think it implies some particular type of safety (for example safety for emitting into HTML without escaping it).

@philipp-spiess
Copy link
Contributor Author

@gaearon Good point. Do you have another idea? Maybe ConcatenateableValue? Feels a bit long and might lead to typos. Maybe ConcatValue is also ok? I can fix it up.

@raunofreiberg
Copy link
Contributor

raunofreiberg commented Aug 12, 2018

CastValue? CastableValue? 🤔

@gaearon
Copy link
Collaborator

gaearon commented Aug 12, 2018

Maybe ToStringResult and callToStringUnlessFunctionOrSymbol?

philipp-spiess added a commit to philipp-spiess/react that referenced this pull request Aug 12, 2018
Following up on the changes I made in facebook#13367, @gaearon suggest that
"safe" could be read as necessary for security. To avoid misleading a
reader, I'm changing the name.

A few names where discussed in the previous PR. I think `ToStringValue`
makes sense since the value itself is not a string yet but an opaque
type that can be cast to a string. For the actual string concatenation,
I've used `toString` now to avoid confusion: `toStringValueToString`
is super weird and it's namespaced anyhow.

Definitely open for suggestions here. :) I'll wait until we wrap up
facebook#13362 and take care of rebase afterwards.
gaearon pushed a commit that referenced this pull request Aug 13, 2018
Following up on the changes I made in #13367, @gaearon suggest that
"safe" could be read as necessary for security. To avoid misleading a
reader, I'm changing the name.

A few names where discussed in the previous PR. I think `ToStringValue`
makes sense since the value itself is not a string yet but an opaque
type that can be cast to a string. For the actual string concatenation,
I've used `toString` now to avoid confusion: `toStringValueToString`
is super weird and it's namespaced anyhow.

Definitely open for suggestions here. :) I'll wait until we wrap up
#13362 and take care of rebase afterwards.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants