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