Fix bugs in Number.prototype.toFixed and toExponential.

toPrecision does not behave correctly: it doesn't pad the number with
trailing zeroes to reach the desired precision.
This commit is contained in:
Tor Andersson
2019-02-06 14:04:18 +01:00
parent 28643e6afb
commit 5f556004a2

View File

@@ -116,44 +116,61 @@ static void Np_toString(js_State *J)
static void numtostr(js_State *J, const char *fmt, int w, double n) static void numtostr(js_State *J, const char *fmt, int w, double n)
{ {
char buf[32], *e; char buf[32], *e;
if (isnan(n)) js_pushliteral(J, "NaN"); sprintf(buf, fmt, w, n);
else if (isinf(n)) js_pushliteral(J, n < 0 ? "-Infinity" : "Infinity"); e = strchr(buf, 'e');
else if (n == 0) js_pushliteral(J, "0"); if (e) {
else { int exp = atoi(e+1);
if (w < 1) w = 1; sprintf(e, "e%+d", exp);
if (w > 17) w = 17;
sprintf(buf, fmt, w, n);
e = strchr(buf, 'e');
if (e) {
int exp = atoi(e+1);
sprintf(e, "e%+d", exp);
}
js_pushstring(J, buf);
} }
js_pushstring(J, buf);
} }
static void Np_toFixed(js_State *J) static void Np_toFixed(js_State *J)
{ {
js_Object *self = js_toobject(J, 0); js_Object *self = js_toobject(J, 0);
int width = js_tointeger(J, 1); int width = js_tointeger(J, 1);
char buf[32];
double x;
if (self->type != JS_CNUMBER) js_typeerror(J, "not a number"); if (self->type != JS_CNUMBER) js_typeerror(J, "not a number");
numtostr(J, "%.*f", width, self->u.number); if (width < 0) js_rangeerror(J, "precision %d out of range", width);
if (width > 20) js_rangeerror(J, "precision %d out of range", width);
x = self->u.number;
if (isnan(x) || isinf(x) || x <= -1e21 || x >= 1e21)
js_pushstring(J, jsV_numbertostring(J, buf, x));
else
numtostr(J, "%.*f", width, x);
} }
static void Np_toExponential(js_State *J) static void Np_toExponential(js_State *J)
{ {
js_Object *self = js_toobject(J, 0); js_Object *self = js_toobject(J, 0);
int width = js_tointeger(J, 1); int width = js_tointeger(J, 1);
char buf[32];
double x;
if (self->type != JS_CNUMBER) js_typeerror(J, "not a number"); if (self->type != JS_CNUMBER) js_typeerror(J, "not a number");
numtostr(J, "%.*e", width, self->u.number); if (width < 0) js_rangeerror(J, "precision %d out of range", width);
if (width > 20) js_rangeerror(J, "precision %d out of range", width);
x = self->u.number;
if (isnan(x) || isinf(x))
js_pushstring(J, jsV_numbertostring(J, buf, x));
else
numtostr(J, "%.*e", width, self->u.number);
} }
static void Np_toPrecision(js_State *J) static void Np_toPrecision(js_State *J)
{ {
js_Object *self = js_toobject(J, 0); js_Object *self = js_toobject(J, 0);
int width = js_tointeger(J, 1); int width = js_tointeger(J, 1);
char buf[32];
double x;
if (self->type != JS_CNUMBER) js_typeerror(J, "not a number"); if (self->type != JS_CNUMBER) js_typeerror(J, "not a number");
numtostr(J, "%.*g", width, self->u.number); if (width < 1) js_rangeerror(J, "precision %d out of range", width);
if (width > 21) js_rangeerror(J, "precision %d out of range", width);
x = self->u.number;
if (isnan(x) || isinf(x))
js_pushstring(J, jsV_numbertostring(J, buf, x));
else
numtostr(J, "%.*g", width, self->u.number);
} }
void jsB_initnumber(js_State *J) void jsB_initnumber(js_State *J)