Comparison to Lua

Duktape borrows a lot from Lua conceptually. Below are a few notes on what's different in Duktape compared to Lua. This may be useful if you're already familiar with Lua.

Array and stack indices are zero-based

All array and stack indices are zero-based, not one-based as in Lua. So, bottom of stack is 0, second element from bottom is 1, and top element is -1. Because 0 is no longer available to denote an invalid/non-existent element, the constant DUK_INVALID_INDEX is used instead in Duktape.

String indices are also zero-based, and slices are indicated with an inclusive start index and an exclusive end index (i.e. [start,end[). In Lua, slices are indicated with inclusive indices (i.e. [start,end]).

Object type represents functions and threads

In Lua functions and threads are a separate type from objects. In Duktape the object type is used for plain objects, Ecmascript and native functions, and threads (coroutines). As a result, all of these have a mutable and extensible set of properties.

Lua userdata and lightuserdata

The concept closest to Lua userdata is the Duktape buffer type, with the following differences:

Lua lightuserdata and Duktape pointer are essentially the same.

If you need to associate properties with a Duktape buffer, you can use an actual object and have the buffer as its property. You can then add a finalizer to the object to free any resources related to the buffer. This works reasonably well as long as nothing else holds a reference to the buffer. If this were the case, the buffer could get used after the object had already been finalized. To safeguard against this, the native C structure should have a flag indicating whether the data structure is open or closed. This is good practice anyway for robust native code.

Garbage collection

Duktape has a combined reference counting and non-incremental mark-and-sweep garbage collector (mark-and-sweep is needed only for reference cycles). Collection pauses can be avoided by disabling voluntary mark-and-sweep passes (DUK_OPT_NO_VOLUNTARY_GC). Lua has an incremental collector with no pauses, but has no reference counting.

Duktape has an emergency garbage collector. Lua 5.2 has an emergency garbage collector while Lua 5.1 does not (there is an emergency GC patch though).

duk_safe_call() vs. lua_cpcall()

duk_safe_call() is a protected C function call which operates in the existing value stack frame. The function call is not visible on the call stack all.

lua_cpcall() creates a new stack frame.

Bytecode use

Duktape Ecmascript function bytecode is currently a purely internal matter. Code cannot currently be loaded from an external pre-compiled bytecode file. Similarly, there is no equivalent to e.g. lua_dump().

Metatables

There is no equivalent of Lua metatables in Ecmascript E5/E5.1, but Ecmascript E6 Proxy objects provide similar functionality. To allow property virtualization better than available in E5/E5.1, Duktape implements an ES6 Proxy subset.

lua_next() vs. duk_next()

lua_next() replaces the previous key and value with a new pair, while duk_next() does not; the caller needs to explicitly pop the key and/or value.

Raw accessors

There is no equivalent to Lua raw table access functions like lua_rawget. One can use the following Ecmascript built-ins for a similar effect (though not with respect to performance): Object.getOwnPropertyDescriptor ( O, P ), Object.defineProperty ( O, P, Attributes ).

Coroutines

There are no primitives for coroutine control in the Duktape API (Lua API has e.g. lua_resume). Coroutines can only be controlled using the functions exposed by the Duktape built-in. Further, Duktape has quite many coroutine yield restrictions now; for instance, coroutines cannot yield from inside constructor calls or getter/setter calls.

Multiple return values

Lua supports multiple return values, Duktape (or Ecmascript) currently doesn't. This may change with Ecmascript E6, which has a syntax for multiple value returns. The Duktape/C API reserves return values above 1 so that they may be later used for multiple return values.

Weak references

Lua supports weak references. Duktape currently doesn't.

Unicode

Lua has no built-in Unicode support (strings are byte strings), while Duktape has support for 16-bit Unicode as part of Ecmascript compliance.

Streaming compilation

Lua has a streaming compilation API which is good when code is read from the disk or perhaps decompressed on-the-fly. Duktape currently does not support streaming compilation because it needs multiple passes over the source code.