Bug 376121: more script object ordering issues, r=brendan, a=dveditz

git-svn-id: svn://10.0.0.236/branches/MOZILLA_1_8_BRANCH@222189 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
crowder%fiverocks.com
2007-03-22 16:06:24 +00:00
parent e823cebd01
commit c4bdf2924a
2 changed files with 93 additions and 33 deletions

View File

@@ -297,4 +297,4 @@ MSG_DEF(JSMSG_BAD_GENERATOR_YIELD, 214, 1, JSEXN_TYPEERR, "yield from closing
MSG_DEF(JSMSG_BAD_YIELD_SYNTAX, 215, 0, JSEXN_SYNTAXERR, "yield expression must be parenthesized")
MSG_DEF(JSMSG_ARRAY_COMP_LEFTSIDE, 216, 0, JSEXN_SYNTAXERR, "invalid array comprehension left-hand side")
MSG_DEF(JSMSG_YIELD_FROM_FILTER, 217, 0, JSEXN_INTERNALERR, "yield not yet supported from filtering predicate")
MSG_DEF(JSMSG_SELF_MODIFYING_SCRIPT, 218, 0, JSEXN_TYPEERR, "self-modifying script detected")
MSG_DEF(JSMSG_COMPILE_EXECED_SCRIPT, 218, 0, JSEXN_TYPEERR, "cannot compile over a script that is currently executing")

View File

@@ -67,6 +67,31 @@
static const char js_script_exec[] = "Script.prototype.exec";
static const char js_script_compile[] = "Script.prototype.compile";
/*
* This routine requires that obj has been locked previously.
*/
static jsint
GetScriptExecDepth(JSContext *cx, JSObject *obj)
{
jsval v;
JS_ASSERT(JS_IS_OBJ_LOCKED(cx, obj));
v = LOCKED_OBJ_GET_SLOT(obj, JSSLOT_START(&js_ScriptClass));
return JSVAL_TO_INT(v);
}
static void
AdjustScriptExecDepth(JSContext *cx, JSObject *obj, jsint delta)
{
jsint execDepth;
JS_LOCK_OBJ(cx, obj);
execDepth = GetScriptExecDepth(cx, obj);
LOCKED_OBJ_SET_SLOT(obj, JSSLOT_START(&js_ScriptClass),
INT_TO_JSVAL(execDepth + delta));
JS_UNLOCK_OBJ(cx, obj);
}
#if JS_HAS_TOSOURCE
static JSBool
script_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
@@ -165,11 +190,13 @@ script_compile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
{
JSString *str;
JSObject *scopeobj;
JSScript *oldscript, *script;
jsval v;
JSScript *script, *oldscript;
JSStackFrame *fp, *caller;
const char *file;
uintN line;
JSPrincipals *principals;
jsint execDepth;
/* Make sure obj is a Script object. */
if (!JS_InstanceOf(cx, obj, &js_ScriptClass, argv))
@@ -192,18 +219,6 @@ script_compile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
argv[1] = OBJECT_TO_JSVAL(scopeobj);
}
/* XXX thread safety was completely neglected in this function... */
oldscript = (JSScript *) JS_GetPrivate(cx, obj);
if (oldscript) {
for (fp = cx->fp; fp; fp = fp->down) {
if (fp->script == oldscript) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_SELF_MODIFYING_SCRIPT);
return JS_FALSE;
}
}
}
/* Compile using the caller's scope chain, which js_Invoke passes to fp. */
fp = cx->fp;
caller = JS_GetScriptedCaller(cx, fp);
@@ -247,15 +262,32 @@ script_compile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
if (!script)
return JS_FALSE;
/* Swap script for obj's old script, if any. */
if (!JS_SetPrivate(cx, obj, script)) {
js_DestroyScript(cx, script);
JS_LOCK_OBJ(cx, obj);
execDepth = GetScriptExecDepth(cx, obj);
/*
* execDepth must be 0 to allow compilation here, otherwise the JSScript
* struct can be released while running.
*/
if (execDepth > 0) {
JS_UNLOCK_OBJ(cx, obj);
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_COMPILE_EXECED_SCRIPT);
return JS_FALSE;
}
/* Swap script for obj's old script, if any. */
v = LOCKED_OBJ_GET_SLOT(obj, JSSLOT_PRIVATE);
oldscript = !JSVAL_IS_VOID(v) ? (JSScript *) JSVAL_TO_PRIVATE(v) : NULL;
LOCKED_OBJ_SET_SLOT(obj, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(script));
JS_UNLOCK_OBJ(cx, obj);
if (oldscript)
js_DestroyScript(cx, oldscript);
script->object = obj;
js_CallNewScriptHook(cx, script, NULL);
out:
/* Return the object. */
*rval = OBJECT_TO_JSVAL(obj);
@@ -267,8 +299,8 @@ script_exec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
JSObject *scopeobj, *parent;
JSStackFrame *fp, *caller;
JSPrincipals *principals;
JSScript *script;
JSBool ok;
if (!JS_InstanceOf(cx, obj, &js_ScriptClass, argv))
return JS_FALSE;
@@ -331,18 +363,27 @@ script_exec(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
if (!scopeobj)
return JS_FALSE;
script = (JSScript *) JS_GetPrivate(cx, obj);
if (!script)
return JS_TRUE;
/* Keep track of nesting depth for the script. */
AdjustScriptExecDepth(cx, obj, 1);
/* Belt-and-braces: check that this script object has access to scopeobj. */
principals = script->principals;
if (!js_CheckPrincipalsAccess(cx, scopeobj, principals,
CLASS_ATOM(cx, Script))) {
return JS_FALSE;
/* Must get to out label after this */
script = (JSScript *) JS_GetPrivate(cx, obj);
if (!script) {
ok = JS_FALSE;
goto out;
}
return js_Execute(cx, scopeobj, script, caller, JSFRAME_EVAL, rval);
/* Belt-and-braces: check that this script object has access to scopeobj. */
ok = js_CheckPrincipalsAccess(cx, scopeobj, script->principals,
CLASS_ATOM(cx, Script));
if (!ok)
goto out;
ok = js_Execute(cx, scopeobj, script, caller, JSFRAME_EVAL, rval);
out:
AdjustScriptExecDepth(cx, obj, -1);
return ok;
}
#if JS_HAS_XDR
@@ -748,6 +789,7 @@ script_thaw(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
JSString *str;
void *buf;
uint32 len;
jsval v;
JSScript *script, *oldscript;
JSBool ok, hasMagic;
@@ -797,13 +839,26 @@ script_thaw(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
goto out;
}
/* Swap script for obj's old script, if any. */
oldscript = (JSScript *) JS_GetPrivate(cx, obj);
ok = JS_SetPrivate(cx, obj, script);
if (!ok) {
JS_free(cx, script);
JS_LOCK_OBJ(cx, obj);
execDepth = GetScriptExecDepth(cx, obj);
/*
* execDepth must be 0 to allow compilation here, otherwise the JSScript
* struct can be released while running.
*/
if (execDepth > 0) {
JS_UNLOCK_OBJ(cx, obj);
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_COMPILE_EXECED_SCRIPT);
goto out;
}
/* Swap script for obj's old script, if any. */
v = LOCKED_OBJ_GET_SLOT(cx, obj, JSSLOT_PRIVATE);
oldscript = !JSVAL_IS_VOID(v) ? (JSScript *) JSVAL_TO_PRIVATE(v) : NULL;
LOCKED_OBJ_SET_SLOT(cx, obj, JSSLOT_PRIVATE, PRIVATE_TO_JSVAL(script));
JS_UNLOCK_OBJ(cx, obj);
if (oldscript)
js_DestroyScript(cx, oldscript);
@@ -884,7 +939,8 @@ const char js_Script_str[] = "Script";
JS_FRIEND_DATA(JSClass) js_ScriptClass = {
js_Script_str,
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Script),
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_Script) |
JSCLASS_HAS_RESERVED_SLOTS(1),
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, script_finalize,
NULL, NULL, script_call, NULL,/*XXXbe xdr*/
@@ -908,6 +964,10 @@ Script(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
*/
*rval = OBJECT_TO_JSVAL(obj);
}
if (!JS_SetReservedSlot(cx, obj, 0, INT_TO_JSVAL(0)))
return JS_FALSE;
return script_compile(cx, obj, argc, argv, rval);
}