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