source: webkit/trunk/JavaScriptCore/runtime/JSFunction.cpp@ 61623

Last change on this file since 61623 was 60762, checked in by [email protected], 15 years ago

Bug 40214 - Clean up error construction / throwing in JSC.

Reviewed by Sam Weinig.

The one egregious insanity here is that creating an error requires
a VM-entry-esqe-host call (the string argument is wrapped as a JS
object & pushed on the RegisterFile, then unwrapped back to a
UString). Changing this also means you only require a global
object, not an ExecState, to create an error.

The methods to create error objects are also parameterized
requiring a switch on the type, which can be made cleaner and
faster by moving to a separate method per error type. Code to add
divot information to error had been duplicated, and is coalesced
back into a single function.

Convenience methods added to create & throw type & syntax error
with a default error message, since this is a common case.

Also, errors are currently thrown either using
"throwError(exec, error)" or "exec->setException(error)" - unify
on the former, since this is more commonly used. Add
"throwVMError(exec, error)" equivalents, as a convenience for
cases where the result was being wrapped in "JSValue::encode(...)".

JavaScriptCore:

  • API/JSCallbackConstructor.cpp:

(JSC::constructJSCallback):

  • API/JSCallbackFunction.cpp:

(JSC::JSCallbackFunction::call):

  • API/JSCallbackObjectFunctions.h:

(JSC::::getOwnPropertySlot):
(JSC::::put):
(JSC::::deleteProperty):
(JSC::::construct):
(JSC::::hasInstance):
(JSC::::call):
(JSC::::toNumber):
(JSC::::toString):
(JSC::::staticValueGetter):
(JSC::::staticFunctionGetter):
(JSC::::callbackGetter):

  • API/JSObjectRef.cpp:

(JSObjectMakeError):

(JSC::BytecodeGenerator::emitNewError):
(JSC::BytecodeGenerator::emitThrowExpressionTooDeepException):

  • bytecompiler/BytecodeGenerator.h:
  • bytecompiler/NodesCodegen.cpp:

(JSC::ThrowableExpressionData::emitThrowError):
(JSC::RegExpNode::emitBytecode):
(JSC::PostfixErrorNode::emitBytecode):
(JSC::PrefixErrorNode::emitBytecode):
(JSC::AssignErrorNode::emitBytecode):
(JSC::ForInNode::emitBytecode):
(JSC::ContinueNode::emitBytecode):
(JSC::BreakNode::emitBytecode):
(JSC::ReturnNode::emitBytecode):
(JSC::LabelNode::emitBytecode):

  • interpreter/CallFrame.h:
  • interpreter/Interpreter.cpp:

(JSC::Interpreter::throwException):
(JSC::Interpreter::privateExecute):

  • jit/JITStubs.cpp:

(JSC::DEFINE_STUB_FUNCTION):

  • jsc.cpp:

(functionRun):
(functionLoad):
(functionCheckSyntax):

  • parser/Nodes.h:
  • runtime/ArrayConstructor.cpp:

(JSC::constructArrayWithSizeQuirk):

  • runtime/ArrayPrototype.cpp:

(JSC::arrayProtoFuncToString):
(JSC::arrayProtoFuncToLocaleString):
(JSC::arrayProtoFuncJoin):
(JSC::arrayProtoFuncFilter):
(JSC::arrayProtoFuncMap):
(JSC::arrayProtoFuncEvery):
(JSC::arrayProtoFuncForEach):
(JSC::arrayProtoFuncSome):
(JSC::arrayProtoFuncReduce):
(JSC::arrayProtoFuncReduceRight):

  • runtime/BooleanPrototype.cpp:

(JSC::booleanProtoFuncToString):
(JSC::booleanProtoFuncValueOf):

  • runtime/DatePrototype.cpp:

