Fix non-Babel-compatible TS decorator usage

This commit is contained in:
Jason Miller
2020-08-12 18:17:50 -04:00
parent 68a5f45432
commit e972f7225a

View File

@@ -23,6 +23,19 @@ type ProcessorWorkerApi = import('./processor-worker').ProcessorWorkerApi;
/** How long the worker should be idle before terminating. */ /** How long the worker should be idle before terminating. */
const workerTimeout = 10000; const workerTimeout = 10000;
/**
* Decorator that manages the (re)starting of the worker and aborting existing jobs. Not all
* processing jobs require a worker (e.g. the main thread canvas encodes), use the needsWorker
* option to control this.
*/
function processingJob(options: ProcessingJobOptions = {}) {
return (target: Processor, propertyKey: string, descriptor: PropertyDescriptor): void => {
const processingFunc = descriptor.value;
descriptor.value = target.runProcessingJob.bind(target, options, processingFunc);
};
}
interface ProcessingJobOptions { interface ProcessingJobOptions {
needsWorker?: boolean; needsWorker?: boolean;
} }
@@ -41,18 +54,10 @@ export default class Processor {
/** setTimeout ID for killing the worker when idle. */ /** setTimeout ID for killing the worker when idle. */
private _workerTimeoutId: number = 0; private _workerTimeoutId: number = 0;
/** /** @private */
* Decorator that manages the (re)starting of the worker and aborting existing jobs. Not all async runProcessingJob(options: ProcessingJobOptions, processingFunc: any, ...args: any[]) {
* processing jobs require a worker (e.g. the main thread canvas encodes), use the needsWorker
* option to control this.
*/
private static _processingJob(options: ProcessingJobOptions = {}) {
const { needsWorker = false } = options; const { needsWorker = false } = options;
return (target: Processor, propertyKey: string, descriptor: PropertyDescriptor): void => {
const processingFunc = descriptor.value;
descriptor.value = async function (this: Processor, ...args: any[]) {
this._latestJobId += 1; this._latestJobId += 1;
const jobId = this._latestJobId; const jobId = this._latestJobId;
this.abortCurrent(); this.abortCurrent();
@@ -65,7 +70,8 @@ export default class Processor {
// definition can't be overwritten. // definition can't be overwritten.
this._worker = new Worker( this._worker = new Worker(
'./processor-worker', './processor-worker',
{ name: 'processor-worker', type: 'module' }, { name: 'processor-worker' },
// { name: 'processor-worker', type: 'module' },
) as Worker; ) as Worker;
// Need to do some TypeScript trickery to make the type match. // Need to do some TypeScript trickery to make the type match.
this._workerApi = proxy(this._worker) as any as ProcessorWorkerApi; this._workerApi = proxy(this._worker) as any as ProcessorWorkerApi;
@@ -85,8 +91,6 @@ export default class Processor {
if (jobId === this._latestJobId) this._jobCleanup(); if (jobId === this._latestJobId) this._jobCleanup();
return returnVal; return returnVal;
};
};
} }
private _jobCleanup(): void { private _jobCleanup(): void {
@@ -116,33 +120,33 @@ export default class Processor {
} }
// Off main thread jobs: // Off main thread jobs:
@Processor._processingJob({ needsWorker: true }) @processingJob({ needsWorker: true })
imageQuant(data: ImageData, opts: QuantizeOptions): Promise<ImageData> { imageQuant(data: ImageData, opts: QuantizeOptions): Promise<ImageData> {
return this._workerApi!.quantize(data, opts); return this._workerApi!.quantize(data, opts);
} }
@Processor._processingJob({ needsWorker: true }) @processingJob({ needsWorker: true })
rotate( rotate(
data: ImageData, opts: import('./rotate/processor-meta').RotateOptions, data: ImageData, opts: import('./rotate/processor-meta').RotateOptions,
): Promise<ImageData> { ): Promise<ImageData> {
return this._workerApi!.rotate(data, opts); return this._workerApi!.rotate(data, opts);
} }
@Processor._processingJob({ needsWorker: true }) @processingJob({ needsWorker: true })
workerResize( workerResize(
data: ImageData, opts: import('./resize/processor-meta').WorkerResizeOptions, data: ImageData, opts: import('./resize/processor-meta').WorkerResizeOptions,
): Promise<ImageData> { ): Promise<ImageData> {
return this._workerApi!.resize(data, opts); return this._workerApi!.resize(data, opts);
} }
@Processor._processingJob({ needsWorker: true }) @processingJob({ needsWorker: true })
mozjpegEncode( mozjpegEncode(
data: ImageData, opts: MozJPEGEncoderOptions, data: ImageData, opts: MozJPEGEncoderOptions,
): Promise<ArrayBuffer> { ): Promise<ArrayBuffer> {
return this._workerApi!.mozjpegEncode(data, opts); return this._workerApi!.mozjpegEncode(data, opts);
} }
@Processor._processingJob({ needsWorker: true }) @processingJob({ needsWorker: true })
async oxiPngEncode( async oxiPngEncode(
data: ImageData, opts: OxiPNGEncoderOptions, data: ImageData, opts: OxiPNGEncoderOptions,
): Promise<ArrayBuffer> { ): Promise<ArrayBuffer> {
@@ -152,12 +156,12 @@ export default class Processor {
return this._workerApi!.oxiPngEncode(pngBuffer, opts); return this._workerApi!.oxiPngEncode(pngBuffer, opts);
} }
@Processor._processingJob({ needsWorker: true }) @processingJob({ needsWorker: true })
webpEncode(data: ImageData, opts: WebPEncoderOptions): Promise<ArrayBuffer> { webpEncode(data: ImageData, opts: WebPEncoderOptions): Promise<ArrayBuffer> {
return this._workerApi!.webpEncode(data, opts); return this._workerApi!.webpEncode(data, opts);
} }
@Processor._processingJob({ needsWorker: true }) @processingJob({ needsWorker: true })
async webpDecode(blob: Blob): Promise<ImageData> { async webpDecode(blob: Blob): Promise<ImageData> {
const data = await blobToArrayBuffer(blob); const data = await blobToArrayBuffer(blob);
return this._workerApi!.webpDecode(data); return this._workerApi!.webpDecode(data);
@@ -165,42 +169,42 @@ export default class Processor {
// Not-worker jobs: // Not-worker jobs:
@Processor._processingJob() @processingJob()
browserBmpEncode(data: ImageData): Promise<Blob> { browserBmpEncode(data: ImageData): Promise<Blob> {
return browserBMP.encode(data); return browserBMP.encode(data);
} }
@Processor._processingJob() @processingJob()
browserPngEncode(data: ImageData): Promise<Blob> { browserPngEncode(data: ImageData): Promise<Blob> {
return browserPNG.encode(data); return browserPNG.encode(data);
} }
@Processor._processingJob() @processingJob()
browserJpegEncode(data: ImageData, opts: BrowserJPEGOptions): Promise<Blob> { browserJpegEncode(data: ImageData, opts: BrowserJPEGOptions): Promise<Blob> {
return browserJPEG.encode(data, opts); return browserJPEG.encode(data, opts);
} }
@Processor._processingJob() @processingJob()
browserWebpEncode(data: ImageData, opts: BrowserWebpEncodeOptions): Promise<Blob> { browserWebpEncode(data: ImageData, opts: BrowserWebpEncodeOptions): Promise<Blob> {
return browserWebP.encode(data, opts); return browserWebP.encode(data, opts);
} }
@Processor._processingJob() @processingJob()
browserGifEncode(data: ImageData): Promise<Blob> { browserGifEncode(data: ImageData): Promise<Blob> {
return browserGIF.encode(data); return browserGIF.encode(data);
} }
@Processor._processingJob() @processingJob()
browserTiffEncode(data: ImageData): Promise<Blob> { browserTiffEncode(data: ImageData): Promise<Blob> {
return browserTIFF.encode(data); return browserTIFF.encode(data);
} }
@Processor._processingJob() @processingJob()
browserJp2Encode(data: ImageData): Promise<Blob> { browserJp2Encode(data: ImageData): Promise<Blob> {
return browserJP2.encode(data); return browserJP2.encode(data);
} }
@Processor._processingJob() @processingJob()
browserPdfEncode(data: ImageData): Promise<Blob> { browserPdfEncode(data: ImageData): Promise<Blob> {
return browserPDF.encode(data); return browserPDF.encode(data);
} }