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