# Does JSAR Support Web Workers? Complete Implementation Guide

> Discover how JSAR supports Web Workers on Node.js using worker_threads. Explore the complete implementation guide and unlock powerful parallel processing for your applications.

- Repository: [M Creative Lab/jsar-runtime](https://github.com/m-creativelab/jsar-runtime)
- Tags: how-to-guide
- Published: 2026-03-06

---

**Yes, JSAR provides a full Web Workers implementation that mirrors the browser Worker API while running on top of Node.js `worker_threads`.**

The [m-creativelab/jsar-runtime](https://github.com/m-creativelab/jsar-runtime) repository includes a self-contained worker system that simulates the DOM Worker environment in a Node.js-based runtime. This allows JavaScript code written for browser Workers to execute unchanged within the JSAR platform.

## How JSAR Implements Web Workers

JSAR does not rely on browser-native Workers. Instead, it implements the entire Worker specification using Node.js threading primitives. The architecture bridges the Node.js `worker_threads` module with a browser-compatible API layer, complete with DOM events, script loading, and nested worker support.

The system is modularized across four key areas:

- **Worker lifecycle management** – Handles construction, message routing, and termination
- **Entry point bootstrapping** – Sets up the global scope inside the worker thread
- **Event system** – Provides DOM-compatible `MessageEvent` and `ErrorEvent` objects
- **Resource loading** – Integrates with JSAR's asset pipeline for script fetching

## Core Components of the Worker System

### WorkerImpl: The Public Interface

The [[`lib/webworkers/worker.ts`](https://github.com/m-creativelab/jsar-runtime/blob/main/lib/webworkers/worker.ts)](https://github.com/m-creativelab/jsar-runtime/blob/main/lib/webworkers/worker.ts) file exports the `WorkerImpl` class, which implements the standard Worker interface. This class exposes `onmessage`, `onerror`, `onmessageerror`, and methods like `postMessage()` and `terminate()`.

Key implementation details from the source:

- **Document requirement**: The constructor checks for the existence of `document` to ensure Workers are only created within browser-like environments
- **Blob URL support**: Detects `blob:` schemes and resolves underlying Blob sources via `resolveObjectURL`
- **Private initialization**: The `#initHandle()` method wires Node's `'message'`, `'messageerror'`, and `'error'` events to DOM-compatible event objects

When `worker.start()` is called, the class resolves the internal entry script ([`jsar-webworkers-entry.js`](https://github.com/m-creativelab/jsar-runtime/blob/main/jsar-webworkers-entry.js)) and spawns a Node `WorkerThreads.Worker` with a serialized `WorkerRequest` containing the script URL and base URI.

### Entry Script and WorkerContext

The [[`lib/webworkers/entry.ts`](https://github.com/m-creativelab/jsar-runtime/blob/main/lib/webworkers/entry.ts)](https://github.com/m-creativelab/jsar-runtime/blob/main/lib/webworkers/entry.ts) file serves as the bootstrap code executed inside each worker thread. Its responsibilities include:

1. Mapping `globalThis.postMessage` to `parentPort.postMessage` for host communication
2. Injecting `__WorkerImpl` into the global scope to enable **nested workers** (workers creating workers)
3. Instantiating a `WorkerContext` (JSAR's DOM shim) to provide `self` and other globals
4. Loading either inline script sources (from Blobs) or fetching external URLs via the resource loader

### Event Handling

Standard DOM event objects are re-exported from [[`lib/webworkers/events.ts`](https://github.com/m-creativelab/jsar-runtime/blob/main/lib/webworkers/events.ts)](https://github.com/m-creativelab/jsar-runtime/blob/main/lib/webworkers/events.ts). The implementation provides:

- `ErrorEvent` for uncaught exceptions
- `MessageEvent` for data passing between threads

These align with the [WHATWG Web Workers specification](https://html.spec.whatwg.org/multipage/workers.html), ensuring that event handlers like `worker.onmessage` receive objects with `data`, `origin`, and `ports` properties.

### Resource Loading

Workers share the same asset pipeline as the main JSAR runtime through [[`lib/runtime2/ResourceLoader.ts`](https://github.com/m-creativelab/jsar-runtime/blob/main/lib/runtime2/ResourceLoader.ts)](https://github.com/m-creativelab/jsar-runtime/blob/main/lib/runtime2/ResourceLoader.ts). The `ResourceLoaderOnTransmute` interface allows workers to fetch scripts and assets using the same resolution logic as the parent context, including support for custom protocols and transmutation hooks.

## Creating and Using Workers in JSAR

### Basic Worker Instantiation

To create a worker in JSAR, instantiate `WorkerImpl` with a script URL, register event handlers, and call `start()`:

```typescript
import { WorkerImpl } from 'jsar-runtime/lib/webworkers/worker';

// Create worker from a script file
const worker = new WorkerImpl('scripts/computation.js');

// Handle incoming messages
worker.onmessage = (event: MessageEvent) => {
  console.log('Received:', event.data);
};

worker.onerror = (event: ErrorEvent) => {
  console.error('Worker failed:', event.message, event.filename);
};

// Initialize the worker thread
worker.start();

// Send data to the worker
worker.postMessage({ type: 'CALCULATE', payload: [1, 2, 3] });

```

### Nested Workers via __WorkerImpl

JSAR supports spawning workers from within workers using the hidden `__WorkerImpl` global injected by the entry script:

```typescript
// Inside scripts/computation.js (running in worker context)
self.onmessage = (e) => {
  if (e.data.type === 'SPAWN_SUBWORKER') {
    // Create a nested worker
    const subWorker = new __WorkerImpl('scripts/sub-task.js');
    
    subWorker.onmessage = (msg) => {
      self.postMessage({ from: 'nested', result: msg.data });
    };
    
    subWorker.start();
    subWorker.postMessage(e.data.payload);
  }
};

```

This pattern enables parallel processing trees where parent workers delegate to child workers without blocking the main thread.

### Inline Workers with Blob URLs

For dynamic script generation, JSAR supports the Blob URL pattern:

```typescript
const workerScript = `
  self.onmessage = (e) => {
    const result = e.data.map(x => x * 2);
    self.postMessage(result);
  };
`;

const blob = new Blob([workerScript], { type: 'application/javascript' });
const blobUrl = URL.createObjectURL(blob);

const worker = new WorkerImpl(blobUrl);
worker.onmessage = (ev) => console.log('Doubled:', ev.data);
worker.start();
worker.postMessage([5, 10, 15]);

```

The `WorkerImpl` constructor detects the `blob:` protocol and extracts the underlying source code for execution in the worker context.

## Summary

- JSAR implements the complete Web Workers API using Node.js `worker_threads` as the underlying engine
- The `WorkerImpl` class in [`lib/webworkers/worker.ts`](https://github.com/m-creativelab/jsar-runtime/blob/main/lib/webworkers/worker.ts) provides the standard Worker interface with DOM-compatible events
- Workers can spawn nested workers using the `__WorkerImpl` global available in worker contexts
- Script loading supports both external URLs and inline Blob sources through the integrated ResourceLoader
- The implementation requires a DOM environment (checks for `document`) to maintain browser semantics

## Frequently Asked Questions

### Does JSAR support Web Workers?

Yes. JSAR includes a full Web Workers implementation that mirrors the browser API. The system uses Node.js `worker_threads` internally while exposing standard Worker methods like `postMessage()`, `terminate()`, and event handlers. The source code in [`lib/webworkers/worker.ts`](https://github.com/m-creativelab/jsar-runtime/blob/main/lib/webworkers/worker.ts) implements this interface completely.

### Can workers spawn other workers in JSAR?

Yes, JSAR supports nested workers. When a worker script executes, the entry script ([`lib/webworkers/entry.ts`](https://github.com/m-creativelab/jsar-runtime/blob/main/lib/webworkers/entry.ts)) injects `__WorkerImpl` into the global scope. This allows code running inside a worker to instantiate child workers using `new __WorkerImpl(url)`, enabling hierarchical parallel processing.

### How does JSAR handle worker script loading?

JSAR uses its `ResourceLoader` system (from [`lib/runtime2/ResourceLoader.ts`](https://github.com/m-creativelab/jsar-runtime/blob/main/lib/runtime2/ResourceLoader.ts)) to resolve worker scripts. The `WorkerImpl` constructor accepts standard URLs or Blob URLs. For Blob sources, the implementation resolves the underlying source code via `resolveObjectURL`. The entry script then either evaluates the inline source or fetches the external resource through the runtime's asset pipeline.

### Is the JSAR Worker API compatible with standard browser Workers?

Yes. The implementation aims for compatibility with the [WHATWG Web Workers specification](https://html.spec.whatwg.org/multipage/workers.html). Event objects (`MessageEvent`, `ErrorEvent`), the `self` global scope, and method signatures match browser behavior. Code written for standard browser Workers typically runs in JSAR without modification, provided it does not rely on browser-specific APIs unavailable in the JSAR runtime.