fontoxpath
Version:
A minimalistic XPath 3.1 engine in JavaScript
52 lines (42 loc) • 1.92 kB
JavaScript
import { evaluateXPathToFirstNode, evaluateXPathToNodes, evaluateXPathToBoolean } from 'fontoxpath';
import * as slimdom from 'slimdom';
import xqString from 'text-loader!./performance-regression.xq';
const cacheId = {};
function timeXPath (xpath, document) {
const then = performance.now();
chai.assert(evaluateXPathToBoolean(xpath, document), `The passed XPath ${xpath} should resolve to true`);
const now = performance.now();
return now - then;
}
function fillDocument (document, element, depth) {
element.setAttribute('depth', depth);
if (depth === 0) {
return element;
}
var prototypeElement = element.appendChild(
fillDocument(
document,
document.createElement('ele'),
depth - 1));
for (let i = 1, l = 10; i < l; ++i) {
element.appendChild(prototypeElement.cloneNode(true));
}
return element;
}
function runTests (document) {
const element = evaluateXPathToFirstNode(xqString, document, null, null, { language: 'XQuery3.1' });
const cells = evaluateXPathToNodes('descendant::entry', element);
before(function () {
this.timeout(30000);
});
it('Makes queries exit early by streaming them and only consuming the first item', function () {
this.timeout(10000);
for (var i = 0; i < 100; ++i) {
const times = cells.map(cell => timeXPath('"let $colname := ./@colname, $namest := ./@namest, $nameend := ./@nameend, $startindex := ./ancestor::Q{}tgroup[1]/Q{}colspec[@colname = $namest]/preceding-sibling::Q{}colspec => count() + 1, $endindex := ./ancestor::Q{}tgroup[1]/Q{}colspec[@colname = $nameend]/preceding-sibling::Q{}colspec => count() + 1 return if ($colname and not($namest or $nameend)) then 1 else ($endindex - $startindex) + 1"', cell));
console.log(times.reduce((sum, time) => sum + time, 0) / times.length);
}
});
}
describe('performance regression of 2.8.0', () => {
describe('in slimdom', () => runTests(new slimdom.Document()));
});