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