Browse Source

Merge pull request #1164 from svaarala/es6-object-coercion-cleanups

ES6 Object constructor coercion cleanups
pull/1160/head
Sami Vaarala 8 years ago
committed by GitHub
parent
commit
51be5d49be
  1. 10
      RELEASES.rst
  2. 5
      doc/release-notes-v2-0.rst
  3. 1
      src-input/duk_api_internal.h
  4. 16
      src-input/duk_api_stack.c
  5. 31
      src-input/duk_bi_object.c
  6. 10
      src-input/duk_bi_reflect.c

10
RELEASES.rst

@ -1727,9 +1727,13 @@ Planned
Buffer.prototype.toString() does UTF-8 decoding (previously buffer data
was copied into internal string representation as is) (GH-1020)
* Incompatible change: ES6 argument policy for Object.keys() etc. Instead of
throwing a TypeError, they now either coerce to an object or treat the
primitive as a non-extensible object with no properties (GH-1028)
* Incompatible change: change Object constructor argument coercion policy
to match ES6 requirements for .keys(), .getOwnPropertyNames(),
.getOwnPropertyDescriptor(), .getPrototypeOf(), .freeze(), .isFrozen(),
.seal(), .isSealed(), .preventExtensions(), and .isExtensible();
instead of rejecting non-objects with a TypeError, they are now coerced
to objects or treated as non-extensible objects with no own properties
(GH-1028, GH-1164)
* Incompatible change: plain pointer values now test true in instanceof
(plainPointer instanceof Duktape.Pointer === true) (GH-864)

5
doc/release-notes-v2-0.rst

@ -1066,6 +1066,11 @@ Other incompatible changes
requirements. For example ``function foo() {"ecmascript"}`` is now
``function foo() { [ecmascript code] }``.
* Object constructor methods like Object.keys(), Object.freeze(), etc now
follow more lenient ES6 coercion semantics: non-object arguments are either
coerced to objects or treated like non-extensible objects with no own
properties.
* Duktape.info() now returns an object rather than an array. The object has
named properties like ``.type`` and ``.enext`` for the internal fields which
is easier to version and work with. The names of the properties are not

1
src-input/duk_api_internal.h

