shithub: libmujs

Download patch

ref: ac6cc9f7b7b59f47d85b1e9f4c924dcb3c2ac134
parent: 1a7d3ea1e615b6d49f2906c1af24b94b319c8476
author: Tor Andersson <tor@ccxvii.net>
date: Fri Jan 24 17:30:48 EST 2014

Automagically update Array length property.

--- a/jsproperty.c
+++ b/jsproperty.c
@@ -90,6 +90,13 @@
 	return *result = newproperty(J, name);
 }
 
+static js_Property *delete(js_State *J, js_Property *node, const char *name)
+{
+	// TODO
+	return node;
+}
+
+
 js_Object *jsV_newobject(js_State *J, js_Class type, js_Object *prototype)
 {
 	js_Object *obj = calloc(sizeof(js_Object), 1);
@@ -136,6 +143,11 @@
 	js_Property *result;
 	obj->properties = insert(J, obj->properties, name, &result);
 	return result;
+}
+
+void jsV_delproperty(js_State *J, js_Object *obj, const char *name)
+{
+	obj->properties = delete(J, obj->properties, name);
 }
 
 /* Flatten hierarchy of enumerable properties into an iterator object */
--- a/jsrun.c
+++ b/jsrun.c
@@ -270,7 +270,16 @@
 
 static void jsR_getproperty(js_State *J, js_Object *obj, const char *name)
 {
-	js_Property *ref = jsV_getproperty(J, obj, name);
+	js_Property *ref;
+
+	if (obj->type == JS_CARRAY) {
+		if (!strcmp(name, "length")) {
+			js_pushnumber(J, obj->u.a.length);
+			return;
+		}
+	}
+
+	ref = jsV_getproperty(J, obj, name);
 	if (ref)
 		js_pushvalue(J, ref->value);
 	else
@@ -277,18 +286,52 @@
 		js_pushundefined(J);
 }
 
-static void jsR_setproperty(js_State *J, js_Object *obj, const char *name, js_Value v)
+static void jsR_setproperty(js_State *J, js_Object *obj, const char *name, int idx)
 {
-	js_Property *ref = jsV_setproperty(J, obj, name);
+	js_Property *ref;
+
+	if (obj->type == JS_CARRAY) {
+		unsigned int k;
+		char buf[32];
+
+		if (!strcmp(name, "length")) {
+			double rawlen = js_tonumber(J, idx);
+			unsigned int newlen = jsV_numbertouint32(rawlen);
+			unsigned int oldlen = obj->u.a.length;
+			if (newlen != rawlen)
+				js_rangeerror(J, "array length");
+			for (k = newlen; k < oldlen; ++k) {
+				sprintf(buf, "%u", k);
+				jsV_delproperty(J, obj, buf);
+			}
+			obj->u.a.length = newlen;
+			return;
+		}
+
+		k = jsV_numbertouint32(jsV_stringtonumber(J, name));
+		if (k >= obj->u.a.length) {
+			sprintf(buf, "%u", k);
+			if (!strcmp(buf, name))
+				obj->u.a.length = k + 1;
+		}
+	}
+
+	ref = jsV_setproperty(J, obj, name);
 	if (ref && !(ref->atts & JS_READONLY))
-		ref->value = v;
+		ref->value = js_tovalue(J, idx);
 }
 
-static void jsR_defproperty(js_State *J, js_Object *obj, const char *name, js_Value v, int atts)
+static void jsR_defproperty(js_State *J, js_Object *obj, const char *name, int idx, int atts)
 {
-	js_Property *ref = jsV_setproperty(J, obj, name);
+	js_Property *ref;
+
+	if (obj->type == JS_CARRAY)
+		if (!strcmp(name, "length"))
+			return;
+
+	ref = jsV_setproperty(J, obj, name);
 	if (ref) {
-		ref->value = v;
+		ref->value = js_tovalue(J, idx);
 		ref->atts = atts;
 	}
 }
@@ -295,7 +338,9 @@
 
 static void jsR_delproperty(js_State *J, js_Object *obj, const char *name)
 {
-	// TODO
+	js_Property *ref = jsV_getownproperty(J, obj, name);
+	if (ref && !(ref->atts & JS_DONTDELETE))
+		jsV_delproperty(J, obj, name);
 }
 
 /* Registry, global and object property accessors */
@@ -336,7 +381,7 @@
 
 void js_setregistry(js_State *J, const char *name)
 {
-	jsR_setproperty(J, J->R, name, js_tovalue(J, -1));
+	jsR_setproperty(J, J->R, name, -1);
 	js_pop(J, 1);
 }
 
