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