]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/JSFunction.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / 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 JSFunction* JSFunction::createBuiltinFunction(VM& vm, FunctionExecutable* executable, JSGlobalObject* globalObject, const String& name)
141 {
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);
145 return function;
146 }
147
148 FunctionRareData* JSFunction::allocateAndInitializeRareData(ExecState* exec, size_t inlineCapacity)
149 {
150 ASSERT(!m_rareData);
151 VM& vm = exec->vm();
152 JSObject* prototype = jsDynamicCast<JSObject*>(get(exec, vm.propertyNames->prototype));
153 if (!prototype)
154 prototype = globalObject()->objectPrototype();
155 FunctionRareData* rareData = FunctionRareData::create(vm, prototype, inlineCapacity);
156
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();
160
161 m_rareData.set(vm, this, rareData);
162 return m_rareData.get();
163 }
164
165 FunctionRareData* JSFunction::initializeRareData(ExecState* exec, size_t inlineCapacity)
166 {
167 ASSERT(!!m_rareData);
168 VM& vm = exec->vm();
169 JSObject* prototype = jsDynamicCast<JSObject*>(get(exec, vm.propertyNames->prototype));
170 if (!prototype)
171 prototype = globalObject()->objectPrototype();
172 m_rareData->initialize(globalObject()->vm(), prototype, inlineCapacity);
173 return m_rareData.get();
174 }
175
176 String JSFunction::name(ExecState* exec)
177 {
178 return get(exec, exec->vm().propertyNames->name).toWTFString(exec);
179 }
180
181 String JSFunction::displayName(ExecState* exec)
182 {
183 JSValue displayName = getDirect(exec->vm(), exec->vm().propertyNames->displayName);
184
185 if (displayName && isJSString(displayName))
186 return asString(displayName)->tryGetValue();
187
188 return String();
189 }
190
191 const String JSFunction::calculatedDisplayName(ExecState* exec)
192 {
193 const String explicitName = displayName(exec);
194
195 if (!explicitName.isEmpty())
196 return explicitName;
197
198 const String actualName = name(exec);
199 if (!actualName.isEmpty() || isHostOrBuiltinFunction())
200 return actualName;
201
202 return jsExecutable()->inferredName().string();
203 }
204
205 const SourceCode* JSFunction::sourceCode() const
206 {
207 if (isHostOrBuiltinFunction())
208 return 0;
209 return &jsExecutable()->source();
210 }
211
212 void JSFunction::visitChildren(JSCell* cell, SlotVisitor& visitor)
213 {
214 JSFunction* thisObject = jsCast<JSFunction*>(cell);
215 ASSERT_GC_OBJECT_INHERITS(thisObject, info());
216 Base::visitChildren(thisObject, visitor);
217
218 visitor.append(&thisObject->m_executable);
219 if (thisObject->m_rareData)
220 visitor.append(&thisObject->m_rareData);
221 }
222
223 CallType JSFunction::getCallData(JSCell* cell, CallData& callData)
224 {
225 JSFunction* thisObject = jsCast<JSFunction*>(cell);
226 if (thisObject->isHostFunction()) {
227 callData.native.function = thisObject->nativeFunction();
228 return CallTypeHost;
229 }
230 callData.js.functionExecutable = thisObject->jsExecutable();
231 callData.js.scope = thisObject->scope();
232 return CallTypeJS;
233 }
234
235 class RetrieveArgumentsFunctor {
236 public:
237 RetrieveArgumentsFunctor(JSFunction* functionObj)
238 : m_targetCallee(jsDynamicCast<JSObject*>(functionObj))
239 , m_result(jsNull())
240 {
241 }
242
243 JSValue result() const { return m_result; }
244
245 StackVisitor::Status operator()(StackVisitor& visitor)
246 {
247 JSObject* callee = visitor->callee();
248 if (callee != m_targetCallee)
249 return StackVisitor::Continue;
250
251 m_result = JSValue(visitor->createArguments());
252 return StackVisitor::Done;
253 }
254
255 private:
256 JSObject* m_targetCallee;
257 JSValue m_result;
258 };
259
260 static JSValue retrieveArguments(ExecState* exec, JSFunction* functionObj)
261 {
262 RetrieveArgumentsFunctor functor(functionObj);
263 exec->iterate(functor);
264 return functor.result();
265 }
266
267 EncodedJSValue JSFunction::argumentsGetter(ExecState* exec, JSObject* slotBase, EncodedJSValue, PropertyName)
268 {
269 JSFunction* thisObj = jsCast<JSFunction*>(slotBase);
270 ASSERT(!thisObj->isHostFunction());
271
272 return JSValue::encode(retrieveArguments(exec, thisObj));
273 }
274
275 class RetrieveCallerFunctionFunctor {
276 public:
277 RetrieveCallerFunctionFunctor(JSFunction* functionObj)
278 : m_targetCallee(jsDynamicCast<JSObject*>(functionObj))
279 , m_hasFoundFrame(false)
280 , m_hasSkippedToCallerFrame(false)
281 , m_result(jsNull())
282 {
283 }
284
285 JSValue result() const { return m_result; }
286
287 StackVisitor::Status operator()(StackVisitor& visitor)
288 {
289 JSObject* callee = visitor->callee();
290
291 if (callee && callee->inherits(JSBoundFunction::info()))
292 return StackVisitor::Continue;
293
294 if (!m_hasFoundFrame && (callee != m_targetCallee))
295 return StackVisitor::Continue;
296
297 m_hasFoundFrame = true;
298 if (!m_hasSkippedToCallerFrame) {
299 m_hasSkippedToCallerFrame = true;
300 return StackVisitor::Continue;
301 }
302
303 if (callee)
304 m_result = callee;
305 return StackVisitor::Done;
306 }
307
308 private:
309 JSObject* m_targetCallee;
310 bool m_hasFoundFrame;
311 bool m_hasSkippedToCallerFrame;
312 JSValue m_result;
313 };
314
315 static JSValue retrieveCallerFunction(ExecState* exec, JSFunction* functionObj)
316 {
317 RetrieveCallerFunctionFunctor functor(functionObj);
318 exec->iterate(functor);
319 return functor.result();
320 }
321
322 EncodedJSValue JSFunction::callerGetter(ExecState* exec, JSObject* slotBase, EncodedJSValue, PropertyName)
323 {
324 JSFunction* thisObj = jsCast<JSFunction*>(slotBase);
325 ASSERT(!thisObj->isHostFunction());
326 JSValue caller = retrieveCallerFunction(exec, thisObj);
327
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);
334 }
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")));
339 }
340
341 EncodedJSValue JSFunction::lengthGetter(ExecState*, JSObject* slotBase, EncodedJSValue, PropertyName)
342 {
343 JSFunction* thisObj = jsCast<JSFunction*>(slotBase);
344 ASSERT(!thisObj->isHostFunction());
345 return JSValue::encode(jsNumber(thisObj->jsExecutable()->parameterCount()));
346 }
347
348 EncodedJSValue JSFunction::nameGetter(ExecState*, JSObject* slotBase, EncodedJSValue, PropertyName)
349 {
350 JSFunction* thisObj = jsCast<JSFunction*>(slotBase);
351 ASSERT(!thisObj->isHostFunction());
352 return JSValue::encode(thisObj->jsExecutable()->nameValue());
353 }
354
355 bool JSFunction::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
356 {
357 JSFunction* thisObject = jsCast<JSFunction*>(object);
358 if (thisObject->isHostOrBuiltinFunction())
359 return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
360
361 if (propertyName == exec->propertyNames().prototype) {
362 VM& vm = exec->vm();
363 unsigned attributes;
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));
371 }
372
373 slot.setValue(thisObject, attributes, thisObject->getDirect(offset), offset);
374 }
375
376 if (propertyName == exec->propertyNames().arguments) {
377 if (thisObject->jsExecutable()->isStrictMode()) {
378 bool result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
379 if (!result) {
380 thisObject->putDirectAccessor(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec->vm()), DontDelete | DontEnum | Accessor);
381 result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
382 ASSERT(result);
383 }
384 return result;
385 }
386 slot.setCacheableCustom(thisObject, ReadOnly | DontEnum | DontDelete, argumentsGetter);
387 return true;
388 }
389
390 if (propertyName == exec->propertyNames().length) {
391 slot.setCacheableCustom(thisObject, ReadOnly | DontEnum | DontDelete, lengthGetter);
392 return true;
393 }
394
395 if (propertyName == exec->propertyNames().name) {
396 slot.setCacheableCustom(thisObject, ReadOnly | DontEnum | DontDelete, nameGetter);
397 return true;
398 }
399
400 if (propertyName == exec->propertyNames().caller) {
401 if (thisObject->jsExecutable()->isStrictMode()) {
402 bool result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
403 if (!result) {
404 thisObject->putDirectAccessor(exec, propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec->vm()), DontDelete | DontEnum | Accessor);
405 result = Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
406 ASSERT(result);
407 }
408 return result;
409 }
410 slot.setCacheableCustom(thisObject, ReadOnly | DontEnum | DontDelete, callerGetter);
411 return true;
412 }
413
414 return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
415 }
416
417 void JSFunction::getOwnNonIndexPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
418 {
419 JSFunction* thisObject = jsCast<JSFunction*>(object);
420 if (!thisObject->isHostOrBuiltinFunction() && mode.includeDontEnumProperties()) {
421 VM& vm = exec->vm();
422 // Make sure prototype has been reified.
423 PropertySlot slot(thisObject);
424 thisObject->methodTable(vm)->getOwnPropertySlot(thisObject, exec, vm.propertyNames->prototype, slot);
425
426 propertyNames.add(vm.propertyNames->arguments);
427 propertyNames.add(vm.propertyNames->caller);
428 propertyNames.add(vm.propertyNames->length);
429 propertyNames.add(vm.propertyNames->name);
430 }
431 Base::getOwnNonIndexPropertyNames(thisObject, exec, propertyNames, mode);
432 }
433
434 void JSFunction::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
435 {
436 JSFunction* thisObject = jsCast<JSFunction*>(cell);
437 if (thisObject->isHostOrBuiltinFunction()) {
438 Base::put(thisObject, exec, propertyName, value, slot);
439 return;
440 }
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);
451 return;
452 }
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);
458 return;
459 }
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);
463 return;
464 }
465 Base::put(thisObject, exec, propertyName, value, slot);
466 }
467
468 bool JSFunction::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
469 {
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))
478 return false;
479 return Base::deleteProperty(thisObject, exec, propertyName);
480 }
481
482 bool JSFunction::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool throwException)
483 {
484 JSFunction* thisObject = jsCast<JSFunction*>(object);
485 if (thisObject->isHostOrBuiltinFunction())
486 return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
487
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);
496 }
497
498 bool valueCheck;
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);
505 }
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);
513 }
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());
519 else
520 return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
521
522 if (descriptor.configurablePresent() && descriptor.configurable()) {
523 if (throwException)
524 exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Attempting to change configurable attribute of unconfigurable property.")));
525 return false;
526 }
527 if (descriptor.enumerablePresent() && descriptor.enumerable()) {
528 if (throwException)
529 exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Attempting to change enumerable attribute of unconfigurable property.")));
530 return false;
531 }
532 if (descriptor.isAccessorDescriptor()) {
533 if (throwException)
534 exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Attempting to change access mechanism for an unconfigurable property.")));
535 return false;
536 }
537 if (descriptor.writablePresent() && descriptor.writable()) {
538 if (throwException)
539 exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Attempting to change writable attribute of unconfigurable property.")));
540 return false;
541 }
542 if (!valueCheck) {
543 if (throwException)
544 exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Attempting to change value of a readonly property.")));
545 return false;
546 }
547 return true;
548 }
549
550 // ECMA 13.2.2 [[Construct]]
551 ConstructType JSFunction::getConstructData(JSCell* cell, ConstructData& constructData)
552 {
553 JSFunction* thisObject = jsCast<JSFunction*>(cell);
554
555 if (thisObject->isBuiltinFunction())
556 return ConstructTypeNone;
557
558 if (thisObject->isHostFunction()) {
559 constructData.native.function = thisObject->nativeConstructor();
560 return ConstructTypeHost;
561 }
562 constructData.js.functionExecutable = thisObject->jsExecutable();
563 constructData.js.scope = thisObject->scope();
564 return ConstructTypeJS;
565 }
566
567 String getCalculatedDisplayName(CallFrame* callFrame, JSObject* object)
568 {
569 if (JSFunction* function = jsDynamicCast<JSFunction*>(object))
570 return function->calculatedDisplayName(callFrame);
571 if (InternalFunction* function = jsDynamicCast<InternalFunction*>(object))
572 return function->calculatedDisplayName(callFrame);
573 return "";
574 }
575
576 } // namespace JSC