This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
The mORMot scripting layer provides thread-safe JavaScript engine integration for client and server-side scripting. It enables user-defined workflows and automation in applications built with the mORMot framework.
- QuickJS (
mormot.script.quickjs.pas) - Small, standalone JavaScript interpreter ideal for client-side execution - SpiderMonkey (planned) - Mozilla's JavaScript interpreter with JIT compilation for high-performance server scenarios
Note: SpiderMonkey support is referenced but not yet implemented in this directory.
-
Abstract Core (
mormot.script.core.pas- 731 lines)- Engine-agnostic base classes and interfaces
- Thread-safe engine pooling via
TThreadSafeManager - Remote debugging infrastructure (Firefox DevTools protocol)
- Worker thread management
-
Engine Implementation (
mormot.script.quickjs.pas- 30 lines)- Currently minimal (implementation pending)
- Will implement QuickJS-specific bindings
Per-thread JavaScript execution context. Never instantiate directly - always obtained via TThreadSafeManager.ThreadSafeEngine.
Critical Properties:
Runtime/Context- Opaque handles to native JS runtime/context (pointers work across all engines)ThreadID- Owning thread (engine instances are NOT thread-safe across threads)ContentVersion- Incremental counter for hot-reload detectionNeverExpire- Prevents automatic expiration cleanup
Lifecycle Hooks (override in implementations):
AfterCreate- Called outside Manager lock after constructionBeforeDestroy- Called outside Manager lock before destructionDoBeginRequest/DoEndRequest- FPU state management, embraced byThreadSafeCall()From(aContext)- Static method to retrieve engine from execution context
Manages a pool of per-thread engine instances with automatic expiration.
Core Methods:
ThreadSafeEngine(ThreadData, Tag)- Get or create engine for current threadEngine(ThreadID)- Lookup engine by thread ID (returns nil if unknown)InitializeMainEngine- Creates non-pooled main engine (call once from main thread)NewEngine- Create standalone engine outside pool (caller must free)
Expiration Management:
EngineExpireTimeOutMinutes(default: 0 = never) - Auto-recreate engines to prevent JS memory leaks- Production recommendation: 240 minutes (4 hours)
- Engines with
NeverExpire=trueare exempt
Debugging:
StartDebugger(Port)- Listen for Firefox DevTools connections (default port: 6000)StopDebugger- Shutdown debugger threadPauseDebuggerOnFirstStep- Break on first line of script
Events:
OnNewEngine- Triggered after creating engine (customize initial state)OnGetName- Provide debug name for engineOnGetWebAppRootPath- Set web app root for debugger contextOnDebuggerInit- Configure debugger when it connects
- Each thread gets its own
TThreadSafeEngineinstance - Manager maintains a locked list (
TSynObjectListLightLocked) mappingThreadID → Engine - NEVER share engine instances between threads
DoBeginRequest/DoEndRequest save/restore FPU flags to prevent corruption from JS execution (especially for SpiderMonkey). Automatically handled by ThreadSafeCall().
// Application code increments version when scripts change
Manager.ContentVersion := Manager.ContentVersion + 1;
// Framework auto-detects stale engines and recreates them
Engine := Manager.ThreadSafeEngine; // May return new instance
if Engine.ContentVersion <> Manager.ContentVersion then
// Engine was recreated - reload your scriptsImplements Firefox's remote debugging protocol (not Chrome DevTools). See: https://firefox-source-docs.mozilla.org/devtools/backend/protocol.html
Manager.StartDebugger('6000'); // Default port
// Connect Firefox DevTools to localhost:6000IRemoteDebugger- Debugger server implementationIWorkerManager- Worker thread coordination
📖 Full Documentation: See SAD Chapter 22: Scripting Engine for complete examples.
- Abstract base classes (
TThreadSafeEngine,TThreadSafeManager) - Thread pooling and lifecycle management
- Debugging infrastructure (Firefox DevTools protocol)
- Worker thread interfaces
- Low-level QuickJS bindings (
mormot.lib.quickjs) - fully functional withJS_NewRuntime,JS_Eval, etc.
- High-level QuickJS wrapper (
mormot.script.quickjs) - convenience layer - TQuickJSVariant custom variant type for late-binding
- ORM/SOA integration helpers
- SpiderMonkey integration (for high-performance server scenarios)
- JIT compilation support
uses
mormot.core.base, // Base types
mormot.core.os, // OS abstractions
mormot.core.unicode, // UTF-8 handling
mormot.core.text, // Text utilities
mormot.core.data, // Data structures
mormot.core.rtti, // RTTI integration
mormot.core.json, // JSON serialization
mormot.lib.static; // Static library loadingOnLog: TSynLogProc- Redirect to mORMot's TSynLog- Manager logs engine creation/destruction if
OnLogassigned
var
Manager: TThreadSafeManager;
Engine: TThreadSafeEngine;
begin
Manager := TQuickJSManager.Create(TQuickJSEngine); // Hypothetical
try
// In request handler thread:
Engine := Manager.ThreadSafeEngine;
Engine.ThreadSafeCall(
procedure(E: TThreadSafeEngine)
begin
// Execute script here
end);
finally
Manager.Free; // Frees all pooled engines
end;
end;Manager.InitializeMainEngine;
Manager.MainEngine.ThreadSafeCall(...);Manager.OnNewEngine :=
procedure(Engine: TThreadSafeEngine)
begin
// Register custom native functions
// Set global objects
// Load standard libraries
end;- Never call engine constructors directly - Use
TThreadSafeManager.ThreadSafeEngine - Thread affinity is strict - One engine per thread, never shared
- Low-level QuickJS is available - Use
mormot.lib.quickjsfor direct JS execution - High-level wrapper in development -
mormot.script.quickjsconvenience layer coming - Debugging uses Firefox protocol - Not Chrome DevTools
- ContentVersion drives hot reload - Application responsibility to increment
- FPU corruption prevention - Always use
ThreadSafeCall()for script execution - Expiration prevents memory leaks - Set
EngineExpireTimeOutMinutesfor long-running servers
📖 SAD Documentation: SAD Chapter 22: Scripting Engine - comprehensive guide with code examples
External References:
- Main README:
/mnt/w/mORMot2/README.md - Framework docs: https://synopse.info/files/doc/mORMot2.html
- QuickJS upstream: https://bellard.org/quickjs/
- Firefox debugging protocol: https://firefox-source-docs.mozilla.org/devtools/backend/protocol.html
Last Updated: 2025-10-10 (based on source analysis) Status: Abstract layer complete, engine implementations pending License: MPL/GPL/LGPL tri-license