2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
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.
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.
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
22 #include "FunctionPrototype.h"
24 #include "Arguments.h"
26 #include "JSFunction.h"
28 #include "Interpreter.h"
30 #include "PrototypeFunction.h"
34 ASSERT_CLASS_FITS_IN_CELL(FunctionPrototype
);
36 static JSValue JSC_HOST_CALL
functionProtoFuncToString(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
37 static JSValue JSC_HOST_CALL
functionProtoFuncApply(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
38 static JSValue JSC_HOST_CALL
functionProtoFuncCall(ExecState
*, JSObject
*, JSValue
, const ArgList
&);
40 FunctionPrototype::FunctionPrototype(ExecState
* exec
, NonNullPassRefPtr
<Structure
> structure
)
41 : InternalFunction(&exec
->globalData(), structure
, exec
->propertyNames().nullIdentifier
)
43 putDirectWithoutTransition(exec
->propertyNames().length
, jsNumber(exec
, 0), DontDelete
| ReadOnly
| DontEnum
);
46 void FunctionPrototype::addFunctionProperties(ExecState
* exec
, Structure
* prototypeFunctionStructure
, NativeFunctionWrapper
** callFunction
, NativeFunctionWrapper
** applyFunction
)
48 putDirectFunctionWithoutTransition(exec
, new (exec
) NativeFunctionWrapper(exec
, prototypeFunctionStructure
, 0, exec
->propertyNames().toString
, functionProtoFuncToString
), DontEnum
);
49 *applyFunction
= new (exec
) NativeFunctionWrapper(exec
, prototypeFunctionStructure
, 2, exec
->propertyNames().apply
, functionProtoFuncApply
);
50 putDirectFunctionWithoutTransition(exec
, *applyFunction
, DontEnum
);
51 *callFunction
= new (exec
) NativeFunctionWrapper(exec
, prototypeFunctionStructure
, 1, exec
->propertyNames().call
, functionProtoFuncCall
);
52 putDirectFunctionWithoutTransition(exec
, *callFunction
, DontEnum
);
55 static JSValue JSC_HOST_CALL
callFunctionPrototype(ExecState
*, JSObject
*, JSValue
, const ArgList
&)
61 CallType
FunctionPrototype::getCallData(CallData
& callData
)
63 callData
.native
.function
= callFunctionPrototype
;
69 // Compatibility hack for the Optimost JavaScript library. (See <rdar://problem/6595040>.)
70 static inline void insertSemicolonIfNeeded(UString
& functionBody
)
72 ASSERT(functionBody
[0] == '{');
73 ASSERT(functionBody
[functionBody
.size() - 1] == '}');
75 for (size_t i
= functionBody
.size() - 2; i
> 0; --i
) {
76 UChar ch
= functionBody
[i
];
77 if (!Lexer::isWhiteSpace(ch
) && !Lexer::isLineTerminator(ch
)) {
78 if (ch
!= ';' && ch
!= '}')
79 functionBody
= makeString(functionBody
.substr(0, i
+ 1), ";", functionBody
.substr(i
+ 1, functionBody
.size() - (i
+ 1)));
85 JSValue JSC_HOST_CALL
functionProtoFuncToString(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
&)
87 if (thisValue
.inherits(&JSFunction::info
)) {
88 JSFunction
* function
= asFunction(thisValue
);
89 if (!function
->isHostFunction()) {
90 FunctionExecutable
* executable
= function
->jsExecutable();
91 UString sourceString
= executable
->source().toString();
92 insertSemicolonIfNeeded(sourceString
);
93 return jsString(exec
, makeString("function ", function
->name(exec
), "(", executable
->paramString(), ") ", sourceString
));
97 if (thisValue
.inherits(&InternalFunction::info
)) {
98 InternalFunction
* function
= asInternalFunction(thisValue
);
99 return jsString(exec
, makeString("function ", function
->name(exec
), "() {\n [native code]\n}"));
102 return throwError(exec
, TypeError
);
105 JSValue JSC_HOST_CALL
functionProtoFuncApply(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
& args
)
108 CallType callType
= thisValue
.getCallData(callData
);
109 if (callType
== CallTypeNone
)
110 return throwError(exec
, TypeError
);
112 JSValue array
= args
.at(1);
114 MarkedArgumentBuffer applyArgs
;
115 if (!array
.isUndefinedOrNull()) {
116 if (!array
.isObject())
117 return throwError(exec
, TypeError
);
118 if (asObject(array
)->classInfo() == &Arguments::info
)
119 asArguments(array
)->fillArgList(exec
, applyArgs
);
120 else if (isJSArray(&exec
->globalData(), array
))
121 asArray(array
)->fillArgList(exec
, applyArgs
);
122 else if (asObject(array
)->inherits(&JSArray::info
)) {
123 unsigned length
= asArray(array
)->get(exec
, exec
->propertyNames().length
).toUInt32(exec
);
124 for (unsigned i
= 0; i
< length
; ++i
)
125 applyArgs
.append(asArray(array
)->get(exec
, i
));
127 return throwError(exec
, TypeError
);
130 return call(exec
, thisValue
, callType
, callData
, args
.at(0), applyArgs
);
133 JSValue JSC_HOST_CALL
functionProtoFuncCall(ExecState
* exec
, JSObject
*, JSValue thisValue
, const ArgList
& args
)
136 CallType callType
= thisValue
.getCallData(callData
);
137 if (callType
== CallTypeNone
)
138 return throwError(exec
, TypeError
);
141 args
.getSlice(1, callArgs
);
142 return call(exec
, thisValue
, callType
, callData
, args
.at(0), callArgs
);