blob: 2f2e270b2107c0e8272acf9acae0292ac1769061 [file] [log] [blame]
gwt.team.knorton3bee6a42006-12-11 01:16:34 +00001/*
gwt.team.scottb5aa171d2007-04-11 21:11:15 +00002 * Copyright 2007 Google Inc.
gwt.team.knorton3bee6a42006-12-11 01:16:34 +00003 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
14 * the License.
15 */
gwt.team.scottbab0aa682006-12-06 23:14:19 +000016#include "FunctionObject.h"
17#include <kjs/array_object.h>
18
19using namespace KJS;
20
21const ClassInfo FunctionObject::info = {"Function", 0, 0, 0};
22
23class CallFunction : public FunctionObject {
24public:
gwt.team.scottb5aa171d2007-04-11 21:11:15 +000025 CallFunction(): FunctionObject("call") {
26 }
gwt.team.scottbab0aa682006-12-06 23:14:19 +000027
gwt.team.scottb5aa171d2007-04-11 21:11:15 +000028 virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj,
29 const List &args)
30 {
31 // Copied from FunctionProtoFunc::callAsFunction()
32 JSValue *thisArg = args[0];
33 JSObject *func = thisObj;
gwt.team.scottbab0aa682006-12-06 23:14:19 +000034
gwt.team.scottb5aa171d2007-04-11 21:11:15 +000035 if (!func->implementsCall()) {
36 return throwError(exec, TypeError);
37 }
gwt.team.scottbab0aa682006-12-06 23:14:19 +000038
gwt.team.scottb5aa171d2007-04-11 21:11:15 +000039 JSObject *callThis;
40 if (thisArg->isUndefinedOrNull()) {
41 callThis = exec->dynamicInterpreter()->globalObject();
42 } else {
43 callThis = thisArg->toObject(exec);
44 }
gwt.team.scottbab0aa682006-12-06 23:14:19 +000045
gwt.team.scottb5aa171d2007-04-11 21:11:15 +000046 return func->call(exec, callThis, args.copyTail());
47 }
gwt.team.scottbab0aa682006-12-06 23:14:19 +000048};
49
50class ApplyFunction : public FunctionObject {
51public:
gwt.team.scottb5aa171d2007-04-11 21:11:15 +000052 ApplyFunction(): FunctionObject("apply") {
53 }
gwt.team.scottbab0aa682006-12-06 23:14:19 +000054
gwt.team.scottb5aa171d2007-04-11 21:11:15 +000055 virtual JSValue *callAsFunction(ExecState *exec, JSObject *thisObj,
56 const List &args)
57 {
58 // Copied from FunctionProtoFunc::callAsFunction()
59 JSObject *func = thisObj;
60 if (!func->implementsCall()) {
61 return throwError(exec, TypeError);
62 }
gwt.team.scottbab0aa682006-12-06 23:14:19 +000063
gwt.team.scottb5aa171d2007-04-11 21:11:15 +000064 JSValue *thisArg = args[0];
65 JSObject *applyThis;
66 if (thisArg->isUndefinedOrNull()) {
67 applyThis = exec->dynamicInterpreter()->globalObject();
68 } else {
69 applyThis = thisArg->toObject(exec);
70 }
gwt.team.scottbab0aa682006-12-06 23:14:19 +000071
gwt.team.scottb5aa171d2007-04-11 21:11:15 +000072 JSValue *argArray = args[1];
73 List applyArgs;
74 if (!argArray->isUndefinedOrNull()) {
75 if (!argArray->isObject(&ArrayInstance::info)) {
76 return throwError(exec, TypeError);
77 }
gwt.team.scottbab0aa682006-12-06 23:14:19 +000078
gwt.team.scottb5aa171d2007-04-11 21:11:15 +000079 JSObject *argArrayObj = static_cast<JSObject *>(argArray);
80 unsigned int length = argArrayObj->get(exec, lengthPropertyName)
81 ->toUInt32(exec);
82 for (unsigned int i = 0; i < length; ++i) {
83 applyArgs.append(argArrayObj->get(exec,i));
84 }
85 }
86 return func->call(exec, applyThis, applyArgs);
87 }
gwt.team.scottbab0aa682006-12-06 23:14:19 +000088};
89
90
91static UString makeFunctionString(const UString& name) {
gwt.team.scottb5aa171d2007-04-11 21:11:15 +000092 return "\nfunction " + name + "() {\n [native code]\n}\n";
gwt.team.scottbab0aa682006-12-06 23:14:19 +000093}
94
gwt.team.scottb5aa171d2007-04-11 21:11:15 +000095JSValue *FunctionObject::getter(ExecState* exec, JSObject* obj,
96 const Identifier& propertyName, const PropertySlot& slot)
97{
98 if (propertyName.ustring() == "toString") {
99 return new ToStringFunction();
100 } else if (propertyName.ustring() == "call") {
101 return new CallFunction();
102 } else if (propertyName.ustring() == "apply") {
103 return new ApplyFunction();
104 }
105 return jsUndefined();
gwt.team.scottbab0aa682006-12-06 23:14:19 +0000106}
107
108FunctionObject::FunctionObject(const UString& name): name(name) {
109}
110
gwt.team.scottb5aa171d2007-04-11 21:11:15 +0000111bool FunctionObject::getOwnPropertySlot(ExecState *exec,
112 const Identifier& propertyName, PropertySlot& slot)
113{
114 if (propertyName.ustring() == "toString") {
115 slot.setCustom(this, getter);
116 return true;
117 }
118 if (propertyName.ustring() == "call") {
119 slot.setCustom(this, getter);
120 return true;
121 }
122 if (propertyName.ustring() == "apply") {
123 slot.setCustom(this, getter);
124 return true;
125 }
126 return false;
gwt.team.scottbab0aa682006-12-06 23:14:19 +0000127}
128
gwt.team.scottb5aa171d2007-04-11 21:11:15 +0000129bool FunctionObject::canPut(ExecState *exec, const Identifier &propertyName)
130 const
131{
132 return false;
gwt.team.scottbab0aa682006-12-06 23:14:19 +0000133}
134
gwt.team.scottb5aa171d2007-04-11 21:11:15 +0000135void FunctionObject::put(ExecState *exec, const Identifier &propertyName,
136 JSValue *value, int attr)
137{
gwt.team.scottbab0aa682006-12-06 23:14:19 +0000138}
139
gwt.team.scottb5aa171d2007-04-11 21:11:15 +0000140bool FunctionObject::deleteProperty(ExecState *exec,
141 const Identifier &propertyName)
142{
143 return false;
gwt.team.scottbab0aa682006-12-06 23:14:19 +0000144}
145
146JSValue *FunctionObject::defaultValue(ExecState *exec, JSType hint) const {
gwt.team.scottb5aa171d2007-04-11 21:11:15 +0000147 return jsString(makeFunctionString(name));
gwt.team.scottbab0aa682006-12-06 23:14:19 +0000148}
149
150bool FunctionObject::implementsCall() const {
gwt.team.scottb5aa171d2007-04-11 21:11:15 +0000151 return true;
gwt.team.scottbab0aa682006-12-06 23:14:19 +0000152}
153
154// ToStringFunction
gwt.team.scottbab0aa682006-12-06 23:14:19 +0000155ToStringFunction::ToStringFunction(): FunctionObject("toString") {
156}
157
gwt.team.scottb5aa171d2007-04-11 21:11:15 +0000158JSValue *ToStringFunction::callAsFunction(ExecState *exec, JSObject *thisObj,
159 const List &args)
160{
161 if (!thisObj) {
162 return throwError(exec, TypeError);
163 }
164 return jsString(thisObj->toString(exec));
gwt.team.scottbab0aa682006-12-06 23:14:19 +0000165}