Reference Counting
QuickJS uses reference counting for memory management of JavaScript values. Understanding and correctly using these functions is critical to prevent memory leaks and use-after-free bugs.Overview
JSValue represents a JavaScript value which can be a primitive type or an object. Values with reference counts (objects, strings, etc.) must be explicitly managed:
- Increment the reference count when you want to keep a value:
JS_DupValue() - Decrement the reference count when done with a value:
JS_FreeValue()
JS_FreeValue() on them is safe and does nothing.
Reference Counting Rules
The QuickJS API follows these conventions:Function Parameters
JSValueparameter: Function takes ownership; caller must NOT callJS_FreeValue()JSValueConstparameter: Function does NOT take ownership; caller MUST callJS_FreeValue()later
Return Values
- Function returning
JSValue: Transfers ownership to caller; caller MUST callJS_FreeValue() - Function returning
JSValueConst: Does NOT transfer ownership; caller must NOT callJS_FreeValue()
Core Functions
JS_FreeValue
Decrements the reference count of a value and frees it if the count reaches zero.ctx- JavaScript contextv- Value to free
JS_FreeValueRT
Decrements the reference count using the runtime instead of a context.rt- JavaScript runtimev- Value to free
JS_DupValue
Increments the reference count of a value.ctx- JavaScript contextv- Value to duplicate
JS_DupValueRT
Increments the reference count using the runtime.rt- JavaScript runtimev- Value to duplicate
Common Patterns
Creating and Freeing Values
Passing Values to Functions
When a function takesJSValue (not JSValueConst), it takes ownership:
JSValueConst, it does NOT take ownership:
Returning Values from C Functions
C functions that returnJSValue must return a newly allocated value:
Storing Values
When storing a value in a data structure, duplicate it:Error Handling
When an error occurs, free any values you’ve created:Using goto for Cleanup
A common pattern for complex initialization:Reference Count Checks
JS_VALUE_HAS_REF_COUNT
Checks if a value has a reference count.Debugging Reference Counting Issues
QuickJS provides dump flags to help debug memory issues:JS_FreeRuntime() to see what wasn’t properly freed.
Common Mistakes
Double Free
Memory Leak
Using After Free
Not Duplicating Stored Values
Best Practices
- Always match creation with destruction: Every
JS_New*should have a correspondingJS_FreeValue - Check function signatures:
JSValueparameters take ownership,JSValueConstdon’t - Duplicate when storing: Use
JS_DupValue()when storing a value in a data structure - Use goto for cleanup: In complex functions, use goto to ensure proper cleanup on error
- Free in reverse order: When freeing multiple values, free them in reverse order of creation
- Check for exceptions: Always check return values for
JS_EXCEPTIONbefore using them - Use the build-time checker: Compile with
-DJS_CHECK_JSVALUEduring development to catch type mismatches