+ JSFunction* thisObject = jsCast<JSFunction*>(object);
+ if (thisObject->isHostFunction())
+ return Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
+
+ if (propertyName == exec->propertyNames().prototype) {
+ PropertySlot slot;
+ thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, propertyName, slot);
+ return Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
+ }
+
+ if (propertyName == exec->propertyNames().arguments) {
+ if (thisObject->jsExecutable()->isStrictMode()) {
+ bool result = Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
+ if (!result) {
+ thisObject->putDirectAccessor(exec->globalData(), propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor);
+ result = Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
+ ASSERT(result);
+ }
+ return result;
+ }
+ descriptor.setDescriptor(exec->interpreter()->retrieveArgumentsFromVMCode(exec, thisObject), ReadOnly | DontEnum | DontDelete);
+ return true;
+ }
+
+ if (propertyName == exec->propertyNames().length) {
+ descriptor.setDescriptor(jsNumber(thisObject->jsExecutable()->parameterCount()), ReadOnly | DontEnum | DontDelete);
+ return true;
+ }
+
+ if (propertyName == exec->propertyNames().caller) {
+ if (thisObject->jsExecutable()->isStrictMode()) {
+ bool result = Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
+ if (!result) {
+ thisObject->putDirectAccessor(exec->globalData(), propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor);
+ result = Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
+ ASSERT(result);
+ }
+ return result;
+ }
+ descriptor.setDescriptor(exec->interpreter()->retrieveCallerFromVMCode(exec, thisObject), ReadOnly | DontEnum | DontDelete);
+ return true;
+ }
+
+ return Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor);
+}
+
+void JSFunction::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+{
+ JSFunction* thisObject = jsCast<JSFunction*>(object);
+ if (!thisObject->isHostFunction() && (mode == IncludeDontEnumProperties)) {
+ // Make sure prototype has been reified.
+ PropertySlot slot;
+ thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, exec->propertyNames().prototype, slot);
+
+ propertyNames.add(exec->propertyNames().arguments);
+ propertyNames.add(exec->propertyNames().caller);
+ propertyNames.add(exec->propertyNames().length);
+ }
+ Base::getOwnPropertyNames(thisObject, exec, propertyNames, mode);
+}
+
+void JSFunction::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
+{
+ JSFunction* thisObject = jsCast<JSFunction*>(cell);
+ if (thisObject->isHostFunction()) {
+ Base::put(thisObject, exec, propertyName, value, slot);
+ return;
+ }
+ if (propertyName == exec->propertyNames().prototype) {
+ // Make sure prototype has been reified, such that it can only be overwritten
+ // following the rules set out in ECMA-262 8.12.9.
+ PropertySlot slot;
+ thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, propertyName, slot);
+ }
+ if (thisObject->jsExecutable()->isStrictMode() && (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().caller)) {
+ // This will trigger the property to be reified, if this is not already the case!
+ bool okay = thisObject->hasProperty(exec, propertyName);
+ ASSERT_UNUSED(okay, okay);
+ Base::put(thisObject, exec, propertyName, value, slot);