Use comlink in workers (#5915)

pull/5922/head
Paulus Schoutsen 2020-05-18 07:51:46 -07:00 committed by GitHub
parent d38a0f0366
commit a66d2ca1b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 117 additions and 81 deletions

View File

@ -2,6 +2,7 @@ const webpack = require("webpack");
const path = require("path");
const TerserPlugin = require("terser-webpack-plugin");
const ManifestPlugin = require("webpack-manifest-plugin");
const WorkerPlugin = require("worker-plugin");
const paths = require("./paths.js");
const env = require("./env.js");
const { babelLoaderConfig } = require("./babel.js");
@ -51,6 +52,7 @@ const createWebpackConfig = ({
],
},
plugins: [
new WorkerPlugin(),
new ManifestPlugin(),
new webpack.DefinePlugin({
__DEV__: !isProdBuild,
@ -105,7 +107,7 @@ const createWebpackConfig = ({
latestBuild ? "frontend_latest" : "frontend_es5"
),
publicPath: latestBuild ? "/frontend_latest/" : "/frontend_es5/",
// For workerize loader
// To silence warning in worker plugin
globalObject: "self",
},
};

View File

@ -86,6 +86,7 @@
"chart.js": "~2.8.0",
"chartjs-chart-timeline": "^0.3.0",
"codemirror": "^5.49.0",
"comlink": "^4.3.0",
"cpx": "^1.5.0",
"deep-clone-simple": "^1.1.1",
"deep-freeze": "^0.0.1",
@ -108,6 +109,7 @@
"memoize-one": "^5.0.2",
"moment": "^2.24.0",
"node-vibrant": "^3.1.5",
"proxy-polyfill": "^0.3.1",
"regenerator-runtime": "^0.13.2",
"resize-observer": "^1.0.0",
"roboto-fontface": "^0.10.0",
@ -195,7 +197,7 @@
"webpack-dev-server": "^3.10.3",
"webpack-manifest-plugin": "^2.0.4",
"workbox-build": "^5.1.3",
"workerize-loader": "^1.1.0"
"worker-plugin": "^4.0.3"
},
"_comment": "Polymer fixed to 3.1 because 3.2 throws on logbook page",
"_comment_2": "Fix in https://github.com/Polymer/polymer/pull/5569",

View File

@ -14,9 +14,6 @@ import { classMap } from "lit-html/directives/class-map";
import { ifDefined } from "lit-html/directives/if-defined";
import { styleMap } from "lit-html/directives/style-map";
import { scroll } from "lit-virtualizer";
// @ts-ignore
// eslint-disable-next-line import/no-webpack-loader-syntax
import sortFilterWorker from "workerize-loader!./sort_filter_worker";
import { fireEvent } from "../../common/dom/fire_event";
import "../../common/search/search-input";
import { debounce } from "../../common/util/debounce";
@ -24,6 +21,7 @@ import { nextRender } from "../../common/util/render-status";
import "../ha-checkbox";
import type { HaCheckbox } from "../ha-checkbox";
import "../ha-icon";
import { filterSortData } from "./sort-filter";
declare global {
// for fire event
@ -117,8 +115,6 @@ export class HaDataTable extends LitElement {
private curRequest = 0;
private _worker: any | undefined;
private _debounceSearch = debounce(
(value: string) => {
this._filter = value;
@ -140,11 +136,6 @@ export class HaDataTable extends LitElement {
}
}
protected firstUpdated(properties: PropertyValues) {
super.firstUpdated(properties);
this._worker = sortFilterWorker();
}
protected updated(properties: PropertyValues) {
super.updated(properties);
@ -383,7 +374,7 @@ export class HaDataTable extends LitElement {
this.curRequest++;
const curRequest = this.curRequest;
const filterProm = this._worker.filterSortData(
const filterProm = filterSortData(
this.data,
this._sortColumns,
this._filter,

View File

@ -0,0 +1,26 @@
import { wrap } from "comlink";
type FilterSortDataType = typeof import("./sort_filter_worker").api["filterSortData"];
type filterSortDataParamTypes = Parameters<FilterSortDataType>;
let worker: any | undefined;
export const filterSortData = async (
data: filterSortDataParamTypes[0],
columns: filterSortDataParamTypes[1],
filter: filterSortDataParamTypes[2],
direction: filterSortDataParamTypes[3],
sortColumn: filterSortDataParamTypes[4]
): Promise<ReturnType<FilterSortDataType>> => {
if (!worker) {
worker = wrap(new Worker("./sort_filter_worker", { type: "module" }));
}
return await worker.filterSortData(
data,
columns,
filter,
direction,
sortColumn
);
};

View File

@ -1,57 +1,34 @@
import memoizeOne from "memoize-one";
// eslint-disable-next-line import/no-cycle
import {
DataTableColumnContainer,
DataTableColumnData,
// To use comlink under ES5
import "proxy-polyfill";
import { expose } from "comlink";
import type {
DataTableSortColumnData,
DataTableRowData,
SortingDirection,
HaDataTable,
} from "./ha-data-table";
export const filterSortData = memoizeOne(
async (
type SortableColumnContainer = HaDataTable["_sortColumns"];
const filterSortData = (
data: DataTableRowData[],
columns: DataTableColumnContainer,
columns: SortableColumnContainer,
filter: string,
direction: SortingDirection,
sortColumn?: string
) =>
sortColumn
? _memSortData(
await _memFilterData(data, columns, filter),
columns,
direction,
sortColumn
)
: _memFilterData(data, columns, filter)
);
) => {
const filteredData = filter ? filterData(data, columns, filter) : data;
const _memFilterData = memoizeOne(
async (
data: DataTableRowData[],
columns: DataTableColumnContainer,
filter: string
) => {
if (!filter) {
return data;
if (!sortColumn) {
return filteredData;
}
return filterData(data, columns, filter.toUpperCase());
}
);
const _memSortData = memoizeOne(
(
data: DataTableRowData[],
columns: DataTableColumnContainer,
direction: SortingDirection,
sortColumn: string
) => {
return sortData(data, columns[sortColumn], direction, sortColumn);
}
);
return sortData(filteredData, columns, direction, sortColumn);
};
export const filterData = (
const filterData = (
data: DataTableRowData[],
columns: DataTableColumnContainer,
columns: SortableColumnContainer,
filter: string
) =>
data.filter((row) => {
@ -70,9 +47,9 @@ export const filterData = (
});
});
export const sortData = (
const sortData = (
data: DataTableRowData[],
column: DataTableColumnData,
column: DataTableSortColumnData,
direction: SortingDirection,
sortColumn: string
) =>
@ -105,3 +82,10 @@ export const sortData = (
}
return 0;
});
// Export for types
export const api = {
filterSortData,
};
expose(api);

View File

@ -1,10 +1,6 @@
import { customElement, property, UpdatingElement } from "lit-element";
// @ts-ignore
// eslint-disable-next-line import/no-webpack-loader-syntax
import markdownWorker from "workerize-loader!../resources/markdown_worker";
import { fireEvent } from "../common/dom/fire_event";
let worker: any | undefined;
import { renderMarkdown } from "../resources/render-markdown";
@customElement("ha-markdown")
class HaMarkdown extends UpdatingElement {
@ -16,16 +12,11 @@ class HaMarkdown extends UpdatingElement {
protected update(changedProps) {
super.update(changedProps);
if (!worker) {
worker = markdownWorker();
}
this._render();
}
private async _render() {
this.innerHTML = await worker.renderMarkdown(
this.innerHTML = await renderMarkdown(
this.content,
{
breaks: this.breaks,

View File

@ -2,6 +2,8 @@ import objAssign from "es6-object-assign";
import "mdn-polyfills/Array.prototype.includes";
import "regenerator-runtime/runtime";
import "unfetch/polyfill";
// To use comlink under ES5
import "proxy-polyfill";
objAssign.polyfill();

View File

@ -1,3 +1,6 @@
// To use comlink under ES5
import "proxy-polyfill";
import { expose } from "comlink";
import marked from "marked";
// @ts-ignore
import filterXSS from "xss";
@ -9,14 +12,14 @@ interface WhiteList {
let whiteListNormal: WhiteList | undefined;
let whiteListSvg: WhiteList | undefined;
export const renderMarkdown = (
const renderMarkdown = (
content: string,
markedOptions: object,
hassOptions: {
// Do not allow SVG on untrusted content, it allows XSS.
allowSvg?: boolean;
} = {}
) => {
): string => {
if (!whiteListNormal) {
whiteListNormal = {
...filterXSS.whiteList,
@ -45,3 +48,10 @@ export const renderMarkdown = (
whiteList,
});
};
// Export for types
export const api = {
renderMarkdown,
};
expose(api);

View File

@ -0,0 +1,18 @@
import { wrap } from "comlink";
type RenderMarkdownType = typeof import("./markdown_worker").api["renderMarkdown"];
type renderMarkdownParamTypes = Parameters<RenderMarkdownType>;
let worker: any | undefined;
export const renderMarkdown = async (
content: renderMarkdownParamTypes[0],
markedOptions: renderMarkdownParamTypes[1],
hassOptions?: renderMarkdownParamTypes[2]
): Promise<ReturnType<RenderMarkdownType>> => {
if (!worker) {
worker = wrap(new Worker("./markdown_worker", { type: "module" }));
}
return await worker.renderMarkdown(content, markedOptions, hassOptions);
};

View File

@ -5691,6 +5691,11 @@ combined-stream@^1.0.6, combined-stream@~1.0.6:
dependencies:
delayed-stream "~1.0.0"
comlink@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/comlink/-/comlink-4.3.0.tgz#80b3366baccd87897dab3638ebfcfae28b2f87c7"
integrity sha512-mu4KKKNuW8TvkfpW/H88HBPeILubBS6T94BdD1VWBXNXfiyqVtwUCVNO1GeNOBTsIswzsMjWlycYr+77F5b84g==
command-line-args@^5.0.2:
version "5.1.0"
resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.1.0.tgz#632d3d3df35c8f0cc4365e442a3fd6d63b65621b"
@ -12146,6 +12151,11 @@ proxy-addr@~2.0.5:
forwarded "~0.1.2"
ipaddr.js "1.9.0"
proxy-polyfill@^0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/proxy-polyfill/-/proxy-polyfill-0.3.1.tgz#163d5283cf928dd8ddb5c5e88528e4ccd233496f"
integrity sha512-jywE1NIksgIGqZc4uF0QLbXGz2RcHQobsCkAW+8F0nr/6agap+TWksEAKyLnIBafPD88HT9qZR2ec0oomHdjcQ==
prr@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
@ -15517,12 +15527,12 @@ worker-farm@^1.7.0:
dependencies:
errno "~0.1.7"
workerize-loader@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/workerize-loader/-/workerize-loader-1.1.0.tgz#d3a634390dcb685cc1ee292cd1fffeef0a646044"
integrity sha512-cU2jPVE3AzzVxOonBe9lCCO//qwE9s/K4a9njFVRLueznzNDNND5vGHVorGuzK6xvamdDOZ9+g7CPIc7QKzucQ==
worker-plugin@^4.0.3:
version "4.0.3"
resolved "https://registry.yarnpkg.com/worker-plugin/-/worker-plugin-4.0.3.tgz#7c42e600d5931ad154d3d5f187a32446df64db0f"
integrity sha512-7hFDYWiKcE3yHZvemsoM9lZis/PzurHAEX1ej8PLCu818Rt6QqUAiDdxHPCKZctzmhqzPpcFSgvMCiPbtooqAg==
dependencies:
loader-utils "^1.2.3"
loader-utils "^1.1.0"
wrap-ansi@^2.0.0:
version "2.1.0"