(JSC::dateProtoFuncToString):
(JSC::dateProtoFuncToUTCString):
(JSC::dateProtoFuncToISOString):
(JSC::dateProtoFuncToDateString):
(JSC::dateProtoFuncToTimeString):
(JSC::dateProtoFuncToLocaleString):
(JSC::dateProtoFuncToLocaleDateString):
(JSC::dateProtoFuncToLocaleTimeString):
(JSC::dateProtoFuncGetTime):
(JSC::dateProtoFuncGetFullYear):
(JSC::dateProtoFuncGetUTCFullYear):
(JSC::dateProtoFuncToGMTString):
(JSC::dateProtoFuncGetMonth):
(JSC::dateProtoFuncGetUTCMonth):
(JSC::dateProtoFuncGetDate):
(JSC::dateProtoFuncGetUTCDate):
(JSC::dateProtoFuncGetDay):
(JSC::dateProtoFuncGetUTCDay):
(JSC::dateProtoFuncGetHours):
(JSC::dateProtoFuncGetUTCHours):
(JSC::dateProtoFuncGetMinutes):
(JSC::dateProtoFuncGetUTCMinutes):
(JSC::dateProtoFuncGetSeconds):
(JSC::dateProtoFuncGetUTCSeconds):
(JSC::dateProtoFuncGetMilliSeconds):
(JSC::dateProtoFuncGetUTCMilliseconds):
(JSC::dateProtoFuncGetTimezoneOffset):
(JSC::dateProtoFuncSetTime):
(JSC::setNewValueFromTimeArgs):
(JSC::setNewValueFromDateArgs):
(JSC::dateProtoFuncSetMilliSeconds):
(JSC::dateProtoFuncSetUTCMilliseconds):
(JSC::dateProtoFuncSetSeconds):
(JSC::dateProtoFuncSetUTCSeconds):
(JSC::dateProtoFuncSetMinutes):
(JSC::dateProtoFuncSetUTCMinutes):
(JSC::dateProtoFuncSetHours):
(JSC::dateProtoFuncSetUTCHours):
(JSC::dateProtoFuncSetDate):
(JSC::dateProtoFuncSetUTCDate):
(JSC::dateProtoFuncSetMonth):
(JSC::dateProtoFuncSetUTCMonth):
(JSC::dateProtoFuncSetFullYear):
(JSC::dateProtoFuncSetUTCFullYear):
(JSC::dateProtoFuncSetYear):
(JSC::dateProtoFuncGetYear):
(JSC::dateProtoFuncToJSON):

  • runtime/Error.cpp:

(JSC::createError):
(JSC::createEvalError):
(JSC::createRangeError):
(JSC::createReferenceError):
(JSC::createSyntaxError):
(JSC::createTypeError):
(JSC::createURIError):
(JSC::addErrorSourceInfo):
(JSC::addErrorDivotInfo):
(JSC::addErrorInfo):
(JSC::hasErrorInfo):
(JSC::throwError):
(JSC::throwTypeError):
(JSC::throwSyntaxError):

  • runtime/Error.h:

(JSC::throwVMError):
(JSC::throwVMTypeError):

  • runtime/ErrorConstructor.cpp:

(JSC::constructWithErrorConstructor):
(JSC::callErrorConstructor):

  • runtime/ErrorConstructor.h:
  • runtime/ErrorInstance.cpp:

(JSC::ErrorInstance::ErrorInstance):
(JSC::ErrorInstance::create):

  • runtime/ErrorInstance.h:
  • runtime/ErrorPrototype.cpp:

(JSC::ErrorPrototype::ErrorPrototype):

  • runtime/ExceptionHelpers.cpp:

(JSC::createStackOverflowError):
(JSC::createUndefinedVariableError):
(JSC::createInvalidParamError):
(JSC::createNotAConstructorError):
(JSC::createNotAFunctionError):
(JSC::createNotAnObjectError):
(JSC::throwOutOfMemoryError):

  • runtime/ExceptionHelpers.h:
  • runtime/Executable.cpp:

(JSC::EvalExecutable::compile):
(JSC::ProgramExecutable::checkSyntax):
(JSC::ProgramExecutable::compile):

  • runtime/FunctionConstructor.cpp:

(JSC::constructFunction):

  • runtime/FunctionPrototype.cpp:

