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.
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.
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.
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.
27 #include "JSFunction.h"
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"
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"
46 #include "PropertyNameArray.h"
47 #include "StackVisitor.h"
51 EncodedJSValue JSC_HOST_CALL
callHostFunctionAsConstructor(ExecState
* exec
)
53 return throwVMError(exec
, createNotAConstructorError(exec
, exec
->callee()));
56 const ClassInfo
JSFunction::s_info
= { "Function", &Base::s_info
, 0, CREATE_METHOD_TABLE(JSFunction
) };
58 bool JSFunction::isHostFunctionNonInline() const
60 return isHostFunction();
63 JSFunction
* JSFunction::create(VM
& vm
, FunctionExecutable
* executable
, JSScope
* scope
)
65 JSFunction
* result
= createImpl(vm
, executable
, scope
);
66 executable
->singletonFunction()->notifyWrite(vm
, result
, "Allocating a function");
70 static inline NativeExecutable
* getNativeExecutable(VM
& vm
, NativeFunction nativeFunction
, Intrinsic intrinsic
, NativeFunction nativeConstructor
)
73 UNUSED_PARAM(intrinsic
);
75 if (intrinsic
!= NoIntrinsic
&& vm
.canUseJIT()) {
76 ASSERT(nativeConstructor
== callHostFunctionAsConstructor
);
77 return vm
.getHostFunction(nativeFunction
, intrinsic
);
80 return vm
.getHostFunction(nativeFunction
, nativeConstructor
);
83 JSFunction
* JSFunction::create(VM
& vm
, JSGlobalObject
* globalObject
, int length
, const String
& name
, NativeFunction nativeFunction
, Intrinsic intrinsic
, NativeFunction nativeConstructor
)
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
);
92 class JSStdFunction
: public JSFunction
{
94 JSStdFunction(VM
& vm
, JSGlobalObject
* object
, Structure
* structure
, NativeStdFunction
&& function
)
95 : JSFunction(vm
, object
, structure
)
96 , stdFunction(WTF::move(function
)) { }
98 NativeStdFunction stdFunction
;
101 static EncodedJSValue JSC_HOST_CALL
runStdFunction(ExecState
* state
)
103 JSStdFunction
* jsFunction
= jsCast
<JSStdFunction
*>(state
->callee());
105 return jsFunction
->stdFunction(state
);
108 JSFunction
* JSFunction::create(VM
& vm
, JSGlobalObject
* globalObject
, int length
, const String
& name
, NativeStdFunction
&& nativeStdFunction
, Intrinsic intrinsic
, NativeFunction nativeConstructor
)
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
);
117 JSFunction::JSFunction(VM
& vm
, JSGlobalObject
* globalObject
, Structure
* structure
)
118 : Base(vm
, globalObject
, structure
)
123 void JSFunction::finishCreation(VM
& vm
, NativeExecutable
* executable
, int length
, const String
& name
)
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
);
132 JSFunction
* JSFunction::createBuiltinFunction(VM
& vm
, FunctionExecutable
* executable
, JSGlobalObject
* globalObject
)
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
);
140 JSFunction
* JSFunction::createBuiltinFunction(VM
& vm
, FunctionExecutable
* executable
, JSGlobalObject
* globalObject
, const String
& name
)
142 JSFunction
* function
= create(vm
, executable
, globalObject
);
143 function
->putDirect(vm
, vm
.propertyNames
->name
, jsString(&vm
, name
), DontDelete
| ReadOnly
| DontEnum
);
144 function
->putDirect(vm
, vm
.propertyNames
->length
, jsNumber(executable
->parameterCount()), DontDelete
| ReadOnly
| DontEnum
);
148 FunctionRareData
* JSFunction::allocateAndInitializeRareData(ExecState
* exec
, size_t inlineCapacity
)
152 JSObject
* prototype
= jsDynamicCast
<JSObject
*>(get(exec
, vm
.propertyNames
->prototype
));
154 prototype
= globalObject()->objectPrototype();
155 FunctionRareData
* rareData
= FunctionRareData::create(vm
, prototype
, inlineCapacity
);
157 // A DFG compilation thread may be trying to read the rare data
158 // We want to ensure that it sees it properly allocated
159 WTF::storeStoreFence();
161 m_rareData
.set(vm
, this, rareData
);
162 return m_rareData
.get();
165 FunctionRareData
* JSFunction::initializeRareData(ExecState
* exec
, size_t inlineCapacity
)
167 ASSERT(!!m_rareData
);
169 JSObject
* prototype
= jsDynamicCast
<JSObject
*>(get(exec
, vm
.propertyNames
->prototype
));
171 prototype
= globalObject()->objectPrototype();
172 m_rareData
->initialize(globalObject()->vm(), prototype
, inlineCapacity
);
173 return m_rareData
.get();
176 String
JSFunction::name(ExecState
* exec
)
178 return get(exec
, exec
->vm().propertyNames
->name
).toWTFString(exec
);
181 String
JSFunction::displayName(ExecState
* exec
)
183 JSValue displayName
= getDirect(exec
->vm(), exec
->vm().propertyNames
->displayName
);
185 if (displayName
&& isJSString(displayName
))
186 return asString(displayName
)->tryGetValue();
191 const String
JSFunction::calculatedDisplayName(ExecState
* exec
)
193 const String explicitName
= displayName(exec
);
195 if (!explicitName
.isEmpty())
198 const String actualName
= name(exec
);
199 if (!actualName
.isEmpty() || isHostOrBuiltinFunction())
202 return jsExecutable()->inferredName().string();
205 const SourceCode
* JSFunction::sourceCode() const
207 if (isHostOrBuiltinFunction())
209 return &jsExecutable()->source();
212 void JSFunction::visitChildren(JSCell
* cell
, SlotVisitor
& visitor
)
214 JSFunction
* thisObject
= jsCast
<JSFunction
*>(cell
);
215 ASSERT_GC_OBJECT_INHERITS(thisObject
, info());
216 Base::visitChildren(thisObject
, visitor
);
218 visitor
.append(&thisObject
->m_executable
);
219 if (thisObject
->m_rareData
)
220 visitor
.append(&thisObject
->m_rareData
);
223 CallType
JSFunction::getCallData(JSCell
* cell
, CallData
& callData
)
225 JSFunction
* thisObject
= jsCast
<JSFunction
*>(cell
);
226 if (thisObject
->isHostFunction()) {
227 callData
.native
.function
= thisObject
->nativeFunction();
230 callData
.js
.functionExecutable
= thisObject
->jsExecutable();
231 callData
.js
.scope
= thisObject
->scope();
235 class RetrieveArgumentsFunctor
{
237 RetrieveArgumentsFunctor(JSFunction
* functionObj
)
238 : m_targetCallee(jsDynamicCast
<JSObject
*>(functionObj
))
243 JSValue
result() const { return m_result
; }
245 StackVisitor::Status
operator()(StackVisitor
& visitor
)
247 JSObject
* callee
= visitor
->callee();
248 if (callee
!= m_targetCallee
)
249 return StackVisitor::Continue
;
251 m_result
= JSValue(visitor
->createArguments());
252 return StackVisitor::Done
;
256 JSObject
* m_targetCallee
;
260 static JSValue
retrieveArguments(ExecState
* exec
, JSFunction
* functionObj
)
262 RetrieveArgumentsFunctor
functor(functionObj
);
263 exec
->iterate(functor
);
264 return functor
.result();
267 EncodedJSValue
JSFunction::argumentsGetter(ExecState
* exec
, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
269 JSFunction
* thisObj
= jsCast
<JSFunction
*>(slotBase
);
270 ASSERT(!thisObj
->isHostFunction());
272 return JSValue::encode(retrieveArguments(exec
, thisObj
));
275 class RetrieveCallerFunctionFunctor
{
277 RetrieveCallerFunctionFunctor(JSFunction
* functionObj
)
278 : m_targetCallee(jsDynamicCast
<JSObject
*>(functionObj
))
279 , m_hasFoundFrame(false)
280 , m_hasSkippedToCallerFrame(false)
285 JSValue
result() const { return m_result
; }
287 StackVisitor::Status
operator()(StackVisitor
& visitor
)
289 JSObject
* callee
= visitor
->callee();
291 if (callee
&& callee
->inherits(JSBoundFunction::info()))
292 return StackVisitor::Continue
;
294 if (!m_hasFoundFrame
&& (callee
!= m_targetCallee
))
295 return StackVisitor::Continue
;
297 m_hasFoundFrame
= true;
298 if (!m_hasSkippedToCallerFrame
) {
299 m_hasSkippedToCallerFrame
= true;
300 return StackVisitor::Continue
;
305 return StackVisitor::Done
;
309 JSObject
* m_targetCallee
;
310 bool m_hasFoundFrame
;
311 bool m_hasSkippedToCallerFrame
;
315 static JSValue
retrieveCallerFunction(ExecState
* exec
, JSFunction
* functionObj
)
317 RetrieveCallerFunctionFunctor
functor(functionObj
);
318 exec
->iterate(functor
);
319 return functor
.result();
322 EncodedJSValue
JSFunction::callerGetter(ExecState
* exec
, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
324 JSFunction
* thisObj
= jsCast
<JSFunction
*>(slotBase
);
325 ASSERT(!thisObj
->isHostFunction());
326 JSValue caller
= retrieveCallerFunction(exec
, thisObj
);
328 // See ES5.1 15.3.5.4 - Function.caller may not be used to retrieve a strict caller.
329 if (!caller
.isObject() || !asObject(caller
)->inherits(JSFunction::info())) {
330 // It isn't a JSFunction, but if it is a JSCallee from a program or call eval, return null.
331 if (jsDynamicCast
<JSCallee
*>(caller
))
332 return JSValue::encode(jsNull());
333 return JSValue::encode(caller
);
335 JSFunction
* function
= jsCast
<JSFunction
*>(caller
);
336 if (function
->isHostOrBuiltinFunction() || !function
->jsExecutable()->isStrictMode())
337 return JSValue::encode(caller
);
338 return JSValue::encode(throwTypeError(exec
, ASCIILiteral("Function.caller used to retrieve strict caller")));
341 EncodedJSValue
JSFunction::lengthGetter(ExecState
*, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
343 JSFunction
* thisObj
= jsCast
<JSFunction
*>(slotBase
);
344 ASSERT(!thisObj
->isHostFunction());
345 return JSValue::encode(jsNumber(thisObj
->jsExecutable()->parameterCount()));
348 EncodedJSValue
JSFunction::nameGetter(ExecState
*, JSObject
* slotBase
, EncodedJSValue
, PropertyName
)
350 JSFunction
* thisObj
= jsCast
<JSFunction
*>(slotBase
);
351 ASSERT(!thisObj
->isHostFunction());
352 return JSValue::encode(thisObj
->jsExecutable()->nameValue());
355 bool JSFunction::getOwnPropertySlot(JSObject
* object
, ExecState
* exec
, PropertyName propertyName
, PropertySlot
& slot
)
357 JSFunction
* thisObject
= jsCast
<JSFunction
*>(object
);
358 if (thisObject
->isHostOrBuiltinFunction())
359 return Base::getOwnPropertySlot(thisObject
, exec
, propertyName
, slot
);
361 if (propertyName
== exec
->propertyNames().prototype
) {
364 PropertyOffset offset
= thisObject
->getDirectOffset(vm
, propertyName
, attributes
);
365 if (!isValidOffset(offset
)) {
366 JSObject
* prototype
= constructEmptyObject(exec
);
367 prototype
->putDirect(vm
, exec
->propertyNames().constructor
, thisObject
, DontEnum
);
368 thisObject
->putDirect(vm
, exec
->propertyNames().prototype
, prototype
, DontDelete
| DontEnum
);
369 offset
= thisObject
->getDirectOffset(vm
, exec
->propertyNames().prototype
, attributes
);
370 ASSERT(isValidOffset(offset
));
373 slot
.setValue(thisObject
, attributes
, thisObject
->getDirect(offset
), offset
);
376 if (propertyName
== exec
->propertyNames().arguments
) {
377 if (thisObject
->jsExecutable()->isStrictMode()) {
378 bool result
= Base::getOwnPropertySlot(thisObject
, exec
, propertyName
, slot
);
380 thisObject
->putDirectAccessor(exec
, propertyName
, thisObject
->globalObject()->throwTypeErrorGetterSetter(exec
->vm()), DontDelete
| DontEnum
| Accessor
);
381 result
= Base::getOwnPropertySlot(thisObject
, exec
, propertyName
, slot
);
386 slot
.setCacheableCustom(thisObject
, ReadOnly
| DontEnum
| DontDelete
, argumentsGetter
);
390 if (propertyName
== exec
->propertyNames().length
) {
391 slot
.setCacheableCustom(thisObject
, ReadOnly
| DontEnum
| DontDelete
, lengthGetter
);
395 if (propertyName
== exec
->propertyNames().name
) {
396 slot
.setCacheableCustom(thisObject
, ReadOnly
| DontEnum
| DontDelete
, nameGetter
);
400 if (propertyName
== exec
->propertyNames().caller
) {
401 if (thisObject
->jsExecutable()->isStrictMode()) {
402 bool result
= Base::getOwnPropertySlot(thisObject
, exec
, propertyName
, slot
);
404 thisObject
->putDirectAccessor(exec
, propertyName
, thisObject
->globalObject()->throwTypeErrorGetterSetter(exec
->vm()), DontDelete
| DontEnum
| Accessor
);
405 result
= Base::getOwnPropertySlot(thisObject
, exec
, propertyName
, slot
);
410 slot
.setCacheableCustom(thisObject
, ReadOnly
| DontEnum
| DontDelete
, callerGetter
);
414 return Base::getOwnPropertySlot(thisObject
, exec
, propertyName
, slot
);
417 void JSFunction::getOwnNonIndexPropertyNames(JSObject
* object
, ExecState
* exec
, PropertyNameArray
& propertyNames
, EnumerationMode mode
)
419 JSFunction
* thisObject
= jsCast
<JSFunction
*>(object
);
420 if (!thisObject
->isHostOrBuiltinFunction() && mode
.includeDontEnumProperties()) {
422 // Make sure prototype has been reified.
423 PropertySlot
slot(thisObject
);
424 thisObject
->methodTable(vm
)->getOwnPropertySlot(thisObject
, exec
, vm
.propertyNames
->prototype
, slot
);
426 propertyNames
.add(vm
.propertyNames
->arguments
);
427 propertyNames
.add(vm
.propertyNames
->caller
);
428 propertyNames
.add(vm
.propertyNames
->length
);
429 propertyNames
.add(vm
.propertyNames
->name
);
431 Base::getOwnNonIndexPropertyNames(thisObject
, exec
, propertyNames
, mode
);
434 void JSFunction::put(JSCell
* cell
, ExecState
* exec
, PropertyName propertyName
, JSValue value
, PutPropertySlot
& slot
)
436 JSFunction
* thisObject
= jsCast
<JSFunction
*>(cell
);
437 if (thisObject
->isHostOrBuiltinFunction()) {
438 Base::put(thisObject
, exec
, propertyName
, value
, slot
);
441 if (propertyName
== exec
->propertyNames().prototype
) {
442 // Make sure prototype has been reified, such that it can only be overwritten
443 // following the rules set out in ECMA-262 8.12.9.
444 PropertySlot
slot(thisObject
);
445 thisObject
->methodTable(exec
->vm())->getOwnPropertySlot(thisObject
, exec
, propertyName
, slot
);
446 if (thisObject
->m_rareData
)
447 thisObject
->m_rareData
->clear("Store to prototype property of a function");
448 // Don't allow this to be cached, since a [[Put]] must clear m_rareData.
449 PutPropertySlot
dontCache(thisObject
);
450 Base::put(thisObject
, exec
, propertyName
, value
, dontCache
);
453 if (thisObject
->jsExecutable()->isStrictMode() && (propertyName
== exec
->propertyNames().arguments
|| propertyName
== exec
->propertyNames().caller
)) {
454 // This will trigger the property to be reified, if this is not already the case!
455 bool okay
= thisObject
->hasProperty(exec
, propertyName
);
456 ASSERT_UNUSED(okay
, okay
);
457 Base::put(thisObject
, exec
, propertyName
, value
, slot
);
460 if (propertyName
== exec
->propertyNames().arguments
|| propertyName
== exec
->propertyNames().length
|| propertyName
== exec
->propertyNames().name
|| propertyName
== exec
->propertyNames().caller
) {
461 if (slot
.isStrictMode())
462 throwTypeError(exec
, StrictModeReadonlyPropertyWriteError
);
465 Base::put(thisObject
, exec
, propertyName
, value
, slot
);
468 bool JSFunction::deleteProperty(JSCell
* cell
, ExecState
* exec
, PropertyName propertyName
)
470 JSFunction
* thisObject
= jsCast
<JSFunction
*>(cell
);
471 // For non-host functions, don't let these properties by deleted - except by DefineOwnProperty.
472 if (!thisObject
->isHostOrBuiltinFunction() && !exec
->vm().isInDefineOwnProperty()
473 && (propertyName
== exec
->propertyNames().arguments
474 || propertyName
== exec
->propertyNames().length
475 || propertyName
== exec
->propertyNames().name
476 || propertyName
== exec
->propertyNames().prototype
477 || propertyName
== exec
->propertyNames().caller
))
479 return Base::deleteProperty(thisObject
, exec
, propertyName
);
482 bool JSFunction::defineOwnProperty(JSObject
* object
, ExecState
* exec
, PropertyName propertyName
, const PropertyDescriptor
& descriptor
, bool throwException
)
484 JSFunction
* thisObject
= jsCast
<JSFunction
*>(object
);
485 if (thisObject
->isHostOrBuiltinFunction())
486 return Base::defineOwnProperty(object
, exec
, propertyName
, descriptor
, throwException
);
488 if (propertyName
== exec
->propertyNames().prototype
) {
489 // Make sure prototype has been reified, such that it can only be overwritten
490 // following the rules set out in ECMA-262 8.12.9.
491 PropertySlot
slot(thisObject
);
492 thisObject
->methodTable(exec
->vm())->getOwnPropertySlot(thisObject
, exec
, propertyName
, slot
);
493 if (thisObject
->m_rareData
)
494 thisObject
->m_rareData
->clear("Store to prototype property of a function");
495 return Base::defineOwnProperty(object
, exec
, propertyName
, descriptor
, throwException
);
499 if (propertyName
== exec
->propertyNames().arguments
) {
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
);
506 valueCheck
= !descriptor
.value() || sameValue(exec
, descriptor
.value(), retrieveArguments(exec
, thisObject
));
507 } else if (propertyName
== exec
->propertyNames().caller
) {
508 if (thisObject
->jsExecutable()->isStrictMode()) {
509 PropertySlot
slot(thisObject
);
510 if (!Base::getOwnPropertySlot(thisObject
, exec
, propertyName
, slot
))
511 thisObject
->putDirectAccessor(exec
, propertyName
, thisObject
->globalObject()->throwTypeErrorGetterSetter(exec
->vm()), DontDelete
| DontEnum
| Accessor
);
512 return Base::defineOwnProperty(object
, exec
, propertyName
, descriptor
, throwException
);
514 valueCheck
= !descriptor
.value() || sameValue(exec
, descriptor
.value(), retrieveCallerFunction(exec
, thisObject
));
515 } else if (propertyName
== exec
->propertyNames().length
)
516 valueCheck
= !descriptor
.value() || sameValue(exec
, descriptor
.value(), jsNumber(thisObject
->jsExecutable()->parameterCount()));
517 else if (propertyName
== exec
->propertyNames().name
)
518 valueCheck
= !descriptor
.value() || sameValue(exec
, descriptor
.value(), thisObject
->jsExecutable()->nameValue());
520 return Base::defineOwnProperty(object
, exec
, propertyName
, descriptor
, throwException
);
522 if (descriptor
.configurablePresent() && descriptor
.configurable()) {
524 exec
->vm().throwException(exec
, createTypeError(exec
, ASCIILiteral("Attempting to change configurable attribute of unconfigurable property.")));
527 if (descriptor
.enumerablePresent() && descriptor
.enumerable()) {
529 exec
->vm().throwException(exec
, createTypeError(exec
, ASCIILiteral("Attempting to change enumerable attribute of unconfigurable property.")));
532 if (descriptor
.isAccessorDescriptor()) {
534 exec
->vm().throwException(exec
, createTypeError(exec
, ASCIILiteral("Attempting to change access mechanism for an unconfigurable property.")));
537 if (descriptor
.writablePresent() && descriptor
.writable()) {
539 exec
->vm().throwException(exec
, createTypeError(exec
, ASCIILiteral("Attempting to change writable attribute of unconfigurable property.")));
544 exec
->vm().throwException(exec
, createTypeError(exec
, ASCIILiteral("Attempting to change value of a readonly property.")));
550 // ECMA 13.2.2 [[Construct]]
551 ConstructType
JSFunction::getConstructData(JSCell
* cell
, ConstructData
& constructData
)
553 JSFunction
* thisObject
= jsCast
<JSFunction
*>(cell
);
555 if (thisObject
->isBuiltinFunction())
556 return ConstructTypeNone
;
558 if (thisObject
->isHostFunction()) {
559 constructData
.native
.function
= thisObject
->nativeConstructor();
560 return ConstructTypeHost
;
562 constructData
.js
.functionExecutable
= thisObject
->jsExecutable();
563 constructData
.js
.scope
= thisObject
->scope();
564 return ConstructTypeJS
;
567 String
getCalculatedDisplayName(CallFrame
* callFrame
, JSObject
* object
)
569 if (JSFunction
* function
= jsDynamicCast
<JSFunction
*>(object
))
570 return function
->calculatedDisplayName(callFrame
);
571 if (InternalFunction
* function
= jsDynamicCast
<InternalFunction
*>(object
))
572 return function
->calculatedDisplayName(callFrame
);