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

Object with zero-length string key and Set/Map value results in error #25

Closed
dumbmatter opened this issue May 19, 2021 · 5 comments · Fixed by dfahlander/typeson#31
Closed
Labels

Comments

@dumbmatter
Copy link

dumbmatter commented May 19, 2021

I got this bug report dumbmatter/realistic-structured-clone#8 and somehow didn't notice it until now.

Here's a short script to reproduce:

const Typeson = require("typeson");
const preset = require("typeson-registry/dist/presets/builtin");

const TSON = new Typeson().register(preset);

const test = (obj) => {
    const encapsulated = TSON.encapsulate(obj);
    console.log("encapsulated", encapsulated);

    const revived = TSON.revive(encapsulated);
    console.log("revived", revived);
}

console.log("This works");
test({"": "some value"});

console.log("\nThis works");
test({"a": new Set()});

console.log("\nThis fails");
test({"": new Set()});

As you can see... "" as a key works. new Set() as a value works. But together, it produces this error.

This works
encapsulated { '': 'some value' }
revived { '': 'some value' }

This works
encapsulated { a: [], '$types': { a: 'set' } }
revived { a: Set(0) {} }

This fails
encapsulated { '': [], '$types': { '': 'set' } }
TypeError: object is not iterable (cannot read property Symbol(Symbol.iterator))
    at new Set (<anonymous>)
    at Object.revive (/home/jdscheff/projects/realistic-structured-clone/node_modules/typeson-registry/dist/presets/builtin.js:1:21697)
    at executeReviver (/home/jdscheff/projects/realistic-structured-clone/node_modules/typeson/dist/typeson-commonjs2.min.js:1:12438)
    at reducer (/home/jdscheff/projects/realistic-structured-clone/node_modules/typeson/dist/typeson-commonjs2.min.js:1:13964)
    at Array.reduce (<anonymous>)
    at _revive (/home/jdscheff/projects/realistic-structured-clone/node_modules/typeson/dist/typeson-commonjs2.min.js:1:13862)
    at Typeson.revive (/home/jdscheff/projects/realistic-structured-clone/node_modules/typeson/dist/typeson-commonjs2.min.js:1:13990)
    at test (/home/jdscheff/projects/realistic-structured-clone/bug.js:10:26)
    at Object.<anonymous> (/home/jdscheff/projects/realistic-structured-clone/bug.js:21:1)

Similar error with Map instead of Set. In a little testing with other objects, I was not able to trigger the error. Although with new Date() it also does something weird:

This works
encapsulated { '': 'some value' }
revived { '': 'some value' }

This works
encapsulated { a: 1621404266214, '$types': { a: 'date' } }
revived { a: 2021-05-19T06:04:26.214Z }

This fails
encapsulated { '': 1621404266215, '$types': { '': 'date' } }
revived Invalid Date

This is with the latest versions of typeson and typeson-registry.

@brettz9
Copy link
Collaborator

brettz9 commented May 19, 2021

I've confirmed this is an issue (and in typeson core), seemingly confined to top-level objects with the empty string key (probably because the empty string is otherwise used to indicate the root object). I'm surprised this wasn't caught as we do escape even for objects with $types, but apparently got through. Unfortunately, I'm a bit too preoccupied to look into a fix for this now, and not sure when I might be able to. Should be able to review a PR, however.

@brettz9 brettz9 added the bug label May 19, 2021
brettz9 added a commit to brettz9/typeson that referenced this issue Dec 29, 2022
BREAKING CHANGE:

Empty string now may only reference root object when encapsulated and at top of `$: {}`
brettz9 added a commit to brettz9/typeson that referenced this issue Dec 29, 2022
…lander/typeson-registry#25

BREAKING CHANGE:

Empty string now may only reference root object when encapsulated and at top of `$: {}`
brettz9 added a commit to brettz9/typeson that referenced this issue Dec 29, 2022
…in an empty-string-aware manner; fixes dfahlander/typeson-registry#25

BREAKING CHANGE:

