page-parser-tree
Version:
Library to find elements in a dynamic web page
242 lines (203 loc) • 7.47 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = watcherFinderMerger;
var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
var _liveSet = _interopRequireDefault(require("live-set"));
function watcherFinderMerger(scheduler, tagTree, tag, tagOptions, watcherSet, finder, logError) {
return new _liveSet["default"]({
scheduler: scheduler,
read: function read() {
throw new Error('Should not happen');
},
listen: function listen(setValues, controller) {
var currentElements = new Set();
var currentElementContexts = new Set();
var watcherFoundElements = new Set();
var watcherFoundElementsMissedByFinder = new Set();
var sub = null;
if (watcherSet) {
sub = watcherSet.subscribe({
start: function start() {
if (!watcherSet) throw new Error();
var currentValues = watcherSet.values();
setValues(currentValues);
currentValues.forEach(function (ec) {
watcherFoundElements.add(ec.el);
currentElements.add(ec.el);
currentElementContexts.add(ec);
});
},
next: function next(changes) {
changes.forEach(function (change) {
if (change.type === 'add') {
var _el = change.value.el;
watcherFoundElements.add(_el);
if (currentElements.has(_el)) {
logError(new Error("PageParserTree(".concat(tag, ") watcher found element already found by finder")), _el);
} else {
currentElements.add(_el);
currentElementContexts.add(change.value);
controller.add(change.value);
}
} else if (change.type === 'remove') {
var _el2 = change.value.el;
watcherFoundElements["delete"](_el2);
watcherFoundElementsMissedByFinder["delete"](_el2);
if (currentElementContexts.has(change.value)) {
currentElements["delete"](_el2);
currentElementContexts["delete"](change.value);
controller.remove(change.value);
} // else the ec was added by finder and it will deal with this
}
});
},
error: function error(err) {
controller.error(err);
},
complete: function complete() {
controller.end();
}
});
} else {
setValues(new Set());
}
var finderSchedule = null;
if (finder) {
var fn = finder.fn,
interval = finder.interval;
var ownedBy = tagOptions.ownedBy || [];
var runFinder = function runFinder() {
var finderRunFoundElements = new Set();
var found = fn(tagTree.getValue());
for (var i = 0, len = found.length; i < len; i++) {
var _el3 = found[i];
finderRunFoundElements.add(_el3);
if (!currentElements.has(_el3)) {
currentElements.add(_el3);
var ec = makeElementContext(_el3, tagTree, ownedBy);
currentElementContexts.add(ec);
controller.add(ec);
if (watcherSet) {
logError(new Error("PageParserTree(".concat(tag, ") finder found element missed by watcher")), _el3);
if (sub) sub.pullChanges();
}
}
}
currentElementContexts.forEach(function (ec) {
var el = ec.el;
if (!finderRunFoundElements.has(el)) {
if (watcherFoundElements.has(el)) {
if (!watcherFoundElementsMissedByFinder.has(el)) {
watcherFoundElementsMissedByFinder.add(el);
logError(new Error("PageParserTree(".concat(tag, ") watcher found element missed by finder")), el);
}
} else {
currentElementContexts["delete"](ec);
currentElements["delete"](el);
controller.remove(ec);
if (sub) sub.pullChanges();
}
}
});
scheduler.flush();
};
finderSchedule = scheduleRepeatingFinder(interval, currentElements, runFinder);
}
return {
unsubscribe: function unsubscribe() {
if (finderSchedule != null) finderSchedule.dispose();
if (sub) sub.unsubscribe();
},
pullChanges: function pullChanges() {
if (sub) sub.pullChanges();
}
};
}
});
}
function scheduleRepeatingFinder(interval, currentElements, runFinder) {
var finderStartedTimestamp = Date.now();
var timeoutHandle = null;
var idleHandle = null;
var step = function step() {
idleHandle = null;
runFinder();
scheduleNextStep();
};
var scheduleNextStep = function scheduleNextStep() {
var time;
if (interval == null) {
time = 5000 + Math.random() * 1000;
} else if (typeof interval === 'number') {
time = interval;
} else if (typeof interval === 'function') {
time = interval(currentElements.size, Date.now() - finderStartedTimestamp);
} else {
throw new Error("interval has wrong type: ".concat((0, _typeof2["default"])(interval)));
} // Assert to Flow that all paths should have set time to a number.
time;
if (time === Infinity) {
return;
}
timeoutHandle = setTimeout(function () {
timeoutHandle = null;
if (global.requestIdleCallback && global.cancelIdleCallback) {
// Wait up to `time` milliseconds again until there's an idle moment.
idleHandle = global.requestIdleCallback(step, {
timeout: time
});
} else {
step();
}
}, time);
};
scheduleNextStep();
return {
dispose: function dispose() {
if (timeoutHandle != null) clearTimeout(timeoutHandle);
if (idleHandle != null) global.cancelIdleCallback(idleHandle);
}
};
}
function makeElementContext(el, tagTree, ownedBy) {
// Don't compute parents until it's read from.
// This is important because nodes aren't added to the tag tree until
// PageParserTree iterates over the results, and some of these nodes may be
// owned by each other.
var _cachedParents = null;
return {
el: el,
get parents() {
if (!_cachedParents) {
var root = tagTree.getValue();
var parents = [];
var current = el.parentElement;
while (current) {
var tagTreeNodes = tagTree.getNodesForValue(current);
for (var i = 0, len = tagTreeNodes.length; i < len; i++) {
var node = tagTreeNodes[i];
var tag = node.getTag();
if (tag == null || ownedBy.indexOf(tag) >= 0) {
parents.push({
tag: tag,
node: node
});
break;
}
}
if (current === root) break;
current = current.parentElement;
}
parents.reverse();
_cachedParents = parents;
}
return _cachedParents;
}
};
}
module.exports = exports.default;
module.exports.default = exports.default;
//# sourceMappingURL=watcherFinderMerger.js.map