@ -216,6 +216,7 @@ DUK_INTERNAL_DECL void duk_require_constructable(duk_context *ctx, duk_idx_t idx
DUK_INTERNAL_DECL void duk_resolve_nonbound_function(duk_context *ctx);
DUK_INTERNAL_DECL duk_idx_t duk_get_top_require_min(duk_context *ctx, duk_idx_t min_top);
DUK_INTERNAL_DECL duk_idx_t duk_get_top_index_unsafe(duk_context *ctx);
DUK_INTERNAL_DECL void duk_pop_unsafe(duk_context *ctx);

16
src-input/duk_api_stack.c

@ -374,6 +374,22 @@ DUK_EXTERNAL duk_idx_t duk_get_top(duk_context *ctx) {
return (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
}
/* Internal helper to get current top but to require a minimum top value
* (TypeError if not met).
*/
DUK_INTERNAL duk_idx_t duk_get_top_require_min(duk_context *ctx, duk_idx_t min_top) {
duk_hthread *thr = (duk_hthread *) ctx;
duk_idx_t ret;
DUK_ASSERT_CTX_VALID(ctx);
ret = (duk_idx_t) (thr->valstack_top - thr->valstack_bottom);
if (ret < min_top) {
DUK_ERROR_TYPE_INVALID_ARGS(thr);
}
return ret;
}
/* Set stack top within currently allocated range, but don't reallocate.
* This is performance critical especially for call handling, so whenever
* changing, profile and look at generated code.

31
src-input/duk_bi_object.c

@ -57,10 +57,7 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor_assign(duk_context *ctx) {
duk_idx_t nargs;
duk_int_t idx;
nargs = duk_get_top(ctx);
if (nargs < 1) {
DUK_DCERROR_TYPE_INVALID_ARGS((duk_hthread *) ctx);
}
nargs = duk_get_top_require_min(ctx, 1 /*min_top*/);
duk_to_object(ctx, 0);
for (idx = 1; idx < nargs; idx++) {
@ -79,8 +76,9 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor_assign(duk_context *ctx) {
duk_put_prop(ctx, 0);
/* [ target ... enum ] */
}
duk_pop(ctx);
/* Could pop enumerator, but unnecessary because of duk_set_top()
* below.
*/
}
duk_set_top(ctx, 1);
@ -98,24 +96,15 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is(duk_context *ctx) {
#if defined(DUK_USE_OBJECT_BUILTIN)
DUK_INTERNAL duk_ret_t duk_bi_object_constructor_create(duk_context *ctx) {
duk_tval *tv;
duk_hobject *proto = NULL;
duk_hobject *proto;
DUK_ASSERT_TOP(ctx, 2);
#if defined(DUK_USE_BUFFEROBJECT_SUPPORT)
duk_hbufobj_promote_plain(ctx, 0);
#endif
tv = duk_get_tval(ctx, 0);
DUK_ASSERT(tv != NULL);
if (DUK_TVAL_IS_NULL(tv)) {
DUK_ASSERT(proto == NULL);
} else if (DUK_TVAL_IS_OBJECT(tv)) {
proto = DUK_TVAL_GET_OBJECT(tv);
DUK_ASSERT(proto != NULL);
} else {
DUK_DCERROR_TYPE_INVALID_ARGS((duk_hthread *) ctx);
}
proto = duk_require_hobject_accept_mask(ctx, 0, DUK_TYPE_MASK_NULL);
DUK_ASSERT(proto != NULL || duk_is_null(ctx, 0));
(void) duk_push_object_helper_proto(ctx,
DUK_HOBJECT_FLAG_EXTENSIBLE |
@ -302,8 +291,7 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is_sealed_frozen_shared(duk_con
* is considered to be already sealed and frozen.
*/
h = duk_get_hobject(ctx, 0);
duk_push_boolean(ctx, (h == NULL) ?
1 :
duk_push_boolean(ctx, (h == NULL) ||
duk_hobject_object_is_sealed_frozen_helper((duk_hthread *) ctx, h, is_frozen /*is_frozen*/));
}
return 1;
@ -393,7 +381,6 @@ DUK_INTERNAL duk_ret_t duk_bi_object_getprototype_shared(duk_context *ctx) {
if (magic == 0) {
DUK_ASSERT_TOP(ctx, 0);
duk_push_this_coercible_to_object(ctx);
tv = DUK_HTHREAD_THIS_PTR(thr);
}
DUK_ASSERT(duk_get_top(ctx) >= 1);
if (magic < 2) {
@ -651,7 +638,7 @@ DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is_extensible(duk_context *ctx)
h = duk_require_hobject_accept_mask(ctx, 0, DUK_TYPE_MASK_LIGHTFUNC | DUK_TYPE_MASK_BUFFER);
}
duk_push_boolean(ctx, h != NULL && DUK_HOBJECT_HAS_EXTENSIBLE(h));
duk_push_boolean(ctx, (h != NULL) && DUK_HOBJECT_HAS_EXTENSIBLE(h));
return 1;
}
#endif /* DUK_USE_OBJECT_BUILTIN || DUK_USE_REFLECT_BUILTIN */

10
src-input/duk_bi_reflect.c

@ -36,10 +36,7 @@ DUK_INTERNAL duk_ret_t duk_bi_reflect_object_get(duk_context *ctx) {
duk_tval *tv_key;
duk_idx_t nargs;
nargs = duk_get_top(ctx);
if (nargs < 2) {
DUK_DCERROR_TYPE_INVALID_ARGS((duk_hthread *) ctx);
}
nargs = duk_get_top_require_min(ctx, 2 /*min_top*/);
(void) duk_require_hobject(ctx, 0);
(void) duk_to_string(ctx, 1);
if (nargs >= 3 && !duk_strict_equals(ctx, 0, 2)) {
@ -86,10 +83,7 @@ DUK_INTERNAL duk_ret_t duk_bi_reflect_object_set(duk_context *ctx) {
duk_idx_t nargs;
duk_bool_t ret;
nargs = duk_get_top(ctx);
if (nargs < 3) {
DUK_DCERROR_TYPE_INVALID_ARGS((duk_hthread *) ctx);
}
nargs = duk_get_top_require_min(ctx, 3 /*min_top*/);
(void) duk_require_hobject(ctx, 0);
(void) duk_to_string(ctx, 1);
if (nargs >= 4 && !duk_strict_equals(ctx, 0, 3)) {

Loading…
Cancel
Save