08150c229f4152aa772e854509427f1c31af7544
[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-2009, 2015-2017 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 "AsyncGeneratorPrototype.h"
30 #include "BuiltinNames.h"
31 #include "ClonedArguments.h"
32 #include "CodeBlock.h"
33 #include "CommonIdentifiers.h"
34 #include "CallFrame.h"
35 #include "ExceptionHelpers.h"
36 #include "FunctionPrototype.h"
37 #include "GeneratorPrototype.h"
38 #include "GetterSetter.h"
39 #include "JSArray.h"
40 #include "JSBoundFunction.h"
41 #include "JSCInlines.h"
42 #include "JSFunctionInlines.h"
43 #include "JSGlobalObject.h"
44 #include "Interpreter.h"
45 #include "ObjectConstructor.h"
46 #include "ObjectPrototype.h"
47 #include "Parser.h"
48 #include "PropertyNameArray.h"
49 #include "StackVisitor.h"
50
51 namespace JSC {
52
53 EncodedJSValue JSC_HOST_CALL callHostFunctionAsConstructor(ExecState* exec)
54 {
55     VM& vm = exec->vm();
56     auto scope = DECLARE_THROW_SCOPE(vm);
57     return throwVMError(exec, scope, createNotAConstructorError(exec, exec->jsCallee()));
58 }
59
60 const ClassInfo JSFunction::s_info = { "Function", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSFunction) };
61
62 bool JSFunction::isHostFunctionNonInline() const
63 {
64     return isHostFunction();
65 }
66
67 JSFunction* JSFunction::create(VM& vm, FunctionExecutable* executable, JSScope* scope)
68 {
69     return create(vm, executable, scope, scope->globalObject(vm)->functionStructure());
70 }
71
72 JSFunction* JSFunction::create(VM& vm, FunctionExecutable* executable, JSScope* scope, Structure* structure)
73 {
74     JSFunction* result = createImpl(vm, executable, scope, structure);
75     executable->singletonFunction()->notifyWrite(vm, result, "Allocating a function");
76     return result;
77 }
78
79 JSFunction* JSFunction::create(VM& vm, JSGlobalObject* globalObject, int length, const String& name, NativeFunction nativeFunction, Intrinsic intrinsic, NativeFunction nativeConstructor, const DOMJIT::Signature* signature)
80 {
81     NativeExecutable* executable = vm.getHostFunction(nativeFunction, intrinsic, nativeConstructor, signature, name);
82     JSFunction* function = new (NotNull, allocateCell<JSFunction>(vm.heap)) JSFunction(vm, globalObject, globalObject->functionStructure());
83     // Can't do this during initialization because getHostFunction might do a GC allocation.
84     function->finishCreation(vm, executable, length, name);
85     return function;
86 }
87
88 JSFunction::JSFunction(VM& vm, JSGlobalObject* globalObject, Structure* structure)
89     : Base(vm, globalObject, structure)
90     , m_executable()
91 {
92 }
93
94 void JSFunction::finishCreation(VM& vm, NativeExecutable* executable, int length, const String& name)
95 {
96     Base::finishCreation(vm);
97     ASSERT(inherits(vm, info()));
98     m_executable.set(vm, this, executable);
99     // Some NativeExecutable functions, like JSBoundFunction, decide to lazily allocate their name string.
100     if (!name.isNull())
101         putDirect(vm, vm.propertyNames->name, jsString(&vm, name), ReadOnly | DontEnum);
102     putDirect(vm, vm.propertyNames->length, jsNumber(length), ReadOnly | DontEnum);
103 }
104
105 FunctionRareData* JSFunction::allocateRareData(VM& vm)
106 {
107     ASSERT(!m_rareData);
108     FunctionRareData* rareData = FunctionRareData::create(vm);
109
110     // A DFG compilation thread may be trying to read the rare data
111     // We want to ensure that it sees it properly allocated
112     WTF::storeStoreFence();
113
114     m_rareData.set(vm, this, rareData);
115     return m_rareData.get();
116 }
117
118 FunctionRareData* JSFunction::allocateAndInitializeRareData(ExecState* exec, size_t inlineCapacity)
119 {
120     ASSERT(!m_rareData);
121     VM& vm = exec->vm();
122     JSObject* prototype = jsDynamicCast<JSObject*>(vm, get(exec, vm.propertyNames->prototype));
123     JSGlobalObject* globalObject = this->globalObject(vm);
124     if (!prototype)
125         prototype = globalObject->objectPrototype();
126     FunctionRareData* rareData = FunctionRareData::create(vm);
127     rareData->initializeObjectAllocationProfile(vm, globalObject, prototype, inlineCapacity);
128
129     // A DFG compilation thread may be trying to read the rare data
130     // We want to ensure that it sees it properly allocated
131     WTF::storeStoreFence();
132
133     m_rareData.set(vm, this, rareData);
134     return m_rareData.get();
135 }
136
137 FunctionRareData* JSFunction::initializeRareData(ExecState* exec, size_t inlineCapacity)
138 {
139     ASSERT(!!m_rareData);
140     VM& vm = exec->vm();
141     JSObject* prototype = jsDynamicCast<JSObject*>(vm, get(exec, vm.propertyNames->prototype));
142     JSGlobalObject* globalObject = this->globalObject(vm);
143     if (!prototype)
144         prototype = globalObject->objectPrototype();
145     m_rareData->initializeObjectAllocationProfile(vm, globalObject, prototype, inlineCapacity);
146     return m_rareData.get();
147 }
148
149 String JSFunction::name(VM& vm)
150 {
151     if (isHostFunction()) {
152         NativeExecutable* executable = jsCast<NativeExecutable*>(this->executable());
153         return executable->name();
154     }
155     const Identifier identifier = jsExecutable()->name();
156     if (identifier == vm.propertyNames->builtinNames().starDefaultPrivateName())
157         return emptyString();
158     return identifier.string();
159 }
160
161 String JSFunction::displayName(VM& vm)
162 {
163     JSValue displayName = getDirect(vm, vm.propertyNames->displayName);
164     
165     if (displayName && isJSString(displayName))
166         return asString(displayName)->tryGetValue();
167     
168     return String();
169 }
170
171 const String JSFunction::calculatedDisplayName(VM& vm)
172 {
173     const String explicitName = displayName(vm);
174     
175     if (!explicitName.isEmpty())
176         return explicitName;
177     
178     const String actualName = name(vm);
179     if (!actualName.isEmpty() || isHostOrBuiltinFunction())
180         return actualName;
181     
182     return jsExecutable()->inferredName().string();
183 }
184
185 const SourceCode* JSFunction::sourceCode() const
186 {
187     if (isHostOrBuiltinFunction())
188         return 0;
189     return &jsExecutable()->source();
190 }
191     
192 void JSFunction::visitChildren(JSCell* cell, SlotVisitor& visitor)
193 {
194     JSFunction* thisObject = jsCast<JSFunction*>(cell);
195     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
196     Base::visitChildren(thisObject, visitor);
197
198     visitor.append(thisObject->m_executable);
199     visitor.append(thisObject->m_rareData);
200 }
201
202 CallType JSFunction::getCallData(JSCell* cell, CallData& callData)
203 {
204     JSFunction* thisObject = jsCast<JSFunction*>(cell);
205     if (thisObject->isHostFunction()) {
206         callData.native.function = thisObject->nativeFunction();
207         return CallType::Host;
208     }
209     callData.js.functionExecutable = thisObject->jsExecutable();
210     callData.js.scope = thisObject->scope();
211     return CallType::JS;
212 }
213
214 class RetrieveArgumentsFunctor {
215 public:
216     RetrieveArgumentsFunctor(JSFunction* functionObj)
217         : m_targetCallee(functionObj)
218         , m_result(jsNull())
219     {
220     }
221
222     JSValue result() const { return m_result; }
223
224     StackVisitor::Status operator()(StackVisitor& visitor) const
225     {
226         if (!visitor->callee().isCell())
227             return StackVisitor::Continue;
228
229         JSCell* callee = visitor->callee().asCell();
230         if (callee != m_targetCallee)
231             return StackVisitor::Continue;
232
233         m_result = JSValue(visitor->createArguments());
234         return StackVisitor::Done;
235     }
236
237 private:
238     JSObject* m_targetCallee;
239     mutable JSValue m_result;
240 };
241
242 static JSValue retrieveArguments(ExecState* exec, JSFunction* functionObj)
243 {
244     RetrieveArgumentsFunctor functor(functionObj);
245     exec->iterate(functor);
246     return functor.result();
247 }
248
249 EncodedJSValue JSFunction::argumentsGetter(ExecState* exec, EncodedJSValue thisValue, PropertyName)
250 {
251     JSFunction* thisObj = jsCast<JSFunction*>(JSValue::decode(thisValue));
252     ASSERT(!thisObj->isHostFunction());
253
254     return JSValue::encode(retrieveArguments(exec, thisObj));
255 }
256
257 class RetrieveCallerFunctionFunctor {
258 public:
259     RetrieveCallerFunctionFunctor(JSFunction* functionObj)
260         : m_targetCallee(functionObj)
261         , m_hasFoundFrame(false)
262         , m_hasSkippedToCallerFrame(false)
263         , m_result(jsNull())
264     {
265     }
266
267     JSValue result() const { return m_result; }
268
269     StackVisitor::Status operator()(StackVisitor& visitor) const
270     {
271         if (!visitor->callee().isCell())
272             return StackVisitor::Continue;
273
274         JSCell* callee = visitor->callee().asCell();
275
276         if (callee && callee->inherits(*callee->vm(), 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     mutable bool m_hasFoundFrame;
296     mutable bool m_hasSkippedToCallerFrame;
297     mutable 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, EncodedJSValue thisValue, PropertyName)
308 {
309     VM& vm = exec->vm();
310     auto scope = DECLARE_THROW_SCOPE(vm);
311
312     JSFunction* thisObj = jsCast<JSFunction*>(JSValue::decode(thisValue));
313     ASSERT(!thisObj->isHostFunction());
314     JSValue caller = retrieveCallerFunction(exec, thisObj);
315
316     // See ES5.1 15.3.5.4 - Function.caller may not be used to retrieve a strict caller.
317     if (!caller.isObject() || !asObject(caller)->inherits(vm, JSFunction::info())) {
318         // It isn't a JSFunction, but if it is a JSCallee from a program or eval call or an internal constructor, return null.
319         if (jsDynamicCast<JSCallee*>(vm, caller) || jsDynamicCast<InternalFunction*>(vm, caller))
320             return JSValue::encode(jsNull());
321         return JSValue::encode(caller);
322     }
323     JSFunction* function = jsCast<JSFunction*>(caller);
324
325     // Firefox returns null for native code callers, so we match that behavior.
326     if (function->isHostOrBuiltinFunction())
327         return JSValue::encode(jsNull());
328     if (!function->jsExecutable()->isStrictMode())
329         return JSValue::encode(caller);
330     return JSValue::encode(throwTypeError(exec, scope, ASCIILiteral("Function.caller used to retrieve strict caller")));
331 }
332
333 bool JSFunction::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
334 {
335     VM& vm = exec->vm();
336     JSFunction* thisObject = jsCast<JSFunction*>(object);
337     if (thisObject->isHostOrBuiltinFunction()) {
338         thisObject->reifyLazyPropertyForHostOrBuiltinIfNeeded(vm, exec, propertyName);
339         return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
340     }
341
342     if (propertyName == vm.propertyNames->prototype && thisObject->jsExecutable()->hasPrototypeProperty() && !thisObject->jsExecutable()->isClassConstructorFunction()) {
343         unsigned attributes;
344         PropertyOffset offset = thisObject->getDirectOffset(vm, propertyName, attributes);
345         if (!isValidOffset(offset)) {
346             JSObject* prototype = nullptr;
347             if (isGeneratorWrapperParseMode(thisObject->jsExecutable()->parseMode())) {
348                 // Unlike function instances, the object that is the value of the a GeneratorFunction's prototype
349                 // property does not have a constructor property whose value is the GeneratorFunction instance.
350                 // https://tc39.github.io/ecma262/#sec-generatorfunction-instances-prototype
351                 prototype = constructEmptyObject(exec, thisObject->globalObject(vm)->generatorPrototype());
352             } else if (thisObject->jsExecutable()->parseMode() == SourceParseMode::AsyncGeneratorWrapperFunctionMode)
353                 prototype = constructEmptyObject(exec, thisObject->globalObject(vm)->asyncGeneratorPrototype());
354             else {
355                 prototype = constructEmptyObject(exec);
356                 prototype->putDirect(vm, vm.propertyNames->constructor, thisObject, DontEnum);
357             }
358
359             thisObject->putDirect(vm, vm.propertyNames->prototype, prototype, DontDelete | DontEnum);
360             offset = thisObject->getDirectOffset(vm, vm.propertyNames->prototype, attributes);
361             ASSERT(isValidOffset(offset));
362         }
363
364         slot.setValue(thisObject, attributes, thisObject->getDirect(offset), offset);
365     }
366
367     if (propertyName == exec->propertyNames().arguments) {
368         if (!thisObject->jsExecutable()->hasCallerAndArgumentsProperties())
369             return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
370         
371         slot.setCacheableCustom(thisObject, ReadOnly | DontEnum | DontDelete, argumentsGetter);
372         return true;
373     }
374
375     if (propertyName == exec->propertyNames().caller) {
376         if (!thisObject->jsExecutable()->hasCallerAndArgumentsProperties())
377             return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
378
379         slot.setCacheableCustom(thisObject, ReadOnly | DontEnum | DontDelete, callerGetter);
380         return true;
381     }
382
383     thisObject->reifyLazyPropertyIfNeeded(vm, exec, propertyName);
384
385     return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
386 }
387
388 void JSFunction::getOwnNonIndexPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
389 {
390     JSFunction* thisObject = jsCast<JSFunction*>(object);
391     VM& vm = exec->vm();
392     if (mode.includeDontEnumProperties()) {
393         if (!thisObject->isHostOrBuiltinFunction()) {
394             // Make sure prototype has been reified.
395             PropertySlot slot(thisObject, PropertySlot::InternalMethodType::VMInquiry);
396             thisObject->methodTable(vm)->getOwnPropertySlot(thisObject, exec, vm.propertyNames->prototype, slot);
397
398             if (thisObject->jsExecutable()->hasCallerAndArgumentsProperties()) {
399                 propertyNames.add(vm.propertyNames->arguments);
400                 propertyNames.add(vm.propertyNames->caller);
401             }
402             if (!thisObject->hasReifiedLength())
403                 propertyNames.add(vm.propertyNames->length);
404             if (!thisObject->hasReifiedName())
405                 propertyNames.add(vm.propertyNames->name);
406         } else {
407             if (thisObject->isBuiltinFunction() && !thisObject->hasReifiedLength())
408                 propertyNames.add(vm.propertyNames->length);
409             if ((thisObject->isBuiltinFunction() || thisObject->inherits(vm, JSBoundFunction::info())) && !thisObject->hasReifiedName())
410                 propertyNames.add(vm.propertyNames->name);
411         }
412     }
413     Base::getOwnNonIndexPropertyNames(thisObject, exec, propertyNames, mode);
414 }
415
416 bool JSFunction::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
417 {
418     VM& vm = exec->vm();
419     auto scope = DECLARE_THROW_SCOPE(vm);
420
421     JSFunction* thisObject = jsCast<JSFunction*>(cell);
422
423     if (UNLIKELY(isThisValueAltered(slot, thisObject))) {
424         scope.release();
425         return ordinarySetSlow(exec, thisObject, propertyName, value, slot.thisValue(), slot.isStrictMode());
426     }
427
428     if (thisObject->isHostOrBuiltinFunction()) {
429         LazyPropertyType propType = thisObject->reifyLazyPropertyForHostOrBuiltinIfNeeded(vm, exec, propertyName);
430         if (propType == LazyPropertyType::IsLazyProperty)
431             slot.disableCaching();
432         scope.release();
433         return Base::put(thisObject, exec, propertyName, value, slot);
434     }
435
436     if (propertyName == vm.propertyNames->prototype) {
437         slot.disableCaching();
438         // Make sure prototype has been reified, such that it can only be overwritten
439         // following the rules set out in ECMA-262 8.12.9.
440         PropertySlot getSlot(thisObject, PropertySlot::InternalMethodType::VMInquiry);
441         thisObject->methodTable(vm)->getOwnPropertySlot(thisObject, exec, propertyName, getSlot);
442         if (thisObject->m_rareData)
443             thisObject->m_rareData->clear("Store to prototype property of a function");
444         scope.release();
445         return Base::put(thisObject, exec, propertyName, value, slot);
446     }
447
448     if (propertyName == vm.propertyNames->arguments || propertyName == vm.propertyNames->caller) {
449         slot.disableCaching();
450         if (!thisObject->jsExecutable()->hasCallerAndArgumentsProperties()) {
451             // This will trigger the property to be reified, if this is not already the case!
452             // FIXME: Investigate if the `hasProperty()` call is even needed, as in the `!hasCallerAndArgumentsProperties()` case,
453             // these properties are not lazy and should not need to be reified. (https://bugs.webkit.org/show_bug.cgi?id=163579)
454             bool okay = thisObject->hasProperty(exec, propertyName);
455             RETURN_IF_EXCEPTION(scope, false);
456             ASSERT_UNUSED(okay, okay);
457             scope.release();
458             return Base::put(thisObject, exec, propertyName, value, slot);
459         }
460         return typeError(exec, scope, slot.isStrictMode(), ASCIILiteral(ReadonlyPropertyWriteError));
461     }
462     LazyPropertyType propType = thisObject->reifyLazyPropertyIfNeeded(vm, exec, propertyName);
463     if (propType == LazyPropertyType::IsLazyProperty)
464         slot.disableCaching();
465     scope.release();
466     return Base::put(thisObject, exec, propertyName, value, slot);
467 }
468
469 bool JSFunction::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
470 {
471     VM& vm = exec->vm();
472     JSFunction* thisObject = jsCast<JSFunction*>(cell);
473     if (thisObject->isHostOrBuiltinFunction())
474         thisObject->reifyLazyPropertyForHostOrBuiltinIfNeeded(vm, exec, propertyName);
475     else if (vm.deletePropertyMode() != VM::DeletePropertyMode::IgnoreConfigurable) {
476         // For non-host functions, don't let these properties by deleted - except by DefineOwnProperty.
477         FunctionExecutable* executable = thisObject->jsExecutable();
478         
479         if (propertyName == exec->propertyNames().caller || propertyName == exec->propertyNames().arguments)
480             return !executable->hasCallerAndArgumentsProperties();
481
482         if (propertyName == exec->propertyNames().prototype && !executable->isArrowFunction())
483             return false;
484
485         thisObject->reifyLazyPropertyIfNeeded(vm, exec, propertyName);
486     }
487     
488     return Base::deleteProperty(thisObject, exec, propertyName);
489 }
490
491 bool JSFunction::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool throwException)
492 {
493     VM& vm = exec->vm();
494     auto scope = DECLARE_THROW_SCOPE(vm);
495
496     JSFunction* thisObject = jsCast<JSFunction*>(object);
497     if (thisObject->isHostOrBuiltinFunction()) {
498         thisObject->reifyLazyPropertyForHostOrBuiltinIfNeeded(vm, exec, propertyName);
499         scope.release();
500         return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
501     }
502
503     if (propertyName == vm.propertyNames->prototype) {
504         // Make sure prototype has been reified, such that it can only be overwritten
505         // following the rules set out in ECMA-262 8.12.9.
506         PropertySlot slot(thisObject, PropertySlot::InternalMethodType::VMInquiry);
507         thisObject->methodTable(vm)->getOwnPropertySlot(thisObject, exec, propertyName, slot);
508         if (thisObject->m_rareData)
509             thisObject->m_rareData->clear("Store to prototype property of a function");
510         scope.release();
511         return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
512     }
513
514     bool valueCheck;
515     if (propertyName == vm.propertyNames->arguments) {
516         if (!thisObject->jsExecutable()->hasCallerAndArgumentsProperties()) {
517             if (thisObject->jsExecutable()->isClass()) {
518                 thisObject->reifyLazyPropertyIfNeeded(vm, exec, propertyName);
519                 scope.release();
520                 return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
521             }
522             PropertySlot slot(thisObject, PropertySlot::InternalMethodType::VMInquiry);
523             if (!Base::getOwnPropertySlot(thisObject, exec, propertyName, slot))
524                 thisObject->putDirectAccessor(exec, propertyName, thisObject->globalObject(vm)->throwTypeErrorArgumentsCalleeAndCallerGetterSetter(), DontDelete | DontEnum | Accessor);
525             scope.release();
526             return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
527         }
528         valueCheck = !descriptor.value() || sameValue(exec, descriptor.value(), retrieveArguments(exec, thisObject));
529     } else if (propertyName == vm.propertyNames->caller) {
530         if (!thisObject->jsExecutable()->hasCallerAndArgumentsProperties()) {
531             if (thisObject->jsExecutable()->isClass()) {
532                 thisObject->reifyLazyPropertyIfNeeded(vm, exec, propertyName);
533                 scope.release();
534                 return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
535             }
536             PropertySlot slot(thisObject, PropertySlot::InternalMethodType::VMInquiry);
537             if (!Base::getOwnPropertySlot(thisObject, exec, propertyName, slot))
538                 thisObject->putDirectAccessor(exec, propertyName, thisObject->globalObject(vm)->throwTypeErrorArgumentsCalleeAndCallerGetterSetter(), DontDelete | DontEnum | Accessor);
539             scope.release();
540             return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
541         }
542         valueCheck = !descriptor.value() || sameValue(exec, descriptor.value(), retrieveCallerFunction(exec, thisObject));
543     } else {
544         thisObject->reifyLazyPropertyIfNeeded(vm, exec, propertyName);
545         scope.release();
546         return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
547     }
548      
549     if (descriptor.configurablePresent() && descriptor.configurable())
550         return typeError(exec, scope, throwException, ASCIILiteral(UnconfigurablePropertyChangeConfigurabilityError));
551     if (descriptor.enumerablePresent() && descriptor.enumerable())
552         return typeError(exec, scope, throwException, ASCIILiteral(UnconfigurablePropertyChangeEnumerabilityError));
553     if (descriptor.isAccessorDescriptor())
554         return typeError(exec, scope, throwException, ASCIILiteral(UnconfigurablePropertyChangeAccessMechanismError));
555     if (descriptor.writablePresent() && descriptor.writable())
556         return typeError(exec, scope, throwException, ASCIILiteral(UnconfigurablePropertyChangeWritabilityError));
557     if (!valueCheck)
558         return typeError(exec, scope, throwException, ASCIILiteral(ReadonlyPropertyChangeError));
559     return true;
560 }
561
562 // ECMA 13.2.2 [[Construct]]
563 ConstructType JSFunction::getConstructData(JSCell* cell, ConstructData& constructData)
564 {
565     JSFunction* thisObject = jsCast<JSFunction*>(cell);
566
567     if (thisObject->isHostFunction()) {
568         if (thisObject->nativeConstructor() == callHostFunctionAsConstructor)
569             return ConstructType::None;
570         constructData.native.function = thisObject->nativeConstructor();
571         return ConstructType::Host;
572     }
573
574     FunctionExecutable* functionExecutable = thisObject->jsExecutable();
575     if (functionExecutable->constructAbility() == ConstructAbility::CannotConstruct)
576         return ConstructType::None;
577
578     constructData.js.functionExecutable = functionExecutable;
579     constructData.js.scope = thisObject->scope();
580     return ConstructType::JS;
581 }
582
583 String getCalculatedDisplayName(VM& vm, JSObject* object)
584 {
585     if (JSFunction* function = jsDynamicCast<JSFunction*>(vm, object))
586         return function->calculatedDisplayName(vm);
587     if (InternalFunction* function = jsDynamicCast<InternalFunction*>(vm, object))
588         return function->calculatedDisplayName(vm);
589     return emptyString();
590 }
591
592 void JSFunction::setFunctionName(ExecState* exec, JSValue value)
593 {
594     VM& vm = exec->vm();
595     auto scope = DECLARE_THROW_SCOPE(vm);
596
597     // The "name" property may have been already been defined as part of a property list in an
598     // object literal (and therefore reified).
599     if (hasReifiedName())
600         return;
601
602     ASSERT(!isHostFunction());
603     ASSERT(jsExecutable()->ecmaName().isNull());
604     String name;
605     if (value.isSymbol()) {
606         SymbolImpl& uid = asSymbol(value)->privateName().uid();
607         if (uid.isNullSymbol())
608             name = emptyString();
609         else
610             name = makeString('[', String(&uid), ']');
611     } else {
612         JSString* jsStr = value.toString(exec);
613         RETURN_IF_EXCEPTION(scope, void());
614         name = jsStr->value(exec);
615         RETURN_IF_EXCEPTION(scope, void());
616     }
617     reifyName(vm, exec, name);
618 }
619
620 void JSFunction::reifyLength(VM& vm)
621 {
622     FunctionRareData* rareData = this->rareData(vm);
623
624     ASSERT(!hasReifiedLength());
625     ASSERT(!isHostFunction());
626     JSValue initialValue = jsNumber(jsExecutable()->parameterCount());
627     unsigned initialAttributes = DontEnum | ReadOnly;
628     const Identifier& identifier = vm.propertyNames->length;
629     putDirect(vm, identifier, initialValue, initialAttributes);
630
631     rareData->setHasReifiedLength();
632 }
633
634 void JSFunction::reifyName(VM& vm, ExecState* exec)
635 {
636     const Identifier& ecmaName = jsExecutable()->ecmaName();
637     String name;
638     // https://tc39.github.io/ecma262/#sec-exports-runtime-semantics-evaluation
639     // When the ident is "*default*", we need to set "default" for the ecma name.
640     // This "*default*" name is never shown to users.
641     if (ecmaName == exec->propertyNames().builtinNames().starDefaultPrivateName())
642         name = exec->propertyNames().defaultKeyword.string();
643     else
644         name = ecmaName.string();
645     reifyName(vm, exec, name);
646 }
647
648 void JSFunction::reifyName(VM& vm, ExecState* exec, String name)
649 {
650     FunctionRareData* rareData = this->rareData(vm);
651
652     ASSERT(!hasReifiedName());
653     ASSERT(!isHostFunction());
654     unsigned initialAttributes = DontEnum | ReadOnly;
655     const Identifier& propID = vm.propertyNames->name;
656
657     if (exec->lexicalGlobalObject()->needsSiteSpecificQuirks()) {
658         auto illegalCharMatcher = [] (UChar ch) -> bool {
659             return ch == ' ' || ch == '|';
660         };
661         if (name.find(illegalCharMatcher) != notFound)
662             name = String();
663     }
664     
665     if (jsExecutable()->isGetter())
666         name = makeString("get ", name);
667     else if (jsExecutable()->isSetter())
668         name = makeString("set ", name);
669
670     putDirect(vm, propID, jsString(exec, name), initialAttributes);
671     rareData->setHasReifiedName();
672 }
673
674 JSFunction::LazyPropertyType JSFunction::reifyLazyPropertyIfNeeded(VM& vm, ExecState* exec, PropertyName propertyName)
675 {
676     if (reifyLazyLengthIfNeeded(vm, exec, propertyName) == LazyPropertyType::IsLazyProperty)
677         return LazyPropertyType::IsLazyProperty;
678     if (propertyName == vm.propertyNames->name) {
679         if (!hasReifiedName())
680             reifyName(vm, exec);
681         return LazyPropertyType::IsLazyProperty;
682     }
683     return LazyPropertyType::NotLazyProperty;
684 }
685
686 JSFunction::LazyPropertyType JSFunction::reifyLazyPropertyForHostOrBuiltinIfNeeded(VM& vm, ExecState* exec, PropertyName propertyName)
687 {
688     ASSERT(isHostOrBuiltinFunction());
689     if (isBuiltinFunction()) {
690         if (reifyLazyLengthIfNeeded(vm, exec, propertyName) == LazyPropertyType::IsLazyProperty)
691             return LazyPropertyType::IsLazyProperty;
692     }
693     return reifyLazyBoundNameIfNeeded(vm, exec, propertyName);
694 }
695
696 JSFunction::LazyPropertyType JSFunction::reifyLazyLengthIfNeeded(VM& vm, ExecState*, PropertyName propertyName)
697 {
698     if (propertyName == vm.propertyNames->length) {
699         if (!hasReifiedLength())
700             reifyLength(vm);
701         return LazyPropertyType::IsLazyProperty;
702     }
703     return LazyPropertyType::NotLazyProperty;
704 }
705
706 JSFunction::LazyPropertyType JSFunction::reifyLazyBoundNameIfNeeded(VM& vm, ExecState* exec, PropertyName propertyName)
707 {
708     const Identifier& nameIdent = vm.propertyNames->name;
709     if (propertyName != nameIdent)
710         return LazyPropertyType::NotLazyProperty;
711
712     if (hasReifiedName())
713         return LazyPropertyType::IsLazyProperty;
714
715     if (isBuiltinFunction())
716         reifyName(vm, exec);
717     else if (this->inherits(vm, JSBoundFunction::info())) {
718         FunctionRareData* rareData = this->rareData(vm);
719         String name = makeString("bound ", static_cast<NativeExecutable*>(m_executable.get())->name());
720         unsigned initialAttributes = DontEnum | ReadOnly;
721         putDirect(vm, nameIdent, jsString(exec, name), initialAttributes);
722         rareData->setHasReifiedName();
723     }
724     return LazyPropertyType::IsLazyProperty;
725 }
726
727 } // namespace JSC