shithub: libmujs

Download patch

ref: 7228ec51c423cd57413c2c1c9b65b288d0189f5b
parent: 288eef80e136441fe00bc618b523139cb6bb5bca
author: Tor Andersson <tor@ccxvii.net>
date: Thu Jan 16 12:04:29 EST 2014

Handle "this" by always keeping it in stack[0].

--- a/jscompile.c
+++ b/jscompile.c
@@ -357,12 +357,12 @@
 		break;
 	default:
 		cexp(J, F, fun);
-		emit(J, F, OP_THIS);
+		emit(J, F, OP_GLOBAL);
 		break;
 	}
 	n = cargs(J, F, args);
 	emit(J, F, OP_CALL);
-	emit(J, F, 1 + n);
+	emit(J, F, n);
 }
 
 static void cexp(JF, js_Ast *exp)
--- a/jscompile.h
+++ b/jscompile.h
@@ -26,6 +26,7 @@
 	OP_TRUE,
 	OP_FALSE,
 	OP_THIS,
+	OP_GLOBAL,
 
 	OP_FUNDEC,	/* <closure> -S- */
 	OP_VARDEC,	/* -S- */
--- a/jsdump.c
+++ b/jsdump.c
@@ -666,7 +666,18 @@
 	case JS_TBOOLEAN: printf(v.u.boolean ? "true" : "false"); break;
 	case JS_TNUMBER: printf("%.9g", v.u.number); break;
 	case JS_TSTRING: printf("'%s'", v.u.string); break;
-	case JS_TOBJECT: printf("<object %p>", v.u.object); break;
+	case JS_TOBJECT:
+		switch (v.u.object->type) {
+		case JS_COBJECT: printf("object(%p)", v.u.object); break;
+		case JS_CARRAY: printf("array(%p)", v.u.object); break;
+		case JS_CFUNCTION: printf("function(%s)", v.u.object->function->name); break;
+		case JS_CCFUNCTION: printf("cfunction(%p)", v.u.object->cfunction); break;
+		case JS_CBOOLEAN: printf("boolean(%d)", v.u.object->primitive.boolean); break;
+		case JS_CNUMBER: printf("number(%g)", v.u.object->primitive.number); break;
+		case JS_CSTRING: printf("string('%s')", v.u.object->primitive.string); break;
+		default: printf("<unknown %p>", v.u.object); break;
+		}
+		break;
 	}
 }
 
--- a/jsrun.c
+++ b/jsrun.c
@@ -8,7 +8,7 @@
 static int top = 0;
 static int bot = 0;
 
-static void js_call(js_State *J, int argc);
+static void jsR_run(js_State *J, js_Function *F, js_Environment *E);
 
 static void js_dumpstack(js_State *J)
 {
@@ -220,11 +220,57 @@
 
 void js_trap(js_State *J)
 {
+	fprintf(stderr, "trap!\n");
 	js_dumpstack(J);
 }
 
-static void runfun(js_State *J, js_Function *F, js_Environment *E)
+static void jsR_callfunction(js_State *J, int n, js_Function *F, js_Environment *scope)
 {
+	js_Environment *E;
+	int i;
+
+	E = jsR_newenvironment(J, jsR_newobject(J, JS_COBJECT), scope);
+	for (i = 0; i < n; i++) {
+		js_Property *ref = js_decvar(J, E, F->params[i]);
+		if (i < n)
+			ref->value = js_tovalue(J, i + 1);
+	}
+	js_pop(J, n);
+
+	jsR_run(J, F, E);
+
+	js_rot3pop2(J);
+}
+
+static void jsR_callcfunction(js_State *J, int n, js_CFunction F)
+{
+	int rv = F(J, n + 1);
+	if (rv) {
+		js_Value v = js_tovalue(J, -1);
+		js_pop(J, top - bot + 1);
+		js_pushvalue(J, v);
+	} else {
+		js_pop(J, top - bot + 1);
+		js_pushundefined(J);
+	}
+}
+
+void js_call(js_State *J, int n)
+{
+	js_Object *obj = js_toobject(J, -n - 2);
+	int savebot = bot;
+	bot = top - n - 1;
+	if (obj->type == JS_CFUNCTION)
+		jsR_callfunction(J, n, obj->function, obj->scope);
+	else if (obj->type == JS_CCFUNCTION)
+		jsR_callcfunction(J, n, obj->cfunction);
+	else
+		jsR_error(J, "TypeError (not a function)");
+	bot = savebot;
+}
+
+static void jsR_run(js_State *J, js_Function *F, js_Environment *E)
+{
 	js_Function **FT = F->funtab;
 	double *NT = F->numtab;
 	const char **ST = F->strtab;
@@ -263,7 +309,8 @@
 		case OP_TRUE: js_pushboolean(J, 1); break;
 		case OP_FALSE: js_pushboolean(J, 0); break;
 
-		case OP_THIS: js_pushnull(J); break;
+		case OP_THIS: js_pushobject(J, js_toobject(J, 0)); break;
+		case OP_GLOBAL: js_pushobject(J, J->G); break;
 
 		case OP_FUNDEC:
 			ref = js_decvar(J, E, ST[*pc++]);
@@ -528,47 +575,6 @@
 	}
 }
 
-static void js_call(js_State *J, int argc)
-{
-	js_Environment *E;
-	js_Property *ref;
-	js_Function *F;
-	js_Object *obj;
-	int i;
-	int savebot = bot;
-
-	bot = top - argc;
-
-	obj = js_toobject(J, -argc - 1);
-
-	F = obj->function;
-	if (F) {
-		E = jsR_newenvironment(J, jsR_newobject(J, JS_COBJECT), obj->scope);
-
-		for (i = 0; i < F->numparams; ++i) {
-			ref = js_decvar(J, E, F->params[i]);
-			if (i + 1 < argc)
-				ref->value = js_tovalue(J, i + 1);
-		}
-		js_pop(J, argc + 1);
-
-		runfun(J, F, E);
-	} else {
-		js_CFunction CF = obj->cfunction;
-		i = CF(J, argc);
-		if (i) {
-			js_Value v = js_tovalue(J, -1);
-			js_pop(J, top - bot + 1);
-			js_pushvalue(J, v);
-		} else {
-			js_pop(J, top - bot + 1);
-			js_pushundefined(J);
-		}
-	}
-
-	bot = savebot;
-}
-
 js_Environment *jsR_newenvironment(js_State *J, js_Object *vars, js_Environment *outer)
 {
 	js_Environment *E = malloc(sizeof *E);
@@ -633,7 +639,8 @@
 		return;
 	}
 
-	runfun(J, F, J->GE);
+	js_pushobject(J, J->G); /* initial "this" */
+	jsR_run(J, F, J->GE);
 
 	js_dumpobject(J, J->G);
 	js_dumpstack(J);