1 | /*
|
---|
2 | * This file is part of the KDE libraries
|
---|
3 | * Copyright (C) 1999-2001 Harri Porten ([email protected])
|
---|
4 | * Copyright (C) 2001 Peter Kelly ([email protected])
|
---|
5 | * Copyright (C) 2003 Apple Computer, Inc.
|
---|
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 _KJS_INTERPRETER_H_
|
---|
25 | #define _KJS_INTERPRETER_H_
|
---|
26 |
|
---|
27 | #include "ExecState.h"
|
---|
28 | #include "protect.h"
|
---|
29 | #include "value.h"
|
---|
30 | #include "types.h"
|
---|
31 |
|
---|
32 | namespace KJS {
|
---|
33 |
|
---|
34 | class ArrayObjectImp;
|
---|
35 | class ArrayPrototype;
|
---|
36 | class BooleanObjectImp;
|
---|
37 | class BooleanPrototype;
|
---|
38 | class Context;
|
---|
39 | class DateObjectImp;
|
---|
40 | class DatePrototype;
|
---|
41 | class Debugger;
|
---|
42 | class ErrorObjectImp;
|
---|
43 | class ErrorPrototype;
|
---|
44 | class EvalError;
|
---|
45 | class EvalErrorPrototype;
|
---|
46 | class FunctionObjectImp;
|
---|
47 | class FunctionPrototype;
|
---|
48 | class NativeErrorImp;
|
---|
49 | class NativeErrorPrototype;
|
---|
50 | class NumberObjectImp;
|
---|
51 | class NumberPrototype;
|
---|
52 | class ObjectObjectImp;
|
---|
53 | class ObjectPrototype;
|
---|
54 | class RangeError;
|
---|
55 | class RangeErrorPrototype;
|
---|
56 | class ReferenceError;
|
---|
57 | class ReferenceError;
|
---|
58 | class ReferenceErrorPrototype;
|
---|
59 | class RegExpObjectImp;
|
---|
60 | class RegExpPrototype;
|
---|
61 | class RuntimeMethod;
|
---|
62 | class SavedBuiltins;
|
---|
63 | class ScopeChain;
|
---|
64 | class StringObjectImp;
|
---|
65 | class StringPrototype;
|
---|
66 | class SyntaxErrorPrototype;
|
---|
67 | class TypeError;
|
---|
68 | class TypeErrorPrototype;
|
---|
69 | class UriError;
|
---|
70 | class UriErrorPrototype;
|
---|
71 |
|
---|
72 | /**
|
---|
73 | * Interpreter objects can be used to evaluate ECMAScript code. Each
|
---|
74 | * interpreter has a global object which is used for the purposes of code
|
---|
75 | * evaluation, and also provides access to built-in properties such as
|
---|
76 | * " Object" and "Number".
|
---|
77 | */
|
---|
78 | class Interpreter {
|
---|
79 | friend class Collector;
|
---|
80 | public:
|
---|
81 | /**
|
---|
82 | * Creates a new interpreter. The supplied object will be used as the global
|
---|
83 | * object for all scripts executed with this interpreter. During
|
---|
84 | * constuction, all the standard properties such as "Object" and "Number"
|
---|
85 | * will be added to the global object.
|
---|
86 | *
|
---|
87 | * Note: You should not use the same global object for multiple
|
---|
88 | * interpreters.
|
---|
89 | *
|
---|
90 | * This is due do the fact that the built-in properties are set in the
|
---|
91 | * constructor, and if these objects have been modified from another
|
---|
92 | * interpreter (e.g. a script modifying String.prototype), the changes will
|
---|
93 | * be overridden.
|
---|
94 | *
|
---|
95 | * @param global The object to use as the global object for this interpreter
|
---|
96 | */
|
---|
97 | Interpreter(JSObject* globalObject);
|
---|
98 | /**
|
---|
99 | * Creates a new interpreter. A global object will be created and
|
---|
100 | * initialized with the standard global properties.
|
---|
101 | */
|
---|
102 | Interpreter();
|
---|
103 |
|
---|
104 | /**
|
---|
105 | * Resets the global object's default properties and adds the default object
|
---|
106 | * prototype to its prototype chain.
|
---|
107 | */
|
---|
108 | void initGlobalObject();
|
---|
109 |
|
---|
110 | /**
|
---|
111 | * Returns the object that is used as the global object during all script
|
---|
112 | * execution performed by this interpreter
|
---|
113 | */
|
---|
114 | JSObject* globalObject() const;
|
---|
115 |
|
---|
116 | /**
|
---|
117 | * Returns the execution state object which can be used to execute
|
---|
118 | * scripts using this interpreter at a the "global" level, i.e. one
|
---|
119 | * with a execution context that has the global object as the "this"
|
---|
120 | * value, and who's scope chain contains only the global object.
|
---|
121 | *
|
---|
122 | * Note: this pointer remains constant for the life of the interpreter
|
---|
123 | * and should not be manually deleted.
|
---|
124 | *
|
---|
125 | * @return The interpreter global execution state object
|
---|
126 | */
|
---|
127 | virtual ExecState *globalExec();
|
---|
128 |
|
---|
129 | /**
|
---|
130 | * Parses the supplied ECMAScript code and checks for syntax errors.
|
---|
131 | *
|
---|
132 | * @param code The code to check
|
---|
133 | * @return A normal completion if there were no syntax errors in the code,
|
---|
134 | * otherwise a throw completion with the syntax error as its value.
|
---|
135 | */
|
---|
136 | Completion checkSyntax(const UString& sourceURL, int startingLineNumber, const UString& code);
|
---|
137 | Completion checkSyntax(const UString& sourceURL, int startingLineNumber, const UChar* code, int codeLength);
|
---|
138 |
|
---|
139 | /**
|
---|
140 | * Evaluates the supplied ECMAScript code.
|
---|
141 | *
|
---|
142 | * Since this method returns a Completion, you should check the type of
|
---|
143 | * completion to detect an error or before attempting to access the returned
|
---|
144 | * value. For example, if an error occurs during script execution and is not
|
---|
145 | * caught by the script, the completion type will be Throw.
|
---|
146 | *
|
---|
147 | * If the supplied code is invalid, a SyntaxError will be thrown.
|
---|
148 | *
|
---|
149 | * @param code The code to evaluate
|
---|
150 | * @param thisV The value to pass in as the "this" value for the script
|
---|
151 | * execution. This should either be jsNull() or an Object.
|
---|
152 | * @return A completion object representing the result of the execution.
|
---|
153 | */
|
---|
154 | Completion evaluate(const UString& sourceURL, int startingLineNumber, const UChar* code, int codeLength, JSValue* thisV = 0);
|
---|
155 | Completion evaluate(const UString& sourceURL, int startingLineNumber, const UString& code, JSValue* thisV = 0);
|
---|
156 |
|
---|
157 | /**
|
---|
158 | * Returns the builtin "Object" object. This is the object that was set
|
---|
159 | * as a property of the global object during construction; if the property
|
---|
160 | * is replaced by script code, this method will still return the original
|
---|
161 | * object.
|
---|
162 | *
|
---|
163 | * @return The builtin "Object" object
|
---|
164 | */
|
---|
165 | JSObject *builtinObject() const;
|
---|
166 |
|
---|
167 | /**
|
---|
168 | * Returns the builtin "Function" object.
|
---|
169 | */
|
---|
170 | JSObject *builtinFunction() const;
|
---|
171 |
|
---|
172 | /**
|
---|
173 | * Returns the builtin "Array" object.
|
---|
174 | */
|
---|
175 | JSObject *builtinArray() const;
|
---|
176 |
|
---|
177 | /**
|
---|
178 | * Returns the builtin "Boolean" object.
|
---|
179 | */
|
---|
180 | JSObject *builtinBoolean() const;
|
---|
181 |
|
---|
182 | /**
|
---|
183 | * Returns the builtin "String" object.
|
---|
184 | */
|
---|
185 | JSObject *builtinString() const;
|
---|
186 |
|
---|
187 | /**
|
---|
188 | * Returns the builtin "Number" object.
|
---|
189 | */
|
---|
190 | JSObject *builtinNumber() const;
|
---|
191 |
|
---|
192 | /**
|
---|
193 | * Returns the builtin "Date" object.
|
---|
194 | */
|
---|
195 | JSObject *builtinDate() const;
|
---|
196 |
|
---|
197 | /**
|
---|
198 | * Returns the builtin "RegExp" object.
|
---|
199 | */
|
---|
200 | JSObject *builtinRegExp() const;
|
---|
201 |
|
---|
202 | /**
|
---|
203 | * Returns the builtin "Error" object.
|
---|
204 | */
|
---|
205 | JSObject *builtinError() const;
|
---|
206 |
|
---|
207 | /**
|
---|
208 | * Returns the builtin "Object.prototype" object.
|
---|
209 | */
|
---|
210 | JSObject *builtinObjectPrototype() const;
|
---|
211 |
|
---|
212 | /**
|
---|
213 | * Returns the builtin "Function.prototype" object.
|
---|
214 | */
|
---|
215 | JSObject *builtinFunctionPrototype() const;
|
---|
216 |
|
---|
217 | /**
|
---|
218 | * Returns the builtin "Array.prototype" object.
|
---|
219 | */
|
---|
220 | JSObject *builtinArrayPrototype() const;
|
---|
221 |
|
---|
222 | /**
|
---|
223 | * Returns the builtin "Boolean.prototype" object.
|
---|
224 | */
|
---|
225 | JSObject *builtinBooleanPrototype() const;
|
---|
226 |
|
---|
227 | /**
|
---|
228 | * Returns the builtin "String.prototype" object.
|
---|
229 | */
|
---|
230 | JSObject *builtinStringPrototype() const;
|
---|
231 |
|
---|
232 | /**
|
---|
233 | * Returns the builtin "Number.prototype" object.
|
---|
234 | */
|
---|
235 | JSObject *builtinNumberPrototype() const;
|
---|
236 |
|
---|
237 | /**
|
---|
238 | * Returns the builtin "Date.prototype" object.
|
---|
239 | */
|
---|
240 | JSObject *builtinDatePrototype() const;
|
---|
241 |
|
---|
242 | /**
|
---|
243 | * Returns the builtin "RegExp.prototype" object.
|
---|
244 | */
|
---|
245 | JSObject *builtinRegExpPrototype() const;
|
---|
246 |
|
---|
247 | /**
|
---|
248 | * Returns the builtin "Error.prototype" object.
|
---|
249 | */
|
---|
250 | JSObject *builtinErrorPrototype() const;
|
---|
251 |
|
---|
252 | /**
|
---|
253 | * The initial value of "Error" global property
|
---|
254 | */
|
---|
255 | JSObject *builtinEvalError() const;
|
---|
256 | JSObject *builtinRangeError() const;
|
---|
257 | JSObject *builtinReferenceError() const;
|
---|
258 | JSObject *builtinSyntaxError() const;
|
---|
259 | JSObject *builtinTypeError() const;
|
---|
260 | JSObject *builtinURIError() const;
|
---|
261 |
|
---|
262 | JSObject *builtinEvalErrorPrototype() const;
|
---|
263 | JSObject *builtinRangeErrorPrototype() const;
|
---|
264 | JSObject *builtinReferenceErrorPrototype() const;
|
---|
265 | JSObject *builtinSyntaxErrorPrototype() const;
|
---|
266 | JSObject *builtinTypeErrorPrototype() const;
|
---|
267 | JSObject *builtinURIErrorPrototype() const;
|
---|
268 |
|
---|
269 | enum CompatMode { NativeMode, IECompat, NetscapeCompat };
|
---|
270 | /**
|
---|
271 | * Call this to enable a compatibility mode with another browser.
|
---|
272 | * (by default konqueror is in "native mode").
|
---|
273 | * Currently, in KJS, this only changes the behavior of Date::getYear()
|
---|
274 | * which returns the full year under IE.
|
---|
275 | */
|
---|
276 | void setCompatMode(CompatMode mode) { m_compatMode = mode; }
|
---|
277 | CompatMode compatMode() const { return m_compatMode; }
|
---|
278 |
|
---|
279 | /**
|
---|
280 | * Run the garbage collection. Returns true when at least one object
|
---|
281 | * was collected; false otherwise.
|
---|
282 | */
|
---|
283 | static bool collect();
|
---|
284 |
|
---|
285 | /**
|
---|
286 | * Called during the mark phase of the garbage collector. Subclasses
|
---|
287 | * implementing custom mark methods must make sure to chain to this one.
|
---|
288 | */
|
---|
289 | virtual void mark();
|
---|
290 |
|
---|
291 | #ifdef KJS_DEBUG_MEM
|
---|
292 | /**
|
---|
293 | * @internal
|
---|
294 | */
|
---|
295 | static void finalCheck();
|
---|
296 | #endif
|
---|
297 |
|
---|
298 | static bool shouldPrintExceptions();
|
---|
299 | static void setShouldPrintExceptions(bool);
|
---|
300 |
|
---|
301 | void saveBuiltins (SavedBuiltins&) const;
|
---|
302 | void restoreBuiltins (const SavedBuiltins&);
|
---|
303 |
|
---|
304 | /**
|
---|
305 | * Determine if the value is a global object (for any interpreter). This may
|
---|
306 | * be difficult to determine for multiple uses of JSC in a process that are
|
---|
307 | * logically independent of each other. In the case of WebCore, this method
|
---|
308 | * is used to determine if an object is the Window object so we can perform
|
---|
309 | * security checks.
|
---|
310 | */
|
---|
311 | virtual bool isGlobalObject(JSValue*) { return false; }
|
---|
312 |
|
---|
313 | /**
|
---|
314 | * Find the interpreter for a particular global object. This should really
|
---|
315 | * be a static method, but we can't do that is C++. Again, as with isGlobalObject()
|
---|
316 | * implementation really need to know about all instances of Interpreter
|
---|
317 | * created in an application to correctly implement this method. The only
|
---|
318 | * override of this method is currently in WebCore.
|
---|
319 | */
|
---|
320 | virtual Interpreter* interpreterForGlobalObject(const JSValue*) { return 0; }
|
---|
321 |
|
---|
322 | /**
|
---|
323 | * Determine if the it is 'safe' to execute code in the target interpreter from an
|
---|
324 | * object that originated in this interpreter. This check is used to enforce WebCore
|
---|
325 | * cross frame security rules. In particular, attempts to access 'bound' objects are
|
---|
326 | * not allowed unless isSafeScript returns true.
|
---|
327 | */
|
---|
328 | virtual bool isSafeScript(const Interpreter*) { return true; }
|
---|
329 |
|
---|
330 | // Chained list of interpreters (ring)
|
---|
331 | static Interpreter* firstInterpreter() { return s_hook; }
|
---|
332 | Interpreter* nextInterpreter() const { return next; }
|
---|
333 | Interpreter* prevInterpreter() const { return prev; }
|
---|
334 |
|
---|
335 | Debugger* debugger() const { return m_debugger; }
|
---|
336 | void setDebugger(Debugger* d) { m_debugger = d; }
|
---|
337 |
|
---|
338 | void setContext(Context* c) { m_context = c; }
|
---|
339 | Context* context() const { return m_context; }
|
---|
340 |
|
---|
341 | static Interpreter* interpreterWithGlobalObject(JSObject*);
|
---|
342 |
|
---|
343 | void setTimeoutTime(unsigned timeoutTime) { m_timeoutTime = timeoutTime; }
|
---|
344 |
|
---|
345 | void startTimeoutCheck();
|
---|
346 | void stopTimeoutCheck();
|
---|
347 |
|
---|
348 | bool timedOut();
|
---|
349 |
|
---|
350 | void ref() { ++m_refCount; }
|
---|
351 | void deref() { if (--m_refCount <= 0) delete this; }
|
---|
352 | int refCount() const { return m_refCount; }
|
---|
353 |
|
---|
354 | protected:
|
---|
355 | virtual ~Interpreter(); // only deref should delete us
|
---|
356 | virtual bool shouldInterruptScript() const { return true; }
|
---|
357 |
|
---|
358 | unsigned m_timeoutTime;
|
---|
359 |
|
---|
360 | private:
|
---|
361 | void init();
|
---|
362 |
|
---|
363 | void resetTimeoutCheck();
|
---|
364 | bool checkTimeout();
|
---|
365 |
|
---|
366 | // Uncopyable
|
---|
367 | Interpreter(const Interpreter&);
|
---|
368 | Interpreter operator=(const Interpreter&);
|
---|
369 |
|
---|
370 | int m_refCount;
|
---|
371 |
|
---|
372 | ExecState m_globalExec;
|
---|
373 |
|
---|
374 | // Chained list of interpreters (ring) - for collector
|
---|
375 | static Interpreter* s_hook;
|
---|
376 | Interpreter *next, *prev;
|
---|
377 |
|
---|
378 | int m_recursion;
|
---|
379 |
|
---|
380 | Debugger* m_debugger;
|
---|
381 | Context* m_context;
|
---|
382 | CompatMode m_compatMode;
|
---|
383 |
|
---|
384 | unsigned m_timeAtLastCheckTimeout;
|
---|
385 | unsigned m_timeExecuting;
|
---|
386 | unsigned m_timeoutCheckCount;
|
---|
387 |
|
---|
388 | unsigned m_tickCount;
|
---|
389 | unsigned m_ticksUntilNextTimeoutCheck;
|
---|
390 |
|
---|
391 | JSObject* m_globalObject;
|
---|
392 |
|
---|
393 | ObjectObjectImp* m_Object;
|
---|
394 | FunctionObjectImp* m_Function;
|
---|
395 | ArrayObjectImp* m_Array;
|
---|
396 | BooleanObjectImp* m_Boolean;
|
---|
397 | StringObjectImp* m_String;
|
---|
398 | NumberObjectImp* m_Number;
|
---|
399 | DateObjectImp* m_Date;
|
---|
400 | RegExpObjectImp* m_RegExp;
|
---|
401 | ErrorObjectImp* m_Error;
|
---|
402 |
|
---|
403 | ObjectPrototype* m_ObjectPrototype;
|
---|
404 | FunctionPrototype* m_FunctionPrototype;
|
---|
405 | ArrayPrototype* m_ArrayPrototype;
|
---|
406 | BooleanPrototype* m_BooleanPrototype;
|
---|
407 | StringPrototype* m_StringPrototype;
|
---|
408 | NumberPrototype* m_NumberPrototype;
|
---|
409 | DatePrototype* m_DatePrototype;
|
---|
410 | RegExpPrototype* m_RegExpPrototype;
|
---|
411 | ErrorPrototype* m_ErrorPrototype;
|
---|
412 |
|
---|
413 | NativeErrorImp* m_EvalError;
|
---|
414 | NativeErrorImp* m_RangeError;
|
---|
415 | NativeErrorImp* m_ReferenceError;
|
---|
416 | NativeErrorImp* m_SyntaxError;
|
---|
417 | NativeErrorImp* m_TypeError;
|
---|
418 | NativeErrorImp* m_UriError;
|
---|
419 |
|
---|
420 | NativeErrorPrototype* m_EvalErrorPrototype;
|
---|
421 | NativeErrorPrototype* m_RangeErrorPrototype;
|
---|
422 | NativeErrorPrototype* m_ReferenceErrorPrototype;
|
---|
423 | NativeErrorPrototype* m_SyntaxErrorPrototype;
|
---|
424 | NativeErrorPrototype* m_TypeErrorPrototype;
|
---|
425 | NativeErrorPrototype* m_UriErrorPrototype;
|
---|
426 | };
|
---|
427 |
|
---|
428 | inline bool Interpreter::timedOut()
|
---|
429 | {
|
---|
430 | m_tickCount++;
|
---|
431 |
|
---|
432 | if (m_tickCount != m_ticksUntilNextTimeoutCheck)
|
---|
433 | return false;
|
---|
434 |
|
---|
435 | return checkTimeout();
|
---|
436 | }
|
---|
437 |
|
---|
438 | } // namespace
|
---|
439 |
|
---|
440 | #endif // _KJS_INTERPRETER_H_
|
---|