fuzzysort icon indicating copy to clipboard operation
fuzzysort copied to clipboard

feat(fuzzysort/algorithm): algorithm function return a shallow copy of prepare object

Open pablolmiranda opened this issue 4 years ago • 0 comments

Problem

When algorithm function returns a reference to a cached object. In this case, if the upstream code holds a reference to it, any consequent invocation of the function with the same target will mutate the object and change the upstream result.

Example to reproduce the issue

const fuzzysort = require('./fuzzysort')

const term = 'Inventory Items Average Cos'
const leftText = 'Inventory Items'
const rightText = 'Average Cost'

const tokens = term.split(' ')
const tokensLen = tokens.length

const results = []
for(const tokenIndex in tokens) {
    const left = tokens.slice(0, tokenIndex);
    const right = tokens.slice(0 + tokenIndex,tokensLen);

    const leftMatch = fuzzysort.single(left.join(' '), leftText)
    const rightMatch = fuzzysort.single(right.join(' '), rightText)

    if (leftMatch && rightMatch) {
        console.log('Saving to results:')
        console.log(leftMatch)
        console.log(rightMatch)

        results.push({
            left: leftMatch,
            right: rightMatch
        })
    }
}

console.log('')
console.log('Saved results: ')
console.log(results)

This example generate the following output:

Saving to results:
{
  target: 'Inventory Items',
  _targetLowerCodes: [
    105, 110, 118, 101, 110,
    116, 111, 114, 121,  32,
    105, 116, 101, 109, 115
  ],
  _nextBeginningIndexes: [
     9,  9,  9,  9,  9,  9,
     9,  9,  9, 10, 15, 15,
    15, 15, 15
  ],
  score: 0,
  indexes: [
     0,  1,  2, 3,  4,  5,
     6,  7,  8, 9, 10, 11,
    12, 13, 14
  ],
  obj: null
}
{
  target: 'Average Cost',
  _targetLowerCodes: [
     97, 118, 101, 114,  97,
    103, 101,  32,  99, 111,
    115, 116
  ],
  _nextBeginningIndexes: [
     7,  7, 7,  7,  7,
     7,  7, 8, 12, 12,
    12, 12
  ],
  score: -1,
  indexes: [
     0, 1, 2, 3, 4,
     5, 6, 7, 8, 9,
    10
  ],
  obj: null
}

Saved results:
[
  {
    left: {
      target: 'Inventory Items',
      _targetLowerCodes: [Array],
      _nextBeginningIndexes: [Array],
      score: 0,
      indexes: [Array],
      obj: null
    },
    right: {
      target: 'Average Cost',
      _targetLowerCodes: [Array],
      _nextBeginningIndexes: [Array],
      score: -17,
      indexes: [Array],
      obj: null
    }
  }
]

Proposed solution

Make a shallow copy of the prepared object at the return moment of the algorithm function. This will not impact on the performance of the search function.

pablolmiranda avatar Oct 09 '20 23:10 pablolmiranda