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,