| 1 | /* | 
| 2 |  *  Copyright (C) 2007 Eric Seidel <eric@webkit.org> | 
| 3 |  *  Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. | 
| 4 |  * | 
| 5 |  *  This library is free software; you can redistribute it and/or | 
| 6 |  *  modify it under the terms of the GNU Library General Public | 
| 7 |  *  License as published by the Free Software Foundation; either | 
| 8 |  *  version 2 of the License, or (at your option) any later version. | 
| 9 |  * | 
| 10 |  *  This library is distributed in the hope that it will be useful, | 
| 11 |  *  but WITHOUT ANY WARRANTY; without even the implied warranty of | 
| 12 |  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
| 13 |  *  Library General Public License for more details. | 
| 14 |  * | 
| 15 |  *  You should have received a copy of the GNU Library General Public License | 
| 16 |  *  along with this library; see the file COPYING.LIB.  If not, write to | 
| 17 |  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 
| 18 |  *  Boston, MA 02110-1301, USA. | 
| 19 |  * | 
| 20 |  */ | 
| 21 |  | 
| 22 | #ifndef JSGlobalObject_h | 
| 23 | #define JSGlobalObject_h | 
| 24 |  | 
| 25 | #include "JSArray.h" | 
| 26 | #include "JSGlobalData.h" | 
| 27 | #include "JSVariableObject.h" | 
| 28 | #include "NativeFunctionWrapper.h" | 
| 29 | #include "NumberPrototype.h" | 
| 30 | #include "StringPrototype.h" | 
| 31 | #include "StructureChain.h" | 
| 32 | #include <wtf/HashSet.h> | 
| 33 | #include <wtf/OwnPtr.h> | 
| 34 | #include <wtf/RandomNumber.h> | 
| 35 |  | 
| 36 | namespace JSC { | 
| 37 |  | 
| 38 |     class ArrayPrototype; | 
| 39 |     class BooleanPrototype; | 
| 40 |     class DatePrototype; | 
| 41 |     class Debugger; | 
| 42 |     class ErrorConstructor; | 
| 43 |     class FunctionPrototype; | 
| 44 |     class GlobalCodeBlock; | 
| 45 |     class GlobalEvalFunction; | 
| 46 |     class NativeErrorConstructor; | 
| 47 |     class ProgramCodeBlock; | 
| 48 |     class PrototypeFunction; | 
| 49 |     class RegExpConstructor; | 
| 50 |     class RegExpPrototype; | 
| 51 |     class RegisterFile; | 
| 52 |  | 
| 53 |     struct ActivationStackNode; | 
| 54 |     struct HashTable; | 
| 55 |  | 
| 56 |     typedef Vector<ExecState*, 16> ExecStateStack; | 
| 57 |      | 
| 58 |     class JSGlobalObject : public JSVariableObject { | 
| 59 |     protected: | 
| 60 |         struct JSGlobalObjectData : public JSVariableObject::JSVariableObjectData { | 
| 61 |             // We use an explicit destructor function pointer instead of a | 
| 62 |             // virtual destructor because we want to avoid adding a vtable | 
| 63 |             // pointer to this struct. Adding a vtable pointer would force the | 
| 64 |             // compiler to emit costly pointer fixup code when casting from | 
| 65 |             // JSVariableObjectData* to JSGlobalObjectData*. | 
| 66 |             typedef void (*Destructor)(void*); | 
| 67 |  | 
| 68 |             JSGlobalObjectData(Destructor destructor) | 
| 69 |                 : JSVariableObjectData(&symbolTable, 0) | 
| 70 |                 , destructor(destructor) | 
| 71 |                 , registerArraySize(0) | 
| 72 |                 , globalScopeChain(NoScopeChain()) | 
| 73 |                 , regExpConstructor(0) | 
| 74 |                 , errorConstructor(0) | 
| 75 |                 , evalErrorConstructor(0) | 
| 76 |                 , rangeErrorConstructor(0) | 
| 77 |                 , referenceErrorConstructor(0) | 
| 78 |                 , syntaxErrorConstructor(0) | 
| 79 |                 , typeErrorConstructor(0) | 
| 80 |                 , URIErrorConstructor(0) | 
| 81 |                 , evalFunction(0) | 
| 82 |                 , callFunction(0) | 
| 83 |                 , applyFunction(0) | 
| 84 |                 , objectPrototype(0) | 
| 85 |                 , functionPrototype(0) | 
| 86 |                 , arrayPrototype(0) | 
| 87 |                 , booleanPrototype(0) | 
| 88 |                 , stringPrototype(0) | 
| 89 |                 , numberPrototype(0) | 
| 90 |                 , datePrototype(0) | 
| 91 |                 , regExpPrototype(0) | 
| 92 |                 , methodCallDummy(0) | 
| 93 |                 , weakRandom(static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0))) | 
| 94 |             { | 
| 95 |             } | 
| 96 |              | 
| 97 |             Destructor destructor; | 
| 98 |              | 
| 99 |             size_t registerArraySize; | 
| 100 |  | 
| 101 |             JSGlobalObject* next; | 
| 102 |             JSGlobalObject* prev; | 
| 103 |  | 
| 104 |             Debugger* debugger; | 
| 105 |              | 
| 106 |             ScopeChain globalScopeChain; | 
| 107 |             Register globalCallFrame[RegisterFile::CallFrameHeaderSize]; | 
| 108 |  | 
| 109 |             int recursion; | 
| 110 |  | 
| 111 |             RegExpConstructor* regExpConstructor; | 
| 112 |             ErrorConstructor* errorConstructor; | 
| 113 |             NativeErrorConstructor* evalErrorConstructor; | 
| 114 |             NativeErrorConstructor* rangeErrorConstructor; | 
| 115 |             NativeErrorConstructor* referenceErrorConstructor; | 
| 116 |             NativeErrorConstructor* syntaxErrorConstructor; | 
| 117 |             NativeErrorConstructor* typeErrorConstructor; | 
| 118 |             NativeErrorConstructor* URIErrorConstructor; | 
| 119 |  | 
| 120 |             GlobalEvalFunction* evalFunction; | 
| 121 |             NativeFunctionWrapper* callFunction; | 
| 122 |             NativeFunctionWrapper* applyFunction; | 
| 123 |  | 
| 124 |             ObjectPrototype* objectPrototype; | 
| 125 |             FunctionPrototype* functionPrototype; | 
| 126 |             ArrayPrototype* arrayPrototype; | 
| 127 |             BooleanPrototype* booleanPrototype; | 
| 128 |             StringPrototype* stringPrototype; | 
| 129 |             NumberPrototype* numberPrototype; | 
| 130 |             DatePrototype* datePrototype; | 
| 131 |             RegExpPrototype* regExpPrototype; | 
| 132 |  | 
| 133 |             JSObject* methodCallDummy; | 
| 134 |  | 
| 135 |             RefPtr<Structure> argumentsStructure; | 
| 136 |             RefPtr<Structure> arrayStructure; | 
| 137 |             RefPtr<Structure> booleanObjectStructure; | 
| 138 |             RefPtr<Structure> callbackConstructorStructure; | 
| 139 |             RefPtr<Structure> callbackFunctionStructure; | 
| 140 |             RefPtr<Structure> callbackObjectStructure; | 
| 141 |             RefPtr<Structure> dateStructure; | 
| 142 |             RefPtr<Structure> emptyObjectStructure; | 
| 143 |             RefPtr<Structure> errorStructure; | 
| 144 |             RefPtr<Structure> functionStructure; | 
| 145 |             RefPtr<Structure> numberObjectStructure; | 
| 146 |             RefPtr<Structure> prototypeFunctionStructure; | 
| 147 |             RefPtr<Structure> regExpMatchesArrayStructure; | 
| 148 |             RefPtr<Structure> regExpStructure; | 
| 149 |             RefPtr<Structure> stringObjectStructure; | 
| 150 |  | 
| 151 |             SymbolTable symbolTable; | 
| 152 |             unsigned profileGroup; | 
| 153 |  | 
| 154 |             RefPtr<JSGlobalData> globalData; | 
| 155 |  | 
| 156 |             HashSet<GlobalCodeBlock*> codeBlocks; | 
| 157 |             WeakRandom weakRandom; | 
| 158 |         }; | 
| 159 |  | 
| 160 |     public: | 
| 161 |         void* operator new(size_t, JSGlobalData*); | 
| 162 |  | 
| 163 |         explicit JSGlobalObject() | 
| 164 |             : JSVariableObject(JSGlobalObject::createStructure(prototype: jsNull()), new JSGlobalObjectData(destroyJSGlobalObjectData)) | 
| 165 |         { | 
| 166 |             init(thisValue: this); | 
| 167 |         } | 
| 168 |  | 
| 169 |     protected: | 
| 170 |         JSGlobalObject(NonNullPassRefPtr<Structure> structure, JSGlobalObjectData* data, JSObject* thisValue) | 
| 171 |             : JSVariableObject(structure, data) | 
| 172 |         { | 
| 173 |             init(thisValue); | 
| 174 |         } | 
| 175 |  | 
| 176 |     public: | 
| 177 |         virtual ~JSGlobalObject(); | 
| 178 |  | 
| 179 |         virtual void markChildren(MarkStack&); | 
| 180 |  | 
| 181 |         virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); | 
| 182 |         virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); | 
| 183 |         virtual bool hasOwnPropertyForWrite(ExecState*, const Identifier&); | 
| 184 |         virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&); | 
| 185 |         virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue value, unsigned attributes); | 
| 186 |  | 
| 187 |         virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunc, unsigned attributes); | 
| 188 |         virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunc, unsigned attributes); | 
| 189 |  | 
| 190 |         // Linked list of all global objects that use the same JSGlobalData. | 
| 191 |         JSGlobalObject*& head() { return d()->globalData->head; } | 
| 192 |         JSGlobalObject* next() { return d()->next; } | 
| 193 |  | 
| 194 |         // The following accessors return pristine values, even if a script  | 
| 195 |         // replaces the global object's associated property. | 
| 196 |  | 
| 197 |         RegExpConstructor* regExpConstructor() const { return d()->regExpConstructor; } | 
| 198 |  | 
| 199 |         ErrorConstructor* errorConstructor() const { return d()->errorConstructor; } | 
| 200 |         NativeErrorConstructor* evalErrorConstructor() const { return d()->evalErrorConstructor; } | 
| 201 |         NativeErrorConstructor* rangeErrorConstructor() const { return d()->rangeErrorConstructor; } | 
| 202 |         NativeErrorConstructor* referenceErrorConstructor() const { return d()->referenceErrorConstructor; } | 
| 203 |         NativeErrorConstructor* syntaxErrorConstructor() const { return d()->syntaxErrorConstructor; } | 
| 204 |         NativeErrorConstructor* typeErrorConstructor() const { return d()->typeErrorConstructor; } | 
| 205 |         NativeErrorConstructor* URIErrorConstructor() const { return d()->URIErrorConstructor; } | 
| 206 |  | 
| 207 |         GlobalEvalFunction* evalFunction() const { return d()->evalFunction; } | 
| 208 |  | 
| 209 |         ObjectPrototype* objectPrototype() const { return d()->objectPrototype; } | 
| 210 |         FunctionPrototype* functionPrototype() const { return d()->functionPrototype; } | 
| 211 |         ArrayPrototype* arrayPrototype() const { return d()->arrayPrototype; } | 
| 212 |         BooleanPrototype* booleanPrototype() const { return d()->booleanPrototype; } | 
| 213 |         StringPrototype* stringPrototype() const { return d()->stringPrototype; } | 
| 214 |         NumberPrototype* numberPrototype() const { return d()->numberPrototype; } | 
| 215 |         DatePrototype* datePrototype() const { return d()->datePrototype; } | 
| 216 |         RegExpPrototype* regExpPrototype() const { return d()->regExpPrototype; } | 
| 217 |  | 
| 218 |         JSObject* methodCallDummy() const { return d()->methodCallDummy; } | 
| 219 |  | 
| 220 |         Structure* argumentsStructure() const { return d()->argumentsStructure.get(); } | 
| 221 |         Structure* arrayStructure() const { return d()->arrayStructure.get(); } | 
| 222 |         Structure* booleanObjectStructure() const { return d()->booleanObjectStructure.get(); } | 
| 223 |         Structure* callbackConstructorStructure() const { return d()->callbackConstructorStructure.get(); } | 
| 224 |         Structure* callbackFunctionStructure() const { return d()->callbackFunctionStructure.get(); } | 
| 225 |         Structure* callbackObjectStructure() const { return d()->callbackObjectStructure.get(); } | 
| 226 |         Structure* dateStructure() const { return d()->dateStructure.get(); } | 
| 227 |         Structure* emptyObjectStructure() const { return d()->emptyObjectStructure.get(); } | 
| 228 |         Structure* errorStructure() const { return d()->errorStructure.get(); } | 
| 229 |         Structure* functionStructure() const { return d()->functionStructure.get(); } | 
| 230 |         Structure* numberObjectStructure() const { return d()->numberObjectStructure.get(); } | 
| 231 |         Structure* prototypeFunctionStructure() const { return d()->prototypeFunctionStructure.get(); } | 
| 232 |         Structure* regExpMatchesArrayStructure() const { return d()->regExpMatchesArrayStructure.get(); } | 
| 233 |         Structure* regExpStructure() const { return d()->regExpStructure.get(); } | 
| 234 |         Structure* stringObjectStructure() const { return d()->stringObjectStructure.get(); } | 
| 235 |  | 
| 236 |         void setProfileGroup(unsigned value) { d()->profileGroup = value; } | 
| 237 |         unsigned profileGroup() const { return d()->profileGroup; } | 
| 238 |  | 
| 239 |         Debugger* debugger() const { return d()->debugger; } | 
| 240 |         void setDebugger(Debugger* debugger) { d()->debugger = debugger; } | 
| 241 |          | 
| 242 |         virtual bool supportsProfiling() const { return false; } | 
| 243 |          | 
| 244 |         int recursion() { return d()->recursion; } | 
| 245 |         void incRecursion() { ++d()->recursion; } | 
| 246 |         void decRecursion() { --d()->recursion; } | 
| 247 |          | 
| 248 |         ScopeChain& globalScopeChain() { return d()->globalScopeChain; } | 
| 249 |  | 
| 250 |         virtual bool isGlobalObject() const { return true; } | 
| 251 |  | 
| 252 |         virtual ExecState* globalExec(); | 
| 253 |  | 
| 254 |         virtual bool shouldInterruptScript() const { return true; } | 
| 255 |  | 
| 256 |         virtual bool allowsAccessFrom(const JSGlobalObject*) const { return true; } | 
| 257 |  | 
| 258 |         virtual bool isDynamicScope() const; | 
| 259 |  | 
| 260 |         HashSet<GlobalCodeBlock*>& codeBlocks() { return d()->codeBlocks; } | 
| 261 |  | 
| 262 |         void copyGlobalsFrom(RegisterFile&); | 
| 263 |         void copyGlobalsTo(RegisterFile&); | 
| 264 |          | 
| 265 |         void resetPrototype(JSValue prototype); | 
| 266 |  | 
| 267 |         JSGlobalData* globalData() { return d()->globalData.get(); } | 
| 268 |         JSGlobalObjectData* d() const { return static_cast<JSGlobalObjectData*>(JSVariableObject::d); } | 
| 269 |  | 
| 270 |         static PassRefPtr<Structure> createStructure(JSValue prototype) | 
| 271 |         { | 
| 272 |             return Structure::create(prototype, typeInfo: TypeInfo(ObjectType, StructureFlags)); | 
| 273 |         } | 
| 274 |  | 
| 275 |         double weakRandomNumber() { return d()->weakRandom.get(); } | 
| 276 |     protected: | 
| 277 |  | 
| 278 |         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags; | 
| 279 |  | 
| 280 |         struct GlobalPropertyInfo { | 
| 281 |             GlobalPropertyInfo(const Identifier& i, JSValue v, unsigned a) | 
| 282 |                 : identifier(i) | 
| 283 |                 , value(v) | 
| 284 |                 , attributes(a) | 
| 285 |             { | 
| 286 |             } | 
| 287 |  | 
| 288 |             const Identifier identifier; | 
| 289 |             JSValue value; | 
| 290 |             unsigned attributes; | 
| 291 |         }; | 
| 292 |         void addStaticGlobals(GlobalPropertyInfo*, int count); | 
| 293 |  | 
| 294 |     private: | 
| 295 |         static void destroyJSGlobalObjectData(void*); | 
| 296 |  | 
| 297 |         // FIXME: Fold reset into init. | 
| 298 |         void init(JSObject* thisValue); | 
| 299 |         void reset(JSValue prototype); | 
| 300 |  | 
| 301 |         void setRegisters(Register* registers, Register* registerArray, size_t count); | 
| 302 |  | 
| 303 |         void* operator new(size_t); // can only be allocated with JSGlobalData | 
| 304 |     }; | 
| 305 |  | 
| 306 |     JSGlobalObject* asGlobalObject(JSValue); | 
| 307 |  | 
| 308 |     inline JSGlobalObject* asGlobalObject(JSValue value) | 
| 309 |     { | 
| 310 |         ASSERT(asObject(value)->isGlobalObject()); | 
| 311 |         return static_cast<JSGlobalObject*>(asObject(value)); | 
| 312 |     } | 
| 313 |  | 
| 314 |     inline void JSGlobalObject::setRegisters(Register* registers, Register* registerArray, size_t count) | 
| 315 |     { | 
| 316 |         JSVariableObject::setRegisters(registers, registerArray); | 
| 317 |         d()->registerArraySize = count; | 
| 318 |     } | 
| 319 |  | 
| 320 |     inline void JSGlobalObject::addStaticGlobals(GlobalPropertyInfo* globals, int count) | 
| 321 |     { | 
| 322 |         size_t oldSize = d()->registerArraySize; | 
| 323 |         size_t newSize = oldSize + count; | 
| 324 |         Register* registerArray = new Register[newSize]; | 
| 325 |         if (d()->registerArray) | 
| 326 |             memcpy(dest: registerArray + count, src: d()->registerArray.get(), n: oldSize * sizeof(Register)); | 
| 327 |         setRegisters(registers: registerArray + newSize, registerArray, count: newSize); | 
| 328 |  | 
| 329 |         for (int i = 0, index = -static_cast<int>(oldSize) - 1; i < count; ++i, --index) { | 
| 330 |             GlobalPropertyInfo& global = globals[i]; | 
| 331 |             ASSERT(global.attributes & DontDelete); | 
| 332 |             SymbolTableEntry newEntry(index, global.attributes); | 
| 333 |             symbolTable().add(key: global.identifier.ustring().rep(), mapped: newEntry); | 
| 334 |             registerAt(index) = global.value; | 
| 335 |         } | 
| 336 |     } | 
| 337 |  | 
| 338 |     inline bool JSGlobalObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) | 
| 339 |     { | 
| 340 |         if (JSVariableObject::getOwnPropertySlot(exec, propertyName, slot)) | 
| 341 |             return true; | 
| 342 |         return symbolTableGet(propertyName, slot); | 
| 343 |     } | 
| 344 |  | 
| 345 |     inline bool JSGlobalObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) | 
| 346 |     { | 
| 347 |         if (symbolTableGet(propertyName, descriptor)) | 
| 348 |             return true; | 
| 349 |         return JSVariableObject::getOwnPropertyDescriptor(exec, propertyName, descriptor); | 
| 350 |     } | 
| 351 |  | 
| 352 |     inline bool JSGlobalObject::hasOwnPropertyForWrite(ExecState* exec, const Identifier& propertyName) | 
| 353 |     { | 
| 354 |         PropertySlot slot; | 
| 355 |         if (JSVariableObject::getOwnPropertySlot(exec, propertyName, slot)) | 
| 356 |             return true; | 
| 357 |         bool slotIsWriteable; | 
| 358 |         return symbolTableGet(propertyName, slot, slotIsWriteable); | 
| 359 |     } | 
| 360 |  | 
| 361 |     inline JSValue Structure::prototypeForLookup(ExecState* exec) const | 
| 362 |     { | 
| 363 |         if (typeInfo().type() == ObjectType) | 
| 364 |             return m_prototype; | 
| 365 |  | 
| 366 | #if USE(JSVALUE32) | 
| 367 |         if (typeInfo().type() == StringType) | 
| 368 |             return exec->lexicalGlobalObject()->stringPrototype(); | 
| 369 |  | 
| 370 |         ASSERT(typeInfo().type() == NumberType); | 
| 371 |         return exec->lexicalGlobalObject()->numberPrototype(); | 
| 372 | #else | 
| 373 |         ASSERT(typeInfo().type() == StringType); | 
| 374 |         return exec->lexicalGlobalObject()->stringPrototype(); | 
| 375 | #endif | 
| 376 |     } | 
| 377 |  | 
| 378 |     inline StructureChain* Structure::prototypeChain(ExecState* exec) const | 
| 379 |     { | 
| 380 |         // We cache our prototype chain so our clients can share it. | 
| 381 |         if (!isValid(exec, cachedPrototypeChain: m_cachedPrototypeChain.get())) { | 
| 382 |             JSValue prototype = prototypeForLookup(exec); | 
| 383 |             m_cachedPrototypeChain = StructureChain::create(head: prototype.isNull() ? 0 : asObject(value: prototype)->structure()); | 
| 384 |         } | 
| 385 |         return m_cachedPrototypeChain.get(); | 
| 386 |     } | 
| 387 |  | 
| 388 |     inline bool Structure::isValid(ExecState* exec, StructureChain* cachedPrototypeChain) const | 
| 389 |     { | 
| 390 |         if (!cachedPrototypeChain) | 
| 391 |             return false; | 
| 392 |  | 
| 393 |         JSValue prototype = prototypeForLookup(exec); | 
| 394 |         RefPtr<Structure>* cachedStructure = cachedPrototypeChain->head(); | 
| 395 |         while(*cachedStructure && !prototype.isNull()) { | 
| 396 |             if (asObject(value: prototype)->structure() != *cachedStructure) | 
| 397 |                 return false; | 
| 398 |             ++cachedStructure; | 
| 399 |             prototype = asObject(value: prototype)->prototype(); | 
| 400 |         } | 
| 401 |         return prototype.isNull() && !*cachedStructure; | 
| 402 |     } | 
| 403 |  | 
| 404 |     inline JSGlobalObject* ExecState::dynamicGlobalObject() | 
| 405 |     { | 
| 406 |         if (this == lexicalGlobalObject()->globalExec()) | 
| 407 |             return lexicalGlobalObject(); | 
| 408 |  | 
| 409 |         // For any ExecState that's not a globalExec, the  | 
| 410 |         // dynamic global object must be set since code is running | 
| 411 |         ASSERT(globalData().dynamicGlobalObject); | 
| 412 |         return globalData().dynamicGlobalObject; | 
| 413 |     } | 
| 414 |  | 
| 415 |     inline JSObject* constructEmptyObject(ExecState* exec) | 
| 416 |     { | 
| 417 |         return new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure()); | 
| 418 |     } | 
| 419 |  | 
| 420 |     inline JSArray* constructEmptyArray(ExecState* exec) | 
| 421 |     { | 
| 422 |         return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure()); | 
| 423 |     } | 
| 424 |  | 
| 425 |     inline JSArray* constructEmptyArray(ExecState* exec, unsigned initialLength) | 
| 426 |     { | 
| 427 |         return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), initialLength); | 
| 428 |     } | 
| 429 |  | 
| 430 |     inline JSArray* constructArray(ExecState* exec, JSValue singleItemValue) | 
| 431 |     { | 
| 432 |         MarkedArgumentBuffer values; | 
| 433 |         values.append(v: singleItemValue); | 
| 434 |         return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), values); | 
| 435 |     } | 
| 436 |  | 
| 437 |     inline JSArray* constructArray(ExecState* exec, const ArgList& values) | 
| 438 |     { | 
| 439 |         return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), values); | 
| 440 |     } | 
| 441 |  | 
| 442 |     class DynamicGlobalObjectScope : public Noncopyable { | 
| 443 |     public: | 
| 444 |         DynamicGlobalObjectScope(CallFrame* callFrame, JSGlobalObject* dynamicGlobalObject)  | 
| 445 |             : m_dynamicGlobalObjectSlot(callFrame->globalData().dynamicGlobalObject) | 
| 446 |             , m_savedDynamicGlobalObject(m_dynamicGlobalObjectSlot) | 
| 447 |         { | 
| 448 |             if (!m_dynamicGlobalObjectSlot) { | 
| 449 |                 m_dynamicGlobalObjectSlot = dynamicGlobalObject; | 
| 450 |  | 
| 451 |                 // Reset the date cache between JS invocations to force the VM | 
| 452 |                 // to observe time zone changes. | 
| 453 |                 callFrame->globalData().resetDateCache(); | 
| 454 |             } | 
| 455 |         } | 
| 456 |  | 
| 457 |         ~DynamicGlobalObjectScope() | 
| 458 |         { | 
| 459 |             m_dynamicGlobalObjectSlot = m_savedDynamicGlobalObject; | 
| 460 |         } | 
| 461 |  | 
| 462 |     private: | 
| 463 |         JSGlobalObject*& m_dynamicGlobalObjectSlot; | 
| 464 |         JSGlobalObject* m_savedDynamicGlobalObject; | 
| 465 |     }; | 
| 466 |  | 
| 467 | } // namespace JSC | 
| 468 |  | 
| 469 | #endif // JSGlobalObject_h | 
| 470 |  |