* Fix Proxy.revocable() revoker function .name and .length properties
(empty name, 0 length).
* Summarize a revoked proxy as '[object RevokedProxy]' in internal readable
summary string, and add test coverage.
* Rename internal duk_push_class_string() as duk_push_objproto_tostring()
for clarity, the helper has Object.prototype.toString() semantics
(except when avoid_side_effects = 1).
* Fix duk_push_objproto_tostring() behavior for revoked Proxies, required
behavior is to throw (this happens in the @@toStringTag lookup which is
unconditional).
* Rename duk_get_top_index_unsafe() -> duk_get_top_index_known() for clarity.
* Add more duk_get_top_index_known() call sites when value stack is known
to have >= 1 entries.
* Rename duk_pop_unsafe() and variants to duk_pop_known() which is more
descriptive.
* Use duk_push_{undefined,tval}_unsafe() instead of direct valstack_top
manipulation in executor and a few other places.
* Add test coverage for chained Proxies in call setup.
* Minor code improvements.
* Implement Proxy.revocable() and add test case coverage for some
Proxy revocation basics.
* Fix revoked Proxy handling in instanceof and Array.isArray(), and
add test coverage.
* Fix revoked Proxy handling in call setup, and add test coverage.
Chained Proxies still not supported in call handling.
* Add stack top asserts for internal duk_prop_xxx.c file APIs:
defown, delete, enum, get, getown, has, ownpropkeys, set.
* Fix unused duk_hobject layouts from property table init code
in src-tools.
Switch to using WTF-8 for duk_hstring string representation. The main
differences to previous extended CESU-8/UTF-8 are: (1) valid surrogate
pairs are automatically combined to UTF-8 on string intern while invalid
surrogate characters are encoded in CESU-8, and (2) ECMAScript code always
sees surrogate pairs for non-BMP characters.
Together, these make it more natural to work with non-BMP strings for both
ECMAScript (which no longer sees extended codepoints as before) and native
code (which now sees valid UTF-8 for non-BMP whenever possible).
Internally the main change is in string interning which now always sanitizes
input strings (but no Symbols) to WTF-8. Also all call sites where the byte
representation of strings are dealt with need fixing. WTF-8 leads to some
challenges because it's no longer possible to e.g. find a substring with a
naive byte compare: surrogate characters may either appear directly (CESU-8)
or baked into a non-BMP UTF-8 byte sequence.
The main places where this needs complex handling include:
* charCodeAt / codePointAt
* Extracting a substring
* String .replace()
* String .startsWith() and .endsWith()
* String .split() and search functions (like .indexOf())
* RegExp matching
* String cache behavior
This commit fixes all the necessary sites with minimal baseline implementations
which are in some cases much slower than the previous CESU-8 ones. Further work
is needed to optimize the WTF-8 variants to perform close to CESU-8.
* Rework duk_heaphdr and subclass assertions into functions to
reduce debug build size.
* Add explicit object validity assert passes to mark-and-sweep.
This allows detection of invalid internal structures especially
when used with GC torture.
* Rename assertion macros for consistency, e.g. from
DUK_ASSERT_HSTRING_VALID to DUK_HSTRING_ASSERT_VALID.
Both duk_hthread and duk_context typedefs resolve to struct duk_hthread
internally. In external API duk_context resolves to struct duk_hthread
which is intentionally left undefined as the struct itself is not
dereferenced. Change internal code to use duk_hthread exclusively which
removes unnecessary and awkward thr <-> ctx casts from internals.
The basic guidelines are:
* Public API uses duk_context in prototype declarations. The intent is to
hide the internal type, and there's already a wide dependency on the
type name.
* All internal code, both declarations and definitions, use duk_hthread
exclusively. This is done even for API functions, i.e. an API function
declared as "void duk_foo(duk_context *ctx);" is then defined as
"void duk_foo(duk_hthread *thr);".
When the flag is set, there is either no subclass C struct for the
duk_hobject, or there is a subclass C struct but there are no references
needing DECREF/marking in the struct.
This allows DECREF and mark-and-sweep to handle duk_hobjects with less
overhead for the common cases of plain objects and arrays (and some other
less commonly collected structs like duk_hnatfunc).
Also change Duktape.Thread.prototype internal class from Thread to Object:
with the other changes internal code now assumes that if an object's class
is Thread, it has the duk_hthread memory layout which wouldn't be the case
for Duktape.Thread.prototype.
* 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.
Saves a few hundred bytes of footprint:
* duk_dup_0() = duk_dup(ctx, 0), duk_dup_1() = duk_dup(ctx, 1), etc.
* duk_dup_m2() = duk_dup(ctx, -2), etc.
* duk_dup_m1() is not added, because duk_dup_top() is the same thing
Change handling of plain buffers so that they behave like ArrayBuffer
instances to Ecmascript code, with limitations such as not being
extensible and all properties being virtualized. This simplifies
Ecmascript code as plain buffers are just lightweight ArrayBuffers
(similarly to how lightfuncs appear as function objects). There are
a lot of small changes in how the built-in objects and methods, and
the C API deals with plain buffer values.
Also make a few small changes to plain pointer and lightfunc handling
to improve consistency with how plain buffers are now handled.
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.
Add a C API binding for Object.defineProperty(): duk_def_prop().
In addition to Object.defineProperty() features, the API call provides a
"force" flag which allows properties to be added to non-extensible objects
and non-configurable properties to be changed (except virtual properties
which are immutable).
Because the name duk_def_prop() conflicts with internal calls, rename them
from duk_def_prop*() to duk_xdef_prop*(). This rename also makes it clearer
that the internal duk_xdef_prop*() calls have non-compliant, internal
semantics.
Also reimplement Object.defineProperty() and Object.defineProperties() (and
duk_def_prop()) so that they share the same internal helpers, and there is
no need for a temporary property descriptor object which is unnecessary churn.
Detailed changes:
- New helper to prepare (validate and normalize) property descriptors
- New helper to implement Object.defineProperty() internals, leaving
out validation of the property descriptor
- Reimplement Object.defineProperty() using the new helpers
- Reimplement Object.defineProperties() using the new helpers
- Reimplement duk_define_property() using the new helpers, so that a
temporary property descriptor object is no longer created
- Add support for "force" flag to Object.defineProperty()
* 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.