コード例 #1
0
ファイル: duk_bi_object.c プロジェクト: CarterTsai/duktape
/* Shared helper to implement Object.getPrototypeOf and the ES6
 * Object.prototype.__proto__ getter.
 *
 * https://people.mozilla.org/~jorendorff/es6-draft.html#sec-get-object.prototype.__proto__
 */
DUK_INTERNAL duk_ret_t duk_bi_object_getprototype_shared(duk_context *ctx) {
	duk_hobject *h;
	duk_hobject *proto;

	/* 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(h);
		if (proto) {
			duk_push_hobject(ctx, proto);
		} else {
			duk_push_null(ctx);
		}
	}
	return 1;
}
コード例 #2
0
ファイル: duk_bi_array.c プロジェクト: OakLabsInc/duktape
DUK_INTERNAL duk_ret_t duk_bi_array_prototype_to_string(duk_context *ctx) {
	(void) duk_push_this_coercible_to_object(ctx);
	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_JOIN);

	/* [ ... this func ] */
	if (!duk_is_callable(ctx, -1)) {
		/* Fall back to the initial (original) Object.toString().  We don't
		 * currently have pointers to the built-in functions, only the top
		 * level global objects (like "Array") so this is now done in a bit
		 * of a hacky manner.  It would be cleaner to push the (original)
		 * function and use duk_call_method().
		 */

		/* XXX: 'this' will be ToObject() coerced twice, which is incorrect
		 * but should have no visible side effects.
		 */
		DUK_DDD(DUK_DDDPRINT("this.join is not callable, fall back to (original) Object.toString"));
		duk_set_top(ctx, 0);
		return duk_bi_object_prototype_to_string(ctx);  /* has access to 'this' binding */
	}

	/* [ ... this func ] */

	duk_insert(ctx, -2);

	/* [ ... func this ] */

	DUK_DDD(DUK_DDDPRINT("calling: func=%!iT, this=%!iT",
	                     (duk_tval *) duk_get_tval(ctx, -2),
	                     (duk_tval *) duk_get_tval(ctx, -1)));
	duk_call_method(ctx, 0);

	return 1;
}
コード例 #3
0
ファイル: duk_bi_object.c プロジェクト: cherry-wb/duktape
/* Shared helper to implement Object.getPrototypeOf and the ES6
 * Object.prototype.__proto__ getter.
 *
 * https://people.mozilla.org/~jorendorff/es6-draft.html#sec-get-object.prototype.__proto__
 */
