diff options
Diffstat (limited to 'kjs/internal.h')
-rw-r--r-- | kjs/internal.h | 508 |
1 files changed, 508 insertions, 0 deletions
diff --git a/kjs/internal.h b/kjs/internal.h new file mode 100644 index 000000000..413fdaa52 --- /dev/null +++ b/kjs/internal.h @@ -0,0 +1,508 @@ +// -*- c-basic-offset: 2 -*- +/* + * This file is part of the KDE libraries + * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) + * Copyright (C) 2001 Peter Kelly (pmk@post.com) + * Copyright (C) 2003 Apple Computer, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef _INTERNAL_H_ +#define _INTERNAL_H_ + +#include "ustring.h" +#include "value.h" +#include "object.h" +#include "function.h" +#include "types.h" +#include "interpreter.h" +#include "scope_chain.h" +#include "array_instance.h" + +#ifndef I18N_NOOP +#define I18N_NOOP(s) s +#endif + +namespace KJS { + + static const double D16 = 65536.0; + static const double D32 = 4294967296.0; + + class FunctionBodyNode; + class FunctionBodyNode; + class FunctionPrototypeImp; + class FunctionImp; + class Parameter; + class Debugger; + + // --------------------------------------------------------------------------- + // Primitive impls + // --------------------------------------------------------------------------- + + class UndefinedImp : public ValueImp { + public: + Type type() const { return UndefinedType; } + + Value toPrimitive(ExecState *exec, Type preferred = UnspecifiedType) const; + bool toBoolean(ExecState *exec) const; + double toNumber(ExecState *exec) const; + UString toString(ExecState *exec) const; + Object toObject(ExecState *exec) const; + + static UndefinedImp *staticUndefined; + }; + + inline Undefined::Undefined(UndefinedImp *imp) : Value(imp) { } + + class NullImp : public ValueImp { + public: + Type type() const { return NullType; } + + Value toPrimitive(ExecState *exec, Type preferred = UnspecifiedType) const; + bool toBoolean(ExecState *exec) const; + double toNumber(ExecState *exec) const; + UString toString(ExecState *exec) const; + Object toObject(ExecState *exec) const; + + static NullImp *staticNull; + }; + + inline Null::Null(NullImp *imp) : Value(imp) { } + + class BooleanImp : public ValueImp { + public: + BooleanImp(bool v = false) : val(v) { } + bool value() const { return val; } + + Type type() const { return BooleanType; } + + Value toPrimitive(ExecState *exec, Type preferred = UnspecifiedType) const; + bool toBoolean(ExecState *exec) const; + double toNumber(ExecState *exec) const; + UString toString(ExecState *exec) const; + Object toObject(ExecState *exec) const; + + static BooleanImp *staticTrue; + static BooleanImp *staticFalse; + private: + bool val; + }; + + inline Boolean::Boolean(BooleanImp *imp) : Value(imp) { } + + class StringImp : public ValueImp { + public: + StringImp(const UString& v) : val(v) { } + UString value() const { return val; } + + Type type() const { return StringType; } + + Value toPrimitive(ExecState *exec, Type preferred = UnspecifiedType) const; + bool toBoolean(ExecState *exec) const; + double toNumber(ExecState *exec) const; + UString toString(ExecState *exec) const; + Object toObject(ExecState *exec) const; + + private: + UString val; + }; + + inline String::String(StringImp *imp) : Value(imp) { } + + class NumberImp : public ValueImp { + friend class Number; + friend class InterpreterImp; + public: + static ValueImp *create(int); + static ValueImp *create(double); + static ValueImp *zero() { return SimpleNumber::make(0); } + static ValueImp *one() { return SimpleNumber::make(1); } + static ValueImp *two() { return SimpleNumber::make(2); } + + double value() const { return val; } + + Type type() const { return NumberType; } + + Value toPrimitive(ExecState *exec, Type preferred = UnspecifiedType) const; + bool toBoolean(ExecState *exec) const; + double toNumber(ExecState *exec) const; + UString toString(ExecState *exec) const; + Object toObject(ExecState *exec) const; + + static NumberImp *staticNaN; + + private: + NumberImp(double v) : val(v) { } + + virtual bool toUInt32(unsigned&) const; + + double val; + }; + + inline Number::Number(NumberImp *imp) : Value(imp) { } + + /** + * @short The "label set" in Ecma-262 spec + */ + class LabelStack { + public: + LabelStack(): tos(0L), iterationDepth(0), switchDepth(0) {} + ~LabelStack(); + + LabelStack(const LabelStack &other); + LabelStack &operator=(const LabelStack &other); + + /** + * If id is not empty and is not in the stack already, puts it on top of + * the stack and returns true, otherwise returns false + */ + bool push(const Identifier &id); + /** + * Is the id in the stack? + */ + bool contains(const Identifier &id) const; + /** + * Removes from the stack the last pushed id (what else?) + */ + void pop(); + + void pushIteration() { iterationDepth++; } + void popIteration() { iterationDepth--; } + bool inIteration() const { return (iterationDepth > 0); } + + void pushSwitch() { switchDepth++; } + void popSwitch() { switchDepth--; } + bool inSwitch() const { return (switchDepth > 0); } + + private: + struct StackElem { + Identifier id; + StackElem *prev; + }; + + StackElem *tos; + void clear(); + int iterationDepth; + int switchDepth; + }; + + + // --------------------------------------------------------------------------- + // Parsing & evaluateion + // --------------------------------------------------------------------------- + + class SourceCode { + public: + SourceCode(int _sid) + : sid(_sid), interpreter(0), refcount(0), next(0) {} + + void ref() { refcount++; } + void deref() { if (!--refcount) cleanup(); } + void cleanup(); + + int sid; + InterpreterImp *interpreter; + int refcount; + SourceCode *next; + }; + + /** + * @internal + * + * Parses ECMAScript source code and converts into FunctionBodyNode objects, which + * represent the root of a parse tree. This class provides a conveniant workaround + * for the problem of the bison parser working in a static context. + */ + class Parser { + public: + static FunctionBodyNode *parse(const UChar *code, unsigned int length, SourceCode **src, + int *errLine = 0, UString *errMsg = 0); + + static FunctionBodyNode *progNode; + static SourceCode *source; + static int sid; + private: + }; + + class InterpreterImp { + friend class Collector; + public: + static void globalInit(); + static void globalClear(); + + InterpreterImp(Interpreter *interp, const Object &glob); + ~InterpreterImp(); + + Object &globalObject() const { return const_cast<Object &>(global); } + Interpreter* interpreter() const { return m_interpreter; } + + void initGlobalObject(); + static void lock(); + static void unlock(); + + void mark(); + + ExecState *globalExec() { return globExec; } + bool checkSyntax(const UString &code,int *errLine, UString *errMsg); + bool checkSyntax(const UString &code); + Completion evaluate(const UString &code, const Value &thisV); + Debugger *debugger() const { return dbg; } + void setDebugger(Debugger *d); + + Object builtinObject() const { return b_Object; } + Object builtinFunction() const { return b_Function; } + Object builtinArray() const { return b_Array; } + Object builtinBoolean() const { return b_Boolean; } + Object builtinString() const { return b_String; } + Object builtinNumber() const { return b_Number; } + Object builtinDate() const { return b_Date; } + Object builtinRegExp() const { return b_RegExp; } + Object builtinError() const { return b_Error; } + + Object builtinObjectPrototype() const { return b_ObjectPrototype; } + Object builtinFunctionPrototype() const { return b_FunctionPrototype; } + Object builtinArrayPrototype() const { return b_ArrayPrototype; } + Object builtinBooleanPrototype() const { return b_BooleanPrototype; } + Object builtinStringPrototype() const { return b_StringPrototype; } + Object builtinNumberPrototype() const { return b_NumberPrototype; } + Object builtinDatePrototype() const { return b_DatePrototype; } + Object builtinRegExpPrototype() const { return b_RegExpPrototype; } + Object builtinErrorPrototype() const { return b_ErrorPrototype; } + + Object builtinEvalError() const { return b_evalError; } + Object builtinRangeError() const { return b_rangeError; } + Object builtinReferenceError() const { return b_referenceError; } + Object builtinSyntaxError() const { return b_syntaxError; } + Object builtinTypeError() const { return b_typeError; } + Object builtinURIError() const { return b_uriError; } + + Object builtinEvalErrorPrototype() const { return b_evalErrorPrototype; } + Object builtinRangeErrorPrototype() const { return b_rangeErrorPrototype; } + Object builtinReferenceErrorPrototype() const { return b_referenceErrorPrototype; } + Object builtinSyntaxErrorPrototype() const { return b_syntaxErrorPrototype; } + Object builtinTypeErrorPrototype() const { return b_typeErrorPrototype; } + Object builtinURIErrorPrototype() const { return b_uriErrorPrototype; } + + void setCompatMode(Interpreter::CompatMode mode) { m_compatMode = mode; } + Interpreter::CompatMode compatMode() const { return m_compatMode; } + + // Chained list of interpreters (ring) + static InterpreterImp* firstInterpreter() { return s_hook; } + InterpreterImp *nextInterpreter() const { return next; } + InterpreterImp *prevInterpreter() const { return prev; } + + void addSourceCode(SourceCode *code); + void removeSourceCode(SourceCode *code); + + void setContext(ContextImp *c) { _context = c; } + + private: + void clear(); + Interpreter *m_interpreter; + Object global; + Debugger *dbg; + + // Built-in properties of the object prototype. These are accessible + // from here even if they are replaced by js code (e.g. assigning to + // Array.prototype) + + Object b_Object; + Object b_Function; + Object b_Array; + Object b_Boolean; + Object b_String; + Object b_Number; + Object b_Date; + Object b_RegExp; + Object b_Error; + + Object b_ObjectPrototype; + Object b_FunctionPrototype; + Object b_ArrayPrototype; + Object b_BooleanPrototype; + Object b_StringPrototype; + Object b_NumberPrototype; + Object b_DatePrototype; + Object b_RegExpPrototype; + Object b_ErrorPrototype; + + Object b_evalError; + Object b_rangeError; + Object b_referenceError; + Object b_syntaxError; + Object b_typeError; + Object b_uriError; + + Object b_evalErrorPrototype; + Object b_rangeErrorPrototype; + Object b_referenceErrorPrototype; + Object b_syntaxErrorPrototype; + Object b_typeErrorPrototype; + Object b_uriErrorPrototype; + + ExecState *globExec; + Interpreter::CompatMode m_compatMode; + + // Chained list of interpreters (ring) - for collector + static InterpreterImp* s_hook; + InterpreterImp *next, *prev; + + ContextImp *_context; + + int recursion; + SourceCode *sources; + }; + + class AttachedInterpreter; + class DebuggerImp { + public: + + DebuggerImp() { + interps = 0; + isAborted = false; + } + + void abort() { isAborted = true; } + bool aborted() const { return isAborted; } + + AttachedInterpreter *interps; + bool isAborted; + }; + + /** + * @short Implementation class for functions implemented in JS. + */ + class FunctionImp : public InternalFunctionImp { + friend class ActivationImp; + public: + FunctionImp(ExecState *exec, const Identifier &n = Identifier::null()); + virtual ~FunctionImp(); + + virtual Value get(ExecState *exec, const Identifier &propertyName) const; + virtual void put(ExecState *exec, const Identifier &propertyName, const Value &value, int attr = None); + virtual bool hasProperty(ExecState *exec, const Identifier &propertyName) const; + virtual bool deleteProperty(ExecState *exec, const Identifier &propertyName); + + virtual bool implementsCall() const; + virtual Value call(ExecState *exec, Object &thisObj, const List &args); + + void addParameter(const Identifier &n); + Identifier parameterProperty(int index) const; + // parameters in string representation, e.g. (a, b, c) + UString parameterString() const; + virtual CodeType codeType() const = 0; + + virtual Completion execute(ExecState *exec) = 0; + int firstLine() const { return line0; } + int lastLine() const { return line1; } + int sourceId() const { return sid; } + + virtual const ClassInfo *classInfo() const { return &info; } + static const ClassInfo info; + protected: + Parameter *param; + int line0; + int line1; + int sid; + + private: + void processParameters(ExecState *exec, const List &); + virtual void processVarDecls(ExecState *exec); + }; + + class DeclaredFunctionImp : public FunctionImp { + public: + DeclaredFunctionImp(ExecState *exec, const Identifier &n, + FunctionBodyNode *b, const ScopeChain &sc); + ~DeclaredFunctionImp(); + + bool implementsConstruct() const; + Object construct(ExecState *exec, const List &args); + + virtual Completion execute(ExecState *exec); + CodeType codeType() const { return FunctionCode; } + FunctionBodyNode *body; + + virtual const ClassInfo *classInfo() const { return &info; } + KJS_EXPORT static const ClassInfo info; + private: + virtual void processVarDecls(ExecState *exec); + }; + + class ActivationImp; + + class ArgumentsImp : public ObjectImp { + public: + ArgumentsImp(ExecState *exec, FunctionImp *func, const List &args, ActivationImp *act); + + virtual void mark(); + + virtual Value get(ExecState *exec, const Identifier &propertyName) const; + virtual void put(ExecState *exec, const Identifier &propertyName, + const Value &value, int attr = None); + + virtual const ClassInfo *classInfo() const { return &info; } + static const ClassInfo info; + + private: + ActivationImp *activation; + }; + + class ActivationImp : public ObjectImp { + public: + ActivationImp(FunctionImp *function, const List &arguments); + + virtual Value get(ExecState *exec, const Identifier &propertyName) const; + virtual bool hasProperty(ExecState *exec, const Identifier &propertyName) const; + virtual bool deleteProperty(ExecState *exec, const Identifier &propertyName); + + virtual const ClassInfo *classInfo() const { return &info; } + static const ClassInfo info; + + virtual void mark(); + + private: + FunctionImp *_function; + List _arguments; + mutable ArgumentsImp *_argumentsObject; + }; + + class GlobalFuncImp : public InternalFunctionImp { + public: + GlobalFuncImp(ExecState *exec, FunctionPrototypeImp *funcProto, + int i, int len, const Identifier &_ident); + virtual bool implementsCall() const; + virtual Value call(ExecState *exec, Object &thisObj, const List &args); + virtual CodeType codeType() const; + enum { Eval, ParseInt, ParseFloat, IsNaN, IsFinite, DecodeURI, DecodeURIComponent, + EncodeURI, EncodeURIComponent, Escape, UnEscape, KJSPrint }; + private: + int id; + }; + + // helper function for toInteger, toInt32, toUInt32 and toUInt16 + double roundValue(ExecState *exec, const Value &v); + +#ifndef NDEBUG + void printInfo(ExecState *exec, const char *s, const Value &o, int lineno = -1); +#endif + +} // namespace + + +#endif // _INTERNAL_H_ |