blob: 0a98e7c1356b1a4a96088a4624c4e0016b10bd46 [file] [log] [blame]
kocienda66a6d362001-08-24 14:24:45 +00001/*
darin74f6ed62002-07-22 05:38:39 +00002 * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
mjs6f821c82002-03-22 00:31:57 +00003 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
oliver@apple.com5fca29f2009-08-11 04:35:02 +00004 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
darin5769f312007-07-18 02:25:38 +00005 * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
ggaren6c0384f2007-10-29 05:32:23 +00006 * Copyright (C) 2007 Maks Orlovich
kocienda66a6d362001-08-24 14:24:45 +00007 *
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
mjscdff33b2006-01-23 21:41:36 +000020 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
ggaren07d4ce62005-07-14 18:27:04 +000021 * Boston, MA 02110-1301, USA.
mjs6f821c82002-03-22 00:31:57 +000022 *
kocienda66a6d362001-08-24 14:24:45 +000023 */
24
mjsb64c50a2005-10-03 21:13:12 +000025#include "config.h"
darin@apple.com3dcb6362008-06-16 04:00:19 +000026#include "JSFunction.h"
kocienda66a6d362001-08-24 14:24:45 +000027
barraclough@apple.com3a4eb9b2008-10-18 02:51:52 +000028#include "CodeBlock.h"
ggaren@apple.comfea43532008-08-17 20:23:49 +000029#include "CommonIdentifiers.h"
ggaren@apple.com5169fc92008-11-17 22:11:26 +000030#include "CallFrame.h"
barraclough@apple.comfd8c28a2010-05-25 03:04:43 +000031#include "ExceptionHelpers.h"
weinig@apple.com2ce2a7f2008-06-28 21:22:01 +000032#include "FunctionPrototype.h"
barraclough@apple.com81aa89f2012-02-06 08:56:02 +000033#include "GetterSetter.h"
barraclough@apple.com22215662011-09-22 21:22:17 +000034#include "JSArray.h"
ggaren@apple.com8e93f052007-11-26 23:48:14 +000035#include "JSGlobalObject.h"
ggaren@apple.comfea29f12010-05-29 06:33:05 +000036#include "JSNotAnObject.h"
ggaren@apple.com901a8a22008-11-17 20:57:18 +000037#include "Interpreter.h"
weinig@apple.com2ce2a7f2008-06-28 21:22:01 +000038#include "ObjectPrototype.h"
ggaren@apple.com979382c2007-12-08 00:01:13 +000039#include "Parser.h"
ggaren@apple.com8e93f052007-11-26 23:48:14 +000040#include "PropertyNameArray.h"
darinbceb27f2004-08-12 17:21:29 +000041
darinf9e5d6c2007-01-09 14:54:26 +000042using namespace WTF;
43using namespace Unicode;
44
cwzwarich@webkit.org3f782f62008-09-08 01:28:33 +000045namespace JSC {
barraclough@apple.com99ff3432010-06-03 20:00:18 +000046EncodedJSValue JSC_HOST_CALL callHostFunctionAsConstructor(ExecState* exec)
barraclough@apple.comfd8c28a2010-05-25 03:04:43 +000047{
barraclough@apple.come979a652010-11-16 01:30:25 +000048 return throwVMError(exec, createNotAConstructorError(exec, exec->callee()));
barraclough@apple.comfd8c28a2010-05-25 03:04:43 +000049}
50
mhahnenberg@apple.com3e084662011-09-26 07:05:28 +000051const ClassInfo JSFunction::s_info = { "Function", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSFunction) };
kocienda66a6d362001-08-24 14:24:45 +000052
darin@apple.comcbc86172009-08-13 21:51:50 +000053bool JSFunction::isHostFunctionNonInline() const
54{
55 return isHostFunction();
56}
57
benjamin@webkit.orgcff06e42012-08-30 21:23:51 +000058JSFunction* JSFunction::create(ExecState* exec, JSGlobalObject* globalObject, int length, const String& name, NativeFunction nativeFunction, Intrinsic intrinsic, NativeFunction nativeConstructor)
barraclough@apple.com22215662011-09-22 21:22:17 +000059{
barraclough@apple.com077fdd42012-03-18 01:08:16 +000060 NativeExecutable* executable;
psolanki@apple.com8c31b972012-03-27 18:06:21 +000061#if !ENABLE(JIT)
62 UNUSED_PARAM(intrinsic);
63#else
barraclough@apple.com077fdd42012-03-18 01:08:16 +000064 if (intrinsic != NoIntrinsic && exec->globalData().canUseJIT()) {
65 ASSERT(nativeConstructor == callHostFunctionAsConstructor);
66 executable = exec->globalData().getHostFunction(nativeFunction, intrinsic);
67 } else
68#endif
69 executable = exec->globalData().getHostFunction(nativeFunction, nativeConstructor);
70
ggaren@apple.com215589e2011-12-19 17:45:13 +000071 JSFunction* function = new (NotNull, allocateCell<JSFunction>(*exec->heap())) JSFunction(exec, globalObject, globalObject->functionStructure());
barraclough@apple.com22215662011-09-22 21:22:17 +000072 // Can't do this during initialization because getHostFunction might do a GC allocation.
73 function->finishCreation(exec, executable, length, name);
74 return function;
75}
76
fpizlo@apple.com243788c2012-11-13 19:58:18 +000077void JSFunction::destroy(JSCell* cell)
78{
79 static_cast<JSFunction*>(cell)->JSFunction::~JSFunction();
80}
81
commit-queue@webkit.org6e5671b2011-09-01 23:49:23 +000082JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, Structure* structure)
oliver@apple.com2346a3e2011-09-07 19:40:41 +000083 : Base(exec->globalData(), structure)
commit-queue@webkit.org53aecd22011-08-19 00:58:34 +000084 , m_executable()
ggaren@apple.comb11e7872012-08-30 22:50:00 +000085 , m_scope(exec->globalData(), this, globalObject)
fpizlo@apple.comf5db15e2012-11-14 07:22:57 +000086 // We initialize blind so that changes to the prototype after function creation but before
87 // the optimizer kicks in don't disable optimizations. Once the optimizer kicks in, the
88 // watchpoint will start watching and any changes will both force deoptimization and disable
89 // future attempts to optimize. This is necessary because we are guaranteed that the
90 // inheritorID is changed exactly once prior to optimizations kicking in. We could be
91 // smarter and count the number of times the prototype is clobbered and only optimize if it
92 // was clobbered exactly once, but that seems like overkill. In almost all cases it will be
93 // clobbered once, and if it's clobbered more than once, that will probably only occur
94 // before we started optimizing, anyway.
95 , m_inheritorIDWatchpoint(InitializedBlind)
oliver@apple.com8e293b72010-04-27 04:22:46 +000096{
oliver@apple.come79807b2009-05-05 11:34:23 +000097}
98
benjamin@webkit.orgcff06e42012-08-30 21:23:51 +000099void JSFunction::finishCreation(ExecState* exec, NativeExecutable* executable, int length, const String& name)
commit-queue@webkit.org53aecd22011-08-19 00:58:34 +0000100{
oliver@apple.com2346a3e2011-09-07 19:40:41 +0000101 Base::finishCreation(exec->globalData());
commit-queue@webkit.org53aecd22011-08-19 00:58:34 +0000102 ASSERT(inherits(&s_info));
103 m_executable.set(exec->globalData(), this, executable);
benjamin@webkit.org762e2c62012-09-04 21:19:25 +0000104 putDirect(exec->globalData(), exec->globalData().propertyNames->name, jsString(exec, name), DontDelete | ReadOnly | DontEnum);
commit-queue@webkit.org53aecd22011-08-19 00:58:34 +0000105 putDirect(exec->globalData(), exec->propertyNames().length, jsNumber(length), DontDelete | ReadOnly | DontEnum);
106}
107
barraclough@apple.comcef11dc2012-05-10 18:40:29 +0000108Structure* JSFunction::cacheInheritorID(ExecState* exec)
109{
110 JSValue prototype = get(exec, exec->globalData().propertyNames->prototype);
111 if (prototype.isObject())
112 m_cachedInheritorID.set(exec->globalData(), this, asObject(prototype)->inheritorID(exec->globalData()));
113 else
114 m_cachedInheritorID.set(exec->globalData(), this, globalObject()->emptyObjectStructure());
115 return m_cachedInheritorID.get();
116}
117
ggaren@apple.com0030e132012-09-12 06:14:56 +0000118String JSFunction::name(ExecState* exec)
barraclough@apple.com4be541c2010-05-20 02:38:01 +0000119{
ggaren@apple.com0030e132012-09-12 06:14:56 +0000120 return get(exec, exec->globalData().propertyNames->name).toWTFString(exec);
barraclough@apple.com4be541c2010-05-20 02:38:01 +0000121}
122
ggaren@apple.com0030e132012-09-12 06:14:56 +0000123String JSFunction::displayName(ExecState* exec)
barraclough@apple.com4be541c2010-05-20 02:38:01 +0000124{
oliver@apple.comaf134a72011-04-13 18:48:22 +0000125 JSValue displayName = getDirect(exec->globalData(), exec->globalData().propertyNames->displayName);
barraclough@apple.com4be541c2010-05-20 02:38:01 +0000126
mhahnenberg@apple.comc58d54d2011-12-16 19:06:44 +0000127 if (displayName && isJSString(displayName))
barraclough@apple.com550b0d82010-05-21 23:49:48 +0000128 return asString(displayName)->tryGetValue();
barraclough@apple.com4be541c2010-05-20 02:38:01 +0000129
benjamin@webkit.orgcff06e42012-08-30 21:23:51 +0000130 return String();
barraclough@apple.com4be541c2010-05-20 02:38:01 +0000131}
132
benjamin@webkit.orgcff06e42012-08-30 21:23:51 +0000133const String JSFunction::calculatedDisplayName(ExecState* exec)
barraclough@apple.com4be541c2010-05-20 02:38:01 +0000134{
benjamin@webkit.orgcff06e42012-08-30 21:23:51 +0000135 const String explicitName = displayName(exec);
barraclough@apple.com4be541c2010-05-20 02:38:01 +0000136
137 if (!explicitName.isEmpty())
138 return explicitName;
139
benjamin@webkit.orgcff06e42012-08-30 21:23:51 +0000140 const String actualName = name(exec);
oliver@apple.comf7190bf2012-02-01 23:23:30 +0000141 if (!actualName.isEmpty() || isHostFunction())
142 return actualName;
143
benjamin@webkit.orgc9b7a202012-09-08 05:46:29 +0000144 return jsExecutable()->inferredName().string();
barraclough@apple.com4be541c2010-05-20 02:38:01 +0000145}
146
yurys@chromium.org0114f052011-11-14 09:27:25 +0000147const SourceCode* JSFunction::sourceCode() const
148{
149 if (isHostFunction())
150 return 0;
151 return &jsExecutable()->source();
152}
153
mhahnenberg@apple.com982c9ea2011-09-23 19:40:09 +0000154void JSFunction::visitChildren(JSCell* cell, SlotVisitor& visitor)
155{
mhahnenberg@apple.com135f0512011-11-11 20:40:10 +0000156 JSFunction* thisObject = jsCast<JSFunction*>(cell);
mhahnenberg@apple.com982c9ea2011-09-23 19:40:09 +0000157 ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
158 COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
159 ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
160 Base::visitChildren(thisObject, visitor);
161
ggaren@apple.comb11e7872012-08-30 22:50:00 +0000162 visitor.append(&thisObject->m_scope);
ggaren@apple.comacb40df2012-08-27 03:57:02 +0000163 visitor.append(&thisObject->m_executable);
mjs308be5a2006-08-14 03:06:14 +0000164}
165
mhahnenberg@apple.com2413eb82011-09-27 22:46:51 +0000166CallType JSFunction::getCallData(JSCell* cell, CallData& callData)
167{
mhahnenberg@apple.com135f0512011-11-11 20:40:10 +0000168 JSFunction* thisObject = jsCast<JSFunction*>(cell);
mhahnenberg@apple.com2413eb82011-09-27 22:46:51 +0000169 if (thisObject->isHostFunction()) {
170 callData.native.function = thisObject->nativeFunction();
oliver@apple.come79807b2009-05-05 11:34:23 +0000171 return CallTypeHost;
172 }
mhahnenberg@apple.com2413eb82011-09-27 22:46:51 +0000173 callData.js.functionExecutable = thisObject->jsExecutable();
ggaren@apple.comb11e7872012-08-30 22:50:00 +0000174 callData.js.scope = thisObject->scope();
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000175 return CallTypeJS;
176}
177
barraclough@apple.com38d3c752012-05-12 00:39:43 +0000178JSValue JSFunction::argumentsGetter(ExecState* exec, JSValue slotBase, PropertyName)
mjs70d74212005-08-07 06:17:49 +0000179{
barraclough@apple.com484a9d32012-03-22 18:54:50 +0000180 JSFunction* thisObj = jsCast<JSFunction*>(slotBase);
oliver@apple.come79807b2009-05-05 11:34:23 +0000181 ASSERT(!thisObj->isHostFunction());
fpizlo@apple.come8a38be2012-01-27 01:15:16 +0000182 return exec->interpreter()->retrieveArgumentsFromVMCode(exec, thisObj);
mjs70d74212005-08-07 06:17:49 +0000183}
184
barraclough@apple.com38d3c752012-05-12 00:39:43 +0000185JSValue JSFunction::callerGetter(ExecState* exec, JSValue slotBase, PropertyName)
mjs70d74212005-08-07 06:17:49 +0000186{
barraclough@apple.com484a9d32012-03-22 18:54:50 +0000187 JSFunction* thisObj = jsCast<JSFunction*>(slotBase);
oliver@apple.come79807b2009-05-05 11:34:23 +0000188 ASSERT(!thisObj->isHostFunction());
barraclough@apple.com4f1d0a52012-03-02 00:12:58 +0000189 JSValue caller = exec->interpreter()->retrieveCallerFromVMCode(exec, thisObj);
190
191 // See ES5.1 15.3.5.4 - Function.caller may not be used to retrieve a strict caller.
192 if (!caller.isObject() || !asObject(caller)->inherits(&JSFunction::s_info))
193 return caller;
barraclough@apple.com484a9d32012-03-22 18:54:50 +0000194 JSFunction* function = jsCast<JSFunction*>(caller);
barraclough@apple.com4f1d0a52012-03-02 00:12:58 +0000195 if (function->isHostFunction() || !function->jsExecutable()->isStrictMode())
196 return caller;
benjamin@webkit.org762e2c62012-09-04 21:19:25 +0000197 return throwTypeError(exec, ASCIILiteral("Function.caller used to retrieve strict caller"));
ap3d619142006-10-31 18:16:08 +0000198}
199
barraclough@apple.com38d3c752012-05-12 00:39:43 +0000200JSValue JSFunction::lengthGetter(ExecState*, JSValue slotBase, PropertyName)
ap3d619142006-10-31 18:16:08 +0000201{
barraclough@apple.com484a9d32012-03-22 18:54:50 +0000202 JSFunction* thisObj = jsCast<JSFunction*>(slotBase);
oliver@apple.come79807b2009-05-05 11:34:23 +0000203 ASSERT(!thisObj->isHostFunction());
oliver@apple.com5b67d9e2010-10-25 22:40:53 +0000204 return jsNumber(thisObj->jsExecutable()->parameterCount());
mjs70d74212005-08-07 06:17:49 +0000205}
206
ggaren@apple.com0030e132012-09-12 06:14:56 +0000207JSValue JSFunction::nameGetter(ExecState*, JSValue slotBase, PropertyName)
208{
209 JSFunction* thisObj = jsCast<JSFunction*>(slotBase);
210 ASSERT(!thisObj->isHostFunction());
211 return thisObj->jsExecutable()->nameValue();
212}
213
barraclough@apple.com38d3c752012-05-12 00:39:43 +0000214bool JSFunction::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
mhahnenberg@apple.com19869642011-10-08 21:31:32 +0000215{
mhahnenberg@apple.com135f0512011-11-11 20:40:10 +0000216 JSFunction* thisObject = jsCast<JSFunction*>(cell);
mhahnenberg@apple.com19869642011-10-08 21:31:32 +0000217 if (thisObject->isHostFunction())
218 return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
oliver@apple.come79807b2009-05-05 11:34:23 +0000219
cwzwarich@webkit.orgde65b9e2008-10-24 20:44:58 +0000220 if (propertyName == exec->propertyNames().prototype) {
mhahnenberg@apple.com19869642011-10-08 21:31:32 +0000221 WriteBarrierBase<Unknown>* location = thisObject->getDirectLocation(exec->globalData(), propertyName);
cwzwarich@webkit.orgde65b9e2008-10-24 20:44:58 +0000222
barraclough@apple.com00d4c0e2011-09-15 18:47:20 +0000223 if (!location) {
mhahnenberg@apple.com19869642011-10-08 21:31:32 +0000224 JSObject* prototype = constructEmptyObject(exec, thisObject->globalObject()->emptyObjectStructure());
225 prototype->putDirect(exec->globalData(), exec->propertyNames().constructor, thisObject, DontEnum);
barraclough@apple.com4cc95512012-01-13 01:40:22 +0000226 thisObject->putDirect(exec->globalData(), exec->propertyNames().prototype, prototype, DontDelete | DontEnum);
mhahnenberg@apple.com19869642011-10-08 21:31:32 +0000227 location = thisObject->getDirectLocation(exec->globalData(), exec->propertyNames().prototype);
barraclough@apple.com00d4c0e2011-09-15 18:47:20 +0000228 }
cwzwarich@webkit.orgde65b9e2008-10-24 20:44:58 +0000229
mhahnenberg@apple.com19869642011-10-08 21:31:32 +0000230 slot.setValue(thisObject, location->get(), thisObject->offsetForLocation(location));
cwzwarich@webkit.orgde65b9e2008-10-24 20:44:58 +0000231 }
232
mjs23fc88d2007-03-19 05:43:47 +0000233 if (propertyName == exec->propertyNames().arguments) {
mhahnenberg@apple.com19869642011-10-08 21:31:32 +0000234 if (thisObject->jsExecutable()->isStrictMode()) {
barraclough@apple.com69e904a2011-10-20 01:18:03 +0000235 bool result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
236 if (!result) {
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +0000237 thisObject->putDirectAccessor(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor);
barraclough@apple.com69e904a2011-10-20 01:18:03 +0000238 result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
239 ASSERT(result);
240 }
241 return result;
oliver@apple.com59301852010-10-11 19:12:29 +0000242 }
mhahnenberg@apple.com19869642011-10-08 21:31:32 +0000243 slot.setCacheableCustom(thisObject, argumentsGetter);
mjs234d8b12005-07-25 22:17:20 +0000244 return true;
darin0210a252002-11-20 09:11:43 +0000245 }
ap3d619142006-10-31 18:16:08 +0000246
mjs23fc88d2007-03-19 05:43:47 +0000247 if (propertyName == exec->propertyNames().length) {
mhahnenberg@apple.com19869642011-10-08 21:31:32 +0000248 slot.setCacheableCustom(thisObject, lengthGetter);
mjs234d8b12005-07-25 22:17:20 +0000249 return true;
darin0210a252002-11-20 09:11:43 +0000250 }
ap3d619142006-10-31 18:16:08 +0000251
ggaren@apple.com0030e132012-09-12 06:14:56 +0000252 if (propertyName == exec->propertyNames().name) {
253 slot.setCacheableCustom(thisObject, nameGetter);
254 return true;
255 }
256
mjs23fc88d2007-03-19 05:43:47 +0000257 if (propertyName == exec->propertyNames().caller) {
mhahnenberg@apple.com19869642011-10-08 21:31:32 +0000258 if (thisObject->jsExecutable()->isStrictMode()) {
barraclough@apple.com69e904a2011-10-20 01:18:03 +0000259 bool result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
260 if (!result) {
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +0000261 thisObject->putDirectAccessor(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor);
barraclough@apple.com69e904a2011-10-20 01:18:03 +0000262 result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
263 ASSERT(result);
264 }
265 return result;
oliver@apple.com59301852010-10-11 19:12:29 +0000266 }
mhahnenberg@apple.com19869642011-10-08 21:31:32 +0000267 slot.setCacheableCustom(thisObject, callerGetter);
ap3d619142006-10-31 18:16:08 +0000268 return true;
269 }
270
mhahnenberg@apple.com19869642011-10-08 21:31:32 +0000271 return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
darin0210a252002-11-20 09:11:43 +0000272}
273
barraclough@apple.com38d3c752012-05-12 00:39:43 +0000274bool JSFunction::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor)
oliver@apple.com59301852010-10-11 19:12:29 +0000275{
mhahnenberg@apple.com135f0512011-11-11 20:40:10 +0000276 JSFunction* thisObject = jsCast<JSFunction*>(object);
mhahnenberg@apple.com7f2f7e52011-11-09 21:09:37 +0000277 if (thisObject->isHostFunction())
278 return Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
oliver@apple.com59301852010-10-11 19:12:29 +0000279
280 if (propertyName == exec->propertyNames().prototype) {
281 PropertySlot slot;
mhahnenberg@apple.com7f2f7e52011-11-09 21:09:37 +0000282 thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, propertyName, slot);
283 return Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
oliver@apple.com4b4f7852009-08-26 16:52:15 +0000284 }
285
oliver@apple.com59301852010-10-11 19:12:29 +0000286 if (propertyName == exec->propertyNames().arguments) {
mhahnenberg@apple.com7f2f7e52011-11-09 21:09:37 +0000287 if (thisObject->jsExecutable()->isStrictMode()) {
288 bool result = Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
barraclough@apple.com69e904a2011-10-20 01:18:03 +0000289 if (!result) {
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +0000290 thisObject->putDirectAccessor(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor);
mhahnenberg@apple.com7f2f7e52011-11-09 21:09:37 +0000291 result = Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
barraclough@apple.com69e904a2011-10-20 01:18:03 +0000292 ASSERT(result);
293 }
294 return result;
295 }
fpizlo@apple.come8a38be2012-01-27 01:15:16 +0000296 descriptor.setDescriptor(exec->interpreter()->retrieveArgumentsFromVMCode(exec, thisObject), ReadOnly | DontEnum | DontDelete);
oliver@apple.com59301852010-10-11 19:12:29 +0000297 return true;
298 }
299
300 if (propertyName == exec->propertyNames().length) {
mhahnenberg@apple.com7f2f7e52011-11-09 21:09:37 +0000301 descriptor.setDescriptor(jsNumber(thisObject->jsExecutable()->parameterCount()), ReadOnly | DontEnum | DontDelete);
oliver@apple.com59301852010-10-11 19:12:29 +0000302 return true;
303 }
304
ggaren@apple.com0030e132012-09-12 06:14:56 +0000305 if (propertyName == exec->propertyNames().name) {
306 descriptor.setDescriptor(thisObject->jsExecutable()->nameValue(), ReadOnly | DontEnum | DontDelete);
307 return true;
308 }
309
oliver@apple.com59301852010-10-11 19:12:29 +0000310 if (propertyName == exec->propertyNames().caller) {
mhahnenberg@apple.com7f2f7e52011-11-09 21:09:37 +0000311 if (thisObject->jsExecutable()->isStrictMode()) {
312 bool result = Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
barraclough@apple.com69e904a2011-10-20 01:18:03 +0000313 if (!result) {
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +0000314 thisObject->putDirectAccessor(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor);
mhahnenberg@apple.com7f2f7e52011-11-09 21:09:37 +0000315 result = Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
barraclough@apple.com69e904a2011-10-20 01:18:03 +0000316 ASSERT(result);
317 }
318 return result;
319 }
fpizlo@apple.come8a38be2012-01-27 01:15:16 +0000320 descriptor.setDescriptor(exec->interpreter()->retrieveCallerFromVMCode(exec, thisObject), ReadOnly | DontEnum | DontDelete);
oliver@apple.com59301852010-10-11 19:12:29 +0000321 return true;
322 }
323
mhahnenberg@apple.com7f2f7e52011-11-09 21:09:37 +0000324 return Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
oliver@apple.com59301852010-10-11 19:12:29 +0000325}
326
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +0000327void JSFunction::getOwnNonIndexPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
eric@webkit.orgc293f4c2010-01-13 00:58:21 +0000328{
mhahnenberg@apple.com135f0512011-11-11 20:40:10 +0000329 JSFunction* thisObject = jsCast<JSFunction*>(object);
mhahnenberg@apple.com57262382011-11-03 00:25:45 +0000330 if (!thisObject->isHostFunction() && (mode == IncludeDontEnumProperties)) {
barraclough@apple.com74aa1c92010-11-16 06:05:38 +0000331 // Make sure prototype has been reified.
332 PropertySlot slot;
mhahnenberg@apple.com57262382011-11-03 00:25:45 +0000333 thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, exec->propertyNames().prototype, slot);
barraclough@apple.com74aa1c92010-11-16 06:05:38 +0000334
eric@webkit.orgc293f4c2010-01-13 00:58:21 +0000335 propertyNames.add(exec->propertyNames().arguments);
eric@webkit.orgc293f4c2010-01-13 00:58:21 +0000336 propertyNames.add(exec->propertyNames().caller);
337 propertyNames.add(exec->propertyNames().length);
ggaren@apple.com0030e132012-09-12 06:14:56 +0000338 propertyNames.add(exec->propertyNames().name);
eric@webkit.orgc293f4c2010-01-13 00:58:21 +0000339 }
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +0000340 Base::getOwnNonIndexPropertyNames(thisObject, exec, propertyNames, mode);
eric@webkit.orgc293f4c2010-01-13 00:58:21 +0000341}
342
barraclough@apple.com38d3c752012-05-12 00:39:43 +0000343void JSFunction::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
mhahnenberg@apple.com5e2b7122011-10-08 00:06:07 +0000344{
mhahnenberg@apple.com135f0512011-11-11 20:40:10 +0000345 JSFunction* thisObject = jsCast<JSFunction*>(cell);
mhahnenberg@apple.com5e2b7122011-10-08 00:06:07 +0000346 if (thisObject->isHostFunction()) {
347 Base::put(thisObject, exec, propertyName, value, slot);
oliver@apple.come79807b2009-05-05 11:34:23 +0000348 return;
349 }
barraclough@apple.com74aa1c92010-11-16 06:05:38 +0000350 if (propertyName == exec->propertyNames().prototype) {
351 // Make sure prototype has been reified, such that it can only be overwritten
352 // following the rules set out in ECMA-262 8.12.9.
353 PropertySlot slot;
mhahnenberg@apple.com5c103b02011-10-26 17:55:34 +0000354 thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, propertyName, slot);
barraclough@apple.comcef11dc2012-05-10 18:40:29 +0000355 thisObject->m_cachedInheritorID.clear();
fpizlo@apple.comf5db15e2012-11-14 07:22:57 +0000356 thisObject->m_inheritorIDWatchpoint.notifyWrite();
barraclough@apple.com266a5372012-05-15 03:43:54 +0000357 // Don't allow this to be cached, since a [[Put]] must clear m_cachedInheritorID.
358 PutPropertySlot dontCache;
359 Base::put(thisObject, exec, propertyName, value, dontCache);
360 return;
barraclough@apple.com74aa1c92010-11-16 06:05:38 +0000361 }
barraclough@apple.com69e904a2011-10-20 01:18:03 +0000362 if (thisObject->jsExecutable()->isStrictMode() && (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().caller)) {
363 // This will trigger the property to be reified, if this is not already the case!
364 bool okay = thisObject->hasProperty(exec, propertyName);
365 ASSERT_UNUSED(okay, okay);
366 Base::put(thisObject, exec, propertyName, value, slot);
367 return;
oliver@apple.com59301852010-10-11 19:12:29 +0000368 }
ggaren@apple.com0030e132012-09-12 06:14:56 +0000369 if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length || propertyName == exec->propertyNames().name || propertyName == exec->propertyNames().caller) {
barraclough@apple.comeb88e082012-03-06 20:20:04 +0000370 if (slot.isStrictMode())
371 throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
darin0210a252002-11-20 09:11:43 +0000372 return;
barraclough@apple.comeb88e082012-03-06 20:20:04 +0000373 }
mhahnenberg@apple.com5e2b7122011-10-08 00:06:07 +0000374 Base::put(thisObject, exec, propertyName, value, slot);
darin0210a252002-11-20 09:11:43 +0000375}
376
barraclough@apple.com38d3c752012-05-12 00:39:43 +0000377bool JSFunction::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
mhahnenberg@apple.com914c3ee2011-10-08 06:37:45 +0000378{
mhahnenberg@apple.com135f0512011-11-11 20:40:10 +0000379 JSFunction* thisObject = jsCast<JSFunction*>(cell);
barraclough@apple.com9ce855c2012-03-11 18:58:04 +0000380 // For non-host functions, don't let these properties by deleted - except by DefineOwnProperty.
381 if (!thisObject->isHostFunction() && !exec->globalData().isInDefineOwnProperty()
382 && (propertyName == exec->propertyNames().arguments
383 || propertyName == exec->propertyNames().length
ggaren@apple.com0030e132012-09-12 06:14:56 +0000384 || propertyName == exec->propertyNames().name
barraclough@apple.com9ce855c2012-03-11 18:58:04 +0000385 || propertyName == exec->propertyNames().prototype
386 || propertyName == exec->propertyNames().caller))
darin0210a252002-11-20 09:11:43 +0000387 return false;
mhahnenberg@apple.com914c3ee2011-10-08 06:37:45 +0000388 return Base::deleteProperty(thisObject, exec, propertyName);
darin0210a252002-11-20 09:11:43 +0000389}
390
barraclough@apple.com38d3c752012-05-12 00:39:43 +0000391bool JSFunction::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor, bool throwException)
barraclough@apple.comeb88e082012-03-06 20:20:04 +0000392{
393 JSFunction* thisObject = jsCast<JSFunction*>(object);
394 if (thisObject->isHostFunction())
395 return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
396
397 if (propertyName == exec->propertyNames().prototype) {
398 // Make sure prototype has been reified, such that it can only be overwritten
399 // following the rules set out in ECMA-262 8.12.9.
400 PropertySlot slot;
401 thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, propertyName, slot);
barraclough@apple.comcef11dc2012-05-10 18:40:29 +0000402 thisObject->m_cachedInheritorID.clear();
fpizlo@apple.comf5db15e2012-11-14 07:22:57 +0000403 thisObject->m_inheritorIDWatchpoint.notifyWrite();
barraclough@apple.com7ef41522012-03-19 21:34:25 +0000404 return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
405 }
406
407 bool valueCheck;
408 if (propertyName == exec->propertyNames().arguments) {
409 if (thisObject->jsExecutable()->isStrictMode()) {
410 if (!Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor))
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +0000411 thisObject->putDirectAccessor(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor);
barraclough@apple.com7ef41522012-03-19 21:34:25 +0000412 return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
barraclough@apple.com921cd1f2012-03-19 19:59:03 +0000413 }
barraclough@apple.com7ef41522012-03-19 21:34:25 +0000414 valueCheck = !descriptor.value() || sameValue(exec, descriptor.value(), exec->interpreter()->retrieveArgumentsFromVMCode(exec, thisObject));
415 } else if (propertyName == exec->propertyNames().caller) {
416 if (thisObject->jsExecutable()->isStrictMode()) {
417 if (!Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor))
fpizlo@apple.comd8dd0532012-09-13 04:18:52 +0000418 thisObject->putDirectAccessor(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor);
barraclough@apple.com7ef41522012-03-19 21:34:25 +0000419 return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
barraclough@apple.comeb88e082012-03-06 20:20:04 +0000420 }
barraclough@apple.com7ef41522012-03-19 21:34:25 +0000421 valueCheck = !descriptor.value() || sameValue(exec, descriptor.value(), exec->interpreter()->retrieveCallerFromVMCode(exec, thisObject));
422 } else if (propertyName == exec->propertyNames().length)
423 valueCheck = !descriptor.value() || sameValue(exec, descriptor.value(), jsNumber(thisObject->jsExecutable()->parameterCount()));
ggaren@apple.com0030e132012-09-12 06:14:56 +0000424 else if (propertyName == exec->propertyNames().name)
425 valueCheck = !descriptor.value() || sameValue(exec, descriptor.value(), thisObject->jsExecutable()->nameValue());
barraclough@apple.com7ef41522012-03-19 21:34:25 +0000426 else
427 return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
428
429 if (descriptor.configurablePresent() && descriptor.configurable()) {
430 if (throwException)
benjamin@webkit.org762e2c62012-09-04 21:19:25 +0000431 throwError(exec, createTypeError(exec, ASCIILiteral("Attempting to configurable attribute of unconfigurable property.")));
barraclough@apple.com7ef41522012-03-19 21:34:25 +0000432 return false;
433 }
434 if (descriptor.enumerablePresent() && descriptor.enumerable()) {
435 if (throwException)
benjamin@webkit.org762e2c62012-09-04 21:19:25 +0000436 throwError(exec, createTypeError(exec, ASCIILiteral("Attempting to change enumerable attribute of unconfigurable property.")));
barraclough@apple.com7ef41522012-03-19 21:34:25 +0000437 return false;
438 }
439 if (descriptor.isAccessorDescriptor()) {
440 if (throwException)
benjamin@webkit.org762e2c62012-09-04 21:19:25 +0000441 throwError(exec, createTypeError(exec, ASCIILiteral("Attempting to change access mechanism for an unconfigurable property.")));
barraclough@apple.com7ef41522012-03-19 21:34:25 +0000442 return false;
443 }
444 if (descriptor.writablePresent() && descriptor.writable()) {
445 if (throwException)
benjamin@webkit.org762e2c62012-09-04 21:19:25 +0000446 throwError(exec, createTypeError(exec, ASCIILiteral("Attempting to change writable attribute of unconfigurable property.")));
barraclough@apple.com7ef41522012-03-19 21:34:25 +0000447 return false;
448 }
449 if (!valueCheck) {
barraclough@apple.comeb88e082012-03-06 20:20:04 +0000450 if (throwException)
benjamin@webkit.org762e2c62012-09-04 21:19:25 +0000451 throwError(exec, createTypeError(exec, ASCIILiteral("Attempting to change value of a readonly property.")));
barraclough@apple.comeb88e082012-03-06 20:20:04 +0000452 return false;
453 }
barraclough@apple.com7ef41522012-03-19 21:34:25 +0000454 return true;
barraclough@apple.comeb88e082012-03-06 20:20:04 +0000455}
456
mhahnenberg@apple.com79c8e6e2011-10-08 23:26:41 +0000457// ECMA 13.2.2 [[Construct]]
458ConstructType JSFunction::getConstructData(JSCell* cell, ConstructData& constructData)
459{
mhahnenberg@apple.com135f0512011-11-11 20:40:10 +0000460 JSFunction* thisObject = jsCast<JSFunction*>(cell);
mhahnenberg@apple.com79c8e6e2011-10-08 23:26:41 +0000461 if (thisObject->isHostFunction()) {
462 constructData.native.function = thisObject->nativeConstructor();
barraclough@apple.com22215662011-09-22 21:22:17 +0000463 return ConstructTypeHost;
464 }
mhahnenberg@apple.com79c8e6e2011-10-08 23:26:41 +0000465 constructData.js.functionExecutable = thisObject->jsExecutable();
ggaren@apple.comb11e7872012-08-30 22:50:00 +0000466 constructData.js.scope = thisObject->scope();
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000467 return ConstructTypeJS;
468}
oliver@apple.comf7190bf2012-02-01 23:23:30 +0000469
470
benjamin@webkit.orgcff06e42012-08-30 21:23:51 +0000471String getCalculatedDisplayName(CallFrame* callFrame, JSObject* object)
oliver@apple.comf7190bf2012-02-01 23:23:30 +0000472{
473 if (JSFunction* function = jsDynamicCast<JSFunction*>(object))
474 return function->calculatedDisplayName(callFrame);
475 if (InternalFunction* function = jsDynamicCast<InternalFunction*>(object))
476 return function->calculatedDisplayName(callFrame);
barraclough@apple.com38d3c752012-05-12 00:39:43 +0000477 return "";
oliver@apple.comf7190bf2012-02-01 23:23:30 +0000478}
mrowe@apple.com2f6dfdf2008-05-22 01:20:45 +0000479
cwzwarich@webkit.org3f782f62008-09-08 01:28:33 +0000480} // namespace JSC