Documentation
¶
Overview ¶
Package runtime provides JavaScript execution capabilities for LESS plugins.
This package implements a bridge between Go and Node.js, allowing LESS plugins written in JavaScript to be executed while maintaining performance through shared memory buffer transfer.
Architecture Overview ¶
The runtime uses a hybrid approach combining Node.js for JavaScript execution with shared memory for efficient data transfer:
- Go spawns a persistent Node.js process running plugin-host.js
- Commands are sent via stdin/stdout (JSON protocol)
- Large data (ASTs) is transferred via shared memory buffers
- Node.js executes plugin JavaScript and writes results back
This approach provides:
- Perfect JavaScript compatibility (real Node.js)
- Fast V8 execution (10x faster than embedded runtimes like goja)
- Zero-copy data transfer (no JSON serialization for ASTs)
- Simple plugin loading (native require())
Usage
rt, err := runtime.NewNodeJSRuntime()
if err != nil {
log.Fatal(err)
}
defer rt.Stop()
// Send a command
response, err := rt.SendCommand(runtime.Command{
Cmd: "ping",
})
if err != nil {
log.Fatal(err)
}
IPC Protocol ¶
Commands are JSON objects sent via stdin:
{"id": 1, "cmd": "ping"}
{"id": 2, "cmd": "loadPlugin", "path": "./plugin.js"}
{"id": 3, "cmd": "callFunction", "functionID": "myFunc", "args": [...]}
Responses are JSON objects received via stdout:
{"id": 1, "success": true, "result": "pong"}
{"id": 2, "success": true, "result": {"functions": ["myFunc"]}}
{"id": 3, "success": false, "error": "function not found"}
Index ¶
- Constants
- Variables
- func ClearJSFunctionDefinitionCache()
- func ClearJSFunctionDefinitionCacheForRuntime(runtime *NodeJSRuntime)
- func GetContextVersion() uint64
- func GetJSFunctionDefinitionCacheStats() int
- func IncrementContextVersion()
- func WritePrefetchedVariables(variables map[string]any) []byte
- type ASTFlattener
- type ASTUnflattener
- type BaseNode
- type BatchCall
- type BatchCallResult
- type BinaryVariableWriter
- type CallbackHandler
- type CallbackRequest
- type Command
- type EvalContextProvider
- type FileManagerCollection
- func (fmc *FileManagerCollection) FileManagerCount() int
- func (fmc *FileManagerCollection) FindSupportingManager(filename, currentDirectory string, options map[string]any) *JSFileManager
- func (fmc *FileManagerCollection) GetFileManagers() []*JSFileManager
- func (fmc *FileManagerCollection) LoadFile(filename, currentDirectory string, options map[string]any) (*LoadedFile, error)
- func (fmc *FileManagerCollection) RefreshFileManagers() error
- type FileManagerInfo
- type FlatAST
- func (f *FlatAST) AddNode(node FlatNode) uint32
- func (f *FlatAST) AddProperties(props map[string]any) (uint32, uint32)
- func (f *FlatAST) AddString(s string) uint32
- func (f *FlatAST) GetProperties(offset, length uint32) map[string]any
- func (f *FlatAST) GetString(idx uint32) string
- func (f *FlatAST) ToBytes() ([]byte, error)
- type FlatNode
- type GenericNode
- type JSFileManager
- type JSFunctionDefinition
- func (jf *JSFunctionDefinition) CacheStats() int
- func (jf *JSFunctionDefinition) Call(args ...any) (any, error)
- func (jf *JSFunctionDefinition) CallCtx(ctx any, args ...any) (any, error)
- func (jf *JSFunctionDefinition) CallWithContext(evalContext EvalContextProvider, args ...any) (any, error)
- func (jf *JSFunctionDefinition) ClearCache()
- func (jf *JSFunctionDefinition) IPCMode() JSIPCMode
- func (jf *JSFunctionDefinition) IsContextFree() bool
- func (jf *JSFunctionDefinition) Name() string
- func (jf *JSFunctionDefinition) NeedsEvalArgs() bool
- func (jf *JSFunctionDefinition) SetContextFree(contextFree bool)
- type JSFunctionOption
- type JSIPCMode
- type JSPluginLoader
- func (pl *JSPluginLoader) CallFunction(name string, args []any) (any, error)
- func (pl *JSPluginLoader) ClearCache()
- func (pl *JSPluginLoader) EvalPlugin(contents string, newEnv any, importManager any, pluginArgs map[string]any, ...) any
- func (pl *JSPluginLoader) GetLoadedPlugins() map[string]*Plugin
- func (pl *JSPluginLoader) GetPlugin(cacheKey string) (*Plugin, bool)
- func (pl *JSPluginLoader) GetRegisteredFunctions() ([]string, error)
- func (pl *JSPluginLoader) GetVisitors() ([]map[string]any, error)
- func (pl *JSPluginLoader) LoadPlugin(path, currentDirectory string, context map[string]any, environment any, ...) any
- func (pl *JSPluginLoader) LoadPluginSync(path, currentDirectory string, context map[string]any, environment any, ...) any
- type JSPostProcessor
- type JSPreProcessor
- type JSResultNode
- type JSVisitor
- type LoadedFile
- type Node
- type NodeJSRuntime
- func (rt *NodeJSRuntime) AttachBuffer(shm *SharedMemory) error
- func (rt *NodeJSRuntime) BatchCallFunctions(calls []BatchCall) (map[string]BatchCallResult, error)
- func (rt *NodeJSRuntime) BatchCallFunctionsAndCache(calls []BatchCall) (int, error)
- func (rt *NodeJSRuntime) CallFunctionViaSHM(functionName string, args ...any) (any, error)
- func (rt *NodeJSRuntime) ClearCachedResultsForFunction(funcName string)
- func (rt *NodeJSRuntime) ClearFunctionCache()
- func (rt *NodeJSRuntime) CloseSHMProtocol() error
- func (rt *NodeJSRuntime) CreateSharedMemory(size int) (*SharedMemory, error)
- func (rt *NodeJSRuntime) DecrementScopeDepth()
- func (rt *NodeJSRuntime) DestroySharedMemory(shm *SharedMemory) error
- func (rt *NodeJSRuntime) DetachBuffer(key string) error
- func (rt *NodeJSRuntime) Echo(value any) (any, error)
- func (rt *NodeJSRuntime) Error() error
- func (rt *NodeJSRuntime) FunctionCacheSize() int
- func (rt *NodeJSRuntime) GetCachedResult(key string) (any, bool)
- func (rt *NodeJSRuntime) GetPrefetchBuffer(size int) (*SharedMemory, error)
- func (rt *NodeJSRuntime) GetPrefetchCache(frameCount int, frameHash uint64) []byte
- func (rt *NodeJSRuntime) GetPrefetchCacheStats() (int, int, bool)
- func (rt *NodeJSRuntime) GetSHMProtocol() *SharedMemoryProtocol
- func (rt *NodeJSRuntime) GetScopeDepth() int
- func (rt *NodeJSRuntime) GetScopeSeq() int64
- func (rt *NodeJSRuntime) IncrementScopeDepth()
- func (rt *NodeJSRuntime) IncrementScopeSeq() int64
- func (rt *NodeJSRuntime) InitSHMProtocol() error
- func (rt *NodeJSRuntime) InvalidatePrefetchCache()
- func (rt *NodeJSRuntime) IsAlive() bool
- func (rt *NodeJSRuntime) Ping() error
- func (rt *NodeJSRuntime) PreloadVariables(frames []any) error
- func (rt *NodeJSRuntime) ReadASTBuffer(shm *SharedMemory) (*FlatAST, error)
- func (rt *NodeJSRuntime) RegisterCallback(name string, handler CallbackHandler)
- func (rt *NodeJSRuntime) SendCommand(cmd Command) (Response, error)
- func (rt *NodeJSRuntime) SendCommandFireAndForget(cmd Command) error
- func (rt *NodeJSRuntime) SendCommandWithContext(ctx context, cmd Command) (Response, error)
- func (rt *NodeJSRuntime) SetCachedResult(key string, value any)
- func (rt *NodeJSRuntime) SetPrefetchCache(binaryData []byte, frameCount int, frameHash uint64, varCount int)
- func (rt *NodeJSRuntime) SharedMemoryManager() *SharedMemoryManager
- func (rt *NodeJSRuntime) Start() error
- func (rt *NodeJSRuntime) Stop() error
- func (rt *NodeJSRuntime) UnregisterCallback(name string)
- func (rt *NodeJSRuntime) UseSHMProtocol() bool
- func (rt *NodeJSRuntime) WriteASTBuffer(flat *FlatAST) (*SharedMemory, error)
- type NodeReplacement
- type NodeTypeID
- type ParseASTBufferResult
- type Plugin
- type PluginFunctionRegistry
- func (r *PluginFunctionRegistry) ClearJSFunctions()
- func (r *PluginFunctionRegistry) Get(name string) any
- func (r *PluginFunctionRegistry) GetBuiltinRegistry() any
- func (r *PluginFunctionRegistry) GetJSFunctionNames() []string
- func (r *PluginFunctionRegistry) HasJSFunction(name string) bool
- func (r *PluginFunctionRegistry) RefreshFromRuntime() error
- func (r *PluginFunctionRegistry) RegisterJSFunction(name string)
- func (r *PluginFunctionRegistry) RegisterJSFunctions(names []string)
- type PluginLoadResult
- type PluginScope
- func (ps *PluginScope) AddFileManager(manager any)
- func (ps *PluginScope) AddFunction(name string, fn *JSFunctionDefinition)
- func (ps *PluginScope) AddPlugin(plugin *Plugin, runtime *NodeJSRuntime)
- func (ps *PluginScope) AddPostProcessor(processor any, priority int)
- func (ps *PluginScope) AddPreProcessor(processor any, priority int)
- func (ps *PluginScope) AddVisitor(visitor *JSVisitor)
- func (ps *PluginScope) CreateChild() *PluginScope
- func (ps *PluginScope) GetAllFunctions() map[string]*JSFunctionDefinition
- func (ps *PluginScope) GetFileManagers() []any
- func (ps *PluginScope) GetLocalFunction(name string) (*JSFunctionDefinition, bool)
- func (ps *PluginScope) GetLocalVisitors() []*JSVisitor
- func (ps *PluginScope) GetPlugins() []*Plugin
- func (ps *PluginScope) GetPostEvalVisitors() []*JSVisitor
- func (ps *PluginScope) GetPostProcessors() []any
- func (ps *PluginScope) GetPreEvalVisitors() []*JSVisitor
- func (ps *PluginScope) GetPreProcessors() []any
- func (ps *PluginScope) GetVisitors() []*JSVisitor
- func (ps *PluginScope) IsRoot() bool
- func (ps *PluginScope) LookupFunction(name string) (*JSFunctionDefinition, bool)
- func (ps *PluginScope) Parent() *PluginScope
- func (ps *PluginScope) Release()
- type PrefetchCache
- type ProcessorInfo
- type ProcessorManager
- func (pm *ProcessorManager) GetPostProcessors() []*JSPostProcessor
- func (pm *ProcessorManager) GetPreProcessors() []*JSPreProcessor
- func (pm *ProcessorManager) PostProcessorCount() int
- func (pm *ProcessorManager) PreProcessorCount() int
- func (pm *ProcessorManager) RefreshProcessors() error
- func (pm *ProcessorManager) RunPostProcessors(css string, options map[string]any) (string, error)
- func (pm *ProcessorManager) RunPreProcessors(input string, options map[string]any) (string, error)
- type ProcessorResult
- type ProcessorWithPriority
- type Response
- type RuntimeOption
- type ScopedPluginManager
- type ScopedVisitorIterator
- type SerializeNodeResult
- type SharedMemory
- func (s *SharedMemory) Close() error
- func (s *SharedMemory) Data() []byte
- func (s *SharedMemory) Key() string
- func (s *SharedMemory) Path() string
- func (s *SharedMemory) Read(offset, length int) ([]byte, error)
- func (s *SharedMemory) ReadAll() ([]byte, error)
- func (s *SharedMemory) Size() int
- func (s *SharedMemory) Sync() error
- func (s *SharedMemory) Write(offset int, data []byte) error
- func (s *SharedMemory) WriteAll(data []byte) error
- type SharedMemoryManager
- func (m *SharedMemoryManager) Create(size int) (*SharedMemory, error)
- func (m *SharedMemoryManager) Destroy(key string) error
- func (m *SharedMemoryManager) DestroyAll() error
- func (m *SharedMemoryManager) Get(key string) *SharedMemory
- func (m *SharedMemoryManager) Open(key string) (*SharedMemory, error)
- type SharedMemoryProtocol
- func (p *SharedMemoryProtocol) ClearResponse()
- func (p *SharedMemoryProtocol) Close() error
- func (p *SharedMemoryProtocol) GetArgsSectionInfo() (offset, size uint32)
- func (p *SharedMemoryProtocol) GetControlBlockLayout() map[string]uint32
- func (p *SharedMemoryProtocol) GetFunctionID(name string) (uint32, bool)
- func (p *SharedMemoryProtocol) GetFunctionName(id uint32) (string, bool)
- func (p *SharedMemoryProtocol) GetResultsSectionInfo() (offset, size uint32)
- func (p *SharedMemoryProtocol) GetSectionOffsets() map[string]uint32
- func (p *SharedMemoryProtocol) GetVariablesSectionInfo() (offset, size uint32)
- func (p *SharedMemoryProtocol) IsJSReady() bool
- func (p *SharedMemoryProtocol) Key() string
- func (p *SharedMemoryProtocol) Path() string
- func (p *SharedMemoryProtocol) PrepareCall(functionID uint32, argCount int) error
- func (p *SharedMemoryProtocol) ReadResult() (any, error)
- func (p *SharedMemoryProtocol) RegisterFunction(name string) uint32
- func (p *SharedMemoryProtocol) SignalRequest() error
- func (p *SharedMemoryProtocol) WaitForResponse(maxWaitMs int) (bool, error)
- func (p *SharedMemoryProtocol) WriteArg(argIndex int, value any) (uint32, error)
- func (p *SharedMemoryProtocol) WriteVariables(variables map[string]any) error
- type UnifiedMessage
- type VisitorInfo
- type VisitorManager
- func (vm *VisitorManager) GetPostEvalVisitors() []*JSVisitor
- func (vm *VisitorManager) GetPreEvalVisitors() []*JSVisitor
- func (vm *VisitorManager) ParseASTBuffer(shm *SharedMemory) (*ParseASTBufferResult, error)
- func (vm *VisitorManager) RefreshVisitors() error
- func (vm *VisitorManager) RunPostEvalVisitors(node interface{}) (*VisitorResult, error)
- func (vm *VisitorManager) RunPreEvalVisitors(node interface{}) (*VisitorResult, error)
- func (vm *VisitorManager) SerializeNode(node interface{}) (*SerializeNodeResult, error)
- type VisitorReplacementSet
- type VisitorResult
Constants ¶
const ( FlagParens uint16 = 1 << 0 FlagParensInOp uint16 = 1 << 1 FlagVisible uint16 = 1 << 2 FlagInvisible uint16 = 1 << 3 FlagVisibleSet uint16 = 1 << 4 FlagHasFileInfo uint16 = 1 << 5 FlagHasIndex uint16 = 1 << 6 )
FlatNode flags
const ( FlatASTMagic uint32 = 0x4C455353 // "LESS" FlatASTVersion uint32 = 1 FlatNodeSize int = 24 // bytes per FlatNode )
Binary format constants
const ( PrefetchMagic uint32 = 0x50524546 // "PREF" PrefetchVersion uint32 = 1 // Variable types VarTypeNull byte = 0 VarTypeDimension byte = 1 VarTypeColor byte = 2 VarTypeQuoted byte = 3 VarTypeKeyword byte = 4 VarTypeExpression byte = 5 VarTypeAnonymous byte = 6 VarTypeVariable byte = 7 // Variable reference (name only, needs lookup) )
const ( // Section sizes ControlBlockSize = 4 * 1024 // 4KB VariablesSectionSize = 1 * 1024 * 1024 // 1MB ArgsSectionSize = 1 * 1024 * 1024 // 1MB ResultsSectionSize = 1 * 1024 * 1024 // 1MB ErrorBufferSize = 64 * 1024 // 64KB TotalSHMSize = ControlBlockSize + VariablesSectionSize + ArgsSectionSize + ResultsSectionSize + ErrorBufferSize // Section offsets ControlBlockOffset = 0 VariablesSectionOffset = ControlBlockSize ArgsSectionOffset = VariablesSectionOffset + VariablesSectionSize ResultsSectionOffset = ArgsSectionOffset + ArgsSectionSize ErrorBufferOffset = ResultsSectionOffset + ResultsSectionSize // Control block field offsets (relative to control block start) OffsetRequestReady = 0x000 OffsetResponseReady = 0x004 OffsetFunctionID = 0x008 OffsetArgCount = 0x00C OffsetArgOffsets = 0x010 // Array of 16 uint32s OffsetResultOffset = 0x050 OffsetResultSize = 0x054 OffsetErrorFlag = 0x058 OffsetErrorOffset = 0x05C OffsetErrorSize = 0x060 OffsetShutdown = 0x064 OffsetJSReady = 0x068 MaxArgs = 16 // Argument types for binary serialization ArgTypeNull = 0 ArgTypeDimension = 1 ArgTypeColor = 2 ArgTypeQuoted = 3 ArgTypeKeyword = 4 ArgTypeExpression = 5 ArgTypeAnonymous = 6 ArgTypeVariable = 7 ArgTypeNumber = 8 ArgTypeBoolean = 9 ArgTypeCall = 10 )
Variables ¶
var TypeNameToID = func() map[string]NodeTypeID { m := make(map[string]NodeTypeID) for id, name := range TypeNames { m[name] = id } return m }()
TypeNameToID maps string type names to their IDs.
var TypeNames = map[NodeTypeID]string{ TypeUnknown: "Unknown", TypeAnonymous: "Anonymous", TypeAssignment: "Assignment", TypeAtRule: "AtRule", TypeAttribute: "Attribute", TypeCall: "Call", TypeColor: "Color", TypeCombinator: "Combinator", TypeComment: "Comment", TypeCondition: "Condition", TypeContainer: "Container", TypeDeclaration: "Declaration", TypeDetachedRuleset: "DetachedRuleset", TypeDimension: "Dimension", TypeElement: "Element", TypeExpression: "Expression", TypeExtend: "Extend", TypeImport: "Import", TypeJavaScript: "JavaScript", TypeKeyword: "Keyword", TypeMedia: "Media", TypeMixinCall: "MixinCall", TypeMixinDefinition: "MixinDefinition", TypeNamespaceValue: "NamespaceValue", TypeNegative: "Negative", TypeOperation: "Operation", TypeParen: "Paren", TypeProperty: "Property", TypeQueryInParens: "QueryInParens", TypeQuoted: "Quoted", TypeRuleset: "Ruleset", TypeSelector: "Selector", TypeSelectorList: "SelectorList", TypeUnicodeDescriptor: "UnicodeDescriptor", TypeUnit: "Unit", TypeURL: "URL", TypeValue: "Value", TypeVariable: "Variable", TypeVariableCall: "VariableCall", TypeNode: "Node", }
TypeNames maps type IDs to their string names (for JavaScript compatibility).
Functions ¶
func ClearJSFunctionDefinitionCache ¶
func ClearJSFunctionDefinitionCache()
ClearJSFunctionDefinitionCache clears all cached JSFunctionDefinition objects. This should be called when shutting down or when you need to force fresh objects.
func ClearJSFunctionDefinitionCacheForRuntime ¶
func ClearJSFunctionDefinitionCacheForRuntime(runtime *NodeJSRuntime)
ClearJSFunctionDefinitionCacheForRuntime clears cached JSFunctionDefinition objects for a specific runtime instance. This should be called when a runtime is stopped.
func GetContextVersion ¶
func GetContextVersion() uint64
GetContextVersion returns the current context version.
func GetJSFunctionDefinitionCacheStats ¶
func GetJSFunctionDefinitionCacheStats() int
GetJSFunctionDefinitionCacheStats returns the number of cached JSFunctionDefinition objects.
func IncrementContextVersion ¶
func IncrementContextVersion()
IncrementContextVersion should be called when frames are pushed/popped to invalidate the context cache.
func WritePrefetchedVariables ¶
WritePrefetchedVariables writes a map of prefetched variables to binary format. Returns the binary buffer ready to be written to shared memory.
Types ¶
type ASTFlattener ¶
type ASTFlattener struct {
// contains filtered or unexported fields
}
ASTFlattener converts Go AST nodes to FlatAST format.
func NewASTFlattener ¶
func NewASTFlattener() *ASTFlattener
NewASTFlattener creates a new AST flattener.
func (*ASTFlattener) Flatten ¶
func (af *ASTFlattener) Flatten(root any) (*FlatAST, error)
Flatten flattens an entire AST starting from the root.
func (*ASTFlattener) FlattenNode ¶
func (af *ASTFlattener) FlattenNode(node any, parentIndex uint32) (uint32, error)
FlattenNode flattens a single node and its children recursively. Returns the index of the flattened node.
type ASTUnflattener ¶
type ASTUnflattener struct {
// contains filtered or unexported fields
}
ASTUnflattener reconstructs AST nodes from FlatAST format.
func NewASTUnflattener ¶
func NewASTUnflattener(flat *FlatAST) *ASTUnflattener
NewASTUnflattener creates a new AST unflattener.
func (*ASTUnflattener) Unflatten ¶
func (au *ASTUnflattener) Unflatten() (*GenericNode, error)
Unflatten reconstructs the AST from the flat representation. Returns the root GenericNode.
type BaseNode ¶
type BaseNode interface {
GetNode() *Node
}
BaseNode interface for nodes that embed *Node
type BatchCall ¶
type BatchCall struct {
// Key is a unique identifier for this call (e.g., "funcName:arg1|arg2")
// Used to correlate requests with responses in the batch result map.
Key string `json:"key"`
// Name is the function name to call
Name string `json:"name"`
// Args are the serialized arguments for the function
Args []any `json:"args"`
// Context is the optional evaluation context for variable lookups
Context map[string]any `json:"context,omitempty"`
}
BatchCall represents a single function call in a batch. This is used by BatchCallFunctions to reduce IPC overhead.
type BatchCallResult ¶
type BatchCallResult struct {
// Success indicates if the call succeeded
Success bool `json:"success"`
// Result is the function return value (if successful)
Result any `json:"result,omitempty"`
// Error is the error message (if failed)
Error string `json:"error,omitempty"`
}
BatchCallResult represents the result of a single call in a batch.
type BinaryVariableWriter ¶
type BinaryVariableWriter struct {
// contains filtered or unexported fields
}
BinaryVariableWriter writes variables in binary format to a buffer.
func NewBinaryVariableWriter ¶
func NewBinaryVariableWriter() *BinaryVariableWriter
NewBinaryVariableWriter creates a new binary variable writer.
func (*BinaryVariableWriter) Bytes ¶
func (w *BinaryVariableWriter) Bytes() []byte
Bytes returns the written buffer.
func (*BinaryVariableWriter) Reset ¶
func (w *BinaryVariableWriter) Reset()
Reset clears the buffer for reuse.
func (*BinaryVariableWriter) WriteHeader ¶
func (w *BinaryVariableWriter) WriteHeader(varCount uint32)
WriteHeader writes the prefetch buffer header.
func (*BinaryVariableWriter) WriteVariable ¶
func (w *BinaryVariableWriter) WriteVariable(name string, decl any) (int, error)
WriteVariable writes a single variable to the buffer. Returns the number of bytes written.
type CallbackHandler ¶
CallbackHandler is a function that handles callbacks from Node.js.
type CallbackRequest ¶
type CallbackRequest struct {
ID int64 `json:"id"`
Callback string `json:"callback"`
Data any `json:"data,omitempty"`
}
CallbackRequest represents a callback request from Node.js to Go. This is used for on-demand variable lookup during function execution.
type Command ¶
type Command struct {
ID int64 `json:"id"`
Cmd string `json:"cmd"`
Data any `json:"data,omitempty"`
}
Command represents a command sent to the Node.js process.
type EvalContextProvider ¶
EvalContextProvider is an interface for objects that can provide evaluation context for JavaScript plugin functions that need to access variables.
type FileManagerCollection ¶
type FileManagerCollection struct {
// contains filtered or unexported fields
}
FileManagerCollection manages JavaScript file managers for a plugin loader.
func NewFileManagerCollection ¶
func NewFileManagerCollection(runtime *NodeJSRuntime) *FileManagerCollection
NewFileManagerCollection creates a new file manager collection.
func (*FileManagerCollection) FileManagerCount ¶
func (fmc *FileManagerCollection) FileManagerCount() int
FileManagerCount returns the number of registered file managers.
func (*FileManagerCollection) FindSupportingManager ¶
func (fmc *FileManagerCollection) FindSupportingManager(filename, currentDirectory string, options map[string]any) *JSFileManager
FindSupportingManager finds the first file manager that supports the given file. Returns nil if no file manager supports the file.
func (*FileManagerCollection) GetFileManagers ¶
func (fmc *FileManagerCollection) GetFileManagers() []*JSFileManager
GetFileManagers returns all registered file managers.
func (*FileManagerCollection) LoadFile ¶
func (fmc *FileManagerCollection) LoadFile(filename, currentDirectory string, options map[string]any) (*LoadedFile, error)
LoadFile tries to load a file using the registered file managers. It tries each file manager in order and returns the first successful result. Returns an error if no file manager can load the file.
func (*FileManagerCollection) RefreshFileManagers ¶
func (fmc *FileManagerCollection) RefreshFileManagers() error
RefreshFileManagers fetches the current list of registered file managers from Node.js.
type FileManagerInfo ¶
type FileManagerInfo struct {
Index int `json:"index"`
}
FileManagerInfo contains metadata about a registered JavaScript file manager.
type FlatAST ¶
type FlatAST struct {
// Header information
Version uint32 // Format version
NodeCount uint32 // Number of nodes
RootIndex uint32 // Index of root node
// Tables
Nodes []FlatNode // Array of flat nodes
TypeTable []string // Node type names (for validation)
StringTable []string // String values
PropBuffer []byte // Node-specific properties (JSON encoded)
// contains filtered or unexported fields
}
FlatAST represents a complete flattened AST structure.
func FlattenAST ¶
FlattenAST is a convenience function to flatten an AST.
func (*FlatAST) AddProperties ¶
AddProperties adds properties to the buffer and returns offset and length.
func (*FlatAST) AddString ¶
AddString adds a string to the string table and returns its index. Duplicate strings are deduplicated.
func (*FlatAST) GetProperties ¶
GetProperties retrieves properties from the buffer.
type FlatNode ¶
type FlatNode struct {
TypeID NodeTypeID // Index into type table (2 bytes)
Flags uint16 // Node flags (2 bytes)
ChildIndex uint32 // Index of first child in Nodes array (0 if none)
NextIndex uint32 // Index of next sibling (0 if none)
ParentIndex uint32 // Index of parent node (0 if root)
PropsOffset uint32 // Offset into properties buffer
PropsLength uint32 // Length of properties in buffer
}
FlatNode represents a node in the flattened AST buffer. Each node is 24 bytes in the binary representation.
type GenericNode ¶
type GenericNode struct {
Type string
Properties map[string]any
Children []*GenericNode
Parent *GenericNode
Index int
Parens bool
ParensInOp bool
Visible *bool
FileInfo map[string]any
}
GenericNode represents a reconstructed AST node from flat format. This is used when we don't have the original Go type constructors.
func UnflattenAST ¶
func UnflattenAST(flat *FlatAST) (*GenericNode, error)
UnflattenAST is a convenience function to unflatten an AST.
func (*GenericNode) GetBool ¶
func (g *GenericNode) GetBool(propName string) (bool, bool)
GetBool retrieves a boolean property.
func (*GenericNode) GetFloat64 ¶
func (g *GenericNode) GetFloat64(propName string) (float64, bool)
GetFloat64 retrieves a float64 property.
func (*GenericNode) GetType ¶
func (g *GenericNode) GetType() string
GetType returns the node type name.
func (*GenericNode) ResolveString ¶
func (g *GenericNode) ResolveString(flat *FlatAST, propName string) string
ResolveString resolves a string index to its value.
func (*GenericNode) ToJSON ¶
func (g *GenericNode) ToJSON() map[string]any
ToJSON converts the GenericNode tree to a JSON-serializable map.
type JSFileManager ¶
type JSFileManager struct {
Index int
// contains filtered or unexported fields
}
JSFileManager wraps a JavaScript file manager registered by a plugin. File managers provide custom import resolution logic for LESS files.
func NewJSFileManager ¶
func NewJSFileManager(runtime *NodeJSRuntime, index int) *JSFileManager
NewJSFileManager creates a new JSFileManager wrapper.
func (*JSFileManager) LoadFile ¶
func (fm *JSFileManager) LoadFile(filename, currentDirectory string, options map[string]any) (*LoadedFile, error)
LoadFile loads a file using this file manager. It sends a request to Node.js to call the file manager's loadFile() method.
type JSFunctionDefinition ¶
type JSFunctionDefinition struct {
// contains filtered or unexported fields
}
JSFunctionDefinition implements the FunctionDefinition interface for JavaScript functions. It calls JavaScript functions registered by plugins via the Node.js runtime.
The function supports two IPC modes for communicating with Node.js:
- Shared Memory: Zero-copy transfer using memory-mapped files (default)
- JSON: Traditional JSON serialization over stdio
See the package-level documentation for details on configuring the IPC mode.
OPTIMIZATION: JSFunctionDefinition objects are cached and reused via GetOrCreateJSFunctionDefinition. Result caching happens at the runtime level via GetCachedResult/SetCachedResult, which provides a 95%+ cache hit rate for Bootstrap-style compilations.
CONTEXT-FREE FUNCTIONS: Functions marked as contextFree=true are pure functions that don't need access to LESS variables or evaluation context. These functions:
- Skip context serialization entirely (no frame/variable data sent)
- Use a simpler, faster IPC path
- Can be more aggressively cached
- Examples: math operations, color transformations, string utilities
func GetOrCreateJSFunctionDefinition ¶
func GetOrCreateJSFunctionDefinition(name string, runtime *NodeJSRuntime, opts ...JSFunctionOption) *JSFunctionDefinition
GetOrCreateJSFunctionDefinition retrieves a cached JSFunctionDefinition or creates a new one. This is the primary function to use when you need a JSFunctionDefinition - it ensures that the same object is reused for the same (runtime, name) combination.
Thread-safe: Uses read lock for cache hits, write lock only for cache misses.
OPTIMIZATION: Uses a two-level map (runtime -> name -> definition) to avoid creating string keys on every lookup. The function name string is reused directly.
func NewJSFunctionDefinition ¶
func NewJSFunctionDefinition(name string, runtime *NodeJSRuntime, opts ...JSFunctionOption) *JSFunctionDefinition
NewJSFunctionDefinition creates a new JSFunctionDefinition for calling JavaScript functions registered by plugins.
The default IPC mode is determined by:
- Any options passed (WithJSONMode, WithSharedMemoryMode, WithIPCMode)
- The LESS_JS_IPC_MODE environment variable
- Shared memory mode (if nothing else is specified)
Example usage:
// Use default mode (shared memory, or env var override)
fn := NewJSFunctionDefinition("myFunc", runtime)
// Explicitly use JSON mode
fn := NewJSFunctionDefinition("myFunc", runtime, WithJSONMode())
// Explicitly use shared memory mode
fn := NewJSFunctionDefinition("myFunc", runtime, WithSharedMemoryMode())
OPTIMIZATION: Prefer using GetOrCreateJSFunctionDefinition instead of this function directly to benefit from object reuse caching.
func (*JSFunctionDefinition) CacheStats ¶
func (jf *JSFunctionDefinition) CacheStats() int
CacheStats returns the number of cached entries for this function. Note: Returns 0 since individual function cache stats are not tracked at the runtime level. Use GetJSFunctionDefinitionCacheStats() for the global object cache stats.
func (*JSFunctionDefinition) Call ¶
func (jf *JSFunctionDefinition) Call(args ...any) (any, error)
Call calls the JavaScript function with the given arguments.
The IPC mode (shared memory or JSON) is determined by the function's configuration. See NewJSFunctionDefinition for details on mode selection.
Returns the result node or error.
func (*JSFunctionDefinition) CallCtx ¶
func (jf *JSFunctionDefinition) CallCtx(ctx any, args ...any) (any, error)
CallCtx calls the JavaScript function with context. For JS functions, we ignore the context and just call Call.
func (*JSFunctionDefinition) CallWithContext ¶
func (jf *JSFunctionDefinition) CallWithContext(evalContext EvalContextProvider, args ...any) (any, error)
CallWithContext calls the JavaScript function with evaluation context. This is used by plugin functions that need to access Less variables.
OPTIMIZATION: Uses multiple strategies for optimal performance: 1. For context-free functions, skip context serialization entirely (fastest path) 2. Check result cache first (same args = same result) 3. If SHM protocol is available, use binary protocol 4. Otherwise, use pre-fetch + on-demand lookup
func (*JSFunctionDefinition) ClearCache ¶
func (jf *JSFunctionDefinition) ClearCache()
ClearCache clears the result cache for this function. This clears entries from the runtime-level cache that are keyed with this function's name. Call this between compilations if you want to ensure fresh results.
func (*JSFunctionDefinition) IPCMode ¶
func (jf *JSFunctionDefinition) IPCMode() JSIPCMode
IPCMode returns the current IPC mode for this function.
func (*JSFunctionDefinition) IsContextFree ¶
func (jf *JSFunctionDefinition) IsContextFree() bool
IsContextFree returns true if this function is marked as context-free (pure). Context-free functions don't need access to LESS variables or evaluation context.
func (*JSFunctionDefinition) Name ¶
func (jf *JSFunctionDefinition) Name() string
Name returns the function name.
func (*JSFunctionDefinition) NeedsEvalArgs ¶
func (jf *JSFunctionDefinition) NeedsEvalArgs() bool
NeedsEvalArgs returns true - JS functions always expect evaluated arguments.
func (*JSFunctionDefinition) SetContextFree ¶
func (jf *JSFunctionDefinition) SetContextFree(contextFree bool)
SetContextFree sets whether this function is context-free. This is useful for dynamically updating a function's context requirements.
type JSFunctionOption ¶
type JSFunctionOption func(*JSFunctionDefinition)
JSFunctionOption configures a JSFunctionDefinition.
func WithCaching ¶
func WithCaching() JSFunctionOption
WithCaching enables result caching for deterministic functions. When enabled, function calls with the same arguments will return cached results instead of making IPC calls to Node.js.
This is highly effective for Bootstrap-style plugins where functions like map-get, color-yiq, breakpoint-next are called many times with the same args.
Use this only for functions that are deterministic (same args always = same result) during a single compilation.
Note: Caching is ALWAYS ENABLED at the runtime level via GetCachedResult/SetCachedResult. This option is kept for API compatibility but has no effect - caching cannot be disabled.
func WithContext ¶
func WithContext() JSFunctionOption
WithContext marks the function as requiring context (not pure). This is the default, but can be used to explicitly override a cached function's setting.
func WithContextFree ¶
func WithContextFree() JSFunctionOption
WithContextFree marks the function as context-free (pure). Context-free functions don't need access to LESS variables or evaluation context. This enables significant performance optimizations:
- Skip context serialization (no frame/variable data sent to JS)
- Use a simpler, faster IPC path
- More aggressive caching (pure functions are deterministic)
Use this for functions that:
- Only operate on their input arguments
- Don't access LESS variables (via this.context)
- Don't have side effects
- Always return the same output for the same input
Examples of context-free functions:
- Math operations (add, multiply, sqrt, etc.)
- Color transformations (lighten, darken, saturate)
- String utilities (replace, split, join)
- Type checking (isnumber, iscolor, isstring)
Examples of functions that NEED context:
- Functions that access variables (map-get with variable maps)
- Functions that use `this.context` for variable lookup
- Functions with side effects or state
func WithIPCMode ¶
func WithIPCMode(mode JSIPCMode) JSFunctionOption
WithIPCMode configures the function to use the specified IPC mode. This allows programmatic control over the IPC mode.
func WithJSONMode ¶
func WithJSONMode() JSFunctionOption
WithJSONMode configures the function to use JSON serialization for IPC. This mode serializes arguments and results as JSON, which is simpler but has serialization overhead compared to shared memory mode.
Use this when:
- Debugging IPC issues (JSON is easier to inspect)
- Running in environments without shared memory support
- Working with simple function calls where overhead doesn't matter
func WithSharedMemoryMode ¶
func WithSharedMemoryMode() JSFunctionOption
WithSharedMemoryMode configures the function to use shared memory for IPC. This is the default mode but can be explicitly set to override environment variable configuration.
This mode serializes arguments to FlatAST binary format and writes them to a memory-mapped file that Node.js can read directly.
Use this when:
- Working with complex AST trees
- Performance is critical
- Making many function calls
func WithoutCaching ¶
func WithoutCaching() JSFunctionOption
WithoutCaching disables result caching. Use this for functions that are non-deterministic (may return different results for the same arguments due to side effects or external state).
Note: This option is kept for API compatibility but has no effect. Caching happens at the runtime level and provides 95%+ hit rate.
type JSIPCMode ¶
type JSIPCMode int
JSIPCMode represents the IPC mode for JS function calls.
func ParseIPCMode ¶
ParseIPCMode parses an IPC mode string into a JSIPCMode value. Recognized values: "json", "JSON", "sharedmem", "shm", "shared", "SHM", "SHARED" Returns JSIPCModeJSON for unrecognized values (safe default).
type JSPluginLoader ¶
type JSPluginLoader struct {
// contains filtered or unexported fields
}
JSPluginLoader loads JavaScript plugins via the Node.js runtime. It implements the PluginLoader interface from the main less_go package.
func NewJSPluginLoader ¶
func NewJSPluginLoader(runtime *NodeJSRuntime) *JSPluginLoader
NewJSPluginLoader creates a new JavaScript plugin loader.
func (*JSPluginLoader) CallFunction ¶
func (pl *JSPluginLoader) CallFunction(name string, args []any) (any, error)
CallFunction calls a JavaScript function registered by a plugin.
func (*JSPluginLoader) ClearCache ¶
func (pl *JSPluginLoader) ClearCache()
ClearCache clears the plugin cache.
func (*JSPluginLoader) EvalPlugin ¶
func (pl *JSPluginLoader) EvalPlugin(contents string, newEnv any, importManager any, pluginArgs map[string]any, newFileInfo any) any
EvalPlugin evaluates plugin contents directly (for inline plugin code).
func (*JSPluginLoader) GetLoadedPlugins ¶
func (pl *JSPluginLoader) GetLoadedPlugins() map[string]*Plugin
GetLoadedPlugins returns a copy of all loaded plugins.
func (*JSPluginLoader) GetPlugin ¶
func (pl *JSPluginLoader) GetPlugin(cacheKey string) (*Plugin, bool)
GetPlugin retrieves a loaded plugin by its cache key.
func (*JSPluginLoader) GetRegisteredFunctions ¶
func (pl *JSPluginLoader) GetRegisteredFunctions() ([]string, error)
GetRegisteredFunctions returns the names of all functions registered by plugins.
func (*JSPluginLoader) GetVisitors ¶
func (pl *JSPluginLoader) GetVisitors() ([]map[string]any, error)
GetVisitors returns information about registered visitors.
func (*JSPluginLoader) LoadPlugin ¶
func (pl *JSPluginLoader) LoadPlugin(path, currentDirectory string, context map[string]any, environment any, fileManager any) any
LoadPlugin loads a plugin from the specified path. It sends a command to the Node.js runtime to load the plugin using require().
func (*JSPluginLoader) LoadPluginSync ¶
func (pl *JSPluginLoader) LoadPluginSync(path, currentDirectory string, context map[string]any, environment any, fileManager any) any
LoadPluginSync synchronously loads a plugin from the specified path. IMPORTANT: We always call Node.js even for cached plugins, because plugin functions need to be registered in the CURRENT scope. The scope changes during evaluation (e.g., when entering mixins), so each @plugin directive needs to register its functions at the current scope depth.
type JSPostProcessor ¶
JSPostProcessor wraps a JavaScript post-processor registered by a plugin. Post-processors transform CSS output after compilation.
func NewJSPostProcessor ¶
func NewJSPostProcessor(runtime *NodeJSRuntime, index, priority int) *JSPostProcessor
NewJSPostProcessor creates a new JSPostProcessor wrapper.
type JSPreProcessor ¶
JSPreProcessor wraps a JavaScript pre-processor registered by a plugin. Pre-processors transform source code before parsing.
func NewJSPreProcessor ¶
func NewJSPreProcessor(runtime *NodeJSRuntime, index, priority int) *JSPreProcessor
NewJSPreProcessor creates a new JSPreProcessor wrapper.
type JSResultNode ¶
JSResultNode represents a result from a JavaScript function. It implements common node interfaces so it can be used by the Go evaluator.
func (*JSResultNode) GenCSS ¶
func (n *JSResultNode) GenCSS(context any, output interface { Add(string, any, any) })
GenCSS generates CSS output for the node.
func (*JSResultNode) GetType ¶
func (n *JSResultNode) GetType() string
GetType returns the node type.
func (*JSResultNode) GetValue ¶
func (n *JSResultNode) GetValue() any
GetValue returns the node's value property.
func (*JSResultNode) ToCSS ¶
func (n *JSResultNode) ToCSS() string
ToCSS returns a CSS string representation.
type JSVisitor ¶
type JSVisitor struct {
Index int
IsPreEvalVisitor bool
IsReplacing bool
// contains filtered or unexported fields
}
JSVisitor wraps a JavaScript visitor registered by a plugin. It provides methods to invoke the visitor on Go AST nodes.
func NewJSVisitor ¶
func NewJSVisitor(runtime *NodeJSRuntime, info VisitorInfo) *JSVisitor
NewJSVisitor creates a new JSVisitor wrapper.
func (*JSVisitor) Visit ¶
func (v *JSVisitor) Visit(node interface{}) (*VisitorResult, error)
Visit runs the visitor on a Go AST node. It serializes the AST to a buffer, sends it to Node.js, runs the visitor, and returns any modifications.
type LoadedFile ¶
LoadedFile represents the result of loading a file.
type Node ¶
type Node struct {
Parent *Node
VisibilityBlocks *int
NodeVisible *bool
RootNode *Node
Parsed any
Value any
Index int
Parens bool
ParensInOp bool
TypeIndex int
// contains filtered or unexported fields
}
Node represents the base node structure (simplified for serialization)
type NodeJSRuntime ¶
type NodeJSRuntime struct {
// contains filtered or unexported fields
}
NodeJSRuntime manages a Node.js process for JavaScript plugin execution.
func NewNodeJSRuntime ¶
func NewNodeJSRuntime(opts ...RuntimeOption) (*NodeJSRuntime, error)
NewNodeJSRuntime creates a new Node.js runtime instance.
The runtime is not started automatically. Call Start() to spawn the Node.js process.
func (*NodeJSRuntime) AttachBuffer ¶
func (rt *NodeJSRuntime) AttachBuffer(shm *SharedMemory) error
AttachBuffer sends a command to Node.js to attach to a shared memory buffer. Returns the path to the shared memory file for Node.js to map.
func (*NodeJSRuntime) BatchCallFunctions ¶
func (rt *NodeJSRuntime) BatchCallFunctions(calls []BatchCall) (map[string]BatchCallResult, error)
BatchCallFunctions sends multiple function calls to Node.js in a single IPC request. This reduces the overhead of multiple round-trips for plugin function calls.
The function returns a map of results keyed by the BatchCall.Key field. Each result contains Success, Result, and Error fields.
Example usage:
calls := []BatchCall{
{Key: "map-get:colors|primary", Name: "map-get", Args: [...]},
{Key: "color-yiq:#fff", Name: "color-yiq", Args: [...]},
}
results, err := rt.BatchCallFunctions(calls)
// results["map-get:colors|primary"].Result contains the result
func (*NodeJSRuntime) BatchCallFunctionsAndCache ¶
func (rt *NodeJSRuntime) BatchCallFunctionsAndCache(calls []BatchCall) (int, error)
BatchCallFunctionsAndCache sends multiple function calls to Node.js in a single IPC request and caches all successful results. This is the most efficient way to warm up the function result cache for plugin functions.
Returns the number of successfully cached results and any error.
func (*NodeJSRuntime) CallFunctionViaSHM ¶
func (rt *NodeJSRuntime) CallFunctionViaSHM(functionName string, args ...any) (any, error)
CallFunctionViaSHM calls a JavaScript function using the binary shared memory protocol. This is much faster than JSON-based IPC for repeated function calls.
func (*NodeJSRuntime) ClearCachedResultsForFunction ¶
func (rt *NodeJSRuntime) ClearCachedResultsForFunction(funcName string)
ClearCachedResultsForFunction clears cached results for a specific function. The cache key format is "funcName:arg1|arg2|...", so this deletes all entries that start with the function name followed by a colon.
func (*NodeJSRuntime) ClearFunctionCache ¶
func (rt *NodeJSRuntime) ClearFunctionCache()
ClearFunctionCache clears all cached function results. Call this between compilations to ensure fresh results.
func (*NodeJSRuntime) CloseSHMProtocol ¶
func (rt *NodeJSRuntime) CloseSHMProtocol() error
CloseSHMProtocol closes the shared memory protocol and releases resources.
func (*NodeJSRuntime) CreateSharedMemory ¶
func (rt *NodeJSRuntime) CreateSharedMemory(size int) (*SharedMemory, error)
CreateSharedMemory creates a new shared memory segment of the specified size.
func (*NodeJSRuntime) DecrementScopeDepth ¶
func (rt *NodeJSRuntime) DecrementScopeDepth()
DecrementScopeDepth decreases the scope depth by 1 (if > 0).
func (*NodeJSRuntime) DestroySharedMemory ¶
func (rt *NodeJSRuntime) DestroySharedMemory(shm *SharedMemory) error
DestroySharedMemory destroys a shared memory segment by key.
func (*NodeJSRuntime) DetachBuffer ¶
func (rt *NodeJSRuntime) DetachBuffer(key string) error
DetachBuffer sends a command to Node.js to detach from a shared memory buffer.
func (*NodeJSRuntime) Echo ¶
func (rt *NodeJSRuntime) Echo(value any) (any, error)
Echo sends a value to Node.js and expects it back (for testing).
func (*NodeJSRuntime) Error ¶
func (rt *NodeJSRuntime) Error() error
Error returns any error from the runtime's background operations.
func (*NodeJSRuntime) FunctionCacheSize ¶
func (rt *NodeJSRuntime) FunctionCacheSize() int
FunctionCacheSize returns the number of cached function results.
func (*NodeJSRuntime) GetCachedResult ¶
func (rt *NodeJSRuntime) GetCachedResult(key string) (any, bool)
GetCachedResult retrieves a cached function result by key. Returns the cached value and true if found, or nil and false if not cached.
func (*NodeJSRuntime) GetPrefetchBuffer ¶
func (rt *NodeJSRuntime) GetPrefetchBuffer(size int) (*SharedMemory, error)
GetPrefetchBuffer returns a reusable shared memory buffer for prefetch data. The buffer is created on first use and reused across calls. If the required size is larger than the current buffer, it's resized.
func (*NodeJSRuntime) GetPrefetchCache ¶
func (rt *NodeJSRuntime) GetPrefetchCache(frameCount int, frameHash uint64) []byte
GetPrefetchCache returns the cached prefetch binary data if it's still valid for the given frames. Returns nil if the cache is invalid or doesn't exist.
The cache is considered valid if: 1. It exists 2. The frame count matches 3. The frame hash matches (detecting structural changes)
func (*NodeJSRuntime) GetPrefetchCacheStats ¶
func (rt *NodeJSRuntime) GetPrefetchCacheStats() (int, int, bool)
GetPrefetchCacheStats returns statistics about the prefetch cache. Returns (binarySize, varCount, isValid).
func (*NodeJSRuntime) GetSHMProtocol ¶
func (rt *NodeJSRuntime) GetSHMProtocol() *SharedMemoryProtocol
GetSHMProtocol returns the shared memory protocol if initialized.
func (*NodeJSRuntime) GetScopeDepth ¶
func (rt *NodeJSRuntime) GetScopeDepth() int
GetScopeDepth returns the current plugin scope depth.
func (*NodeJSRuntime) GetScopeSeq ¶
func (rt *NodeJSRuntime) GetScopeSeq() int64
GetScopeSeq returns the current scope sequence number.
func (*NodeJSRuntime) IncrementScopeDepth ¶
func (rt *NodeJSRuntime) IncrementScopeDepth()
IncrementScopeDepth increases the scope depth by 1.
func (*NodeJSRuntime) IncrementScopeSeq ¶
func (rt *NodeJSRuntime) IncrementScopeSeq() int64
IncrementScopeSeq increments the scope sequence number and returns the new value. This should be called whenever EnterScope is called.
func (*NodeJSRuntime) InitSHMProtocol ¶
func (rt *NodeJSRuntime) InitSHMProtocol() error
InitSHMProtocol initializes the high-performance shared memory protocol. This creates a persistent 4MB shared memory region for binary IPC. Call this once at the start of compilation for maximum performance.
func (*NodeJSRuntime) InvalidatePrefetchCache ¶
func (rt *NodeJSRuntime) InvalidatePrefetchCache()
InvalidatePrefetchCache explicitly invalidates the prefetch cache. Call this when you know the evaluation context has changed significantly.
func (*NodeJSRuntime) IsAlive ¶
func (rt *NodeJSRuntime) IsAlive() bool
IsAlive returns true if the Node.js process is running.
func (*NodeJSRuntime) Ping ¶
func (rt *NodeJSRuntime) Ping() error
Ping sends a ping command to verify the Node.js process is responsive.
func (*NodeJSRuntime) PreloadVariables ¶
func (rt *NodeJSRuntime) PreloadVariables(frames []any) error
PreloadVariables writes all variables from the evaluation context to shared memory. This should be called once at the start of compilation for best performance.
func (*NodeJSRuntime) ReadASTBuffer ¶
func (rt *NodeJSRuntime) ReadASTBuffer(shm *SharedMemory) (*FlatAST, error)
ReadASTBuffer reads a FlatAST from a shared memory segment. This reads the AST data that was written by Node.js.
func (*NodeJSRuntime) RegisterCallback ¶
func (rt *NodeJSRuntime) RegisterCallback(name string, handler CallbackHandler)
RegisterCallback registers a callback handler for a specific callback type.
func (*NodeJSRuntime) SendCommand ¶
func (rt *NodeJSRuntime) SendCommand(cmd Command) (Response, error)
SendCommand sends a command to the Node.js process and waits for a response.
func (*NodeJSRuntime) SendCommandFireAndForget ¶
func (rt *NodeJSRuntime) SendCommandFireAndForget(cmd Command) error
SendCommandFireAndForget sends a command without waiting for a response. This is useful for commands that don't need a response or when the response can be safely ignored. The command is still sent with an ID for logging purposes.
CRITICAL: Only use this for idempotent operations where: 1. The response is not needed by the caller 2. Order of execution is not critical 3. Failure can be tolerated or will be detected later
This dramatically reduces IPC latency for operations like scope management where we send hundreds of thousands of updates during Bootstrap4 compilation.
func (*NodeJSRuntime) SendCommandWithContext ¶
func (rt *NodeJSRuntime) SendCommandWithContext(ctx context, cmd Command) (Response, error)
SendCommandWithContext sends a command with a context for timeout/cancellation.
func (*NodeJSRuntime) SetCachedResult ¶
func (rt *NodeJSRuntime) SetCachedResult(key string, value any)
SetCachedResult stores a function result in the cache.
func (*NodeJSRuntime) SetPrefetchCache ¶
func (rt *NodeJSRuntime) SetPrefetchCache(binaryData []byte, frameCount int, frameHash uint64, varCount int)
SetPrefetchCache stores the serialized prefetch binary data in the cache. The frameCount and frameHash are used for invalidation checks.
func (*NodeJSRuntime) SharedMemoryManager ¶
func (rt *NodeJSRuntime) SharedMemoryManager() *SharedMemoryManager
SharedMemoryManager returns the shared memory manager for this runtime.
func (*NodeJSRuntime) Start ¶
func (rt *NodeJSRuntime) Start() error
Start spawns the Node.js process and begins handling IPC.
func (*NodeJSRuntime) Stop ¶
func (rt *NodeJSRuntime) Stop() error
Stop gracefully shuts down the Node.js process.
func (*NodeJSRuntime) UnregisterCallback ¶
func (rt *NodeJSRuntime) UnregisterCallback(name string)
UnregisterCallback removes a callback handler.
func (*NodeJSRuntime) UseSHMProtocol ¶
func (rt *NodeJSRuntime) UseSHMProtocol() bool
UseSHMProtocol returns whether the binary SHM protocol is enabled.
func (*NodeJSRuntime) WriteASTBuffer ¶
func (rt *NodeJSRuntime) WriteASTBuffer(flat *FlatAST) (*SharedMemory, error)
WriteASTBuffer writes a FlatAST to shared memory and returns the segment. This enables zero-copy transfer of AST data to Node.js.
type NodeReplacement ¶
type NodeReplacement struct {
ParentIndex int `json:"parentIndex"`
ChildIndex int `json:"childIndex"`
Replacement interface{} `json:"replacement"`
}
NodeReplacement represents a single node replacement in the AST.
type NodeTypeID ¶
type NodeTypeID uint16
NodeTypeID represents a unique identifier for each AST node type.
const ( TypeUnknown NodeTypeID = iota TypeAnonymous TypeAssignment TypeAtRule TypeAttribute TypeCall TypeColor TypeCombinator TypeComment TypeCondition TypeContainer TypeDeclaration TypeDetachedRuleset TypeDimension TypeElement TypeExpression TypeExtend TypeImport TypeJavaScript TypeKeyword TypeMedia TypeMixinCall TypeMixinDefinition TypeNamespaceValue TypeNegative TypeOperation TypeParen TypeProperty TypeQueryInParens TypeQuoted TypeRuleset TypeSelector TypeSelectorList TypeUnicodeDescriptor TypeUnit TypeURL TypeValue TypeVariable TypeVariableCall TypeNode // Base Node type )
Node type constants - these map to JavaScript type names.
func GetTypeID ¶
func GetTypeID(node any) NodeTypeID
GetTypeID returns the type ID for a node based on its GetType() method.
type ParseASTBufferResult ¶
type ParseASTBufferResult struct {
Version uint32
NodeCount uint32
RootIndex uint32
StringTableSize int
TypeTableSize int
}
ParseASTBufferResult contains the result of parsing an AST buffer.
type Plugin ¶
type Plugin struct {
Path string // Resolved path to the plugin
Filename string // Original filename/identifier
Functions []string // Names of registered functions
ContextFreeFunctions map[string]bool // Map of function names that are context-free (pure)
Visitors int // Number of registered visitors
PreProcessors int // Number of registered pre-processors
PostProcessors int // Number of registered post-processors
FileManagers int // Number of registered file managers
Cached bool // Whether this was loaded from cache
IPCMode JSIPCMode // Preferred IPC mode for this plugin's functions (json or shared-memory)
}
Plugin represents a loaded JavaScript plugin with its registered components.
func (*Plugin) IsContextFree ¶
IsContextFree returns true if the specified function is marked as context-free.
type PluginFunctionRegistry ¶
type PluginFunctionRegistry struct {
// contains filtered or unexported fields
}
PluginFunctionRegistry provides a unified interface for both built-in Go functions and JavaScript plugin functions.
func NewPluginFunctionRegistry ¶
func NewPluginFunctionRegistry(builtinRegistry any, runtime *NodeJSRuntime) *PluginFunctionRegistry
NewPluginFunctionRegistry creates a new PluginFunctionRegistry.
func (*PluginFunctionRegistry) ClearJSFunctions ¶
func (r *PluginFunctionRegistry) ClearJSFunctions()
ClearJSFunctions removes all registered JavaScript functions.
func (*PluginFunctionRegistry) Get ¶
func (r *PluginFunctionRegistry) Get(name string) any
Get retrieves a function definition by name. JavaScript functions take precedence over built-in functions (shadowing).
func (*PluginFunctionRegistry) GetBuiltinRegistry ¶
func (r *PluginFunctionRegistry) GetBuiltinRegistry() any
GetBuiltinRegistry returns the underlying built-in registry.
func (*PluginFunctionRegistry) GetJSFunctionNames ¶
func (r *PluginFunctionRegistry) GetJSFunctionNames() []string
GetJSFunctionNames returns the names of all registered JavaScript functions.
func (*PluginFunctionRegistry) HasJSFunction ¶
func (r *PluginFunctionRegistry) HasJSFunction(name string) bool
HasJSFunction checks if a JavaScript function is registered.
func (*PluginFunctionRegistry) RefreshFromRuntime ¶
func (r *PluginFunctionRegistry) RefreshFromRuntime() error
RefreshFromRuntime queries the Node.js runtime for registered functions and updates the registry. OPTIMIZATION: Uses GetOrCreateJSFunctionDefinition to reuse cached objects.
func (*PluginFunctionRegistry) RegisterJSFunction ¶
func (r *PluginFunctionRegistry) RegisterJSFunction(name string)
RegisterJSFunction registers a JavaScript function by name. OPTIMIZATION: Uses GetOrCreateJSFunctionDefinition to reuse cached objects.
func (*PluginFunctionRegistry) RegisterJSFunctions ¶
func (r *PluginFunctionRegistry) RegisterJSFunctions(names []string)
RegisterJSFunctions registers multiple JavaScript functions by name. OPTIMIZATION: Uses GetOrCreateJSFunctionDefinition to reuse cached objects.
type PluginLoadResult ¶
type PluginLoadResult struct {
Success bool `json:"success"`
Error string `json:"error,omitempty"`
Cached bool `json:"cached"`
Functions []string `json:"functions,omitempty"`
ContextFreeFunctions []string `json:"contextFreeFunctions,omitempty"` // Functions that don't need context
Visitors int `json:"visitors,omitempty"`
PreProcessors int `json:"preProcessors,omitempty"`
PostProcessors int `json:"postProcessors,omitempty"`
FileManagers int `json:"fileManagers,omitempty"`
IPCMode string `json:"ipcMode,omitempty"` // "json" or "shm" - preferred IPC mode
}
PluginLoadResult contains the result of loading a plugin via Node.js.
type PluginScope ¶
type PluginScope struct {
// contains filtered or unexported fields
}
PluginScope represents a scope in the plugin hierarchy. It manages functions, visitors, and other plugin components that are scoped to a particular level in the LESS AST (e.g., file-level, ruleset-level, mixin-level).
Plugin scoping follows these rules: - Global plugins (@plugin at file root) affect the entire file - Local plugins (@plugin inside rulesets) only affect that scope and children - Child scopes can shadow parent functions (local overrides global) - Visitors from parent scopes are inherited
func NewPluginScope ¶
func NewPluginScope(parent *PluginScope) *PluginScope
NewPluginScope creates a new plugin scope with an optional parent. If parent is nil, this is a root (global) scope.
OPTIMIZATION: Uses sync.Pool to reuse PluginScope objects. Call Release() when the scope is no longer needed to return it to the pool.
func NewRootPluginScope ¶
func NewRootPluginScope() *PluginScope
NewRootPluginScope creates a root (global) plugin scope.
func (*PluginScope) AddFileManager ¶
func (ps *PluginScope) AddFileManager(manager any)
AddFileManager adds a file manager to this scope.
func (*PluginScope) AddFunction ¶
func (ps *PluginScope) AddFunction(name string, fn *JSFunctionDefinition)
AddFunction registers a function in this scope. This allows a local plugin to shadow a function from a parent scope.
func (*PluginScope) AddPlugin ¶
func (ps *PluginScope) AddPlugin(plugin *Plugin, runtime *NodeJSRuntime)
AddPlugin registers a plugin in this scope. It extracts the plugin's functions and visitors and registers them locally.
OPTIMIZATION: Uses GetOrCreateJSFunctionDefinition to reuse cached objects. This eliminates redundant object allocations by reusing the same JSFunctionDefinition object for each (runtime, name) pair across all scopes.
Per-plugin IPC mode: Each plugin can specify its preferred IPC mode (JSON or SHM). This allows plugins to optimize for their specific use case: - JSON: Better for plugins with many small function calls (lower per-call overhead) - SHM: Better for plugins with large data transfers (less serialization)
Context-free functions: Plugins can declare functions as context-free (pure). These functions don't need access to LESS variables and skip context serialization.
func (*PluginScope) AddPostProcessor ¶
func (ps *PluginScope) AddPostProcessor(processor any, priority int)
AddPostProcessor adds a post-processor to this scope with the given priority.
func (*PluginScope) AddPreProcessor ¶
func (ps *PluginScope) AddPreProcessor(processor any, priority int)
AddPreProcessor adds a pre-processor to this scope with the given priority.
func (*PluginScope) AddVisitor ¶
func (ps *PluginScope) AddVisitor(visitor *JSVisitor)
AddVisitor registers a visitor in this scope.
func (*PluginScope) CreateChild ¶
func (ps *PluginScope) CreateChild() *PluginScope
CreateChild creates a new child scope with this scope as its parent. This is used when entering a new scoping boundary (e.g., a ruleset with @plugin).
func (*PluginScope) GetAllFunctions ¶
func (ps *PluginScope) GetAllFunctions() map[string]*JSFunctionDefinition
GetAllFunctions returns all functions visible from this scope (including inherited).
func (*PluginScope) GetFileManagers ¶
func (ps *PluginScope) GetFileManagers() []any
GetFileManagers returns all file managers from this scope and parents.
func (*PluginScope) GetLocalFunction ¶
func (ps *PluginScope) GetLocalFunction(name string) (*JSFunctionDefinition, bool)
GetLocalFunction returns a function only if it's defined in this scope (not inherited).
func (*PluginScope) GetLocalVisitors ¶
func (ps *PluginScope) GetLocalVisitors() []*JSVisitor
GetLocalVisitors returns only visitors defined in this scope (not inherited).
func (*PluginScope) GetPlugins ¶
func (ps *PluginScope) GetPlugins() []*Plugin
GetPlugins returns all plugins registered in this scope.
func (*PluginScope) GetPostEvalVisitors ¶
func (ps *PluginScope) GetPostEvalVisitors() []*JSVisitor
GetPostEvalVisitors returns all post-evaluation visitors from this scope and parents.
func (*PluginScope) GetPostProcessors ¶
func (ps *PluginScope) GetPostProcessors() []any
GetPostProcessors returns all post-processors from this scope and parents, sorted by priority.
func (*PluginScope) GetPreEvalVisitors ¶
func (ps *PluginScope) GetPreEvalVisitors() []*JSVisitor
GetPreEvalVisitors returns all pre-evaluation visitors from this scope and parents.
func (*PluginScope) GetPreProcessors ¶
func (ps *PluginScope) GetPreProcessors() []any
GetPreProcessors returns all pre-processors from this scope and parents, sorted by priority.
func (*PluginScope) GetVisitors ¶
func (ps *PluginScope) GetVisitors() []*JSVisitor
GetVisitors returns all visitors from this scope and all parent scopes. Parent visitors are included because they should still run on child content.
func (*PluginScope) IsRoot ¶
func (ps *PluginScope) IsRoot() bool
IsRoot returns true if this is a root (global) scope.
func (*PluginScope) LookupFunction ¶
func (ps *PluginScope) LookupFunction(name string) (*JSFunctionDefinition, bool)
LookupFunction looks up a function by name, searching from this scope up to the root. Local functions shadow parent functions with the same name. Returns the function and true if found, nil and false otherwise.
func (*PluginScope) Parent ¶
func (ps *PluginScope) Parent() *PluginScope
Parent returns the parent scope, or nil if this is the root.
func (*PluginScope) Release ¶
func (ps *PluginScope) Release()
Release returns the scope to the pool for reuse. The scope should not be used after calling Release(). This clears references to prevent memory leaks and returns the scope to the pool.
IMPORTANT: Only call Release() on child scopes that are no longer needed. Do not release scopes that may still be referenced elsewhere.
type PrefetchCache ¶
type PrefetchCache struct {
// contains filtered or unexported fields
}
PrefetchCache caches the serialized binary prefetch buffer for plugin function calls. This avoids the overhead of collecting and serializing ~39 variables on every call when the evaluation context (frames) hasn't changed.
type ProcessorInfo ¶
ProcessorInfo contains metadata about a registered JavaScript processor.
type ProcessorManager ¶
type ProcessorManager struct {
// contains filtered or unexported fields
}
ProcessorManager manages JavaScript pre/post processors for a plugin loader.
func NewProcessorManager ¶
func NewProcessorManager(runtime *NodeJSRuntime) *ProcessorManager
NewProcessorManager creates a new processor manager.
func (*ProcessorManager) GetPostProcessors ¶
func (pm *ProcessorManager) GetPostProcessors() []*JSPostProcessor
GetPostProcessors returns all registered post-processors.
func (*ProcessorManager) GetPreProcessors ¶
func (pm *ProcessorManager) GetPreProcessors() []*JSPreProcessor
GetPreProcessors returns all registered pre-processors.
func (*ProcessorManager) PostProcessorCount ¶
func (pm *ProcessorManager) PostProcessorCount() int
PostProcessorCount returns the number of registered post-processors.
func (*ProcessorManager) PreProcessorCount ¶
func (pm *ProcessorManager) PreProcessorCount() int
PreProcessorCount returns the number of registered pre-processors.
func (*ProcessorManager) RefreshProcessors ¶
func (pm *ProcessorManager) RefreshProcessors() error
RefreshProcessors fetches the current list of registered processors from Node.js.
func (*ProcessorManager) RunPostProcessors ¶
RunPostProcessors runs all post-processors on the CSS output. Processors are run in order of their priority (lower priority runs first).
func (*ProcessorManager) RunPreProcessors ¶
RunPreProcessors runs all pre-processors on the input source code. Processors are run in order of their priority (lower priority runs first).
type ProcessorResult ¶
type ProcessorResult struct {
Success bool `json:"success"`
Output string `json:"output,omitempty"`
Error string `json:"error,omitempty"`
}
ProcessorResult contains the result of running a processor.
type ProcessorWithPriority ¶
ProcessorWithPriority wraps a processor with its priority for ordering.
type Response ¶
type Response struct {
ID int64 `json:"id"`
Success bool `json:"success"`
Result any `json:"result,omitempty"`
Error string `json:"error,omitempty"`
}
Response represents a response from the Node.js process.
type RuntimeOption ¶
type RuntimeOption func(*NodeJSRuntime)
RuntimeOption configures a NodeJSRuntime.
func WithNodeCommand ¶
func WithNodeCommand(cmd string) RuntimeOption
WithNodeCommand sets the Node.js command to use (default: "node").
func WithPluginHostPath ¶
func WithPluginHostPath(path string) RuntimeOption
WithPluginHostPath sets the path to the plugin-host.js file.
type ScopedPluginManager ¶
type ScopedPluginManager struct {
// contains filtered or unexported fields
}
ScopedPluginManager wraps a PluginScope and provides the interface expected by the less_go PluginManager. This allows PluginScope to be used in the existing transform_tree.go visitor loop.
func NewScopedPluginManager ¶
func NewScopedPluginManager(scope *PluginScope, runtime *NodeJSRuntime) *ScopedPluginManager
NewScopedPluginManager creates a new scoped plugin manager.
func (*ScopedPluginManager) GetFileManagers ¶
func (spm *ScopedPluginManager) GetFileManagers() []any
GetFileManagers returns all file managers from the scope.
func (*ScopedPluginManager) GetPostProcessors ¶
func (spm *ScopedPluginManager) GetPostProcessors() []any
GetPostProcessors returns all post-processors from the scope.
func (*ScopedPluginManager) GetPreProcessors ¶
func (spm *ScopedPluginManager) GetPreProcessors() []any
GetPreProcessors returns all pre-processors from the scope.
func (*ScopedPluginManager) GetVisitors ¶
func (spm *ScopedPluginManager) GetVisitors() []any
GetVisitors returns all visitors from the scope.
func (*ScopedPluginManager) Visitor ¶
func (spm *ScopedPluginManager) Visitor() *ScopedVisitorIterator
Visitor returns a visitor iterator for transform_tree.go compatibility.
type ScopedVisitorIterator ¶
type ScopedVisitorIterator struct {
// contains filtered or unexported fields
}
ScopedVisitorIterator provides visitor iteration for transform_tree.go.
func (*ScopedVisitorIterator) First ¶
func (vi *ScopedVisitorIterator) First()
First resets the iterator to the beginning.
func (*ScopedVisitorIterator) Get ¶
func (vi *ScopedVisitorIterator) Get() any
Get returns the next visitor in the iteration.
type SerializeNodeResult ¶
SerializeNodeResult contains the result of serializing a node.
type SharedMemory ¶
type SharedMemory struct {
// contains filtered or unexported fields
}
SharedMemory represents a shared memory segment backed by a memory-mapped file. This provides zero-copy data transfer between Go and Node.js processes.
func (*SharedMemory) Close ¶
func (s *SharedMemory) Close() error
Close unmaps the memory and closes the file.
func (*SharedMemory) Data ¶
func (s *SharedMemory) Data() []byte
Data returns the underlying byte slice (read-only copy).
func (*SharedMemory) Key ¶
func (s *SharedMemory) Key() string
Key returns the unique identifier for this segment.
func (*SharedMemory) Path ¶
func (s *SharedMemory) Path() string
Path returns the file path for this segment.
func (*SharedMemory) Read ¶
func (s *SharedMemory) Read(offset, length int) ([]byte, error)
Read reads data from the shared memory segment.
func (*SharedMemory) ReadAll ¶
func (s *SharedMemory) ReadAll() ([]byte, error)
ReadAll reads all data from the shared memory segment.
func (*SharedMemory) Size ¶
func (s *SharedMemory) Size() int
Size returns the size of the mapped region.
func (*SharedMemory) Sync ¶
func (s *SharedMemory) Sync() error
Sync flushes any cached writes to the backing file. This is critical for IPC with processes that read the file directly instead of memory-mapping it (like Node.js using fs.readFileSync).
func (*SharedMemory) Write ¶
func (s *SharedMemory) Write(offset int, data []byte) error
Write writes data to the shared memory segment at the specified offset.
func (*SharedMemory) WriteAll ¶
func (s *SharedMemory) WriteAll(data []byte) error
WriteAll writes data to the beginning of the segment.
type SharedMemoryManager ¶
type SharedMemoryManager struct {
// contains filtered or unexported fields
}
SharedMemoryManager manages shared memory segments for a runtime.
func NewSharedMemoryManager ¶
func NewSharedMemoryManager() (*SharedMemoryManager, error)
NewSharedMemoryManager creates a new shared memory manager.
func (*SharedMemoryManager) Create ¶
func (m *SharedMemoryManager) Create(size int) (*SharedMemory, error)
Create creates a new shared memory segment of the specified size.
func (*SharedMemoryManager) Destroy ¶
func (m *SharedMemoryManager) Destroy(key string) error
Destroy destroys a shared memory segment.
func (*SharedMemoryManager) DestroyAll ¶
func (m *SharedMemoryManager) DestroyAll() error
DestroyAll destroys all shared memory segments and cleans up.
func (*SharedMemoryManager) Get ¶
func (m *SharedMemoryManager) Get(key string) *SharedMemory
Get retrieves a shared memory segment by key.
func (*SharedMemoryManager) Open ¶
func (m *SharedMemoryManager) Open(key string) (*SharedMemory, error)
Open opens an existing shared memory segment by key (read-only).
type SharedMemoryProtocol ¶
type SharedMemoryProtocol struct {
// contains filtered or unexported fields
}
SharedMemoryProtocol manages a persistent shared memory region for high-performance IPC between Go and Node.js.
func NewSharedMemoryProtocol ¶
func NewSharedMemoryProtocol(shmManager *SharedMemoryManager) (*SharedMemoryProtocol, error)
NewSharedMemoryProtocol creates a new shared memory protocol instance.
func (*SharedMemoryProtocol) ClearResponse ¶
func (p *SharedMemoryProtocol) ClearResponse()
ClearResponse clears the response ready flag for the next call.
func (*SharedMemoryProtocol) Close ¶
func (p *SharedMemoryProtocol) Close() error
Close releases the shared memory resources.
func (*SharedMemoryProtocol) GetArgsSectionInfo ¶
func (p *SharedMemoryProtocol) GetArgsSectionInfo() (offset, size uint32)
GetArgsSectionInfo returns info about the args section for JS.
func (*SharedMemoryProtocol) GetControlBlockLayout ¶
func (p *SharedMemoryProtocol) GetControlBlockLayout() map[string]uint32
GetControlBlockLayout returns the control block layout for JS initialization.
func (*SharedMemoryProtocol) GetFunctionID ¶
func (p *SharedMemoryProtocol) GetFunctionID(name string) (uint32, bool)
GetFunctionID returns the ID for a function name.
func (*SharedMemoryProtocol) GetFunctionName ¶
func (p *SharedMemoryProtocol) GetFunctionName(id uint32) (string, bool)
GetFunctionName returns the name for a function ID.
func (*SharedMemoryProtocol) GetResultsSectionInfo ¶
func (p *SharedMemoryProtocol) GetResultsSectionInfo() (offset, size uint32)
GetResultsSectionInfo returns info about the results section for JS.
func (*SharedMemoryProtocol) GetSectionOffsets ¶
func (p *SharedMemoryProtocol) GetSectionOffsets() map[string]uint32
GetSectionOffsets returns all section offsets for JS.
func (*SharedMemoryProtocol) GetVariablesSectionInfo ¶
func (p *SharedMemoryProtocol) GetVariablesSectionInfo() (offset, size uint32)
GetVariablesSectionInfo returns info about the variables section for JS.
func (*SharedMemoryProtocol) IsJSReady ¶
func (p *SharedMemoryProtocol) IsJSReady() bool
IsJSReady checks if JavaScript has signaled it's ready.
func (*SharedMemoryProtocol) Key ¶
func (p *SharedMemoryProtocol) Key() string
Key returns the unique key for this shared memory segment.
func (*SharedMemoryProtocol) Path ¶
func (p *SharedMemoryProtocol) Path() string
Path returns the path to the shared memory file.
func (*SharedMemoryProtocol) PrepareCall ¶
func (p *SharedMemoryProtocol) PrepareCall(functionID uint32, argCount int) error
PrepareCall prepares a function call in shared memory. Returns the offset where arguments should be written.
func (*SharedMemoryProtocol) ReadResult ¶
func (p *SharedMemoryProtocol) ReadResult() (any, error)
ReadResult reads the result from the results section.
func (*SharedMemoryProtocol) RegisterFunction ¶
func (p *SharedMemoryProtocol) RegisterFunction(name string) uint32
RegisterFunction registers a function and returns its ID.
func (*SharedMemoryProtocol) SignalRequest ¶
func (p *SharedMemoryProtocol) SignalRequest() error
SignalRequest signals that the request is ready.
func (*SharedMemoryProtocol) WaitForResponse ¶
func (p *SharedMemoryProtocol) WaitForResponse(maxWaitMs int) (bool, error)
WaitForResponse waits for the JavaScript side to signal completion. This uses busy-waiting with file re-reads to detect changes from Node.js.
func (*SharedMemoryProtocol) WriteArg ¶
func (p *SharedMemoryProtocol) WriteArg(argIndex int, value any) (uint32, error)
WriteArg writes an argument to the arguments section. Returns the offset where the argument was written.
func (*SharedMemoryProtocol) WriteVariables ¶
func (p *SharedMemoryProtocol) WriteVariables(variables map[string]any) error
WriteVariables writes all variables to the variables section in binary format. This should be called once at the start of compilation.
type UnifiedMessage ¶
type UnifiedMessage struct {
ID int64 `json:"id"`
Success bool `json:"success"`
Result any `json:"result,omitempty"`
Error string `json:"error,omitempty"`
Callback string `json:"callback,omitempty"` // Only set for callback requests
Data any `json:"data,omitempty"` // Only set for callback requests
}
UnifiedMessage is used for single-pass JSON parsing of IPC messages. It can represent either a Response or a CallbackRequest.
type VisitorInfo ¶
type VisitorInfo struct {
Index int `json:"index"`
IsPreEvalVisitor bool `json:"isPreEvalVisitor"`
IsReplacing bool `json:"isReplacing"`
}
VisitorInfo contains metadata about a registered JavaScript visitor.
type VisitorManager ¶
type VisitorManager struct {
// contains filtered or unexported fields
}
VisitorManager manages JavaScript visitors for a plugin loader.
func NewVisitorManager ¶
func NewVisitorManager(runtime *NodeJSRuntime) *VisitorManager
NewVisitorManager creates a new visitor manager.
func (*VisitorManager) GetPostEvalVisitors ¶
func (vm *VisitorManager) GetPostEvalVisitors() []*JSVisitor
GetPostEvalVisitors returns all post-evaluation visitors.
func (*VisitorManager) GetPreEvalVisitors ¶
func (vm *VisitorManager) GetPreEvalVisitors() []*JSVisitor
GetPreEvalVisitors returns all pre-evaluation visitors.
func (*VisitorManager) ParseASTBuffer ¶
func (vm *VisitorManager) ParseASTBuffer(shm *SharedMemory) (*ParseASTBufferResult, error)
ParseASTBuffer parses an AST buffer and returns metadata.
func (*VisitorManager) RefreshVisitors ¶
func (vm *VisitorManager) RefreshVisitors() error
RefreshVisitors fetches the current list of registered visitors from Node.js.
func (*VisitorManager) RunPostEvalVisitors ¶
func (vm *VisitorManager) RunPostEvalVisitors(node interface{}) (*VisitorResult, error)
RunPostEvalVisitors runs all post-evaluation visitors on an AST.
func (*VisitorManager) RunPreEvalVisitors ¶
func (vm *VisitorManager) RunPreEvalVisitors(node interface{}) (*VisitorResult, error)
RunPreEvalVisitors runs all pre-evaluation visitors on an AST.
func (*VisitorManager) SerializeNode ¶
func (vm *VisitorManager) SerializeNode(node interface{}) (*SerializeNodeResult, error)
SerializeNode serializes a JavaScript node to buffer format.
type VisitorReplacementSet ¶
type VisitorReplacementSet struct {
VisitorIndex int `json:"visitorIndex"`
Replacements []NodeReplacement `json:"replacements"`
}
VisitorReplacementSet contains replacements from a single visitor.
type VisitorResult ¶
type VisitorResult struct {
Success bool `json:"success"`
Replacements []VisitorReplacementSet `json:"replacements,omitempty"`
VisitorCount int `json:"visitorCount,omitempty"`
ResultType string `json:"resultType,omitempty"`
Message string `json:"message,omitempty"`
}
VisitorResult contains the result of running a visitor.