1 /*
2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 */
20
21 #include "config.h"
22 #include "FunctionPrototype.h"
23
24 #include "Arguments.h"
25 #include "JSArray.h"
26 #include "JSFunction.h"
27 #include "JSString.h"
28 #include "Interpreter.h"
29 #include "PrototypeFunction.h"
30
31 namespace JSC {
32
33 ASSERT_CLASS_FITS_IN_CELL(FunctionPrototype);
34
35 static JSValuePtr functionProtoFuncToString(ExecState*, JSObject*, JSValuePtr, const ArgList&);
36 static JSValuePtr functionProtoFuncApply(ExecState*, JSObject*, JSValuePtr, const ArgList&);
37 static JSValuePtr functionProtoFuncCall(ExecState*, JSObject*, JSValuePtr, const ArgList&);
38
FunctionPrototype(ExecState * exec,PassRefPtr<Structure> structure)39 FunctionPrototype::FunctionPrototype(ExecState* exec, PassRefPtr<Structure> structure)
40 : InternalFunction(&exec->globalData(), structure, exec->propertyNames().nullIdentifier)
41 {
42 putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 0), DontDelete | ReadOnly | DontEnum);
43 }
44
addFunctionProperties(ExecState * exec,Structure * prototypeFunctionStructure)45 void FunctionPrototype::addFunctionProperties(ExecState* exec, Structure* prototypeFunctionStructure)
46 {
47 putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 0, exec->propertyNames().toString, functionProtoFuncToString), DontEnum);
48 putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 2, exec->propertyNames().apply, functionProtoFuncApply), DontEnum);
49 putDirectFunctionWithoutTransition(exec, new (exec) PrototypeFunction(exec, prototypeFunctionStructure, 1, exec->propertyNames().call, functionProtoFuncCall), DontEnum);
50 }
51
callFunctionPrototype(ExecState *,JSObject *,JSValuePtr,const ArgList &)52 static JSValuePtr callFunctionPrototype(ExecState*, JSObject*, JSValuePtr, const ArgList&)
53 {
54 return jsUndefined();
55 }
56
57 // ECMA 15.3.4
getCallData(CallData & callData)58 CallType FunctionPrototype::getCallData(CallData& callData)
59 {
60 callData.native.function = callFunctionPrototype;
61 return CallTypeHost;
62 }
63
64 // Functions
65
functionProtoFuncToString(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList &)66 JSValuePtr functionProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
67 {
68 if (thisValue.isObject(&JSFunction::info)) {
69 JSFunction* function = asFunction(thisValue);
70 return jsString(exec, "function " + function->name(&exec->globalData()) + "(" + function->body()->paramString() + ") " + function->body()->toSourceString());
71 }
72
73 if (thisValue.isObject(&InternalFunction::info)) {
74 InternalFunction* function = asInternalFunction(thisValue);
75 return jsString(exec, "function " + function->name(&exec->globalData()) + "() {\n [native code]\n}");
76 }
77
78 return throwError(exec, TypeError);
79 }
80
functionProtoFuncApply(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList & args)81 JSValuePtr functionProtoFuncApply(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
82 {
83 CallData callData;
84 CallType callType = thisValue.getCallData(callData);
85 if (callType == CallTypeNone)
86 return throwError(exec, TypeError);
87
88 JSValuePtr thisArg = args.at(exec, 0);
89 JSValuePtr argArray = args.at(exec, 1);
90
91 JSValuePtr applyThis;
92 if (thisArg.isUndefinedOrNull())
93 applyThis = exec->globalThisValue();
94 else
95 applyThis = thisArg.toObject(exec);
96
97 ArgList applyArgs;
98 if (!argArray.isUndefinedOrNull()) {
99 if (!argArray.isObject())
100 return throwError(exec, TypeError);
101 if (asObject(argArray)->classInfo() == &Arguments::info)
102 asArguments(argArray)->fillArgList(exec, applyArgs);
103 else if (exec->interpreter()->isJSArray(argArray))
104 asArray(argArray)->fillArgList(exec, applyArgs);
105 else if (asObject(argArray)->inherits(&JSArray::info)) {
106 unsigned length = asArray(argArray)->get(exec, exec->propertyNames().length).toUInt32(exec);
107 for (unsigned i = 0; i < length; ++i)
108 applyArgs.append(asArray(argArray)->get(exec, i));
109 } else
110 return throwError(exec, TypeError);
111 }
112
113 return call(exec, thisValue, callType, callData, applyThis, applyArgs);
114 }
115
functionProtoFuncCall(ExecState * exec,JSObject *,JSValuePtr thisValue,const ArgList & args)116 JSValuePtr functionProtoFuncCall(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
117 {
118 CallData callData;
119 CallType callType = thisValue.getCallData(callData);
120 if (callType == CallTypeNone)
121 return throwError(exec, TypeError);
122
123 JSValuePtr thisArg = args.at(exec, 0);
124
125 JSObject* callThis;
126 if (thisArg.isUndefinedOrNull())
127 callThis = exec->globalThisValue();
128 else
129 callThis = thisArg.toObject(exec);
130
131 ArgList argsTail;
132 args.getSlice(1, argsTail);
133 return call(exec, thisValue, callType, callData, callThis, argsTail);
134 }
135
136 } // namespace JSC
137