From bd2c6ddbff0eb1b864e3445bcd834a4027b84210 Mon Sep 17 00:00:00 2001 From: Joscha Feth Date: Sat, 28 Sep 2024 23:03:09 +0100 Subject: [PATCH] refactor: move out of class --- lib/types.js | 74 ++++++++++++++++++++++++++-------------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/lib/types.js b/lib/types.js index f149fd95..5521296c 100644 --- a/lib/types.js +++ b/lib/types.js @@ -1252,28 +1252,44 @@ function generateProjectionIndexer(projectionFn) { }; } -function generateDefaultIndexer() { - this._dynamicBranches = null; - this._bucketIndices = {}; - this.types.forEach(function (type, index) { - if (Type.isType(type, 'abstract', 'logical')) { - if (!this._dynamicBranches) { - this._dynamicBranches = []; +function generateDefaultIndexer(types) { + const dynamicBranches = []; + const bucketIndices = {}; + + const getBranchIndex = (any, index) => { + let logicalBranches = dynamicBranches; + for (let i = 0, l = logicalBranches.length; i < l; i++) { + let branch = logicalBranches[i]; + if (branch.type._check(any)) { + if (index === undefined) { + index = branch.index; + } else { + // More than one branch matches the value so we aren't guaranteed to + // infer the correct type. We throw rather than corrupt data. This can + // be fixed by "tightening" the logical types. + throw new Error('ambiguous conversion'); + } } - this._dynamicBranches.push({index, type}); + } + return index; + } + + types.forEach(function (type, index) { + if (Type.isType(type, 'abstract', 'logical')) { + dynamicBranches.push({index, type}); } else { let bucket = getTypeBucket(type); - if (this._bucketIndices[bucket] !== undefined) { + if (bucketIndices[bucket] !== undefined) { throw new Error(`ambiguous unwrapped union: ${j(this)}`); } - this._bucketIndices[bucket] = index; + bucketIndices[bucket] = index; } }, this); return (val) => { - let index = this._bucketIndices[getValueBucket(val)]; - if (this._dynamicBranches) { + let index = bucketIndices[getValueBucket(val)]; + if (dynamicBranches.length) { // Slower path, we must run the value through all branches. - index = this._getBranchIndex(val, index); + index = getBranchIndex(val, index); } return index; }; @@ -1310,30 +1326,12 @@ class UnwrappedUnionType extends UnionType { } } this._getIndex = _projectionFn - ? generateProjectionIndexer(projectionFn) + ? generateProjectionIndexer(_projectionFn) : generateDefaultIndexer.bind(this)(this.types); Object.freeze(this); } - _getBranchIndex (any, index) { - let logicalBranches = this._dynamicBranches; - for (let i = 0, l = logicalBranches.length; i < l; i++) { - let branch = logicalBranches[i]; - if (branch.type._check(any)) { - if (index === undefined) { - index = branch.index; - } else { - // More than one branch matches the value so we aren't guaranteed to - // infer the correct type. We throw rather than corrupt data. This can - // be fixed by "tightening" the logical types. - throw new Error('ambiguous conversion'); - } - } - } - return index; - } - _check (val, flags, hook, path) { let index = this._getIndex(val); let b = index !== undefined; @@ -1393,16 +1391,18 @@ class UnwrappedUnionType extends UnionType { // Using the `coerceBuffers` option can cause corruption and erroneous // failures with unwrapped unions (in rare cases when the union also // contains a record which matches a buffer's JSON representation). - if (isJsonBuffer(val) && this._bucketIndices.buffer !== undefined) { - index = this._bucketIndices.buffer; - } else { - index = this._getIndex(val); + if (isJsonBuffer(val)) { + let bufIndex = this.types.findIndex(t => getTypeBucket(t) === 'buffer'); + if (bufIndex !== -1) { + index = bufIndex; + } } + index ??= this._getIndex(val); break; case 2: // Decoding from JSON, we must unwrap the value. if (val === null) { - index = this._bucketIndices['null']; + index = this._getIndex(null); } else if (typeof val === 'object') { let keys = Object.keys(val); if (keys.length === 1) {