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_