(JSC::functionProtoFuncToString):
(JSC::functionProtoFuncApply):
(JSC::functionProtoFuncCall):

  • runtime/Identifier.cpp:

(JSC::Identifier::from):

  • runtime/Identifier.h:
  • runtime/JSArray.cpp:

(JSC::JSArray::put):

  • runtime/JSFunction.cpp:

(JSC::callHostFunctionAsConstructor):

  • runtime/JSGlobalObjectFunctions.cpp:

(JSC::encode):
(JSC::decode):
(JSC::globalFuncEval):

  • runtime/JSONObject.cpp:

(JSC::Stringifier::appendStringifiedValue):
(JSC::Walker::walk):
(JSC::JSONProtoFuncParse):
(JSC::JSONProtoFuncStringify):

  • runtime/JSObject.cpp:

(JSC::throwSetterError):
(JSC::JSObject::put):
(JSC::JSObject::putWithAttributes):
(JSC::JSObject::defaultValue):
(JSC::JSObject::hasInstance):
(JSC::JSObject::defineOwnProperty):

  • runtime/JSObject.h:
  • runtime/JSValue.cpp:

(JSC::JSValue::toObjectSlowCase):
(JSC::JSValue::synthesizeObject):
(JSC::JSValue::synthesizePrototype):

  • runtime/NativeErrorConstructor.cpp:

(JSC::constructWithNativeErrorConstructor):
(JSC::callNativeErrorConstructor):

  • runtime/NativeErrorConstructor.h:
  • runtime/NumberPrototype.cpp:

(JSC::numberProtoFuncToString):
(JSC::numberProtoFuncToLocaleString):
(JSC::numberProtoFuncValueOf):
(JSC::numberProtoFuncToFixed):
(JSC::numberProtoFuncToExponential):
(JSC::numberProtoFuncToPrecision):

  • runtime/ObjectConstructor.cpp:

(JSC::objectConstructorGetPrototypeOf):
(JSC::objectConstructorGetOwnPropertyDescriptor):
(JSC::objectConstructorGetOwnPropertyNames):
(JSC::objectConstructorKeys):
(JSC::toPropertyDescriptor):
(JSC::objectConstructorDefineProperty):
(JSC::objectConstructorDefineProperties):
(JSC::objectConstructorCreate):

  • runtime/ObjectPrototype.cpp:

(JSC::objectProtoFuncDefineGetter):
(JSC::objectProtoFuncDefineSetter):

  • runtime/RegExpConstructor.cpp:

(JSC::constructRegExp):

  • runtime/RegExpObject.cpp:

(JSC::RegExpObject::match):

  • runtime/RegExpPrototype.cpp:

(JSC::regExpProtoFuncTest):
(JSC::regExpProtoFuncExec):
(JSC::regExpProtoFuncCompile):
(JSC::regExpProtoFuncToString):

  • runtime/StringPrototype.cpp:

(JSC::stringProtoFuncToString):

WebCore:

  • WebCore.xcodeproj/project.pbxproj:
  • bindings/js/JSArrayBufferConstructor.h:

(WebCore::construct):

  • bindings/js/JSArrayBufferViewHelper.h:

(WebCore::setWebGLArrayHelper):

  • bindings/js/JSAudioConstructor.cpp:

(WebCore::constructAudio):

  • bindings/js/JSCanvasRenderingContext2DCustom.cpp:

(WebCore::JSCanvasRenderingContext2D::setFillColor):
(WebCore::JSCanvasRenderingContext2D::setStrokeColor):
(WebCore::JSCanvasRenderingContext2D::drawImage):
(WebCore::JSCanvasRenderingContext2D::drawImageFromRect):
(WebCore::JSCanvasRenderingContext2D::setShadow):
(WebCore::JSCanvasRenderingContext2D::createPattern):
(WebCore::JSCanvasRenderingContext2D::fillText):
(WebCore::JSCanvasRenderingContext2D::strokeText):

  • bindings/js/JSClipboardCustom.cpp:

