26
26
#include "JSFunction.h"
27
27
#include "JSString.h"
28
28
#include "Interpreter.h"
29
30
#include "PrototypeFunction.h"
33
34
ASSERT_CLASS_FITS_IN_CELL(FunctionPrototype);
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&);
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&);
39
FunctionPrototype::FunctionPrototype(ExecState* exec, PassRefPtr<Structure> structure)
40
FunctionPrototype::FunctionPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure)
40
41
: InternalFunction(&exec->globalData(), structure, exec->propertyNames().nullIdentifier)
42
43
putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 0), DontDelete | ReadOnly | DontEnum);
45
void FunctionPrototype::addFunctionProperties(ExecState* exec, Structure* prototypeFunctionStructure)
46
void FunctionPrototype::addFunctionProperties(ExecState* exec, Structure* prototypeFunctionStructure, NativeFunctionWrapper** callFunction, NativeFunctionWrapper** applyFunction)
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);
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);
52
static JSValuePtr callFunctionPrototype(ExecState*, JSObject*, JSValuePtr, const ArgList&)
55
static JSValue JSC_HOST_CALL callFunctionPrototype(ExecState*, JSObject*, JSValue, const ArgList&)
54
57
return jsUndefined();
66
JSValuePtr functionProtoFuncToString(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList&)
68
if (thisValue->isObject(&JSFunction::info)) {
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 = 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)) {
69
88
JSFunction* function = asFunction(thisValue);
70
return jsString(exec, "function " + function->name(&exec->globalData()) + "(" + function->body()->paramString() + ") " + function->body()->toSourceString());
89
if (!function->isHostFunction()) {
90
FunctionExecutable* executable = function->jsExecutable();
91
UString sourceString = executable->source().toString();
92
insertSemicolonIfNeeded(sourceString);
93
return jsString(exec, "function " + function->name(&exec->globalData()) + "(" + executable->paramString() + ") " + sourceString);
73
if (thisValue->isObject(&InternalFunction::info)) {
97
if (thisValue.inherits(&InternalFunction::info)) {
74
98
InternalFunction* function = asInternalFunction(thisValue);
75
99
return jsString(exec, "function " + function->name(&exec->globalData()) + "() {\n [native code]\n}");
78
102
return throwError(exec, TypeError);
81
JSValuePtr functionProtoFuncApply(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
105
JSValue JSC_HOST_CALL functionProtoFuncApply(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
83
107
CallData callData;
84
CallType callType = thisValue->getCallData(callData);
108
CallType callType = thisValue.getCallData(callData);
85
109
if (callType == CallTypeNone)
86
110
return throwError(exec, TypeError);
88
JSValuePtr thisArg = args.at(exec, 0);
89
JSValuePtr argArray = args.at(exec, 1);
92
if (thisArg->isUndefinedOrNull())
93
applyThis = exec->globalThisValue();
95
applyThis = thisArg->toObject(exec);
98
if (!argArray->isUndefinedOrNull()) {
99
if (!argArray->isObject())
112
JSValue array = args.at(1);
114
MarkedArgumentBuffer applyArgs;
115
if (!array.isUndefinedOrNull()) {
116
if (!array.isObject())
100
117
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);
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);
107
124
for (unsigned i = 0; i < length; ++i)
108
applyArgs.append(asArray(argArray)->get(exec, i));
125
applyArgs.append(asArray(array)->get(exec, i));
110
127
return throwError(exec, TypeError);
113
return call(exec, thisValue, callType, callData, applyThis, applyArgs);
130
return call(exec, thisValue, callType, callData, args.at(0), applyArgs);
116
JSValuePtr functionProtoFuncCall(ExecState* exec, JSObject*, JSValuePtr thisValue, const ArgList& args)
133
JSValue JSC_HOST_CALL functionProtoFuncCall(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args)
118
135
CallData callData;
119
CallType callType = thisValue->getCallData(callData);
136
CallType callType = thisValue.getCallData(callData);
120
137
if (callType == CallTypeNone)
121
138
return throwError(exec, TypeError);
123
JSValuePtr thisArg = args.at(exec, 0);
126
if (thisArg->isUndefinedOrNull())
127
callThis = exec->globalThisValue();
129
callThis = thisArg->toObject(exec);
132
args.getSlice(1, argsTail);
133
return call(exec, thisValue, callType, callData, callThis, argsTail);
141
args.getSlice(1, callArgs);
142
return call(exec, thisValue, callType, callData, args.at(0), callArgs);
136
145
} // namespace JSC