UNPKG

page-parser-tree

Version:

Library to find elements in a dynamic web page

242 lines (203 loc) 7.47 kB
"use strict"; 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