UNPKG

fontoxpath

Version:

A minimalistic XPath 3.1 engine in JavaScript

81 lines (71 loc) 1.94 kB
import Selector from '../../Selector'; import Specificity from '../../Specificity'; import Sequence from '../../dataTypes/Sequence'; import { trueBoolean, falseBoolean } from '../../dataTypes/createAtomicValue'; import { DONE_TOKEN, notReady, ready } from '../../util/iterators'; /** * @extends {Selector} */ class OrOperator extends Selector { /** * @param {!Array<!Selector>} selectors */ constructor (selectors) { const maxSpecificity = selectors.reduce((maxSpecificity, selector) => { if (maxSpecificity.compareTo(selector.specificity) > 0) { return maxSpecificity; } return selector.specificity; }, new Specificity({})); super(maxSpecificity, { canBeStaticallyEvaluated: selectors.every(selector => selector.canBeStaticallyEvaluated) }); // If all subSelectors define the same bucket: use that one, else, use no bucket. this._bucket = selectors.reduce(function (bucket, selector) { if (bucket === undefined) { return selector.getBucket(); } if (bucket === null) { return null; } if (bucket !== selector.getBucket()) { return null; } return bucket; }, undefined); this._subSelectors = selectors; } evaluate (dynamicContext) { let i = 0; let resultSequence = null; let done = false; return new Sequence({ next: () => { if (!done) { while (i < this._subSelectors.length) { if (!resultSequence) { resultSequence = this._subSelectors[i].evaluateMaybeStatically(dynamicContext); } const ebv = resultSequence.tryGetEffectiveBooleanValue(); if (!ebv.ready) { return notReady(ebv.promise); } if (ebv.value === true) { done = true; return ready(trueBoolean); } resultSequence = null; i++; } done = true; return ready(falseBoolean); } return DONE_TOKEN; } }); } getBucket () { return this._bucket; } } export default OrOperator;