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

Clarify the handling of +0 and -0 in keys #375

Open
abacabadabacaba opened this issue Jan 25, 2022 · 11 comments · May be fixed by #386
Open

Clarify the handling of +0 and -0 in keys #375

abacabadabacaba opened this issue Jan 25, 2022 · 11 comments · May be fixed by #386
Labels
has-pr has-tests interop Behavior difference between engines TPAC2024 Topic for discussion at TPAC 2024

Comments

@abacabadabacaba
Copy link

Currently, according to the spec, both +0 and -0 are valid keys. So, when a value is stored with the key -0, a later call to getAllKeys should return -0 as the key. However, some implementations instead are replacing -0 with +0.

Also, given that -0 == +0, an object store or a unique index can have either -0 or +0 as a key, but not both.

The value +0 or -0 can be the whole key, or a (possibly nested) array element of the key.

I think that the spec should be clarified to note the existence of equal but different keys, and to provide examples of correct behavior (e.g. put replacing an entry with a different key).

@inexorabletash
Copy link
Member

Ooof, I can't believe we overlooked this.

I'd be in favor of saying that keys should be normalized to +0 but we should survey implementations and see what they are all doing.

@abacabadabacaba do you have details about what each implementation does?

@abacabadabacaba
Copy link
Author

Firefox is normalizing the keys, Chromium doesn't. I reported the Firefox behavior here as violating the spec.

@asutherland
Copy link
Collaborator

Thanks so much for the spec bug and Firefox bug with easy reproduction! Firefox was not intentionally normalizing here, bit manipulations just went wrong when trying to create a binary encoding that sorted sensibly.

That said, normalizing to +0 intentionally does seem desirable because of the uniqueness problem (because of the language around key equal to).

@inexorabletash
Copy link
Member

I put together a test & normalization fix for Blink. The WPT is here:

https://chromium-review.googlesource.com/c/chromium/src/+/3700521/2/third_party/blink/web_tests/external/wpt/IndexedDB/key_negative_zero.any.js

Without a code change, as expected these are the failures:

FAIL put(v, -0) key should normalize to +0 assert_equals: key should be normalized to +0 expected 0 but got -0
FAIL put(v, +0) / getKey(v, -0) normalization assert_equals: getKey(-0) should see +0 expected 0 but got -0
FAIL put(v, -0) / getKey(v, -0) normalization assert_equals: getKey(-0) should see +0 expected 0 but got -0
FAIL put(v, -0) / getAllKeys() normalization assert_equals: key should be normalized to +0 expected 0 but got -0

Anyone want to take a look at the WPT and see if I missed any important cases? One that comes to mind is IDBKeyRange.bound(0, 10).includes(-0) and other permutations with open/closed bounds.

@inexorabletash inexorabletash linked a pull request Jun 11, 2022 that will close this issue
5 tasks
@inexorabletash
Copy link
Member

And a spec PR at #386 but maybe we want to say more. Feedback welcome!

@inexorabletash
Copy link
Member

@marcoscaceres - know anyone on WebKit that would interested in reviewing the WebKit behavior and/or spec/WPTs here?

@asutherland - same question, but for Gecko?

@marcoscaceres
Copy link
Member

I'll try to find someone...

@szewai
Copy link

szewai commented Oct 13, 2022

WebKit does not normalize negative 0, so for the proposed test, here are the failed tests:
FAIL put(v, -0) key should normalize to +0 assert_equals: key should be normalized to +0 expected 0 but got -0
FAIL put(v, -0) / getKey(v, +0) normalization assert_equals: getKey(+0) should see +0 expected 0 but got -0
FAIL put(v, -0) / getKey(v, -0) normalization assert_equals: getKey(-0) should see +0 expected 0 but got -0
FAIL put(v, -0) / getAllKeys() normalization assert_equals: key should be normalized to +0 expected 0 but got -0

Looks like we have a different case than Blink in the no-normalization implementation.

Generally I think the normalization would simplify the spec and implementation, i.e. we can always assume no -0 in keys. But with existing implementation we have, that probably means we need to convert -0 in database to 0 after the spec change. How is Blink going to deal with this? @inexorabletash

For the test, I think we can add test for extracting key with key path from value (e.g. ensure -0 is converted to 0 in key, but not in value).

@inexorabletash
Copy link
Member

Apologies for the delay, I've been OOO for a bit.

Generally I think the normalization would simplify the spec and implementation, i.e. we can always assume no -0 in keys. But with existing implementation we have, that probably means we need to convert -0 in database to 0 after the spec change. How is Blink going to deal with this? @inexorabletash

@szewai - In Blink, all internal key comparisons treat -0 and 0 the same. The patch just ensures that when doing a key-to-JS conversion any -0 is mapped to +0. Whatever was previously stored in the database gets "fixed" on retrieval. This only happens to keys, not values. I can't think of a case that doesn't cover, but I may be missing something.

@w3c w3c deleted a comment Jan 15, 2023
@inexorabletash
Copy link
Member

@szewai - hey, sorry for the long delay here - any further thoughts about making this change in WebKit? What do you think of the WPT and spec PR #386 ?

This is obviously pretty minor, but it'd be nice to get it off the radar if we've got consensus.

@szewai
Copy link

szewai commented Jun 13, 2023

@szewai - hey, sorry for the long delay here - any further thoughts about making this change in WebKit? What do you think of the WPT and spec PR #386 ?

This is obviously pretty minor, but it'd be nice to get it off the radar if we've got consensus.

Hello! This sounds good to me. I filed https://bugs.webkit.org/show_bug.cgi?id=258053.

@inexorabletash inexorabletash added the interop Behavior difference between engines label Dec 19, 2023
@inexorabletash inexorabletash added the TPAC2024 Topic for discussion at TPAC 2024 label Jul 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
has-pr has-tests interop Behavior difference between engines TPAC2024 Topic for discussion at TPAC 2024
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants