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.
 
 
 
 
 
 

127 lines
5.5 KiB

<h1 id="comparisontolua">Comparison to Lua</h1>
<p>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.</p>
<h2>Array and stack indices are zero-based</h2>
<p>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 <code>DUK_INVALID_INDEX</code> is used instead in Duktape.</p>
<p>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]).</p>
<h2>Object type represents functions and threads</h2>
<p>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.</p>
<h2>Lua userdata and lightuserdata</h2>
<p>The concept closest to Lua <code>userdata</code> is the Duktape <code>buffer</code>
type, with the following differences:</p>
<ul>
<li>Duktape buffers can be resizable, Lua userdata values cannot. If a
Duktape buffer is resizable, its data pointer is no longer guaranteed
to be stable.</li>
<li>Duktape buffers are raw byte arrays without any properties, Lua userdata
objects can store an environment reference.</li>
</ul>
<p>Lua <code>lightuserdata</code> and Duktape <code>pointer</code> are essentially
the same.</p>
<p>If you need to associate properties with a Duktape buffer, you can use
a buffer object instead (or create your own object and store the plain 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.</p>
<h2>Garbage collection</h2>
<p>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
(disable <code>DUK_USE_VOLUNTARY_GC</code>). Lua has an incremental collector with
no pauses, but has no reference counting.</p>
<p>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).</p>
<h2>duk_safe_call() vs. lua_cpcall()</h2>
<p><code>duk_safe_call()</code> 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.</p>
<p><code>lua_cpcall()</code> creates a new stack frame.</p>
<h2>Bytecode dump/load</h2>
<p>Starting from Duktape 1.3 Duktape has a bytecode dump/load mechanism
similar to Lua <code>lua_dump()</code>. See
<a href="#bytecodedumpload">Bytecode dump/load</a>.</p>
<h2>Metatables</h2>
<p>There is no equivalent of Lua metatables in Ecmascript E5/E5.1, but
<a href="http://www.ecma-international.org/ecma-262/6.0/index.html#sec-proxy-objects">Ecmascript ES2015 Proxy objects</a>
provide similar functionality. To allow property virtualization better than available in
E5/E5.1, Duktape implements an <a href="#es6-proxy">ES2015 Proxy subset</a>.</p>
<h2>lua_next() vs. duk_next()</h2>
<p><code>lua_next()</code> replaces the previous key and value with a new pair,
while <code>duk_next()</code> does not; the caller needs to explicitly pop the
key and/or value.</p>
<h2>Raw accessors</h2>
<p>There is no equivalent to Lua raw table access functions like
<code>lua_rawget</code>. One can use the following Ecmascript built-ins
for a similar effect (though not with respect to performance):
<a href="http://www.ecma-international.org/ecma-262/5.1/#sec-15.2.3.3">Object.getOwnPropertyDescriptor ( O, P )</a>,
<a href="http://www.ecma-international.org/ecma-262/5.1/#sec-15.2.3.6">Object.defineProperty ( O, P, Attributes )</a>.</p>
<h2>Coroutines</h2>
<p>There are no primitives for coroutine control in the Duktape API
(Lua API has e.g. <code>lua_resume</code>). Coroutines can only be controlled
using the functions exposed by the <code>Duktape</code> built-in. Further,
Duktape has quite many coroutine yield restrictions now; for instance,
coroutines cannot yield from inside constructor calls or getter/setter calls.</p>
<h2>Multiple return values</h2>
<p>Lua supports multiple return values, Duktape (or Ecmascript) currently
doesn't. This may change with Ecmascript ES2015, 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.</p>
<h2>Weak references</h2>
<p>Lua supports weak references. Duktape currently doesn't.</p>
<h2>Unicode</h2>
<p>Lua has no built-in Unicode support (strings are byte strings), while
Duktape has support for 16-bit Unicode as part of Ecmascript compliance.</p>
<h2>Streaming compilation</h2>
<p>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.</p>