Problem
_searchObjectList builds its key list from FuseIndex.keys, which holds the raw user-specified weights. KeyStore normalises those weights (so they sum to 1), but _searchObjectList never consults KeyStore — it reads the original numbers directly.
This has two observable effects:
1. Score underflow for high key weights
A single key always normalises to weight = 1.0 (the only key contributes 100 % of the weight). Yet when a user writes weight: 100, the raw value is used in the exponent:
// Exact match (score === 0) → uses Number.EPSILON as base
Math.pow(Number.EPSILON, 100 * fieldNorm) // underflows to exactly 0
const fuseW1 = new Fuse([{ text: 'hello' }], { keys: [{ name: 'text', weight: 1 }], includeScore: true })
const fuseW100 = new Fuse([{ text: 'hello' }], { keys: [{ name: 'text', weight: 100 }], includeScore: true })
fuseW1.search('hello')[0].score // ~2.2e-16 (correct)
fuseW100.search('hello')[0].score // 0 ← wrong: underflow due to raw weight=100
After normalisation both instances have key.weight = 1.0, so the scores must be equal.
2. Score inconsistency between string queries and logical-expression queries
_searchObjectList (used for plain string queries) uses raw weights, while _searchLogical (used for Expression objects) fetches keys from this._keyStore.get(keyId) — the normalised version. The same search over the same data produces different absolute score values depending on query form.
Root cause
// src/core/index.ts — _searchObjectList
const { keys, records } = this._myIndex // ← FuseIndex.keys = raw weights
should use this._keyStore.keys() (normalised), consistent with _searchLogical.
Minimal reproduction
import Fuse from 'fuse.js'
// Single-key: weight:1 and weight:100 both normalise to 1.0
const f1 = new Fuse([{ text: 'hello' }], { keys: [{ name: 'text', weight: 1 }], includeScore: true })
const f100 = new Fuse([{ text: 'hello' }], { keys: [{ name: 'text', weight: 100 }], includeScore: true })
console.log(f1.search('hello')[0].score) // ~2.2e-16
console.log(f100.search('hello')[0].score) // 0 ← underflow
Expected
Both calls return the same score (normalised weight = 1.0 for a single key).
Problem
_searchObjectListbuilds its key list fromFuseIndex.keys, which holds the raw user-specified weights.KeyStorenormalises those weights (so they sum to 1), but_searchObjectListnever consultsKeyStore— it reads the original numbers directly.This has two observable effects:
1. Score underflow for high key weights
A single key always normalises to
weight = 1.0(the only key contributes 100 % of the weight). Yet when a user writesweight: 100, the raw value is used in the exponent:After normalisation both instances have
key.weight = 1.0, so the scores must be equal.2. Score inconsistency between string queries and logical-expression queries
_searchObjectList(used for plain string queries) uses raw weights, while_searchLogical(used forExpressionobjects) fetches keys fromthis._keyStore.get(keyId)— the normalised version. The same search over the same data produces different absolute score values depending on query form.Root cause
should use
this._keyStore.keys()(normalised), consistent with_searchLogical.Minimal reproduction
Expected
Both calls return the same score (normalised weight = 1.0 for a single key).