* Keep .prototype value on stack while holding the 'proto' pointer, in case the
value is virtualized and comes from a getter or a Proxy.
* Improve error message for the case where the rval has no .prototype property.
This case comes up often with Duktape/C function constructors because they
don't have a .prototype property by default.
Remove the special ecma-to-ecma call setup code and just use the normal
unprotected call setup code for that instead. Most of the code is the
same; just before calling into the bytecode executor check if the current
executor can be reused, and if so, indicate the situation using a special
return code.
Also remove internal duk_handle_call_protected() and implement all
protected API calls via duk_safe_call(). This reduces footprint and code
duplication further.
Rework call handling to use helpers more to make the call handling code
easier to follow.
Various other minor changer, e.g. DUK_OP_NEW is now DUK_OP_CONSCALL and
bytecode sets up the initial default instance.
Add support for 'new.target' expression without yet adding support for an
explicit newTarget which may differ from the constructor function being
called.
* Strings with 0xFF byte prefix are considered special symbols: they have
typeof "symbol" but still mostly behave as strings (e.g. allow ToString)
so that existing code dealing with internal keys, especially inside
Duktape, can work with fewer changes.
* Strings with 0x80 byte prefix are global symbols, e.g. Symbol.for('foo')
creates the byte representatio: 0x80 "foo"
* Strings with 0x81 byte prefix are unique symbols; the 0x81 byte is followed
by the Symbol description, and an internal string component ensuring
uniqueness is separated by a 0xFF byte (which can never appear anywhere in
an extended UTF-8 string). The unique suffix is up to Duktape internals,
currently two 32-bit counters are used. For example:
0x81 "mySymbol" 0xFF "0-17".
* Well-known symbols use the 0x81 prefix but lack a unique suffix, so their
format is 0x81 <description> 0xFF.
* ES6 distinguishes between an undefined symbol description and an empty
string symbol description. This distinction is not currently visible via
Ecmascript bindings but may be visible in the future. Append an extra
0xFF to the unique suffix when the description is undefined, i.e.
0x81 0xFF <unique suffix> 0xFF.
* Remove 'enumerate' trap.
* Use 'ownKeys' trap for "for-in" too, as specified in ES7.
* Add enumerability check for 'ownKeys' result when used in for-in or
Object.keys(). Because there's no support for 'getOwnPropertyDescriptor'
trap yet, the check will always operate directly on the target object.
These don't play well with the API currently: the Duktape specific error
codes don't have Ecmascript Error class counterparts so they don't get
represented usefully as Ecmascript objects (e.g. AllocError is a plain
Error from Ecmascript point of view).
There's no real need for Duktape specific error code. Some of the codes
had become unused; a couple were used but Ecmascript standard types can
be used instead.
Also minor error message tweaking.
Improve readability by doing the following renames:
* duk_hcompiledfunction -> duk_hcompfunc
* duk_hnativefunction -> duk_hnatfunc
* duk_hbufferobject -> duk_hbufobj
Corresponding renames for all caps defines.
Previously a shared macro string (DUK_STR_UNSUPPORTED) would map to a symbol
(duk_str_unsupported). This worked better in very old compilers where string
sharing might not be supported. However, the approach is awkward to maintain
because it's difficult to ensure unused strings don't cause compiler warnings.
Rework duk_strings.h to provide the string constants directly without declaring
them as symbols. Remove duk_strings.c.
* Use shared error macros and shared error handler to reduce the size of call
sites of common errors.
* Make zero argument DUK_ERROR() calls non-vararg calls to reduce call site
footprint. Non-vararg calls have smaller call sites and because there are
a lot of call sites, this turns out to be significant.
* Remove variadic macros from internal DUK_ERROR() macro set and add separate
macros for argument counts 0 to 4; this is more portable and requires less
conditional code, and works well when a non-vararg call is used for most
error call sites.
* Rework macro / function argument order for the error path, try to keep 'thr'
in the same argument slot to avoid unnecessary register moves.
* Pack linenumber and error code into a single 32-bit argument when possible,
removes one more constant load from the call site.
* Convert some internal errors to RangeErrors when the underlying cause is an
implementation limit (such as a compiler temp limit) rather than an actual
unexpected internal situation.
* Simplify and share a few error messages to reduce string count.
Emscripten depends on a Function's .toString() having a certain format
(beyond what is guaranteed by the E5 specification). In particular, it
won't parse Duktape's current format where the function body is replaced
with a comment indicating the function type, e.g.:
function foo() {/* ecmascript */}
Change this format to indicate the function type using a string literal
(similarly to how directive prologue works):
function foo() {"ecmascript"}
This is equally informational and will work directly with Emscripten.
Also change handling for anonymous functions: substituting "anon" for an
anonymous function in an Ecmascript function's .toString() output is a bit
misleading. It also causes an Emscripten issue when a source regexp expects
there to be no name for an anonymous function in the .toString() output.
* Add duk_require_function() and duk_require_callable() API calls
* Make duk_is_callable() a macro which calls duk_is_function()
* Include index for "invalid index" errors
* Add expected type and offending type/value for duk_require_xxx() errors
* Improve Array.prototype.forEach() and other iterator errors
An external buffer is similar to a dynamic buffer but the external data
pointer is managed by user code rather than Duktape, and may point to an
arbitrary address. For example, user can build an external buffer which
points to a framebuffer and operate on that framebuffer from Ecmascript
code via the buffer.
* Fix outstanding FIXME issues for lightfunc semantics.
* Improve API and Ecmascript testcases to match.
* Clarify lightfunc limitations, e.g. finalizer limitations.
* Guide and API documentation changes for lightfuncs.
* Fix compile warning: duk_str_not_object unused.
When doing a single file build, drop DUK_INTERNAL_DECL declarations which
would otherwise be mapped to "static". This avoids the problem with C++
where a static data symbol is both forward declared and defined.
With this change static definitions must appear before their first use in
the single file build. This requires a change in combine_src.py which is
done in a separate commit.
These were revealed after fixing DUK_SINGLE_FILE, gcc will complain about
these internal functions being declared, defined, but not used. There were
also a few declared functions that did not exist. Compiled binary size was
reduced by a few kilobytes!
Unused functions must be commented out carefully: some functions might be
used with certain feature options but not by the defaults. These removals
were verified with grep.
There are no call sites for DUK_DEBUG_DUMP_HEAP() so all the functions
in duk_debug_heap.c are unused, even with a debug build.
Out of the checked allocation macros, only DUK_REALLOC_INDIRECT_CHECKED() is
actually in use at the moment. This commit just comments the unused stuff
out, but it might be better to just remove the unused stuff entirely.
Note: If 'count' exceeds valstack_max, an "invalid count" message is thrown
(same goes for a negative count). Use the same message also for the case
where 'count' exceeds the source stack depth just a little. Previously the
code would use a different error message for this case.
Duktape 0.11.0 would allow an empty throw (e.g. "throw;") and would
also allow automatic semicolon insertion between "throw" and its
argument, e.g.::
throw
123;
The above must be rejected with a SyntaxError according to E5.1.
Both empty throw and the above newline case are rejected by V8 and
Rhino, so the previous more lenient behavior should not conflict
with real world code.
Partially clean up the duk_set_top() implementation, and fix the 32-bit
pointer wrapping bug where e.g. a top value of 0x20000000UL would wrap
the 32-bit address space (0x20000000UL * sizeof(duk_tval) is 2^32 when
duk_tval is 8 bytes) and would therefore incorrectly be equivalent to
duk_set_top(0).
Other typing fixes.