@@ -352,13 +397,13 @@
 
 void js_setglobal(js_State *J, const char *name)
 {
-	jsR_setproperty(J, J->G, name, js_tovalue(J, -1));
+	jsR_setproperty(J, J->G, name, -1);
 	js_pop(J, 1);
 }
 
 void js_defglobal(js_State *J, const char *name, int atts)
 {
-	jsR_defproperty(J, J->G, name, js_tovalue(J, -1), atts);
+	jsR_defproperty(J, J->G, name, -1, atts);
 	js_pop(J, 1);
 }
 
@@ -369,13 +414,13 @@
 
 void js_setproperty(js_State *J, int idx, const char *name)
 {
-	jsR_setproperty(J, js_toobject(J, idx), name, js_tovalue(J, -1));
+	jsR_setproperty(J, js_toobject(J, idx), name, -1);
 	js_pop(J, 1);
 }
 
 void js_defproperty(js_State *J, int idx, const char *name, int atts)
 {
-	jsR_defproperty(J, js_toobject(J, idx), name, js_tovalue(J, -1), atts);
+	jsR_defproperty(J, js_toobject(J, idx), name, -1, atts);
 	js_pop(J, 1);
 }
 
@@ -399,9 +444,9 @@
 	return E;
 }
 
-static void js_decvar(js_State *J, const char *name, js_Value v)
+static void js_decvar(js_State *J, const char *name, int idx)
 {
-	jsR_setproperty(J, J->E->variables, name, v);
+	jsR_setproperty(J, J->E->variables, name, idx);
 }
 
 static void js_getvar(js_State *J, const char *name)
@@ -432,7 +477,7 @@
 		}
 		E = E->outer;
 	} while (E);
-	jsR_setproperty(J, J->G, name, js_tovalue(J, -1));
+	jsR_setproperty(J, J->G, name, -1);
 }
 
 /* Function calls */
@@ -448,10 +493,10 @@
 	J->E = jsR_newenvironment(J, jsV_newobject(J, JS_COBJECT, NULL), scope);
 	for (i = 0; i < F->numparams; ++i) {
 		if (i < n)
-			js_decvar(J, F->params[i], js_tovalue(J, i + 1));
+			js_decvar(J, F->params[i], i + 1);
 		else {
 			js_pushundefined(J);
-			js_decvar(J, F->params[i], js_tovalue(J, -1));
+			js_decvar(J, F->params[i], -1);
 			js_pop(J, 1);
 		}
 	}
@@ -660,13 +705,13 @@
 		case OP_GLOBAL: js_pushobject(J, J->G); break;
 
 		case OP_FUNDEC:
-			js_decvar(J, ST[*pc++], js_tovalue(J, -1));
+			js_decvar(J, ST[*pc++], -1);
 			js_pop(J, 1);
 			break;
 
 		case OP_VARDEC:
 			js_pushundefined(J);
-			js_decvar(J, ST[*pc++], js_tovalue(J, -1));
+			js_decvar(J, ST[*pc++], -1);
 			js_pop(J, 1);
 			break;
 
@@ -705,7 +750,7 @@
 		case OP_SETPROP:
 			obj = js_toobject(J, -3);
 			str = js_tostring(J, -2);
-			jsR_setproperty(J, obj, str, js_tovalue(J, -1));
+			jsR_setproperty(J, obj, str, -1);
 			js_rot3pop2(J);
 			break;
 
@@ -712,7 +757,7 @@
 		case OP_SETPROPS:
 			str = ST[*pc++];
 			obj = js_toobject(J, -2);
-			jsR_setproperty(J, obj, str, js_tovalue(J, -1));
+			jsR_setproperty(J, obj, str, -1);
 			js_rot2pop1(J);
 			break;
 
--- a/jsvalue.h
+++ b/jsvalue.h
@@ -54,6 +54,9 @@
 		double number;
 		const char *string;
 		struct {
+			unsigned int length;
+		} a;
+		struct {
 			js_Function *function;
 			js_Environment *scope;
 		} f;
@@ -112,6 +115,7 @@
 js_Property *jsV_getproperty(js_State *J, js_Object *obj, const char *name);
 js_Property *jsV_setproperty(js_State *J, js_Object *obj, const char *name);
 js_Property *jsV_nextproperty(js_State *J, js_Object *obj, const char *name);
+void jsV_delproperty(js_State *J, js_Object *obj, const char *name);
 
 js_Object *jsV_newiterator(js_State *J, js_Object *obj);
 const char *jsV_nextiterator(js_State *J, js_Object *iobj);