mirror of
https://github.com/GoogleChromeLabs/squoosh.git
synced 2025-11-11 16:26:20 +00:00
wasm-bindgen-rayon and new OMT plugin (#1007)
* WIP: wasm-bindgen-rayon and new OMT plugin * Bump package-lock * Make OMT work again * Update year * Restore accidental change * Prevent minification of `nextDefineUri` * Delay loading external deps This gives inline `define` calls a chance to define dependencies for earlier `define` calls on the same page. * Add comment
This commit is contained in:
69
codecs/oxipng/Cargo.lock
generated
69
codecs/oxipng/Cargo.lock
generated
@@ -1,5 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "adler"
|
||||
version = "0.2.3"
|
||||
@@ -232,6 +234,15 @@ dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.48"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc9f84f9b115ce7843d60706df1422a916680bfdfcbdb0447c5614ff9d7e4d78"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
@@ -350,12 +361,6 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0"
|
||||
|
||||
[[package]]
|
||||
name = "oxipng"
|
||||
version = "4.0.3"
|
||||
@@ -401,9 +406,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.24"
|
||||
version = "1.0.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
|
||||
checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
@@ -484,24 +489,28 @@ dependencies = [
|
||||
"pest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spmc"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02a8428da277a8e3a15271d79943e80ccc2ef254e78813a166a08d65e4c3ece5"
|
||||
|
||||
[[package]]
|
||||
name = "squoosh-oxipng"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"libdeflater",
|
||||
"log",
|
||||
"once_cell",
|
||||
"oxipng",
|
||||
"rayon",
|
||||
"wasm-bindgen",
|
||||
"wasm-bindgen-rayon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.58"
|
||||
version = "1.0.72"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc60a3d73ea6594cd712d830cc1f0390fd71542d8c8cd24e70cc54cdfd5e05d5"
|
||||
checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -522,9 +531,9 @@ checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.69"
|
||||
version = "0.2.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3cd364751395ca0f68cafb17666eee36b63077fb5ecd972bbcd74c90c4bf736e"
|
||||
checksum = "83240549659d187488f91f33c0f8547cbfef0b2088bc470c116d1d260ef623d9"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"wasm-bindgen-macro",
|
||||
@@ -532,9 +541,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.69"
|
||||
version = "0.2.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1114f89ab1f4106e5b55e688b828c0ab0ea593a1ea7c094b141b14cbaaec2d62"
|
||||
checksum = "ae70622411ca953215ca6d06d3ebeb1e915f0f6613e3b495122878d7ebec7dae"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"lazy_static",
|
||||
@@ -547,9 +556,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.69"
|
||||
version = "0.2.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a6ac8995ead1f084a8dea1e65f194d0973800c7f571f6edd70adf06ecf77084"
|
||||
checksum = "3e734d91443f177bfdb41969de821e15c516931c3c3db3d318fa1b68975d0f6f"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
@@ -557,9 +566,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.69"
|
||||
version = "0.2.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5a48c72f299d80557c7c62e37e7225369ecc0c963964059509fbafe917c7549"
|
||||
checksum = "d53739ff08c8a68b0fdbcd54c372b8ab800b1449ab3c9d706503bc7dd1621b2c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -569,7 +578,19 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.69"
|
||||
name = "wasm-bindgen-rayon"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e7811dd7f9398f14cc76efd356f98f03aa30419dea46aa810d71e819fc97158"
|
||||
checksum = "3069d2a42e7a7e3bfde668f84adb5fbc35701ca2b39b27a064cbd5ede4e78194"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"rayon",
|
||||
"spmc",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9a543ae66aa233d14bb765ed9af4a33e81b8b58d1584cf1b47ff8cd0b9e4489"
|
||||
|
||||
@@ -14,15 +14,13 @@ crate-type = ["cdylib"]
|
||||
[dependencies]
|
||||
oxipng = { version = "4.0.1", default-features = false, features = ["libdeflater"] }
|
||||
libdeflater = { version = "0.7.1", features = ["freestanding"] }
|
||||
wasm-bindgen = "0.2.68"
|
||||
wasm-bindgen = "0.2.73"
|
||||
log = { version = "0.4.11", features = ["release_max_level_off"] }
|
||||
rayon = { version = "1.5.0", optional = true }
|
||||
once_cell = { version = "1.5.2", optional = true }
|
||||
crossbeam-channel = { version = "0.5.0", optional = true }
|
||||
wasm-bindgen-rayon = { version = "1.0", optional = true }
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
opt-level = "s"
|
||||
|
||||
[features]
|
||||
parallel = ["oxipng/parallel", "rayon", "crossbeam-channel", "once_cell"]
|
||||
parallel = ["oxipng/parallel", "wasm-bindgen-rayon"]
|
||||
|
||||
@@ -6,6 +6,4 @@ rm -rf pkg,{-parallel}
|
||||
export CFLAGS="${CFLAGS} -DUNALIGNED_ACCESS_IS_FAST=1"
|
||||
wasm-pack build -t web
|
||||
RUSTFLAGS='-C target-feature=+atomics,+bulk-memory' wasm-pack build -t web -d pkg-parallel -- -Z build-std=panic_abort,std --features=parallel
|
||||
# Workaround https://github.com/rustwasm/wasm-bindgen/issues/2133:
|
||||
sed -i "s|maybe_memory:|maybe_memory?:|" pkg-parallel/squoosh_oxipng.d.ts
|
||||
rm pkg{,-parallel}/.gitignore
|
||||
|
||||
98
codecs/oxipng/pkg-parallel/snippets/wasm-bindgen-rayon-3d2df09ebec17a22/src/workerHelpers.js
generated
Normal file
98
codecs/oxipng/pkg-parallel/snippets/wasm-bindgen-rayon-3d2df09ebec17a22/src/workerHelpers.js
generated
Normal file
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* Copyright 2021 Google Inc. All Rights Reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// Note: we use `wasm_bindgen_worker_`-prefixed message types to make sure
|
||||
// we can handle bundling into other files, which might happen to have their
|
||||
// own `postMessage`/`onmessage` communication channels.
|
||||
//
|
||||
// If we didn't take that into the account, we could send much simpler signals
|
||||
// like just `0` or whatever, but the code would be less resilient.
|
||||
|
||||
function waitForMsgType(target, type) {
|
||||
return new Promise(resolve => {
|
||||
target.addEventListener('message', function onMsg({ data }) {
|
||||
if (data == null || data.type !== type) return;
|
||||
target.removeEventListener('message', onMsg);
|
||||
resolve(data);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
waitForMsgType(self, 'wasm_bindgen_worker_init').then(async data => {
|
||||
// # Note 1
|
||||
// Our JS should have been generated in
|
||||
// `[out-dir]/snippets/wasm-bindgen-rayon-[hash]/workerHelpers.js`,
|
||||
// resolve the main module via `../../..`.
|
||||
//
|
||||
// This might need updating if the generated structure changes on wasm-bindgen
|
||||
// side ever in the future, but works well with bundlers today. The whole
|
||||
// point of this crate, after all, is to abstract away unstable features
|
||||
// and temporary bugs so that you don't need to deal with them in your code.
|
||||
//
|
||||
// # Note 2
|
||||
// This could be a regular import, but then some bundlers complain about
|
||||
// circular deps.
|
||||
//
|
||||
// Dynamic import could be cheap if this file was inlined into the parent,
|
||||
// which would require us just using `../../..` in `new Worker` below,
|
||||
// but that doesn't work because wasm-pack unconditionally adds
|
||||
// "sideEffects":false (see below).
|
||||
//
|
||||
// OTOH, even though it can't be inlined, it should be still reasonably
|
||||
// cheap since the requested file is already in cache (it was loaded by
|
||||
// the main thread).
|
||||
const pkg = await import('../../..');
|
||||
await pkg.default(data.module, data.memory);
|
||||
postMessage({ type: 'wasm_bindgen_worker_ready' });
|
||||
pkg.wbg_rayon_start_worker(data.receiver);
|
||||
});
|
||||
|
||||
export async function startWorkers(module, memory, builder) {
|
||||
const workerInit = {
|
||||
type: 'wasm_bindgen_worker_init',
|
||||
module,
|
||||
memory,
|
||||
receiver: builder.receiver()
|
||||
};
|
||||
|
||||
try {
|
||||
await Promise.all(
|
||||
Array.from({ length: builder.numThreads() }, () => {
|
||||
// Self-spawn into a new Worker.
|
||||
//
|
||||
// TODO: while `new URL('...', import.meta.url) becomes a semi-standard
|
||||
// way to get asset URLs relative to the module across various bundlers
|
||||
// and browser, ideally we should switch to `import.meta.resolve`
|
||||
// once it becomes a standard.
|
||||
//
|
||||
// Note: we could use `../../..` as the URL here to inline workerHelpers.js
|
||||
// into the parent entry instead of creating another split point -
|
||||
// this would be preferable from optimization perspective -
|
||||
// however, Webpack then eliminates all message handler code
|
||||
// because wasm-pack produces "sideEffects":false in package.json
|
||||
// unconditionally.
|
||||
//
|
||||
// The only way to work around that is to have side effect code
|
||||
// in an entry point such as Worker file itself.
|
||||
const worker = new Worker(new URL('./workerHelpers.js', import.meta.url), {
|
||||
type: 'module'
|
||||
});
|
||||
worker.postMessage(workerInit);
|
||||
return waitForMsgType(worker, 'wasm_bindgen_worker_ready');
|
||||
})
|
||||
);
|
||||
builder.build();
|
||||
} finally {
|
||||
builder.free();
|
||||
}
|
||||
}
|
||||
35
codecs/oxipng/pkg-parallel/squoosh_oxipng.d.ts
generated
vendored
35
codecs/oxipng/pkg-parallel/squoosh_oxipng.d.ts
generated
vendored
@@ -7,25 +7,43 @@
|
||||
*/
|
||||
export function optimise(data: Uint8Array, level: number): Uint8Array;
|
||||
/**
|
||||
* @param {number} num
|
||||
* @returns {any}
|
||||
* @param {number} num_threads
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
export function worker_initializer(num: number): any;
|
||||
export function initThreadPool(num_threads: number): Promise<any>;
|
||||
/**
|
||||
* @param {number} receiver
|
||||
*/
|
||||
export function wbg_rayon_start_worker(receiver: number): void;
|
||||
/**
|
||||
*/
|
||||
export function start_main_thread(): void;
|
||||
export class wbg_rayon_PoolBuilder {
|
||||
free(): void;
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
numThreads(): number;
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
receiver(): number;
|
||||
/**
|
||||
*/
|
||||
export function start_worker_thread(): void;
|
||||
build(): void;
|
||||
}
|
||||
|
||||
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
|
||||
|
||||
export interface InitOutput {
|
||||
readonly optimise: (a: number, b: number, c: number, d: number) => void;
|
||||
readonly worker_initializer: (a: number) => number;
|
||||
readonly start_main_thread: () => void;
|
||||
readonly start_worker_thread: () => void;
|
||||
readonly __wbg_wbg_rayon_poolbuilder_free: (a: number) => void;
|
||||
readonly wbg_rayon_poolbuilder_numThreads: (a: number) => number;
|
||||
readonly wbg_rayon_poolbuilder_receiver: (a: number) => number;
|
||||
readonly wbg_rayon_poolbuilder_build: (a: number) => void;
|
||||
readonly initThreadPool: (a: number) => number;
|
||||
readonly wbg_rayon_start_worker: (a: number) => void;
|
||||
readonly __wbindgen_export_0: WebAssembly.Memory;
|
||||
readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
|
||||
readonly __wbindgen_malloc: (a: number) => number;
|
||||
readonly __wbindgen_free: (a: number, b: number) => void;
|
||||
readonly __wbindgen_start: () => void;
|
||||
@@ -41,4 +59,3 @@ export interface InitOutput {
|
||||
* @returns {Promise<InitOutput>}
|
||||
*/
|
||||
export default function init (module_or_path?: InitInput | Promise<InitInput>, maybe_memory?: WebAssembly.Memory): Promise<InitOutput>;
|
||||
|
||||
111
codecs/oxipng/pkg-parallel/squoosh_oxipng.js
generated
111
codecs/oxipng/pkg-parallel/squoosh_oxipng.js
generated
@@ -1,21 +1,6 @@
|
||||
import { startWorkers } from './snippets/wasm-bindgen-rayon-3d2df09ebec17a22/src/workerHelpers.js';
|
||||
|
||||
let wasm;
|
||||
let memory;
|
||||
|
||||
const heap = new Array(32).fill(undefined);
|
||||
|
||||
heap.push(undefined, null, true, false);
|
||||
|
||||
let heap_next = heap.length;
|
||||
|
||||
function addHeapObject(obj) {
|
||||
if (heap_next === heap.length) heap.push(heap.length + 1);
|
||||
const idx = heap_next;
|
||||
heap_next = heap[idx];
|
||||
|
||||
heap[idx] = obj;
|
||||
return idx;
|
||||
}
|
||||
|
||||
let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
||||
|
||||
@@ -33,6 +18,21 @@ function getStringFromWasm0(ptr, len) {
|
||||
return cachedTextDecoder.decode(getUint8Memory0().slice(ptr, ptr + len));
|
||||
}
|
||||
|
||||
const heap = new Array(32).fill(undefined);
|
||||
|
||||
heap.push(undefined, null, true, false);
|
||||
|
||||
let heap_next = heap.length;
|
||||
|
||||
function addHeapObject(obj) {
|
||||
if (heap_next === heap.length) heap.push(heap.length + 1);
|
||||
const idx = heap_next;
|
||||
heap_next = heap[idx];
|
||||
|
||||
heap[idx] = obj;
|
||||
return idx;
|
||||
}
|
||||
|
||||
let WASM_VECTOR_LEN = 0;
|
||||
|
||||
function passArray8ToWasm0(arg, malloc) {
|
||||
@@ -60,8 +60,7 @@ function getArrayU8FromWasm0(ptr, len) {
|
||||
*/
|
||||
export function optimise(data, level) {
|
||||
try {
|
||||
const retptr = wasm.__wbindgen_export_1.value - 16;
|
||||
wasm.__wbindgen_export_1.value = retptr;
|
||||
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
||||
var ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_malloc);
|
||||
var len0 = WASM_VECTOR_LEN;
|
||||
wasm.optimise(retptr, ptr0, len0, level);
|
||||
@@ -71,7 +70,7 @@ export function optimise(data, level) {
|
||||
wasm.__wbindgen_free(r0, r1 * 1);
|
||||
return v1;
|
||||
} finally {
|
||||
wasm.__wbindgen_export_1.value += 16;
|
||||
wasm.__wbindgen_add_to_stack_pointer(16);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,29 +88,66 @@ function takeObject(idx) {
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
* @param {number} num
|
||||
* @returns {any}
|
||||
* @param {number} num_threads
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
export function worker_initializer(num) {
|
||||
var ret = wasm.worker_initializer(num);
|
||||
export function initThreadPool(num_threads) {
|
||||
var ret = wasm.initThreadPool(num_threads);
|
||||
return takeObject(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} receiver
|
||||
*/
|
||||
export function start_main_thread() {
|
||||
wasm.start_main_thread();
|
||||
export function wbg_rayon_start_worker(receiver) {
|
||||
wasm.wbg_rayon_start_worker(receiver);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
export function start_worker_thread() {
|
||||
wasm.start_worker_thread();
|
||||
export class wbg_rayon_PoolBuilder {
|
||||
|
||||
static __wrap(ptr) {
|
||||
const obj = Object.create(wbg_rayon_PoolBuilder.prototype);
|
||||
obj.ptr = ptr;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
__destroy_into_raw() {
|
||||
const ptr = this.ptr;
|
||||
this.ptr = 0;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
free() {
|
||||
const ptr = this.__destroy_into_raw();
|
||||
wasm.__wbg_wbg_rayon_poolbuilder_free(ptr);
|
||||
}
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
numThreads() {
|
||||
var ret = wasm.wbg_rayon_poolbuilder_numThreads(this.ptr);
|
||||
return ret >>> 0;
|
||||
}
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
receiver() {
|
||||
var ret = wasm.wbg_rayon_poolbuilder_receiver(this.ptr);
|
||||
return ret;
|
||||
}
|
||||
/**
|
||||
*/
|
||||
build() {
|
||||
wasm.wbg_rayon_poolbuilder_build(this.ptr);
|
||||
}
|
||||
}
|
||||
|
||||
async function load(module, imports, maybe_memory) {
|
||||
async function load(module, imports) {
|
||||
if (typeof Response === 'function' && module instanceof Response) {
|
||||
memory = imports.wbg.memory = new WebAssembly.Memory({initial:17,maximum:16384,shared:true});
|
||||
if (typeof WebAssembly.instantiateStreaming === 'function') {
|
||||
try {
|
||||
return await WebAssembly.instantiateStreaming(module, imports);
|
||||
@@ -130,7 +166,6 @@ async function load(module, imports, maybe_memory) {
|
||||
return await WebAssembly.instantiate(bytes, imports);
|
||||
|
||||
} else {
|
||||
memory = imports.wbg.memory = maybe_memory;
|
||||
const instance = await WebAssembly.instantiate(module, imports);
|
||||
|
||||
if (instance instanceof WebAssembly.Instance) {
|
||||
@@ -144,10 +179,13 @@ async function load(module, imports, maybe_memory) {
|
||||
|
||||
async function init(input, maybe_memory) {
|
||||
if (typeof input === 'undefined') {
|
||||
input = import.meta.url.replace(/\.js$/, '_bg.wasm');
|
||||
input = new URL('squoosh_oxipng_bg.wasm', import.meta.url);
|
||||
}
|
||||
const imports = {};
|
||||
imports.wbg = {};
|
||||
imports.wbg.__wbindgen_throw = function(arg0, arg1) {
|
||||
throw new Error(getStringFromWasm0(arg0, arg1));
|
||||
};
|
||||
imports.wbg.__wbindgen_module = function() {
|
||||
var ret = init.__wbindgen_wasm_module;
|
||||
return addHeapObject(ret);
|
||||
@@ -156,19 +194,18 @@ async function init(input, maybe_memory) {
|
||||
var ret = wasm.__wbindgen_export_0;
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbg_of_6510501edc06d65e = function(arg0, arg1) {
|
||||
var ret = Array.of(takeObject(arg0), takeObject(arg1));
|
||||
imports.wbg.__wbg_startWorkers_914655bb4d5bb5e1 = function(arg0, arg1, arg2) {
|
||||
var ret = startWorkers(takeObject(arg0), takeObject(arg1), wbg_rayon_PoolBuilder.__wrap(arg2));
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_throw = function(arg0, arg1) {
|
||||
throw new Error(getStringFromWasm0(arg0, arg1));
|
||||
};
|
||||
|
||||
if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) {
|
||||
input = fetch(input);
|
||||
}
|
||||
|
||||
const { instance, module } = await load(await input, imports, maybe_memory);
|
||||
imports.wbg.memory = maybe_memory || new WebAssembly.Memory({initial:17,maximum:16384,shared:true});
|
||||
|
||||
const { instance, module } = await load(await input, imports);
|
||||
|
||||
wasm = instance.exports;
|
||||
init.__wbindgen_wasm_module = module;
|
||||
|
||||
Binary file not shown.
10
codecs/oxipng/pkg-parallel/squoosh_oxipng_bg.wasm.d.ts
generated
vendored
10
codecs/oxipng/pkg-parallel/squoosh_oxipng_bg.wasm.d.ts
generated
vendored
@@ -1,10 +1,14 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
export function optimise(a: number, b: number, c: number, d: number): void;
|
||||
export function worker_initializer(a: number): number;
|
||||
export function start_main_thread(): void;
|
||||
export function start_worker_thread(): void;
|
||||
export function __wbg_wbg_rayon_poolbuilder_free(a: number): void;
|
||||
export function wbg_rayon_poolbuilder_numThreads(a: number): number;
|
||||
export function wbg_rayon_poolbuilder_receiver(a: number): number;
|
||||
export function wbg_rayon_poolbuilder_build(a: number): void;
|
||||
export function initThreadPool(a: number): number;
|
||||
export function wbg_rayon_start_worker(a: number): void;
|
||||
export const __wbindgen_export_0: WebAssembly.Memory;
|
||||
export function __wbindgen_add_to_stack_pointer(a: number): number;
|
||||
export function __wbindgen_malloc(a: number): number;
|
||||
export function __wbindgen_free(a: number, b: number): void;
|
||||
export function __wbindgen_start(): void;
|
||||
|
||||
2
codecs/oxipng/pkg/squoosh_oxipng.d.ts
generated
vendored
2
codecs/oxipng/pkg/squoosh_oxipng.d.ts
generated
vendored
@@ -12,6 +12,7 @@ export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembl
|
||||
export interface InitOutput {
|
||||
readonly memory: WebAssembly.Memory;
|
||||
readonly optimise: (a: number, b: number, c: number, d: number) => void;
|
||||
readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
|
||||
readonly __wbindgen_malloc: (a: number) => number;
|
||||
readonly __wbindgen_free: (a: number, b: number) => void;
|
||||
}
|
||||
@@ -25,4 +26,3 @@ export interface InitOutput {
|
||||
* @returns {Promise<InitOutput>}
|
||||
*/
|
||||
export default function init (module_or_path?: InitInput | Promise<InitInput>): Promise<InitOutput>;
|
||||
|
||||
11
codecs/oxipng/pkg/squoosh_oxipng.js
generated
11
codecs/oxipng/pkg/squoosh_oxipng.js
generated
@@ -44,8 +44,7 @@ function getArrayU8FromWasm0(ptr, len) {
|
||||
*/
|
||||
export function optimise(data, level) {
|
||||
try {
|
||||
const retptr = wasm.__wbindgen_export_0.value - 16;
|
||||
wasm.__wbindgen_export_0.value = retptr;
|
||||
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
||||
var ptr0 = passArray8ToWasm0(data, wasm.__wbindgen_malloc);
|
||||
var len0 = WASM_VECTOR_LEN;
|
||||
wasm.optimise(retptr, ptr0, len0, level);
|
||||
@@ -55,13 +54,12 @@ export function optimise(data, level) {
|
||||
wasm.__wbindgen_free(r0, r1 * 1);
|
||||
return v1;
|
||||
} finally {
|
||||
wasm.__wbindgen_export_0.value += 16;
|
||||
wasm.__wbindgen_add_to_stack_pointer(16);
|
||||
}
|
||||
}
|
||||
|
||||
async function load(module, imports) {
|
||||
if (typeof Response === 'function' && module instanceof Response) {
|
||||
|
||||
if (typeof WebAssembly.instantiateStreaming === 'function') {
|
||||
try {
|
||||
return await WebAssembly.instantiateStreaming(module, imports);
|
||||
@@ -80,7 +78,6 @@ async function load(module, imports) {
|
||||
return await WebAssembly.instantiate(bytes, imports);
|
||||
|
||||
} else {
|
||||
|
||||
const instance = await WebAssembly.instantiate(module, imports);
|
||||
|
||||
if (instance instanceof WebAssembly.Instance) {
|
||||
@@ -94,7 +91,7 @@ async function load(module, imports) {
|
||||
|
||||
async function init(input) {
|
||||
if (typeof input === 'undefined') {
|
||||
input = import.meta.url.replace(/\.js$/, '_bg.wasm');
|
||||
input = new URL('squoosh_oxipng_bg.wasm', import.meta.url);
|
||||
}
|
||||
const imports = {};
|
||||
imports.wbg = {};
|
||||
@@ -106,6 +103,8 @@ async function init(input) {
|
||||
input = fetch(input);
|
||||
}
|
||||
|
||||
|
||||
|
||||
const { instance, module } = await load(await input, imports);
|
||||
|
||||
wasm = instance.exports;
|
||||
|
||||
Binary file not shown.
1
codecs/oxipng/pkg/squoosh_oxipng_bg.wasm.d.ts
generated
vendored
1
codecs/oxipng/pkg/squoosh_oxipng_bg.wasm.d.ts
generated
vendored
@@ -2,5 +2,6 @@
|
||||
/* eslint-disable */
|
||||
export const memory: WebAssembly.Memory;
|
||||
export function optimise(a: number, b: number, c: number, d: number): void;
|
||||
export function __wbindgen_add_to_stack_pointer(a: number): number;
|
||||
export function __wbindgen_malloc(a: number): number;
|
||||
export function __wbindgen_free(a: number, b: number): void;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#[cfg(feature = "parallel")]
|
||||
pub use wasm_bindgen_rayon::init_thread_pool;
|
||||
|
||||
use oxipng::AlphaOptim;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[cfg(feature = "parallel")]
|
||||
pub mod parallel;
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn optimise(data: &[u8], level: u8) -> Vec<u8> {
|
||||
let mut options = oxipng::Options::from_preset(level);
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
use crossbeam_channel::{bounded, Receiver, Sender};
|
||||
use once_cell::sync::OnceCell;
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen::JsValue;
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(js_namespace = Array, js_name = of)]
|
||||
fn array_of_2(a: JsValue, b: JsValue) -> JsValue;
|
||||
}
|
||||
|
||||
// This is one of the parts that work around Chromium incorrectly implementing postMessage:
|
||||
// https://bugs.chromium.org/p/chromium/issues/detail?id=1075645
|
||||
//
|
||||
// rayon::ThreadPoolBuilder (used below) executes spawn handler to populate the worker pool,
|
||||
// and then blocks the current thread until each worker unblocks its (opaque) lock.
|
||||
//
|
||||
// Normally, we could use postMessage directly inside the spawn handler to
|
||||
// post module + memory + threadPtr to each worker, and the block the current thread.
|
||||
//
|
||||
// However, that bug means that postMessage is currently delayed until the next event loop,
|
||||
// which will never spin since we block the current thread, and so the other workers will
|
||||
// never be able to unblock us.
|
||||
//
|
||||
// To work around this problem, we:
|
||||
// 1) Expose `worker_initializer` that returns module + memory pair (without threadPtr)
|
||||
// that workers can be initialised with to become native threads.
|
||||
// JavaScript can postMessage this pair in advance, and asynchronously wait for workers
|
||||
// to acknowledge the receipt.
|
||||
// 2) Create a global communication channel on the Rust side using crossbeam.
|
||||
// It will be used to send threadPtr to the pre-initialised workers
|
||||
// instead of postMessage.
|
||||
// 3) Provide a separate `start_main_thread` that expects all workers to be ready,
|
||||
// and just uses the provided channel to send `threadPtr`s using the
|
||||
// shared memory and blocks the current thread until they're all grabbed.
|
||||
// 4) Provide a `worker_initializer` that is expected to be invoked from various workers,
|
||||
// reads one `threadPtr` from the shared channel and starts running it.
|
||||
static CHANNEL: OnceCell<(Sender<rayon::ThreadBuilder>, Receiver<rayon::ThreadBuilder>)> =
|
||||
OnceCell::new();
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn worker_initializer(num: usize) -> JsValue {
|
||||
CHANNEL.get_or_init(|| bounded(num));
|
||||
array_of_2(wasm_bindgen::module(), wasm_bindgen::memory())
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn start_main_thread() {
|
||||
let (sender, _) = CHANNEL.get().unwrap();
|
||||
|
||||
rayon::ThreadPoolBuilder::new()
|
||||
.num_threads(sender.capacity().unwrap())
|
||||
.spawn_handler(|thread| Ok(sender.send(thread).unwrap_throw()))
|
||||
.build_global()
|
||||
.unwrap_throw()
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn start_worker_thread() {
|
||||
let (_, receiver) = CHANNEL.get().unwrap();
|
||||
receiver.recv().unwrap_throw().run()
|
||||
}
|
||||
@@ -137,10 +137,24 @@ export default function (inputOptions, outputOptions, resolveFileUrl) {
|
||||
const dependencies = getDependencies(clientOutput, clientEntry);
|
||||
|
||||
if (property.startsWith(allSrcPlaceholder)) {
|
||||
const depCodes = dependencies.map(
|
||||
(name) => clientOutput.find((item) => item.fileName === name).code,
|
||||
);
|
||||
return JSON.stringify([clientEntry.code, ...depCodes].join(';'));
|
||||
const allModules = [
|
||||
clientEntry,
|
||||
...dependencies.map((name) =>
|
||||
clientOutput.find((item) => item.fileName === name),
|
||||
),
|
||||
];
|
||||
|
||||
const inlineDefines = [
|
||||
...allModules.map(
|
||||
(item) =>
|
||||
`self.nextDefineUri=location.origin+${resolveFileUrl(item)};${
|
||||
item.code
|
||||
}`,
|
||||
),
|
||||
'self.nextDefineUri=""',
|
||||
];
|
||||
|
||||
return JSON.stringify(inlineDefines.join(''));
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -48,7 +48,7 @@ const appendCssSource = `
|
||||
}
|
||||
`;
|
||||
|
||||
export default function (resolveFileUrl) {
|
||||
export default function () {
|
||||
/** @type {string[]} */
|
||||
let emittedCSSIds;
|
||||
/** @type {Map<string, string>} */
|
||||
|
||||
112
lib/omt.ejs
112
lib/omt.ejs
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2020 Google Inc. All Rights Reserved.
|
||||
* Copyright 2021 Google Inc. All Rights Reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
@@ -13,80 +13,64 @@
|
||||
|
||||
// If the loader is already loaded, just stop.
|
||||
if (!self.<%- amdFunctionName %>) {
|
||||
const singleRequire = async name => {
|
||||
if (name === 'require') return require;
|
||||
let url;
|
||||
if (name.startsWith(location.origin)) {
|
||||
url = name.slice(location.origin.length);
|
||||
} else {
|
||||
url = name.slice(1) + '.js';
|
||||
}
|
||||
if (!url.startsWith('/c/')) {
|
||||
url = '/c' + url;
|
||||
}
|
||||
name = './static' + url;
|
||||
if (registry[name]) return registry[name];
|
||||
let registry = {};
|
||||
|
||||
if (!registry[name]) {
|
||||
const singleRequire = (uri, parentUri) => {
|
||||
let origURI = uri;
|
||||
uri = new URL(uri + ".js", parentUri).href;
|
||||
return registry[uri] || (
|
||||
<% if (useEval) { %>
|
||||
const text = await fetch(url).then(resp => resp.text());
|
||||
eval(text);
|
||||
fetch(uri)
|
||||
.then(resp => resp.text())
|
||||
.then(code => {
|
||||
self.nextDefineUri = uri;
|
||||
eval(code);
|
||||
})
|
||||
<% } else { %>
|
||||
if ("document" in self) {
|
||||
await new Promise(resolve => {
|
||||
new Promise(resolve => {
|
||||
if ("document" in self) {
|
||||
const script = document.createElement("script");
|
||||
script.src = url;
|
||||
document.head.appendChild(script);
|
||||
script.src = uri;
|
||||
script.onload = resolve;
|
||||
});
|
||||
} else {
|
||||
importScripts(url);
|
||||
}
|
||||
document.head.appendChild(script);
|
||||
} else {
|
||||
self.nextDefineUri = uri;
|
||||
importScripts(uri);
|
||||
resolve();
|
||||
}
|
||||
})
|
||||
<% } %>
|
||||
}
|
||||
if (!registry[name]) {
|
||||
throw new Error(`Module ${name} didn’t register its module`);
|
||||
}
|
||||
return registry[name];
|
||||
.then(() => {
|
||||
let promise = registry[uri];
|
||||
if (!promise) {
|
||||
throw new Error(`Module ${uri} didn’t register its module`);
|
||||
}
|
||||
return promise;
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const require = (names, resolve) => {
|
||||
Promise.all(names.map(singleRequire))
|
||||
.then(modules => resolve(modules.length === 1 ? modules[0] : modules));
|
||||
};
|
||||
|
||||
const registry = {
|
||||
require: Promise.resolve(require)
|
||||
};
|
||||
|
||||
self.<%- amdFunctionName %> = (moduleName, depsNames, factory) => {
|
||||
if (registry[moduleName]) {
|
||||
self.<%- amdFunctionName %> = (depsNames, factory) => {
|
||||
const uri = self.nextDefineUri || ("document" in self ? document.currentScript.src : "") || location.href;
|
||||
if (registry[uri]) {
|
||||
// Module is already loading or loaded.
|
||||
return;
|
||||
}
|
||||
registry[moduleName] = Promise.resolve().then(() => {
|
||||
let exports = {};
|
||||
const module = {
|
||||
uri: location.origin + moduleName.slice(1)
|
||||
};
|
||||
return Promise.all(
|
||||
depsNames.map(depName => {
|
||||
switch(depName) {
|
||||
case "exports":
|
||||
return exports;
|
||||
case "module":
|
||||
return module;
|
||||
default:
|
||||
return singleRequire(depName);
|
||||
}
|
||||
})
|
||||
).then(deps => {
|
||||
const facValue = factory(...deps);
|
||||
if (!exports.default) {
|
||||
exports.default = facValue;
|
||||
}
|
||||
return exports;
|
||||
});
|
||||
let exports = {};
|
||||
const require = depUri => singleRequire(depUri, uri);
|
||||
const specialDeps = {
|
||||
module: { uri },
|
||||
exports,
|
||||
require
|
||||
};
|
||||
// Note: Promise.resolve() is necessary to delay loading until all the
|
||||
// `define`s on the current page had a chance to execute first.
|
||||
// This allows to inline some deps on the main page.
|
||||
registry[uri] = Promise.resolve().then(() => Promise.all(depsNames.map(
|
||||
depName => specialDeps[depName] || require(depName)
|
||||
))).then(deps => {
|
||||
factory(...deps);
|
||||
return exports;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
110
package-lock.json
generated
110
package-lock.json
generated
@@ -179,13 +179,25 @@
|
||||
}
|
||||
},
|
||||
"@surma/rollup-plugin-off-main-thread": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-1.4.2.tgz",
|
||||
"integrity": "sha512-yBMPqmd1yEJo/280PAMkychuaALyQ9Lkb5q1ck3mjJrFuEobIfhnQ4J3mbvBoISmR3SWMWV+cGB/I0lCQee79A==",
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.1.tgz",
|
||||
"integrity": "sha512-7OU8wfyv18YPWVmecg2/0Jh+pm3lQbvPhIWHd1YQpoxPKPW/vsDNGBaCnMKsZbz29RjgCoXKugAjyagPncgdEw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ejs": "^2.6.1",
|
||||
"ejs": "^3.1.6",
|
||||
"json5": "^2.2.0",
|
||||
"magic-string": "^0.25.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"json5": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
|
||||
"integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"minimist": "^1.2.5"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@types/color-name": {
|
||||
@@ -405,6 +417,12 @@
|
||||
"integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
|
||||
"dev": true
|
||||
},
|
||||
"async": {
|
||||
"version": "0.9.2",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
|
||||
"integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=",
|
||||
"dev": true
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||
@@ -1597,10 +1615,13 @@
|
||||
}
|
||||
},
|
||||
"ejs": {
|
||||
"version": "2.7.4",
|
||||
"resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz",
|
||||
"integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==",
|
||||
"dev": true
|
||||
"version": "3.1.6",
|
||||
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.6.tgz",
|
||||
"integrity": "sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"jake": "^10.6.1"
|
||||
}
|
||||
},
|
||||
"electron-to-chromium": {
|
||||
"version": "1.3.538",
|
||||
@@ -1797,6 +1818,15 @@
|
||||
"integrity": "sha512-na2cwntTVgMsR+BZ2YBr/XQk941DKDw2LJKbV7g6TRdGBQ3rx8V53oEviG8zPWoBOySwK9w/SlZ/gb/F/48I8A==",
|
||||
"dev": true
|
||||
},
|
||||
"filelist": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.2.tgz",
|
||||
"integrity": "sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"minimatch": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
@@ -2306,6 +2336,70 @@
|
||||
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
|
||||
"dev": true
|
||||
},
|
||||
"jake": {
|
||||
"version": "10.8.2",
|
||||
"resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz",
|
||||
"integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"async": "0.9.x",
|
||||
"chalk": "^2.4.2",
|
||||
"filelist": "^1.0.1",
|
||||
"minimatch": "^3.0.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-convert": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
|
||||
"dev": true
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
|
||||
"dev": true
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"jest-worker": {
|
||||
"version": "26.3.0",
|
||||
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.3.0.tgz",
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
"@rollup/plugin-commonjs": "^17.0.0",
|
||||
"@rollup/plugin-node-resolve": "^11.1.0",
|
||||
"@rollup/plugin-replace": "^2.3.4",
|
||||
"@surma/rollup-plugin-off-main-thread": "^1.4.2",
|
||||
"@surma/rollup-plugin-off-main-thread": "^2.2.1",
|
||||
"@types/dedent": "^0.7.0",
|
||||
"@types/mime-types": "^2.1.0",
|
||||
"@types/node": "^14.14.7",
|
||||
|
||||
@@ -37,13 +37,6 @@ function resolveFileUrl({ fileName }) {
|
||||
return JSON.stringify(fileName.replace(/^static\//, '/'));
|
||||
}
|
||||
|
||||
// With AMD output, Rollup always uses document.baseURI, which breaks in workers.
|
||||
// This fixes it:
|
||||
function resolveImportMeta(property, { chunkId }) {
|
||||
if (property !== 'url') return;
|
||||
return `new URL(${resolveFileUrl({ fileName: chunkId })}, location).href`;
|
||||
}
|
||||
|
||||
const dir = '.tmp/build';
|
||||
const staticPath = 'static/c/[name]-[hash][extname]';
|
||||
const jsPath = staticPath.replace('[extname]', '.js');
|
||||
@@ -62,6 +55,7 @@ export default async function ({ watch }) {
|
||||
path.join(__dirname, 'lib', 'omt.ejs'),
|
||||
'utf-8',
|
||||
);
|
||||
|
||||
await del('.tmp/build');
|
||||
|
||||
const isProduction = !watch;
|
||||
@@ -83,7 +77,7 @@ export default async function ({ watch }) {
|
||||
]),
|
||||
urlPlugin(),
|
||||
dataURLPlugin(),
|
||||
cssPlugin(resolveFileUrl),
|
||||
cssPlugin(),
|
||||
];
|
||||
|
||||
return {
|
||||
@@ -105,12 +99,12 @@ export default async function ({ watch }) {
|
||||
},
|
||||
preserveModules: true,
|
||||
plugins: [
|
||||
{ resolveFileUrl, resolveImportMeta },
|
||||
{ resolveFileUrl },
|
||||
clientBundlePlugin(
|
||||
{
|
||||
external: ['worker_threads'],
|
||||
plugins: [
|
||||
{ resolveFileUrl, resolveImportMeta },
|
||||
{ resolveFileUrl },
|
||||
OMT({ loader: await omtLoaderPromise }),
|
||||
serviceWorkerPlugin({
|
||||
output: 'static/serviceworker.js',
|
||||
|
||||
@@ -14,54 +14,17 @@ import initOxiWasmST, {
|
||||
optimise as optimiseST,
|
||||
} from 'codecs/oxipng/pkg/squoosh_oxipng';
|
||||
import initOxiWasmMT, {
|
||||
worker_initializer,
|
||||
start_main_thread,
|
||||
initThreadPool,
|
||||
optimise as optimiseMT,
|
||||
} from 'codecs/oxipng/pkg-parallel/squoosh_oxipng';
|
||||
import oxiWasmUrlST from 'url:codecs/oxipng/pkg/squoosh_oxipng_bg.wasm';
|
||||
import oxiWasmUrlMT from 'url:codecs/oxipng/pkg-parallel/squoosh_oxipng_bg.wasm';
|
||||
import { EncodeOptions } from '../shared/meta';
|
||||
import { threads } from 'wasm-feature-detect';
|
||||
import workerURL from 'omt:./sub-worker';
|
||||
import type { WorkerInit } from './sub-worker';
|
||||
|
||||
function initWorker(worker: Worker, workerInit: WorkerInit) {
|
||||
return new Promise<void>((resolve) => {
|
||||
worker.postMessage(workerInit);
|
||||
worker.addEventListener('message', () => resolve(), { once: true });
|
||||
});
|
||||
}
|
||||
|
||||
async function initMT() {
|
||||
const num = navigator.hardwareConcurrency;
|
||||
|
||||
// First, let browser fetch and spawn Workers for our pool in the background.
|
||||
// This is fairly expensive, so we want to start it as early as possible.
|
||||
const workers = Array.from({ length: num }, () => new Worker(workerURL));
|
||||
|
||||
// Meanwhile, asynchronously compile, instantiate and initialise Wasm on our main thread.
|
||||
await initOxiWasmMT(oxiWasmUrlMT);
|
||||
|
||||
// Get module+memory from the Wasm instance.
|
||||
//
|
||||
// Ideally we wouldn't go via Wasm bindings here, since both are just JS variables, but memory is
|
||||
// currently not exposed on the Wasm instance correctly by wasm-bindgen.
|
||||
const workerInit: WorkerInit = worker_initializer(num);
|
||||
|
||||
// Once done, we want to send module+memory to each Worker so that they instantiate Wasm too.
|
||||
// While doing so, we need to wait for Workers to acknowledge that they have received our message.
|
||||
// Ideally this shouldn't be necessary, but Chromium currently doesn't conform to the spec:
|
||||
// https://bugs.chromium.org/p/chromium/issues/detail?id=1075645
|
||||
//
|
||||
// If we didn't do this ping-pong game, the `start_main_thread` below would block the current
|
||||
// thread on an atomic before even *sending* the `postMessage` containing memory,
|
||||
// so Workers would never be able to unblock us back.
|
||||
await Promise.all(workers.map((worker) => initWorker(worker, workerInit)));
|
||||
|
||||
// Finally, instantiate rayon pool - this will use shared Wasm memory to send tasks to the
|
||||
// Workers and then block until they're all ready.
|
||||
start_main_thread();
|
||||
|
||||
await initThreadPool(navigator.hardwareConcurrency);
|
||||
return optimiseMT;
|
||||
}
|
||||
|
||||
@@ -77,7 +40,7 @@ export default async function encode(
|
||||
options: EncodeOptions,
|
||||
): Promise<ArrayBuffer> {
|
||||
if (!wasmReady) {
|
||||
wasmReady = (await threads()) ? initMT() : initST();
|
||||
wasmReady = threads().then((hasThreads: boolean) => hasThreads ? initMT() : initST());
|
||||
}
|
||||
|
||||
const optimise = await wasmReady;
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
import initOxiPNG, {
|
||||
start_worker_thread,
|
||||
} from 'codecs/oxipng/pkg-parallel/squoosh_oxipng';
|
||||
|
||||
export type WorkerInit = [WebAssembly.Module, WebAssembly.Memory];
|
||||
|
||||
addEventListener(
|
||||
'message',
|
||||
async (event) => {
|
||||
// Tell the "main" thread that we've received the message.
|
||||
//
|
||||
// At this point, the "main" thread can run Wasm that
|
||||
// will synchronously block waiting on other atomics.
|
||||
//
|
||||
// Note that we don't need to wait for Wasm instantiation here - it's
|
||||
// better to start main thread as early as possible, and then it blocks
|
||||
// on a shared atomic anyway until Worker is fully ready.
|
||||
// @ts-ignore
|
||||
postMessage(null);
|
||||
|
||||
await initOxiPNG(...(event.data as WorkerInit));
|
||||
start_worker_thread();
|
||||
},
|
||||
{ once: true },
|
||||
);
|
||||
@@ -85,7 +85,6 @@ import jxlEncWasm from 'url:codecs/jxl/enc/jxl_enc.wasm';
|
||||
import * as jxlEnc from 'entry-data:codecs/jxl/enc/jxl_enc';
|
||||
|
||||
// OXI
|
||||
import * as oxiMtWorker from 'entry-data:features/encoders/oxiPNG/worker/sub-worker';
|
||||
import oxiMtWasm from 'url:codecs/oxipng/pkg-parallel/squoosh_oxipng_bg.wasm';
|
||||
import oxiWasm from 'url:codecs/oxipng/pkg/squoosh_oxipng_bg.wasm';
|
||||
|
||||
@@ -176,7 +175,7 @@ export const theRest = (async () => {
|
||||
|
||||
// OXI
|
||||
if (supportsThreads) {
|
||||
items.push(oxiMtWorker.main, ...oxiMtWorker.deps, oxiMtWasm);
|
||||
items.push(oxiMtWasm);
|
||||
} else {
|
||||
items.push(oxiWasm);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
},
|
||||
"include": [
|
||||
"src/features/**/worker/**/*",
|
||||
"src/features/**/sub-worker/**/*",
|
||||
"src/features/**/shared/**/*",
|
||||
"src/features/worker-utils/**/*",
|
||||
"src/features-worker/**/*",
|
||||
|
||||
Reference in New Issue
Block a user