Empty string now may only reference root object when encapsulated and at top of `$: {}`
@brettz9
Copy link
Collaborator

brettz9 commented Dec 29, 2022

I've finally got around to looking into this. I've submitted a PR to fix this at dfahlander/typeson#30 but thought it would be good to confirm it works for you before merging if possible.

There were two issues, both related to the fact that we were internally sometimes using the empty string to refer to the root object and sometimes (kind of) allowing for the empty string.

This PR now should insist that:

  1. The empty string will only be present to represent the root object when the object and type are encapsulated in $, e.g., {$: {'': 1234567890}, $types: {$: {'': 'Date'}}}. (We previously used this escaping mechanism for certain scenarios, but not for the empty-string-as-root scenario.
  2. Revival will not treat the normal presence of the empty string as root, but instead as a regular empty string property.

@dumbmatter : Do you think you'll have a chance to take a look relatively soon? Sorry this is quite a while later. I'd like to get the fix out soon, but I think this is unfortunately somewhat of a breaking change, so better to have another pair of eyes on it, even if you're not really familiar with the internals. If not, that's fine; I can just look to release, as it is passing the new tests, and I believe addresses the situation.

@dfahlander : This should, I think, be a breaking change given that the encapsulation format may now necessarily differ, though I expect only a subset of users will be impacted.

@dumbmatter
Copy link
Author

I spent 5 minutes trying to get my original example code to run and I'm lost in CJS/ESM issues that I don't want to deal with right now :) regardless, I probably can't say much more than if the tests pass or not.

@dfahlander
Copy link
Owner

Thanks @brettz9 🙏

brettz9 added a commit to brettz9/typeson that referenced this issue Dec 30, 2022
…in an empty-string-aware manner; fixes dfahlander/typeson-registry#25

BREAKING CHANGE:

Empty string now may only reference root object when encapsulated and at top of `$: {}`
brettz9 added a commit to brettz9/typeson that referenced this issue Dec 31, 2022
…fahlander/typeson-registry#25

BREAKING CHANGE:

Empty string keys are now escaped as `''` and `''` within keys are escaped as `''''`.
brettz9 added a commit to brettz9/typeson that referenced this issue Dec 31, 2022
…fahlander/typeson-registry#25

BREAKING CHANGE:

Empty string keys are now escaped as `''` and `''` within keys are escaped as `''''`.
brettz9 added a commit to brettz9/typeson that referenced this issue Dec 31, 2022
…fahlander/typeson-registry#25

BREAKING CHANGE:

Empty string keys are now escaped as `''` and `''` within keys are escaped as `''''`.
@brettz9
Copy link
Collaborator

brettz9 commented Dec 31, 2022

Realized there was a problem with the approach in my previous PR. Experimented and then realized there was a simpler solution which also minimized format changes.

The PR also adds some more examples of the typeson format in the README so people could see more how the format was build, including escaping.

I'll just wait a little in case anyone wants to review, but basically I've just distinguished between a path for whole objects and an empty string path by escaping the empty string as '' (and then escaping '' instances as '''').

brettz9 added a commit to brettz9/typeson that referenced this issue Dec 31, 2022
…fahlander/typeson-registry#25

BREAKING CHANGE:

Empty string keys are now escaped as `''` and `''` within keys are escaped as `''''`.
brettz9 added a commit to brettz9/typeson that referenced this issue Jan 1, 2023
…fahlander/typeson-registry#25

BREAKING CHANGE:

Empty string keys are now escaped as `''` and `''` within keys are escaped as `''''`.
brettz9 added a commit to dfahlander/typeson that referenced this issue Jan 1, 2023
…fahlander/typeson-registry#25

BREAKING CHANGE:

Empty string keys are now escaped as `''` and `''` within keys are escaped as `''''`.
brettz9 added a commit to brettz9/typeson-registry that referenced this issue Jan 1, 2023
BREAKING CHANGE:

Empty string components of key paths are now escaped (as `''`)
while `''` is escaped as `''''`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
3 participants