blob: 1b98f422234069af9962cf26177afe3d88ec783c [file]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @ts-check
'use strict';
const _innerWorker = new Worker('tree-worker.js');
/**
* We use a worker to keep large tree creation logic off the UI thread.
* This class is used to interact with the worker.
*/
class TreeWorker {
/**
* @param {Worker} worker Web worker to wrap
*/
constructor(worker) {
this._worker = worker;
/** ID counter used by `waitForResponse` */
this._requestId = 1;
/** @type {(data: TreeProgress) => void | null} callback for `loadTree` */
this._loadTreeCallback = null;
this._worker.addEventListener('message', event => {
if (this._loadTreeCallback && event.data.id === 0) {
this._loadTreeCallback(event.data);
}
});
}
/**
*
* @param {string} action
* @param {any} data
*/
_waitForResponse(action, data) {
const id = ++this._requestId;
return new Promise((resolve, reject) => {
const handleResponse = event => {
if (event.data.id === id) {
this._worker.removeEventListener('message', handleResponse);
if (event.data.error) {
reject(event.data.error);
} else {
resolve(event.data.result);
}
}
};
this._worker.addEventListener('message', handleResponse);
this._worker.postMessage({id, action, data});
});
}
/**
* Get data for a node with `idPath`. Loads information about the node and its
* direct children. Deeper children can be loaded by calling this function
* again.
* @param {string} idPath Path of the node to find
* @returns {Promise<TreeNode | null>}
*/
openNode(idPath) {
return this._waitForResponse('open', idPath);
}
/**
* Set callback used after `loadTree` is first called.
* @param {(data: TreeProgress) => void} callback Called when the worker
* has some data to display. Complete when `progress` is 1.
*/
setOnProgressHandler(callback) {
this._loadTreeCallback = callback;
}
/**
* Loads the tree data given on a worker thread and replaces the tree view in
* the UI once complete. Uses query string as state for the options.
* Use `onProgress` before calling `loadTree`.
* @param {string} input
* @returns {Promise<TreeProgress>}
*/
loadTree(input = null) {
return this._waitForResponse('load', {
input,
options: location.search.slice(1),
});
}
}
const worker = new TreeWorker(_innerWorker);
// Kick off the worker ASAP so it can start parsing data faster.
// Subsequent calls will just use a worker locally.
const treeReady = worker.loadTree('from-url://');