From ba2ebf0b6cd075bcf92542bb5ef7d3dc42c9bd06 Mon Sep 17 00:00:00 2001 From: Andrew Stein Date: Sun, 12 Nov 2023 02:02:39 -0500 Subject: [PATCH] Self-extracting wasm wrapper --- cpp/perspective/build.js | 25 +- cpp/perspective/package.json | 3 - .../src/include/perspective/scalar.h | 86 ++--- packages/perspective/package.json | 1 - .../perspective/src/js/perspective.browser.js | 51 +-- packages/perspective/src/js/perspective.js | 32 +- .../perspective/src/js/perspective.node.js | 55 +-- rust/perspective-viewer/Cargo.lock | 352 ++++++++++++------ rust/perspective-viewer/Cargo.toml | 10 +- rust/perspective-viewer/package.json | 3 +- rust/perspective-viewer/src/rust/lib.rs | 64 ++-- .../src/rust/utils/console_logger.rs | 35 +- rust/perspective-viewer/src/ts/init.ts | 95 ++--- .../tasks/bootstrap-runtime/Cargo.toml | 28 ++ .../tasks/bootstrap-runtime/lib.rs | 60 +++ .../tasks/bootstrap/Cargo.toml | 27 ++ .../tasks/bootstrap/main.rs | 79 ++++ .../tasks/bundle/Cargo.toml | 2 +- rust/perspective-viewer/tasks/bundle/main.rs | 40 +- tools/perspective-scripts/sh_perspective.mjs | 2 + yarn.lock | 5 - 21 files changed, 644 insertions(+), 411 deletions(-) create mode 100644 rust/perspective-viewer/tasks/bootstrap-runtime/Cargo.toml create mode 100644 rust/perspective-viewer/tasks/bootstrap-runtime/lib.rs create mode 100644 rust/perspective-viewer/tasks/bootstrap/Cargo.toml create mode 100644 rust/perspective-viewer/tasks/bootstrap/main.rs diff --git a/cpp/perspective/build.js b/cpp/perspective/build.js index 3600f12323..b37e00575a 100644 --- a/cpp/perspective/build.js +++ b/cpp/perspective/build.js @@ -13,15 +13,20 @@ const { execSync } = require("child_process"); const os = require("os"); const path = require("path"); -const fflate = require("fflate"); -const fs = require("fs"); const stdio = "inherit"; -const env = process.PSP_DEBUG ? "debug" : "release"; +const env = process.env.PSP_DEBUG ? "debug" : "release"; const cwd = path.join(process.cwd(), "dist", env); delete process.env.NODE; +function bootstrap(file) { + execSync(`cargo run -p perspective-bootstrap -- ${file}`, { + cwd: path.join(process.cwd(), "..", "..", "rust", "perspective-viewer"), + stdio, + }); +} + try { execSync(`mkdirp ${cwd}`, { stdio }); process.env.CLICOLOR_FORCE = 1; @@ -29,20 +34,18 @@ try { cwd, stdio, }); + execSync(`emmake make -j${process.env.PSP_NUM_CPUS || os.cpus().length}`, { cwd, stdio, }); + execSync(`cpy web/**/* ../web`, { cwd, stdio }); execSync(`cpy node/**/* ../node`, { cwd, stdio }); - - const wasm = fs.readFileSync("dist/web/perspective.cpp.wasm"); - const compressed = fflate.compressSync(wasm); - fs.writeFileSync("dist/web/perspective.cpp.wasm", compressed); - - const wasm2 = fs.readFileSync("dist/node/perspective.cpp.wasm"); - const compressed2 = fflate.compressSync(wasm2); - fs.writeFileSync("dist/node/perspective.cpp.wasm", compressed2); + if (!process.env.PSP_DEBUG) { + bootstrap(`../../cpp/perspective/dist/web/perspective.cpp.wasm`); + bootstrap(`../../cpp/perspective/dist/node/perspective.cpp.wasm`); + } } catch (e) { console.error(e); process.exit(1); diff --git a/cpp/perspective/package.json b/cpp/perspective/package.json index 9396ac4351..c7a1b7bbba 100644 --- a/cpp/perspective/package.json +++ b/cpp/perspective/package.json @@ -12,8 +12,5 @@ "scripts": { "build": "node ../../tools/perspective-scripts/run_emsdk.mjs node ./build.js", "clean": "rimraf dist" - }, - "devDependencies": { - "fflate": "^0.7.4" } } diff --git a/cpp/perspective/src/include/perspective/scalar.h b/cpp/perspective/src/include/perspective/scalar.h index e024035b0a..664c73e59a 100644 --- a/cpp/perspective/src/include/perspective/scalar.h +++ b/cpp/perspective/src/include/perspective/scalar.h @@ -200,49 +200,49 @@ struct PERSPECTIVE_EXPORT t_tscalar { bool m_inplace; }; -inline t_tscalar operator"" _ts(long double v) { - t_tscalar rv; - double tmp = v; - rv.set(tmp); - return rv; -} - -inline t_tscalar operator"" _ts(unsigned long long int v) { - t_tscalar rv; - std::int64_t tmp = v; - rv.set(tmp); - return rv; -} - -inline t_tscalar operator"" _ts(const char* v, std::size_t len) { - t_tscalar rv; - rv.set(v); - return rv; -} - -inline t_tscalar operator"" _ns(long double v) { - t_tscalar rv; - rv.m_data.m_uint64 = 0; - rv.m_type = DTYPE_FLOAT64; - rv.m_status = STATUS_INVALID; - return rv; -} - -inline t_tscalar operator"" _ns(unsigned long long int v) { - t_tscalar rv; - rv.m_data.m_uint64 = 0; - rv.m_type = DTYPE_INT64; - rv.m_status = STATUS_INVALID; - return rv; -} - -inline t_tscalar operator"" _ns(const char* v, std::size_t len) { - t_tscalar rv; - rv.m_data.m_uint64 = 0; - rv.m_type = DTYPE_STR; - rv.m_status = STATUS_INVALID; - return rv; -} +// inline t_tscalar operator"" _ts(long double v) { +// t_tscalar rv; +// double tmp = v; +// rv.set(tmp); +// return rv; +// } + +// inline t_tscalar operator"" _ts(unsigned long long int v) { +// t_tscalar rv; +// std::int64_t tmp = v; +// rv.set(tmp); +// return rv; +// } + +// inline t_tscalar operator"" _ts(const char* v, std::size_t len) { +// t_tscalar rv; +// rv.set(v); +// return rv; +// } + +// inline t_tscalar operator"" _ns(long double v) { +// t_tscalar rv; +// rv.m_data.m_uint64 = 0; +// rv.m_type = DTYPE_FLOAT64; +// rv.m_status = STATUS_INVALID; +// return rv; +// } + +// inline t_tscalar operator"" _ns(unsigned long long int v) { +// t_tscalar rv; +// rv.m_data.m_uint64 = 0; +// rv.m_type = DTYPE_INT64; +// rv.m_status = STATUS_INVALID; +// return rv; +// } + +// inline t_tscalar operator"" _ns(const char* v, std::size_t len) { +// t_tscalar rv; +// rv.m_data.m_uint64 = 0; +// rv.m_type = DTYPE_STR; +// rv.m_status = STATUS_INVALID; +// return rv; +// } PERSPECTIVE_EXPORT t_tscalar mknone(); PERSPECTIVE_EXPORT t_tscalar mknull(t_dtype dtype); diff --git a/packages/perspective/package.json b/packages/perspective/package.json index 7fbfa1eb5e..49fc978bee 100644 --- a/packages/perspective/package.json +++ b/packages/perspective/package.json @@ -42,7 +42,6 @@ "clean": "rimraf dist" }, "dependencies": { - "fflate": "^0.7.4", "stoppable": "1.1.0", "ws": "^6.1.2" }, diff --git a/packages/perspective/src/js/perspective.browser.js b/packages/perspective/src/js/perspective.browser.js index 3ae3d46d02..3f29c6ef93 100644 --- a/packages/perspective/src/js/perspective.browser.js +++ b/packages/perspective/src/js/perspective.browser.js @@ -14,19 +14,13 @@ import * as defaults from "./config/constants.js"; import { get_config, get_type_config as _get_type_config } from "./config"; import { Client } from "./api/client.js"; import { WebSocketClient } from "./websocket/client"; - import { override_config } from "./config/index.js"; -import { Decompress } from "fflate"; import wasm_worker from "../../src/js/perspective.worker.js"; import wasm from "../../dist/pkg/web/perspective.cpp.wasm"; let IS_INLINE = false; -function is_gzip(buffer) { - return new Uint32Array(buffer.slice(0, 4))[0] == 559903; -} - /** * Singleton WASM file download cache. */ @@ -41,59 +35,22 @@ const _override = /* @__PURE__ */ (function () { async wasm() { let _wasm = await wasm; - - let parts = []; - let length = 0; - const decompressor = new Decompress((chunk) => { - if (chunk) { - length += chunk.byteLength; - parts.push(chunk); - } - }); - if (_wasm instanceof ArrayBuffer && !_wasm.buffer) { _wasm = new Uint8Array(_wasm); } if (_wasm.buffer && _wasm.buffer instanceof ArrayBuffer) { IS_INLINE = true; - if (is_gzip(_wasm.buffer)) { - decompressor.push(_wasm, true); - } else { - length = _wasm.byteLength; - parts = [_wasm]; - } + length = _wasm.byteLength; + this._wasm = _wasm; } else if (_wasm instanceof ArrayBuffer) { length = _wasm.byteLength; - parts = [new Uint8Array(_wasm)]; + this._wasm = new Uint8Array(_wasm); } else { const resp = await fetch(_wasm); - const reader = resp.body.getReader(); - let state = 0; - while (true) { - const { value, done } = await reader.read(); - if (done) break; - if ( - (state === 0 && is_gzip(value.buffer)) || - state === 1 - ) { - state = 1; - decompressor.push(value, done); - } else { - state = 2; - length += value.byteLength; - parts.push(value); - } - } + this._wasm = await resp.arrayBuffer(); } - let offset = 0; - const buffer = new Uint8Array(length); - for (const part of parts) { - buffer.set(part, offset); - offset += part.byteLength; - } - this._wasm = buffer.buffer; return this._wasm; } })(); diff --git a/packages/perspective/src/js/perspective.js b/packages/perspective/src/js/perspective.js index 6e1b14cdeb..989d065d95 100644 --- a/packages/perspective/src/js/perspective.js +++ b/packages/perspective/src/js/perspective.js @@ -2195,20 +2195,24 @@ export default function (Module) { * @param {ArrayBuffer} buffer an ArrayBuffer or Buffer containing the * Perspective WASM code */ - init(msg) { - if (typeof WebAssembly === "undefined") { - throw new Error("WebAssembly not supported"); - } else { - __MODULE__({ - wasmBinary: msg.buffer, - wasmJSMethod: "native-wasm", - locateFile: (x) => x, - }).then((mod) => { - __MODULE__ = mod; - __MODULE__.init(); - super.init(msg); - }); - } + async init(msg) { + let wasmBinary = msg.buffer; + try { + const mod = await WebAssembly.instantiate(wasmBinary); + const exports = mod.instance.exports; + const size = exports.size(); + const offset = exports.offset(); + const array = new Uint8Array(exports.memory.buffer); + wasmBinary = array.slice(offset, offset + size); + } catch {} + __MODULE__ = await __MODULE__({ + wasmBinary, + wasmJSMethod: "native-wasm", + locateFile: (x) => x, + }); + + __MODULE__.init(); + super.init(msg); } } diff --git a/packages/perspective/src/js/perspective.node.js b/packages/perspective/src/js/perspective.node.js index d4e0ed0e68..d8aa3e484b 100644 --- a/packages/perspective/src/js/perspective.node.js +++ b/packages/perspective/src/js/perspective.node.js @@ -24,52 +24,33 @@ const http = require("http"); const WebSocket = require("ws"); const process = require("process"); const path = require("path"); -const { Decompress } = require("fflate"); const load_perspective = require("../../dist/pkg/node/perspective.cpp.js"); const LOCAL_PATH = path.join(process.cwd(), "node_modules"); const buffer = require("../../dist/pkg/node/perspective.cpp.wasm").default; -function deflate(buffer) { - let parts = []; - let length = 0; - const decompressor = new Decompress((chunk) => { - if (chunk) { - length += chunk.byteLength; - parts.push(chunk); - } - }); - - decompressor.push(buffer, true); - let offset = 0; - const buffer2 = new Uint8Array(length); - for (const part of parts) { - buffer2.set(part, offset); - offset += part.byteLength; - } - - return buffer2.buffer; -} const SYNC_SERVER = new (class extends Server { init(msg) { - let done; - this._loaded_promise = new Promise((x) => { - done = x; - }); - buffer - .then((buffer) => { - return load_perspective({ - wasmBinary: deflate(buffer), - wasmJSMethod: "native-wasm", - }); - }) - .then((core) => { - core.init(); - this.perspective = perspective(core); - super.init(msg); - done(); + this._loaded_promise = (async () => { + let wasmBinary = await buffer; + try { + const mod = await WebAssembly.instantiate(wasmBinary); + const exports = mod.instance.exports; + const size = exports.size(); + const offset = exports.offset(); + const array = new Uint8Array(exports.memory.buffer); + wasmBinary = array.slice(offset, offset + size); + } catch {} + const core = await load_perspective({ + wasmBinary, + wasmJSMethod: "native-wasm", }); + + core.init(); + this.perspective = perspective(core); + super.init(msg); + })(); } post(msg) { diff --git a/rust/perspective-viewer/Cargo.lock b/rust/perspective-viewer/Cargo.lock index 0a24865fa5..fb2e8234f1 100644 --- a/rust/perspective-viewer/Cargo.lock +++ b/rust/perspective-viewer/Cargo.lock @@ -41,6 +41,54 @@ dependencies = [ "libc", ] +[[package]] +name = "anstream" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" + +[[package]] +name = "anstyle-parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +dependencies = [ + "anstyle", + "windows-sys", +] + [[package]] name = "anyhow" version = "1.0.75" @@ -70,13 +118,13 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.73" +version = "0.1.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" +checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2 1.0.69", "quote 1.0.33", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -133,9 +181,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "boolinator" @@ -191,6 +239,46 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "clap" +version = "4.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +dependencies = [ + "heck 0.4.1", + "proc-macro2 1.0.69", + "quote 1.0.33", + "syn 2.0.39", +] + +[[package]] +name = "clap_lex" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" + [[package]] name = "codespan-reporting" version = "0.11.1" @@ -201,6 +289,12 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + [[package]] name = "console_error_panic_hook" version = "0.1.7" @@ -228,9 +322,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.109" +version = "1.0.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c390c123d671cc547244943ecad81bdaab756c6ea332d9ca9c1f48d952a24895" +checksum = "7129e341034ecb940c9072817cd9007974ea696844fc4dd582dc1653a7fbe2e8" dependencies = [ "cc", "cxxbridge-flags", @@ -240,9 +334,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.109" +version = "1.0.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00d3d3ac9ffb900304edf51ca719187c779f4001bb544f26c4511d621de905cf" +checksum = "a2a24f3f5f8eed71936f21e570436f024f5c2e25628f7496aa7ccd03b90109d5" dependencies = [ "cc", "codespan-reporting", @@ -250,24 +344,24 @@ dependencies = [ "proc-macro2 1.0.69", "quote 1.0.33", "scratch", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] name = "cxxbridge-flags" -version = "1.0.109" +version = "1.0.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94415827ecfea0f0c74c8cad7d1a86ddb3f05354d6a6ddeda0adee5e875d2939" +checksum = "06fdd177fc61050d63f67f5bd6351fac6ab5526694ea8e359cd9cd3b75857f44" [[package]] name = "cxxbridge-macro" -version = "1.0.109" +version = "1.0.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33dbbe9f5621c9247f97ec14213b04f350bff4b6cebefe834c60055db266ecf" +checksum = "587663dd5fb3d10932c8aecfe7c844db1bcf0aee93eeab08fac13dc1212c2e7f" dependencies = [ "proc-macro2 1.0.69", "quote 1.0.33", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -307,9 +401,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" +checksum = "7c18ee0ed65a5f1f81cac6b1d213b69c35fa47d4252ad41f1486dbd8226fe36e" dependencies = [ "libc", "windows-sys", @@ -329,7 +423,7 @@ checksum = "311a6d2f1f9d60bff73d2c78a0af97ed27f79672f15c238192a5bbb64db56d00" dependencies = [ "proc-macro2 1.0.69", "quote 1.0.33", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -380,9 +474,9 @@ checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" [[package]] name = "futures" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" dependencies = [ "futures-channel", "futures-core", @@ -395,9 +489,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" dependencies = [ "futures-core", "futures-sink", @@ -405,15 +499,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" [[package]] name = "futures-executor" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" dependencies = [ "futures-core", "futures-task", @@ -422,38 +516,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" [[package]] name = "futures-macro" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2 1.0.69", "quote 1.0.33", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" dependencies = [ "futures-channel", "futures-core", @@ -469,9 +563,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" dependencies = [ "cfg-if", "js-sys", @@ -527,7 +621,7 @@ dependencies = [ "gloo-storage 0.3.0", "gloo-timers 0.3.0", "gloo-utils 0.2.0", - "gloo-worker 0.4.1", + "gloo-worker 0.4.0", ] [[package]] @@ -646,7 +740,7 @@ dependencies = [ "gloo-events 0.2.0", "gloo-utils 0.2.0", "serde", - "serde-wasm-bindgen 0.6.0", + "serde-wasm-bindgen 0.6.1", "serde_urlencoded", "thiserror", "wasm-bindgen", @@ -810,9 +904,9 @@ dependencies = [ [[package]] name = "gloo-worker" -version = "0.4.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cbd4c35cc3a2b1fb792318acc06bd514193f6d058173da5cdbcdabe6514303" +checksum = "76495d3dd87de51da268fa3a593da118ab43eb7f8809e17eb38d3319b424e400" dependencies = [ "bincode", "futures", @@ -836,14 +930,14 @@ dependencies = [ "proc-macro-crate", "proc-macro2 1.0.69", "quote 1.0.33", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] name = "hashbrown" -version = "0.14.1" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12" +checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" [[package]] name = "heck" @@ -868,9 +962,9 @@ checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] name = "http" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "f95b9abcae896730d42b78e09c155ed4ddf82c07b4de772c64aee5b2d8b7c150" dependencies = [ "bytes", "fnv", @@ -879,16 +973,16 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.57" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows", + "windows-core", ] [[package]] @@ -908,18 +1002,29 @@ checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" [[package]] name = "implicit-clone" -version = "0.4.1" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af3d77000817fd9e7db159e8d52ed9b5941a2cdbfbdc8ca646e59887ae2b2dd1" +checksum = "16c5448a864f9abf124ef8bf2a3cc37eb9fd99fe2e804a8b3235d7357bca2c25" dependencies = [ + "implicit-clone-derive", "indexmap", ] +[[package]] +name = "implicit-clone-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9311685eb9a34808bbb0608ad2fcab9ae216266beca5848613e95553ac914e3b" +dependencies = [ + "quote 1.0.33", + "syn 2.0.39", +] + [[package]] name = "indexmap" -version = "2.0.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ "equivalent", "hashbrown", @@ -1004,9 +1109,9 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.149" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] name = "link-cplusplus" @@ -1019,9 +1124,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" +checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" [[package]] name = "log" @@ -1187,7 +1292,7 @@ dependencies = [ "procss", "rmp-serde", "serde", - "serde-wasm-bindgen 0.6.0", + "serde-wasm-bindgen 0.6.1", "serde_json", "tracing", "tracing-subscriber", @@ -1199,10 +1304,25 @@ dependencies = [ ] [[package]] -name = "perspective-bundle" +name = "perspective-bootstrap" version = "2.6.1" dependencies = [ + "clap", "flate2", + "wasm-opt", +] + +[[package]] +name = "perspective-bootstrap-runtime" +version = "2.6.1" +dependencies = [ + "flate2", +] + +[[package]] +name = "perspective-bundle" +version = "2.6.1" +dependencies = [ "wasm-bindgen-cli-support", "wasm-opt", ] @@ -1224,7 +1344,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2 1.0.69", "quote 1.0.33", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -1287,7 +1407,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" dependencies = [ "proc-macro2 1.0.69", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -1395,18 +1515,18 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.3.5" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "regex" -version = "1.10.1" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaac441002f822bc9705a681810a4dd2963094b9ca0ddc41cb963a4c189189ea" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", @@ -1416,9 +1536,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5011c7e263a695dc8ca064cddb722af1be54e517a280b12a5356f98366899e5d" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", @@ -1461,11 +1581,11 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.38.19" +version = "0.38.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "745ecfa778e66b2b63c88a61cb36e0eea109e803b0b86bf9879fbc77c70e86ed" +checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "errno", "libc", "linux-raw-sys", @@ -1504,9 +1624,9 @@ checksum = "a3cf7c11c38cb994f3d40e8a8cde3bbd1f72a435e4c49e85d6553d8312306152" [[package]] name = "serde" -version = "1.0.189" +version = "1.0.192" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537" +checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" dependencies = [ "serde_derive", ] @@ -1535,9 +1655,9 @@ dependencies = [ [[package]] name = "serde-wasm-bindgen" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30c9933e5689bd420dc6c87b7a1835701810cbc10cd86a26e4da45b73e6b1d78" +checksum = "17ba92964781421b6cef36bf0d7da26d201e96d84e1b10e7ae6ed416e516906d" dependencies = [ "js-sys", "serde", @@ -1546,20 +1666,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.189" +version = "1.0.192" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5" +checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" dependencies = [ "proc-macro2 1.0.69", "quote 1.0.33", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] name = "serde_json" -version = "1.0.107" +version = "1.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ "itoa", "ryu", @@ -1598,9 +1718,15 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.1" +version = "1.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" + +[[package]] +name = "strsim" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "strum" @@ -1645,9 +1771,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.38" +version = "2.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" dependencies = [ "proc-macro2 1.0.69", "quote 1.0.33", @@ -1656,9 +1782,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.8.0" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" dependencies = [ "cfg-if", "fastrand", @@ -1684,22 +1810,22 @@ checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" [[package]] name = "thiserror" -version = "1.0.49" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.49" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2 1.0.69", "quote 1.0.33", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -1714,9 +1840,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.33.0" +version = "1.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" +checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" dependencies = [ "backtrace", "pin-project-lite", @@ -1735,9 +1861,9 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" [[package]] name = "toml_edit" @@ -1752,9 +1878,9 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.39" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee2ef2af84856a50c1d430afce2fdded0a4ec7eda868db86409b4543df0797f9" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "pin-project-lite", "tracing-attributes", @@ -1769,7 +1895,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2 1.0.69", "quote 1.0.33", - "syn 2.0.38", + "syn 2.0.39", ] [[package]] @@ -1784,12 +1910,12 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +checksum = "f751112709b4e791d8ce53e32c4ed2d353565a795ce84da2285393f41557bdf2" dependencies = [ - "lazy_static", "log", + "once_cell", "tracing-core", ] @@ -1831,6 +1957,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "valuable" version = "0.1.0" @@ -1898,7 +2030,7 @@ dependencies = [ "once_cell", "proc-macro2 1.0.69", "quote 1.0.33", - "syn 2.0.38", + "syn 2.0.39", "wasm-bindgen-shared", ] @@ -1964,7 +2096,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2 1.0.69", "quote 1.0.33", - "syn 2.0.38", + "syn 2.0.39", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2130,10 +2262,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows" -version = "0.48.0" +name = "windows-core" +version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" dependencies = [ "windows-targets", ] @@ -2206,9 +2338,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winnow" -version = "0.5.17" +version = "0.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3b801d0e0a6726477cc207f60162da452f3a95adb368399bef20a946e06f65c" +checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b" dependencies = [ "memchr", ] @@ -2250,5 +2382,5 @@ dependencies = [ "proc-macro-error", "proc-macro2 1.0.69", "quote 1.0.33", - "syn 2.0.38", + "syn 2.0.39", ] diff --git a/rust/perspective-viewer/Cargo.toml b/rust/perspective-viewer/Cargo.toml index bf3ce877d9..d0b0d831fe 100644 --- a/rust/perspective-viewer/Cargo.toml +++ b/rust/perspective-viewer/Cargo.toml @@ -26,20 +26,16 @@ include = [ "src/**/*", "Cargo.toml", "package.json", - "tasks/xbuild/*", + "tasks/bundle/*", ] [workspace] -members = ["tasks/bundle"] +members = ["tasks/bundle", "tasks/bootstrap-runtime", "tasks/bootstrap"] [lib] crate-type = ["cdylib", "rlib"] path = "src/rust/lib.rs" -[features] -define_custom_elements_async = [] -default = [] - [profile.dev] panic = "abort" opt-level = "s" @@ -113,7 +109,7 @@ serde_json = { version = "1.0.107", features = ["raw_value"] } serde-wasm-bindgen = "0.6.0" # Async-aware logging that can be disabled at compile-time. -tracing = { version = ">=0.1.36", features = ["release_max_level_error"] } +tracing = { version = ">=0.1.36", features = ["release_max_level_off"] } tracing-subscriber = "0.3.15" # Browser API bindings diff --git a/rust/perspective-viewer/package.json b/rust/perspective-viewer/package.json index 16b704a131..f96f70a1dc 100644 --- a/rust/perspective-viewer/package.json +++ b/rust/perspective-viewer/package.json @@ -40,8 +40,7 @@ "access": "public" }, "dependencies": { - "@finos/perspective": "^2.6.1", - "fflate": "^0.7.4" + "@finos/perspective": "^2.6.1" }, "devDependencies": { "react": "^16.14.0", diff --git a/rust/perspective-viewer/src/rust/lib.rs b/rust/perspective-viewer/src/rust/lib.rs index 0a07f17d3c..941fb79cc1 100644 --- a/rust/perspective-viewer/src/rust/lib.rs +++ b/rust/perspective-viewer/src/rust/lib.rs @@ -39,11 +39,7 @@ pub mod utils; use utils::JsValueSerdeExt; use wasm_bindgen::prelude::*; -use crate::custom_elements::copy_dropdown::CopyDropDownMenuElement; -use crate::custom_elements::debug_plugin::PerspectiveDebugPluginElement; -use crate::custom_elements::export_dropdown::ExportDropDownMenuElement; -use crate::custom_elements::viewer::PerspectiveViewerElement; -use crate::utils::{define_web_component, ApiResult}; +use crate::utils::ApiResult; /// Register a plugin globally. #[wasm_bindgen(js_name = "registerPlugin")] @@ -52,6 +48,13 @@ pub fn register_plugin(name: &str) { PLUGIN_REGISTRY.register_plugin(name); } +/// Initialize process-wide state, must be called before any other methods +/// after WebAssembly compilation. +#[wasm_bindgen(js_name = "init")] +pub fn init() { + crate::utils::set_global_logging(); +} + /// Export all ExprTK commands, for use in generating documentation. #[wasm_bindgen(js_name = "getExprTKCommands")] pub fn get_exprtk_commands() -> ApiResult> { @@ -65,47 +68,24 @@ pub fn get_exprtk_commands() -> ApiResult> { /// Register this crate's Custom Elements in the browser's current session. /// This must occur before calling any public API methods on these Custom /// Elements from JavaScript, as the methods themselves won't be defined yet. -/// By default, this crate does not register `PerspectiveViewerElement` (as to -/// preserve backwards-compatible synchronous API). -#[cfg(not(test))] -#[cfg(not(feature = "define_custom_elements_async"))] -#[wasm_bindgen(js_name = "defineWebComponents")] -pub fn js_define_web_components() { - crate::utils::set_global_logging(); - define_web_components!("export * as psp from '../../perspective.js'"); - tracing::info!("Perspective initialized."); -} - -/// Register Web Components with the global registry, given a Perspective -/// module. This function shouldn't be called directly; instead, use the -/// `define_web_components!` macro to both call this method and hook the -/// wasm_bindgen module object. -pub fn bootstrap_web_components(psp: &JsValue) { - if cfg!(feature = "define_custom_elements_async") { - define_web_component::(psp); - define_web_component::(psp); - } - - define_web_component::(psp); - define_web_component::(psp); -} - +/// This macro is provided for bootstrapping the `perspectve` crate when used +/// as a dependency in another Rust crate; there is no need to call this +/// function for disting directly to JavaScript, as we recreate this logic +/// in TypeScript to make sure the custom element is defined before the +/// WebAssembly is asynchronously loaded. #[macro_export] macro_rules! define_web_components { - (@prelude $x:expr) => {{ - #[wasm_bindgen::prelude::wasm_bindgen(inline_js = $x)] + ($x:expr) => {{ + use wasm_bindgen::prelude::{wasm_bindge, JsValue}; + use $crate::custom_elements::viewer::PerspectiveViewerElement; + use $crate::utils::define_web_component; + + #[wasm_bindgen(inline_js = $x)] extern "C" { - #[wasm_bindgen::prelude::wasm_bindgen(js_name = "psp")] - pub static PSP: wasm_bindgen::prelude::JsValue; + #[wasm_bindgen(js_name = "psp")] + static PSP: JsValue; } - &PSP - }}; - (@custom_elements $psp:expr) => {{ - $crate::bootstrap_web_components($psp); - }}; - ($x:expr) => {{ - let psp = $crate::define_web_components!(@prelude $x); - $crate::define_web_components!(@custom_elements psp); + define_web_component::(PSP); }}; } diff --git a/rust/perspective-viewer/src/rust/utils/console_logger.rs b/rust/perspective-viewer/src/rust/utils/console_logger.rs index 883018b9f5..0f649cbd44 100644 --- a/rust/perspective-viewer/src/rust/utils/console_logger.rs +++ b/rust/perspective-viewer/src/rust/utils/console_logger.rs @@ -11,6 +11,7 @@ // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ use std::fmt::{Debug, Write}; +use std::sync::OnceLock; use tracing::field::{Field, Visit}; use tracing::Subscriber; @@ -185,16 +186,30 @@ impl LookupSpan<'a>> Layer for WasmLogger { /// `tracing::Subscriber`, so it should not be called when `perspective` is used /// as a library from a larger app; in this case the app itself should configure /// `tracing` explicitly. +/// +/// Why is this stubbed out for `--release` builds, you may ask? While `tracing` +/// has support for [compile-time log ellision](https://docs.rs/tracing/latest/tracing/level_filters/index.html) +/// (which is enabled), even at `"max_level_off"` there is a 80k binary +/// payload generated from `set_global_logging()` in wasm. As this module does +/// not currently use even `"error"` level logging in `--release` builds, +/// we stub this library out entirely to save bytes. +#[cfg(debug_assertions)] pub fn set_global_logging() { - use tracing_subscriber::layer::SubscriberExt; - let filter = tracing_subscriber::filter::filter_fn(|meta| { - meta.module_path() - .as_ref() - .map(|x| x.starts_with("perspective")) - .unwrap_or_default() + static INIT_LOGGING: OnceLock<()> = OnceLock::new(); + INIT_LOGGING.get_or_init(|| { + use tracing_subscriber::layer::SubscriberExt; + let filter = tracing_subscriber::filter::filter_fn(|meta| { + meta.module_path() + .as_ref() + .map(|x| x.starts_with("perspective")) + .unwrap_or_default() + }); + + let layer = WasmLogger::default().with_filter(filter); + let subscriber = tracing_subscriber::Registry::default().with(layer); + tracing::subscriber::set_global_default(subscriber).unwrap(); }); - - let layer = WasmLogger::default().with_filter(filter); - let subscriber = tracing_subscriber::Registry::default().with(layer); - tracing::subscriber::set_global_default(subscriber).unwrap(); } + +#[cfg(not(debug_assertions))] +pub fn set_global_logging() {} diff --git a/rust/perspective-viewer/src/ts/init.ts b/rust/perspective-viewer/src/ts/init.ts index 044dbf379a..b268263bcb 100644 --- a/rust/perspective-viewer/src/ts/init.ts +++ b/rust/perspective-viewer/src/ts/init.ts @@ -10,8 +10,9 @@ // ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃ // ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ -import { Decompress } from "fflate"; -import init_wasm, * as wasm_module from "../../dist/pkg/perspective.js"; +// import init_wasm, * as wasm_module from "../../dist/pkg/perspective_bootstrap.js"; +import * as wasm_module from "../../dist/pkg/perspective.js"; + import wasm from "../../dist/pkg/perspective_bg.wasm"; // There is no way to provide a default rejection handler within a promise and @@ -23,68 +24,46 @@ window.addEventListener("unhandledrejection", (event) => { } }); -function is_gzip(buffer) { - return new Uint32Array(buffer.slice(0, 4))[0] == 559903; -} +type Module = { + size(): number; + offset(): number; + memory: WebAssembly.Memory; +}; -async function load_wasm() { - // Perform a silly dance to deal with the different ways webpack and esbuild - // load binary - const compressed = (await wasm) as unknown; - - let parts: Uint8Array[] = []; - let length = 0; - const decompressor = new Decompress((chunk) => { - if (chunk) { - length += chunk.byteLength; - parts.push(chunk); - } - }); - - if (compressed instanceof URL || typeof compressed === "string") { - const resp = await fetch(compressed.toString()); - const reader = resp.body?.getReader(); - let state = 0; - if (reader !== undefined) { - while (true) { - const { value, done } = await reader.read(); - if (done || value === undefined) break; - if ((state === 0 && is_gzip(value?.buffer)) || state === 1) { - state = 1; - decompressor.push(value, done); - } else { - state = 2; - length += value.byteLength; - parts.push(value); - } - } - } - } else if (compressed instanceof Uint8Array) { - if (is_gzip(compressed.buffer)) { - decompressor.push(compressed, true); - } else { - length = compressed.byteLength; - parts = [compressed]; - } +async function compile(buff_or_url) { + if (buff_or_url instanceof URL) { + return await WebAssembly.instantiateStreaming(fetch(buff_or_url)); } else { - const array = new Uint8Array(compressed as ArrayBuffer); - if (is_gzip(compressed)) { - decompressor.push(array, true); - } else { - length = array.byteLength; - parts = [array]; - } + return await WebAssembly.instantiate(buff_or_url); } +} - let offset = 0; - const buffer = new Uint8Array(length); - for (const part of parts) { - buffer.set(part, offset); - offset += part.byteLength; +async function release_build(buff_or_url) { + const mod = await compile(buff_or_url); + const exports = mod.instance.exports as Module; + const size = exports.size(); + const offset = exports.offset(); + const array = new Uint8Array(exports.memory.buffer); + const uncompressed_wasm = array.slice(offset, offset + size); + await wasm_module.default(uncompressed_wasm); +} + +async function debug_build(buff_or_url) { + await wasm_module.default(buff_or_url); +} + +async function load_wasm() { + // Perform a silly dance to deal with the different ways webpack and esbuild + // load binary, as this may either be an `ArrayBuffer` or `URL` depening + // on whether `inline` option was specified to `perspective-esbuild-plugin`. + const buff_or_url = await wasm; + try { + await release_build(buff_or_url); + } catch { + await debug_build(buff_or_url); } - await init_wasm(buffer); - wasm_module.defineWebComponents(); + wasm_module.init(); return wasm_module; } diff --git a/rust/perspective-viewer/tasks/bootstrap-runtime/Cargo.toml b/rust/perspective-viewer/tasks/bootstrap-runtime/Cargo.toml new file mode 100644 index 0000000000..33ca1835df --- /dev/null +++ b/rust/perspective-viewer/tasks/bootstrap-runtime/Cargo.toml @@ -0,0 +1,28 @@ +# ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ +# ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃ +# ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃ +# ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃ +# ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃ +# ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫ +# ┃ Copyright (c) 2017, the Perspective Authors. ┃ +# ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃ +# ┃ This file is part of the Perspective library, distributed under the terms ┃ +# ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃ +# ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + +[package] +name = "perspective-bootstrap-runtime" +description = "A tiny runtime wrapper to create self-extracting wasm binaries" +version = "2.6.1" +edition = "2021" + +[lib] +crate-type = ["cdylib"] +path = "lib.rs" + +[dependencies] +flate2 = "1.0.28" + +[features] +env_target = [] +default_features = [] \ No newline at end of file diff --git a/rust/perspective-viewer/tasks/bootstrap-runtime/lib.rs b/rust/perspective-viewer/tasks/bootstrap-runtime/lib.rs new file mode 100644 index 0000000000..18f944b516 --- /dev/null +++ b/rust/perspective-viewer/tasks/bootstrap-runtime/lib.rs @@ -0,0 +1,60 @@ +// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ +// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃ +// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃ +// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃ +// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃ +// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫ +// ┃ Copyright (c) 2017, the Perspective Authors. ┃ +// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃ +// ┃ This file is part of the Perspective library, distributed under the terms ┃ +// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃ +// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + +//! `perspective-bootstrap` is a self-extracting `zlib` compressed binary. +//! The _best_ way to distribute Perspective's `.wasm` components is to +//! compress them on disk, then configure your web server to apply the +//! `Content-Encoding: gzip` header _without_ zipping the content, then use +//! the browser's `WebAssembly.instantiateStreaming()` to compile the result. +//! However, _no one_ in practice does this. While the self-extracing method +//! is certainly slower, larger and more complicated, it works without any +//! special configuration, and the load performance penalty is small for +//! Perspective's payload size. +//! +//! In the interest of being small, this library does not rely on `wasm_bindgen` +//! so the API is quite low-level - the caller must independently get the size +//! and offset of the uncompressed WASM and `slice()`` this from the process' +//! `WebAssembly.Memory` externally. Afterwards, the compiled wasm archive +//! is garbage-collected by the JavaScript runtime (just like any JS object), +//! freeing the uncompressed memory from the archive. +//! +//! This module is not built in debug builds, and there is a separate load path +//! in `init.ts` to handle this. + +use std::io::Read; + +/// The target executable is provided from the environment at compile time, but +/// this is hidden behind a feature flag so `rust-analyzer` does not freak out. +#[cfg(not(feature = "env_target"))] +const COMPRESSED_BYTES: &[u8] = &[]; + +#[cfg(feature = "env_target")] +const COMPRESSED_BYTES: &[u8] = include_bytes!(env!("TARGET")); + +static DECOMPRESSED_BYTES: std::sync::OnceLock> = std::sync::OnceLock::new(); + +#[no_mangle] +pub fn size() -> usize { + DECOMPRESSED_BYTES.get_or_init(init).len() +} + +#[no_mangle] +pub fn offset() -> *const u8 { + DECOMPRESSED_BYTES.get_or_init(init).as_ptr() +} + +fn init() -> Vec { + let mut decoder = flate2::read::ZlibDecoder::new(COMPRESSED_BYTES); + let mut y = vec![]; + decoder.read_to_end(&mut y).unwrap(); + y +} diff --git a/rust/perspective-viewer/tasks/bootstrap/Cargo.toml b/rust/perspective-viewer/tasks/bootstrap/Cargo.toml new file mode 100644 index 0000000000..3cecd4d5e6 --- /dev/null +++ b/rust/perspective-viewer/tasks/bootstrap/Cargo.toml @@ -0,0 +1,27 @@ +# ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ +# ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃ +# ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃ +# ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃ +# ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃ +# ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫ +# ┃ Copyright (c) 2017, the Perspective Authors. ┃ +# ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃ +# ┃ This file is part of the Perspective library, distributed under the terms ┃ +# ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃ +# ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + +[package] +name = "perspective-bootstrap" +description = "A CLI utility to create self-extracting wasm binaries" +version = "2.6.1" +edition = "2021" + +[[bin]] +name = "bootstrap" +path = "main.rs" +bench = false + +[dependencies] +clap = { version = "4.4.8", features = ["derive"] } +flate2 = "1.0.28" +wasm-opt = "0.116.0" \ No newline at end of file diff --git a/rust/perspective-viewer/tasks/bootstrap/main.rs b/rust/perspective-viewer/tasks/bootstrap/main.rs new file mode 100644 index 0000000000..56d9088cde --- /dev/null +++ b/rust/perspective-viewer/tasks/bootstrap/main.rs @@ -0,0 +1,79 @@ +// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ +// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃ +// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃ +// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃ +// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃ +// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫ +// ┃ Copyright (c) 2017, the Perspective Authors. ┃ +// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃ +// ┃ This file is part of the Perspective library, distributed under the terms ┃ +// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃ +// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + +#![feature(lazy_cell)] + +use std::fs; +use std::io::Write; +use std::path::Path; +use std::process::{exit, Command}; + +use clap::*; +use flate2::write::ZlibEncoder; +use flate2::Compression; +use wasm_opt::OptimizationOptions; + +#[derive(Parser)] +#[command(author, version, about, long_about = None)] +struct BundleArgs { + /// Input path + input: String, + + /// Output path + #[arg(short, long)] + output: Option, +} + +fn zip(outpath: &Path) { + let input = std::fs::read(outpath).unwrap(); + let mut encoder = ZlibEncoder::new(Vec::new(), Compression::best()); + encoder.write_all(&input).unwrap(); + let encoded = encoder.finish().unwrap(); + std::fs::write(outpath, encoded).unwrap(); +} + +fn main() { + let args = BundleArgs::parse(); + zip(Path::new(&args.input)); + Command::new("cargo") + .args(["build"]) + .args(["--target", "wasm32-unknown-unknown"]) + .args(["--features", "env_target"]) + .args(["-Z", "build-std=std,panic_abort"]) + .args(["-Z", "build-std-features=panic_immediate_abort"]) + .args(["-p", "perspective-bootstrap-runtime"]) + .args(["--release"]) + .env("TARGET", &fs::canonicalize(args.input.clone()).unwrap()) + .execute(); + + let inpath = Path::new("target/wasm32-unknown-unknown/release") + .join("perspective_bootstrap_runtime.wasm"); + + OptimizationOptions::new_optimize_for_size() + .one_caller_inline_max_size(15) + .run(inpath.clone(), args.output.unwrap_or(args.input)) + .unwrap(); +} + +trait SimpleCommand { + fn execute(&mut self); +} + +impl SimpleCommand for Command { + fn execute(&mut self) { + match self.status().ok().and_then(|x| x.code()) { + Some(0) => (), + Some(x) => exit(x), + None => exit(1), + } + } +} diff --git a/rust/perspective-viewer/tasks/bundle/Cargo.toml b/rust/perspective-viewer/tasks/bundle/Cargo.toml index 8d034a7c1a..18f2d121da 100644 --- a/rust/perspective-viewer/tasks/bundle/Cargo.toml +++ b/rust/perspective-viewer/tasks/bundle/Cargo.toml @@ -12,6 +12,7 @@ [package] name = "perspective-bundle" +description = "A CLI utility to build and link persecptive-viewer" version = "2.6.1" edition = "2021" @@ -21,6 +22,5 @@ path = "main.rs" bench = false [dependencies] -flate2 = "1.0.28" wasm-bindgen-cli-support = "0.2.87" wasm-opt = "0.116.0" diff --git a/rust/perspective-viewer/tasks/bundle/main.rs b/rust/perspective-viewer/tasks/bundle/main.rs index af83d63065..5b3dd3b1d1 100644 --- a/rust/perspective-viewer/tasks/bundle/main.rs +++ b/rust/perspective-viewer/tasks/bundle/main.rs @@ -13,13 +13,10 @@ #![feature(lazy_cell)] use std::env::args; -use std::io::Write; use std::path::Path; use std::process::{exit, Command}; use std::sync::LazyLock; -use flate2::write::GzEncoder; -use flate2::Compression; use wasm_bindgen_cli_support::Bindgen; use wasm_opt::OptimizationOptions; @@ -29,20 +26,26 @@ static IS_RELEASE: LazyLock = LazyLock::new(|| args().any(|x| x == "--rele /// defined in the `/.cargo/config.toml` because they would define this build /// script's parameters also, and there is no way to reset e.g. the `target` /// field to the host platform. -fn build() { +fn build(pkg: Option<&str>) { let mut debug_flags = vec![]; if *IS_RELEASE { debug_flags.push("--release"); } - Command::new("cargo") - .env("RUSTFLAGS", "--cfg=web_sys_unstable_apis") + let mut cmd = Command::new("cargo"); + + cmd.env("RUSTFLAGS", "--cfg=web_sys_unstable_apis") .args(["build"]) .args(["--target", "wasm32-unknown-unknown"]) .args(["-Z", "build-std=std,panic_abort"]) .args(["-Z", "build-std-features=panic_immediate_abort"]) - .args(debug_flags) - .execute() + .args(debug_flags); + + if let Some(pkg) = pkg { + cmd.args(["-p", pkg]); + } + + cmd.execute() } /// Generate the `wasm-bindgen` JavaScript and WASM bindings. @@ -63,30 +66,27 @@ fn bindgen(outdir: &Path, artifact: &str) { /// Run `wasm-opt` and output the new binary on top of the old one. fn opt(outpath: &Path) { if *IS_RELEASE { - OptimizationOptions::new_opt_level_4() + OptimizationOptions::new_optimize_for_size() .one_caller_inline_max_size(15) .run(outpath, outpath) .unwrap(); - } -} -/// Gzip the binary. -fn zip(outpath: &Path) { - let input = std::fs::read(outpath).unwrap(); - let mut encoder = GzEncoder::new(Vec::new(), Compression::best()); - encoder.write_all(&input).unwrap(); - let encoded = encoder.finish().unwrap(); - std::fs::write(outpath, encoded).unwrap(); + Command::new("cargo") + .args(["run"]) + .args(["-p", "perspective-bootstrap"]) + .args(["--"]) + .args(["dist/pkg/perspective_bg.wasm"]) + .execute(); + } } fn main() { let outdir = Path::new("dist/pkg"); let artifact = "perspective"; let outpath = &Path::new(outdir).join(format!("{}_bg.wasm", artifact)); - build(); + build(None); bindgen(outdir, artifact); opt(outpath); - zip(outpath); } trait SimpleCommand { diff --git a/tools/perspective-scripts/sh_perspective.mjs b/tools/perspective-scripts/sh_perspective.mjs index 77c127a985..97bea2d071 100644 --- a/tools/perspective-scripts/sh_perspective.mjs +++ b/tools/perspective-scripts/sh_perspective.mjs @@ -177,6 +177,8 @@ export const run_with_scope = async function run_recursive(strings, ...args) { } else { new_uncompiled.push(pkgname); } + } else { + batch.push(pkgname); } } diff --git a/yarn.lock b/yarn.lock index 72bc61bbe9..10476273e9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8634,11 +8634,6 @@ feed@^4.2.2: dependencies: xml-js "^1.6.11" -fflate@^0.7.4: - version "0.7.4" - resolved "https://registry.npmjs.org/fflate/-/fflate-0.7.4.tgz" - integrity sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw== - figures@^3.0.0: version "3.2.0" resolved "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz"