internal.h

00001 // -*- c-basic-offset: 2 -*-
00002 /*
00003  *  This file is part of the KDE libraries
00004  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
00005  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
00006  *  Copyright (C) 2003 Apple Computer, Inc.
00007  *
00008  *  This library is free software; you can redistribute it and/or
00009  *  modify it under the terms of the GNU Library General Public
00010  *  License as published by the Free Software Foundation; either
00011  *  version 2 of the License, or (at your option) any later version.
00012  *
00013  *  This library is distributed in the hope that it will be useful,
00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  *  Library General Public License for more details.
00017  *
00018  *  You should have received a copy of the GNU Library General Public License
00019  *  along with this library; see the file COPYING.LIB.  If not, write to
00020  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00021  *  Boston, MA 02110-1301, USA.
00022  *
00023  */
00024 
00025 #ifndef _INTERNAL_H_
00026 #define _INTERNAL_H_
00027 
00028 #include "ustring.h"
00029 #include "value.h"
00030 #include "object.h"
00031 #include "function.h"
00032 #include "types.h"
00033 #include "interpreter.h"
00034 #include "scope_chain.h"
00035 #include "array_instance.h"
00036 
00037 #ifndef I18N_NOOP
00038 #define I18N_NOOP(s) s
00039 #endif
00040 
00041 namespace KJS {
00042 
00043   static const double D16 = 65536.0;
00044   static const double D32 = 4294967296.0;
00045 
00046   class FunctionBodyNode;
00047   class FunctionBodyNode;
00048   class FunctionPrototypeImp;
00049   class FunctionImp;
00050   class Parameter;
00051   class Debugger;
00052 
00053   // ---------------------------------------------------------------------------
00054   //                            Primitive impls
00055   // ---------------------------------------------------------------------------
00056 
00057   class UndefinedImp : public ValueImp {
00058   public:
00059     Type type() const { return UndefinedType; }
00060 
00061     Value toPrimitive(ExecState *exec, Type preferred = UnspecifiedType) const;
00062     bool toBoolean(ExecState *exec) const;
00063     double toNumber(ExecState *exec) const;
00064     UString toString(ExecState *exec) const;
00065     Object toObject(ExecState *exec) const;
00066 
00067     static UndefinedImp *staticUndefined;
00068   };
00069 
00070   inline Undefined::Undefined(UndefinedImp *imp) : Value(imp) { }
00071 
00072   class NullImp : public ValueImp {
00073   public:
00074     Type type() const { return NullType; }
00075 
00076     Value toPrimitive(ExecState *exec, Type preferred = UnspecifiedType) const;
00077     bool toBoolean(ExecState *exec) const;
00078     double toNumber(ExecState *exec) const;
00079     UString toString(ExecState *exec) const;
00080     Object toObject(ExecState *exec) const;
00081 
00082     static NullImp *staticNull;
00083   };
00084 
00085   inline Null::Null(NullImp *imp) : Value(imp) { }
00086 
00087   class BooleanImp : public ValueImp {
00088   public:
00089     BooleanImp(bool v = false) : val(v) { }
00090     bool value() const { return val; }
00091 
00092     Type type() const { return BooleanType; }
00093 
00094     Value toPrimitive(ExecState *exec, Type preferred = UnspecifiedType) const;
00095     bool toBoolean(ExecState *exec) const;
00096     double toNumber(ExecState *exec) const;
00097     UString toString(ExecState *exec) const;
00098     Object toObject(ExecState *exec) const;
00099 
00100     static BooleanImp *staticTrue;
00101     static BooleanImp *staticFalse;
00102   private:
00103     bool val;
00104   };
00105 
00106   inline Boolean::Boolean(BooleanImp *imp) : Value(imp) { }
00107 
00108   class StringImp : public ValueImp {
00109   public:
00110     StringImp(const UString& v) : val(v) { }
00111     UString value() const { return val; }
00112 
00113     Type type() const { return StringType; }
00114 
00115     Value toPrimitive(ExecState *exec, Type preferred = UnspecifiedType) const;
00116     bool toBoolean(ExecState *exec) const;
00117     double toNumber(ExecState *exec) const;
00118     UString toString(ExecState *exec) const;
00119     Object toObject(ExecState *exec) const;
00120 
00121   private:
00122     UString val;
00123   };
00124 
00125   inline String::String(StringImp *imp) : Value(imp) { }
00126 
00127   class NumberImp : public ValueImp {
00128     friend class Number;
00129     friend class InterpreterImp;
00130   public:
00131     static ValueImp *create(int);
00132     static ValueImp *create(double);
00133     static ValueImp *zero() { return SimpleNumber::make(0); }
00134     static ValueImp *one() { return SimpleNumber::make(1); }
00135     static ValueImp *two() { return SimpleNumber::make(2); }
00136 
00137     double value() const { return val; }
00138 
00139     Type type() const { return NumberType; }
00140 
00141     Value toPrimitive(ExecState *exec, Type preferred = UnspecifiedType) const;
00142     bool toBoolean(ExecState *exec) const;
00143     double toNumber(ExecState *exec) const;
00144     UString toString(ExecState *exec) const;
00145     Object toObject(ExecState *exec) const;
00146 
00147     static NumberImp *staticNaN;
00148 
00149   private:
00150     NumberImp(double v) : val(v) { }
00151 
00152     virtual bool toUInt32(unsigned&) const;
00153 
00154     double val;
00155   };
00156 
00157   inline Number::Number(NumberImp *imp) : Value(imp) { }
00158 
00162   class LabelStack {
00163   public:
00164     LabelStack(): tos(0L), iterationDepth(0), switchDepth(0) {}
00165     ~LabelStack();
00166 
00167     LabelStack(const LabelStack &other);
00168     LabelStack &operator=(const LabelStack &other);
00169 
00174     bool push(const Identifier &id);
00178     bool contains(const Identifier &id) const;
00182     void pop();
00183 
00184     void pushIteration() { iterationDepth++; }
00185     void popIteration() { iterationDepth--; }
00186     bool inIteration() const { return (iterationDepth > 0); }
00187 
00188     void pushSwitch() { switchDepth++; }
00189     void popSwitch() { switchDepth--; }
00190     bool inSwitch() const { return (switchDepth > 0); }
00191 
00192   private:
00193     struct StackElem {
00194       Identifier id;
00195       StackElem *prev;
00196     };
00197 
00198     StackElem *tos;
00199     void clear();
00200     int iterationDepth;
00201     int switchDepth;
00202   };
00203 
00204 
00205   // ---------------------------------------------------------------------------
00206   //                            Parsing & evaluateion
00207   // ---------------------------------------------------------------------------
00208 
00209   class SourceCode {
00210   public:
00211     SourceCode(int _sid)
00212       : sid(_sid), interpreter(0), refcount(0), next(0) {}
00213 
00214     void ref() { refcount++; }
00215     void deref() { if (!--refcount) cleanup(); }
00216     void cleanup();
00217 
00218     int sid;
00219     InterpreterImp *interpreter;
00220     int refcount;
00221     SourceCode *next;
00222   };
00223 
00231   class Parser {
00232   public:
00233     static FunctionBodyNode *parse(const UChar *code, unsigned int length, SourceCode **src,
00234                    int *errLine = 0, UString *errMsg = 0);
00235 
00236     static FunctionBodyNode *progNode;
00237     static SourceCode *source;
00238     static int sid;
00239   private:
00240   };
00241 
00242   class InterpreterImp {
00243     friend class Collector;
00244   public:
00245     static void globalInit();
00246     static void globalClear();
00247 
00248     InterpreterImp(Interpreter *interp, const Object &glob);
00249     ~InterpreterImp();
00250 
00251     Object &globalObject() const { return const_cast<Object &>(global); }
00252     Interpreter* interpreter() const { return m_interpreter; }
00253 
00254     void initGlobalObject();
00255     static void lock();
00256     static void unlock();
00257 
00258     void mark();
00259 
00260     ExecState *globalExec() { return globExec; }
00261     bool checkSyntax(const UString &code,int *errLine, UString *errMsg);
00262     bool checkSyntax(const UString &code);
00263     Completion evaluate(const UString &code, const Value &thisV);
00264     Debugger *debugger() const { return dbg; }
00265     void setDebugger(Debugger *d);
00266 
00267     Object builtinObject() const { return b_Object; }
00268     Object builtinFunction() const { return b_Function; }
00269     Object builtinArray() const { return b_Array; }
00270     Object builtinBoolean() const { return b_Boolean; }
00271     Object builtinString() const { return b_String; }
00272     Object builtinNumber() const { return b_Number; }
00273     Object builtinDate() const { return b_Date; }
00274     Object builtinRegExp() const { return b_RegExp; }
00275     Object builtinError() const { return b_Error; }
00276 
00277     Object builtinObjectPrototype() const { return b_ObjectPrototype; }
00278     Object builtinFunctionPrototype() const { return b_FunctionPrototype; }
00279     Object builtinArrayPrototype() const { return b_ArrayPrototype; }
00280     Object builtinBooleanPrototype() const { return b_BooleanPrototype; }
00281     Object builtinStringPrototype() const { return b_StringPrototype; }
00282     Object builtinNumberPrototype() const { return b_NumberPrototype; }
00283     Object builtinDatePrototype() const { return b_DatePrototype; }
00284     Object builtinRegExpPrototype() const { return b_RegExpPrototype; }
00285     Object builtinErrorPrototype() const { return b_ErrorPrototype; }
00286 
00287     Object builtinEvalError() const { return b_evalError; }
00288     Object builtinRangeError() const { return b_rangeError; }
00289     Object builtinReferenceError() const { return b_referenceError; }
00290     Object builtinSyntaxError() const { return b_syntaxError; }
00291     Object builtinTypeError() const { return b_typeError; }
00292     Object builtinURIError() const { return b_uriError; }
00293 
00294     Object builtinEvalErrorPrototype() const { return b_evalErrorPrototype; }
00295     Object builtinRangeErrorPrototype() const { return b_rangeErrorPrototype; }
00296     Object builtinReferenceErrorPrototype() const { return b_referenceErrorPrototype; }
00297     Object builtinSyntaxErrorPrototype() const { return b_syntaxErrorPrototype; }
00298     Object builtinTypeErrorPrototype() const { return b_typeErrorPrototype; }
00299     Object builtinURIErrorPrototype() const { return b_uriErrorPrototype; }
00300 
00301     void setCompatMode(Interpreter::CompatMode mode) { m_compatMode = mode; }
00302     Interpreter::CompatMode compatMode() const { return m_compatMode; }
00303 
00304     // Chained list of interpreters (ring)
00305     static InterpreterImp* firstInterpreter() { return s_hook; }
00306     InterpreterImp *nextInterpreter() const { return next; }
00307     InterpreterImp *prevInterpreter() const { return prev; }
00308 
00309     void addSourceCode(SourceCode *code);
00310     void removeSourceCode(SourceCode *code);
00311 
00312     void setContext(ContextImp *c) { _context = c; }
00313 
00314   private:
00315     void clear();
00316     Interpreter *m_interpreter;
00317     Object global;
00318     Debugger *dbg;
00319 
00320     // Built-in properties of the object prototype. These are accessible
00321     // from here even if they are replaced by js code (e.g. assigning to
00322     // Array.prototype)
00323 
00324     Object b_Object;
00325     Object b_Function;
00326     Object b_Array;
00327     Object b_Boolean;
00328     Object b_String;
00329     Object b_Number;
00330     Object b_Date;
00331     Object b_RegExp;
00332     Object b_Error;
00333 
00334     Object b_ObjectPrototype;
00335     Object b_FunctionPrototype;
00336     Object b_ArrayPrototype;
00337     Object b_BooleanPrototype;
00338     Object b_StringPrototype;
00339     Object b_NumberPrototype;
00340     Object b_DatePrototype;
00341     Object b_RegExpPrototype;
00342     Object b_ErrorPrototype;
00343 
00344     Object b_evalError;
00345     Object b_rangeError;
00346     Object b_referenceError;
00347     Object b_syntaxError;
00348     Object b_typeError;
00349     Object b_uriError;
00350 
00351     Object b_evalErrorPrototype;
00352     Object b_rangeErrorPrototype;
00353     Object b_referenceErrorPrototype;
00354     Object b_syntaxErrorPrototype;
00355     Object b_typeErrorPrototype;
00356     Object b_uriErrorPrototype;
00357 
00358     ExecState *globExec;
00359     Interpreter::CompatMode m_compatMode;
00360 
00361     // Chained list of interpreters (ring) - for collector
00362     static InterpreterImp* s_hook;
00363     InterpreterImp *next, *prev;
00364 
00365     ContextImp *_context;
00366 
00367     int recursion;
00368     SourceCode *sources;
00369   };
00370 
00371   class AttachedInterpreter;
00372   class DebuggerImp {
00373   public:
00374 
00375     DebuggerImp() {
00376       interps = 0;
00377       isAborted = false;
00378     }
00379 
00380     void abort() { isAborted = true; }
00381     bool aborted() const { return isAborted; }
00382 
00383     AttachedInterpreter *interps;
00384     bool isAborted;
00385   };
00386 
00390   class FunctionImp : public InternalFunctionImp {
00391     friend class ActivationImp;
00392   public:
00393     FunctionImp(ExecState *exec, const Identifier &n = Identifier::null());
00394     virtual ~FunctionImp();
00395 
00396     virtual Value get(ExecState *exec, const Identifier &propertyName) const;
00397     virtual void put(ExecState *exec, const Identifier &propertyName, const Value &value, int attr = None);
00398     virtual bool hasProperty(ExecState *exec, const Identifier &propertyName) const;
00399     virtual bool deleteProperty(ExecState *exec, const Identifier &propertyName);
00400 
00401     virtual bool implementsCall() const;
00402     virtual Value call(ExecState *exec, Object &thisObj, const List &args);
00403 
00404     void addParameter(const Identifier &n);
00405     Identifier parameterProperty(int index) const;
00406     // parameters in string representation, e.g. (a, b, c)
00407     UString parameterString() const;
00408     virtual CodeType codeType() const = 0;
00409 
00410     virtual Completion execute(ExecState *exec) = 0;
00411     int firstLine() const { return line0; }
00412     int lastLine() const { return line1; }
00413     int sourceId() const { return sid; }
00414 
00415     virtual const ClassInfo *classInfo() const { return &info; }
00416     static const ClassInfo info;
00417   protected:
00418     Parameter *param;
00419     int line0;
00420     int line1;
00421     int sid;
00422 
00423   private:
00424     void processParameters(ExecState *exec, const List &);
00425     virtual void processVarDecls(ExecState *exec);
00426   };
00427 
00428   class DeclaredFunctionImp : public FunctionImp {
00429   public:
00430     DeclaredFunctionImp(ExecState *exec, const Identifier &n,
00431             FunctionBodyNode *b, const ScopeChain &sc);
00432     ~DeclaredFunctionImp();
00433 
00434     bool implementsConstruct() const;
00435     Object construct(ExecState *exec, const List &args);
00436 
00437     virtual Completion execute(ExecState *exec);
00438     CodeType codeType() const { return FunctionCode; }
00439     FunctionBodyNode *body;
00440 
00441     virtual const ClassInfo *classInfo() const { return &info; }
00442     KJS_EXPORT static const ClassInfo info;
00443   private:
00444     virtual void processVarDecls(ExecState *exec);
00445   };
00446 
00447   class ActivationImp;
00448 
00449   class ArgumentsImp : public ObjectImp {
00450   public:
00451     ArgumentsImp(ExecState *exec, FunctionImp *func, const List &args, ActivationImp *act);
00452 
00453     virtual void mark();
00454 
00455     virtual Value get(ExecState *exec, const Identifier &propertyName) const;
00456     virtual void put(ExecState *exec, const Identifier &propertyName,
00457              const Value &value, int attr = None);
00458 
00459     virtual const ClassInfo *classInfo() const { return &info; }
00460     static const ClassInfo info;
00461 
00462   private:
00463     ActivationImp *activation;
00464   };
00465 
00466   class ActivationImp : public ObjectImp {
00467   public:
00468     ActivationImp(FunctionImp *function, const List &arguments);
00469 
00470     virtual Value get(ExecState *exec, const Identifier &propertyName) const;
00471     virtual bool hasProperty(ExecState *exec, const Identifier &propertyName) const;
00472     virtual bool deleteProperty(ExecState *exec, const Identifier &propertyName);
00473 
00474     virtual const ClassInfo *classInfo() const { return &info; }
00475     static const ClassInfo info;
00476 
00477     virtual void mark();
00478 
00479   private:
00480     FunctionImp *_function;
00481     List _arguments;
00482     mutable ArgumentsImp *_argumentsObject;
00483   };
00484 
00485   class GlobalFuncImp : public InternalFunctionImp {
00486   public:
00487     GlobalFuncImp(ExecState *exec, FunctionPrototypeImp *funcProto,
00488           int i, int len, const Identifier &_ident);
00489     virtual bool implementsCall() const;
00490     virtual Value call(ExecState *exec, Object &thisObj, const List &args);
00491     virtual CodeType codeType() const;
00492     enum { Eval, ParseInt, ParseFloat, IsNaN, IsFinite, DecodeURI, DecodeURIComponent,
00493        EncodeURI, EncodeURIComponent, Escape, UnEscape, KJSPrint };
00494   private:
00495     int id;
00496   };
00497 
00498   // helper function for toInteger, toInt32, toUInt32 and toUInt16
00499   double roundValue(ExecState *exec, const Value &v);
00500 
00501 #ifndef NDEBUG
00502   void printInfo(ExecState *exec, const char *s, const Value &o, int lineno = -1);
00503 #endif
00504 
00505 } // namespace
00506 
00507 
00508 #endif //  _INTERNAL_H_
KDE Home | KDE Accessibility Home | Description of Access Keys