shithub: libmujs

Download patch

ref: 40dd4a252f13086148e49bc2763515ceb914b6a8
parent: e673ae661fe3e92bdfa6c14c601bd63254b4ded2
author: Tor Andersson <tor.andersson@artifex.com>
date: Thu Jan 8 10:44:45 EST 2015

Add eval op-code to implement proper 'this' binding for eval code.

--- a/jsbuiltin.c
+++ b/jsbuiltin.c
@@ -28,17 +28,6 @@
 	js_defproperty(J, -2, name, JS_DONTENUM);
 }
 
-static void jsB_eval(js_State *J)
-{
-	if (!js_isstring(J, -1)) {
-		js_copy(J, 1);
-		return;
-	}
-	js_loadeval(J, "(eval)", js_tostring(J, -1));
-	js_pushglobal(J);
-	js_call(J, 0);
-}
-
 static void jsB_parseInt(js_State *J)
 {
 	const char *s = js_tostring(J, 1);
@@ -228,7 +217,6 @@
 	js_pushundefined(J);
 	js_defglobal(J, "undefined", JS_READONLY | JS_DONTENUM | JS_DONTCONF);
 
-	jsB_globalf(J, "eval", jsB_eval, 1);
 	jsB_globalf(J, "parseInt", jsB_parseInt, 1);
 	jsB_globalf(J, "parseFloat", jsB_parseFloat, 1);
 	jsB_globalf(J, "isNaN", jsB_isNaN, 1);
--- a/jscompile.c
+++ b/jscompile.c
@@ -436,6 +436,16 @@
 	}
 }
 
+static void ceval(JF, js_Ast *fun, js_Ast *args)
+{
+	int n = cargs(J, F, args);
+	if (n == 0)
+		emit(J, F, OP_UNDEF);
+	else while (n-- > 1)
+		emit(J, F, OP_POP);
+	emit(J, F, OP_EVAL);
+}
+
 static void ccall(JF, js_Ast *fun, js_Ast *args)
 {
 	int n;
@@ -453,6 +463,12 @@
 		emitstring(J, F, OP_GETPROP_S, fun->b->string);
 		emit(J, F, OP_ROT2);
 		break;
+	case EXP_IDENTIFIER:
+		if (!strcmp(fun->string, "eval")) {
+			ceval(J, F, fun, args);
+			return;
+		}
+		/* fall through */
 	default:
 		cexp(J, F, fun);
 		emit(J, F, OP_GLOBAL);
--- a/jscompile.h
+++ b/jscompile.h
@@ -63,6 +63,7 @@
 	OP_ITERATOR,	/* <obj> -- <iobj> */
 	OP_NEXTITER,	/* <iobj> -- ( <iobj> <name> true | false ) */
 
+	OP_EVAL,	/* <args...> -(numargs)- <returnvalue> */
 	OP_CALL,	/* <closure> <this> <args...> -(numargs)- <returnvalue> */
 	OP_NEW,		/* <closure> <args...> -(numargs)- <returnvalue> */
 
--- a/jsrun.c
+++ b/jsrun.c
@@ -1024,6 +1024,16 @@
 	}
 }
 
+void js_eval(js_State *J)
+{
+	if (!js_isstring(J, -1))
+		return;
+	js_loadeval(J, "(eval)", js_tostring(J, -1));
+	js_rot2pop1(J);
+	js_copy(J, 0); /* copy 'this' */
+	js_call(J, 0);
+}
+
 int js_pconstruct(js_State *J, int n)
 {
 	if (js_try(J))
@@ -1334,6 +1344,10 @@
 			break;
 
 		/* Function calls */
+
+		case OP_EVAL:
+			js_eval(J);
+			break;
 
 		case OP_CALL:
 			js_call(J, *pc++);
--- a/mujs.h
+++ b/mujs.h
@@ -79,6 +79,7 @@
 void js_loadstring(js_State *J, const char *filename, const char *source);
 void js_loadfile(js_State *J, const char *filename);
 
+void js_eval(js_State *J);
 void js_call(js_State *J, int n);
 void js_construct(js_State *J, int n);
 
--- a/opnames.h
+++ b/opnames.h
@@ -45,6 +45,7 @@
 "delprop_s",
 "iterator",
 "nextiter",
+"eval",
 "call",
 "new",
 "typeof",