mirror of https://github.com/svaarala/duktape.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
174 lines
6.8 KiB
174 lines
6.8 KiB
<h1 id="concepts">Concepts</h1>
|
|
|
|
<h2>Heap</h2>
|
|
|
|
<p>A single region for garbage collection. Shared by one or more
|
|
contexts.</p>
|
|
|
|
<h2>Context</h2>
|
|
|
|
<p>A handle used in the Duktape API, associated with a Duktape thread
|
|
(coroutine) and its call and value stacks.</p>
|
|
|
|
<h2>Call stack (of a context)</h2>
|
|
|
|
<p>Book-keeping of the active function call chain of a context.
|
|
Includes both Ecmascript and Duktape/C function calls.</p>
|
|
|
|
<h2>Value stack (of a context)</h2>
|
|
|
|
<p>Storage for tagged values belonging to current activations in a
|
|
context's call stack.</p>
|
|
|
|
<p>The values kept in a value stack are traditional tagged <a href="#stack-type">types</a>.
|
|
Stack entries are indexed either from the bottom (>= 0) or from the top
|
|
(< 0) of the most recent function call.
|
|
</p>
|
|
|
|
<h2>Value stack index</h2>
|
|
|
|
<p>Non-negative (>= 0) indices refer to stack entries in the
|
|
current stack frame, relative to the frame bottom:</p>
|
|
|
|
<pre class="stack">
|
|
[ 0 1 2 3 4 5! ]
|
|
</pre>
|
|
|
|
<p>Negative (< 0) indices refer to stack entries relative to the top:</p>
|
|
|
|
<pre class="stack">
|
|
[ -6 -5 -4 -3 -2 -1! ]
|
|
</pre>
|
|
|
|
<p>The special constant <code>DUK_INVALID_INDEX</code> 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".</p>
|
|
|
|
<p>The <i>value stack top</i> (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.</p>
|
|
|
|
<pre class="stack">
|
|
[ 0 1 2 3 4 5! 6? ]
|
|
</pre>
|
|
|
|
<div class="note">
|
|
<p>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.</p>
|
|
</div>
|
|
|
|
<h2 id="stack-type">Stack type</h2>
|
|
|
|
<div class="table-wrap">
|
|
<table>
|
|
<tr class="header"><th>Type</th><th>Type constant</th><th>Type mask constant</th><th>Description</th><th>Heap alloc</th></tr>
|
|
<tr><td>(none)</td><td>DUK_TYPE_NONE</td><td>DUK_TYPE_MASK_NONE</td><td>no type (missing value, invalid index, etc)</td><td>no</td></tr>
|
|
<tr><td>undefined</td><td>DUK_TYPE_UNDEFINED</td><td>DUK_TYPE_MASK_UNDEFINED</td><td><code>undefined</code></td><td>no</td></tr>
|
|
<tr><td>null</td><td>DUK_TYPE_NULL</td><td>DUK_TYPE_MASK_NULL</td><td><code>null</code></td><td>no</td></tr>
|
|
<tr><td>boolean</td><td>DUK_TYPE_BOOLEAN</td><td>DUK_TYPE_MASK_BOOLEAN</td><td><code>true</code> and <code>false</code></td><td>no</td></tr>
|
|
<tr><td>number</td><td>DUK_TYPE_NUMBER</td><td>DUK_TYPE_MASK_NUMBER</td><td>IEEE double</td><td>no</td></tr>
|
|
<tr><td>string</td><td>DUK_TYPE_STRING</td><td>DUK_TYPE_MASK_STRING</td><td>immutable string</td><td>yes</td></tr>
|
|
<tr><td>object</td><td>DUK_TYPE_OBJECT</td><td>DUK_TYPE_MASK_OBJECT</td><td>object with properties</td><td>yes</td></tr>
|
|
<tr><td>buffer</td><td>DUK_TYPE_BUFFER</td><td>DUK_TYPE_MASK_BUFFER</td><td>mutable byte buffer, fixed/dynamic</td><td>yes</td></tr>
|
|
<tr><td>pointer</td><td>DUK_TYPE_POINTER</td><td>DUK_TYPE_MASK_POINTER</td><td>opaque pointer (void *)</td><td>no</td></tr>
|
|
<tr><td>lightfunc</td><td>DUK_TYPE_LIGHTFUNC</td><td>DUK_TYPE_MASK_LIGHTFUNC</td><td>plain Duktape/C pointer (non-object)</td><td>no</td></tr>
|
|
</table>
|
|
</div>
|
|
|
|
<p>The "Heap alloc" column indicates whether the tagged value points to
|
|
a heap allocated object with possibly additional allocations (like object
|
|
property table).</p>
|
|
|
|
<h2>Stack type mask</h2>
|
|
|
|
<p>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:</p>
|
|
|
|
<pre class="c-code">
|
|
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");
|
|
}
|
|
</pre>
|
|
|
|
<p>There is a specific API call for matching a set of types even more
|
|
conveniently:</p>
|
|
|
|
<pre class="c-code">
|
|
if (duk_check_type_mask(ctx, -3, DUK_TYPE_MASK_NUMBER |
|
|
DUK_TYPE_MASK_STRING |
|
|
DUK_TYPE_MASK_OBJECT)) {
|
|
printf("type is number, string, or object\n");
|
|
}
|
|
</pre>
|
|
|
|
<h2>Array index</h2>
|
|
|
|
<p>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 <code>obj[123]</code>
|
|
is really just a shorthand for <code>obj["123"]</code>.</p>
|
|
|
|
<p>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.</p>
|
|
|
|
<h2>Duktape/C function</h2>
|
|
|
|
<p>A C function with a Duktape/C API signature can be associated with an
|
|
Ecmascript function object or a lightfunc value, and gets called when
|
|
the associated value is called from Ecmascript code. Example:</p>
|
|
<pre class="c-code">
|
|
int my_func(duk_context *ctx) {
|
|
duk_push_int(ctx, 123);
|
|
return 1;
|
|
}
|
|
</pre>
|
|
|
|
<p>Argument count given in value stack is specified when the corresponding
|
|
Ecmascript function object is created: either a fixed number of arguments
|
|
of <code>DUK_VARARGS</code> for getting arguments "as is". Extra arguments
|
|
are dropped and missing arguments padded with <code>undefined</code> as necessary.
|
|
Use <code><a href="#duk_get_top">duk_get_top()</a></code> to determine number of
|
|
actual arguments.
|
|
</p>
|
|
|
|
<p>Function return values:</p>
|
|
<ul>
|
|
<li>Return value 1: stack top contains return value.</li>
|
|
<li>Return value 0: return value is <code>undefined</code>.</li>
|
|
<li>Return value <0: shorthand for throwing errors, use <code>DUK_RET_xxx</code>
|
|
constants which are negative variants of <code>DUK_ERR_xxx</code>.</li>
|
|
<li>Return value >1: reserved, currently invalid.</li>
|
|
</ul>
|
|
|
|
<p>No error message can be given when using the error shorthand:</p>
|
|
<pre class="c-code">
|
|
int my_func(duk_context *ctx) {
|
|
if (duk_get_top(ctx) == 0) {
|
|
/* throw TypeError if no arguments given */
|
|
return DUK_RET_TYPE_ERROR;
|
|
}
|
|
/* ... */
|
|
}
|
|
</pre>
|
|
|
|
<h2>Stashes</h2>
|
|
|
|
<p>A stash is an object reachable from C code using the Duktape/C API, but
|
|
which is unreachable from Ecmascript code. Stashes allow C code to store
|
|
internal state which can be safely isolated from Ecmascript code. There are
|
|
three stashes:</p>
|
|
<ul>
|
|
<li>Heap stash: shared by all threads in the same heap.</li>
|
|
<li>Global stash: shared by all threads which share a global object.</li>
|
|
<li>Thread stash: specific to a certain thread.</li>
|
|
</ul>
|
|
|