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

Add JSON roundtripping goal and consequences #42

Merged
merged 1 commit into from
Aug 28, 2019

Conversation

mheiber
Copy link
Contributor

@mheiber mheiber commented Aug 17, 2019

  • Add Object.from(record)
  • Add behavior of JSON.stringify(tuple) and
    JSON.stringify(record)
  • Clarify what values are allowed as
    keys/values of records and as entries in tuples

fix #39

@ljharb
Copy link
Member

ljharb commented Aug 17, 2019

That also precludes including frozen functions - then the proposal is not really about immutability, it’s about json round tripping, which means that mutable objects should be allowed if they can json round trip.

@ljharb
Copy link
Member

ljharb commented Aug 17, 2019

What does Object.from do with things that aren’t records or tuples?

@mheiber mheiber mentioned this pull request Aug 17, 2019
@mheiber
Copy link
Contributor Author

mheiber commented Aug 17, 2019

@ljharb I'm doubting whether Object.from was a good idea, since there is already so much weird stuff in JS. What about co-opting new Object(record) and Object(record) instead? They already use the toObject abstract op that says how to make an object from each kind of thing.

@ljharb
Copy link
Member

ljharb commented Aug 17, 2019

Object(record) must make a boxed primitive object that's instanceof Record; if you want to convert it to a plain object, you need something different.

@@ -22,19 +22,20 @@ ECMAScript proposal for the Record and Tuple const value types (also known as im

# Overview

The goal of this proposal is to introduce deeply constant/immutable value types to JavaScript. It has multiple objectives:
The goal of this proposal is to introduce deeply constant/immutable data structures to JavaScript. It has multiple objectives:
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@ljharb, you said

That also precludes including frozen functions - then the proposal is not really about immutability, it’s about json round tripping, which means that mutable objects should be allowed if they can json round trip.

  1. What alternative are you suggesting?

  2. Is the issue that you see immutability and simple (de)serialization as non-orthogonal goals? If so, note that the proposal is already not 100% orthogonal:

  • We could add immutable objects where === is pointer equality. In fact, JS libraries offer those already! Examples include ImmutableJS, Mori, and MicroState.
  • We could add mutable objects where === is structural. In fact, we could do that very easily by having a new well-known symbol, Symbol@@equals, thereby allowing userland implementations of arbitrary equality-checking algorithms.

There are tradeoffs here. My hope is to bias toward providing good performance and developer ergonomics at the expense of some orthogonality.

  1. Would you agree that it will be beneficial to have predictable and useful serialization?

I believe the proposal was designed with ease of serialization/deserialization in mind, such as communicating data with workers. Keeping serialisation simple for now helps us build toward that goal.

You specifically mentioned functions:
- You mentioned frozen functions specifically. There is no special-casing for freezing in the current proposal. #{ a: Object.freeze({}) } errors if I understand correctly.
- Functions are particularly nasty if we want a good (de)serialisation story. They aren't supported by JSON.stringify by default, and aren't supported at all by the HTML5 structured clone algorithm.

Copy link
Member

Choose a reason for hiding this comment

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

I guess I'm a bit confused. If this proposal is about immutability, then any immutable object - including deeply frozen ones - seem like they should be included.

If it's primarily about JSON-serialization and structural equality, then there's not really any point in making them immutable - they could just be mutable JSON-serializable primitives.

It's worth looking into https://github.com/sebmarkbage/ecmascript-shallow-equal and why it was withdrawn - it seems like it might run into the same concerns.

Copy link
Contributor Author

@mheiber mheiber Aug 17, 2019

Choose a reason for hiding this comment

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

As I said, in my interpretation the proposal has multiple, related goals. And there may be a tradeoff between orthogonality and usefulness.

Thanks for the link to the shallow equality proposal. That proposal seems to have been withdrawn for unrelated reasons: https://github.com/sebmarkbage/ecmascript-shallow-equal#status-of-this-proposal. In the shallow-equal proposal, the semantics weren't fully specced (for perf reasons), but vendors were afraid to implement because they sensed they would be locked in to certain implementations for backwards-compatibility.

@mheiber
Copy link
Contributor Author

mheiber commented Aug 28, 2019

related: #45

README.md Outdated Show resolved Hide resolved
- Add Object.from(record)
- Add behavior of JSON.stringify(tuple) and
JSON.stringify(record)
- Clarify what values are allowed as
keys/values of records and as entries in tuples
@rickbutton rickbutton merged commit 26dcc82 into tc39:master Aug 28, 2019
@littledan
Copy link
Member

I like the Record.from API, and I think the JSON serialization behavior is good documentation (it falls out of other things in this readme), but I don't understand the motivation for the JSON round-tripping property. It seems really odd to me to exclude symbols, undefined and BigInt. Further, I was hoping that this proposal would give us the core data model that would expand to "value classes" including private fields, which would definitely not JSON round-trip. And finally, sorting the keys breaks JSON round-tripping. Why not have as a goal, a subset of this will JSON round-trip?

@mheiber
Copy link
Contributor Author

mheiber commented Sep 3, 2019

Thanks for your feedback, @littledan . I guess I never wrote why I thought JSON roundtripping would be a good goal:

  • We get lossless structured clone support for free. Related to this issue: Interaction with Structured Clone algorithm #45
  • One of the performance things we're excited about is that it is a step toward being able to cheaply get data from JSON. When working with JSON, few roundtripping hazards just seems nice if we can have it without giving up too much. I have in mind use cases reading/writing ASTs to/from disk when doing incremental compilation, or saving and rehydrating Redux stores.
  1. Why is it odd to exclude symbols? We couldn't come up with a use case.

  2. The undefined thing is odd, I agree, and I hadn't thought of BigInt. Does BigInt work with Structured Clone?

  3. Re expanding the core data model more: does allowing JSON roundtripping for Record and Tuple preclude having 'value classes' with private fields later? (real question, not sure what the implications are)

  4. Can you explain the sorting issue?

@mheiber mheiber deleted the serialization branch September 4, 2019 18:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Interactions with Symbols
4 participants