shithub: libmujs

Download patch

ref: d248b0ce1800a1ebf2c853f205c1947642185c6a
parent: d0225981aa3a66174c699ac380fd863b08dfd2af
author: Tor Andersson <tor.andersson@artifex.com>
date: Mon Nov 11 06:34:43 EST 2019

Bug 701886: Always create new scope for eval().

Distinguish eval code from script code.

--- a/jsdump.c
+++ b/jsdump.c
@@ -885,6 +885,7 @@
 				v.u.object->u.f.function->line);
 			break;
 		case JS_CSCRIPT: printf("[Script %s]", v.u.object->u.f.function->filename); break;
+		case JS_CEVAL: printf("[Eval %s]", v.u.object->u.f.function->filename); break;
 		case JS_CCFUNCTION: printf("[CFunction %s]", v.u.object->u.c.name); break;
 		case JS_CBOOLEAN: printf("[Boolean %d]", v.u.object->u.boolean); break;
 		case JS_CNUMBER: printf("[Number %g]", v.u.object->u.number); break;
--- a/jsfunction.c
+++ b/jsfunction.c
@@ -56,7 +56,7 @@
 	if (!js_iscallable(J, 0))
 		js_typeerror(J, "not a function");
 
-	if (self->type == JS_CFUNCTION || self->type == JS_CSCRIPT) {
+	if (self->type == JS_CFUNCTION || self->type == JS_CSCRIPT || self->type == JS_CEVAL) {
 		js_Function *F = self->u.f.function;
 
 		if (js_try(J)) {
--- a/jsgc.c
+++ b/jsgc.c
@@ -97,7 +97,7 @@
 	if (obj->type == JS_CITERATOR) {
 		jsG_markobject(J, mark, obj->u.iter.target);
 	}
-	if (obj->type == JS_CFUNCTION || obj->type == JS_CSCRIPT) {
+	if (obj->type == JS_CFUNCTION || obj->type == JS_CSCRIPT || obj->type == JS_CEVAL) {
 		if (obj->u.f.scope && obj->u.f.scope->gcmark != mark)
 			jsG_markenvironment(J, mark, obj->u.f.scope);
 		if (obj->u.f.function && obj->u.f.function->gcmark != mark)
--- a/jsi.h
+++ b/jsi.h
@@ -110,7 +110,7 @@
 
 void js_newarguments(js_State *J);
 void js_newfunction(js_State *J, js_Function *function, js_Environment *scope);
-void js_newscript(js_State *J, js_Function *function, js_Environment *scope);
+void js_newscript(js_State *J, js_Function *fun, js_Environment *scope, int type);
 void js_loadeval(js_State *J, const char *filename, const char *source);
 
 js_Regexp *js_toregexp(js_State *J, int idx);
--- a/jsobject.c
+++ b/jsobject.c
@@ -31,6 +31,7 @@
 		case JS_CARRAY: js_pushliteral(J, "[object Array]"); break;
 		case JS_CFUNCTION: js_pushliteral(J, "[object Function]"); break;
 		case JS_CSCRIPT: js_pushliteral(J, "[object Function]"); break;
+		case JS_CEVAL: js_pushliteral(J, "[object Function]"); break;
 		case JS_CCFUNCTION: js_pushliteral(J, "[object Function]"); break;
 		case JS_CERROR: js_pushliteral(J, "[object Error]"); break;
 		case JS_CBOOLEAN: js_pushliteral(J, "[object Boolean]"); break;
--- a/jsrepr.c
+++ b/jsrepr.c
@@ -161,6 +161,7 @@
 			break;
 		case JS_CFUNCTION:
 		case JS_CSCRIPT:
+		case JS_CEVAL:
 			reprfun(J, sb, obj->u.f.function);
 			break;
 		case JS_CCFUNCTION:
--- a/jsrun.c
+++ b/jsrun.c
@@ -200,6 +200,7 @@
 	if (v->type == JS_TOBJECT)
 		return v->u.object->type == JS_CFUNCTION ||
 			v->u.object->type == JS_CSCRIPT ||
+			v->u.object->type == JS_CEVAL ||
 			v->u.object->type == JS_CCFUNCTION;
 	return 0;
 }
@@ -1009,6 +1010,32 @@
 	jsR_restorescope(J);
 }
 
+static void jsR_calleval(js_State *J, int n, js_Function *F, js_Environment *scope)
+{
+	js_Value v;
+	int i;
+
+	scope = jsR_newenvironment(J, jsV_newobject(J, JS_COBJECT, NULL), scope);
+
+	jsR_savescope(J, scope);
+
+	/* scripts take no arguments */
+	js_pop(J, n);
+
+	for (i = 0; i < F->varlen; ++i) {
+		js_pushundefined(J);
+		js_initvar(J, F->vartab[i], -1);
+		js_pop(J, 1);
+	}
+
+	jsR_run(J, F);
+	v = *stackidx(J, -1);
+	TOP = --BOT; /* clear stack */
+	js_pushvalue(J, v);
+
+	jsR_restorescope(J);
+}
+
 static void jsR_callscript(js_State *J, int n, js_Function *F, js_Environment *scope)
 {
 	js_Value v;
@@ -1082,6 +1109,10 @@
 	} else if (obj->type == JS_CSCRIPT) {
 		jsR_pushtrace(J, obj->u.f.function->name, obj->u.f.function->filename, obj->u.f.function->line);
 		jsR_callscript(J, n, obj->u.f.function, obj->u.f.scope);
+		--J->tracetop;
+	} else if (obj->type == JS_CEVAL) {
+		jsR_pushtrace(J, obj->u.f.function->name, obj->u.f.function->filename, obj->u.f.function->line);
+		jsR_calleval(J, n, obj->u.f.function, obj->u.f.scope);
 		--J->tracetop;
 	} else if (obj->type == JS_CCFUNCTION) {
 		jsR_pushtrace(J, obj->u.c.name, "native", 0);
--- a/jsstate.c
+++ b/jsstate.c
@@ -112,7 +112,7 @@
 	P = jsP_parse(J, filename, source);
 	F = jsC_compilescript(J, P, iseval ? J->strict : J->default_strict);
 	jsP_freeparse(J);
-	js_newscript(J, F, iseval ? (J->strict ? J->E : NULL) : J->GE);
+	js_newscript(J, F, iseval ? (J->strict ? J->E : NULL) : J->GE, iseval ? JS_CEVAL : JS_CSCRIPT);
 
 	js_endtry(J);
 }
--- a/jsvalue.c
+++ b/jsvalue.c
@@ -421,9 +421,9 @@
 	}
 }
 
-void js_newscript(js_State *J, js_Function *fun, js_Environment *scope)
+void js_newscript(js_State *J, js_Function *fun, js_Environment *scope, int type)
 {
-	js_Object *obj = jsV_newobject(J, JS_CSCRIPT, NULL);
+	js_Object *obj = jsV_newobject(J, type, NULL);
 	obj->u.f.function = fun;
 	obj->u.f.scope = scope;
 	js_pushobject(J, obj);
--- a/jsvalue.h
+++ b/jsvalue.h
@@ -26,7 +26,8 @@
 	JS_COBJECT,
 	JS_CARRAY,
 	JS_CFUNCTION,
-	JS_CSCRIPT, /* function created from global/eval code */
+	JS_CSCRIPT, /* function created from global code */
+	JS_CEVAL, /* function created from eval code */
 	JS_CCFUNCTION, /* built-in function */
 	JS_CERROR,
 	JS_CBOOLEAN,