[ES6] Implement ES6 arrow function syntax. Prototype of arrow function should be...
[WebKit-https.git] / Source / JavaScriptCore / runtime / JSFunction.cpp
1 /*
2  *  Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
4  *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2015 Apple Inc. All rights reserved.
5  *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
6  *  Copyright (C) 2007 Maks Orlovich
7  *  Copyright (C) 2015 Canon Inc. All rights reserved.
8  *
9  *  This library is free software; you can redistribute it and/or
10  *  modify it under the terms of the GNU Library General Public
11  *  License as published by the Free Software Foundation; either
12  *  version 2 of the License, or (at your option) any later version.
13  *
14  *  This library is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  *  Library General Public License for more details.
18  *
19  *  You should have received a copy of the GNU Library General Public License
20  *  along with this library; see the file COPYING.LIB.  If not, write to
21  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  *  Boston, MA 02110-1301, USA.
23  *
24  */
25
26 #include "config.h"
27 #include "JSFunction.h"
28
29 #include "ClonedArguments.h"
30 #include "CodeBlock.h"
31 #include "CommonIdentifiers.h"
32 #include "CallFrame.h"
33 #include "ExceptionHelpers.h"
34 #include "FunctionPrototype.h"
35 #include "GetterSetter.h"
36 #include "JSArray.h"
37 #include "JSBoundFunction.h"
38 #include "JSCInlines.h"
39 #include "JSFunctionInlines.h"
40 #include "JSGlobalObject.h"
41 #include "JSNotAnObject.h"
42 #include "Interpreter.h"
43 #include "ObjectConstructor.h"
44 #include "ObjectPrototype.h"
45 #include "Parser.h"
46 #include "PropertyNameArray.h"
47 #include "StackVisitor.h"
48
49 namespace JSC {
50
51 EncodedJSValue JSC_HOST_CALL callHostFunctionAsConstructor(ExecState* exec)
52 {
53     return throwVMError(exec, createNotAConstructorError(exec, exec->callee()));
54 }
55
56 const ClassInfo JSFunction::s_info = { "Function", &Base::s_info, 0, CREATE_METHOD_TABLE(JSFunction) };
57
58 bool JSFunction::isHostFunctionNonInline() const
59 {
60     return isHostFunction();
61 }
62
63 JSFunction* JSFunction::create(VM& vm, FunctionExecutable* executable, JSScope* scope)
64 {
65     JSFunction* result = createImpl(vm, executable, scope);
66     executable->singletonFunction()->notifyWrite(vm, result, "Allocating a function");
67     return result;
68 }
69
70 #if ENABLE(WEBASSEMBLY)
71 JSFunction* JSFunction::create(VM& vm, WebAssemblyExecutable* executable, JSScope* scope)
72 {
73     JSFunction* function = new (NotNull, allocateCell<JSFunction>(vm.heap)) JSFunction(vm, executable, scope);
74     ASSERT(function->structure()->globalObject());
75     function->finishCreation(vm);
76     return function;
77 }
78 #endif
79
80 NativeExecutable* JSFunction::lookUpOrCreateNativeExecutable(VM& vm, NativeFunction nativeFunction, Intrinsic intrinsic, NativeFunction nativeConstructor)
81 {
82 #if !ENABLE(JIT)
83     UNUSED_PARAM(intrinsic);
84 #else
85     if (intrinsic != NoIntrinsic && vm.canUseJIT()) {
86         ASSERT(nativeConstructor == callHostFunctionAsConstructor);
87         return vm.getHostFunction(nativeFunction, intrinsic);
88     }
89 #endif
90     return vm.getHostFunction(nativeFunction, nativeConstructor);
91 }
92
93 JSFunction* JSFunction::create(VM& vm, JSGlobalObject* globalObject, int length, const String& name, NativeFunction nativeFunction, Intrinsic intrinsic, NativeFunction nativeConstructor)
94 {
95     NativeExecutable* executable = lookUpOrCreateNativeExecutable(vm, nativeFunction, intrinsic, nativeConstructor);
96     JSFunction* function = new (NotNull, allocateCell<JSFunction>(vm.heap)) JSFunction(vm, globalObject, globalObject->functionStructure());
97     // Can't do this during initialization because getHostFunction might do a GC allocation.
98     function->finishCreation(vm, executable, length, name);
99     return function;
100 }
101
102 JSFunction::JSFunction(VM& vm, JSGlobalObject* globalObject, Structure* structure)
103     : Base(vm, globalObject, structure)
104     , m_executable()
105 {
106 }
107
108 void JSFunction::finishCreation(VM& vm, NativeExecutable* executable, int length, const String& name)
109 {
110     Base::finishCreation(vm);
111     ASSERT(inherits(info()));
112     m_executable.set(vm, this, executable);
113     putDirect(vm, vm.propertyNames->name, jsString(&vm, name), DontDelete | ReadOnly | DontEnum);
114     putDirect(vm, vm.propertyNames->length, jsNumber(length), DontDelete | ReadOnly | DontEnum);
115 }
116
117 JSFunction* JSFunction::createBuiltinFunction(VM& vm, FunctionExecutable* executable, JSGlobalObject* globalObject)
118 {
119     JSFunction* function = create(vm, executable, globalObject);
120     function->putDirect(vm, vm.propertyNames->name, jsString(&vm, executable->name().string()), DontDelete | ReadOnly | DontEnum);
121     function->putDirect(vm, vm.propertyNames->length, jsNumber(executable->parameterCount()), DontDelete | ReadOnly | DontEnum);
122     return function;
123 }
124
125 JSFunction* JSFunction::createBuiltinFunction(VM& vm, FunctionExecutable* executable, JSGlobalObject* globalObject, const String& name)
126 {
127     JSFunction* function = create(vm, executable, globalObject);
128     function->putDirect(vm, vm.propertyNames->name, jsString(&vm, name), DontDelete | ReadOnly | DontEnum);
129     function->putDirect(vm, vm.propertyNames->length, jsNumber(executable->parameterCount()), DontDelete | ReadOnly | DontEnum);
130     return function;
131 }
132
133 FunctionRareData* JSFunction::allocateAndInitializeRareData(ExecState* exec, size_t inlineCapacity)
134 {
135     ASSERT(!m_rareData);
136     VM& vm = exec->vm();
137     JSObject* prototype = jsDynamicCast<JSObject*>(get(exec, vm.propertyNames->prototype));
138     if (!prototype)
139         prototype = globalObject()->objectPrototype();
140     FunctionRareData* rareData = FunctionRareData::create(vm, prototype, inlineCapacity);
141
142     // A DFG compilation thread may be trying to read the rare data
143     // We want to ensure that it sees it properly allocated
144     WTF::storeStoreFence();
145
146     m_rareData.set(vm, this, rareData);
147     return m_rareData.get();
148 }
149
150 FunctionRareData* JSFunction::initializeRareData(ExecState* exec, size_t inlineCapacity)
151 {
152     ASSERT(!!m_rareData);
153     VM& vm = exec->vm();
154     JSObject* prototype = jsDynamicCast<JSObject*>(get(exec, vm.propertyNames->prototype));
155     if (!prototype)
156         prototype = globalObject()->objectPrototype();
157     m_rareData->initialize(globalObject()->vm(), prototype, inlineCapacity);
158     return m_rareData.get();
159 }
160
161 String JSFunction::name(ExecState* exec)
162 {
163     return get(exec, exec->vm().propertyNames->name).toWTFString(exec);
164 }
165
166 String JSFunction::displayName(ExecState* exec)
167 {
168     JSValue displayName = getDirect(exec->vm(), exec->vm().propertyNames->displayName);
169     
170     if (displayName && isJSString(displayName))
171         return asString(displayName)->tryGetValue();
172     
173     return String();
174 }
175
176 const String JSFunction::calculatedDisplayName(ExecState* exec)
177 {
178     const String explicitName = displayName(exec);
179     
180     if (!explicitName.isEmpty())
181         return explicitName;
182     
183     const String actualName = name(exec);
184     if (!actualName.isEmpty() || isHostOrBuiltinFunction())
185         return actualName;
186     
187     return jsExecutable()->inferredName().string();
188 }
189
190 const SourceCode* JSFunction::sourceCode() const
191 {
192     if (isHostOrBuiltinFunction())
193         return 0;
194     return &jsExecutable()->source();
195 }
196     
197 void JSFunction::visitChildren(JSCell* cell, SlotVisitor& visitor)
198 {
199     JSFunction* thisObject = jsCast<JSFunction*>(cell);
200     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
201     Base::visitChildren(thisObject, visitor);
202
203     visitor.append(&thisObject->m_executable);
204     if (thisObject->m_rareData)
205         visitor.append(&thisObject->m_rareData);
206 }
207
208 CallType JSFunction::getCallData(JSCell* cell, CallData& callData)
209 {
210     JSFunction* thisObject = jsCast<JSFunction*>(cell);
211     if (thisObject->isHostFunction()) {
212         callData.native.function = thisObject->nativeFunction();
213         return CallTypeHost;
214     }
215     callData.js.functionExecutable = thisObject->jsExecutable();
216     callData.js.scope = thisObject->scope();
217     return CallTypeJS;
218 }
219
220 class RetrieveArgumentsFunctor {
221 public:
222     RetrieveArgumentsFunctor(JSFunction* functionObj)
223         : m_targetCallee(jsDynamicCast<JSObject*>(functionObj))
224         , m_result(jsNull())
225     {
226     }
227
228     JSValue result() const { return m_result; }
229
230     StackVisitor::Status operator()(StackVisitor& visitor)
231     {
232         JSObject* callee = visitor->callee();
233         if (callee != m_targetCallee)
234             return StackVisitor::Continue;
235
236         m_result = JSValue(visitor->createArguments());
237         return StackVisitor::Done;
238     }
239
240 private:
241     JSObject* m_targetCallee;
242     JSValue m_result;
243 };
244
245 static JSValue retrieveArguments(ExecState* exec, JSFunction* functionObj)
246 {
247     RetrieveArgumentsFunctor functor(functionObj);
248     exec->iterate(functor);
249     return functor.result();
250 }
251
252 EncodedJSValue JSFunction::argumentsGetter(ExecState* exec, JSObject* slotBase, EncodedJSValue, PropertyName)
253 {
254     JSFunction* thisObj = jsCast<JSFunction*>(slotBase);
255     ASSERT(!thisObj->isHostFunction());
256
257     return JSValue::encode(retrieveArguments(exec, thisObj));
258 }
259
260 class RetrieveCallerFunctionFunctor {
261 public:
262     RetrieveCallerFunctionFunctor(JSFunction* functionObj)
263         : m_targetCallee(jsDynamicCast<JSObject*>(functionObj))
264         , m_hasFoundFrame(false)
265         , m_hasSkippedToCallerFrame(false)
266         , m_result(jsNull())
267     {
268     }
269
270     JSValue result() const { return m_result; }
271
272     StackVisitor::Status operator()(StackVisitor& visitor)
273     {
274         JSObject* callee = visitor->callee();
275
276         if (callee && callee->inherits(JSBoundFunction::info()))
277             return StackVisitor::Continue;
278
279         if (!m_hasFoundFrame && (callee != m_targetCallee))
280             return StackVisitor::Continue;
281
282         m_hasFoundFrame = true;
283         if (!m_hasSkippedToCallerFrame) {
284             m_hasSkippedToCallerFrame = true;
285             return StackVisitor::Continue;
286         }
287
288         if (callee)
289             m_result = callee;
290         return StackVisitor::Done;
291     }
292
293 private:
294     JSObject* m_targetCallee;
295     bool m_hasFoundFrame;
296     bool m_hasSkippedToCallerFrame;
297     JSValue m_result;
298 };
299
300 static JSValue retrieveCallerFunction(ExecState* exec, JSFunction* functionObj)
301 {
302     RetrieveCallerFunctionFunctor functor(functionObj);
303     exec->iterate(functor);
304     return functor.result();
305 }
306
307 EncodedJSValue JSFunction::callerGetter(ExecState* exec, JSObject* slotBase, EncodedJSValue, PropertyName)
308 {
309     JSFunction* thisObj = jsCast<JSFunction*>(slotBase);
310     ASSERT(!thisObj->isHostFunction());
311     JSValue caller = retrieveCallerFunction(exec, thisObj);
312
313     // See ES5.1 15.3.5.4 - Function.caller may not be used to retrieve a strict caller.
314     if (!caller.isObject() || !asObject(caller)->inherits(JSFunction::info())) {
315         // It isn't a JSFunction, but if it is a JSCallee from a program or call eval, return null.
316         if (jsDynamicCast<JSCallee*>(caller))
317             return JSValue::encode(jsNull());
318         return JSValue::encode(caller);
319     }
320     JSFunction* function = jsCast<JSFunction*>(caller);
321     if (function->isHostOrBuiltinFunction() || !function->jsExecutable()->isStrictMode())
322         return JSValue::encode(caller);
323     return JSValue::encode(throwTypeError(exec, ASCIILiteral("Function.caller used to retrieve strict caller")));
324 }
325
326 EncodedJSValue JSFunction::lengthGetter(ExecState*, JSObject* slotBase, EncodedJSValue, PropertyName)
327 {
328     JSFunction* thisObj = jsCast<JSFunction*>(slotBase);
329     ASSERT(!thisObj->isHostFunction());
330     return JSValue::encode(jsNumber(thisObj->jsExecutable()->parameterCount()));
331 }
332
333 EncodedJSValue JSFunction::nameGetter(ExecState*, JSObject* slotBase, EncodedJSValue, PropertyName)
334 {
335     JSFunction* thisObj = jsCast<JSFunction*>(slotBase);
336     ASSERT(!thisObj->isHostFunction());
337     return JSValue::encode(thisObj->jsExecutable()->nameValue());
338 }
339
340 bool JSFunction::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
341 {
342     JSFunction* thisObject = jsCast<JSFunction*>(object);
343     if (thisObject->isHostOrBuiltinFunction())
344         return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
345
346     if (propertyName == exec->propertyNames().prototype && !thisObject->jsExecutable()->isArrowFunction()) {
347         VM& vm = exec->vm();
348         unsigned attributes;
349         PropertyOffset offset = thisObject->getDirectOffset(vm, propertyName, attributes);
350         if (!isValidOffset(offset)) {
351             JSObject* prototype = constructEmptyObject(exec);
352             prototype->putDirect(vm, exec->propertyNames().constructor, thisObject, DontEnum);
353             thisObject->putDirect(vm, exec->propertyNames().prototype, prototype, DontDelete | DontEnum);
354             offset = thisObject->getDirectOffset(vm, exec->propertyNames().prototype, attributes);
355             ASSERT(isValidOffset(offset));
356         }
357
358         slot.setValue(thisObject, attributes, thisObject->getDirect(offset), offset);
359     }
360
361     if (propertyName == exec->propertyNames().arguments) {
362         if (thisObject->jsExecutable()->isStrictMode()) {
363             bool result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
364             if (!result) {
365                 thisObject->putDirectAccessor(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec->vm()), DontDelete | DontEnum | Accessor);
366                 result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
367                 ASSERT(result);
368             }
369             return result;
370         }
371         slot.setCacheableCustom(thisObject, ReadOnly | DontEnum | DontDelete, argumentsGetter);
372         return true;
373     }
374
375     if (propertyName == exec->propertyNames().length) {
376         slot.setCacheableCustom(thisObject, ReadOnly | DontEnum | DontDelete, lengthGetter);
377         return true;
378     }
379
380     if (propertyName == exec->propertyNames().name) {
381         slot.setCacheableCustom(thisObject, ReadOnly | DontEnum | DontDelete, nameGetter);
382         return true;
383     }
384
385     if (propertyName == exec->propertyNames().caller) {
386         if (thisObject->jsExecutable()->isStrictMode()) {
387             bool result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
388             if (!result) {
389                 thisObject->putDirectAccessor(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec->vm()), DontDelete | DontEnum | Accessor);
390                 result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
391                 ASSERT(result);
392             }
393             return result;
394         }
395         slot.setCacheableCustom(thisObject, ReadOnly | DontEnum | DontDelete, callerGetter);
396         return true;
397     }
398
399     return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
400 }
401
402 void JSFunction::getOwnNonIndexPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
403 {
404     JSFunction* thisObject = jsCast<JSFunction*>(object);
405     if (!thisObject->isHostOrBuiltinFunction() && mode.includeDontEnumProperties()) {
406         VM& vm = exec->vm();
407         // Make sure prototype has been reified.
408         PropertySlot slot(thisObject);
409         thisObject->methodTable(vm)->getOwnPropertySlot(thisObject, exec, vm.propertyNames->prototype, slot);
410
411         propertyNames.add(vm.propertyNames->arguments);
412         propertyNames.add(vm.propertyNames->caller);
413         propertyNames.add(vm.propertyNames->length);
414         propertyNames.add(vm.propertyNames->name);
415     }
416     Base::getOwnNonIndexPropertyNames(thisObject, exec, propertyNames, mode);
417 }
418
419 void JSFunction::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
420 {
421     JSFunction* thisObject = jsCast<JSFunction*>(cell);
422     if (thisObject->isHostOrBuiltinFunction()) {
423         Base::put(thisObject, exec, propertyName, value, slot);
424         return;
425     }
426     if (propertyName == exec->propertyNames().prototype) {
427         // Make sure prototype has been reified, such that it can only be overwritten
428         // following the rules set out in ECMA-262 8.12.9.
429         PropertySlot slot(thisObject);
430         thisObject->methodTable(exec->vm())->getOwnPropertySlot(thisObject, exec, propertyName, slot);
431         if (thisObject->m_rareData)
432             thisObject->m_rareData->clear("Store to prototype property of a function");
433         // Don't allow this to be cached, since a [[Put]] must clear m_rareData.
434         PutPropertySlot dontCache(thisObject);
435         Base::put(thisObject, exec, propertyName, value, dontCache);
436         return;
437     }
438     if (thisObject->jsExecutable()->isStrictMode() && (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().caller)) {
439         // This will trigger the property to be reified, if this is not already the case!
440         bool okay = thisObject->hasProperty(exec, propertyName);
441         ASSERT_UNUSED(okay, okay);
442         Base::put(thisObject, exec, propertyName, value, slot);
443         return;
444     }
445     if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length || propertyName == exec->propertyNames().name || propertyName == exec->propertyNames().caller) {
446         if (slot.isStrictMode())
447             throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
448         return;
449     }
450     Base::put(thisObject, exec, propertyName, value, slot);
451 }
452
453 bool JSFunction::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
454 {
455     JSFunction* thisObject = jsCast<JSFunction*>(cell);
456     // For non-host functions, don't let these properties by deleted - except by DefineOwnProperty.
457     if (!thisObject->isHostOrBuiltinFunction() && !exec->vm().isInDefineOwnProperty()) {
458         FunctionExecutable* executable = thisObject->jsExecutable();
459         if (propertyName == exec->propertyNames().arguments
460             || propertyName == exec->propertyNames().length
461             || propertyName == exec->propertyNames().name
462             || (propertyName == exec->propertyNames().prototype && !executable->isArrowFunction())
463             || propertyName == exec->propertyNames().caller)
464         return false;
465     }
466     
467     return Base::deleteProperty(thisObject, exec, propertyName);
468 }
469
470 bool JSFunction::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool throwException)
471 {
472     JSFunction* thisObject = jsCast<JSFunction*>(object);
473     if (thisObject->isHostOrBuiltinFunction())
474         return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
475
476     if (propertyName == exec->propertyNames().prototype) {
477         // Make sure prototype has been reified, such that it can only be overwritten
478         // following the rules set out in ECMA-262 8.12.9.
479         PropertySlot slot(thisObject);
480         thisObject->methodTable(exec->vm())->getOwnPropertySlot(thisObject, exec, propertyName, slot);
481         if (thisObject->m_rareData)
482             thisObject->m_rareData->clear("Store to prototype property of a function");
483         return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
484     }
485
486     bool valueCheck;
487     if (propertyName == exec->propertyNames().arguments) {
488         if (thisObject->jsExecutable()->isStrictMode()) {
489             PropertySlot slot(thisObject);
490             if (!Base::getOwnPropertySlot(thisObject, exec, propertyName, slot))
491                 thisObject->putDirectAccessor(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec->vm()), DontDelete | DontEnum | Accessor);
492             return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
493         }
494         valueCheck = !descriptor.value() || sameValue(exec, descriptor.value(), retrieveArguments(exec, thisObject));
495     } else if (propertyName == exec->propertyNames().caller) {
496         if (thisObject->jsExecutable()->isStrictMode()) {
497             PropertySlot slot(thisObject);
498             if (!Base::getOwnPropertySlot(thisObject, exec, propertyName, slot))
499                 thisObject->putDirectAccessor(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec->vm()), DontDelete | DontEnum | Accessor);
500             return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
501         }
502         valueCheck = !descriptor.value() || sameValue(exec, descriptor.value(), retrieveCallerFunction(exec, thisObject));
503     } else if (propertyName == exec->propertyNames().length)
504         valueCheck = !descriptor.value() || sameValue(exec, descriptor.value(), jsNumber(thisObject->jsExecutable()->parameterCount()));
505     else if (propertyName == exec->propertyNames().name)
506         valueCheck = !descriptor.value() || sameValue(exec, descriptor.value(), thisObject->jsExecutable()->nameValue());
507     else
508         return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
509      
510     if (descriptor.configurablePresent() && descriptor.configurable()) {
511         if (throwException)
512             exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Attempting to change configurable attribute of unconfigurable property.")));
513         return false;
514     }
515     if (descriptor.enumerablePresent() && descriptor.enumerable()) {
516         if (throwException)
517             exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Attempting to change enumerable attribute of unconfigurable property.")));
518         return false;
519     }
520     if (descriptor.isAccessorDescriptor()) {
521         if (throwException)
522             exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Attempting to change access mechanism for an unconfigurable property.")));
523         return false;
524     }
525     if (descriptor.writablePresent() && descriptor.writable()) {
526         if (throwException)
527             exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Attempting to change writable attribute of unconfigurable property.")));
528         return false;
529     }
530     if (!valueCheck) {
531         if (throwException)
532             exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Attempting to change value of a readonly property.")));
533         return false;
534     }
535     return true;
536 }
537
538 // ECMA 13.2.2 [[Construct]]
539 ConstructType JSFunction::getConstructData(JSCell* cell, ConstructData& constructData)
540 {
541     JSFunction* thisObject = jsCast<JSFunction*>(cell);
542
543     if (thisObject->isHostFunction()) {
544         constructData.native.function = thisObject->nativeConstructor();
545         return ConstructTypeHost;
546     }
547
548     FunctionExecutable* functionExecutable = thisObject->jsExecutable();
549     if (functionExecutable->constructAbility() == ConstructAbility::CannotConstruct)
550         return ConstructTypeNone;
551
552     constructData.js.functionExecutable = functionExecutable;
553     constructData.js.scope = thisObject->scope();
554     return ConstructTypeJS;
555 }
556
557 String getCalculatedDisplayName(CallFrame* callFrame, JSObject* object)
558 {
559     if (JSFunction* function = jsDynamicCast<JSFunction*>(object))
560         return function->calculatedDisplayName(callFrame);
561     if (InternalFunction* function = jsDynamicCast<InternalFunction*>(object))
562         return function->calculatedDisplayName(callFrame);
563     return "";
564 }
565
566 } // namespace JSC