Changeset 30871 in webkit for trunk/JavaScriptCore/kjs/nodes.cpp


Ignore:
Timestamp:
Mar 7, 2008, 11:46:33 AM (17 years ago)
Author:
[email protected]
Message:

JavaScriptCore:

Reviewed by Darin Adler.


Fixed <rdar://problem/5689093> Stricter (ES4) eval semantics


The basic rule is:


  • "eval(s)" is treated as an operator that gives the ES3 eval behavior.

... but only if there is no overriding declaration of "eval" in scope.

  • All other invocations treat eval as a function that evaluates a script in the context of its "this" object.

... but if its "this" object is not the global object it was
originally associated with, eval throws an exception.


Because only expressions of the form "eval(s)" have access to local
scope, the compiler can now statically determine whether a function
needs local scope to be dynamic.

  • kjs/nodes.h: Added FunctionCallEvalNode. It works just like FuncationCallResolveNode, except it statically indicates that the node may execute eval in the ES3 way.
  • kjs/nodes.cpp:
  • kjs/nodes2string.cpp:
  • tests/mozilla/expected.html: This patch happens to fix a Mozilla JS test, but it's a bit of a pyrrhic victory. The test intends to test Mozilla's generic API for calling eval on any object, but, in reality, we only support calling eval on the global object.

LayoutTests:

Reviewed by Darin Adler.

Tests for <rdar://problem/5689093> Stricter (ES4) eval semantics


  • fast/js/eval-cross-window-expected.txt: Added.
  • fast/js/eval-cross-window.html: Added.
  • fast/js/eval-keyword-vs-function-expected.txt: Added.
  • fast/js/eval-keyword-vs-function.html: Added.
  • fast/js/eval-overriding-expected.txt: Added.
  • fast/js/eval-overriding.html: Added.


Tests to make sure not to regress security:

  • http/tests/security/resources/xss-eval2.html: Added.
  • http/tests/security/resources/xss-eval3.html: Added.
  • http/tests/security/xss-eval-expected.txt: Added.
  • http/tests/security/xss-eval.html: Added.

