mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 542797 - change obj_eval from JSNative to JSFastNative (r=mrbkap)
--HG-- extra : rebase_source : 5138b86418081cfa331b05947e5988c1f81065ef
This commit is contained in:
parent
87a5e61db3
commit
df420a425b
@ -1123,18 +1123,17 @@ JS_StackFramePrincipals(JSContext *cx, JSStackFrame *fp)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSPrincipals *)
|
||||
JS_EvalFramePrincipals(JSContext *cx, JSStackFrame *fp, JSStackFrame *caller)
|
||||
JSPrincipals *
|
||||
js_EvalFramePrincipals(JSContext *cx, JSObject *callee, JSStackFrame *caller)
|
||||
{
|
||||
JSPrincipals *principals, *callerPrincipals;
|
||||
JSSecurityCallbacks *callbacks;
|
||||
|
||||
callbacks = JS_GetSecurityCallbacks(cx);
|
||||
if (callbacks && callbacks->findObjectPrincipals) {
|
||||
principals = callbacks->findObjectPrincipals(cx, fp->callee());
|
||||
} else {
|
||||
if (callbacks && callbacks->findObjectPrincipals)
|
||||
principals = callbacks->findObjectPrincipals(cx, callee);
|
||||
else
|
||||
principals = NULL;
|
||||
}
|
||||
if (!caller)
|
||||
return principals;
|
||||
callerPrincipals = JS_StackFramePrincipals(cx, caller);
|
||||
@ -1144,6 +1143,12 @@ JS_EvalFramePrincipals(JSContext *cx, JSStackFrame *fp, JSStackFrame *caller)
|
||||
: callerPrincipals;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSPrincipals *)
|
||||
JS_EvalFramePrincipals(JSContext *cx, JSStackFrame *fp, JSStackFrame *caller)
|
||||
{
|
||||
return js_EvalFramePrincipals(cx, fp->callee(), caller);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void *)
|
||||
JS_GetFrameAnnotation(JSContext *cx, JSStackFrame *fp)
|
||||
{
|
||||
|
@ -195,6 +195,9 @@ JS_StackFramePrincipals(JSContext *cx, JSStackFrame *fp);
|
||||
extern JS_PUBLIC_API(JSPrincipals *)
|
||||
JS_EvalFramePrincipals(JSContext *cx, JSStackFrame *fp, JSStackFrame *caller);
|
||||
|
||||
JSPrincipals *
|
||||
js_EvalFramePrincipals(JSContext *cx, JSObject *callee, JSStackFrame *caller);
|
||||
|
||||
extern JS_PUBLIC_API(void *)
|
||||
JS_GetFrameAnnotation(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
|
@ -1567,7 +1567,7 @@ js_Execute(JSContext *cx, JSObject *chain, JSScript *script,
|
||||
* CallStack of |down|. If |down == cx->fp|, the callstack is simply
|
||||
* the context's active callstack, so we can use |down->varobj(cx)|.
|
||||
* When |down != cx->fp|, we need to do a slow linear search. Luckily,
|
||||
* this only happens with eval and JS_EvaluateInStackFrame.
|
||||
* this only happens with indirect eval and JS_EvaluateInStackFrame.
|
||||
*/
|
||||
if (down == cx->fp) {
|
||||
callStack.setInitialVarObj(down->varobj(cx));
|
||||
|
149
js/src/jsobj.cpp
149
js/src/jsobj.cpp
@ -1244,33 +1244,21 @@ EvalCacheHash(JSContext *cx, JSString *str)
|
||||
}
|
||||
|
||||
static JSBool
|
||||
obj_eval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
obj_eval(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
JSStackFrame *fp, *caller, *callerFrame;
|
||||
JSBool indirectCall;
|
||||
JSPrincipals *principals;
|
||||
const char *file;
|
||||
uintN line;
|
||||
JSString *str;
|
||||
JSScript *script;
|
||||
JSBool ok;
|
||||
JSScript **bucket = NULL; /* avoid GCC warning with early decl&init */
|
||||
#if JS_HAS_EVAL_THIS_SCOPE
|
||||
JSObject *callerScopeChain = NULL;
|
||||
JSBool setCallerScopeChain = JS_FALSE;
|
||||
JSTempValueRooter scopetvr;
|
||||
#endif
|
||||
JSObject *withObject = NULL;
|
||||
if (argc < 1) {
|
||||
*vp = JSVAL_VOID;
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
fp = js_GetTopStackFrame(cx);
|
||||
caller = js_GetScriptedCaller(cx, fp);
|
||||
JSStackFrame *caller = js_GetTopStackFrame(cx);
|
||||
if (!caller) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_BAD_INDIRECT_CALL, js_eval_str);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
indirectCall = (caller->regs && *caller->regs->pc != JSOP_EVAL);
|
||||
bool indirectCall = (caller->regs && *caller->regs->pc != JSOP_EVAL);
|
||||
|
||||
/*
|
||||
* This call to js_GetWrappedObject is safe because of the security checks
|
||||
@ -1281,6 +1269,10 @@ obj_eval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
* we're guaranteed to be allowed to access) then we do a security
|
||||
* check.
|
||||
*/
|
||||
jsval *argv = JS_ARGV(cx, vp);
|
||||
JSObject *obj = JS_THIS_OBJECT(cx, vp);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
obj = js_GetWrappedObject(cx, obj);
|
||||
|
||||
/*
|
||||
@ -1303,7 +1295,7 @@ obj_eval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
}
|
||||
|
||||
if (!JSVAL_IS_STRING(argv[0])) {
|
||||
*rval = argv[0];
|
||||
*vp = argv[0];
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
@ -1323,6 +1315,13 @@ obj_eval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
argv[1] = OBJECT_TO_JSVAL(scopeobj);
|
||||
}
|
||||
|
||||
/* Guard for conditionally-created with object below. */
|
||||
struct WithGuard {
|
||||
JSObject *obj;
|
||||
WithGuard() : obj(NULL) {}
|
||||
~WithGuard() { if (obj) obj->setPrivate(NULL); }
|
||||
} withGuard;
|
||||
|
||||
/* From here on, control must exit through label out with ok set. */
|
||||
MUST_FLOW_THROUGH("out");
|
||||
uintN staticLevel = caller->script->staticLevel + 1;
|
||||
@ -1331,11 +1330,9 @@ obj_eval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
* Bring fp->scopeChain up to date. We're either going to use
|
||||
* it (direct call) or save it and restore it (indirect call).
|
||||
*/
|
||||
callerScopeChain = js_GetScopeChain(cx, caller);
|
||||
if (!callerScopeChain) {
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
}
|
||||
JSObject *callerScopeChain = js_GetScopeChain(cx, caller);
|
||||
if (!callerScopeChain)
|
||||
return JS_FALSE;
|
||||
|
||||
#if JS_HAS_EVAL_THIS_SCOPE
|
||||
/*
|
||||
@ -1348,24 +1345,18 @@ obj_eval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
staticLevel = 0;
|
||||
|
||||
OBJ_TO_INNER_OBJECT(cx, obj);
|
||||
if (!obj) {
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
}
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
|
||||
ok = js_CheckPrincipalsAccess(cx, obj,
|
||||
if (!js_CheckPrincipalsAccess(cx, obj,
|
||||
JS_StackFramePrincipals(cx, caller),
|
||||
cx->runtime->atomState.evalAtom);
|
||||
if (!ok)
|
||||
goto out;
|
||||
cx->runtime->atomState.evalAtom)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* NB: We know obj is a global object here. */
|
||||
JS_ASSERT(!OBJ_GET_PARENT(cx, obj));
|
||||
caller->scopeChain = scopeobj = obj;
|
||||
|
||||
/* Remember scopeobj so we can null its private when done. */
|
||||
setCallerScopeChain = JS_TRUE;
|
||||
JS_PUSH_TEMP_ROOT_OBJECT(cx, callerScopeChain, &scopetvr);
|
||||
scopeobj = obj;
|
||||
} else {
|
||||
/*
|
||||
* Compile using the caller's current scope object.
|
||||
@ -1379,33 +1370,27 @@ obj_eval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
} else {
|
||||
scopeobj = js_GetWrappedObject(cx, scopeobj);
|
||||
OBJ_TO_INNER_OBJECT(cx, scopeobj);
|
||||
if (!scopeobj) {
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
}
|
||||
if (!scopeobj)
|
||||
return JS_FALSE;
|
||||
|
||||
ok = js_CheckPrincipalsAccess(cx, scopeobj,
|
||||
if (!js_CheckPrincipalsAccess(cx, scopeobj,
|
||||
JS_StackFramePrincipals(cx, caller),
|
||||
cx->runtime->atomState.evalAtom);
|
||||
if (!ok)
|
||||
goto out;
|
||||
cx->runtime->atomState.evalAtom))
|
||||
return JS_FALSE;
|
||||
|
||||
/*
|
||||
* If scopeobj is not a global object, then we need to wrap it in a
|
||||
* with object to maintain invariants in the engine (see bug 520164).
|
||||
*/
|
||||
if (scopeobj->getParent()) {
|
||||
withObject = js_NewWithObject(cx, scopeobj,
|
||||
JS_GetGlobalForObject(cx, scopeobj),
|
||||
0);
|
||||
if (!withObject) {
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
}
|
||||
scopeobj = withObject;
|
||||
JSObject *global = JS_GetGlobalForObject(cx, scopeobj);
|
||||
withGuard.obj = js_NewWithObject(cx, scopeobj, global, 0);
|
||||
if (!withGuard.obj)
|
||||
return JS_FALSE;
|
||||
|
||||
scopeobj = withGuard.obj;
|
||||
JS_ASSERT(argc >= 2);
|
||||
argv[1] = OBJECT_TO_JSVAL(scopeobj);
|
||||
argv[1] = OBJECT_TO_JSVAL(withGuard.obj);
|
||||
}
|
||||
|
||||
/* We're pretending that we're in global code. */
|
||||
@ -1413,17 +1398,18 @@ obj_eval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
}
|
||||
|
||||
/* Ensure we compile this eval with the right object in the scope chain. */
|
||||
scopeobj = js_CheckScopeChainValidity(cx, scopeobj, js_eval_str);
|
||||
if (!scopeobj) {
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
}
|
||||
JSObject *result = js_CheckScopeChainValidity(cx, scopeobj, js_eval_str);
|
||||
JS_ASSERT_IF(result, result == scopeobj);
|
||||
if (!result)
|
||||
return JS_FALSE;
|
||||
|
||||
principals = JS_EvalFramePrincipals(cx, fp, caller);
|
||||
file = js_ComputeFilename(cx, caller, principals, &line);
|
||||
JSObject *callee = JSVAL_TO_OBJECT(vp[0]);
|
||||
JSPrincipals *principals = js_EvalFramePrincipals(cx, callee, caller);
|
||||
uintN line;
|
||||
const char *file = js_ComputeFilename(cx, caller, principals, &line);
|
||||
|
||||
str = JSVAL_TO_STRING(argv[0]);
|
||||
script = NULL;
|
||||
JSString *str = JSVAL_TO_STRING(argv[0]);
|
||||
JSScript *script = NULL;
|
||||
|
||||
/*
|
||||
* Cache local eval scripts indexed by source qualified by scope.
|
||||
@ -1434,7 +1420,7 @@ obj_eval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
* eval was called, whose strictness doesn't change. Scripts produced by
|
||||
* calls to eval from global code are not cached.
|
||||
*/
|
||||
bucket = EvalCacheHash(cx, str);
|
||||
JSScript **bucket = EvalCacheHash(cx, str);
|
||||
if (!indirectCall && caller->fun) {
|
||||
uintN count = 0;
|
||||
JSScript **scriptp = bucket;
|
||||
@ -1506,32 +1492,24 @@ obj_eval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
* global code. This includes indirect eval and direct eval called with a
|
||||
* scope object parameter.
|
||||
*/
|
||||
callerFrame = (staticLevel != 0) ? caller : NULL;
|
||||
JSStackFrame *callerFrame = (staticLevel != 0) ? caller : NULL;
|
||||
if (!script) {
|
||||
script = JSCompiler::compileScript(cx, scopeobj, callerFrame,
|
||||
principals,
|
||||
TCF_COMPILE_N_GO | TCF_NEED_MUTABLE_SCRIPT,
|
||||
str->chars(), str->length(),
|
||||
NULL, file, line, str, staticLevel);
|
||||
if (!script) {
|
||||
ok = JS_FALSE;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc < 2) {
|
||||
/* Execute using caller's new scope object (might be a Call object). */
|
||||
scopeobj = caller->scopeChain;
|
||||
if (!script)
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Belt-and-braces: check that the lesser of eval's principals and the
|
||||
* caller's principals has access to scopeobj.
|
||||
*/
|
||||
ok = js_CheckPrincipalsAccess(cx, scopeobj, principals,
|
||||
cx->runtime->atomState.evalAtom);
|
||||
if (ok)
|
||||
ok = js_Execute(cx, scopeobj, script, callerFrame, JSFRAME_EVAL, rval);
|
||||
JSBool ok = js_CheckPrincipalsAccess(cx, scopeobj, principals,
|
||||
cx->runtime->atomState.evalAtom) &&
|
||||
js_Execute(cx, scopeobj, script, callerFrame, JSFRAME_EVAL, vp);
|
||||
|
||||
script->u.nextToGC = *bucket;
|
||||
*bucket = script;
|
||||
@ -1539,16 +1517,6 @@ obj_eval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
||||
script->owner = NULL;
|
||||
#endif
|
||||
|
||||
out:
|
||||
#if JS_HAS_EVAL_THIS_SCOPE
|
||||
/* Restore OBJ_GET_PARENT(scopeobj) not callerScopeChain in case of Call. */
|
||||
if (setCallerScopeChain) {
|
||||
caller->scopeChain = callerScopeChain;
|
||||
JS_POP_TEMP_ROOT(cx, &scopetvr);
|
||||
}
|
||||
#endif
|
||||
if (withObject)
|
||||
withObject->setPrivate(NULL);
|
||||
return ok;
|
||||
}
|
||||
|
||||
@ -3703,7 +3671,8 @@ js_InitEval(JSContext *cx, JSObject *obj)
|
||||
{
|
||||
/* ECMA (15.1.2.1) says 'eval' is a property of the global object. */
|
||||
if (!js_DefineFunction(cx, obj, cx->runtime->atomState.evalAtom,
|
||||
obj_eval, 1, 0)) {
|
||||
(JSNative)obj_eval, 1,
|
||||
JSFUN_FAST_NATIVE | JSFUN_STUB_GSOPS)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -806,7 +806,7 @@ XPC_SJOW_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||
|
||||
if (STOBJ_GET_CLASS(objToWrap) == &js_ScriptClass ||
|
||||
(::JS_ObjectIsFunction(cx, objToWrap) &&
|
||||
::JS_GetFunctionNative(cx, ::JS_ValueToFunction(cx, argv[0])) ==
|
||||
::JS_GetFunctionFastNative(cx, ::JS_ValueToFunction(cx, argv[0])) ==
|
||||
XPCWrapper::sEvalNative)) {
|
||||
return ThrowException(NS_ERROR_INVALID_ARG, cx);
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ namespace XPCWrapper {
|
||||
const PRUint32 sWrappedObjSlot = 1;
|
||||
const PRUint32 sFlagsSlot = 0;
|
||||
const PRUint32 sNumSlots = 2;
|
||||
JSNative sEvalNative = nsnull;
|
||||
JSFastNative sEvalNative = nsnull;
|
||||
|
||||
const PRUint32 FLAG_RESOLVING = 0x1;
|
||||
const PRUint32 LAST_FLAG = FLAG_RESOLVING;
|
||||
|
@ -204,7 +204,7 @@ extern const PRUint32 sNumSlots;
|
||||
* Cross origin wrappers and safe JSObject wrappers both need to know
|
||||
* which native is 'eval' for various purposes.
|
||||
*/
|
||||
extern JSNative sEvalNative;
|
||||
extern JSFastNative sEvalNative;
|
||||
|
||||
enum FunctionObjectSlot {
|
||||
eWrappedFunctionSlot = 0,
|
||||
@ -245,7 +245,7 @@ FindEval(XPCCallContext &ccx, JSObject *obj)
|
||||
}
|
||||
|
||||
sEvalNative =
|
||||
::JS_GetFunctionNative(ccx, ::JS_ValueToFunction(ccx, eval_val));
|
||||
::JS_GetFunctionFastNative(ccx, ::JS_ValueToFunction(ccx, eval_val));
|
||||
|
||||
if (!sEvalNative) {
|
||||
return DoThrowException(NS_ERROR_UNEXPECTED, ccx);
|
||||
|
Loading…
Reference in New Issue
Block a user