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.

1049 lines
40 KiB

=========================
Duktape 2.0 release notes
=========================
Release overview
================
Main changes in this release (see RELEASES.rst for full details):
* Improve buffer bindings: plain buffers now behave like ArrayBuffers,
and Duktape.Buffer has been removed with ArrayBuffer taking its place.
* FIXME
The release has API incompatible changes, see upgrading notes below.
Upgrading from Duktape 1.5.x
============================
There are API incompatible changes in this release. Whenever possible the
incompatible changes cause a compilation error (or warning) so that fixing
call sites should be straightforward. Below are instructions on how to
migrate from 1.5.x to 2.0.0. There are also bug fixes and other minor
behavioral changes which may affect some applications, see ``RELEASES.rst``
for details.
There are backwards compatible providers for some removed/modified API calls
in ``extras/duk-v1-compat``.
Supporting Duktape 1.x and Duktape 2.x simultaneously
-----------------------------------------------------
For C code you can use the ``DUK_VERSION`` define to support both Duktape 1.x
and 2.x in the same application. For example::
#if (DUK_VERSION >= 20000)
rc = duk_safe_call(ctx, my_safe_call, NULL, 1 /*nargs*/, 1 /*nrets*/);
#else
rc = duk_safe_call(ctx, my_safe_call, 1 /*nargs*/, 1 /*nrets*/);
#endif
If you're developing against Duktape master before 2.x release, ``DUK_VERSION``
is set to 19999 so that you can use::
#if (DUK_VERSION >= 19999)
rc = duk_safe_call(ctx, my_safe_call, NULL, 1 /*nargs*/, 1 /*nrets*/);
#else
rc = duk_safe_call(ctx, my_safe_call, 1 /*nargs*/, 1 /*nrets*/);
#endif
Similarly for Ecmascript code you can::
var plainBuffer;
if (Duktape.version >= 19999) {
plainBuffer = ArrayBuffer.plainOf(bufferObject);
} else {
plainBuffer = Duktape.Buffer(bufferObject);
}
Or you can detect features specifically::
var plainBuffer = (typeof ArrayBuffer.plainOf === 'function' ?
ArrayBuffer.plainOf : Duktape.Buffer)(bufferObject);
DUK_OPT_xxx feature option support removed
------------------------------------------
Duktape 2.x no longer supports ``DUK_OPT_xxx`` options given via the compiler
command line. Instead, all options are encoded in ``duk_config.h``.
To use custom Duktape options, use the ``tools/configure.py`` tool to create
a customized ``duk_config.h`` and prepared Duktape sources matching the
configuration. For example to enable assertions and fastint support::
$ python2 tools/configure.py \
--output-directory /tmp/output \
--source-directory src-input \
--config-metadata config \
-DDUK_USE_FASTINT \
-DDUK_USE_ASSERTIONS
# Prepared duk_config.h header and Duktape sources (duktape.h and
# duktape.c) are in /tmp/output. Compile normally with your application.
$ gcc -std=c99 -Wall -o/tmp/test -I/tmp/output /tmp/output/duktape.c \
my_application.c -lm
See http://wiki.duktape.org/Configuring.html for details and examples.
To upgrade:
* If you're using the Duktape default configuration (and no ``DUK_OPT_xxx``)
compiler options, no actions are needed.
* Otherwise, remove ``DUK_OPT_xxx`` options from the compilation command and
add a ``tools/configure.py`` pre-step to your build. Add the equivalent
``DUK_USE_xxx`` options to ``tools/configure.py`` argument list; for example
``-DDUK_USE_FASTINT``.
* If you're using a ``duk_custom.h`` header there are three simple approaches:
- To embed your custom header into ``duk_config.h`` statically, use
``--fixup-file duk_custom.h`` in ``tools/configure.py`` options.
- To include your custom header at compilation time, similarly to
``DUK_OPT_HAVE_CUSTOM_H``, use ``--fixup-line '#include "duk_custom.h"'``
in ``tools/configure.py`` options.
- Finally, you can remove your custom header and add the equivalent options
to ``tools/configure.py`` when possible.
Built-ins disabled in configuration are now absent
--------------------------------------------------
If a built-in is disabled when running ``configure.py``, it won't be present
in the Ecmascript environment. For example, with ``-UDUK_USE_ES6_PROXY``::
duk> new Proxy()
ReferenceError: identifier 'Proxy' undefined
at [anon] (duk_js_var.c:1262) internal
at global (input:1) preventsyield
duk> typeof Proxy
= "undefined"
In Duktape 1.x the binding was present but would just throw an Error when
invoked::
duk> new Proxy()
Error: unknown error (rc -1)
at Proxy () native strict construct preventsyield
at global (input:1) preventsyield
duk> typeof Proxy
= "function"
The revised behavior saves footprint and allows scripts to detect
supported built-ins reliably using e.g.::
if (typeof Proxy === 'function') {
// supported
}
To upgrade:
* In most cases no action is needed. If your code relies on the builtins
being present but throwing an error (which seems unlikely), such call
sites need to be fixed.
Tooling changes
---------------
There are some tooling changes in this release:
* The distributable now includes raw sources in ``src-input/`` and some
tooling in ``tools/``. This allows Duktape sources to be modified and
re-amalgamated directly from the distributable. The distributable still
includes sources prepared using default configuration (``src/``,
``src-noline/``, and ``src-separate``) and some configuration examples.
* The tooling includes a new ``tools/configure.py`` tool which creates
a ``duk_config.h`` and matching prepared sources simultaneously. This
allows use of ROM built-ins from the distributable (previously required a
manual ``dist.py --rom-support ...`` command.
* The ``make_dist.py`` utility in Duktape main repo has been renamed to
``dist.py`` and no longer supports ``--rom-support``,
``--rom-auto-lightfunc``, and ``--user-builtin-metadata`` options. Use
the ``tools/configure.py`` tool instead, which supports these options.
However, ``--user-builtin-metadata`` has been renamed ``--builtin-file``.
* The ``config/genconfig.py`` has been relocated to ``tools/genconfig.py`` in
the distributable. It can still be used as a standalone tool, but using
configure.py is recommended instead.
To upgrade:
* If you're just using the default sources and ``duk_config.h`` in the
distributable, no changes are needed.
* If you're using ``genconfig.py``, check the path; correct path is now
``tools/genconfig.py``. Consider replacing genconfig.py with configure.py.
* If you're using ROM built-ins via ``make_dist.py``, change your build to
use ``tools/configure.py`` instead, and rename ``--user-builtins-metadata``
options to ``--builtin-file``.
Dist package file changes
-------------------------
* Configuration metadata is now in unpacked form in ``dist/config`` to match
the Duktape master repo and make config files more convenient to patch.
The ``dist/tools/genconfig.py`` tool no longer accepts a tar.gz metadata
argument.
* The pre-built ``duk_config.h`` examples have been removed as somewhat
useless. Use ``dist/tools/configure.py`` (or ``dist/tools/genconfig.py)``
to generate ``duk_config.h`` files.
* ``dist/duk_build_meta.json`` has been renamed to ``dist/duk_dist_meta.json``
for clarity. It no longer contains string data scanned from source files.
This metadata is now in source directories, e.g.
``dist/src/duk_source_meta.json`` as the string set potentially depends
on options used to prepare sources.
* Source metadata, e.g. ``dist/src/metadata.json``, has been renamed to
``dist/src/duk_source_meta.json`` for clarity. The metadata contains
Duktape version information, strings scanned from source files, and for
combined (amalgamated) sources the line number metadata.
Buffer behavior changes
-----------------------
There are a lot of buffer behavior changes in the 2.x release; see detailed
changes below. Here's a summary of changes:
* Plain buffers now behave like ArrayBuffer instances (to the extent possible)
for Ecmascript code, and ``Duktape.Buffer`` has been removed, with
``ArrayBuffer`` taking its place. There are numerous small changes to how
plain buffers are treated by standard built-ins as a result.
* Plain buffer and ArrayBuffer have numeric indices (e.g. ``arrayBuf[6]``) as
before, but the properties are not enumerable so that they won't be e.g.
JSON serialized.
* Plain buffer string coercion (``String(plainBuffer)``) now mimics ArrayBuffer
and usually results in the string ``[object ArrayBuffer]``.
* Default built-in bindings no longer provide the ability to do a 1:1
buffer-to-string coercion where the buffer bytes are used directly as the
internal string bytes (see https://github.com/svaarala/duktape/issues/1005).
C code can still do so using ``duk_buffer_to_string()`` (or by direct buffer
and string operations) and can expose such a binding to Ecmascript code.
* Node.js Buffer binding has been aligned more with Node.js v6.9.1 (from
Node.js v0.12.1) and some (but not all) behavior differences to actual
Node.js have been fixed.
* Disabling ``DUK_USE_BUFFEROBJECT_SUPPORT`` allows use of plain buffers in
the C API, and allows manipulation of plain buffers in Ecmascript code via
their virtual properties (index properties, ``.length``, etc). Plain buffers
will still inherit from ``ArrayBuffer.prototype``, but all ArrayBuffer, typed
array, and Node.js Buffer methods will be non-functional. Plain buffers
won't object coerce. Duktape custom built-ins operating on plain buffers
(like Duktape.dec() with hex or base-64 encoding) continue to work. (This
behavior is not guaranteed and may change even in minor versions.)
To upgrade:
* If you're using buffers in general, review http://wiki.duktape.org/HowtoBuffers.html
which has been updated for Duktape 2.0.
* If you're using standard ArrayBuffers and typed arrays, no changes should
normally be necessary, however:
- Typed array ``.subarray()`` handling of arguments inheriting from a typed
array (rather than being a direct instance) has been fixed so that the result
has the default prototype for the result type (e.g. ``Uint8Array.prototype``)
rather than being copied from the argument.
* If you're using the Node.js Buffer binding, review the following:
- Node.js Buffer ``.slice()`` handling of arguments inheriting from a Buffer
(rather than being a direct instance) has been fixed so that the result has
the default prototype (``Buffer.prototype``) rather than being copied from
the argument.
- Node.js Buffer ``.concat()`` always returns a buffer copy, even for a
one-element input array which had special handling in Node.js v0.12.1.
- Node.hs Buffer.prototype ``.toString()`` now decodes the input buffer
using UTF-8, emitting replacement characters for invalid UTF-8 sequences.
- Review Buffer code for Node.js Buffer changes between Node.js versions
v0.12.1 and v6.9.1 in general.
* If you're using plain buffers, review their usage especially in Ecmascript
code.
- One important change is that ``String(plainBuffer)`` and ``duk_to_string()``
for a buffer does not work as before, use new ``duk_buffer_to_string()``
C API call instead. There's no equivalent function for the default
Ecmascript built-ins.
- Another important change is that plain buffers, like ArrayBuffer objects,
boolean coerce to ``true`` regardless of buffer size (zero or larger) and
contents.
* If you're using ``Duktape.Buffer``, the following new built-ins replace its
functionality (and more):
- ``ArrayBuffer.allocPlain()``: to allocate a new (fixed) plain buffer
- ``ArrayBuffer.plainOf()``: to get the underlying plain buffer of any
buffer object (without making a copy)
Some detailed changes (see ``tests/ecmascript/test-dev-plain-buffer.js)`` for
even more detail):
* ``typeof plainBuffer`` is now ``object`` instead of ``buffer``.
- ``plainBuffer instanceof ArrayBuffer`` is true.
* Plain buffer Object.prototype.toString() now usually (assuming no overridden
.toString()) yields ``[object ArrayBuffer]`` instead of ``[object Buffer]``.
* Plain buffer inherits from ArrayBuffer.prototype instead of
Duktape.Buffer.prototype.
* For a plain buffer ``duk_to_string()`` no longer creates a string with the
same underlying bytes, but results in ``[object ArrayBuffer]`` instead
(unless ``.toString()`` or ``.valueOf()`` has been overridden); in
particular, using a plain buffer as an object property key is misleading
as ``obj[buf]`` is (usually) equivalent to ``obj['[object ArrayBuffer]']``.
``duk_to_buffer()`` for a string still results in a plain buffer with the
same underlying bytes as before.
* A new ``duk_buffer_to_string()`` API call converts any buffer value to a
string with the same underlying bytes as in the buffer (like
``duk_to_string()`` did in Duktape 1.x). Ecmascript built-ins no longer
have this ability directly.
* ``duk_to_boolean()`` for plain buffer: always true, even if buffer is zero
length.
* ``duk_to_primitive()`` for plain buffer: plain buffer now not considered a
primitive value (same as for a full ArrayBuffer object) and usually coerces
to the string ``[object ArrayBuffer]``.
* ``duk_is_primitive()`` for a plain buffer is now false to match how
``duk_to_primitive()`` deals with plain buffers (i.e. coerces them rather
than returning them as is).
* When a plain buffer is used as the "this" binding of a function call, it is
ToObject() coerced to an actual ArrayBuffer if the call target is non-strict.
This mimics what happens to e.g. plain strings. Lightfuncs have also been
revised to behave the same way (in Duktape 1.x they would not be ToObject()
coerced in this situation).
* ``new ArrayBuffer(plainBuffer)`` no longer creates a new ArrayBuffer with
the same underlying plain buffer; instead, the plain buffer gets coerced to
zero and creates a zero-length ArrayBuffer. This matches how an ArrayBuffer
argument is handled in ``new ArrayBuffer()``.
- ``new Buffer(plainBuffer)`` no longer special cases plain buffer and gets
treated like an ArrayBuffer: a fresh Buffer with matching ``.length`` is
created and index elements are copied into the result buffer (in effect
making an actual buffer copy).
* XXX: This will most likely change with Node.js Buffer binding version
update, as Node.js Buffer constructor also recognizes ArrayBuffers now.
- ``ArrayBuffer.isView(nodejsBuffer)`` is now true to reflect the fact that
Node.js Buffers are Uint8Arrays in newer Node.js versions.
* ``new Uint32Array(plainBuffer)`` and other typed array constructors coerce
the argument plain buffer into an ArrayBuffer instance which is then used
as the result ``.buffer``. The coerced ArrayBuffer shares the same
underlying plain buffer (storage).
* XXX: This may still change.
* ``new DataView(plainBuffer)`` is now accepted (Duktape 1.x would reject with
TypeError) and gets treated like for typed arrays: the plain buffer is coerced
into an ArrayBuffer with the same underlying plain buffer (storage).
* ``ArrayBuffer.prototype.slice()`` accepts a plain buffer and the resulting slice
(which is a copy) is also a plain buffer.
* ``typedarray.prototype.subarray()`` accepts a plain buffer and the resulting slice
is an ArrayBuffer because plain buffers cannot represent a view offset/length.
(This could arguably also be a Uint8Array because ES6 doesn't recognize
ArrayBuffers which have a view offset. However, as custom behavior, .subarray()
also returns an ArrayBuffer when called with an ArrayBuffer instance, so the
current plain buffer behavior is consistent with that.)
* Node.js ``Buffer.prototype.slice()`` accepts a plain buffer and the result is a
Node.js Buffer (which itself is a special Uint8Array instance).
* ``plainBuffer.valueOf()`` ordinarily backed by ``Object.prototype.valueOf()``
returns `Object(plainBuffer)`, i.e. converts plain buffer to an actual ArrayBuffer.
This matches normal ``Object.prototype.valueOf()`` behavior, e.g. plain string is
coerced into a String object.
- ``JSON.stringify()`` now recognizes plain buffers like ArrayBuffer instances;
the result is typically ``{}`` without a ``.toJSON()`` implementation.
* XXX: JX/JC treatment may still change.
* ``Object.freeze()`` not allowed for plain buffers or buffer objects (Duktape
1.x allowed silently) because array index elements cannot be made non-writable.
This is an internal limitation and failing with a TypeError signals this to the
caller (and matches how e.g. V8 handles ``Object.freeze(new Uint8Array(4))``).
- Typed array ``.subarray()`` and Node.js Buffer ``.slice()`` result internal
prototype is now set to the default prototype of the result type (e.g. initial
value of ``Uint8Array.prototype`` if the input is an Uint8Array) rather than
being copied from the argument.
* Node.js ``Buffer`` and ``Buffer.prototype`` methods now accept plain buffers.
* XXX: this (and other buffer mixing) may still change.
Pointer behavior changes
------------------------
There are very minor changes to pointer value behavior:
* ``plainPointer instanceof Duktape.Pointer`` now evaluates to ``true``
(``false`` in Duktape 1.x).
To upgrade:
* If you're using pointer values in Ecmascript code, check pointer handling.
Lightfunc behavior changes
--------------------------
There are very minor changes to lightfunc value behavior:
* ``duk_is_primitive()`` now returns false for lightfuncs; this is more in
line with how lightfuncs behave in Ecmascript ToPrimitive() coercion and
matches how plain buffers work in Duktape 2.x.
* ``[[DefaultValue]]`` coercion now considers lightfuncs non-primitive
(previously considered primitive and thus accepted as ``[[DefaultValue]]``
result).
* When a lightfunc is used as the "this" binding of a function call, it is
ToObject() coerced to a full function when the call target is non-strict.
Duktape 1.x would not coerce the lightfunc to an object in this situation;
the change was made to match plain buffer behavior. Note that because
lightfuncs themselves are considered strict functions, this only happens
when the call target is not a lightfunc but the "this" binding is.
To upgrade:
* If you're using lightfuncs, review their handling.
print() and alert() globals removed
-----------------------------------
The ``print()`` and ``alert()`` globals were removed because they depended on
stdout/stderr which is a portability issue on some platforms. Further, even
if stdout/stderr is available, it's not always the appropriate place for debug
printouts, so it's cleaner if the application provides its own debug/console
logging functions.
To upgrade:
* If you don't use ``print()`` or ``alert()`` no action is needed; they simply
won't be a part of the global object anymore.
* If a simple ``print()`` and/or ``alert()`` suffices, you can use something
like this::
static duk_ret_t my_print(duk_context *ctx) {
duk_push_string(ctx, " ");
duk_insert(ctx, 0);
duk_join(ctx, duk_get_top(ctx) - 1);
fprintf(stdout, "%s\n", duk_to_string(ctx, -1)); /* 'stderr' for alert() */
fflush(stdout); /* may or may not want to flush, depends on application */
return 0;
}
/* And after Duktape heap creation (or after each new thread with a
* fresh global environment):
*/
duk_push_c_function(ctx, my_print, DUK_VARARGS);
duk_put_global_string(ctx, "print");
* If you do need ``print()`` and/or ``alert()`` with the Duktape 1.x
semantics you can include the following extra into your compilation:
``extras/print-alert``.
Built-in CommonJS module framework removed
------------------------------------------
The built-in CommonJS module loading framework consisting of ``require()``,
``Duktape.modSearch()`` and ``Duktape.modLoaded`` was removed; a module
framework isn't always needed, and when it is, it's difficult for a single
framework to match the very different use cases.
To upgrade:
* If you don't use the built-in module loading framework, no action is needed.
* If you do use the built-in module loading framework and want to continue
using a module loader with Duktape 1.x semantics, you can include the
following extra into your compilation: ``extras/module-duktape``.
* If you're upgrading, there are also other alternatives to module loading.
For example, the ``extras/module-node`` module loader provides Node.js-like
semantics with a more flexible module resolution and loading process.
Duktape.Logger, duk_log(), and duk_log_va() removed
---------------------------------------------------
The built-in logging framework consisting of ``Duktape.Logger``, ``duk_log()``,
and ``duk_log_va()`` were removed because they depended on stdout/stderr which
is a portability issue on some platforms. The logging framework also didn't
always match user expectations: for some uses it was too simple (lacking e.g.
expressive backend configuration); for other uses it was too complex (too
high a ROM/RAM footprint for some embedded uses). Sometimes an existing API
like ``console.log()`` was preferred while in other cases a platform specific
logging binding was more appropriate.
To upgrade:
* If you don't need ``Duktape.Logger`` or the C logging API calls, no action
is needed.
* If you do need ``Duktape.Logger`` and/or the C logging API calls with
Duktape 1.x semantics, you can include the following extra into your
compilation: ``extras/logging``.
duk_safe_call() userdata
------------------------
There's a new userdata argument for ``duk_safe_call()``::
/* Duktape 1.x */
typedef duk_ret_t (*duk_safe_call_function) (duk_context *ctx);
duk_int_t duk_safe_call(duk_context *ctx, duk_safe_call_function func, duk_idx_t nargs, duk_idx_t nrets);
/* Duktape 2.x */
typedef duk_ret_t (*duk_safe_call_function) (duk_context *ctx, void *udata);
duk_int_t duk_safe_call(duk_context *ctx, duk_safe_call_function func, void *udata, duk_idx_t nargs, duk_idx_t nrets);
The additional userdata argument makes it easier to pass a C pointer to the
safe-called function without the need to push a pointer onto the value stack.
Multiple C values can be passed by packing them into a stack-allocated struct
and passing a pointer to the struct as the userdata.
To upgrade:
* Add a userdata argument to duk_safe_call() call sites. If no relevant
userdata exists, pass a NULL.
* Add a userdata argument to safe call targets. If no relevant userdata
exists, just ignore the argument.
* If a call site needs to support both Duktape 1.x and Duktape 2.x, use
a DUK_VERSION preprocessor check::
#if (DUK_VERSION >= 20000)
duk_ret_t my_safe_call(duk_context *ctx, void *udata) {
#else
duk_ret_t my_safe_call(duk_context *ctx) {
#endif
/* Ignore 'udata'. */
}
/* ... */
#if (DUK_VERSION >= 20000)
rc = duk_safe_call(ctx, my_safe_call, NULL, 1 /*nargs*/, 1 /*nrets*/);
#else
rc = duk_safe_call(ctx, my_safe_call, 1 /*nargs*/, 1 /*nrets*/);
#endif
Duktape specific error codes removed from API
---------------------------------------------
Duktape specific error codes were removed from the public API and from
internals. These error codes were not very widely used, and they didn't
have an Ecmascript counterpart (for example, a ``DUK_ERR_API_ERROR`` mapped
to a plain ``Error`` object) which was confusing. The removed error codes
and defines are:
* ``DUK_ERR_UNIMPLEMENTED_ERROR`` / ``DUK_RET_UNIMPLEMENTED_ERROR``
* ``DUK_ERR_UNSUPPORTED_ERROR`` / ``DUK_RET_UNSUPPORTED_ERROR``
* ``DUK_ERR_INTERNAL_ERROR`` / ``DUK_RET_INTERNAL_ERROR``
* ``DUK_ERR_ALLOC_ERROR`` / ``DUK_RET_ALLOC_ERROR``
* ``DUK_ERR_ASSERTION_ERROR`` / ``DUK_RET_ASSERTION_ERROR``
* ``DUK_ERR_API_ERROR`` / ``DUK_RET_API_ERROR``
* ``DUK_ERR_UNCAUGHT_ERROR`` / ``DUK_RET_UNCAUGHT_ERROR``
Duktape API related errors were also changed to map to either a ``TypeError``
or ``RangeError`` instead of a plain ``Error``:
* A ``RangeError`` is used when an argument is out of bounds; for example:
a value stack index is out of bounds, pop count is too large, not enough
value stack items for call argument count.
* A ``TypeError`` is used when a value has incorrect type, and is thrown by
for example ``duk_require_boolean()``. ``TypeError`` is also typically
used when nothing else applies.
To upgrade:
* If you use the custom error codes (``DUK_ERR_INTERNAL_ERROR`` etc) in your
code, convert to using standard error codes (``DUK_ERR_TYPE_ERROR``, etc).
* If you depend on API errors mapping to a plain ``Error``, revise such code
to accept also ``TypeError`` or ``RangeError``. (In general depending on a
specific error type should be only be done when it's absolute necessary.)
duk_error(), duk_error_va(), duk_throw(), duk_fatal() have a return value
-------------------------------------------------------------------------
The prototype return value for these error throwers was changed from ``void``
to ``duk_ret_t`` which allows for idioms like::
if (argvalue < 0) {
return duk_error(ctx, DUK_ERR_TYPE_ERROR,
"invalid arg: %d", (int) argvalue);
}
To upgrade:
* Without an explicit cast to ``(void) duk_error(...)`` you may get some new
compiler warnings. Fix by adding the void cast, or convert the call sites
to use the ``return duk_error(...)`` idiom where applicable.
duk_dump_context_stdout() and duk_dump_context_stderr() removed
---------------------------------------------------------------
These two API calls were helpers based on ``duk_push_context_dump()`` which
would write the context dump directly to stdout/stderr. Having a dependency
on stdout/stderr is a portability concern so the calls were removed in
Duktape 2.x.
To upgrade:
* Replace ``duk_dump_context_stdout()`` with an explicit call sequence like::
duk_push_context_dump(ctx);
printf("%s\n", duk_to_string(ctx, -1));
duk_pop(ctx);
Similarly for ``duk_dump_context_stderr()``.
* Alternatively, include extras/duk-v1-compat into your compilation to add back
the removed API calls.
duk_to_defaultvalue() removed
-----------------------------
The ``duk_to_defaultvalue()`` API call was rather technical: it invoked the
internal ``[[DefaultValue]]`` algorithm which is used in ES5.1 as part of
the ToPrimitive() coercion (``duk_to_primitive()``). ES6 no longer specifies
``[[DefaultValue]]`` which has been folded into ToPrimitive(). The API call
thus no longer makes much sense.
To upgrade:
* If you're using ``duk_to_defaultvalue()`` (which is unlikely), you can in
most cases replace it with ``duk_to_primitive()``. The main difference
is that ``duk_to_primitive()`` accepts all argument types (returning
those considered primitive as is) while ``duk_to_defaultvalue()`` rejects
primitive value arguments. See the ES5.1/ES6 specifications for exact
differences between the two.
* Here's an example replacement. Replace this::
duk_to_defaultvalue(ctx, idx, hint);
with::
duk_require_type_mask(ctx, idx, DUK_TYPE_MASK_OBJECT |
DUK_TYPE_MASK_BUFFER |
DUK_TYPE_MASK_LIGHTFUNC);
duk_to_primitive(ctx, idx, hint);
* Alternatively, include extras/duk-v1-compat into your compilation to add back
the removed API call.
File I/O Duktape C API calls were removed
-----------------------------------------
Some platform don't have file I/O API calls (even ANSI), while on others they
are present but don't actually map to the file system (instead, a platform
specific API is used to access the actual file system). Finally, there are
character encoding issues with ANSI C file I/O APIs e.g. on Windows, so that
the built-in file I/O support didn't always work as expected.
To improve portability, the following Duktape C API calls depending on
platform file I/O (fopen() etc) were removed (moved to extras):
* duk_push_string_file()
* duk_compile_file()
* duk_pcompile_file()
* duk_eval_file()
* duk_eval_file_noresult()
* duk_peval_file()
* duk_peval_file_noresult()
To upgrade:
* If you don't use these API calls, no action is needed.
* If you use these API calls you can e.g. implement a helper to push a file
as a string (like ``duk_push_string_file()``) and then implement any needed
compile/eval helpers based on that.
* Alternatively, you can include the following extra into your compilation:
``extras/duk-v1-compat``. The extra provides Duktape 1.x compatible
file-related API call bindings.
duk_debugger_attach() and duk_debugger_attach_custom() merged
-------------------------------------------------------------
The ``duk_debugger_attach_custom()`` API call in Duktape 1.x has been renamed
to ``duk_debugger_attach()`` to eliminate an unnecessary API call variant from
the public API. The remaining debugger attach call always includes an
AppRequest callback argument.
To upgrade:
* ``duk_debugger_attach_custom()`` call sites: rename API call to
``duk_debugger_attach()``; no argument changes are needed.
* ``duk_debugger_attach()`` call sites: add a NULL ``request_cb`` callback
argument.
* If a call site needs to support both Duktape 1.x and Duktape 2.x::
/* Alternative #1: conditional call name. */
#if (DUK_VERSION >= 20000)
duk_debugger_attach(
#else
duk_debugger_attach_custom(
#endif
read_cb,
write_cb,
peek_cb,
read_flush_cb,
write_flush_cb,
request_cb, /* NULL OK if not necessary */
detached_cb,
udata);
/* Alternative #2: conditional request_cb argument. */
duk_debugger_attach(
read_cb,
write_cb,
peek_cb,
read_flush_cb,
write_flush_cb,
#if (DUK_VERSION >= 20000)
request_cb, /* NULL OK if not necessary */
#endif
detached_cb,
udata);
Debug protocol version bumped from 1 to 2
-----------------------------------------
Because there are small incompatible changes in the debug protocol in this
release, the debug protocol version has been bumped from 1 to 2. The version
is provided by the ``DUK_DEBUG_PROTOCOL_VERSION`` constant, and also appears
in the debug protocol version identification string.
To upgrade:
* Review the debug protocol changes and ensure debug client has corresponding
changes.
* Update debug client code to support both versions 1 and 2, or version 2 only.
Debugger detached callback has a duk_context pointer argument
-------------------------------------------------------------
The debugger detached callback is allowed to immediately reattach the debugger
session. However, the detached callback didn't have a ``duk_context *``
argument in Duktape 1.x so that the relevant context pointer needed to be passed
e.g. via the udata argument which is awkward.
In Duktape 2.x an explicit context argument was added::
/* Duktape 1.x */
typedef void (*duk_debug_detached_function) (void *udata);
/* Duktape 2.x */
typedef void (*duk_debug_detached_function) (duk_context *ctx, void *udata);
To upgrade:
* If you're using ``duk_debugger_attach()``, add an additional ``duk_context *``
argument to the detached callback.
* If support for both Duktape 1.x and 2.x is desired, use::
#if DUK_VERSION >= 20000
void my_detached_cb(duk_context *ctx, void *udata) {
#else
void my_detached_cb(void *udata) {
#end
/* ... */
}
Debugger print/alert and logger forwarding removed
--------------------------------------------------
Forwarding of ``print()``, ``alert()``, and log writes, enabled using config
options ``DUK_USE_DEBUGGER_FWD_PRINTALERT`` and ``DUK_USE_DEBUGGER_FWD_LOGGING``,
was removed as part of removing the bindings themselves. Also debugger
notifications Print (0x02), Alert (0x03), Log (0x04) were deprecated.
To upgrade:
* No changes are needed, but print/alert and logger notification support can
be removed from a debug client.
* If you rely on print/alert or logger forwarding in your debugger setup, you
can add custom print/alert or logger forwarding by implementing print/alert
or logging yourself and using AppNotify (``duk_debugger_notify()``) to
forward print/alert or logger text.
Debug print config options changed
----------------------------------
Debug print related config options were reworked as follows:
* Debug prints no longer automatically go to ``stderr``. Instead, an
application must define ``DUK_USE_DEBUG_WRITE()`` in ``duk_config.h``
when ``DUK_USE_DEBUG`` is enabled. The macro is called to write debug log
lines; there's no default provider to avoid platform I/O dependencies.
Using a user-provided macro removes a dependency on platform I/O and also
allows debug logs to be filtered and redirected in whatever manner is most
useful for the application. Example provider::
#define DUK_USE_DEBUG_WRITE(level,file,line,func,msg) do { \
fprintf(stderr, "D%ld %s:%ld (%s): %s\n", \
(long) (level), (file), (long) (line), (func), (msg)); \
} while (0)
See http://wiki.duktape.org/HowtoDebugPrints.html for more information.
* Debug level options ``DUK_USE_DPRINT``, ``DUK_USE_DDPRINT``, and
``DUK_DDDPRINT`` were replaced with a single config option
``DUK_USE_DEBUG_LEVEL`` with a numeric value:
- 0 is minimal logging (matches ``DUK_USE_DPRINT``)
- 1 is verbose logging (matches ``DUK_USE_DDPRINT``)
- 2 is very verbose logging (matches ``DUK_USE_DDDPRINT``)
To upgrade:
* If you're not using debug prints, no action is needed.
* If you're using debug prints:
- Add a ``DUK_USE_DEBUG_WRITE()`` to your ``duk_config.h``. By itself it
won't enable debug prints so it's safe to add even when debug prints are
disabled.
- Convert debug level options from ``DUK_USE_{D,DD,DDD}PRINT`` to the
equivalent ``DUK_USE_DEBUG_LEVEL`` (0, 1, or 2).
Internal duk_harray affects debugger array inspection
-----------------------------------------------------
Duktape 2.x introduces an internal ``duk_harray`` type to represent arrays.
The array ``.length`` property is no longer stored in the property table of
the array but is a C struct field in ``duk_harray`` and the property visible
to Ecmascript code is virtual.
As a result, array ``.length`` is not visible when inspecting ordinary array
properties using e.g. GetObjPropDesc or GetObjPropDescRange. Instead, array
``.length`` is an artificial property ``"length"`` returned by GetHeapObjInfo.
To upgrade:
* If the debug client uses array ``.length`` for e.g. UI purposes, ensure
the artificial property ``"length"`` is used instead.
Other debugger changes
----------------------
* Artificial properties renamed for consistency with internal renaming:
- ``compiledfunction`` -> ``compfunc``
- ``nativefunction`` -> ``natfunc``
- ``bufferobject`` -> ``bufobj``
- ``bound`` -> ``boundfunc``
Fatal error and panic handling reworked
---------------------------------------
The following changes were made to fatal error and panic handling:
* Fatal error function signature was simplied from::
/* Duktape 1.x */
void func(duk_context *ctx, duk_errcode_t code, const char *msg);
to::
/* Duktape 2.x */
void func(void *udata, const char *msg);
where the ``udata`` argument is the userdata argument given in heap creation.
* ``duk_fatal()`` error code argument was removed to match the signature
change.
* The entire concept of "panic errors" was removed and replaced with calls to
the fatal error mechanism. There's a user-registered (optional) fatal error
handler in heap creation, and a built-in default fatal error handler which
is called if user code doesn't provide a fatal error handler.
Some fatal errors, currently assertion failures, happen without a Duktape
heap/thread context so that a user-registered handler cannot be called
(there's no heap reference to look it up). For these errors the default
fatal error handler is always called, with the userdata argument as ``NULL``.
The default fatal error handler can be replaced by editing ``duk_config.h``.
To upgrade:
* If you're not providing a fatal error handler nor using a custom panic
handler, no action is needed -- however, providing a fatal error handler
in heap creation is **strongly recommended**, see
http://wiki.duktape.org/HowtoFatalErrors.html for instructions.
The default fatal error handler will by default cause an intentional
segfault; to improve this behavior define ``DUK_USE_FATAL_HANDLER()``
in your ``duk_config.h``.
* If you have a fatal error handler, update its signature::
/* Duktape 1.x */
void my_fatal(duk_context *ctx, duk_errcode_t error_code, const char *msg) {
/* ... */
}
/* Duktape 2.x */
void my_fatal(void *udata, const char *msg) {
/* ... */
}
* If you're using ``duk_fatal()`` API calls, remove the error code argument::
/* Duktape 1.x */
duk_fatal(ctx, DUK_ERR_INTERNAL_ERROR, "assumption failed");
/* Duktape 2.x */
duk_fatal(ctx, "assumption failed");
* If you have a custom panic handler in your ``duk_config.h``, convert it to
a default fatal error handler, also provided by ``duk_config.h``. Both
Duktape 1.x panic handler and Duktape 2.x default fatal error handler apply
to all Duktape heaps (rather than a specific Duktape heap).
InitJS support removed
----------------------
Both Duktape InitJS (``DUK_USE_BUILTIN_INITJS``) and user InitJS
(``DUK_USE_USER_INITJS``) were removed. Duktape built-in InitJS is no
longer needed (and was never used for very much). User InitJS was rarely
used and it's not a full solution because custom environment initialization
may also involve native initialization code which isn't supported by the
mechanism.
To upgrade:
* Duktape built-in InitJS removal requires no user code changes.
* If you're using the user InitJS option, call sites need to be modified to
run the init code explicitly on heap/thread creation.
Enumeration order changes
-------------------------
Enumeration order for ``Object.getOwnPropertyNames()`` has been changed to
match ES6/ES7 ``[[OwnPropertyKeys]]`` enumeration order, which is:
* Array indices in ascending order
* Normal (non-array-index) property keys in insertion order
* Symbols in insertion order
While not required by ES6/ES7, the same enumeration order is also used in
Duktape 2.x for ``for-in``, ``Object.keys()``, and ``duk_enum()``. A related
change is that ``duk_enum()`` flags ``DUK_ENUM_ARRAY_INDICES_ONLY`` and
``DUK_ENUM_SORT_ARRAY_INDICES`` can now be used independently.
The revised enumeration order makes enumeration behavior more predictable
and matches other modern engines. In particular, sparse arrays (arrays
without an internal array part) now enumerate identically to dense arrays.
To upgrade:
* Check application code for enumeration assumptions.
Other incompatible changes
--------------------------
* Normal and constructor function call argument limit is now 255, down from
the previous 511.
* If a user function is called using the identifier 'eval', such a call won't
get tailcall optimized even if otherwise possible.
* ``duk_char_code_at()`` and ``String.charCodeAt()`` now return 0xFFFD (Unicode
replacement character) if the string cannot be decoded as extended UTF-8,
previously an error was thrown. This situation never occurs for standard
Ecmascript strings or valid UTF-8 strings.
* Legacy octal literal handling has been improved to match more closely with
ES6 Annex B. Octal look-alike decimal literals like "0778" and "0778.123"
are now allowed.
* Legacy octal escape handling in string literals has been improved to match
more closely with ES6 Annex B and other engines: "\078" is not accepted and
is the same as "\u00078", "\8" and "\9" are accepted as literal "8" and "9"
(even in strict mode).
Known issues
============
FIXME.
Raw issues from test runs
=========================
API tests
---------
FIXME.
Ecmascript tests
----------------
FIXME.
test262
-------
FIXME.