I removed these tests because we no longer match the behavior they
expected, and the new tests are more comprehensive:


  • fast/js/window-eval-context-expected.txt: Removed.
  • fast/js/window-eval-context.html: Removed.
  • fast/js/window-eval-tearoff-expected.txt: Removed.
  • fast/js/window-eval-tearoff.html: Removed.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/nodes.cpp

    r30726 r30871  
    949949}
    950950
    951 void FunctionCallValueNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
    952 {
    953     nodeStack.append(m_args.get());
    954     nodeStack.append(m_expr.get());
    955 }
    956 
    957 // ECMA 11.2.3
    958 JSValue* FunctionCallValueNode::evaluate(ExecState* exec)
    959 {
    960     JSValue* v = m_expr->evaluate(exec);
    961     KJS_CHECKEXCEPTIONVALUE
    962 
    963     if (!v->isObject()) {
    964         return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, m_expr.get());
    965     }
    966 
    967     JSObject* func = static_cast<JSObject*>(v);
    968 
    969     if (!func->implementsCall()) {
    970         return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, m_expr.get());
    971     }
    972 
    973     List argList;
    974     m_args->evaluateList(exec, argList);
    975     KJS_CHECKEXCEPTIONVALUE
    976 
    977     JSObject* thisObj =  exec->dynamicGlobalObject();
    978 
    979     return func->call(exec, thisObj, argList);
    980 }
    981 
    982 void FunctionCallResolveNode::optimizeVariableAccess(const SymbolTable& symbolTable, const LocalStorage&, NodeStack& nodeStack)
    983 {
    984     nodeStack.append(m_args.get());
    985 
    986     size_t index = symbolTable.get(m_ident.ustring().rep());
    987     if (index != missingSymbolMarker())
    988         new (this) LocalVarFunctionCallNode(index);
    989 }
    990 
    991 // ECMA 11.2.3
    992 JSValue* FunctionCallResolveNode::inlineEvaluate(ExecState* exec)
    993 {
    994     // Check for missed optimization opportunity.
    995     ASSERT(!canSkipLookup(exec, m_ident));
    996 
     951template <ExpressionNode::CallerType callerType>
     952inline JSValue* ExpressionNode::resolveAndCall(ExecState* exec, const Identifier& ident, ArgumentsNode* args)
     953{
    997954    const ScopeChain& chain = exec->scopeChain();
    998955    ScopeChainIterator iter = chain.begin();
     
    1006963    do {
    1007964        base = *iter;
    1008         if (base->getPropertySlot(exec, m_ident, slot)) {
    1009             JSValue* v = slot.getValue(exec, base, m_ident);
     965        if (base->getPropertySlot(exec, ident, slot)) {
     966            JSValue* v = slot.getValue(exec, base, ident);
    1010967            KJS_CHECKEXCEPTIONVALUE
    1011968
    1012969            if (!v->isObject())
    1013                 return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, m_ident);
     970                return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, ident);
    1014971
    1015972            JSObject* func = static_cast<JSObject*>(v);
    1016973
    1017974            if (!func->implementsCall())
    1018                 return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, m_ident);
     975                return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, ident);
    1019976
    1020977            List argList;
    1021             m_args->evaluateList(exec, argList);
     978            args->evaluateList(exec, argList);
    1022979            KJS_CHECKEXCEPTIONVALUE
    1023980
     
    1032989                thisObj = exec->dynamicGlobalObject();
    1033990
     991            if (callerType == EvalOperator) {
     992                if (base == exec->lexicalGlobalObject() && func == exec->lexicalGlobalObject()->evalFunction()) {
     993                    exec->dynamicGlobalObject()->tearOffActivation(exec);
     994                    return eval(exec, exec->scopeChain(), exec->variableObject(), exec->dynamicGlobalObject(), exec->thisValue(), argList);
     995                }
     996            }
    1034997            return func->call(exec, thisObj, argList);
    1035998        }
     
    10371000    } while (iter != end);
    10381001
    1039     return throwUndefinedVariableError(exec, m_ident);
     1002    return throwUndefinedVariableError(exec, ident);
     1003}
     1004
     1005void EvalFunctionCallNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
     1006{
     1007    nodeStack.append(m_args.get());
     1008}
     1009
     1010JSValue* EvalFunctionCallNode::evaluate(ExecState* exec)
     1011{
     1012    return resolveAndCall<EvalOperator>(exec, exec->propertyNames().eval, m_args.get());
     1013}
     1014
     1015void FunctionCallValueNode::optimizeVariableAccess(const SymbolTable&, const LocalStorage&, NodeStack& nodeStack)
     1016{
     1017    nodeStack.append(m_args.get());
     1018    nodeStack.append(m_expr.get());
     1019}
     1020
     1021// ECMA 11.2.3
     1022JSValue* FunctionCallValueNode::evaluate(ExecState* exec)
     1023{
     1024    JSValue* v = m_expr->evaluate(exec);
     1025    KJS_CHECKEXCEPTIONVALUE
     1026
     1027    if (!v->isObject()) {
     1028        return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, m_expr.get());
     1029    }
     1030
     1031    JSObject* func = static_cast<JSObject*>(v);
     1032
     1033    if (!func->implementsCall()) {
     1034        return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, m_expr.get());
     1035    }
     1036
     1037    List argList;
     1038    m_args->evaluateList(exec, argList);
     1039    KJS_CHECKEXCEPTIONVALUE
     1040
     1041    JSObject* thisObj =  exec->dynamicGlobalObject();
     1042
     1043    return func->call(exec, thisObj, argList);
     1044}
     1045
     1046void FunctionCallResolveNode::optimizeVariableAccess(const SymbolTable& symbolTable, const LocalStorage&, NodeStack& nodeStack)
     1047{
     1048    nodeStack.append(m_args.get());
     1049
     1050    size_t index = symbolTable.get(m_ident.ustring().rep());
     1051    if (index != missingSymbolMarker())
     1052        new (this) LocalVarFunctionCallNode(index);
     1053}
     1054
     1055// ECMA 11.2.3
     1056JSValue* FunctionCallResolveNode::inlineEvaluate(ExecState* exec)
     1057{
     1058    // Check for missed optimization opportunity.
     1059    ASSERT(!canSkipLookup(exec, m_ident));
     1060
     1061    return resolveAndCall<FunctionCall>(exec, m_ident, m_args.get());
    10401062}
    10411063
Note: See TracChangeset for help on using the changeset viewer.