Skip to content

Commit ba0c60f

Browse files
committed
rebuild cql4browsers after npm audit fix
1 parent 8c701b8 commit ba0c60f

1 file changed

Lines changed: 193 additions & 21 deletions

File tree

examples/browser/cql4browsers.js

Lines changed: 193 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16505,6 +16505,26 @@ const UnitTables = exports.UnitTables = {
1650516505
}
1650616506
return smi(hashed);
1650716507
}
16508+
// Per-process seed for the secondary collision hash. Never exposed nor
16509+
// serialized, so the public `hash()` stays deterministic. An odd base in
16510+
// [3, 2^20) keeps `base * h` exact as a double (no `Math.imul`).
16511+
var COLLISION_HASH_BASE = ((Math.random() * 0x100000) | 1) % 0x100000 || 0x9e37;
16512+
// Secondary hash to index entries within a `HashCollisionNode`, where every key
16513+
// shares the same primary `hash()`. Using a different, seeded base scatters
16514+
// crafted collision families (e.g. "Aa"/"BB", which only collide under base 31)
16515+
// that an attacker cannot precompute without the seed. It only narrows
16516+
// candidates — `is()` still decides equality — so non-string keys can safely
16517+
// fall back to the (here constant) primary hash and a linear scan.
16518+
function hashCollisionKey(key) {
16519+
if (typeof key !== 'string') {
16520+
return hash(key);
16521+
}
16522+
var hashed = 0;
16523+
for (var ii = 0; ii < key.length; ii++) {
16524+
hashed = (COLLISION_HASH_BASE * hashed + key.charCodeAt(ii)) | 0;
16525+
}
16526+
return hashed;
16527+
}
1650816528
function hashSymbol(sym) {
1650916529
var hashed = symbolMap[sym];
1651016530
if (hashed !== undefined) {
@@ -18437,20 +18457,79 @@ const UnitTables = exports.UnitTables = {
1843718457
return new HashArrayMapNode(ownerID, newCount, newNodes);
1843818458
};
1843918459

18460+
/**
18461+
* Trie leaf gathering entries whose keys all share the same 32-bit `hash()`.
18462+
* The trie routes by hash, so colliding keys cannot be separated and land here
18463+
* in a flat `entries` array, disambiguated by `is()`.
18464+
*
18465+
* To guard against hash-flooding DoS (CWE-407), large buckets build a secondary
18466+
* index keyed by a per-process seeded hash (`hashCollisionKey`). `is()` still
18467+
* decides equality, so the index can only ever narrow candidates, never lose a key.
18468+
*/
1844018469
var HashCollisionNode = function HashCollisionNode(ownerID, keyHash, entries) {
1844118470
this.ownerID = ownerID;
1844218471
this.keyHash = keyHash;
1844318472
this.entries = entries;
18473+
// Lazy `{ [secondaryHash]: number[] }`, built only past
18474+
// MIN_HASH_COLLISION_INDEX_SIZE so small buckets keep their linear path.
18475+
this._index = undefined;
1844418476
};
1844518477

18446-
HashCollisionNode.prototype.get = function get (shift, keyHash, key, notSetValue) {
18478+
// Returns the position of `key` in `this.entries`, or -1. Uses the secondary
18479+
// index when present; builds it only when `buildIndex` is true (reads and
18480+
// transient inserts, where the node is reused so the O(n) build amortizes).
18481+
// Persistent inserts already pay an O(n) copy, so a throwaway index is skipped.
18482+
HashCollisionNode.prototype._positionOf = function _positionOf (key, buildIndex) {
18483+
var entries = this.entries;
18484+
var index = this._index;
18485+
if (
18486+
index === undefined &&
18487+
buildIndex &&
18488+
entries.length >= MIN_HASH_COLLISION_INDEX_SIZE
18489+
) {
18490+
index = this._buildIndex();
18491+
}
18492+
if (index !== undefined) {
18493+
var positions = index[hashCollisionKey(key)];
18494+
if (positions !== undefined) {
18495+
for (var jj = 0; jj < positions.length; jj++) {
18496+
var ii = positions[jj];
18497+
if (is(key, entries[ii][0])) {
18498+
return ii;
18499+
}
18500+
}
18501+
}
18502+
return -1;
18503+
}
18504+
for (var ii$1 = 0, len = entries.length; ii$1 < len; ii$1++) {
18505+
if (is(key, entries[ii$1][0])) {
18506+
return ii$1;
18507+
}
18508+
}
18509+
return -1;
18510+
};
18511+
18512+
// Builds and memoizes the secondary index. A plain object, not `Map` — which
18513+
// in this module resolves to the *Immutable* Map, not the native one.
18514+
HashCollisionNode.prototype._buildIndex = function _buildIndex () {
18515+
var index = Object.create(null);
1844718516
var entries = this.entries;
1844818517
for (var ii = 0, len = entries.length; ii < len; ii++) {
18449-
if (is(key, entries[ii][0])) {
18450-
return entries[ii][1];
18518+
var secondaryHash = hashCollisionKey(entries[ii][0]);
18519+
var positions = index[secondaryHash];
18520+
if (positions !== undefined) {
18521+
positions.push(ii);
18522+
} else {
18523+
index[secondaryHash] = [ii];
1845118524
}
1845218525
}
18453-
return notSetValue;
18526+
this._index = index;
18527+
return index;
18528+
};
18529+
18530+
HashCollisionNode.prototype.get = function get (shift, keyHash, key, notSetValue) {
18531+
var idx = this._positionOf(key, true);
18532+
return idx === -1 ? notSetValue : this.entries[idx][1];
1845418533
};
1845518534

1845618535
HashCollisionNode.prototype.update = function update (ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {
@@ -18470,14 +18549,11 @@ const UnitTables = exports.UnitTables = {
1847018549
}
1847118550

1847218551
var entries = this.entries;
18473-
var idx = 0;
1847418552
var len = entries.length;
18475-
for (; idx < len; idx++) {
18476-
if (is(key, entries[idx][0])) {
18477-
break;
18478-
}
18479-
}
18480-
var exists = idx < len;
18553+
var isEditable = ownerID && ownerID === this.ownerID;
18554+
var foundIdx = this._positionOf(key, isEditable);
18555+
var idx = foundIdx === -1 ? len : foundIdx;
18556+
var exists = foundIdx !== -1;
1848118557

1848218558
if (exists ? entries[idx][1] === value : removed) {
1848318559
return this;
@@ -18491,7 +18567,6 @@ const UnitTables = exports.UnitTables = {
1849118567
return new ValueNode(ownerID, this.keyHash, entries[idx ^ 1]);
1849218568
}
1849318569

18494-
var isEditable = ownerID && ownerID === this.ownerID;
1849518570
var newEntries = isEditable ? entries : arrCopy(entries);
1849618571

1849718572
if (exists) {
@@ -18500,11 +18575,27 @@ const UnitTables = exports.UnitTables = {
1850018575
idx === len - 1
1850118576
? newEntries.pop()
1850218577
: (newEntries[idx] = newEntries.pop());
18578+
// The swap-pop reshuffles positions; drop the stale index (rebuilt lazily).
18579+
if (isEditable) {
18580+
this._index = undefined;
18581+
}
1850318582
} else {
18583+
// Same key, same position: the index stays valid.
1850418584
newEntries[idx] = [key, value];
1850518585
}
1850618586
} else {
1850718587
newEntries.push([key, value]);
18588+
// Keep the index in sync on the transient insert path. Persistent inserts
18589+
// return a fresh node below whose index rebuilds lazily, so skip them.
18590+
if (isEditable && this._index !== undefined) {
18591+
var secondaryHash = hashCollisionKey(key);
18592+
var positions = this._index[secondaryHash];
18593+
if (positions !== undefined) {
18594+
positions.push(len);
18595+
} else {
18596+
this._index[secondaryHash] = [len];
18597+
}
18598+
}
1850818599
}
1850918600

1851018601
if (isEditable) {
@@ -18838,6 +18929,12 @@ const UnitTables = exports.UnitTables = {
1883818929
var MAX_BITMAP_INDEXED_SIZE = SIZE / 2;
1883918930
var MIN_HASH_ARRAY_MAP_SIZE = SIZE / 4;
1884018931

18932+
// Above this many colliding entries, a `HashCollisionNode` builds a seeded
18933+
// secondary index instead of scanning linearly. Kept small so the rare,
18934+
// naturally-occurring collision buckets stay overhead-free, while adversarial
18935+
// hash-flooding (thousands of keys sharing one hash) degrades gracefully.
18936+
var MIN_HASH_COLLISION_INDEX_SIZE = 16;
18937+
1884118938
function coerceKeyPath(keyPath) {
1884218939
if (isArrayLike(keyPath) && typeof keyPath !== 'string') {
1884318940
return keyPath;
@@ -19026,7 +19123,7 @@ const UnitTables = exports.UnitTables = {
1902619123
assertNotInfinite(size);
1902719124
if (size > 0 && size < SIZE) {
1902819125
// eslint-disable-next-line no-constructor-return
19029-
return makeList(0, size, SHIFT, null, new VNode(iter.toArray()));
19126+
return makeList(0, size, SHIFT, undefined, new VNode(iter.toArray()));
1903019127
}
1903119128
// eslint-disable-next-line no-constructor-return
1903219129
return empty.withMutations(function (list) {
@@ -19269,6 +19366,13 @@ const UnitTables = exports.UnitTables = {
1926919366
return obj.asImmutable();
1927019367
};
1927119368

19369+
/**
19370+
* A node in the List's 32-wide trie. At inner levels `array` holds child
19371+
* `VNode`s; at the leaf level it holds the List's values. Missing slots are
19372+
* `undefined` array holes.
19373+
*
19374+
* @template T
19375+
*/
1927219376
var VNode = function VNode(array, ownerID) {
1927319377
this.array = array;
1927419378
this.ownerID = ownerID;
@@ -19405,6 +19509,16 @@ const UnitTables = exports.UnitTables = {
1940519509
}
1940619510
}
1940719511

19512+
/**
19513+
* @param {number} origin
19514+
* @param {number} capacity
19515+
* @param {number} level
19516+
* @param {VNode | undefined} [root] The trie root, or `undefined` when every
19517+
* in-range value lives in the tail (or is a virtual `undefined`).
19518+
* @param {VNode | undefined} [tail]
19519+
* @param {OwnerID} [ownerID]
19520+
* @param {number} [hash]
19521+
*/
1940819522
function makeList(origin, capacity, level, root, tail, ownerID, hash) {
1940919523
var list = Object.create(ListPrototype);
1941019524
list.size = capacity - origin;
@@ -19522,6 +19636,14 @@ const UnitTables = exports.UnitTables = {
1952219636
return new VNode(node ? node.array.slice() : [], ownerID);
1952319637
}
1952419638

19639+
/**
19640+
* Returns the leaf `VNode` holding `rawIndex`, or `undefined` when no node is
19641+
* allocated for it (an all-`undefined` region).
19642+
*
19643+
* @param {List} list
19644+
* @param {number} rawIndex
19645+
* @returns {VNode | undefined}
19646+
*/
1952519647
function listNodeFor(list, rawIndex) {
1952619648
if (rawIndex >= getTailOffset(list._capacity)) {
1952719649
return list._tail;
@@ -19537,7 +19659,39 @@ const UnitTables = exports.UnitTables = {
1953719659
}
1953819660
}
1953919661

19662+
/**
19663+
* Validates requested bounds before int32 coercion in setListBounds().
19664+
* Throws when origin/capacity would exceed the trie's safe range.
19665+
*/
19666+
function validateListBoundsRequest(list, begin, end) {
19667+
var requestedOrigin = list._origin + (begin === undefined ? 0 : begin);
19668+
var requestedCapacity =
19669+
end === undefined
19670+
? list._capacity
19671+
: end < 0
19672+
? list._capacity + end
19673+
: list._origin + end;
19674+
19675+
// Keep origin/capacity within the trie's safe signed 32-bit range.
19676+
if (
19677+
(Number.isFinite(requestedCapacity) && requestedCapacity > MAX_LIST_SIZE) ||
19678+
(Number.isFinite(requestedOrigin) && requestedOrigin < -MAX_LIST_SIZE) ||
19679+
(Number.isFinite(requestedCapacity) &&
19680+
Number.isFinite(requestedOrigin) &&
19681+
requestedCapacity - requestedOrigin > MAX_LIST_SIZE)
19682+
) {
19683+
throw new RangeError(
19684+
'Invalid List size: a List cannot hold more than ' +
19685+
MAX_LIST_SIZE +
19686+
' (2 ** 30) values.'
19687+
);
19688+
}
19689+
}
19690+
1954019691
function setListBounds(list, begin, end) {
19692+
// Validate full-precision bounds before int32 coercion.
19693+
validateListBoundsRequest(list, begin, end);
19694+
1954119695
// Sanitize begin & end using this shorthand for ToInt32(argument)
1954219696
// http://www.ecma-international.org/ecma-262/6.0/#sec-toint32
1954319697
if (begin !== undefined) {
@@ -19576,7 +19730,8 @@ const UnitTables = exports.UnitTables = {
1957619730
owner
1957719731
);
1957819732
newLevel += SHIFT;
19579-
offsetShift += 1 << newLevel;
19733+
// Shift origin into non-negative space as trie height grows.
19734+
offsetShift += levelCapacity(newLevel);
1958019735
}
1958119736
if (offsetShift) {
1958219737
newOrigin += offsetShift;
@@ -19589,7 +19744,7 @@ const UnitTables = exports.UnitTables = {
1958919744
var newTailOffset = getTailOffset(newCapacity);
1959019745

1959119746
// New size might need creating a higher root.
19592-
while (newTailOffset >= 1 << (newLevel + SHIFT)) {
19747+
while (newTailOffset >= levelCapacity(newLevel + SHIFT)) {
1959319748
newRoot = new VNode(
1959419749
newRoot && newRoot.array.length ? [newRoot] : [],
1959519750
owner
@@ -19632,7 +19787,7 @@ const UnitTables = exports.UnitTables = {
1963219787
newOrigin -= newTailOffset;
1963319788
newCapacity -= newTailOffset;
1963419789
newLevel = SHIFT;
19635-
newRoot = null;
19790+
newRoot = undefined;
1963619791
newTail = newTail && newTail.removeBefore(owner, 0, newOrigin);
1963719792

1963819793
// Otherwise, if the root has been trimmed, garbage collect.
@@ -19687,6 +19842,19 @@ const UnitTables = exports.UnitTables = {
1968719842
return size < SIZE ? 0 : ((size - 1) >>> SHIFT) << SHIFT;
1968819843
}
1968919844

19845+
// The largest number of values a List can hold. Above this the 32-bit trie math
19846+
// in setListBounds() stays in the safe signed 32-bit range.
19847+
var MAX_LIST_SIZE = Math.pow( 2, 30 ); // 1073741824
19848+
19849+
/**
19850+
* Computes 2 ** exp for the trie level-raising loops in setListBounds().
19851+
* Use the cheap bitwise operator shift whenever possible, otherwise fall back to exponentiation.
19852+
* This is necessary because bitwise operators in JavaScript only work on 32-bit signed integers, so for exp >= 31, we need to use exponentiation to avoid overflow.
19853+
*/
19854+
function levelCapacity(exp) {
19855+
return exp < 31 ? 1 << exp : Math.pow( 2, exp );
19856+
}
19857+
1969019858
/**
1969119859
* True if `maybeOrderedMap` is an OrderedMap.
1969219860
*/
@@ -20102,6 +20270,9 @@ const UnitTables = exports.UnitTables = {
2010220270
reduction = v;
2010320271
}
2010420272
else {
20273+
// `reduction` has already been seeded here (either with the provided
20274+
// initial value or with the first iterated value), so it is never the
20275+
// `undefined` placeholder — only a `V` or a `R`.
2010520276
reduction = reducer.call(context, reduction, v, k, c);
2010620277
}
2010720278
}, reverse);
@@ -21286,11 +21457,12 @@ const UnitTables = exports.UnitTables = {
2128621457

2128721458
has: function has(index) {
2128821459
index = wrapIndex(this, index);
21460+
2128921461
return (
2129021462
index >= 0 &&
2129121463
(this.size !== undefined
2129221464
? this.size === Infinity || index < this.size
21293-
: this.indexOf(index) !== -1)
21465+
: this.find(function (_, key) { return key === index; }, undefined, NOT_SET) !== NOT_SET)
2129421466
);
2129521467
},
2129621468

@@ -21751,15 +21923,15 @@ const UnitTables = exports.UnitTables = {
2175121923
};
2175221924

2175321925
Repeat.prototype.indexOf = function indexOf (searchValue) {
21754-
if (is(this._value, searchValue)) {
21926+
if (this.size !== 0 && is(this._value, searchValue)) {
2175521927
return 0;
2175621928
}
2175721929
return -1;
2175821930
};
2175921931

2176021932
Repeat.prototype.lastIndexOf = function lastIndexOf (searchValue) {
21761-
if (is(this._value, searchValue)) {
21762-
return this.size;
21933+
if (this.size !== 0 && is(this._value, searchValue)) {
21934+
return this.size - 1;
2176321935
}
2176421936
return -1;
2176521937
};
@@ -21840,7 +22012,7 @@ const UnitTables = exports.UnitTables = {
2184022012
return isIndexed(v) ? v.toList() : isKeyed(v) ? v.toMap() : v.toSet();
2184122013
}
2184222014

21843-
var version = "5.1.6";
22015+
var version = "5.1.9";
2184422016

2184522017
/* eslint-disable import/order */
2184622018

0 commit comments

Comments
 (0)