(WebCore::JSClipboard::clearData):
(WebCore::JSClipboard::getData):
(WebCore::JSClipboard::setDragImage):

  • bindings/js/JSDOMBinding.cpp:

(WebCore::setDOMException):
(WebCore::toJSSequence):

  • bindings/js/JSDOMWrapper.cpp:

(WebCore::DOMObject::defineOwnProperty):

  • bindings/js/JSDesktopNotificationsCustom.cpp:

(WebCore::JSNotificationCenter::requestPermission):

  • bindings/js/JSEventSourceConstructor.cpp:

(WebCore::constructEventSource):

  • bindings/js/JSHTMLDocumentCustom.cpp:

(WebCore::JSHTMLDocument::open):

  • bindings/js/JSHTMLInputElementCustom.cpp:

(WebCore::JSHTMLInputElement::selectionStart):
(WebCore::JSHTMLInputElement::setSelectionStart):
(WebCore::JSHTMLInputElement::selectionEnd):
(WebCore::JSHTMLInputElement::setSelectionEnd):
(WebCore::JSHTMLInputElement::setSelectionRange):

  • bindings/js/JSImageConstructor.cpp:

(WebCore::constructImage):

  • bindings/js/JSJavaScriptCallFrameCustom.cpp:

(WebCore::JSJavaScriptCallFrame::evaluate):

  • bindings/js/JSMessageChannelConstructor.cpp:

(WebCore::JSMessageChannelConstructor::construct):

  • bindings/js/JSMessagePortCustom.cpp:

(WebCore::fillMessagePortArray):

  • bindings/js/JSOptionConstructor.cpp:

(WebCore::constructHTMLOptionElement):

  • bindings/js/JSSVGMatrixCustom.cpp:

(WebCore::JSSVGMatrix::multiply):

  • bindings/js/JSSharedWorkerConstructor.cpp:

(WebCore::constructSharedWorker):

  • bindings/js/JSWebGLRenderingContextCustom.cpp:

(WebCore::JSWebGLRenderingContext::bufferData):
(WebCore::JSWebGLRenderingContext::bufferSubData):
(WebCore::getObjectParameter):
(WebCore::JSWebGLRenderingContext::getFramebufferAttachmentParameter):
(WebCore::JSWebGLRenderingContext::getParameter):
(WebCore::JSWebGLRenderingContext::getProgramParameter):
(WebCore::JSWebGLRenderingContext::getShaderParameter):
(WebCore::JSWebGLRenderingContext::getUniform):
(WebCore::JSWebGLRenderingContext::texImage2D):
(WebCore::JSWebGLRenderingContext::texSubImage2D):
(WebCore::dataFunctionf):
(WebCore::dataFunctioni):
(WebCore::dataFunctionMatrix):

  • bindings/js/JSWebSocketConstructor.cpp:

(WebCore::constructWebSocket):

  • bindings/js/JSWebSocketCustom.cpp:

(WebCore::JSWebSocket::send):

  • bindings/js/JSWorkerConstructor.cpp:

(WebCore::constructWorker):

  • bindings/js/JSXMLHttpRequestConstructor.cpp:

(WebCore::constructXMLHttpRequest):

  • bindings/js/JSXMLHttpRequestCustom.cpp:

(WebCore::JSXMLHttpRequest::open):

  • bindings/js/SerializedScriptValue.cpp:

(WebCore::BaseWalker::throwStackOverflow):
(WebCore::BaseWalker::throwInterruptedException):
(WebCore::SerializingTreeWalker::startArray):
(WebCore::SerializingTreeWalker::startObject):

  • bindings/js/WorkerScriptController.cpp:

(WebCore::WorkerScriptController::setException):

  • bindings/scripts/CodeGeneratorJS.pm:
  • bridge/c/c_instance.cpp:

(JSC::Bindings::CInstance::moveGlobalExceptionToExecState):
(JSC::Bindings::CInstance::invokeMethod):
(JSC::Bindings::CInstance::invokeDefaultMethod):
(JSC::Bindings::CInstance::invokeConstruct):

  • bridge/jni/jsc/JNIBridgeJSC.cpp:

