[Streams API] ReadableJSStream should handle promises returned by JS source start...
[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 static inline NativeExecutable* getNativeExecutable(VM& vm, NativeFunction nativeFunction, Intrinsic intrinsic, NativeFunction nativeConstructor)
71 {
72 #if !ENABLE(JIT)
73     UNUSED_PARAM(intrinsic);
74 #else
75     if (intrinsic != NoIntrinsic && vm.canUseJIT()) {
76         ASSERT(nativeConstructor == callHostFunctionAsConstructor);
77         return vm.getHostFunction(nativeFunction, intrinsic);
78     }
79 #endif
80     return vm.getHostFunction(nativeFunction, nativeConstructor);
81 }
82
83 JSFunction* JSFunction::create(VM& vm, JSGlobalObject* globalObject, int length, const String& name, NativeFunction nativeFunction, Intrinsic intrinsic, NativeFunction nativeConstructor)
84 {
85     NativeExecutable* executable = getNativeExecutable(vm, nativeFunction, intrinsic, nativeConstructor);
86     JSFunction* function = new (NotNull, allocateCell<JSFunction>(vm.heap)) JSFunction(vm, globalObject, globalObject->functionStructure());
87     // Can't do this during initialization because getHostFunction might do a GC allocation.
88     function->finishCreation(vm, executable, length, name);
89     return function;
90 }
91
92 class JSStdFunction : public JSFunction {
93 public:
94     JSStdFunction(VM& vm, JSGlobalObject* object, Structure* structure, NativeStdFunction&& function)
95         : JSFunction(vm, object, structure)
96         , stdFunction(WTF::move(function)) { }
97
98     NativeStdFunction stdFunction;
99 };
100
101 static EncodedJSValue JSC_HOST_CALL runStdFunction(ExecState* state)
102 {
103     JSStdFunction* jsFunction = jsCast<JSStdFunction*>(state->callee());
104     ASSERT(jsFunction);
105     return jsFunction->stdFunction(state);
106 }
107
108 JSFunction* JSFunction::create(VM& vm, JSGlobalObject* globalObject, int length, const String& name, NativeStdFunction&& nativeStdFunction, Intrinsic intrinsic, NativeFunction nativeConstructor)
109 {
110     NativeExecutable* executable = getNativeExecutable(vm, runStdFunction, intrinsic, nativeConstructor);
111     JSStdFunction* function = new (NotNull, allocateCell<JSStdFunction>(vm.heap)) JSStdFunction(vm, globalObject, globalObject->functionStructure(), WTF::move(nativeStdFunction));
112     // Can't do this during initialization because getHostFunction might do a GC allocation.
113     function->finishCreation(vm, executable, length, name);
114     return function;
115 }
116
117 JSFunction::JSFunction(VM& vm, JSGlobalObject* globalObject, Structure* structure)
118     : Base(vm, globalObject, structure)
119     , m_executable()
120 {
121 }
122
123 void JSFunction::finishCreation(VM& vm, NativeExecutable* executable, int length, const String& name)
124 {
125     Base::finishCreation(vm);
126     ASSERT(inherits(info()));
127     m_executable.set(vm, this, executable);
128     putDirect(vm, vm.propertyNames->name, jsString(&vm, name), DontDelete | ReadOnly | DontEnum);
129     putDirect(vm, vm.propertyNames->length, jsNumber(length), DontDelete | ReadOnly | DontEnum);
130 }
131
132 JSFunction* JSFunction::createBuiltinFunction(VM& vm, FunctionExecutable* executable, JSGlobalObject* globalObject)
133 {
134     JSFunction* function = create(vm, executable, globalObject);
135     function->putDirect(vm, vm.propertyNames->name, jsString(&vm, executable->name().string()), DontDelete | ReadOnly | DontEnum);
136     function->putDirect(vm, vm.propertyNames->length, jsNumber(executable->parameterCount()), DontDelete | ReadOnly | DontEnum);
137     return function;
138 }
139
140 FunctionRareData* JSFunction::allocateAndInitializeRareData(ExecState* exec, size_t inlineCapacity)
141 {
142     ASSERT(!m_rareData);
143     VM& vm = exec->vm();
144     JSObject* prototype = jsDynamicCast<JSObject*>(get(exec, vm.propertyNames->prototype));
145     if (!prototype)
146         prototype = globalObject()->objectPrototype();
147     FunctionRareData* rareData = FunctionRareData::create(vm, prototype, inlineCapacity);
148
149     // A DFG compilation thread may be trying to read the rare data
150     // We want to ensure that it sees it properly allocated
151     WTF::storeStoreFence();
152
153     m_rareData.set(vm, this, rareData);
154     return m_rareData.get();
155 }
156
157 FunctionRareData* JSFunction::initializeRareData(ExecState* exec, size_t inlineCapacity)
158 {
159     ASSERT(!!m_rareData);
160     VM& vm = exec->vm();
161     JSObject* prototype = jsDynamicCast<JSObject*>(get(exec, vm.propertyNames->prototype));
162     if (!prototype)
163         prototype = globalObject()->objectPrototype();
164     m_rareData->initialize(globalObject()->vm(), prototype, inlineCapacity);
165     return m_rareData.get();
166 }
167
168 String JSFunction::name(ExecState* exec)
169 {
170     return get(exec, exec->vm().propertyNames->name).toWTFString(exec);
171 }
172
173 String JSFunction::displayName(ExecState* exec)
174 {
175     JSValue displayName = getDirect(exec->vm(), exec->vm().propertyNames->displayName);
176     
177     if (displayName && isJSString(displayName))
178         return asString(displayName)->tryGetValue();
179     
180     return String();
181 }
182
183 const String JSFunction::calculatedDisplayName(ExecState* exec)
184 {
185     const String explicitName = displayName(exec);
186     
187     if (!explicitName.isEmpty())
188         return explicitName;
189     
190     const String actualName = name(exec);
191     if (!actualName.isEmpty() || isHostOrBuiltinFunction())
192         return actualName;
193     
194     return jsExecutable()->inferredName().string();
195 }
196
197 const SourceCode* JSFunction::sourceCode() const
198 {
199     if (isHostOrBuiltinFunction())
200         return 0;
201     return &jsExecutable()->source();
202 }
203     
204 void JSFunction::visitChildren(JSCell* cell, SlotVisitor& visitor)
205 {
206     JSFunction* thisObject = jsCast<JSFunction*>(cell);
207     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
208     Base::visitChildren(thisObject, visitor);
209
210     visitor.append(&thisObject->m_executable);
211     if (thisObject->m_rareData)
212         visitor.append(&thisObject->m_rareData);
213 }
214
215 CallType JSFunction::getCallData(JSCell* cell, CallData& callData)
216 {
217     JSFunction* thisObject = jsCast<JSFunction*>(cell);
218     if (thisObject->isHostFunction()) {
219         callData.native.function = thisObject->nativeFunction();
220         return CallTypeHost;
221     }
222     callData.js.functionExecutable = thisObject->jsExecutable();
223     callData.js.scope = thisObject->scope();
224     return CallTypeJS;
225 }
226
227 class RetrieveArgumentsFunctor {
228 public:
229     RetrieveArgumentsFunctor(JSFunction* functionObj)
230         : m_targetCallee(jsDynamicCast<JSObject*>(functionObj))
231         , m_result(jsNull())
232     {
233     }
234
235     JSValue result() const { return m_result; }
236
237     StackVisitor::Status operator()(StackVisitor& visitor)
238     {
239         JSObject* callee = visitor->callee();
240         if (callee != m_targetCallee)
241             return StackVisitor::Continue;
242
243         m_result = JSValue(visitor->createArguments());
244         return StackVisitor::Done;
245     }
246
247 private:
248     JSObject* m_targetCallee;
249     JSValue m_result;
250 };
251
252 static JSValue retrieveArguments(ExecState* exec, JSFunction* functionObj)
253 {
254     RetrieveArgumentsFunctor functor(functionObj);
255     exec->iterate(functor);
256     return functor.result();
257 }
258
259 EncodedJSValue JSFunction::argumentsGetter(ExecState* exec, JSObject* slotBase, EncodedJSValue, PropertyName)
260 {
261     JSFunction* thisObj = jsCast<JSFunction*>(slotBase);
262     ASSERT(!thisObj->isHostFunction());
263
264     return JSValue::encode(retrieveArguments(exec, thisObj));
265 }
266
267 class RetrieveCallerFunctionFunctor {
268 public:
269     RetrieveCallerFunctionFunctor(JSFunction* functionObj)
270         : m_targetCallee(jsDynamicCast<JSObject*>(functionObj))
271         , m_hasFoundFrame(false)
272         , m_hasSkippedToCallerFrame(false)
273         , m_result(jsNull())
274     {
275     }
276
277     JSValue result() const { return m_result; }
278
279     StackVisitor::Status operator()(StackVisitor& visitor)
280     {
281         JSObject* callee = visitor->callee();
282
283         if (callee && callee->inherits(JSBoundFunction::info()))
284             return StackVisitor::Continue;
285
286         if (!m_hasFoundFrame && (callee != m_targetCallee))
287             return StackVisitor::Continue;
288
289         m_hasFoundFrame = true;
290         if (!m_hasSkippedToCallerFrame) {
291             m_hasSkippedToCallerFrame = true;
292             return StackVisitor::Continue;
293         }
294
295         if (callee)
296             m_result = callee;
297         return StackVisitor::Done;
298     }
299
300 private:
301     JSObject* m_targetCallee;
302     bool m_hasFoundFrame;
303     bool m_hasSkippedToCallerFrame;
304     JSValue m_result;
305 };
306
307 static JSValue retrieveCallerFunction(ExecState* exec, JSFunction* functionObj)
308 {
309     RetrieveCallerFunctionFunctor functor(functionObj);
310     exec->iterate(functor);
311     return functor.result();
312 }
313
314 EncodedJSValue JSFunction::callerGetter(ExecState* exec, JSObject* slotBase, EncodedJSValue, PropertyName)
315 {
316     JSFunction* thisObj = jsCast<JSFunction*>(slotBase);
317     ASSERT(!thisObj->isHostFunction());
318     JSValue caller = retrieveCallerFunction(exec, thisObj);
319
320     // See ES5.1 15.3.5.4 - Function.caller may not be used to retrieve a strict caller.
321     if (!caller.isObject() || !asObject(caller)->inherits(JSFunction::info())) {
322         // It isn't a JSFunction, but if it is a JSCallee from a program or call eval, return null.
323         if (jsDynamicCast<JSCallee*>(caller))
324             return JSValue::encode(jsNull());
325         return JSValue::encode(caller);
326     }
327     JSFunction* function = jsCast<JSFunction*>(caller);
328     if (function->isHostOrBuiltinFunction() || !function->jsExecutable()->isStrictMode())
329         return JSValue::encode(caller);
330     return JSValue::encode(throwTypeError(exec, ASCIILiteral("Function.caller used to retrieve strict caller")));
331 }
332
333 EncodedJSValue JSFunction::lengthGetter(ExecState*, JSObject* slotBase, EncodedJSValue, PropertyName)
334 {
335     JSFunction* thisObj = jsCast<JSFunction*>(slotBase);
336     ASSERT(!thisObj->isHostFunction());
337     return JSValue::encode(jsNumber(thisObj->jsExecutable()->parameterCount()));
338 }
339
340 EncodedJSValue JSFunction::nameGetter(ExecState*, JSObject* slotBase, EncodedJSValue, PropertyName)
341 {
342     JSFunction* thisObj = jsCast<JSFunction*>(slotBase);
343     ASSERT(!thisObj->isHostFunction());
344     return JSValue::encode(thisObj->jsExecutable()->nameValue());
345 }
346
347 bool JSFunction::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
348 {
349     JSFunction* thisObject = jsCast<JSFunction*>(object);
350     if (thisObject->isHostOrBuiltinFunction())
351         return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
352
353     if (propertyName == exec->propertyNames().prototype) {
354         VM& vm = exec->vm();
355         unsigned attributes;
356         PropertyOffset offset = thisObject->getDirectOffset(vm, propertyName, attributes);
357         if (!isValidOffset(offset)) {
358             JSObject* prototype = constructEmptyObject(exec);
359             prototype->putDirect(vm, exec->propertyNames().constructor, thisObject, DontEnum);
360             thisObject->putDirect(vm, exec->propertyNames().prototype, prototype, DontDelete | DontEnum);
361             offset = thisObject->getDirectOffset(vm, exec->propertyNames().prototype, attributes);
362             ASSERT(isValidOffset(offset));
363         }
364
365         slot.setValue(thisObject, attributes, thisObject->getDirect(offset), offset);
366     }
367
368     if (propertyName == exec->propertyNames().arguments) {
369         if (thisObject->jsExecutable()->isStrictMode()) {
370             bool result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
371             if (!result) {
372                 thisObject->putDirectAccessor(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec->vm()), DontDelete | DontEnum | Accessor);
373                 result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
374                 ASSERT(result);
375             }
376             return result;
377         }
378         slot.setCacheableCustom(thisObject, ReadOnly | DontEnum | DontDelete, argumentsGetter);
379         return true;
380     }
381
382     if (propertyName == exec->propertyNames().length) {
383         slot.setCacheableCustom(thisObject, ReadOnly | DontEnum | DontDelete, lengthGetter);
384         return true;
385     }
386
387     if (propertyName == exec->propertyNames().name) {
388         slot.setCacheableCustom(thisObject, ReadOnly | DontEnum | DontDelete, nameGetter);
389         return true;
390     }
391
392     if (propertyName == exec->propertyNames().caller) {
393         if (thisObject->jsExecutable()->isStrictMode()) {
394             bool result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
395             if (!result) {
396                 thisObject->putDirectAccessor(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec->vm()), DontDelete | DontEnum | Accessor);
397                 result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
398                 ASSERT(result);
399             }
400             return result;
401         }
402         slot.setCacheableCustom(thisObject, ReadOnly | DontEnum | DontDelete, callerGetter);
403         return true;
404     }
405
406     return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
407 }
408
409 void JSFunction::getOwnNonIndexPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
410 {
411     JSFunction* thisObject = jsCast<JSFunction*>(object);
412     if (!thisObject->isHostOrBuiltinFunction() && mode.includeDontEnumProperties()) {
413         VM& vm = exec->vm();
414         // Make sure prototype has been reified.
415         PropertySlot slot(thisObject);
416         thisObject->methodTable(vm)->getOwnPropertySlot(thisObject, exec, vm.propertyNames->prototype, slot);
417
418         propertyNames.add(vm.propertyNames->arguments);
419         propertyNames.add(vm.propertyNames->caller);
420         propertyNames.add(vm.propertyNames->length);
421         propertyNames.add(vm.propertyNames->name);
422     }
423     Base::getOwnNonIndexPropertyNames(thisObject, exec, propertyNames, mode);
424 }
425
426 void JSFunction::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
427 {
428     JSFunction* thisObject = jsCast<JSFunction*>(cell);
429     if (thisObject->isHostOrBuiltinFunction()) {
430         Base::put(thisObject, exec, propertyName, value, slot);
431         return;
432     }
433     if (propertyName == exec->propertyNames().prototype) {
434         // Make sure prototype has been reified, such that it can only be overwritten
435         // following the rules set out in ECMA-262 8.12.9.
436         PropertySlot slot(thisObject);
437         thisObject->methodTable(exec->vm())->getOwnPropertySlot(thisObject, exec, propertyName, slot);
438         if (thisObject->m_rareData)
439             thisObject->m_rareData->clear("Store to prototype property of a function");
440         // Don't allow this to be cached, since a [[Put]] must clear m_rareData.
441         PutPropertySlot dontCache(thisObject);
442         Base::put(thisObject, exec, propertyName, value, dontCache);
443         return;
444     }
445     if (thisObject->jsExecutable()->isStrictMode() && (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().caller)) {
446         // This will trigger the property to be reified, if this is not already the case!
447         bool okay = thisObject->hasProperty(exec, propertyName);
448         ASSERT_UNUSED(okay, okay);
449         Base::put(thisObject, exec, propertyName, value, slot);
450         return;
451     }
452     if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length || propertyName == exec->propertyNames().name || propertyName == exec->propertyNames().caller) {
453         if (slot.isStrictMode())
454             throwTypeError(exec, StrictModeReadonlyPropertyWriteError);
455         return;
456     }
457     Base::put(thisObject, exec, propertyName, value, slot);
458 }
459
460 bool JSFunction::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
461 {
462     JSFunction* thisObject = jsCast<JSFunction*>(cell);
463     // For non-host functions, don't let these properties by deleted - except by DefineOwnProperty.
464     if (!thisObject->isHostOrBuiltinFunction() && !exec->vm().isInDefineOwnProperty()
465         && (propertyName == exec->propertyNames().arguments
466             || propertyName == exec->propertyNames().length
467             || propertyName == exec->propertyNames().name
468             || propertyName == exec->propertyNames().prototype
469             || propertyName == exec->propertyNames().caller))
470         return false;
471     return Base::deleteProperty(thisObject, exec, propertyName);
472 }
473
474 bool JSFunction::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool throwException)
475 {
476     JSFunction* thisObject = jsCast<JSFunction*>(object);
477     if (thisObject->isHostOrBuiltinFunction())
478         return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
479
480     if (propertyName == exec->propertyNames().prototype) {
481         // Make sure prototype has been reified, such that it can only be overwritten
482         // following the rules set out in ECMA-262 8.12.9.
483         PropertySlot slot(thisObject);
484         thisObject->methodTable(exec->vm())->getOwnPropertySlot(thisObject, exec, propertyName, slot);
485         if (thisObject->m_rareData)
486             thisObject->m_rareData->clear("Store to prototype property of a function");
487         return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
488     }
489
490     bool valueCheck;
491     if (propertyName == exec->propertyNames().arguments) {
492         if (thisObject->jsExecutable()->isStrictMode()) {
493             PropertySlot slot(thisObject);
494             if (!Base::getOwnPropertySlot(thisObject, exec, propertyName, slot))
495                 thisObject->putDirectAccessor(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec->vm()), DontDelete | DontEnum | Accessor);
496             return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
497         }
498         valueCheck = !descriptor.value() || sameValue(exec, descriptor.value(), retrieveArguments(exec, thisObject));
499     } else if (propertyName == exec->propertyNames().caller) {
500         if (thisObject->jsExecutable()->isStrictMode()) {
501             PropertySlot slot(thisObject);
502             if (!Base::getOwnPropertySlot(thisObject, exec, propertyName, slot))
503                 thisObject->putDirectAccessor(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec->vm()), DontDelete | DontEnum | Accessor);
504             return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
505         }
506         valueCheck = !descriptor.value() || sameValue(exec, descriptor.value(), retrieveCallerFunction(exec, thisObject));
507     } else if (propertyName == exec->propertyNames().length)
508         valueCheck = !descriptor.value() || sameValue(exec, descriptor.value(), jsNumber(thisObject->jsExecutable()->parameterCount()));
509     else if (propertyName == exec->propertyNames().name)
510         valueCheck = !descriptor.value() || sameValue(exec, descriptor.value(), thisObject->jsExecutable()->nameValue());
511     else
512         return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
513      
514     if (descriptor.configurablePresent() && descriptor.configurable()) {
515         if (throwException)
516             exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Attempting to configurable attribute of unconfigurable property.")));
517         return false;
518     }
519     if (descriptor.enumerablePresent() && descriptor.enumerable()) {
520         if (throwException)
521             exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Attempting to change enumerable attribute of unconfigurable property.")));
522         return false;
523     }
524     if (descriptor.isAccessorDescriptor()) {
525         if (throwException)
526             exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Attempting to change access mechanism for an unconfigurable property.")));
527         return false;
528     }
529     if (descriptor.writablePresent() && descriptor.writable()) {
530         if (throwException)
531             exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Attempting to change writable attribute of unconfigurable property.")));
532         return false;
533     }
534     if (!valueCheck) {
535         if (throwException)
536             exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Attempting to change value of a readonly property.")));
537         return false;
538     }
539     return true;
540 }
541
542 // ECMA 13.2.2 [[Construct]]
543 ConstructType JSFunction::getConstructData(JSCell* cell, ConstructData& constructData)
544 {
545     JSFunction* thisObject = jsCast<JSFunction*>(cell);
546
547     if (thisObject->isBuiltinFunction())
548         return ConstructTypeNone;
549
550     if (thisObject->isHostFunction()) {
551         constructData.native.function = thisObject->nativeConstructor();
552         return ConstructTypeHost;
553     }
554     constructData.js.functionExecutable = thisObject->jsExecutable();
555     constructData.js.scope = thisObject->scope();
556     return ConstructTypeJS;
557 }
558
559 String getCalculatedDisplayName(CallFrame* callFrame, JSObject* object)
560 {
561     if (JSFunction* function = jsDynamicCast<JSFunction*>(object))
562         return function->calculatedDisplayName(callFrame);
563     if (InternalFunction* function = jsDynamicCast<InternalFunction*>(object))
564         return function->calculatedDisplayName(callFrame);
565     return "";
566 }
567
568 } // namespace JSC