duk_ret_t duk_bi_object_getprototype_shared(duk_context *ctx) {
	duk_hobject *h;

	/* 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(ctx, 0);
	DUK_ASSERT(h != NULL);

	/* 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->prototype) {
		duk_push_hobject(ctx, h->prototype);
	} else {
		duk_push_null(ctx);
	}
	return 1;
}
コード例 #4
0
ファイル: duk_bi_array.c プロジェクト: OakLabsInc/duktape
/* Shared entry code for many Array built-ins.  Note that length is left
 * on stack (it could be popped, but that's not necessary).
 */
DUK_LOCAL duk_uint32_t duk__push_this_obj_len_u32(duk_context *ctx) {
	duk_uint32_t len;

	(void) duk_push_this_coercible_to_object(ctx);
	duk_get_prop_stridx(ctx, -1, DUK_STRIDX_LENGTH);
	len = duk_to_uint32(ctx, -1);

	/* -> [ ... ToObject(this) ToUint32(length) ] */
	return len;
}
コード例 #5
0
ファイル: duk_bi_object.c プロジェクト: CarterTsai/duktape
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 tailcall? */
	return 1;
}
コード例 #6
0
ファイル: duk_bi_object.c プロジェクト: fatcerberus/duktape
DUK_INTERNAL duk_ret_t duk_bi_object_prototype_to_locale_string(duk_hthread *thr) {
	DUK_ASSERT_TOP(thr, 0);
	(void) duk_push_this_coercible_to_object(thr);
	duk_get_prop_stridx_short(thr, 0, DUK_STRIDX_TO_STRING);
#if 0  /* This is mentioned explicitly in the E5.1 spec, but duk_call_method() checks for it in practice. */
	duk_require_callable(thr, 1);
#endif
	duk_dup_0(thr);  /* -> [ O toString O ] */
	duk_call_method(thr, 0);  /* XXX: call method tail call? */
	return 1;
}
コード例 #7
0
ファイル: duk_bi_object.c プロジェクト: harold-b/duktape
/* Shared helper to implement Object.getPrototypeOf,
 * Object.prototype.__proto__ getter, and Reflect.getPrototypeOf.
 *
 * 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) {
	/*
	 *  magic = 0: __proto__ getter
	 *  magic = 1: Object.getPrototypeOf()
	 *  magic = 2: Reflect.getPrototypeOf()
	 */

	duk_hthread *thr = (duk_hthread *) ctx;
	duk_hobject *h;
	duk_hobject *proto;
	duk_tval *tv;
	duk_int_t magic;

	magic = duk_get_current_magic(ctx);

	if (magic == 0) {
		DUK_ASSERT_TOP(ctx, 0);
		duk_push_this_coercible_to_object(ctx);
	}
	DUK_ASSERT(duk_get_top(ctx) >= 1);
	if (magic < 2) {
		/* ES2015 Section 19.1.2.9, step 1 */
		duk_to_object(ctx, 0);
	}
	tv = DUK_GET_TVAL_POSIDX(ctx, 0);

	switch (DUK_TVAL_GET_TAG(tv)) {
	case DUK_TAG_BUFFER:
		proto = thr->builtins[DUK_BIDX_UINT8ARRAY_PROTOTYPE];
		break;
	case DUK_TAG_LIGHTFUNC:
		proto = thr->builtins[DUK_BIDX_FUNCTION_PROTOTYPE];
		break;
	case DUK_TAG_OBJECT:
		h = DUK_TVAL_GET_OBJECT(tv);
		proto = DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h);
		break;
	default:
		/* This implicitly handles CheckObjectCoercible() caused
		 * TypeError.
		 */
		DUK_DCERROR_TYPE_INVALID_ARGS(thr);
	}
	if (proto != NULL) {
		duk_push_hobject(ctx, proto);
	} else {
		duk_push_null(ctx);
	}
	return 1;
}
コード例 #8
0
ファイル: duk_bi_object.c プロジェクト: remoe/duktape
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 */
	duk_push_boolean(ctx, duk_hobject_prototype_chain_contains(thr, h_v->prototype, h_obj));
	return 1;
}
コード例 #9
0
ファイル: duk_bi_object.c プロジェクト: fatcerberus/duktape
DUK_INTERNAL duk_ret_t duk_bi_object_prototype_is_prototype_of(duk_hthread *thr) {
	duk_hobject *h_v;
	duk_hobject *h_obj;

	DUK_ASSERT_TOP(thr, 1);

	h_v = duk_get_hobject(thr, 0);
	if (!h_v) {
		duk_push_false(thr);  /* XXX: tail call: return duk_push_false(thr) */
		return 1;
	}

	h_obj = duk_push_this_coercible_to_object(thr);
	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(thr, duk_hobject_prototype_chain_contains(thr, DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_v), h_obj, 0 /*ignore_loop*/));
	return 1;
}
コード例 #10
0
ファイル: duk_bi_object.c プロジェクト: CarterTsai/duktape
DUK_INTERNAL duk_ret_t duk_bi_object_prototype_value_of(duk_context *ctx) {
	(void) duk_push_this_coercible_to_object(ctx);
	return 1;
}
コード例 #11
0
ファイル: duk_bi_object.c プロジェクト: fatcerberus/duktape
DUK_INTERNAL duk_ret_t duk_bi_object_prototype_value_of(duk_hthread *thr) {
	/* For lightfuncs and plain buffers, returns Object() coerced. */
	(void) duk_push_this_coercible_to_object(thr);
	return 1;
}
コード例 #12
0
ファイル: duk_bi_array.c プロジェクト: OakLabsInc/duktape
DUK_INTERNAL duk_ret_t duk_bi_array_prototype_concat(duk_context *ctx) {
	duk_idx_t i, n;
	duk_uarridx_t idx, idx_last;
	duk_uarridx_t j, len;
	duk_hobject *h;

	/* XXX: the insert here is a bit expensive if there are a lot of items.
	 * It could also be special cased in the outermost for loop quite easily
	 * (as the element is dup()'d anyway).
	 */

	(void) duk_push_this_coercible_to_object(ctx);
	duk_insert(ctx, 0);
	n = duk_get_top(ctx);
	duk_push_array(ctx);  /* -> [ ToObject(this) item1 ... itemN arr ] */

	/* NOTE: The Array special behaviors are NOT invoked by duk_xdef_prop_index()
	 * (which differs from the official algorithm).  If no error is thrown, this
	 * doesn't matter as the length is updated at the end.  However, if an error
	 * is thrown, the length will be unset.  That shouldn't matter because the
	 * caller won't get a reference to the intermediate value.
	 */

	idx = 0;
	idx_last = 0;
	for (i = 0; i < n; i++) {
		DUK_ASSERT_TOP(ctx, n + 1);

		/* [ ToObject(this) item1 ... itemN arr ] */

		duk_dup(ctx, i);
		h = duk_get_hobject_with_class(ctx, -1, DUK_HOBJECT_CLASS_ARRAY);
		if (!h) {
			duk_xdef_prop_index_wec(ctx, -2, idx++);
			idx_last = idx;
			continue;
		}

		/* [ ToObject(this) item1 ... itemN arr item(i) ] */

		/* XXX: an array can have length higher than 32 bits; this is not handled
		 * correctly now.
		 */
		len = (duk_uarridx_t) duk_get_length(ctx, -1);
		for (j = 0; j < len; j++) {
			if (duk_get_prop_index(ctx, -1, j)) {
				/* [ ToObject(this) item1 ... itemN arr item(i) item(i)[j] ] */
				duk_xdef_prop_index_wec(ctx, -3, idx++);
				idx_last = idx;
			} else {
				idx++;
				duk_pop(ctx);
#if defined(DUK_USE_NONSTD_ARRAY_CONCAT_TRAILER)
				/* According to E5.1 Section 15.4.4.4 nonexistent trailing
				 * elements do not affect 'length' of the result.  Test262
				 * and other engines disagree, so update idx_last here too.
				 */
				idx_last = idx;
#else
				/* Strict standard behavior, ignore trailing elements for
				 * result 'length'.
				 */
#endif
			}
		}
		duk_pop(ctx);
	}

	/* The E5.1 Section 15.4.4.4 algorithm doesn't set the length explicitly
	 * in the end, but because we're operating with an internal value which
	 * is known to be an array, this should be equivalent.
	 */
	duk_push_uarridx(ctx, idx_last);
	duk_xdef_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);

	DUK_ASSERT_TOP(ctx, n + 1);
	return 1;
}
コード例 #13
0
ファイル: duk_bi_array.c プロジェクト: andoma/duktape
int duk_bi_array_prototype_concat(duk_context *ctx) {
	int i, n;
	int j, len;
	int idx, idx_last;
	duk_hobject *h;

	/* XXX: the insert here is a bit expensive if there are a lot of items.
	 * It could also be special cased in the outermost for loop quite easily
	 * (as the element is dup()'d anyway).
	 */

	(void) duk_push_this_coercible_to_object(ctx);
	duk_insert(ctx, 0);
	n = duk_get_top(ctx);
	duk_push_array(ctx);  /* -> [ ToObject(this) item1 ... itemN arr ] */

	/* NOTE: The Array special behaviors are NOT invoked by duk_def_prop_index()
	 * (which differs from the official algorithm).  If no error is thrown, this
	 * doesn't matter as the length is updated at the end.  However, if an error
	 * is thrown, the length will be unset.  That shouldn't matter because the
	 * caller won't get a reference to the intermediate value.
	 */

	idx = 0;
	idx_last = 0;
	for (i = 0; i < n; i++) {
		DUK_ASSERT_TOP(ctx, n + 1);

		/* [ ToObject(this) item1 ... itemN arr ] */

		duk_dup(ctx, i);
		h = duk_get_hobject_with_class(ctx, -1, DUK_HOBJECT_CLASS_ARRAY);
		if (!h) {
			duk_def_prop_index(ctx, -2, idx++, DUK_PROPDESC_FLAGS_WEC);
			idx_last = idx;
			continue;
		}

		/* [ ToObject(this) item1 ... itemN arr item(i) ] */

		/* FIXME: an array can have length higher than 32 bits; this is not handled
		 * correctly now (also len is signed so length above 2**31-1 will have trouble.
		 */
		len = duk_get_length(ctx, -1);
		for (j = 0; j < len; j++) {
			if (duk_get_prop_index(ctx, -1, j)) {
				/* [ ToObject(this) item1 ... itemN arr item(i) item(i)[j] ] */
				duk_def_prop_index(ctx, -3, idx++, DUK_PROPDESC_FLAGS_WEC);
				idx_last = idx;
			} else {
				/* XXX: according to E5.1 Section 15.4.4.4 nonexistent trailing
				 * elements do not affect 'length' but test262 disagrees.  Work
				 * as E5.1 mandates for now and don't touch idx_last.
				 */
				idx++;
				duk_pop(ctx);
			}
		}
		duk_pop(ctx);
	}

	duk_push_number(ctx, (double) idx_last);
	duk_def_prop_stridx(ctx, -2, DUK_STRIDX_LENGTH, DUK_PROPDESC_FLAGS_W);

	DUK_ASSERT_TOP(ctx, n + 1);
	return 1;
}
コード例 #14
0
int duk_builtin_object_prototype_value_of(duk_context *ctx) {
	duk_push_this_coercible_to_object(ctx);
	return 1;
}