(JavaField::dispatchValueFromInstance):
(JavaField::dispatchSetValueToInstance):

  • bridge/jni/jsc/JavaInstanceJSC.cpp:

(JavaInstance::invokeMethod):

  • bridge/objc/objc_instance.mm:

(ObjcInstance::moveGlobalExceptionToExecState):
(ObjcInstance::invokeMethod):

  • bridge/objc/objc_runtime.mm:

(JSC::Bindings::ObjcField::valueFromInstance):
(JSC::Bindings::ObjcField::setValueToInstance):
(JSC::Bindings::ObjcArray::setValueAt):
(JSC::Bindings::ObjcArray::valueAt):
(JSC::Bindings::callObjCFallbackObject):

  • bridge/objc/objc_utility.h:
  • bridge/objc/objc_utility.mm:

(JSC::Bindings::throwError):

  • bridge/runtime_array.cpp:

(JSC::RuntimeArray::put):

  • bridge/runtime_method.cpp:

(JSC::callRuntimeMethod):

  • bridge/runtime_object.cpp:

(JSC::Bindings::RuntimeObject::throwInvalidAccessError):

WebKit/mac:

  • Plugins/Hosted/NetscapePluginInstanceProxy.mm:

(WebKit::NetscapePluginInstanceProxy::moveGlobalExceptionToExecState):

  • Plugins/Hosted/ProxyInstance.mm:

(WebKit::ProxyInstance::invokeMethod):

  • Property svn:eol-style set to native
