Concepts

Heap

A single region for garbage collection. Shared by one or more contexts.

Context

A handle used in the Duktape API, associated with a Duktape thread (coroutine) and its call and value stacks.

Call stack (of a context)

Book-keeping of the active function call chain in a context. Includes both Ecmascript and Duktape/C function calls.

Value stack (of a context)

Book-keeping of tagged values belonging to current activations in a context's call stack.

The values kept in a value stack are traditional tagged types. Stack entries are indexed either from the bottom or from the top of the most recent function call.

Value stack index

Non-negative (>= 0) indices refer to stack entries in the current stack frame, relative to the frame bottom:

[ 0 1 2 3 4 5! ]

Negative (< 0) indices refer to stack entries relative to the top:

[ -6 -5 -4 -3 -2 -1! ]

The special constant DUK_INVALID_INDEX is a negative integer which denotes an invalid stack index. It can be returned from API calls and can also be given to API calls to indicate a "no value".

The value stack top (or just "top") is the non-negative index of an imaginary element just above the highest used index. For instance, above the highest used index is 5, so the stack top is 6. The top indicates the current stack size, and is also the index of the next element pushed to the stack.

[ 0 1 2 3 4 5! 6? ]

API stack operations are always confined to the current stack frame. There is no way to refer to stack entries below the current frame. This is intentional, as it protects functions in the call stack from affecting each other's values.

Stack type

TypeType constantType mask constantDescriptionHeap alloc
(none)DUK_TYPE_NONEDUK_TYPE_MASK_NONEno type (missing value, invalid index, etc)no
undefinedDUK_TYPE_UNDEFINEDDUK_TYPE_MASK_UNDEFINEDundefinedno
nullDUK_TYPE_NULLDUK_TYPE_MASK_NULLnullno
booleanDUK_TYPE_BOOLEANDUK_TYPE_MASK_BOOLEANtrue and falseno
numberDUK_TYPE_NUMBERDUK_TYPE_MASK_NUMBERIEEE doubleno
stringDUK_TYPE_STRINGDUK_TYPE_MASK_STRINGimmutable stringyes
objectDUK_TYPE_OBJECTDUK_TYPE_MASK_OBJECTobject with propertiesyes
bufferDUK_TYPE_BUFFERDUK_TYPE_MASK_BUFFERmutable byte buffer, fixed/dynamicyes
pointerDUK_TYPE_POINTERDUK_TYPE_MASK_POINTERopaque pointer (void *)no

The "Heap alloc" column indicates whether the tagged value points to a heap allocated object with possibly additional allocations (like object property table).

Stack type mask

Each stack type has a bit index which allows a set of stack types to be represented as a bit mask. Calling code can use such bit sets to e.g. check whether or not a certain stack value belongs to a set of types. Example:

if (duk_get_type_mask(ctx, -3) & (DUK_TYPE_MASK_NUMBER |
                                  DUK_TYPE_MASK_STRING |
                                  DUK_TYPE_MASK_OBJECT)) {
    printf("type is number, string, or object\n");
}
Add duk_check_type_mask() to shortcut above use case?

Array index

Ecmascript object and array keys can only be strings; this includes array indices (0, 1, 2, ...) which are expressed as canonical string representations ("0", "1", "2", ...) of the respective numbers for all integers in the range [0, 2**32-1]. Conceptually any key used in a property lookup is first coerced to a string, so that obj[123] is really just a shorthand for obj["123"].

Duktape tries to avoid explicit number-to-string conversions for array accesses whenever possible, so it is preferable to use numeric array indices in both Ecmascript code and C code using the Duktape API.

Duktape/C function

A C function with a Duktape/C API signature can be associated with an Ecmascript function object, and gets called when the Ecmascript function object is called. Example:

int my_func(duk_context *ctx) {
    duk_push_int(ctx, 123);
    return 1;
}

Argument count given in value stack is specified when the corresponding Ecmascript function object is created: either a fixed number of arguments of DUK_VARARGS for getting arguments "as is". Extra arguments are dropped and missing arguments padded with undefined as necessary. Use duk_get_top() to determine number of actual arguments.

Function return values:

No error message can be given when using the error shorthand:

int my_func(duk_context *ctx) {
    if (duk_get_top(ctx) == 0) {
        /* throw TypeError if no arguments given */
        return DUK_RET_TYPE_ERROR;
    }
    /* ... */
}