]>
Commit | Line | Data |
---|---|---|
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 Apple Inc. All rights reserved. | |
5 | * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) | |
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 "FunctionPrototype.h" | |
32 | #include "JSGlobalObject.h" | |
33 | #include "Interpreter.h" | |
34 | #include "ObjectPrototype.h" | |
35 | #include "Parser.h" | |
36 | #include "PropertyNameArray.h" | |
37 | #include "ScopeChainMark.h" | |
38 | ||
39 | using namespace WTF; | |
40 | using namespace Unicode; | |
41 | ||
42 | namespace JSC { | |
43 | ||
44 | ASSERT_CLASS_FITS_IN_CELL(JSFunction); | |
45 | ||
46 | const ClassInfo JSFunction::info = { "Function", &InternalFunction::info, 0, 0 }; | |
47 | ||
48 | JSFunction::JSFunction(ExecState* exec, const Identifier& name, FunctionBodyNode* body, ScopeChainNode* scopeChainNode) | |
49 | : Base(&exec->globalData(), exec->lexicalGlobalObject()->functionStructure(), name) | |
50 | , m_body(body) | |
51 | , m_scopeChain(scopeChainNode) | |
52 | { | |
53 | } | |
54 | ||
55 | JSFunction::~JSFunction() | |
56 | { | |
57 | #if ENABLE(JIT) | |
58 | // JIT code for other functions may have had calls linked directly to the code for this function; these links | |
59 | // are based on a check for the this pointer value for this JSFunction - which will no longer be valid once | |
60 | // this memory is freed and may be reused (potentially for another, different JSFunction). | |
61 | if (m_body && m_body->isGenerated()) | |
62 | m_body->generatedBytecode().unlinkCallers(); | |
63 | #endif | |
64 | } | |
65 | ||
66 | void JSFunction::mark() | |
67 | { | |
68 | Base::mark(); | |
69 | m_body->mark(); | |
70 | m_scopeChain.mark(); | |
71 | } | |
72 | ||
73 | CallType JSFunction::getCallData(CallData& callData) | |
74 | { | |
75 | callData.js.functionBody = m_body.get(); | |
76 | callData.js.scopeChain = m_scopeChain.node(); | |
77 | return CallTypeJS; | |
78 | } | |
79 | ||
80 | JSValuePtr JSFunction::call(ExecState* exec, JSValuePtr thisValue, const ArgList& args) | |
81 | { | |
82 | return exec->interpreter()->execute(m_body.get(), exec, this, thisValue.toThisObject(exec), args, m_scopeChain.node(), exec->exceptionSlot()); | |
83 | } | |
84 | ||
85 | JSValuePtr JSFunction::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) | |
86 | { | |
87 | JSFunction* thisObj = asFunction(slot.slotBase()); | |
88 | return exec->interpreter()->retrieveArguments(exec, thisObj); | |
89 | } | |
90 | ||
91 | JSValuePtr JSFunction::callerGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) | |
92 | { | |
93 | JSFunction* thisObj = asFunction(slot.slotBase()); | |
94 | return exec->interpreter()->retrieveCaller(exec, thisObj); | |
95 | } | |
96 | ||
97 | JSValuePtr JSFunction::lengthGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) | |
98 | { | |
99 | JSFunction* thisObj = asFunction(slot.slotBase()); | |
100 | return jsNumber(exec, thisObj->m_body->parameterCount()); | |
101 | } | |
102 | ||
103 | bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) | |
104 | { | |
105 | if (propertyName == exec->propertyNames().prototype) { | |
106 | JSValuePtr* location = getDirectLocation(propertyName); | |
107 | ||
108 | if (!location) { | |
109 | JSObject* prototype = new (exec) JSObject(m_scopeChain.globalObject()->emptyObjectStructure()); | |
110 | prototype->putDirect(exec->propertyNames().constructor, this, DontEnum); | |
111 | putDirect(exec->propertyNames().prototype, prototype, DontDelete); | |
112 | location = getDirectLocation(propertyName); | |
113 | } | |
114 | ||
115 | slot.setValueSlot(this, location, offsetForLocation(location)); | |
116 | } | |
117 | ||
118 | if (propertyName == exec->propertyNames().arguments) { | |
119 | slot.setCustom(this, argumentsGetter); | |
120 | return true; | |
121 | } | |
122 | ||
123 | if (propertyName == exec->propertyNames().length) { | |
124 | slot.setCustom(this, lengthGetter); | |
125 | return true; | |
126 | } | |
127 | ||
128 | if (propertyName == exec->propertyNames().caller) { | |
129 | slot.setCustom(this, callerGetter); | |
130 | return true; | |
131 | } | |
132 | ||
133 | return Base::getOwnPropertySlot(exec, propertyName, slot); | |
134 | } | |
135 | ||
136 | void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValuePtr value, PutPropertySlot& slot) | |
137 | { | |
138 | if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length) | |
139 | return; | |
140 | Base::put(exec, propertyName, value, slot); | |
141 | } | |
142 | ||
143 | bool JSFunction::deleteProperty(ExecState* exec, const Identifier& propertyName) | |
144 | { | |
145 | if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length) | |
146 | return false; | |
147 | return Base::deleteProperty(exec, propertyName); | |
148 | } | |
149 | ||
150 | // ECMA 13.2.2 [[Construct]] | |
151 | ConstructType JSFunction::getConstructData(ConstructData& constructData) | |
152 | { | |
153 | constructData.js.functionBody = m_body.get(); | |
154 | constructData.js.scopeChain = m_scopeChain.node(); | |
155 | return ConstructTypeJS; | |
156 | } | |
157 | ||
158 | JSObject* JSFunction::construct(ExecState* exec, const ArgList& args) | |
159 | { | |
160 | Structure* structure; | |
161 | JSValuePtr prototype = get(exec, exec->propertyNames().prototype); | |
162 | if (prototype.isObject()) | |
163 | structure = asObject(prototype)->inheritorID(); | |
164 | else | |
165 | structure = exec->lexicalGlobalObject()->emptyObjectStructure(); | |
166 | JSObject* thisObj = new (exec) JSObject(structure); | |
167 | ||
168 | JSValuePtr result = exec->interpreter()->execute(m_body.get(), exec, this, thisObj, args, m_scopeChain.node(), exec->exceptionSlot()); | |
169 | if (exec->hadException() || !result.isObject()) | |
170 | return thisObj; | |
171 | return asObject(result); | |
172 | } | |
173 | ||
174 | } // namespace JSC |