Lodash cloneDeep with Web Worker Instances

When a Web Worker instance is passed into the Lodash _.cloneDeep method, Lodash fails to duplicate the actual background thread because active runtime instances cannot be serialized or duplicated. Instead of throwing an error, Lodash checks the worker's internal type tag against its whitelist of cloneable objects; because Worker is not supported, _.cloneDeep will either return an empty object ({}) if the worker is cloned directly at the root, or preserve the original reference if it is nested inside another object.

Why Web Workers Cannot Be Cloned

A Web Worker is not a plain data structure; it represents an active operating system thread or browser background task with its own execution context, event loop, and memory heap. The JavaScript runtime does not allow copying thread execution states or native host bindings.

While the native HTML structured clone algorithm (structuredClone()) explicitly throws a DataCloneError when encountering an uncloneable host object like a Worker, Lodash handles deep cloning through its own custom heuristics without throwing exceptions.

How Lodash Processes the Worker Internally

Lodash uses an internal function named baseClone to recursively copy values. The process for a Worker instance proceeds as follows:

  1. Tag Detection: Lodash resolves the internal object tag using Object.prototype.toString.call(value). For a Web Worker, this evaluates to "[object Worker]".
  2. Whitelist Verification: Lodash maintains an internal lookup table called cloneableTags. This table explicitly supports standard data types such as Object, Array, Map, Set, Date, RegExp, ArrayBuffer, and TypedArrays.
  3. Fallback Logic: Because "[object Worker]" is absent from cloneableTags, Lodash classifies the instance as an uncloneable object and executes its fallback condition:
if (!cloneableTags[tag]) {
    return object ? value : {};
}

Root-Level vs. Nested Behavior

Because of Lodash's internal check against the parent object argument, the output changes depending on how the worker is passed:

Best Practices

Relying on _.cloneDeep around objects that manage background threads can introduce unexpected side effects or silent bugs due to shallow reference sharing or empty object replacements.