shithub: libmujs

Download patch

ref: 5f556004a271f9c0a6cc7589d2f77d6511429bd7
parent: 28643e6afb0c4a59b361a190d96c952c1c78ac77
author: Tor Andersson <tor.andersson@artifex.com>
date: Wed Feb 6 09:04:18 EST 2019

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.

--- a/jsnumber.c
+++ b/jsnumber.c
@@ -116,20 +116,13 @@
 static void numtostr(js_State *J, const char *fmt, int w, double n)
 {
 	char buf[32], *e;
-	if (isnan(n)) js_pushliteral(J, "NaN");
-	else if (isinf(n)) js_pushliteral(J, n < 0 ? "-Infinity" : "Infinity");
-	else if (n == 0) js_pushliteral(J, "0");
-	else {
-		if (w < 1) w = 1;
-		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);
+	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);
 }
 
 static void Np_toFixed(js_State *J)
@@ -136,8 +129,16 @@
 {
 	js_Object *self = js_toobject(J, 0);
 	int width = js_tointeger(J, 1);
+	char buf[32];
+	double x;
 	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)
@@ -144,8 +145,16 @@
 {
 	js_Object *self = js_toobject(J, 0);
 	int width = js_tointeger(J, 1);
+	char buf[32];
+	double x;
 	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)
@@ -152,8 +161,16 @@
 {
 	js_Object *self = js_toobject(J, 0);
 	int width = js_tointeger(J, 1);
+	char buf[32];
+	double x;
 	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)