runPdfRenderWorker function
void
runPdfRenderWorker()
Runs the render worker inside a dedicated Web Worker. A consuming web app ships a tiny worker script that calls this:
// web/pdf_render_worker.dart
import 'package:dart_pdf_editor/render_worker_web.dart';
void main() => runPdfRenderWorker();
compiled with dart compile js web/pdf_render_worker.dart -o web/pdf_render_worker.dart.js and served alongside the app; the app then
sets pdfRenderWorkerScriptUrl = 'pdf_render_worker.dart.js' before opening
a viewer. See doc/render_worker_web.md for the full wiring.
Protocol (mirrors the native isolate backend):
{kind:'init', bytes:ArrayBuffer}→ opens the document, replies{kind:'ready'}.{kind:'record', id, page, annotations}→ replies{kind:'result', id, buffer:ArrayBuffer|null}(null = the page can't be offloaded; the main thread renders it locally).
Implementation
void runPdfRenderWorker() {
final scope = globalContext as web.DedicatedWorkerGlobalScope;
PdfDocument? document;
scope.onmessage = ((web.MessageEvent event) {
final data = event.data as JSObject?;
if (data == null) return;
final kind = (data.getProperty('kind'.toJS) as JSString?)?.toDart;
if (kind == 'init') {
final buffer = data.getProperty('bytes'.toJS) as JSArrayBuffer;
try {
document = PdfDocument.open(buffer.toDart.asUint8List());
} catch (_) {
document = null; // a broken document fails every page → local renders
}
scope.postMessage(JSObject()..setProperty('kind'.toJS, 'ready'.toJS));
return;
}
if (kind != 'record') return;
final id = (data.getProperty('id'.toJS) as JSNumber).toDartInt;
final page = (data.getProperty('page'.toJS) as JSNumber).toDartInt;
final annotations =
(data.getProperty('annotations'.toJS) as JSBoolean).toDart;
Uint8List? out;
// A page can decline (image it can't serialize) or throw; surface the reason
// to the main thread so it lands in a PdfPerfLog trace instead of being lost
// in the worker's own console.
String? error;
final doc = document;
try {
if (doc != null) out = _recordPage(doc, page, annotations);
} catch (e, st) {
out = null; // any failure → the main thread renders this page locally
error = '$e\n$st';
}
final result = JSObject()
..setProperty('kind'.toJS, 'result'.toJS)
..setProperty('id'.toJS, id.toJS);
if (out == null) {
result.setProperty('buffer'.toJS, null);
if (error != null) result.setProperty('error'.toJS, error.toJS);
scope.postMessage(result);
} else {
// Copy to an exact-length buffer, then transfer it (zero-copy).
final jsBuffer = Uint8List.fromList(out).buffer.toJS;
result.setProperty('buffer'.toJS, jsBuffer);
scope.postMessage(result, <JSAny>[jsBuffer].toJS);
}
}).toJS;
}