fontoxpath
Version:
A minimalistic XPath 3.1 engine in JavaScript
81 lines (71 loc) • 1.94 kB
JavaScript
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;