source: webkit/trunk/JavaScriptCore/kjs/ExecState.cpp@ 30871

Last change on this file since 30871 was 30871, checked in by [email protected], 17 years ago

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.
  • Property svn:eol-style set to native
File size: 6.5 KB
Line 
1// -*- mode: c++; c-basic-offset: 4 -*-
2/*
3 * Copyright (C) 1999-2001 Harri Porten ([email protected])
4 * Copyright (C) 2001 Peter Kelly ([email protected])
5 * Copyright (C) 2003, 2007, 2008 Apple Inc. All rights reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 *
22 */
23
24#include "config.h"
25#include "ExecState.h"
26
27#include "Activation.h"
28#include "JSGlobalObject.h"
29#include "function.h"
30#include "internal.h"
31#include "scope_chain_mark.h"
32
33namespace KJS {
34
35static inline List* globalEmptyList()
36{
37 static List staticEmptyList;
38 return &staticEmptyList;
39}
40
41// ECMA 10.2
42
43// The constructor for the globalExec pseudo-ExecState
44inline ExecState::ExecState(JSGlobalObject* globalObject)
45 : m_globalObject(globalObject)
46 , m_exception(0)
47 , m_propertyNames(CommonIdentifiers::shared())
48 , m_emptyList(globalEmptyList())
49 , m_callingExec(0)
50 , m_scopeNode(0)
51 , m_function(0)
52 , m_arguments(0)
53 , m_activation(0)
54 , m_localStorage(&globalObject->localStorage())
55 , m_variableObject(globalObject)
56 , m_thisValue(globalObject)
57 , m_iterationDepth(0)
58 , m_switchDepth(0)
59 , m_codeType(GlobalCode)
60{
61 m_scopeChain.push(globalObject);
62}
63
64inline ExecState::ExecState(JSGlobalObject* globalObject, JSObject* /*thisObject*/, ProgramNode* programNode)
65 : m_globalObject(globalObject)
66 , m_exception(0)
67 , m_propertyNames(CommonIdentifiers::shared())
68 , m_emptyList(globalEmptyList())
69 , m_callingExec(0)
70 , m_scopeNode(programNode)
71 , m_function(0)
72 , m_arguments(0)
73 , m_activation(0)
74 , m_localStorage(&globalObject->localStorage())
75 , m_variableObject(globalObject)
76 , m_thisValue(globalObject)
77 , m_iterationDepth(0)
78 , m_switchDepth(0)
79 , m_codeType(GlobalCode)
80{
81 // FIXME: This function ignores the "thisObject" parameter, which means that the API for evaluating
82 // a script with a this object that's not the same as the global object is broken, and probably
83 // has been for some time.
84 ASSERT(m_scopeNode);
85 m_scopeChain.push(globalObject);
86}
87
88inline ExecState::ExecState(JSGlobalObject* globalObject, JSObject* thisObject, EvalNode* evalNode, ExecState* callingExec, const ScopeChain& scopeChain, JSVariableObject* variableObject)
89 : m_globalObject(globalObject)
90 , m_exception(0)
91 , m_propertyNames(callingExec->m_propertyNames)
92 , m_emptyList(callingExec->m_emptyList)
93 , m_callingExec(callingExec)
94 , m_scopeNode(evalNode)
95 , m_function(0)
96 , m_arguments(0)
97 , m_activation(0)
98 , m_localStorage(callingExec->m_localStorage)
99 , m_scopeChain(scopeChain)
100 , m_variableObject(variableObject)
101 , m_thisValue(thisObject)
102 , m_iterationDepth(0)
103 , m_switchDepth(0)
104 , m_codeType(EvalCode)
105{
106 ASSERT(m_scopeNode);
107}
108
109inline ExecState::ExecState(JSGlobalObject* globalObject, JSObject* thisObject,
110 FunctionBodyNode* functionBodyNode, ExecState* callingExec,
111 FunctionImp* func, const List& args)
112 : m_globalObject(globalObject)
113 , m_exception(0)
114 , m_propertyNames(callingExec->m_propertyNames)
115 , m_emptyList(callingExec->m_emptyList)
116 , m_callingExec(callingExec)
117 , m_scopeNode(functionBodyNode)
118 , m_function(func)
119 , m_arguments(&args)
120 , m_scopeChain(func->scope())
121 , m_thisValue(thisObject)
122 , m_iterationDepth(0)
123 , m_switchDepth(0)
124 , m_codeType(FunctionCode)
125{
126 ASSERT(m_scopeNode);
127
128 ActivationImp* activation = globalObject->pushActivation(this);
129 m_activation = activation;
130 m_localStorage = &activation->localStorage();
131 m_variableObject = activation;
132 m_scopeChain.push(activation);
133}
134
135inline ExecState::~ExecState()
136{
137}
138
139JSGlobalObject* ExecState::lexicalGlobalObject() const
140{
141 JSObject* object = m_scopeChain.bottom();
142 if (object && object->isGlobalObject())
143 return static_cast<JSGlobalObject*>(object);
144 return m_globalObject;
145}
146
147void ExecState::markActiveExecStates()
148{
149 ExecStateStack::const_iterator end = activeExecStates().end();
150 for (ExecStateStack::const_iterator it = activeExecStates().begin(); it != end; ++it)
151 (*it)->m_scopeChain.mark();
152}
153
154static inline ExecStateStack& inlineActiveExecStates()
155{
156 static ExecStateStack staticActiveExecStates;
157 return staticActiveExecStates;
158}
159
160ExecStateStack& ExecState::activeExecStates()
161{
162 return inlineActiveExecStates();
163}
164
165GlobalExecState::GlobalExecState(JSGlobalObject* globalObject)
166 : ExecState(globalObject)
167{
168}
169
170GlobalExecState::~GlobalExecState()
171{
172}
173
174InterpreterExecState::InterpreterExecState(JSGlobalObject* globalObject, JSObject* thisObject, ProgramNode* programNode)
175 : ExecState(globalObject, thisObject, programNode)
176{
177 inlineActiveExecStates().append(this);
178}
179
180InterpreterExecState::~InterpreterExecState()
181{
182 ASSERT(inlineActiveExecStates().last() == this);
183 inlineActiveExecStates().removeLast();
184}
185
186EvalExecState::EvalExecState(JSGlobalObject* globalObject, JSObject* thisObj, EvalNode* evalNode, ExecState* callingExec, const ScopeChain& scopeChain, JSVariableObject* variableObject)
187 : ExecState(globalObject, thisObj, evalNode, callingExec, scopeChain, variableObject)
188{
189 inlineActiveExecStates().append(this);
190}
191
192EvalExecState::~EvalExecState()
193{
194 ASSERT(inlineActiveExecStates().last() == this);
195 inlineActiveExecStates().removeLast();
196}
197
198FunctionExecState::FunctionExecState(JSGlobalObject* globalObject, JSObject* thisObject,
199 FunctionBodyNode* functionBodyNode, ExecState* callingExec,
200 FunctionImp* func, const List& args)
201 : ExecState(globalObject, thisObject, functionBodyNode, callingExec, func, args)
202{
203 inlineActiveExecStates().append(this);
204}
205
206FunctionExecState::~FunctionExecState()
207{
208 ASSERT(inlineActiveExecStates().last() == this);
209 inlineActiveExecStates().removeLast();
210
211 if (m_activation->needsPop())
212 m_globalObject->popActivation();
213}
214
215} // namespace KJS
Note: See TracBrowser for help on using the repository browser.