/* ToString() on a value */ const char *jsV_tostring(js_State *J, js_Value *v) { char buf[32]; const char *p; switch (v->type) { default: case JS_TSHRSTR: return v->u.shrstr; case JS_TUNDEFINED: return "undefined"; case JS_TNULL: return "null"; case JS_TBOOLEAN: return v->u.boolean ? "true" : "false"; case JS_TLITSTR: return v->u.litstr; case JS_TMEMSTR: return v->u.memstr->p; case JS_TNUMBER: p = jsV_numbertostring(J, buf, v->u.number); if (p == buf) { unsigned int n = strlen(p); if (n <= offsetof(js_Value, type)) { char *s = v->u.shrstr; while (n--) *s++ = *p++; *s = 0; v->type = JS_TSHRSTR; return v->u.shrstr; } else { v->type = JS_TMEMSTR; v->u.memstr = jsV_newmemstring(J, p, n); return v->u.memstr->p; } } return p; case JS_TOBJECT: jsV_toprimitive(J, v, JS_HSTRING); return jsV_tostring(J, v); } }
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; }
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; }
/* ToNumber() on a value */ double jsV_tonumber(js_State *J, js_Value *v) { switch (v->type) { default: case JS_TSHRSTR: return jsV_stringtonumber(J, v->u.shrstr); case JS_TUNDEFINED: return NAN; case JS_TNULL: return 0; case JS_TBOOLEAN: return v->u.boolean; case JS_TNUMBER: return v->u.number; case JS_TLITSTR: return jsV_stringtonumber(J, v->u.litstr); case JS_TMEMSTR: return jsV_stringtonumber(J, v->u.memstr->p); case JS_TOBJECT: jsV_toprimitive(J, v, JS_HNUMBER); return jsV_tonumber(J, v); } }
/* ToString() on a value */ const char *jsV_tostring(js_State *J, const js_Value *v) { switch (v->type) { default: case JS_TUNDEFINED: return "undefined"; case JS_TNULL: return "null"; case JS_TBOOLEAN: return v->u.boolean ? "true" : "false"; case JS_TNUMBER: return jsV_numbertostring(J, v->u.number); case JS_TSTRING: return v->u.string; case JS_TOBJECT: { js_Value vv = jsV_toprimitive(J, v, JS_HSTRING); return jsV_tostring(J, &vv); } } }
/* ToNumber() on a value */ double jsV_tonumber(js_State *J, const js_Value *v) { switch (v->type) { default: case JS_TUNDEFINED: return NAN; case JS_TNULL: return 0; case JS_TBOOLEAN: return v->u.boolean; case JS_TNUMBER: return v->u.number; case JS_TSTRING: return jsV_stringtonumber(J, v->u.string); case JS_TOBJECT: { js_Value vv = jsV_toprimitive(J, v, JS_HNUMBER); return jsV_tonumber(J, &vv); } } }
void js_toprimitive(js_State *J, int idx, int hint) { jsV_toprimitive(J, stackidx(J, idx), hint); }