1 /* 2 * This file is part of the KDE libraries 3 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) 4 * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. 5 * Copyright (C) 2007, 2008 Maksim Orlovich <maksim@kde.org> 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Library General Public 9 * License as published by the Free Software Foundation; either 10 * version 2 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Library General Public License for more details. 16 * 17 * You should have received a copy of the GNU Library General Public License 18 * along with this library; see the file COPYING.LIB. If not, write to 19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 * Boston, MA 02110-1301, USA. 21 * 22 */ 23 24 #ifndef KJS_FUNCTION_H 25 #define KJS_FUNCTION_H 26 27 #include "object.h" 28 #include "JSVariableObject.h" 29 #include <wtf/OwnPtr.h> 30 31 namespace KJS 32 { 33 34 class ActivationImp; 35 class FunctionPrototype; 36 37 class KJS_EXPORT InternalFunctionImp : public JSObject 38 { 39 public: 40 InternalFunctionImp(); 41 InternalFunctionImp(FunctionPrototype *); 42 InternalFunctionImp(FunctionPrototype *, const Identifier &); 43 44 bool implementsCall() const override; 45 JSValue *callAsFunction(ExecState *, JSObject *thisObjec, const List &args) override = 0; 46 bool implementsHasInstance() const override; 47 classInfo()48 const ClassInfo *classInfo() const override 49 { 50 return &info; 51 } 52 static const ClassInfo info; functionName()53 const Identifier &functionName() const 54 { 55 return m_name; 56 } setFunctionName(const Identifier & name)57 void setFunctionName(const Identifier &name) 58 { 59 m_name = name; 60 } 61 62 private: 63 Identifier m_name; 64 #ifdef _WIN32 65 InternalFunctionImp(const InternalFunctionImp &); 66 InternalFunctionImp &operator=(const InternalFunctionImp &); 67 #endif 68 }; 69 70 /** 71 * A minimal object that just throws an exception if executed. 72 */ 73 class Thrower : public JSObject 74 { 75 public: 76 Thrower(ErrorType type); 77 78 JSValue *callAsFunction(ExecState *exec, JSObject *, const List &args) override; implementsCall()79 bool implementsCall() const override 80 { 81 return true; 82 }; 83 private: 84 ErrorType m_type; 85 }; 86 87 class BoundFunction : public InternalFunctionImp 88 { 89 public: 90 explicit BoundFunction(ExecState *exec, JSObject *targetFunction, JSObject *boundThis, List boundArgs); 91 92 void setTargetFunction(JSObject *targetFunction); 93 void setBoundThis(JSObject *boundThis); 94 void setBoundArgs(const List &boundArgs); 95 96 JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &extraArgs) override; implementsCall()97 bool implementsCall() const override 98 { 99 return true; 100 }; 101 102 using KJS::JSObject::construct; 103 JSObject *construct(ExecState *exec, const List &extraArgs) override; implementsConstruct()104 bool implementsConstruct() const override 105 { 106 return true; 107 }; 108 109 bool hasInstance(ExecState *exec, JSValue *value) override; implementsHasInstance()110 bool implementsHasInstance() const override 111 { 112 return true; 113 }; 114 115 private: 116 ProtectedPtr<JSObject> m_targetFunction; 117 ProtectedPtr<JSObject> m_boundThis; 118 List m_boundArgs; 119 }; 120 121 /** 122 * @internal 123 * 124 * The initial value of Function.prototype (and thus all objects created 125 * with the Function constructor) 126 */ 127 class KJS_EXPORT FunctionPrototype : public InternalFunctionImp 128 { 129 public: 130 FunctionPrototype(ExecState *exec); 131 ~FunctionPrototype() override; 132 133 JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) override; 134 }; 135 136 class IndexToNameMap 137 { 138 public: 139 IndexToNameMap(FunctionImp *func, const List &args); 140 ~IndexToNameMap(); 141 142 Identifier &operator[](int index); 143 Identifier &operator[](const Identifier &indexIdentifier); 144 bool isMapped(const Identifier &index) const; 145 void unMap(const Identifier &index); 146 int size() const; 147 148 private: 149 IndexToNameMap(); // prevent construction w/o parameters 150 int _size; 151 Identifier *_map; 152 }; 153 154 class Arguments : public JSObject 155 { 156 public: 157 Arguments(ExecState *exec, FunctionImp *func, const List &args, ActivationImp *act); 158 void mark() override; 159 using KJS::JSObject::getOwnPropertySlot; 160 bool getOwnPropertySlot(ExecState *, const Identifier &, PropertySlot &) override; 161 using KJS::JSObject::put; 162 void put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr = None) override; 163 using KJS::JSObject::deleteProperty; 164 bool deleteProperty(ExecState *exec, const Identifier &propertyName) override; 165 void getOwnPropertyNames(ExecState *, PropertyNameArray &, PropertyMap::PropertyMode mode) override; 166 167 bool defineOwnProperty(ExecState *exec, const Identifier &propertyName, PropertyDescriptor &desc, bool shouldThrow) override; 168 classInfo()169 const ClassInfo *classInfo() const override 170 { 171 return &info; 172 } 173 static const ClassInfo info; 174 private: 175 static JSValue *mappedIndexGetter(ExecState *exec, JSObject *, const Identifier &, const PropertySlot &slot); 176 177 ActivationImp *_activationObject; 178 mutable IndexToNameMap indexToNameMap; 179 }; 180 181 class ActivationImp : public JSVariableObject 182 { 183 public: 184 enum { 185 FunctionSlot = NumVarObjectSlots, 186 ArgumentsObjectSlot, 187 NumReservedSlots = ArgumentsObjectSlot + 1 188 }; 189 190 void setup(ExecState *exec, FunctionImp *function, const List *arguments, 191 LocalStorageEntry *stackSpace); 192 193 // Request that this activation be torn off when the code using it stops running 194 void requestTearOff(); 195 void performTearOff(); 196 197 using KJS::JSObject::getOwnPropertySlot; 198 bool getOwnPropertySlot(ExecState *exec, const Identifier &, PropertySlot &) override; 199 using KJS::JSObject::put; 200 void put(ExecState *exec, const Identifier &propertyName, JSValue *value, int attr = None) override; 201 using KJS::JSObject::deleteProperty; 202 bool deleteProperty(ExecState *exec, const Identifier &propertyName) override; 203 204 void putDirect(const Identifier &propertyName, JSValue *value, int attr = 0) override; 205 using JSObject::putDirect; 206 JSValue *getDirect(const Identifier &propertyName) const override; 207 bool getPropertyAttributes(const Identifier &propertyName, unsigned &attributes) const override; 208 isLocalReadOnly(int propertyID)209 bool isLocalReadOnly(int propertyID) const 210 { 211 return (localStorage[propertyID].attributes & ReadOnly) == ReadOnly; 212 } 213 classInfo()214 const ClassInfo *classInfo() const override 215 { 216 return &info; 217 } 218 static const ClassInfo info; 219 isActivation()220 bool isActivation() const override 221 { 222 return true; 223 } 224 void setupLocals(FunctionBodyNode *fbody); 225 void setupFunctionLocals(FunctionBodyNode *fbody, ExecState *exec); 226 passedInArguments()227 const List &passedInArguments() const 228 { 229 return *arguments; 230 } 231 232 // really FunctionImp, but type isn't declared yet function()233 JSValue *function() 234 { 235 return functionSlot(); 236 } 237 private: functionSlot()238 JSValue *&functionSlot() 239 { 240 return localStorage[FunctionSlot].val.valueVal; 241 } 242 argumentsObjectSlot()243 JSValue *&argumentsObjectSlot() 244 { 245 return localStorage[ArgumentsObjectSlot].val.valueVal; 246 } 247 248 static PropertySlot::GetValueFunc getArgumentsGetter(); 249 static JSValue *argumentsGetter(ExecState *exec, JSObject *, const Identifier &, const PropertySlot &slot); 250 void createArgumentsObject(ExecState *exec); 251 numLocals()252 int numLocals() const 253 { 254 return lengthSlot(); 255 } validLocal(int id)256 bool validLocal(int id) const 257 { 258 return 0 <= id && id < numLocals(); 259 } 260 const List *arguments; 261 }; 262 263 class GlobalFuncImp : public InternalFunctionImp 264 { 265 public: 266 GlobalFuncImp(ExecState *, FunctionPrototype *, int i, int len, const Identifier &); 267 JSValue *callAsFunction(ExecState *exec, JSObject *thisObj, const List &args) override; 268 enum { Eval, ParseInt, ParseFloat, IsNaN, IsFinite, Escape, UnEscape, 269 DecodeURI, DecodeURIComponent, EncodeURI, EncodeURIComponent 270 #ifndef NDEBUG 271 , KJSPrint 272 #endif 273 }; 274 private: 275 int id; 276 }; 277 278 static const double mantissaOverflowLowerBound = 9007199254740992.0; 279 double parseIntOverflow(const char *s, int length, int radix); 280 281 double parseInt(const UString &s, int radix); 282 double parseFloat(const UString &s); 283 284 } // namespace 285 286 #endif 287