shithub: libmujs

Download patch

ref: 2a027a1b21ace51301989dd4009f6a56d183df92
parent: b595422da9eb0260f2457cbf30e3a5f69de76029
author: Tor Andersson <[email protected]>
date: Thu Jan 16 22:21:20 EST 2014

String concatenation.

--- a/jsobject.h
+++ b/jsobject.h
@@ -36,6 +36,12 @@
 	JS_PCONFIGURABLE = 4,
 };
 
+enum {
+	JS_HNONE,
+	JS_HNUMBER,
+	JS_HSTRING,
+};
+
 struct js_Value
 {
 	js_Type type;
@@ -76,6 +82,7 @@
 double jsR_tonumber(js_State *J, const js_Value *v);
 const char *jsR_tostring(js_State *J, const js_Value *v);
 js_Object *jsR_toobject(js_State *J, const js_Value *v);
+js_Value jsR_toprimitive(js_State *J, const js_Value *v, int preferred);
 
 /* jsproperty.c */
 js_Object *jsR_newobject(js_State *J, js_Class type);
--- a/jsrun.c
+++ b/jsrun.c
@@ -164,6 +164,12 @@
 	return jsR_toobject(J, &stack[idx]);
 }
 
+js_Value js_toprimitive(js_State *J, int idx, int hint)
+{
+	idx = stackidx(J, idx);
+	return jsR_toprimitive(J, &stack[idx], hint);
+}
+
 /* Stack manipulation */
 
 void js_pop(js_State *J, int n)
@@ -528,17 +534,31 @@
 		case OP_LOGNOT:
 			b = js_toboolean(J, -1);
 			js_pop(J, 1);
-			js_pushnumber(J, !b);
+			js_pushboolean(J, !b);
 			break;
 
 		/* Binary expressions */
 
 		case OP_ADD:
-			// TODO: check string concatenation
-			x = js_tonumber(J, -2);
-			y = js_tonumber(J, -1);
-			js_pop(J, 2);
-			js_pushnumber(J, x + y);
+			{
+				js_Value va = js_toprimitive(J, -2, JS_HNONE);
+				js_Value vb = js_toprimitive(J, -1, JS_HNONE);
+				if (va.type == JS_TSTRING || vb.type == JS_TSTRING) {
+					const char *sa = jsR_tostring(J, &va);
+					const char *sb = jsR_tostring(J, &vb);
+					char *sab = malloc(strlen(sa) + strlen(sb) + 1);
+					strcpy(sab, sa);
+					strcat(sab, sb);
+					js_pop(J, 2);
+					js_pushstring(J, sab);
+					free(sab);
+				} else {
+					x = jsR_tonumber(J, &va);
+					y = jsR_tonumber(J, &vb);
+					js_pop(J, 2);
+					js_pushnumber(J, x + y);
+				}
+			}
 			break;
 
 		case OP_SUB:
--- a/jsvalue.c
+++ b/jsvalue.c
@@ -1,15 +1,14 @@
 #include "js.h"
 #include "jsobject.h"
 
-enum {
-	JS_HNONE,
-	JS_HNUMBER,
-	JS_HSTRING,
-};
-
-static js_Value jsR_toprimitive(js_State *J, const js_Value *v, int preferred)
+js_Value jsR_toprimitive(js_State *J, const js_Value *v, int preferred)
 {
-	js_Object *obj = v->u.object;
+	js_Object *obj;
+
+	if (v->type != JS_COBJECT)
+		return *v;
+
+	obj = v->u.object;
 
 	if (preferred == JS_HNONE)
 		preferred = obj->type == JS_CDATE ? JS_HSTRING : JS_HNUMBER;