Use comlink in workers (#5915)
parent
d38a0f0366
commit
a66d2ca1b9
|
@ -2,6 +2,7 @@ const webpack = require("webpack");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const TerserPlugin = require("terser-webpack-plugin");
|
const TerserPlugin = require("terser-webpack-plugin");
|
||||||
const ManifestPlugin = require("webpack-manifest-plugin");
|
const ManifestPlugin = require("webpack-manifest-plugin");
|
||||||
|
const WorkerPlugin = require("worker-plugin");
|
||||||
const paths = require("./paths.js");
|
const paths = require("./paths.js");
|
||||||
const env = require("./env.js");
|
const env = require("./env.js");
|
||||||
const { babelLoaderConfig } = require("./babel.js");
|
const { babelLoaderConfig } = require("./babel.js");
|
||||||
|
@ -51,6 +52,7 @@ const createWebpackConfig = ({
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
|
new WorkerPlugin(),
|
||||||
new ManifestPlugin(),
|
new ManifestPlugin(),
|
||||||
new webpack.DefinePlugin({
|
new webpack.DefinePlugin({
|
||||||
__DEV__: !isProdBuild,
|
__DEV__: !isProdBuild,
|
||||||
|
@ -105,7 +107,7 @@ const createWebpackConfig = ({
|
||||||
latestBuild ? "frontend_latest" : "frontend_es5"
|
latestBuild ? "frontend_latest" : "frontend_es5"
|
||||||
),
|
),
|
||||||
publicPath: latestBuild ? "/frontend_latest/" : "/frontend_es5/",
|
publicPath: latestBuild ? "/frontend_latest/" : "/frontend_es5/",
|
||||||
// For workerize loader
|
// To silence warning in worker plugin
|
||||||
globalObject: "self",
|
globalObject: "self",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -86,6 +86,7 @@
|
||||||
"chart.js": "~2.8.0",
|
"chart.js": "~2.8.0",
|
||||||
"chartjs-chart-timeline": "^0.3.0",
|
"chartjs-chart-timeline": "^0.3.0",
|
||||||
"codemirror": "^5.49.0",
|
"codemirror": "^5.49.0",
|
||||||
|
"comlink": "^4.3.0",
|
||||||
"cpx": "^1.5.0",
|
"cpx": "^1.5.0",
|
||||||
"deep-clone-simple": "^1.1.1",
|
"deep-clone-simple": "^1.1.1",
|
||||||
"deep-freeze": "^0.0.1",
|
"deep-freeze": "^0.0.1",
|
||||||
|
@ -108,6 +109,7 @@
|
||||||
"memoize-one": "^5.0.2",
|
"memoize-one": "^5.0.2",
|
||||||
"moment": "^2.24.0",
|
"moment": "^2.24.0",
|
||||||
"node-vibrant": "^3.1.5",
|
"node-vibrant": "^3.1.5",
|
||||||
|
"proxy-polyfill": "^0.3.1",
|
||||||
"regenerator-runtime": "^0.13.2",
|
"regenerator-runtime": "^0.13.2",
|
||||||
"resize-observer": "^1.0.0",
|
"resize-observer": "^1.0.0",
|
||||||
"roboto-fontface": "^0.10.0",
|
"roboto-fontface": "^0.10.0",
|
||||||
|
@ -195,7 +197,7 @@
|
||||||
"webpack-dev-server": "^3.10.3",
|
"webpack-dev-server": "^3.10.3",
|
||||||
"webpack-manifest-plugin": "^2.0.4",
|
"webpack-manifest-plugin": "^2.0.4",
|
||||||
"workbox-build": "^5.1.3",
|
"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": "Polymer fixed to 3.1 because 3.2 throws on logbook page",
|
||||||
"_comment_2": "Fix in https://github.com/Polymer/polymer/pull/5569",
|
"_comment_2": "Fix in https://github.com/Polymer/polymer/pull/5569",
|
||||||
|
|
|
@ -14,9 +14,6 @@ import { classMap } from "lit-html/directives/class-map";
|
||||||
import { ifDefined } from "lit-html/directives/if-defined";
|
import { ifDefined } from "lit-html/directives/if-defined";
|
||||||
import { styleMap } from "lit-html/directives/style-map";
|
import { styleMap } from "lit-html/directives/style-map";
|
||||||
import { scroll } from "lit-virtualizer";
|
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 { fireEvent } from "../../common/dom/fire_event";
|
||||||
import "../../common/search/search-input";
|
import "../../common/search/search-input";
|
||||||
import { debounce } from "../../common/util/debounce";
|
import { debounce } from "../../common/util/debounce";
|
||||||
|
@ -24,6 +21,7 @@ import { nextRender } from "../../common/util/render-status";
|
||||||
import "../ha-checkbox";
|
import "../ha-checkbox";
|
||||||
import type { HaCheckbox } from "../ha-checkbox";
|
import type { HaCheckbox } from "../ha-checkbox";
|
||||||
import "../ha-icon";
|
import "../ha-icon";
|
||||||
|
import { filterSortData } from "./sort-filter";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
// for fire event
|
// for fire event
|
||||||
|
@ -117,8 +115,6 @@ export class HaDataTable extends LitElement {
|
||||||
|
|
||||||
private curRequest = 0;
|
private curRequest = 0;
|
||||||
|
|
||||||
private _worker: any | undefined;
|
|
||||||
|
|
||||||
private _debounceSearch = debounce(
|
private _debounceSearch = debounce(
|
||||||
(value: string) => {
|
(value: string) => {
|
||||||
this._filter = value;
|
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) {
|
protected updated(properties: PropertyValues) {
|
||||||
super.updated(properties);
|
super.updated(properties);
|
||||||
|
|
||||||
|
@ -383,7 +374,7 @@ export class HaDataTable extends LitElement {
|
||||||
this.curRequest++;
|
this.curRequest++;
|
||||||
const curRequest = this.curRequest;
|
const curRequest = this.curRequest;
|
||||||
|
|
||||||
const filterProm = this._worker.filterSortData(
|
const filterProm = filterSortData(
|
||||||
this.data,
|
this.data,
|
||||||
this._sortColumns,
|
this._sortColumns,
|
||||||
this._filter,
|
this._filter,
|
||||||
|
|
|
@ -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
|
||||||
|
);
|
||||||
|
};
|
|
@ -1,57 +1,34 @@
|
||||||
import memoizeOne from "memoize-one";
|
// To use comlink under ES5
|
||||||
// eslint-disable-next-line import/no-cycle
|
import "proxy-polyfill";
|
||||||
import {
|
import { expose } from "comlink";
|
||||||
DataTableColumnContainer,
|
import type {
|
||||||
DataTableColumnData,
|
DataTableSortColumnData,
|
||||||
DataTableRowData,
|
DataTableRowData,
|
||||||
SortingDirection,
|
SortingDirection,
|
||||||
|
HaDataTable,
|
||||||
} from "./ha-data-table";
|
} from "./ha-data-table";
|
||||||
|
|
||||||
export const filterSortData = memoizeOne(
|
type SortableColumnContainer = HaDataTable["_sortColumns"];
|
||||||
async (
|
|
||||||
data: DataTableRowData[],
|
|
||||||
columns: DataTableColumnContainer,
|
|
||||||
filter: string,
|
|
||||||
direction: SortingDirection,
|
|
||||||
sortColumn?: string
|
|
||||||
) =>
|
|
||||||
sortColumn
|
|
||||||
? _memSortData(
|
|
||||||
await _memFilterData(data, columns, filter),
|
|
||||||
columns,
|
|
||||||
direction,
|
|
||||||
sortColumn
|
|
||||||
)
|
|
||||||
: _memFilterData(data, columns, filter)
|
|
||||||
);
|
|
||||||
|
|
||||||
const _memFilterData = memoizeOne(
|
const filterSortData = (
|
||||||
async (
|
|
||||||
data: DataTableRowData[],
|
|
||||||
columns: DataTableColumnContainer,
|
|
||||||
filter: string
|
|
||||||
) => {
|
|
||||||
if (!filter) {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
return filterData(data, columns, filter.toUpperCase());
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const _memSortData = memoizeOne(
|
|
||||||
(
|
|
||||||
data: DataTableRowData[],
|
|
||||||
columns: DataTableColumnContainer,
|
|
||||||
direction: SortingDirection,
|
|
||||||
sortColumn: string
|
|
||||||
) => {
|
|
||||||
return sortData(data, columns[sortColumn], direction, sortColumn);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
export const filterData = (
|
|
||||||
data: DataTableRowData[],
|
data: DataTableRowData[],
|
||||||
columns: DataTableColumnContainer,
|
columns: SortableColumnContainer,
|
||||||
|
filter: string,
|
||||||
|
direction: SortingDirection,
|
||||||
|
sortColumn?: string
|
||||||
|
) => {
|
||||||
|
const filteredData = filter ? filterData(data, columns, filter) : data;
|
||||||
|
|
||||||
|
if (!sortColumn) {
|
||||||
|
return filteredData;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sortData(filteredData, columns, direction, sortColumn);
|
||||||
|
};
|
||||||
|
|
||||||
|
const filterData = (
|
||||||
|
data: DataTableRowData[],
|
||||||
|
columns: SortableColumnContainer,
|
||||||
filter: string
|
filter: string
|
||||||
) =>
|
) =>
|
||||||
data.filter((row) => {
|
data.filter((row) => {
|
||||||
|
@ -70,9 +47,9 @@ export const filterData = (
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
export const sortData = (
|
const sortData = (
|
||||||
data: DataTableRowData[],
|
data: DataTableRowData[],
|
||||||
column: DataTableColumnData,
|
column: DataTableSortColumnData,
|
||||||
direction: SortingDirection,
|
direction: SortingDirection,
|
||||||
sortColumn: string
|
sortColumn: string
|
||||||
) =>
|
) =>
|
||||||
|
@ -105,3 +82,10 @@ export const sortData = (
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Export for types
|
||||||
|
export const api = {
|
||||||
|
filterSortData,
|
||||||
|
};
|
||||||
|
|
||||||
|
expose(api);
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
import { customElement, property, UpdatingElement } from "lit-element";
|
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";
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
|
import { renderMarkdown } from "../resources/render-markdown";
|
||||||
let worker: any | undefined;
|
|
||||||
|
|
||||||
@customElement("ha-markdown")
|
@customElement("ha-markdown")
|
||||||
class HaMarkdown extends UpdatingElement {
|
class HaMarkdown extends UpdatingElement {
|
||||||
|
@ -16,16 +12,11 @@ class HaMarkdown extends UpdatingElement {
|
||||||
|
|
||||||
protected update(changedProps) {
|
protected update(changedProps) {
|
||||||
super.update(changedProps);
|
super.update(changedProps);
|
||||||
|
|
||||||
if (!worker) {
|
|
||||||
worker = markdownWorker();
|
|
||||||
}
|
|
||||||
|
|
||||||
this._render();
|
this._render();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _render() {
|
private async _render() {
|
||||||
this.innerHTML = await worker.renderMarkdown(
|
this.innerHTML = await renderMarkdown(
|
||||||
this.content,
|
this.content,
|
||||||
{
|
{
|
||||||
breaks: this.breaks,
|
breaks: this.breaks,
|
||||||
|
|
|
@ -2,6 +2,8 @@ import objAssign from "es6-object-assign";
|
||||||
import "mdn-polyfills/Array.prototype.includes";
|
import "mdn-polyfills/Array.prototype.includes";
|
||||||
import "regenerator-runtime/runtime";
|
import "regenerator-runtime/runtime";
|
||||||
import "unfetch/polyfill";
|
import "unfetch/polyfill";
|
||||||
|
// To use comlink under ES5
|
||||||
|
import "proxy-polyfill";
|
||||||
|
|
||||||
objAssign.polyfill();
|
objAssign.polyfill();
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
// To use comlink under ES5
|
||||||
|
import "proxy-polyfill";
|
||||||
|
import { expose } from "comlink";
|
||||||
import marked from "marked";
|
import marked from "marked";
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import filterXSS from "xss";
|
import filterXSS from "xss";
|
||||||
|
@ -9,14 +12,14 @@ interface WhiteList {
|
||||||
let whiteListNormal: WhiteList | undefined;
|
let whiteListNormal: WhiteList | undefined;
|
||||||
let whiteListSvg: WhiteList | undefined;
|
let whiteListSvg: WhiteList | undefined;
|
||||||
|
|
||||||
export const renderMarkdown = (
|
const renderMarkdown = (
|
||||||
content: string,
|
content: string,
|
||||||
markedOptions: object,
|
markedOptions: object,
|
||||||
hassOptions: {
|
hassOptions: {
|
||||||
// Do not allow SVG on untrusted content, it allows XSS.
|
// Do not allow SVG on untrusted content, it allows XSS.
|
||||||
allowSvg?: boolean;
|
allowSvg?: boolean;
|
||||||
} = {}
|
} = {}
|
||||||
) => {
|
): string => {
|
||||||
if (!whiteListNormal) {
|
if (!whiteListNormal) {
|
||||||
whiteListNormal = {
|
whiteListNormal = {
|
||||||
...filterXSS.whiteList,
|
...filterXSS.whiteList,
|
||||||
|
@ -45,3 +48,10 @@ export const renderMarkdown = (
|
||||||
whiteList,
|
whiteList,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Export for types
|
||||||
|
export const api = {
|
||||||
|
renderMarkdown,
|
||||||
|
};
|
||||||
|
|
||||||
|
expose(api);
|
||||||
|
|
|
@ -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);
|
||||||
|
};
|
20
yarn.lock
20
yarn.lock
|
@ -5691,6 +5691,11 @@ combined-stream@^1.0.6, combined-stream@~1.0.6:
|
||||||
dependencies:
|
dependencies:
|
||||||
delayed-stream "~1.0.0"
|
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:
|
command-line-args@^5.0.2:
|
||||||
version "5.1.0"
|
version "5.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.1.0.tgz#632d3d3df35c8f0cc4365e442a3fd6d63b65621b"
|
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"
|
forwarded "~0.1.2"
|
||||||
ipaddr.js "1.9.0"
|
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:
|
prr@~1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
|
resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
|
||||||
|
@ -15517,12 +15527,12 @@ worker-farm@^1.7.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
errno "~0.1.7"
|
errno "~0.1.7"
|
||||||
|
|
||||||
workerize-loader@^1.1.0:
|
worker-plugin@^4.0.3:
|
||||||
version "1.1.0"
|
version "4.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/workerize-loader/-/workerize-loader-1.1.0.tgz#d3a634390dcb685cc1ee292cd1fffeef0a646044"
|
resolved "https://registry.yarnpkg.com/worker-plugin/-/worker-plugin-4.0.3.tgz#7c42e600d5931ad154d3d5f187a32446df64db0f"
|
||||||
integrity sha512-cU2jPVE3AzzVxOonBe9lCCO//qwE9s/K4a9njFVRLueznzNDNND5vGHVorGuzK6xvamdDOZ9+g7CPIc7QKzucQ==
|
integrity sha512-7hFDYWiKcE3yHZvemsoM9lZis/PzurHAEX1ej8PLCu818Rt6QqUAiDdxHPCKZctzmhqzPpcFSgvMCiPbtooqAg==
|
||||||
dependencies:
|
dependencies:
|
||||||
loader-utils "^1.2.3"
|
loader-utils "^1.1.0"
|
||||||
|
|
||||||
wrap-ansi@^2.0.0:
|
wrap-ansi@^2.0.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
|
|
Loading…
Reference in New Issue