(ownerID, shift, keyHash, key, value, didChangeSize, didAlter)
| 481 | } |
| 482 | |
| 483 | update(ownerID, shift, keyHash, key, value, didChangeSize, didAlter) { |
| 484 | if (keyHash === undefined) { |
| 485 | keyHash = hash(key); |
| 486 | } |
| 487 | |
| 488 | const removed = value === NOT_SET; |
| 489 | |
| 490 | if (keyHash !== this.keyHash) { |
| 491 | if (removed) { |
| 492 | return this; |
| 493 | } |
| 494 | SetRef(didAlter); |
| 495 | SetRef(didChangeSize); |
| 496 | return mergeIntoNode(this, ownerID, shift, keyHash, [key, value]); |
| 497 | } |
| 498 | |
| 499 | const entries = this.entries; |
| 500 | const len = entries.length; |
| 501 | const isEditable = ownerID && ownerID === this.ownerID; |
| 502 | const foundIdx = this._positionOf(key, isEditable); |
| 503 | const idx = foundIdx === -1 ? len : foundIdx; |
| 504 | const exists = foundIdx !== -1; |
| 505 | |
| 506 | if (exists ? entries[idx][1] === value : removed) { |
| 507 | return this; |
| 508 | } |
| 509 | |
| 510 | SetRef(didAlter); |
| 511 | // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here |
| 512 | (removed || !exists) && SetRef(didChangeSize); |
| 513 | |
| 514 | if (removed && len === 2) { |
| 515 | return new ValueNode(ownerID, this.keyHash, entries[idx ^ 1]); |
| 516 | } |
| 517 | |
| 518 | const newEntries = isEditable ? entries : arrCopy(entries); |
| 519 | |
| 520 | if (exists) { |
| 521 | if (removed) { |
| 522 | // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here |
| 523 | idx === len - 1 |
| 524 | ? newEntries.pop() |
| 525 | : (newEntries[idx] = newEntries.pop()); |
| 526 | // The swap-pop reshuffles positions; drop the stale index (rebuilt lazily). |
| 527 | if (isEditable) { |
| 528 | this._index = undefined; |
| 529 | } |
| 530 | } else { |
| 531 | // Same key, same position: the index stays valid. |
| 532 | newEntries[idx] = [key, value]; |
| 533 | } |
| 534 | } else { |
| 535 | newEntries.push([key, value]); |
| 536 | // Keep the index in sync on the transient insert path. Persistent inserts |
| 537 | // return a fresh node below whose index rebuilds lazily, so skip them. |
| 538 | if (isEditable && this._index !== undefined) { |
| 539 | const secondaryHash = hashCollisionKey(key); |
| 540 | const positions = this._index[secondaryHash]; |
nothing calls this directly
no test coverage detected