Skip to content

fix: do not resolve array indexes that RFC 6901 does not allow - #17

Open
filipesantoss wants to merge 2 commits into
hyperjump-io:mainfrom
filipesantoss:fix/invalid-array-index
Open

filipesantoss wants to merge 2 commits into
hyperjump-io:mainfrom
filipesantoss:fix/invalid-array-index

Conversation

@filipesantoss

@filipesantoss filipesantoss commented Oct 21, 2026 •

Copy link
Copy Markdown

Fixes #16

Summary

Reads and deletes look up the reference token as a JavaScript property lookup does.

Writes accept only an array index or - for an array.
Writes throw a TypeError with the cursor for any other token.

 get / unset / remove (token)
-  key = computeSegment(token)                    # parseInt for an array
-  if value has own property key
+  if value has own enumerable property token     # items, not an array's length
     read or delete it

 set / assign (token)
   computeSegment(value, token, location)
     if value is an array and token is "-"
       return value.length
-    return parseInt(token, 10)
+    if token is not "0" or digits without a leading "0"
+      throw TypeError "Value at '<cursor>' is an array and '<token>' is not a valid array index"
+    return Number(token)

Merge Danger

A token such as 01 no longer reaches item 1.
A caller that wrote through such a token now gets an error.
A write with a token that is not a number, such as foo, also throws.

@jdesrosiers jdesrosiers left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The strict index check is right for writes, but it shouldn't apply to reads. Here's what I'd like and why.

This library tries to behave the way JavaScript does for the same operation, unless that would contradict RFC 6901.

Reads and deletes should not throw. In JavaScript, [1, 2]["01"] and [1]["foo"] are just property lookups that give undefined. So get should return undefined, and unset/remove should do nothing. This doesn't contradict the spec. Section 7 lists a reference to a nonexistent value as an error, but it leaves the handling of errors to the application, and this library already handles that case by returning undefined.

Writes should throw. In JavaScript, arr["01"] = x adds a non-index property to the array. That gives you a value that isn't valid JSON: JSON.stringify drops the property without any warning. Section 4 also says that when the value is an array, the token MUST be - or an index with no leading zeros. So set and assign are where the check belongs.

The error should follow the existing ones. Please make it a TypeError that includes the location, like the not-a-container errors. For example: Value at '/0' is an array and 'foo' is not a valid array index.

@filipesantoss filipesantoss changed the title fix: reject array indexes that are not zero or digits without a leading zero fix: do not resolve array indexes that RFC 6901 does not allow Oct 26, 2026
@filipesantoss

Copy link
Copy Markdown
Author

8577327 addresses the review.

Own enumerable properties

With Object.hasOwn, the lookup would match length on every array: get("/foo/length") would return the length, and remove("/foo/length") would throw.
The lookup checks for an own enumerable property instead, which excludes length.

NaN

With parseInt, a token that is not a number would become NaN: set("/foo/bar", { foo: ["bar", "baz"] }, "x") would add a property named NaN to the array, which JSON.stringify drops without warning.
That write now throws.

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.

get resolves array indexes that RFC 6901 does not allow

2 participants