Changeset 35016 in webkit for trunk/JavaScriptCore/kjs/JSGlobalObjectFunctions.cpp
- Timestamp:
- Jul 5, 2008, 4:19:36 PM (17 years ago)
- File:
-
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/kjs/JSGlobalObjectFunctions.cpp
r35006 r35016 1 // -*- c-basic-offset: 2 -*-2 1 /* 3 2 * Copyright (C) 1999-2002 Harri Porten ([email protected]) … … 25 24 26 25 #include "config.h" 27 #include "JS Function.h"26 #include "JSGlobalObjectFunctions.h" 28 27 29 28 #include "ExecState.h" 30 #include "FunctionPrototype.h" 31 #include "JSActivation.h" 29 #include "GlobalEvalFunction.h" 32 30 #include "JSGlobalObject.h" 33 31 #include "JSString.h" 34 32 #include "Machine.h" 35 #include "ObjectPrototype.h"36 33 #include "Parser.h" 37 #include "PropertyNameArray.h"38 #include "ScopeChainMark.h"39 #include "debugger.h"40 34 #include "dtoa.h" 41 35 #include "lexer.h" 42 36 #include "nodes.h" 43 #include "operations.h"44 37 #include <errno.h> 45 #include <profiler/Profiler.h>46 38 #include <stdio.h> 47 39 #include <stdlib.h> … … 56 48 57 49 namespace KJS { 58 59 // ----------------------------- JSFunction ----------------------------------60 61 const ClassInfo JSFunction::info = { "Function", &InternalFunction::info, 0, 0 };62 63 JSFunction::JSFunction(ExecState* exec, const Identifier& name, FunctionBodyNode* b, ScopeChainNode* scopeChain)64 : InternalFunction(exec->lexicalGlobalObject()->functionPrototype(), name)65 , body(b)66 , _scope(scopeChain)67 {68 }69 70 void JSFunction::mark()71 {72 InternalFunction::mark();73 body->mark();74 _scope.mark();75 }76 77 CallType JSFunction::getCallData(CallData& callData)78 {79 callData.js.functionBody = body.get();80 callData.js.scopeChain = _scope.node();81 return CallTypeJS;82 }83 84 JSValue* JSFunction::call(ExecState* exec, JSValue* thisValue, const ArgList& args)85 {86 return exec->machine()->execute(body.get(), exec, this, thisValue->toThisObject(exec), args, _scope.node(), exec->exceptionSlot());87 }88 89 JSValue* JSFunction::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)90 {91 JSFunction* thisObj = static_cast<JSFunction*>(slot.slotBase());92 return exec->machine()->retrieveArguments(exec, thisObj);93 }94 95 JSValue* JSFunction::callerGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)96 {97 JSFunction* thisObj = static_cast<JSFunction*>(slot.slotBase());98 return exec->machine()->retrieveCaller(exec, thisObj);99 }100 101 JSValue* JSFunction::lengthGetter(ExecState* exec, const Identifier&, const PropertySlot& slot)102 {103 JSFunction* thisObj = static_cast<JSFunction*>(slot.slotBase());104 return jsNumber(exec, thisObj->body->parameters().size());105 }106 107 bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)108 {109 if (propertyName == exec->propertyNames().arguments) {110 slot.setCustom(this, argumentsGetter);111 return true;112 }113 114 if (propertyName == exec->propertyNames().length) {115 slot.setCustom(this, lengthGetter);116 return true;117 }118 119 if (propertyName == exec->propertyNames().caller) {120 slot.setCustom(this, callerGetter);121 return true;122 }123 124 return InternalFunction::getOwnPropertySlot(exec, propertyName, slot);125 }126 127 void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValue* value)128 {129 if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)130 return;131 InternalFunction::put(exec, propertyName, value);132 }133 134 bool JSFunction::deleteProperty(ExecState* exec, const Identifier& propertyName)135 {136 if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length)137 return false;138 return InternalFunction::deleteProperty(exec, propertyName);139 }140 141 /* Returns the parameter name corresponding to the given index. eg:142 * function f1(x, y, z): getParameterName(0) --> x143 *144 * If a name appears more than once, only the last index at which145 * it appears associates with it. eg:146 * function f2(x, x): getParameterName(0) --> null147 */148 const Identifier& JSFunction::getParameterName(int index)149 {150 Vector<Identifier>& parameters = body->parameters();151 152 if (static_cast<size_t>(index) >= body->parameters().size())153 return _scope.globalObject()->globalData()->propertyNames->nullIdentifier;154 155 const Identifier& name = parameters[index];156 157 // Are there any subsequent parameters with the same name?158 size_t size = parameters.size();159 for (size_t i = index + 1; i < size; ++i)160 if (parameters[i] == name)161 return _scope.globalObject()->globalData()->propertyNames->nullIdentifier;162 163 return name;164 }165 166 // ECMA 13.2.2 [[Construct]]167 ConstructType JSFunction::getConstructData(ConstructData& constructData)168 {169 constructData.js.functionBody = body.get();170 constructData.js.scopeChain = _scope.node();171 return ConstructTypeJS;172 }173 174 JSObject* JSFunction::construct(ExecState* exec, const ArgList& args)175 {176 JSObject* proto;177 JSValue* p = get(exec, exec->propertyNames().prototype);178 if (p->isObject())179 proto = static_cast<JSObject*>(p);180 else181 proto = exec->lexicalGlobalObject()->objectPrototype();182 183 JSObject* thisObj = new (exec) JSObject(proto);184 185 JSValue* result = exec->machine()->execute(body.get(), exec, this, thisObj, args, _scope.node(), exec->exceptionSlot());186 if (exec->hadException() || !result->isObject())187 return thisObj;188 return static_cast<JSObject*>(result);189 }190 191 // ------------------------------ IndexToNameMap ---------------------------------192 193 // We map indexes in the arguments array to their corresponding argument names.194 // Example: function f(x, y, z): arguments[0] = x, so we map 0 to Identifier("x").195 196 // Once we have an argument name, we can get and set the argument's value in the197 // activation object.198 199 // We use Identifier::null to indicate that a given argument's value200 // isn't stored in the activation object.201 202 IndexToNameMap::IndexToNameMap(JSFunction* func, const ArgList& args)203 {204 _map = new Identifier[args.size()];205 this->size = args.size();206 207 unsigned i = 0;208 ArgList::const_iterator end = args.end();209 for (ArgList::const_iterator it = args.begin(); it != end; ++i, ++it)210 _map[i] = func->getParameterName(i); // null if there is no corresponding parameter211 }212 213 IndexToNameMap::~IndexToNameMap()214 {215 delete [] _map;216 }217 218 bool IndexToNameMap::isMapped(const Identifier& index) const219 {220 bool indexIsNumber;221 unsigned indexAsNumber = index.toStrictUInt32(&indexIsNumber);222 223 if (!indexIsNumber)224 return false;225 226 if (indexAsNumber >= size)227 return false;228 229 if (_map[indexAsNumber].isNull())230 return false;231 232 return true;233 }234 235 void IndexToNameMap::unMap(ExecState* exec, const Identifier& index)236 {237 bool indexIsNumber;238 unsigned indexAsNumber = index.toStrictUInt32(&indexIsNumber);239 240 ASSERT(indexIsNumber && indexAsNumber < size);241 242 _map[indexAsNumber] = exec->propertyNames().nullIdentifier;243 }244 245 Identifier& IndexToNameMap::operator[](const Identifier& index)246 {247 bool indexIsNumber;248 unsigned indexAsNumber = index.toStrictUInt32(&indexIsNumber);249 250 ASSERT(indexIsNumber && indexAsNumber < size);251 252 return _map[indexAsNumber];253 }254 255 // ------------------------------ Arguments ---------------------------------256 257 const ClassInfo Arguments::info = { "Arguments", 0, 0, 0 };258 259 // ECMA 10.1.8260 Arguments::Arguments(ExecState* exec, JSFunction* func, const ArgList& args, JSActivation* act)261 : JSObject(exec->lexicalGlobalObject()->objectPrototype())262 , _activationObject(act)263 , indexToNameMap(func, args)264 {265 putDirect(exec->propertyNames().callee, func, DontEnum);266 putDirect(exec, exec->propertyNames().length, args.size(), DontEnum);267 268 int i = 0;269 ArgList::const_iterator end = args.end();270 for (ArgList::const_iterator it = args.begin(); it != end; ++it, ++i) {271 Identifier name = Identifier::from(exec, i);272 if (!indexToNameMap.isMapped(name))273 putDirect(name, *it, DontEnum);274 }275 }276 277 void Arguments::mark()278 {279 JSObject::mark();280 if (_activationObject && !_activationObject->marked())281 _activationObject->mark();282 }283 284 JSValue* Arguments::mappedIndexGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot)285 {286 Arguments* thisObj = static_cast<Arguments*>(slot.slotBase());287 return thisObj->_activationObject->get(exec, thisObj->indexToNameMap[propertyName]);288 }289 290 bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)291 {292 if (indexToNameMap.isMapped(propertyName)) {293 slot.setCustom(this, mappedIndexGetter);294 return true;295 }296 297 return JSObject::getOwnPropertySlot(exec, propertyName, slot);298 }299 300 void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue* value)301 {302 if (indexToNameMap.isMapped(propertyName))303 _activationObject->put(exec, indexToNameMap[propertyName], value);304 else305 JSObject::put(exec, propertyName, value);306 }307 308 bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName)309 {310 if (indexToNameMap.isMapped(propertyName)) {311 indexToNameMap.unMap(exec, propertyName);312 return true;313 } else {314 return JSObject::deleteProperty(exec, propertyName);315 }316 }317 318 // ------------------------------ Global Functions -----------------------------------319 50 320 51 static JSValue* encode(ExecState* exec, const ArgList& args, const char* do_not_escape) … … 682 413 #endif 683 414 684 // ------------------------------ PrototypeFunction -------------------------------685 686 PrototypeFunction::PrototypeFunction(ExecState* exec, int len, const Identifier& name, NativeFunction function)687 : InternalFunction(exec->lexicalGlobalObject()->functionPrototype(), name)688 , m_function(function)689 {690 ASSERT_ARG(function, function);691 putDirect(exec->propertyNames().length, jsNumber(exec, len), DontDelete | ReadOnly | DontEnum);692 }693 694 PrototypeFunction::PrototypeFunction(ExecState* exec, FunctionPrototype* functionPrototype, int len, const Identifier& name, NativeFunction function)695 : InternalFunction(functionPrototype, name)696 , m_function(function)697 {698 ASSERT_ARG(function, function);699 putDirect(exec->propertyNames().length, jsNumber(exec, len), DontDelete | ReadOnly | DontEnum);700 }701 702 CallType PrototypeFunction::getCallData(CallData& callData)703 {704 callData.native.function = m_function;705 return CallTypeNative;706 }707 708 // ------------------------------ PrototypeReflexiveFunction -------------------------------709 710 GlobalEvalFunction::GlobalEvalFunction(ExecState* exec, FunctionPrototype* functionPrototype, int len, const Identifier& name, NativeFunction function, JSGlobalObject* cachedGlobalObject)711 : PrototypeFunction(exec, functionPrototype, len, name, function)712 , m_cachedGlobalObject(cachedGlobalObject)713 {714 ASSERT_ARG(cachedGlobalObject, cachedGlobalObject);715 }716 717 void GlobalEvalFunction::mark()718 {719 PrototypeFunction::mark();720 if (!m_cachedGlobalObject->marked())721 m_cachedGlobalObject->mark();722 }723 724 415 } // namespace KJS
Note:
See TracChangeset
for help on using the changeset viewer.