9a9d89f00a216f5756140dfef561ff9457be36b8
[WebKit-https.git] / JavaScriptCore / kjs / internal.h
1 // -*- c-basic-offset: 2 -*-
2 /*
3  *  This file is part of the KDE libraries
4  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
5  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
6  *  Copyright (C) 2003 Apple Computer, Inc.
7  *
8  *  This library is free software; you can redistribute it and/or
9  *  modify it under the terms of the GNU Library General Public
10  *  License as published by the Free Software Foundation; either
11  *  version 2 of the License, or (at your option) any later version.
12  *
13  *  This library is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  *  Library General Public License for more details.
17  *
18  *  You should have received a copy of the GNU Library General Public License
19  *  along with this library; see the file COPYING.LIB.  If not, write to
20  *  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  *  Boston, MA 02111-1307, USA.
22  *
23  */
24
25 #ifndef _INTERNAL_H_
26 #define _INTERNAL_H_
27
28 #include "ustring.h"
29 #include "value.h"
30 #include "object.h"
31 #include "types.h"
32 #include "interpreter.h"
33 #include "scope_chain.h"
34
35 #define I18N_NOOP(s) s
36
37 namespace KJS {
38
39   static const double D16 = 65536.0;
40   static const double D32 = 4294967296.0;
41
42   class ProgramNode;
43   class FunctionBodyNode;
44   class FunctionPrototypeImp;
45   class FunctionImp;
46   class Debugger;
47
48   // ---------------------------------------------------------------------------
49   //                            Primitive impls
50   // ---------------------------------------------------------------------------
51
52   class UndefinedImp : public ValueImp {
53   public:
54     Type type() const { return UndefinedType; }
55
56     Value toPrimitive(ExecState *exec, Type preferred = UnspecifiedType) const;
57     bool toBoolean(ExecState *exec) const;
58     double toNumber(ExecState *exec) const;
59     UString toString(ExecState *exec) const;
60     Object toObject(ExecState *exec) const;
61
62     static UndefinedImp *staticUndefined;
63   };
64
65   inline Undefined::Undefined(UndefinedImp *imp) : Value(imp) { }
66
67   class NullImp : public ValueImp {
68   public:
69     Type type() const { return NullType; }
70
71     Value toPrimitive(ExecState *exec, Type preferred = UnspecifiedType) const;
72     bool toBoolean(ExecState *exec) const;
73     double toNumber(ExecState *exec) const;
74     UString toString(ExecState *exec) const;
75     Object toObject(ExecState *exec) const;
76
77     static NullImp *staticNull;
78   };
79
80   inline Null::Null(NullImp *imp) : Value(imp) { }
81
82   class BooleanImp : public ValueImp {
83   public:
84     BooleanImp(bool v = false) : val(v) { }
85     bool value() const { return val; }
86
87     Type type() const { return BooleanType; }
88
89     Value toPrimitive(ExecState *exec, Type preferred = UnspecifiedType) const;
90     bool toBoolean(ExecState *exec) const;
91     double toNumber(ExecState *exec) const;
92     UString toString(ExecState *exec) const;
93     Object toObject(ExecState *exec) const;
94
95     static BooleanImp *staticTrue;
96     static BooleanImp *staticFalse;
97   private:
98     bool val;
99   };
100   
101   inline Boolean::Boolean(BooleanImp *imp) : Value(imp) { }
102
103   class StringImp : public ValueImp {
104   public:
105     StringImp(const UString& v) : val(v) { }
106     UString value() const { return val; }
107
108     Type type() const { return StringType; }
109
110     Value toPrimitive(ExecState *exec, Type preferred = UnspecifiedType) const;
111     bool toBoolean(ExecState *exec) const;
112     double toNumber(ExecState *exec) const;
113     UString toString(ExecState *exec) const;
114     Object toObject(ExecState *exec) const;
115
116   private:
117     UString val;
118   };
119
120   inline String::String(StringImp *imp) : Value(imp) { }
121
122   class NumberImp : public ValueImp {
123     friend class Number;
124     friend class InterpreterImp;
125   public:
126     static ValueImp *create(int);
127     static ValueImp *create(double);
128     static ValueImp *zero() { return SimpleNumber::make(0); }
129     static ValueImp *one() { return SimpleNumber::make(1); }
130     static ValueImp *two() { return SimpleNumber::make(2); }
131     
132     double value() const { return val; }
133
134     Type type() const { return NumberType; }
135
136     Value toPrimitive(ExecState *exec, Type preferred = UnspecifiedType) const;
137     bool toBoolean(ExecState *exec) const;
138     double toNumber(ExecState *exec) const;
139     UString toString(ExecState *exec) const;
140     Object toObject(ExecState *exec) const;
141
142     static NumberImp *staticNaN;
143
144   private:
145     NumberImp(double v) : val(v) { }
146
147     virtual bool toUInt32(unsigned&) const;
148
149     double val;
150   };
151
152   inline Number::Number(NumberImp *imp) : Value(imp) { }
153
154   /**
155    * @short The "label set" in Ecma-262 spec
156    */
157   class LabelStack {
158   public:
159     LabelStack(): tos(0L) {}
160     ~LabelStack();
161
162     LabelStack(const LabelStack &other);
163     LabelStack &operator=(const LabelStack &other);
164
165     /**
166      * If id is not empty and is not in the stack already, puts it on top of
167      * the stack and returns true, otherwise returns false
168      */
169     bool push(const Identifier &id);
170     /**
171      * Is the id in the stack?
172      */
173     bool contains(const Identifier &id) const;
174     /**
175      * Removes from the stack the last pushed id (what else?)
176      */
177     void pop();
178   private:
179     struct StackElem {
180       Identifier id;
181       StackElem *prev;
182     };
183
184     StackElem *tos;
185     void clear();
186   };
187
188
189   // ---------------------------------------------------------------------------
190   //                            Parsing & evaluateion
191   // ---------------------------------------------------------------------------
192
193   enum CodeType { GlobalCode,
194                   EvalCode,
195                   FunctionCode,
196                   AnonymousCode };
197
198   /**
199    * @internal
200    *
201    * Parses ECMAScript source code and converts into ProgramNode objects, which
202    * represent the root of a parse tree. This class provides a conveniant workaround
203    * for the problem of the bison parser working in a static context.
204    */
205   class Parser {
206   public:
207     static ProgramNode *parse(const UString &sourceURL, int startingLineNumber,
208                               const UChar *code, unsigned int length, int *sourceId = 0,
209                               int *errLine = 0, UString *errMsg = 0);
210
211     static ProgramNode *progNode;
212     static int sid;
213   };
214
215   class SavedBuiltinsInternal {
216     friend class InterpreterImp;
217   private:
218     ProtectedObject b_Object;
219     ProtectedObject b_Function;
220     ProtectedObject b_Array;
221     ProtectedObject b_Boolean;
222     ProtectedObject b_String;
223     ProtectedObject b_Number;
224     ProtectedObject b_Date;
225     ProtectedObject b_RegExp;
226     ProtectedObject b_Error;
227
228     ProtectedObject b_ObjectPrototype;
229     ProtectedObject b_FunctionPrototype;
230     ProtectedObject b_ArrayPrototype;
231     ProtectedObject b_BooleanPrototype;
232     ProtectedObject b_StringPrototype;
233     ProtectedObject b_NumberPrototype;
234     ProtectedObject b_DatePrototype;
235     ProtectedObject b_RegExpPrototype;
236     ProtectedObject b_ErrorPrototype;
237
238     ProtectedObject b_evalError;
239     ProtectedObject b_rangeError;
240     ProtectedObject b_referenceError;
241     ProtectedObject b_syntaxError;
242     ProtectedObject b_typeError;
243     ProtectedObject b_uriError;
244
245     ProtectedObject b_evalErrorPrototype;
246     ProtectedObject b_rangeErrorPrototype;
247     ProtectedObject b_referenceErrorPrototype;
248     ProtectedObject b_syntaxErrorPrototype;
249     ProtectedObject b_typeErrorPrototype;
250     ProtectedObject b_uriErrorPrototype;
251   };
252
253   class InterpreterImp {
254     friend class Collector;
255   public:
256     static void globalInit();
257     static void globalClear();
258
259     InterpreterImp(Interpreter *interp, const Object &glob);
260     ~InterpreterImp();
261
262     ProtectedObject &globalObject() const { return const_cast<ProtectedObject &>(global); }
263     Interpreter* interpreter() const { return m_interpreter; }
264
265     void initGlobalObject();
266     static void lock();
267     static void unlock();
268     static int lockCount();
269
270     void mark();
271
272     ExecState *globalExec() { return globExec; }
273     bool checkSyntax(const UString &code);
274     Completion evaluate(const UString &code, const Value &thisV, const UString &sourceURL, int startingLineNumber);
275     Debugger *debugger() const { return dbg; }
276     void setDebugger(Debugger *d);
277
278     Object builtinObject() const { return b_Object; }
279     Object builtinFunction() const { return b_Function; }
280     Object builtinArray() const { return b_Array; }
281     Object builtinBoolean() const { return b_Boolean; }
282     Object builtinString() const { return b_String; }
283     Object builtinNumber() const { return b_Number; }
284     Object builtinDate() const { return b_Date; }
285     Object builtinRegExp() const { return b_RegExp; }
286     Object builtinError() const { return b_Error; }
287
288     Object builtinObjectPrototype() const { return b_ObjectPrototype; }
289     Object builtinFunctionPrototype() const { return b_FunctionPrototype; }
290     Object builtinArrayPrototype() const { return b_ArrayPrototype; }
291     Object builtinBooleanPrototype() const { return b_BooleanPrototype; }
292     Object builtinStringPrototype() const { return b_StringPrototype; }
293     Object builtinNumberPrototype() const { return b_NumberPrototype; }
294     Object builtinDatePrototype() const { return b_DatePrototype; }
295     Object builtinRegExpPrototype() const { return b_RegExpPrototype; }
296     Object builtinErrorPrototype() const { return b_ErrorPrototype; }
297
298     Object builtinEvalError() const { return b_evalError; }
299     Object builtinRangeError() const { return b_rangeError; }
300     Object builtinReferenceError() const { return b_referenceError; }
301     Object builtinSyntaxError() const { return b_syntaxError; }
302     Object builtinTypeError() const { return b_typeError; }
303     Object builtinURIError() const { return b_uriError; }
304
305     Object builtinEvalErrorPrototype() const { return b_evalErrorPrototype; }
306     Object builtinRangeErrorPrototype() const { return b_rangeErrorPrototype; }
307     Object builtinReferenceErrorPrototype() const { return b_referenceErrorPrototype; }
308     Object builtinSyntaxErrorPrototype() const { return b_syntaxErrorPrototype; }
309     Object builtinTypeErrorPrototype() const { return b_typeErrorPrototype; }
310     Object builtinURIErrorPrototype() const { return b_uriErrorPrototype; }
311
312     void setCompatMode(Interpreter::CompatMode mode) { m_compatMode = mode; }
313     Interpreter::CompatMode compatMode() const { return m_compatMode; }
314
315     // Chained list of interpreters (ring)
316     static InterpreterImp* firstInterpreter() { return s_hook; }
317     InterpreterImp *nextInterpreter() const { return next; }
318     InterpreterImp *prevInterpreter() const { return prev; }
319
320     static InterpreterImp *interpreterWithGlobalObject(ObjectImp *);
321     
322     void setContext(ContextImp *c) { _context = c; }
323
324     void saveBuiltins (SavedBuiltins &builtins) const;
325     void restoreBuiltins (const SavedBuiltins &builtins);
326
327   private:
328     void clear();
329     Interpreter *m_interpreter;
330     ProtectedObject global;
331     Debugger *dbg;
332
333     // Built-in properties of the object prototype. These are accessible
334     // from here even if they are replaced by js code (e.g. assigning to
335     // Array.prototype)
336
337     ProtectedObject b_Object;
338     ProtectedObject b_Function;
339     ProtectedObject b_Array;
340     ProtectedObject b_Boolean;
341     ProtectedObject b_String;
342     ProtectedObject b_Number;
343     ProtectedObject b_Date;
344     ProtectedObject b_RegExp;
345     ProtectedObject b_Error;
346
347     ProtectedObject b_ObjectPrototype;
348     ProtectedObject b_FunctionPrototype;
349     ProtectedObject b_ArrayPrototype;
350     ProtectedObject b_BooleanPrototype;
351     ProtectedObject b_StringPrototype;
352     ProtectedObject b_NumberPrototype;
353     ProtectedObject b_DatePrototype;
354     ProtectedObject b_RegExpPrototype;
355     ProtectedObject b_ErrorPrototype;
356
357     ProtectedObject b_evalError;
358     ProtectedObject b_rangeError;
359     ProtectedObject b_referenceError;
360     ProtectedObject b_syntaxError;
361     ProtectedObject b_typeError;
362     ProtectedObject b_uriError;
363
364     ProtectedObject b_evalErrorPrototype;
365     ProtectedObject b_rangeErrorPrototype;
366     ProtectedObject b_referenceErrorPrototype;
367     ProtectedObject b_syntaxErrorPrototype;
368     ProtectedObject b_typeErrorPrototype;
369     ProtectedObject b_uriErrorPrototype;
370
371     ExecState *globExec;
372     Interpreter::CompatMode m_compatMode;
373
374     // Chained list of interpreters (ring) - for collector
375     static InterpreterImp* s_hook;
376     InterpreterImp *next, *prev;
377     
378     ContextImp *_context;
379
380     int recursion;
381   };
382
383   class AttachedInterpreter;
384   class DebuggerImp {
385   public:
386
387     DebuggerImp() {
388       interps = 0;
389       isAborted = false;
390     }
391
392     void abort() { isAborted = true; }
393     bool aborted() const { return isAborted; }
394
395     AttachedInterpreter *interps;
396     bool isAborted;
397   };
398
399
400
401   class InternalFunctionImp : public ObjectImp {
402   public:
403     InternalFunctionImp(FunctionPrototypeImp *funcProto);
404     bool implementsHasInstance() const;
405     Boolean hasInstance(ExecState *exec, const Value &value);
406
407     virtual const ClassInfo *classInfo() const { return &info; }
408     static const ClassInfo info;
409   };
410
411   // helper function for toInteger, toInt32, toUInt32 and toUInt16
412   double roundValue(ExecState *exec, const Value &v);
413
414 #ifndef NDEBUG
415   void printInfo(ExecState *exec, const char *s, const Value &o, int lineno = -1);
416 #endif
417
418 }; // namespace
419
420
421 #endif //  _INTERNAL_H_