summaryrefslogtreecommitdiffstats
path: root/src/civetweb/src/third_party/duktape-1.8.0/src-separate/duk_bi_object.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/civetweb/src/third_party/duktape-1.8.0/src-separate/duk_bi_object.c')
-rw-r--r--src/civetweb/src/third_party/duktape-1.8.0/src-separate/duk_bi_object.c577
1 files changed, 577 insertions, 0 deletions
diff --git a/src/civetweb/src/third_party/duktape-1.8.0/src-separate/duk_bi_object.c b/src/civetweb/src/third_party/duktape-1.8.0/src-separate/duk_bi_object.c
new file mode 100644
index 000000000..28509ab34
--- /dev/null
+++ b/src/civetweb/src/third_party/duktape-1.8.0/src-separate/duk_bi_object.c
@@ -0,0 +1,577 @@
+/*
+ * Object built-ins
+ */
+
+#include "duk_internal.h"
+
+DUK_INTERNAL duk_ret_t duk_bi_object_constructor(duk_context *ctx) {
+ if (!duk_is_constructor_call(ctx) &&
+ !duk_is_null_or_undefined(ctx, 0)) {
+ duk_to_object(ctx, 0);
+ return 1;
+ }
+
+ if (duk_is_object(ctx, 0)) {
+ return 1;
+ }
+
+ /* Pointer and buffer primitive values are treated like other
+ * primitives values which have a fully fledged object counterpart:
+ * promote to an object value. Lightfuncs are coerced with
+ * ToObject() even they could also be returned as is.
+ */
+ if (duk_check_type_mask(ctx, 0, DUK_TYPE_MASK_STRING |
+ DUK_TYPE_MASK_BOOLEAN |
+ DUK_TYPE_MASK_NUMBER |
+ DUK_TYPE_MASK_POINTER |
+ DUK_TYPE_MASK_BUFFER |
+ DUK_TYPE_MASK_LIGHTFUNC)) {
+ duk_to_object(ctx, 0);
+ return 1;
+ }
+
+ duk_push_object_helper(ctx,
+ DUK_HOBJECT_FLAG_EXTENSIBLE |
+ DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
+ DUK_BIDX_OBJECT_PROTOTYPE);
+ return 1;
+}
+
+/* Shared helper to implement Object.getPrototypeOf and the ES6
+ * Object.prototype.__proto__ getter.
+ *
+ * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-object.prototype.__proto__
+ */
+DUK_INTERNAL duk_ret_t duk_bi_object_getprototype_shared(duk_context *ctx) {
+ duk_hthread *thr = (duk_hthread *) ctx;
+ duk_hobject *h;
+ duk_hobject *proto;
+
+ DUK_UNREF(thr);
+
+ /* magic: 0=getter call, 1=Object.getPrototypeOf */
+ if (duk_get_current_magic(ctx) == 0) {
+ duk_push_this_coercible_to_object(ctx);
+ duk_insert(ctx, 0);
+ }
+
+ h = duk_require_hobject_or_lfunc(ctx, 0);
+ /* h is NULL for lightfunc */
+
+ /* XXX: should the API call handle this directly, i.e. attempt
+ * to duk_push_hobject(ctx, null) would push a null instead?
+ * (On the other hand 'undefined' would be just as logical, but
+ * not wanted here.)
+ */
+
+ if (h == NULL) {
+ duk_push_hobject_bidx(ctx, DUK_BIDX_FUNCTION_PROTOTYPE);
+ } else {
+ proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
+ if (proto) {
+ duk_push_hobject(ctx, proto);
+ } else {
+ duk_push_null(ctx);
+ }
+ }
+ return 1;
+}
+
+/* Shared helper to implement ES6 Object.setPrototypeOf and
+ * Object.prototype.__proto__ setter.
+ *
+ * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-get-object.prototype.__proto__
+ * http://www.ecma-international.org/ecma-262/6.0/index.html#sec-object.setprototypeof
+ */
+DUK_INTERNAL duk_ret_t duk_bi_object_setprototype_shared(duk_context *ctx) {
+ duk_hthread *thr = (duk_hthread *) ctx;
+ duk_hobject *h_obj;
+ duk_hobject *h_new_proto;
+ duk_hobject *h_curr;
+ duk_ret_t ret_success = 1; /* retval for success path */
+
+ /* Preliminaries for __proto__ and setPrototypeOf (E6 19.1.2.18 steps 1-4);
+ * magic: 0=setter call, 1=Object.setPrototypeOf
+ */
+ if (duk_get_current_magic(ctx) == 0) {
+ duk_push_this_check_object_coercible(ctx);
+ duk_insert(ctx, 0);
+ if (!duk_check_type_mask(ctx, 1, DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_OBJECT)) {
+ return 0;
+ }
+
+ /* __proto__ setter returns 'undefined' on success unlike the
+ * setPrototypeOf() call which returns the target object.
+ */
+ ret_success = 0;
+ } else {
+ duk_require_object_coercible(ctx, 0);
+ duk_require_type_mask(ctx, 1, DUK_TYPE_MASK_NULL | DUK_TYPE_MASK_OBJECT);
+ }
+
+ h_new_proto = duk_get_hobject(ctx, 1);
+ /* h_new_proto may be NULL */
+ if (duk_is_lightfunc(ctx, 0)) {
+ if (h_new_proto == thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE]) {
+ goto skip;
+ }
+ goto fail_nonextensible;
+ }
+ h_obj = duk_get_hobject(ctx, 0);
+ if (!h_obj) {
+ goto skip;
+ }
+ DUK_ASSERT(h_obj != NULL);
+
+ /* [[SetPrototypeOf]] standard behavior, E6 9.1.2 */
+ /* TODO: implement Proxy object support here */
+
+ if (h_new_proto == DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_obj)) {
+ goto skip;
+ }
+ if (!DUK_HOBJECT_HAS_EXTENSIBLE(h_obj)) {
+ goto fail_nonextensible;
+ }
+ for (h_curr = h_new_proto; h_curr != NULL; h_curr = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_curr)) {
+ /* Loop prevention */
+ if (h_curr == h_obj) {
+ goto fail_loop;
+ }
+ }
+ DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h_obj, h_new_proto);
+ /* fall thru */
+
+ skip:
+ duk_set_top(ctx, 1);
+ return ret_success;
+
+ fail_nonextensible:
+ fail_loop:
+ return DUK_RET_TYPE_ERROR;
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_object_constructor_get_own_property_descriptor(duk_context *ctx) {
+ /* XXX: no need for indirect call */
+ return duk_hobject_object_get_own_property_descriptor(ctx);
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_object_constructor_create(duk_context *ctx) {
+ duk_tval *tv;
+ duk_hobject *proto = NULL;
+
+ DUK_ASSERT_TOP(ctx, 2);
+
+ tv = duk_get_tval(ctx, 0);
+ DUK_ASSERT(tv != NULL);
+ if (DUK_TVAL_IS_NULL(tv)) {
+ ;
+ } else if (DUK_TVAL_IS_OBJECT(tv)) {
+ proto = DUK_TVAL_GET_OBJECT(tv);
+ DUK_ASSERT(proto != NULL);
+ } else {
+ return DUK_RET_TYPE_ERROR;
+ }
+
+ (void) duk_push_object_helper_proto(ctx,
+ DUK_HOBJECT_FLAG_EXTENSIBLE |
+ DUK_HOBJECT_CLASS_AS_FLAGS(DUK_HOBJECT_CLASS_OBJECT),
+ proto);
+
+ if (!duk_is_undefined(ctx, 1)) {
+ /* [ O Properties obj ] */
+
+ duk_replace(ctx, 0);
+
+ /* [ obj Properties ] */
+
+ /* Just call the "original" Object.defineProperties() to
+ * finish up.
+ */
+
+ return duk_bi_object_constructor_define_properties(ctx);
+ }
+
+ /* [ O Properties obj ] */
+
+ return 1;
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_property(duk_context *ctx) {
+ duk_hobject *obj;
+ duk_hstring *key;
+ duk_hobject *get;
+ duk_hobject *set;
+ duk_idx_t idx_value;
+ duk_uint_t defprop_flags;
+
+ DUK_ASSERT(ctx != NULL);
+
+ DUK_DDD(DUK_DDDPRINT("Object.defineProperty(): ctx=%p obj=%!T key=%!T desc=%!T",
+ (void *) ctx,
+ (duk_tval *) duk_get_tval(ctx, 0),
+ (duk_tval *) duk_get_tval(ctx, 1),
+ (duk_tval *) duk_get_tval(ctx, 2)));
+
+ /* [ obj key desc ] */
+
+ /* Lightfuncs are currently supported by coercing to a temporary
+ * Function object; changes will be allowed (the coerced value is
+ * extensible) but will be lost.
+ */
+ obj = duk_require_hobject_or_lfunc_coerce(ctx, 0);
+ (void) duk_to_string(ctx, 1);
+ key = duk_require_hstring(ctx, 1);
+ (void) duk_require_hobject(ctx, 2);
+
+ DUK_ASSERT(obj != NULL);
+ DUK_ASSERT(key != NULL);
+ DUK_ASSERT(duk_get_hobject(ctx, 2) != NULL);
+
+ /*
+ * Validate and convert argument property descriptor (an Ecmascript
+ * object) into a set of defprop_flags and possibly property value,
+ * getter, and/or setter values on the value stack.
+ *
+ * Lightfunc set/get values are coerced to full Functions.
+ */
+
+ duk_hobject_prepare_property_descriptor(ctx,
+ 2 /*idx_desc*/,
+ &defprop_flags,
+ &idx_value,
+ &get,
+ &set);
+
+ /*
+ * Use Object.defineProperty() helper for the actual operation.
+ */
+
+ duk_hobject_define_property_helper(ctx,
+ defprop_flags,
+ obj,
+ key,
+ idx_value,
+ get,
+ set);
+
+ /* Ignore the normalize/validate helper outputs on the value stack,
+ * they're popped automatically.
+ */
+
+ /*
+ * Return target object.
+ */
+
+ duk_push_hobject(ctx, obj);
+ return 1;
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_object_constructor_define_properties(duk_context *ctx) {
+ duk_small_uint_t pass;
+ duk_uint_t defprop_flags;
+ duk_hobject *obj;
+ duk_idx_t idx_value;
+ duk_hobject *get;
+ duk_hobject *set;
+
+ /* Lightfunc handling by ToObject() coercion. */
+ obj = duk_require_hobject_or_lfunc_coerce(ctx, 0); /* target */
+ DUK_ASSERT(obj != NULL);
+
+ duk_to_object(ctx, 1); /* properties object */
+
+ DUK_DDD(DUK_DDDPRINT("target=%!iT, properties=%!iT",
+ (duk_tval *) duk_get_tval(ctx, 0),
+ (duk_tval *) duk_get_tval(ctx, 1)));
+
+ /*
+ * Two pass approach to processing the property descriptors.
+ * On first pass validate and normalize all descriptors before
+ * any changes are made to the target object. On second pass
+ * make the actual modifications to the target object.
+ *
+ * Right now we'll just use the same normalize/validate helper
+ * on both passes, ignoring its outputs on the first pass.
+ */
+
+ for (pass = 0; pass < 2; pass++) {
+ duk_set_top(ctx, 2); /* -> [ hobject props ] */
+ duk_enum(ctx, 1, DUK_ENUM_OWN_PROPERTIES_ONLY /*enum_flags*/);
+
+ for (;;) {
+ duk_hstring *key;
+
+ /* [ hobject props enum(props) ] */
+
+ duk_set_top(ctx, 3);
+
+ if (!duk_next(ctx, 2, 1 /*get_value*/)) {
+ break;
+ }
+
+ DUK_DDD(DUK_DDDPRINT("-> key=%!iT, desc=%!iT",
+ (duk_tval *) duk_get_tval(ctx, -2),
+ (duk_tval *) duk_get_tval(ctx, -1)));
+
+ /* [ hobject props enum(props) key desc ] */
+
+ duk_hobject_prepare_property_descriptor(ctx,
+ 4 /*idx_desc*/,
+ &defprop_flags,
+ &idx_value,
+ &get,
+ &set);
+
+ /* [ hobject props enum(props) key desc value? getter? setter? ] */
+
+ if (pass == 0) {
+ continue;
+ }
+
+ key = duk_get_hstring(ctx, 3);
+ DUK_ASSERT(key != NULL);
+
+ duk_hobject_define_property_helper(ctx,
+ defprop_flags,
+ obj,
+ key,
+ idx_value,
+ get,
+ set);
+ }
+ }
+
+ /*
+ * Return target object
+ */
+
+ duk_dup(ctx, 0);
+ return 1;
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_object_constructor_seal_freeze_shared(duk_context *ctx) {
+ duk_hthread *thr = (duk_hthread *) ctx;
+ duk_hobject *h;
+ duk_bool_t is_freeze;
+
+ h = duk_require_hobject_or_lfunc(ctx, 0);
+ if (!h) {
+ /* Lightfunc, always success. */
+ return 1;
+ }
+
+ is_freeze = (duk_bool_t) duk_get_current_magic(ctx);
+ duk_hobject_object_seal_freeze_helper(thr, h, is_freeze);
+
+ /* Sealed and frozen objects cannot gain any more properties,
+ * so this is a good time to compact them.
+ */
+ duk_hobject_compact_props(thr, h);
+
+ return 1;
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_object_constructor_prevent_extensions(duk_context *ctx) {
+ duk_hthread *thr = (duk_hthread *) ctx;
+ duk_hobject *h;
+
+ h = duk_require_hobject_or_lfunc(ctx, 0);
+ if (!h) {
+ /* Lightfunc, always success. */
+ return 1;
+ }
+ DUK_ASSERT(h != NULL);
+
+ DUK_HOBJECT_CLEAR_EXTENSIBLE(h);
+
+ /* A non-extensible object cannot gain any more properties,
+ * so this is a good time to compact.
+ */
+ duk_hobject_compact_props(thr, h);
+
+ return 1;
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is_sealed_frozen_shared(duk_context *ctx) {
+ duk_hobject *h;
+ duk_bool_t is_frozen;
+ duk_bool_t rc;
+
+ h = duk_require_hobject_or_lfunc(ctx, 0);
+ if (!h) {
+ duk_push_true(ctx); /* frozen and sealed */
+ } else {
+ is_frozen = duk_get_current_magic(ctx);
+ rc = duk_hobject_object_is_sealed_frozen_helper((duk_hthread *) ctx, h, is_frozen /*is_frozen*/);
+ duk_push_boolean(ctx, rc);
+ }
+ return 1;
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_object_constructor_is_extensible(duk_context *ctx) {
+ duk_hobject *h;
+
+ h = duk_require_hobject_or_lfunc(ctx, 0);
+ if (!h) {
+ duk_push_false(ctx);
+ } else {
+ duk_push_boolean(ctx, DUK_HOBJECT_HAS_EXTENSIBLE(h));
+ }
+ return 1;
+}
+
+/* Shared helper for Object.getOwnPropertyNames() and Object.keys().
+ * Magic: 0=getOwnPropertyNames, 1=Object.keys.
+ */
+DUK_INTERNAL duk_ret_t duk_bi_object_constructor_keys_shared(duk_context *ctx) {
+ duk_hthread *thr = (duk_hthread *) ctx;
+ duk_hobject *obj;
+#if defined(DUK_USE_ES6_PROXY)
+ duk_hobject *h_proxy_target;
+ duk_hobject *h_proxy_handler;
+ duk_hobject *h_trap_result;
+ duk_uarridx_t i, len, idx;
+#endif
+ duk_small_uint_t enum_flags;
+
+ DUK_ASSERT_TOP(ctx, 1);
+ DUK_UNREF(thr);
+
+ obj = duk_require_hobject_or_lfunc_coerce(ctx, 0);
+ DUK_ASSERT(obj != NULL);
+ DUK_UNREF(obj);
+
+#if defined(DUK_USE_ES6_PROXY)
+ if (DUK_LIKELY(!duk_hobject_proxy_check(thr,
+ obj,
+ &h_proxy_target,
+ &h_proxy_handler))) {
+ goto skip_proxy;
+ }
+
+ duk_push_hobject(ctx, h_proxy_handler);
+ if (!duk_get_prop_stridx(ctx, -1, DUK_STRIDX_OWN_KEYS)) {
+ /* Careful with reachability here: don't pop 'obj' before pushing
+ * proxy target.
+ */
+ DUK_DDD(DUK_DDDPRINT("no ownKeys trap, get keys of target instead"));
+ duk_pop_2(ctx);
+ duk_push_hobject(ctx, h_proxy_target);
+ duk_replace(ctx, 0);
+ DUK_ASSERT_TOP(ctx, 1);
+ goto skip_proxy;
+ }
+
+ /* [ obj handler trap ] */
+ duk_insert(ctx, -2);
+ duk_push_hobject(ctx, h_proxy_target); /* -> [ obj trap handler target ] */
+ duk_call_method(ctx, 1 /*nargs*/); /* -> [ obj trap_result ] */
+ h_trap_result = duk_require_hobject(ctx, -1);
+ DUK_UNREF(h_trap_result);
+
+ len = (duk_uarridx_t) duk_get_length(ctx, -1);
+ idx = 0;
+ duk_push_array(ctx);
+ for (i = 0; i < len; i++) {
+ /* [ obj trap_result res_arr ] */
+ if (duk_get_prop_index(ctx, -2, i) && duk_is_string(ctx, -1)) {
+ /* XXX: for Object.keys() we should check enumerability of key */
+ /* [ obj trap_result res_arr propname ] */
+ duk_put_prop_index(ctx, -2, idx);
+ idx++;
+ } else {
+ duk_pop(ctx);
+ }
+ }
+
+ /* XXX: missing trap result validation for non-configurable target keys
+ * (must be present), for non-extensible target all target keys must be
+ * present and no extra keys can be present.
+ * http://www.ecma-international.org/ecma-262/6.0/#sec-proxy-object-internal-methods-and-internal-slots-ownpropertykeys
+ */
+
+ /* XXX: for Object.keys() the [[OwnPropertyKeys]] result (trap result)
+ * should be filtered so that only enumerable keys remain. Enumerability
+ * should be checked with [[GetOwnProperty]] on the original object
+ * (i.e., the proxy in this case). If the proxy has a getOwnPropertyDescriptor
+ * trap, it should be triggered for every property. If the proxy doesn't have
+ * the trap, enumerability should be checked against the target object instead.
+ * We don't do any of this now, so Object.keys() and Object.getOwnPropertyNames()
+ * return the same result now for proxy traps. We still do clean up the trap
+ * result, so that Object.keys() and Object.getOwnPropertyNames() will return a
+ * clean array of strings without gaps.
+ */
+ return 1;
+
+ skip_proxy:
+#endif /* DUK_USE_ES6_PROXY */
+
+ DUK_ASSERT_TOP(ctx, 1);
+
+ if (duk_get_current_magic(ctx)) {
+ /* Object.keys */
+ enum_flags = DUK_ENUM_OWN_PROPERTIES_ONLY |
+ DUK_ENUM_NO_PROXY_BEHAVIOR;
+ } else {
+ /* Object.getOwnPropertyNames */
+ enum_flags = DUK_ENUM_INCLUDE_NONENUMERABLE |
+ DUK_ENUM_OWN_PROPERTIES_ONLY |
+ DUK_ENUM_NO_PROXY_BEHAVIOR;
+ }
+
+ return duk_hobject_get_enumerated_keys(ctx, enum_flags);
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_object_prototype_to_string(duk_context *ctx) {
+ duk_push_this(ctx);
+ duk_to_object_class_string_top(ctx);
+ return 1;
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_object_prototype_to_locale_string(duk_context *ctx) {
+ DUK_ASSERT_TOP(ctx, 0);
+ (void) duk_push_this_coercible_to_object(ctx);
+ duk_get_prop_stridx(ctx, 0, DUK_STRIDX_TO_STRING);
+ if (!duk_is_callable(ctx, 1)) {
+ return DUK_RET_TYPE_ERROR;
+ }
+ duk_dup(ctx, 0); /* -> [ O toString O ] */
+ duk_call_method(ctx, 0); /* XXX: call method tail call? */
+ return 1;
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_object_prototype_value_of(duk_context *ctx) {
+ (void) duk_push_this_coercible_to_object(ctx);
+ return 1;
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_object_prototype_is_prototype_of(duk_context *ctx) {
+ duk_hthread *thr = (duk_hthread *) ctx;
+ duk_hobject *h_v;
+ duk_hobject *h_obj;
+
+ DUK_ASSERT_TOP(ctx, 1);
+
+ h_v = duk_get_hobject(ctx, 0);
+ if (!h_v) {
+ duk_push_false(ctx); /* XXX: tail call: return duk_push_false(ctx) */
+ return 1;
+ }
+
+ h_obj = duk_push_this_coercible_to_object(ctx);
+ DUK_ASSERT(h_obj != NULL);
+
+ /* E5.1 Section 15.2.4.6, step 3.a, lookup proto once before compare.
+ * Prototype loops should cause an error to be thrown.
+ */
+ duk_push_boolean(ctx, duk_hobject_prototype_chain_contains(thr, DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_v), h_obj, 0 /*ignore_loop*/));
+ return 1;
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_object_prototype_has_own_property(duk_context *ctx) {
+ return duk_hobject_object_ownprop_helper(ctx, 0 /*required_desc_flags*/);
+}
+
+DUK_INTERNAL duk_ret_t duk_bi_object_prototype_property_is_enumerable(duk_context *ctx) {
+ return duk_hobject_object_ownprop_helper(ctx, DUK_PROPDESC_FLAG_ENUMERABLE /*required_desc_flags*/);
+}