File indexing completed on 2024-05-12 15:43:20
0001 /* 0002 * This file is part of the KDE libraries 0003 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) 0004 * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. 0005 * Copyright (C) 2007, 2008 Maksim Orlovich <maksim@kde.org> 0006 * 0007 * This library is free software; you can redistribute it and/or 0008 * modify it under the terms of the GNU Library General Public 0009 * License as published by the Free Software Foundation; either 0010 * version 2 of the License, or (at your option) any later version. 0011 * 0012 * This library is distributed in the hope that it will be useful, 0013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0015 * Library General Public License for more details. 0016 * 0017 * You should have received a copy of the GNU Library General Public License 0018 * along with this library; see the file COPYING.LIB. If not, write to 0019 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0020 * Boston, MA 02110-1301, USA. 0021 * 0022 */ 0023 0024 #ifndef KJS_FUNCTION_H 0025 #define KJS_FUNCTION_H 0026 0027 #include "object.h" 0028 #include "JSVariableObject.h" 0029 #include <wtf/OwnPtr.h> 0030 0031 namespace KJS 0032 { 0033 0034 class ActivationImp; 0035 class FunctionPrototype; 0036 0037 class KJS_EXPORT InternalFunctionImp : public JSObject 0038 { 0039 public: 0040 InternalFunctionImp(); 0041 InternalFunctionImp(FunctionPrototype *); 0042 InternalFunctionImp(FunctionPrototype *, const Identifier &); 0043 0044 bool implementsCall() const override; 0045 JSValue *callAsFunction(ExecState *, JSObject *thisObjec, const List &args) override = 0; 0046 bool implementsHasInstance() const override; 0047 0048 const ClassInfo *classInfo() const override 0049 { 0050 return &info; 0051 } 0052 static const ClassInfo info; 0053 const Identifier &functionName() const 0054 { 0055 return m_name; 0056 } 0057 void setFunctionName(const Identifier &name) 0058 { 0059 m_name = name; 0060 } 0061 0062 private: 0063 Identifier m_name; 0064 #ifdef _WIN32 0065 InternalFunctionImp(const InternalFunctionImp &); 0066 InternalFunctionImp &operator=(const InternalFunctionImp &); 0067 #endif 0068 }; 0069 0070 /** 0071 * A minimal object that just throws an exception if executed. 0072 */ 0073 class Thrower : public JSObject 0074 { 0075 public: 0076 Thrower(ErrorType type); 0077 0078 JSValue *callAsFunction(ExecState *exec, JSObject *, const List &args) override; 0079 bool implementsCall() const override 0080 { 0081 return true; 0082 }; 0083 private: 0084 ErrorType m_type; 0085 }; 0086 0087 class BoundFunction : public InternalFunctionImp 0088 { 0089 public: 0090 explicit BoundFunction(ExecState *exec, JSObject *targetFunction, JSObject *boundThis, List boundArgs); 0091 0092 void setTargetFunction(JSObject *targetFunction); 0093 void setBoundThis(JSObject *boundThis); 0094 void setBoundArgs(const List &boundArgs); 0095 0096 JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &extraArgs) override; 0097 bool implementsCall() const override 0098 { 0099 return true; 0100 }; 0101 0102 using KJS::JSObject::construct; 0103 JSObject *construct(ExecState *exec, const List &extraArgs) override; 0104 bool implementsConstruct() const override 0105 { 0106 return true; 0107 }; 0108 0109 bool hasInstance(ExecState *exec, JSValue *value) override; 0110 bool implementsHasInstance() const override 0111 { 0112 return true; 0113 }; 0114 0115 private: 0116 ProtectedPtr<JSObject> m_targetFunction; 0117 ProtectedPtr<JSObject> m_boundThis; 0118 List m_boundArgs; 0119 }; 0120 0121 /** 0122 * @internal 0123 * 0124 * The initial value of Function.prototype (and thus all objects created 0125 * with the Function constructor) 0126 */ 0127 class KJS_EXPORT FunctionPrototype : public InternalFunctionImp 0128 { 0129 public: 0130 FunctionPrototype(ExecState *exec); 0131 ~FunctionPrototype() override; 0132 0133 JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) override; 0134 }; 0135 0136 class IndexToNameMap 0137 { 0138 public: 0139 IndexToNameMap(FunctionImp *func, const List &args); 0140 ~IndexToNameMap(); 0141 0142 Identifier &operator[](int index); 0143 Identifier &operator[](const Identifier &indexIdentifier); 0144 bool isMapped(const Identifier &index) const; 0145 void unMap(const Identifier &index); 0146 int size() const; 0147 0148 private: 0149 IndexToNameMap(); // prevent construction w/o parameters 0150 int _size; 0151 Identifier *_map; 0152 }; 0153 0154 class Arguments : public JSObject 0155 { 0156 public: 0157 Arguments(ExecState *exec, FunctionImp *func, const List &args, ActivationImp *act); 0158 void mark() override; 0159 using KJS::JSObject::getOwnPropertySlot; 0160 bool getOwnPropertySlot(ExecState *, const Identifier &, PropertySlot &) override; 0161 using KJS::JSObject::put; 0162 void put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr = None) override; 0163 using KJS::JSObject::deleteProperty; 0164 bool deleteProperty(ExecState *exec, const Identifier &propertyName) override; 0165 void getOwnPropertyNames(ExecState *, PropertyNameArray &, PropertyMap::PropertyMode mode) override; 0166 0167 bool defineOwnProperty(ExecState *exec, const Identifier &propertyName, PropertyDescriptor &desc, bool shouldThrow) override; 0168 0169 const ClassInfo *classInfo() const override 0170 { 0171 return &info; 0172 } 0173 static const ClassInfo info; 0174 private: 0175 static JSValue *mappedIndexGetter(ExecState *exec, JSObject *, const Identifier &, const PropertySlot &slot); 0176 0177 ActivationImp *_activationObject; 0178 mutable IndexToNameMap indexToNameMap; 0179 }; 0180 0181 class ActivationImp : public JSVariableObject 0182 { 0183 public: 0184 enum { 0185 FunctionSlot = NumVarObjectSlots, 0186 ArgumentsObjectSlot, 0187 NumReservedSlots = ArgumentsObjectSlot + 1 0188 }; 0189 0190 void setup(ExecState *exec, FunctionImp *function, const List *arguments, 0191 LocalStorageEntry *stackSpace); 0192 0193 // Request that this activation be torn off when the code using it stops running 0194 void requestTearOff(); 0195 void performTearOff(); 0196 0197 using KJS::JSObject::getOwnPropertySlot; 0198 bool getOwnPropertySlot(ExecState *exec, const Identifier &, PropertySlot &) override; 0199 using KJS::JSObject::put; 0200 void put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr = None) override; 0201 using KJS::JSObject::deleteProperty; 0202 bool deleteProperty(ExecState *exec, const Identifier &propertyName) override; 0203 0204 void putDirect(const Identifier &propertyName, JSValue *value, int attr = 0) override; 0205 using JSObject::putDirect; 0206 JSValue *getDirect(const Identifier &propertyName) const override; 0207 bool getPropertyAttributes(const Identifier &propertyName, unsigned &attributes) const override; 0208 0209 bool isLocalReadOnly(int propertyID) const 0210 { 0211 return (localStorage[propertyID].attributes & ReadOnly) == ReadOnly; 0212 } 0213 0214 const ClassInfo *classInfo() const override 0215 { 0216 return &info; 0217 } 0218 static const ClassInfo info; 0219 0220 bool isActivation() const override 0221 { 0222 return true; 0223 } 0224 void setupLocals(FunctionBodyNode *fbody); 0225 void setupFunctionLocals(FunctionBodyNode *fbody, ExecState *exec); 0226 0227 const List &passedInArguments() const 0228 { 0229 return *arguments; 0230 } 0231 0232 // really FunctionImp, but type isn't declared yet 0233 JSValue *function() 0234 { 0235 return functionSlot(); 0236 } 0237 private: 0238 JSValue *&functionSlot() 0239 { 0240 return localStorage[FunctionSlot].val.valueVal; 0241 } 0242 0243 JSValue *&argumentsObjectSlot() 0244 { 0245 return localStorage[ArgumentsObjectSlot].val.valueVal; 0246 } 0247 0248 static PropertySlot::GetValueFunc getArgumentsGetter(); 0249 static JSValue *argumentsGetter(ExecState *exec, JSObject *, const Identifier &, const PropertySlot &slot); 0250 void createArgumentsObject(ExecState *exec); 0251 0252 int numLocals() const 0253 { 0254 return lengthSlot(); 0255 } 0256 bool validLocal(int id) const 0257 { 0258 return 0 <= id && id < numLocals(); 0259 } 0260 const List *arguments; 0261 }; 0262 0263 class GlobalFuncImp : public InternalFunctionImp 0264 { 0265 public: 0266 GlobalFuncImp(ExecState *, FunctionPrototype *, int i, int len, const Identifier &); 0267 JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) override; 0268 enum { Eval, ParseInt, ParseFloat, IsNaN, IsFinite, Escape, UnEscape, 0269 DecodeURI, DecodeURIComponent, EncodeURI, EncodeURIComponent 0270 #ifndef NDEBUG 0271 , KJSPrint 0272 #endif 0273 }; 0274 private: 0275 int id; 0276 }; 0277 0278 static const double mantissaOverflowLowerBound = 9007199254740992.0; 0279 double parseIntOverflow(const char *s, int length, int radix); 0280 0281 double parseInt(const UString &s, int radix); 0282 double parseFloat(const UString &s); 0283 0284 } // namespace 0285 0286 #endif