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

Fix accessing number literal properties on objects #2293

Closed
wants to merge 2 commits into from

Conversation

vkurchatkin
Copy link
Contributor

This uses raw value as string representation of number literal. This is an oversimplification, but better than nothing.

The correct way is to implement this part of the spec: http://www.ecma-international.org/ecma-262/6.0/index.html#sec-tostring-applied-to-the-number-type

Fixes: #1512

@ghost ghost added the CLA Signed label Aug 19, 2016
@vkurchatkin
Copy link
Contributor Author

Switched to string_of_float_trunc, it seems to work good enough

@@ -3644,6 +3644,15 @@ let rec __flow cx ((l: Type.t), (u: Type.use_t)) trace =
in
rec_flow cx trace (o, u)

| (NumT (reason_x, Literal (n, _)), ElemT(reason_op, (ObjT _ as o), t, rw)) ->
let x = string_of_float_trunc n in
Copy link
Contributor

@bhosmer bhosmer Aug 23, 2016

Choose a reason for hiding this comment

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

Hi Vladimir - it looks like the runtime behavior of e.g. obj[n] is to call toString on n and use the result as a property name, so string_of_float_trunc doesn't seem right here - instead we would need some js_string_of_float which replicated the specified behavior of JS's (number).toString.

(Aside: with that in hand, it should be pretty straightforward to support numeric property names in object literals as well!)

Edit: sorry, just reread your original comment, so you know what's up at runtime. We've gone around about the relative merits of using raw, and basically decided that we need to wait until we have a credible replica of toString before going forward on this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Related comment: #380 (comment)

wait until we have a credible replica of toString before going forward on this.

Spec wording vaguely indicates that final result could be implementation-specific, so I'm not sure that it's worth it.

string_of_float_trunc seems to work good enough. Another option is to only allow integer literals as property keys.

Copy link
Contributor

@bhosmer bhosmer Aug 23, 2016

Choose a reason for hiding this comment

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

The problem with string_of_float_trunc is that it would fold distinct properties together, no?

> let obj = {}
< Object {}
> obj[1] = "hey"
< "hey"
> obj[1.1] = 999
< 999
> obj[1]
< "hey"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, it should work for this case. It just truncates trailing . to format integers correctly

@bhosmer bhosmer self-assigned this Aug 23, 2016
@ghost ghost added the CLA Signed label Aug 23, 2016
@vkurchatkin
Copy link
Contributor Author

@bhosmer ping

@samwgoldman
Copy link
Member

I'll take this over from Basil. Thanks for being so patient.

@facebook-github-bot
Copy link
Contributor

@gabelevi has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

@gabelevi
Copy link
Contributor

This looks good to me. I'll import, rebase it past some internal refactors, get it reviewed, and merge it. Sorry for the delay!

@gabelevi
Copy link
Contributor

gabelevi commented Nov 3, 2016

This has turned out to be a little more complicated than anticipated. Since we support types like

function foo(obj: { [key: number]: string }): string {
  return obj[1];
}

It's a problem if we automatically convert 1 into "1" as this PR does. Instead, we need to update GetPropT and SetPropT to carry along the information that this is a number literal. @samwgoldman is going to attempt this within the next few weeks.

@vkurchatkin
Copy link
Contributor Author

@gabelevi haven't thought about this. I'll try to fix it myself, if you don't mind

@samwgoldman
Copy link
Member

Normally I would be hugely supportive but I'm pretty much done with the enabling refactor. Will coordinate with you regarding follow up steps once the diff lands!

@vkurchatkin
Copy link
Contributor Author

@samwgoldman got it!

facebook-github-bot pushed a commit that referenced this pull request Nov 15, 2016
Summary:
Before this diff, computed property access for objects was handled by ElemT
exclusively. This diff generalizes GetProp, SetProp, LookupT, and related use
types to handle both named properties and computed element access.

This refactoring unlocks a few things:
* We can properly implement MethodT for `o[p]()`, where `p` is a literal and
  `o[p]` resolves to a function that references `this`.
* We can convert number literals to strings, if a named property matches
  anywhere along the prototype chain.
* Many uses of symbols will require that we traverse the prototype chain.

Note that none of the above are included in this diff, but rather slated for
follow-up work.

Note the invariant that a computed prop ref's type must be concrete (not open)
and will never be a string literal. This invariant holds because we wait for the
indexer element ot resolve with ElemT before generating the lookup constraints,
and string literals are converted in the named property lookups.

This diff also makes a small change to LookupT. Before, the reason for that use
type was the reason for the property. After this change, that reason is
associated with the "prop ref" instead, and the lookup's own reason should be
the "op reason" -- the reason why we are doing a lookup in the first place.

Ref #2293

Reviewed By: gabelevi

Differential Revision: D4149126

fbshipit-source-id: 54fe4f621ebc8e95ac801e1580c158b00555bbca
@samwgoldman
Copy link
Member

OK, so the groundwork has landed in this revision: 1fd2a72

We now look up the prototype chain for all computed properties:

| _ -> Computed l

To make this work, the trick will be to find all the places that a propref is looked up in an ObjT or InstanceT, see if the propref is a Computed (NumT (_, Literal lit)) and try to convert to a named property. If not, continue propagating the computed propref up the chain.

Let me know if you have any questions, or if there is something else missing.

@mrkev
Copy link
Contributor

mrkev commented Jul 13, 2018

Hopping in real quick to see if you're still pursuing this @vkurchatkin 😅it's been a while

@nmote
Copy link
Contributor

nmote commented Jan 3, 2019

It looks like this has been abandoned. Feel free to reopen if you pick this back up again.

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