Skip to content

fix(slice): explicit zero end no longer returns the whole array#265

Open
spokodev wants to merge 1 commit into
JSONPath-Plus:mainfrom
spokodev:fix-slice-zero-end
Open

fix(slice): explicit zero end no longer returns the whole array#265
spokodev wants to merge 1 commit into
JSONPath-Plus:mainfrom
spokodev:fix-slice-zero-end

Conversation

@spokodev

Copy link
Copy Markdown

Problem

A slice with an explicit 0 end returns the entire array instead of an empty result:

JSONPath({ path: '$[:0]',  json: [0,1,2,3] }) // → [0,1,2,3]   (expected [])
JSONPath({ path: '$[2:0]', json: [0,1,2,3] }) // → [2,3]       (expected [])
JSONPath({ path: '$[0:0]', json: [0,1,2,3] }) // → [0,1,2,3]   (expected [])

For comparison, $[:1][0] and $[2:1][] are already correct — only an explicit 0 end is mishandled. Per the Python slice semantics this library documents, arr[:0] is [].

Cause

In _slice the end index is computed as:

end = (parts[1] && Number.parseInt(parts[1])) || len;

When parts[1] is '0', Number.parseInt('0') is 0, which is falsy, so || len replaces the legitimate index 0 with the array length.

The slice loc is gated upstream by /^(-?\d*):(-?\d*):?(\d*)$/, so parts[1] is always either an empty string (end omitted) or a valid integer string. The fix defaults an omitted (empty) end to len and parses any explicit value, including 0:

end = parts[1] ? Number.parseInt(parts[1]) : len;

start and step are intentionally left unchanged: start's falsy default is already 0, and step's || 1 is a deliberate guard against an infinite i += 0 loop.

This is the same 0-is-falsy class as the @property fix in #245.

Verification

  • New regression test in test/test.slice.js ($[:0], $[2:0], $[0:0][]); fails before, passes after.
  • Full suite: 278 passing.
  • Differential vs Python slice semantics over every valid start:end:step shape on arrays of length 0–7 (4,608 cases): 264 divergences before → 0 after. All 264 were end == 0 cases; the fix introduces no new divergence.

A slice with an explicit `0` end (e.g. `$[:0]`, `$[2:0]`) returned the
entire array instead of an empty result. `end` was computed with
`(parts[1] && Number.parseInt(parts[1])) || len`, so a parsed end of `0`
is falsy and got replaced by the array length. Treat an omitted end
(empty string) as the length and parse any explicit value, including 0.
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.

1 participant