Skip to content

Commit

Permalink
Fix array indices
Browse files Browse the repository at this point in the history
  • Loading branch information
ehmicky committed Mar 6, 2022
1 parent 51a276e commit 3ad61be
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 9 deletions.
23 changes: 16 additions & 7 deletions src/config/normalize/lib/wild_wild_path/tokens/array.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,26 @@ const normalize = function (token) {
// eslint-disable-next-line max-params
const list = function (value, path, token, missing) {
const index = getArrayIndex(value, token)
return [{ value: value[index], path: [...path, index], missing }]
return [
{
value: value[index],
path: [...path, index],
missing: missing || index >= value.length,
},
]
}

// Retrieve an array using a positive or negative index.
// Array indices that are:
// - Positive are kept
// - Negative are converted to index 0
// Negative array indices start from the end.
// Indices that are out-of-bound:
// - Do not error
// - Return an entry with an `undefined` value
// - This allows appending to arrays, e.g. with -0
// - Are min-bounded to 0
// - Are not max-bounded:
// - Those return a missing entry instead
// - Reasons:
// - This is more consistent with how missing entries with property names
// are handled
// - This allows appending with -0
// - This is better when setting values on arrays with varying sizes
export const getArrayIndex = function (value, token) {
return token > 0 || Object.is(token, +0)
? token
Expand Down
11 changes: 9 additions & 2 deletions src/config/normalize/lib/wild_wild_path/tokens/slice.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,22 @@ const normalize = function ({ type, from = 0, to }) {
// Use the token to list entries against a target value.
// eslint-disable-next-line max-params
const list = function (value, path, { from, to }, missing) {
const fromIndex = getArrayIndex(value, from)
const toIndex = Math.max(getArrayIndex(value, to), fromIndex)
const fromIndex = getBoundedIndex(value, from)
const toIndex = Math.max(getBoundedIndex(value, to), fromIndex)
return new Array(toIndex - fromIndex).fill().map((_, index) => ({
value: value[index + fromIndex],
path: [...path, index + fromIndex],
missing,
}))
}

// Unlike the array token, indices are max-bounded to the end of the array:
// - This prevents maliciously creating big arrays to crash the process
// - Appending values is less useful in the context of a slice
const getBoundedIndex = function (value, edge) {
return Math.min(getArrayIndex(value, edge), value.length)
}

// Check if two tokens are the same
const equals = function (tokenA, tokenB) {
return Object.is(tokenA.from, tokenB.from) && Object.is(tokenA.to, tokenB.to)
Expand Down

0 comments on commit 3ad61be

Please sign in to comment.