Skip to main content

Realms and Multiple Contexts

QuickJS supports multiple JavaScript contexts (realms) within a single runtime. This powerful feature allows you to create isolated JavaScript environments that can optionally share objects, similar to how iframes work in web browsers.

Understanding Contexts and Realms

What is a Context?

A JSContext represents a JavaScript realm - a complete JavaScript environment with:
  • Its own global object
  • Its own set of built-in objects (Object, Array, etc.)
  • Its own prototype chains
  • Its own exception state

What is a Runtime?

A JSRuntime represents an isolated JavaScript engine instance with:
  • A single garbage collector
  • A shared memory heap
  • Multiple contexts that can share objects
  • No thread-safety (single-threaded execution)

Creating Multiple Contexts

Independent Contexts

You can create multiple independent contexts within the same runtime:

Shared Contexts

Use JS_DupContext() to create contexts that share the same realm:

Sharing Objects Between Contexts

Transferring Objects

Objects can be shared between contexts in the same runtime:

Important Rules

  1. Same Runtime Required: Objects can only be shared between contexts in the same runtime
  2. Reference Counting: Shared objects use reference counting - free them in each context that uses them
  3. Prototype Chains: Each context has its own prototypes, even for shared objects
  4. Global Objects: Each context has its own global object unless created with JS_DupContext()

Use Cases

Sandboxing

Create isolated environments for untrusted code:

Plugin Systems

Isolate plugins in separate contexts:

Web Worker Simulation

Simulate Web Worker behavior:

Testing Frameworks

Isolate test cases:

Performance Considerations

Memory Usage

  • Each context has its own global object and built-in objects
  • Multiple contexts increase memory usage
  • Use JS_DupContext() when you need shared state to reduce overhead
  • Consider using JS_NewContextRaw() with minimal intrinsics for worker contexts

Garbage Collection

  • All contexts in a runtime share the same garbage collector
  • GC runs affect all contexts in the runtime
  • Objects shared between contexts are only freed when all references are gone

Context Switching

  • Switching between contexts is lightweight
  • No context switch overhead within the same runtime
  • Multiple runtimes require separate processes/threads

Best Practices

  1. One Runtime Per Thread: Never share a runtime across threads
  2. Free in Reverse Order: Free contexts before the runtime
  3. Clean Exception State: Handle exceptions before switching contexts
  4. Document Context Ownership: Clearly document which context owns which objects
  5. Use Const Correctness: Use JSValueConst for parameters that don’t transfer ownership
  6. Limit Context Count: Each context adds overhead; don’t create too many
  7. Consider Context Pools: Reuse contexts instead of creating/destroying frequently

Limitations

  • No Thread Safety: Contexts cannot be safely accessed from multiple threads
  • No Cross-Runtime Sharing: Objects cannot be shared between different runtimes
  • Single GC: All contexts in a runtime are paused during garbage collection
  • Prototype Isolation: Modifying built-in prototypes in one context doesn’t affect others
  • JS_NewContext() - Create a new independent context
  • JS_DupContext() - Create a context that shares the same realm
  • JS_FreeContext() - Free a context
  • JS_GetRuntime() - Get the runtime associated with a context
  • JS_GetGlobalObject() - Get a context’s global object
  • JS_DupValue() - Duplicate a value for sharing between contexts