Bug 398219: avoid storing references to the global scope in the compiled scripts. r,a=brendan

This commit is contained in:
igor@mir2.org 2007-12-19 05:20:45 -08:00
Родитель 1211290d23
Коммит 24269f10d4
4 изменённых файлов: 34 добавлений и 47 удалений

Просмотреть файл

@ -1089,46 +1089,20 @@ fun_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
*/
atom = cx->runtime->atomState.classPrototypeAtom;
if (id == ATOM_KEY(atom)) {
JSObject *proto, *parentProto;
jsval pval;
proto = parentProto = NULL;
if (fun->object != obj &&
(!cx->runtime->findObjectPrincipals ||
cx->runtime->findObjectPrincipals(cx, obj) ==
cx->runtime->findObjectPrincipals(cx, fun->object))) {
/*
* Clone of a function where the clone and the object owning fun
* appear to be in the same trust domain: make the cloned function
* object's 'prototype' property value have the same class as the
* clone-parent's 'prototype' value.
*/
if (!OBJ_GET_PROPERTY(cx, fun->object, ATOM_TO_JSID(atom), &pval))
return JS_FALSE;
if (!JSVAL_IS_PRIMITIVE(pval)) {
/*
* We are about to allocate a new object, so hack the newborn
* root until then to protect pval in case it is figuratively
* up in the air, with no strong refs protecting it.
*/
cx->weakRoots.newborn[GCX_OBJECT] = JSVAL_TO_GCTHING(pval);
parentProto = JSVAL_TO_OBJECT(pval);
}
}
JSObject *proto;
/*
* Beware of the wacky case of a user function named Object -- trying
* to find a prototype for that will recur back here _ad perniciem_.
*/
if (!parentProto && fun->atom == CLASS_ATOM(cx, Object))
if (fun->atom == CLASS_ATOM(cx, Object))
return JS_TRUE;
/*
* If resolving "prototype" in a clone, clone the parent's prototype.
* Pass the constructor's (obj's) parent as the prototype parent, to
* avoid defaulting to parentProto.constructor.__parent__.
* Make the prototype object to have the same parent as the function
* object itself.
*/
proto = js_NewObject(cx, &js_ObjectClass, parentProto,
proto = js_NewObject(cx, &js_ObjectClass, NULL,
OBJ_GET_PARENT(cx, obj));
if (!proto)
return JS_FALSE;
@ -1216,6 +1190,8 @@ fun_xdrObject(JSXDRState *xdr, JSObject **objp)
fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED, NULL, NULL);
if (!fun)
return JS_FALSE;
STOBJ_SET_PARENT(fun->object, NULL);
STOBJ_SET_PROTO(fun->object, NULL);
#ifdef __GNUC__
nvars = nargs = 0; /* quell GCC uninitialized warning */
#endif

Просмотреть файл

@ -4708,7 +4708,7 @@ interrupt:
* scope needed to parent the function object's clone.
*/
parent = OBJ_GET_PARENT(cx, obj);
if (OBJ_GET_CLASS(cx, parent) == &js_BlockClass)
if (parent && OBJ_GET_CLASS(cx, parent) == &js_BlockClass)
fp->blockChain = parent;
parent = js_GetScopeChain(cx, fp);
} else {
@ -4872,8 +4872,7 @@ interrupt:
/*
* Clone the function object with the current scope chain as the
* clone's parent. The original function object is the prototype
* of the clone. Do this only if re-parenting; the compiler may
* clone's parent. Do this only if re-parenting; the compiler may
* have seen the right parent already and created a sufficiently
* well-scoped function object.
*/

Просмотреть файл

@ -1039,19 +1039,25 @@ BindDestructuringArg(JSContext *cx, BindData *data, JSAtom *atom,
static JSFunction *
NewCompilerFunction(JSContext *cx, JSTreeContext *tc, JSAtom *atom,
JSBool lambda)
uintN lambda)
{
JSObject *parent;
JSFunction *fun;
JS_ASSERT((lambda & ~JSFUN_LAMBDA) == 0);
parent = (tc->flags & TCF_IN_FUNCTION) ? tc->fun->object : cx->fp->varobj;
return js_NewFunction(cx, NULL, NULL, 0,
JSFUN_INTERPRETED | (lambda ? JSFUN_LAMBDA : 0),
parent, atom);
fun = js_NewFunction(cx, NULL, NULL, 0, JSFUN_INTERPRETED | lambda,
parent, atom);
if (fun && !(tc->flags & TCF_COMPILE_N_GO)) {
STOBJ_SET_PARENT(fun->object, NULL);
STOBJ_SET_PROTO(fun->object, NULL);
}
return fun;
}
static JSParseNode *
FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
JSBool lambda)
uintN lambda)
{
JSOp op, prevop;
JSParseNode *pn, *body, *result;
@ -1080,7 +1086,7 @@ FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
if (tt == TOK_NAME) {
funAtom = CURRENT_TOKEN(ts).t_atom;
} else {
if (!lambda && (cx->options & JSOPTION_ANONFUNFIX)) {
if (lambda == 0 && (cx->options & JSOPTION_ANONFUNFIX)) {
js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
JSMSG_SYNTAX_ERROR);
return NULL;
@ -1093,7 +1099,7 @@ FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
* Record names for function statements in tc->decls so we know when to
* avoid optimizing variable references that might name a function.
*/
if (!lambda && funAtom) {
if (lambda == 0 && funAtom) {
ATOM_LIST_SEARCH(ale, &tc->decls, funAtom);
if (ale) {
prevop = ALE_JSOP(ale);
@ -1271,7 +1277,7 @@ FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
#if JS_HAS_EXPR_CLOSURES
if (tt == TOK_LC)
MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_BODY);
else if (!lambda)
else if (lambda == 0)
js_MatchToken(cx, ts, TOK_SEMI);
#else
MUST_MATCH_TOKEN(TOK_RC, JSMSG_CURLY_AFTER_BODY);
@ -1337,12 +1343,12 @@ FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
* traversed the function's body
*/
JS_ASSERT(!(funtc.flags & TCF_FUN_USES_NONLOCALS));
if (!lambda && funAtom && !AT_TOP_LEVEL(tc))
if (lambda == 0 && funAtom && !AT_TOP_LEVEL(tc))
tc->flags |= TCF_FUN_HEAVYWEIGHT;
}
result = pn;
if (lambda) {
if (lambda != 0) {
/*
* ECMA ed. 3 standard: function expression, possibly anonymous.
*/
@ -1385,13 +1391,13 @@ FunctionDef(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
static JSParseNode *
FunctionStmt(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
{
return FunctionDef(cx, ts, tc, JS_FALSE);
return FunctionDef(cx, ts, tc, 0);
}
static JSParseNode *
FunctionExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc)
{
return FunctionDef(cx, ts, tc, JS_TRUE);
return FunctionDef(cx, ts, tc, JSFUN_LAMBDA);
}
/*
@ -4259,7 +4265,7 @@ GeneratorExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
* Make the generator function and flag it as interpreted ASAP (see the
* comment in FunctionBody).
*/
fun = NewCompilerFunction(cx, tc, NULL, JS_TRUE);
fun = NewCompilerFunction(cx, tc, NULL, JSFUN_LAMBDA);
if (!fun)
return NULL;
@ -5720,6 +5726,10 @@ PrimaryExpr(JSContext *cx, JSTokenStream *ts, JSTreeContext *tc,
CURRENT_TOKEN(ts).t_reflags);
if (!obj)
return NULL;
if (!(tc->flags & TCF_COMPILE_N_GO)) {
STOBJ_SET_PARENT(obj, NULL);
STOBJ_SET_PROTO(obj, NULL);
}
pn->pn_pob = js_NewParsedObjectBox(cx, tc->parseContext, obj);
if (!pn->pn_pob)

Просмотреть файл

@ -3845,6 +3845,8 @@ regexp_xdrObject(JSXDRState *xdr, JSObject **objp)
obj = js_NewObject(xdr->cx, &js_RegExpClass, NULL, NULL);
if (!obj)
return JS_FALSE;
STOBJ_SET_PARENT(obj, NULL);
STOBJ_SET_PROTO(obj, NULL);
re = js_NewRegExp(xdr->cx, NULL, source, (uint8)flagsword, JS_FALSE);
if (!re)
return JS_FALSE;