Exemplo n.º 1
0
/* ToPrimitive() on a value */
js_Value jsV_toprimitive(js_State *J, const js_Value *v, int preferred)
{
	js_Value vv;
	js_Object *obj;

	if (v->type != JS_TOBJECT)
		return *v;

	obj = v->u.object;

	if (preferred == JS_HNONE)
		preferred = obj->type == JS_CDATE ? JS_HSTRING : JS_HNUMBER;

	if (preferred == JS_HSTRING) {
		if (jsV_toString(J, obj) || jsV_valueOf(J, obj)) {
			vv = js_tovalue(J, -1);
			js_pop(J, 1);
			return vv;
		}
	} else {
		if (jsV_valueOf(J, obj) || jsV_toString(J, obj)) {
			vv = js_tovalue(J, -1);
			js_pop(J, 1);
			return vv;
		}
	}

	js_typeerror(J, "cannot convert object to primitive");
}
Exemplo n.º 2
0
/* ToPrimitive() on a value */
void jsV_toprimitive(js_State *J, js_Value *v, int preferred)
{
	js_Object *obj;

	if (v->type != JS_TOBJECT)
		return;

	obj = v->u.object;

	if (preferred == JS_HNONE)
		preferred = obj->type == JS_CDATE ? JS_HSTRING : JS_HNUMBER;

	if (preferred == JS_HSTRING) {
		if (jsV_toString(J, obj) || jsV_valueOf(J, obj)) {
			*v = *js_tovalue(J, -1);
			js_pop(J, 1);
			return;
		}
	} else {
		if (jsV_valueOf(J, obj) || jsV_toString(J, obj)) {
			*v = *js_tovalue(J, -1);
			js_pop(J, 1);
			return;
		}
	}

	v->type = JS_TLITSTR;
	v->u.litstr = "[object]";
	return;
}
Exemplo n.º 3
0
int js_strictequal(js_State *J)
{
	js_Value va = js_tovalue(J, -2);
	js_Value vb = js_tovalue(J, -1);

	if (va.type != vb.type) return 0;
	if (va.type == JS_TUNDEFINED) return 1;
	if (va.type == JS_TNULL) return 1;
	if (va.type == JS_TNUMBER) return va.u.number == vb.u.number;
	if (va.type == JS_TBOOLEAN) return va.u.boolean == vb.u.boolean;
	if (va.type == JS_TSTRING) return !strcmp(va.u.string, vb.u.string);
	if (va.type == JS_TOBJECT) return va.u.object == vb.u.object;
	return 0;
}
Exemplo n.º 4
0
int js_strictequal(js_State *J)
{
	js_Value *x = js_tovalue(J, -2);
	js_Value *y = js_tovalue(J, -1);

	if (JSV_ISSTRING(x) && JSV_ISSTRING(y))
		return !strcmp(JSV_TOSTRING(x), JSV_TOSTRING(y));

	if (x->type != y->type) return 0;
	if (x->type == JS_TUNDEFINED) return 1;
	if (x->type == JS_TNULL) return 1;
	if (x->type == JS_TNUMBER) return x->u.number == y->u.number;
	if (x->type == JS_TBOOLEAN) return x->u.boolean == y->u.boolean;
	if (x->type == JS_TOBJECT) return x->u.object == y->u.object;
	return 0;
}
Exemplo n.º 5
0
int js_equal(js_State *J)
{
	js_Value *x = js_tovalue(J, -2);
	js_Value *y = js_tovalue(J, -1);

retry:
	if (JSV_ISSTRING(x) && JSV_ISSTRING(y))
		return !strcmp(JSV_TOSTRING(x), JSV_TOSTRING(y));
	if (x->type == y->type) {
		if (x->type == JS_TUNDEFINED) return 1;
		if (x->type == JS_TNULL) return 1;
		if (x->type == JS_TNUMBER) return x->u.number == y->u.number;
		if (x->type == JS_TBOOLEAN) return x->u.boolean == y->u.boolean;
		if (x->type == JS_TOBJECT) return x->u.object == y->u.object;
		return 0;
	}

	if (x->type == JS_TNULL && y->type == JS_TUNDEFINED) return 1;
	if (x->type == JS_TUNDEFINED && y->type == JS_TNULL) return 1;

	if (x->type == JS_TNUMBER && JSV_ISSTRING(y))
		return x->u.number == jsV_tonumber(J, y);
	if (JSV_ISSTRING(x) && y->type == JS_TNUMBER)
		return jsV_tonumber(J, x) == y->u.number;

	if (x->type == JS_TBOOLEAN) {
		x->type = JS_TNUMBER;
		x->u.number = x->u.boolean;
		goto retry;
	}
	if (y->type == JS_TBOOLEAN) {
		y->type = JS_TNUMBER;
		y->u.number = y->u.boolean;
		goto retry;
	}
	if ((JSV_ISSTRING(x) || x->type == JS_TNUMBER) && y->type == JS_TOBJECT) {
		jsV_toprimitive(J, y, JS_HNONE);
		goto retry;
	}
	if (x->type == JS_TOBJECT && (JSV_ISSTRING(y) || y->type == JS_TNUMBER)) {
		jsV_toprimitive(J, x, JS_HNONE);
		goto retry;
	}

	return 0;
}
Exemplo n.º 6
0
int js_equal(js_State *J)
{
	js_Value x = js_tovalue(J, -2);
	js_Value y = js_tovalue(J, -1);

retry:
	if (x.type == y.type) {
		if (x.type == JS_TUNDEFINED) return 1;
		if (x.type == JS_TNULL) return 1;
		if (x.type == JS_TNUMBER) return x.u.number == y.u.number;
		if (x.type == JS_TBOOLEAN) return x.u.boolean == y.u.boolean;
		if (x.type == JS_TSTRING) return !strcmp(x.u.string, y.u.string);
		if (x.type == JS_TOBJECT) return x.u.object == y.u.object;
		return 0;
	}

	if (x.type == JS_TNULL && y.type == JS_TUNDEFINED) return 1;
	if (x.type == JS_TUNDEFINED && y.type == JS_TNULL) return 1;

	if (x.type == JS_TNUMBER && y.type == JS_TSTRING)
		return x.u.number == jsV_tonumber(J, &y);
	if (x.type == JS_TSTRING && y.type == JS_TNUMBER)
		return jsV_tonumber(J, &x) == y.u.number;

	if (x.type == JS_TBOOLEAN) {
		x.type = JS_TNUMBER;
		x.u.number = x.u.boolean;
		goto retry;
	}
	if (y.type == JS_TBOOLEAN) {
		y.type = JS_TNUMBER;
		y.u.number = y.u.boolean;
		goto retry;
	}
	if ((x.type == JS_TSTRING || x.type == JS_TNUMBER) && y.type == JS_TOBJECT) {
		y = jsV_toprimitive(J, &y, JS_HNONE);
		goto retry;
	}
	if (x.type == JS_TOBJECT && (y.type == JS_TSTRING || y.type == JS_TNUMBER)) {
		x = jsV_toprimitive(J, &x, JS_HNONE);
		goto retry;
	}

	return 0;
}
Exemplo n.º 7
0
static void Ap_sort(js_State *J)
{
	struct sortslot *array = NULL;
	int i, n, len;

	len = js_getlength(J, 0);
	if (len <= 0) {
		js_copy(J, 0);
		return;
	}

	if (len >= INT_MAX / (int)sizeof(*array))
		js_rangeerror(J, "array is too large to sort");

	array = js_malloc(J, len * sizeof *array);

	/* Holding objects where the GC cannot see them is illegal, but if we
	 * don't allow the GC to run we can use qsort() on a temporary array of
	 * js_Values for fast sorting.
	 */
	++J->gcpause;

	if (js_try(J)) {
		--J->gcpause;
		js_free(J, array);
		js_throw(J);
	}

	n = 0;
	for (i = 0; i < len; ++i) {
		if (js_hasindex(J, 0, i)) {
			array[n].v = *js_tovalue(J, -1);
			array[n].J = J;
			js_pop(J, 1);
			++n;
		}
	}

	qsort(array, n, sizeof *array, sortcmp);

	for (i = 0; i < n; ++i) {
		js_pushvalue(J, array[i].v);
		js_setindex(J, 0, i);
	}
	for (i = n; i < len; ++i) {
		js_delindex(J, 0, i);
	}

	--J->gcpause;

	js_endtry(J);
	js_free(J, array);

	js_copy(J, 0);
}