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",