File size: 10.5 KB
Line 
1/*
2 * Copyright (C) 1999-2002 Harri Porten ([email protected])
3 * Copyright (C) 2001 Peter Kelly ([email protected])
4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
5 * Copyright (C) 2007 Cameron Zwarich ([email protected])
6 * Copyright (C) 2007 Maks Orlovich
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 *
23 */
24
25#include "config.h"
26#include "JSFunction.h"
27
28#include "CodeBlock.h"
29#include "CommonIdentifiers.h"
30#include "CallFrame.h"
31#include "ExceptionHelpers.h"
32#include "FunctionPrototype.h"
33#include "JSGlobalObject.h"
34#include "JSNotAnObject.h"
35#include "Interpreter.h"
36#include "ObjectPrototype.h"
37#include "Parser.h"
38#include "PropertyNameArray.h"
39#include "ScopeChainMark.h"
40
41using namespace WTF;
42using namespace Unicode;
43
44namespace JSC {
45
46EncodedJSValue JSC_HOST_CALL callHostFunctionAsConstructor(ExecState* exec)
47{
48 CodeBlock* codeBlock = exec->callerFrame()->codeBlock();
49 unsigned vPCIndex = codeBlock->bytecodeOffset(exec, exec->returnPC());
50 return throwVMError(exec, createNotAConstructorError(exec, exec->callee(), vPCIndex, codeBlock));
51}
52
53ASSERT_CLASS_FITS_IN_CELL(JSFunction);
54
55const ClassInfo JSFunction::info = { "Function", 0, 0, 0 };
56
57bool JSFunction::isHostFunctionNonInline() const
58{
59 return isHostFunction();
60}
61
62JSFunction::JSFunction(NonNullPassRefPtr<Structure> structure)
63 : Base(structure)
64 , m_executable(adoptRef(new VPtrHackExecutable()))
65 , m_scopeChain(NoScopeChain())
66{
67}
68
69#if ENABLE(JIT)
70JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, PassRefPtr<NativeExecutable> thunk)
71 : Base(globalObject, structure)
72 , m_executable(thunk)
73 , m_scopeChain(globalObject->globalScopeChain())
74{
75 putDirect(exec->globalData().propertyNames->name, jsString(exec, name.isNull() ? "" : name.ustring()), DontDelete | ReadOnly | DontEnum);
76 putDirect(exec->propertyNames().length, jsNumber(exec, length), DontDelete | ReadOnly | DontEnum);
77}
78#endif
79
80JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, NativeFunction func)
81 : Base(globalObject, structure)
82#if ENABLE(JIT)
83 , m_executable(exec->globalData().getHostFunction(func))
84#endif
85 , m_scopeChain(globalObject->globalScopeChain())
86{
87 putDirect(exec->globalData().propertyNames->name, jsString(exec, name.isNull() ? "" : name.ustring()), DontDelete | ReadOnly | DontEnum);
88#if ENABLE(JIT)
89 putDirect(exec->propertyNames().length, jsNumber(exec, length), DontDelete | ReadOnly | DontEnum);
90#else
91 UNUSED_PARAM(length);
92 UNUSED_PARAM(func);
93 ASSERT_NOT_REACHED();
94#endif
95}
96
97JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<FunctionExecutable> executable, ScopeChainNode* scopeChainNode)
98 : Base(scopeChainNode->globalObject, scopeChainNode->globalObject->functionStructure())
99 , m_executable(executable)
100 , m_scopeChain(scopeChainNode)
101{
102 const Identifier& name = static_cast<FunctionExecutable*>(m_executable.get())->name();
103 putDirect(exec->globalData().propertyNames->name, jsString(exec, name.isNull() ? "" : name.ustring()), DontDelete | ReadOnly | DontEnum);
104}
105
106JSFunction::~JSFunction()
107{
108 ASSERT(vptr() == JSGlobalData::jsFunctionVPtr);
109
110 // JIT code for other functions may have had calls linked directly to the code for this function; these links
111 // are based on a check for the this pointer value for this JSFunction - which will no longer be valid once
112 // this memory is freed and may be reused (potentially for another, different JSFunction).
113 if (!isHostFunction()) {
114#if ENABLE(JIT_OPTIMIZE_CALL)
115 ASSERT(m_executable);
116 if (jsExecutable()->isGeneratedForCall())
117 jsExecutable()->generatedBytecodeForCall().unlinkCallers();
118 if (jsExecutable()->isGeneratedForConstruct())
119 jsExecutable()->generatedBytecodeForConstruct().unlinkCallers();
120#endif
121 }
122}
123
124const UString& JSFunction::name(ExecState* exec)
125{
126 return asString(getDirect(exec->globalData().propertyNames->name))->tryGetValue();
127}
128
129const UString JSFunction::displayName(ExecState* exec)
130{
131 JSValue displayName = getDirect(exec->globalData().propertyNames->displayName);
132
133 if (displayName && isJSString(&exec->globalData(), displayName))
134 return asString(displayName)->tryGetValue();
135
136 return UString::null();
137}
138
139const UString JSFunction::calculatedDisplayName(ExecState* exec)
140{
141 const UString explicitName = displayName(exec);
142
143 if (!explicitName.isEmpty())
144 return explicitName;
145
146 return name(exec);
147}
148
149void JSFunction::markChildren(MarkStack& markStack)
150{
151 Base::markChildren(markStack);
152 if (!isHostFunction()) {
153 jsExecutable()->markAggregate(markStack);
154 scope().markAggregate(markStack);
155 }
156}
157
158CallType JSFunction::getCallData(CallData& callData)
159{
160#if ENABLE(JIT)
161 if (isHostFunction()) {
162 callData.native.function = nativeFunction();
163 return CallTypeHost;
164 }
165#endif
166 callData.js.functionExecutable = jsExecutable();
167 callData.js.scopeChain = scope().node();
168 return CallTypeJS;
169}
170
171JSValue JSFunction::argumentsGetter(ExecState* exec, JSValue slotBase, const Identifier&)
172{
173 JSFunction* thisObj = asFunction(slotBase);
174 ASSERT(!thisObj->isHostFunction());
175 return exec->interpreter()->retrieveArguments(exec, thisObj);
176}
177
178JSValue JSFunction::callerGetter(ExecState* exec, JSValue slotBase, const Identifier&)
179{
180 JSFunction* thisObj = asFunction(slotBase);
181 ASSERT(!thisObj->isHostFunction());
182 return exec->interpreter()->retrieveCaller(exec, thisObj);
183}
184
185JSValue JSFunction::lengthGetter(ExecState* exec, JSValue slotBase, const Identifier&)
186{
187 JSFunction* thisObj = asFunction(slotBase);
188 ASSERT(!thisObj->isHostFunction());
189 return jsNumber(exec, thisObj->jsExecutable()->parameterCount());
190}
191
192bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
193{
194 if (isHostFunction())
195 return Base::getOwnPropertySlot(exec, propertyName, slot);
196
197 if (propertyName == exec->propertyNames().prototype) {
198 JSValue* location = getDirectLocation(propertyName);
199
200 if (!location) {
201 JSObject* prototype = new (exec) JSObject(scope().globalObject()->emptyObjectStructure());
202 prototype->putDirect(exec->propertyNames().constructor, this, DontEnum);
203 putDirect(exec->propertyNames().prototype, prototype, DontDelete);
204 location = getDirectLocation(propertyName);
205 }
206
207 slot.setValueSlot(this, location, offsetForLocation(location));
208 }
209
210 if (propertyName == exec->propertyNames().arguments) {
211 slot.setCacheableCustom(this, argumentsGetter);
212 return true;
213 }
214
215 if (propertyName == exec->propertyNames().length) {
216 slot.setCacheableCustom(this, lengthGetter);
217 return true;
218 }
219
220 if (propertyName == exec->propertyNames().caller) {
221 slot.setCacheableCustom(this, callerGetter);
222 return true;
223 }
224
225 return Base::getOwnPropertySlot(exec, propertyName, slot);
226}
227
228 bool JSFunction::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
229 {
230 if (isHostFunction())
231 return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
232
233 if (propertyName == exec->propertyNames().prototype) {
234 PropertySlot slot;
235 getOwnPropertySlot(exec, propertyName, slot);
236 return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
237 }
238
239 if (propertyName == exec->propertyNames().arguments) {
240 descriptor.setDescriptor(exec->interpreter()->retrieveArguments(exec, this), ReadOnly | DontEnum | DontDelete);
241 return true;
242 }
243
244 if (propertyName == exec->propertyNames().length) {
245 descriptor.setDescriptor(jsNumber(exec, jsExecutable()->parameterCount()), ReadOnly | DontEnum | DontDelete);
246 return true;
247 }
248
249 if (propertyName == exec->propertyNames().caller) {
250 descriptor.setDescriptor(exec->interpreter()->retrieveCaller(exec, this), ReadOnly | DontEnum | DontDelete);
251 return true;
252 }
253
254 return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
255 }
256
257void JSFunction::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
258{
259 if (!isHostFunction() && (mode == IncludeDontEnumProperties)) {
260 propertyNames.add(exec->propertyNames().arguments);
261 propertyNames.add(exec->propertyNames().callee);
262 propertyNames.add(exec->propertyNames().caller);
263 propertyNames.add(exec->propertyNames().length);
264 }
265 Base::getOwnPropertyNames(exec, propertyNames, mode);
266}
267
268void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
269{
270 if (isHostFunction()) {
271 Base::put(exec, propertyName, value, slot);
272 return;
273 }
274 if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)
275 return;
276 Base::put(exec, propertyName, value, slot);
277}
278
279bool JSFunction::deleteProperty(ExecState* exec, const Identifier& propertyName)
280{
281 if (isHostFunction())
282 return Base::deleteProperty(exec, propertyName);
283 if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)
284 return false;
285 return Base::deleteProperty(exec, propertyName);
286}
287
288// ECMA 13.2.2 [[Construct]]
289ConstructType JSFunction::getConstructData(ConstructData& constructData)
290{
291 if (isHostFunction())
292 return ConstructTypeNone;
293 constructData.js.functionExecutable = jsExecutable();
294 constructData.js.scopeChain = scope().node();
295 return ConstructTypeJS;
296}
297
298} // namespace JSC
Note: See TracBrowser for help on using the repository browser.