source: webkit/trunk/JavaScriptCore/kjs/ExecState.h@ 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: 8.3 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#ifndef ExecState_h
25#define ExecState_h
26
27#include "LabelStack.h"
28#include "LocalStorage.h"
29#include "completion.h"
30#include "list.h"
31#include "scope_chain.h"
32
33namespace KJS {
34
35 class ActivationImp;
36 class CommonIdentifiers;
37 class EvalNode;
38 class FunctionBodyNode;
39 class FunctionImp;
40 class GlobalFuncImp;
41 class Interpreter;
42 class JSGlobalObject;
43 class JSVariableObject;
44 class ProgramNode;
45 class ScopeNode;
46
47 enum CodeType { GlobalCode, EvalCode, FunctionCode };
48
49 typedef Vector<ExecState*, 16> ExecStateStack;
50
51 // Represents the current state of script execution.
52 // Passed as the first argument to most functions.
53 class ExecState : Noncopyable {
54 public:
55 // Global object that was in scope when the current script started executing.
56 JSGlobalObject* dynamicGlobalObject() const { return m_globalObject; }
57
58 // Global object that was in scope when the current body of code was defined.
59 JSGlobalObject* lexicalGlobalObject() const;
60
61 void setException(JSValue* exception) { m_exception = exception; }
62 void clearException() { m_exception = 0; }
63 JSValue* exception() const { return m_exception; }
64 JSValue** exceptionSlot() { return &m_exception; }
65 bool hadException() const { return !!m_exception; }
66 JSValue* takeException() { JSValue* exception = m_exception; m_exception = 0; return exception; }
67
68 const ScopeChain& scopeChain() const { return m_scopeChain; }
69 void pushScope(JSObject* s) { m_scopeChain.push(s); }
70 void popScope() { m_scopeChain.pop(); }
71 void replaceScopeChainTop(JSObject* o) { m_scopeChain.replaceTop(o); }
72
73 JSVariableObject* variableObject() const { return m_variableObject; }
74 void setVariableObject(JSVariableObject* v) { m_variableObject = v; }
75
76 JSObject* thisValue() const { return m_thisValue; }
77
78 ExecState* callingExecState() { return m_callingExec; }
79
80 ActivationImp* activationObject() { return m_activation; }
81 void setActivationObject(ActivationImp* a) { m_activation = a; }
82 CodeType codeType() { return m_codeType; }
83 ScopeNode* scopeNode() { return m_scopeNode; }
84 FunctionImp* function() const { return m_function; }
85 const List* arguments() const { return m_arguments; }
86
87 LabelStack& seenLabels() { return m_labelStack; }
88
89 void pushIteration() { m_iterationDepth++; }
90 void popIteration() { m_iterationDepth--; }
91 bool inIteration() const { return (m_iterationDepth > 0); }
92
93 void pushSwitch() { m_switchDepth++; }
94 void popSwitch() { m_switchDepth--; }
95 bool inSwitch() const { return (m_switchDepth > 0); }
96
97 // These pointers are used to avoid accessing global variables for these,
98 // to avoid taking PIC branches in Mach-O binaries.
99 const CommonIdentifiers& propertyNames() const { return *m_propertyNames; }
100 const List& emptyList() const { return *m_emptyList; }
101
102 LocalStorage& localStorage() { return *m_localStorage; }
103 void setLocalStorage(LocalStorage* s) { m_localStorage = s; }
104
105 // These are only valid right after calling execute().
106 ComplType completionType() const { return m_completionType; }
107 const Identifier& breakOrContinueTarget() const
108 {
109 ASSERT(m_completionType == Break || m_completionType == Continue);
110 return *m_breakOrContinueTarget;
111 }
112
113 // Only for use in the implementation of execute().
114 void setCompletionType(ComplType type)
115 {
116 ASSERT(type != Break);
117 ASSERT(type != Continue);
118 m_completionType = type;
119 }
120 JSValue* setNormalCompletion()
121 {
122 ASSERT(!hadException());
123 m_completionType = Normal;
124 return 0;
125 }
126 JSValue* setNormalCompletion(JSValue* value)
127 {
128 ASSERT(!hadException());
129 m_completionType = Normal;
130 return value;
131 }
132 JSValue* setBreakCompletion(const Identifier* target)
133 {
134 ASSERT(!hadException());
135 m_completionType = Break;
136 m_breakOrContinueTarget = target;
137 return 0;
138 }
139 JSValue* setContinueCompletion(const Identifier* target)
140 {
141 ASSERT(!hadException());
142 m_completionType = Continue;
143 m_breakOrContinueTarget = target;
144 return 0;
145 }
146 JSValue* setReturnValueCompletion(JSValue* returnValue)
147 {
148 ASSERT(!hadException());
149 ASSERT(returnValue);
150 m_completionType = ReturnValue;
151 return returnValue;
152 }
153 JSValue* setThrowCompletion(JSValue* exception)
154 {
155 ASSERT(!hadException());
156 ASSERT(exception);
157 m_completionType = Throw;
158 return exception;
159 }
160 JSValue* setInterruptedCompletion()
161 {
162 ASSERT(!hadException());
163 m_completionType = Interrupted;
164 return 0;
165 }
166
167 static void markActiveExecStates();
168 static ExecStateStack& activeExecStates();
169
170 protected:
171 ExecState(JSGlobalObject*);
172 ExecState(JSGlobalObject*, JSObject* thisObject, ProgramNode*);
173 ExecState(JSGlobalObject*, JSObject* thisObject, EvalNode*, ExecState* callingExecState, const ScopeChain&, JSVariableObject*);
174 ExecState(JSGlobalObject*, JSObject* thisObject, FunctionBodyNode*, ExecState* callingExecState, FunctionImp*, const List& args);
175 ~ExecState();
176
177 // ExecStates are always stack-allocated, and the garbage collector
178 // marks the stack, so we don't need to protect the objects below from GC.
179
180 JSGlobalObject* m_globalObject;
181 JSValue* m_exception;
182 CommonIdentifiers* m_propertyNames;
183 const List* m_emptyList;
184
185 ExecState* m_callingExec;
186
187 ScopeNode* m_scopeNode;
188
189 FunctionImp* m_function;
190 const List* m_arguments;
191 ActivationImp* m_activation;
192 LocalStorage* m_localStorage;
193
194 ScopeChain m_scopeChain;
195 JSVariableObject* m_variableObject;
196 JSObject* m_thisValue;
197
198 LabelStack m_labelStack;
199 int m_iterationDepth;
200 int m_switchDepth;
201 CodeType m_codeType;
202
203 ComplType m_completionType;
204 const Identifier* m_breakOrContinueTarget;
205 };
206
207 class GlobalExecState : public ExecState {
208 public:
209 GlobalExecState(JSGlobalObject*);
210 ~GlobalExecState();
211 };
212
213 class InterpreterExecState : public ExecState {
214 public:
215 InterpreterExecState(JSGlobalObject*, JSObject* thisObject, ProgramNode*);
216 ~InterpreterExecState();
217 };
218
219 class EvalExecState : public ExecState {
220 public:
221 EvalExecState(JSGlobalObject*, JSObject* thisObj, EvalNode*, ExecState* callingExec, const ScopeChain&, JSVariableObject*);
222 ~EvalExecState();
223 };
224
225 class FunctionExecState : public ExecState {
226 public:
227 FunctionExecState(JSGlobalObject*, JSObject* thisObject, FunctionBodyNode*,
228 ExecState* callingExecState, FunctionImp*, const List& args);
229 ~FunctionExecState();
230 };
231
232} // namespace KJS
233
234#endif // ExecState_h
Note: See TracBrowser for help on using the repository browser.