]>
Commit | Line | Data |
---|---|---|
9dae56ea A |
1 | /* |
2 | * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. | |
3 | * Copyright (C) 2008 Cameron Zwarich (cwzwarich@uwaterloo.ca) | |
4 | * | |
5 | * Redistribution and use in source and binary forms, with or without | |
6 | * modification, are permitted provided that the following conditions | |
7 | * are met: | |
8 | * | |
9 | * 1. Redistributions of source code must retain the above copyright | |
10 | * notice, this list of conditions and the following disclaimer. | |
11 | * 2. Redistributions in binary form must reproduce the above copyright | |
12 | * notice, this list of conditions and the following disclaimer in the | |
13 | * documentation and/or other materials provided with the distribution. | |
14 | * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of | |
15 | * its contributors may be used to endorse or promote products derived | |
16 | * from this software without specific prior written permission. | |
17 | * | |
18 | * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY | |
19 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
20 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
21 | * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY | |
22 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
23 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
25 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
27 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
28 | */ | |
29 | ||
30 | #include "config.h" | |
31 | #include "JSGlobalObject.h" | |
32 | ||
33 | #include "JSCallbackConstructor.h" | |
34 | #include "JSCallbackFunction.h" | |
35 | #include "JSCallbackObject.h" | |
36 | ||
37 | #include "Arguments.h" | |
38 | #include "ArrayConstructor.h" | |
39 | #include "ArrayPrototype.h" | |
40 | #include "BooleanConstructor.h" | |
41 | #include "BooleanPrototype.h" | |
42 | #include "CodeBlock.h" | |
43 | #include "DateConstructor.h" | |
44 | #include "DatePrototype.h" | |
6fe7ccc8 | 45 | #include "Error.h" |
9dae56ea A |
46 | #include "ErrorConstructor.h" |
47 | #include "ErrorPrototype.h" | |
48 | #include "FunctionConstructor.h" | |
49 | #include "FunctionPrototype.h" | |
6fe7ccc8 A |
50 | #include "GetterSetter.h" |
51 | #include "JSBoundFunction.h" | |
ba379fdc | 52 | #include "JSFunction.h" |
9dae56ea A |
53 | #include "JSGlobalObjectFunctions.h" |
54 | #include "JSLock.h" | |
ba379fdc | 55 | #include "JSONObject.h" |
9dae56ea | 56 | #include "Interpreter.h" |
14957cd0 | 57 | #include "Lookup.h" |
9dae56ea A |
58 | #include "MathObject.h" |
59 | #include "NativeErrorConstructor.h" | |
60 | #include "NativeErrorPrototype.h" | |
61 | #include "NumberConstructor.h" | |
62 | #include "NumberPrototype.h" | |
63 | #include "ObjectConstructor.h" | |
64 | #include "ObjectPrototype.h" | |
65 | #include "Profiler.h" | |
9dae56ea A |
66 | #include "RegExpConstructor.h" |
67 | #include "RegExpMatchesArray.h" | |
68 | #include "RegExpObject.h" | |
69 | #include "RegExpPrototype.h" | |
70 | #include "ScopeChainMark.h" | |
71 | #include "StringConstructor.h" | |
72 | #include "StringPrototype.h" | |
73 | #include "Debugger.h" | |
74 | ||
14957cd0 A |
75 | #include "JSGlobalObject.lut.h" |
76 | ||
9dae56ea A |
77 | namespace JSC { |
78 | ||
6fe7ccc8 A |
79 | const ClassInfo JSGlobalObject::s_info = { "GlobalObject", &JSVariableObject::s_info, 0, ExecState::globalObjectTable, CREATE_METHOD_TABLE(JSGlobalObject) }; |
80 | ||
81 | const GlobalObjectMethodTable JSGlobalObject::s_globalObjectMethodTable = { &allowsAccessFrom, &supportsProfiling, &supportsRichSourceInfo, &shouldInterruptScript | |
82 | , &shouldInterruptScriptBeforeTimeout | |
83 | }; | |
14957cd0 A |
84 | |
85 | /* Source for JSGlobalObject.lut.h | |
86 | @begin globalObjectTable | |
87 | parseInt globalFuncParseInt DontEnum|Function 2 | |
88 | parseFloat globalFuncParseFloat DontEnum|Function 1 | |
89 | isNaN globalFuncIsNaN DontEnum|Function 1 | |
90 | isFinite globalFuncIsFinite DontEnum|Function 1 | |
91 | escape globalFuncEscape DontEnum|Function 1 | |
92 | unescape globalFuncUnescape DontEnum|Function 1 | |
93 | decodeURI globalFuncDecodeURI DontEnum|Function 1 | |
94 | decodeURIComponent globalFuncDecodeURIComponent DontEnum|Function 1 | |
95 | encodeURI globalFuncEncodeURI DontEnum|Function 1 | |
96 | encodeURIComponent globalFuncEncodeURIComponent DontEnum|Function 1 | |
97 | @end | |
98 | */ | |
99 | ||
9dae56ea A |
100 | ASSERT_CLASS_FITS_IN_CELL(JSGlobalObject); |
101 | ||
102 | // Default number of ticks before a timeout check should be done. | |
103 | static const int initialTickCountThreshold = 255; | |
104 | ||
105 | // Preferred number of milliseconds between each timeout check | |
106 | static const int preferredScriptCheckTimeInterval = 1000; | |
107 | ||
14957cd0 | 108 | template <typename T> static inline void visitIfNeeded(SlotVisitor& visitor, WriteBarrier<T>* v) |
9dae56ea | 109 | { |
14957cd0 A |
110 | if (*v) |
111 | visitor.append(v); | |
9dae56ea A |
112 | } |
113 | ||
114 | JSGlobalObject::~JSGlobalObject() | |
115 | { | |
14957cd0 A |
116 | if (m_debugger) |
117 | m_debugger->detach(this); | |
9dae56ea A |
118 | |
119 | Profiler** profiler = Profiler::enabledProfilerReference(); | |
120 | if (UNLIKELY(*profiler != 0)) { | |
14957cd0 | 121 | (*profiler)->stopProfiling(this); |
9dae56ea | 122 | } |
9dae56ea A |
123 | } |
124 | ||
6fe7ccc8 A |
125 | void JSGlobalObject::destroy(JSCell* cell) |
126 | { | |
127 | jsCast<JSGlobalObject*>(cell)->JSGlobalObject::~JSGlobalObject(); | |
128 | } | |
129 | ||
9dae56ea A |
130 | void JSGlobalObject::init(JSObject* thisValue) |
131 | { | |
6fe7ccc8 | 132 | ASSERT(globalData().apiLock().currentThreadIsHoldingLock()); |
14957cd0 | 133 | |
f9bf01c6 A |
134 | structure()->disableSpecificFunctionTracking(); |
135 | ||
6fe7ccc8 | 136 | m_globalScopeChain.set(globalData(), this, ScopeChainNode::create(0, this, &globalData(), this, thisValue)); |
9dae56ea | 137 | |
14957cd0 | 138 | JSGlobalObject::globalExec()->init(0, 0, m_globalScopeChain.get(), CallFrame::noCaller(), 0, 0); |
9dae56ea | 139 | |
14957cd0 | 140 | m_debugger = 0; |
9dae56ea | 141 | |
9dae56ea A |
142 | reset(prototype()); |
143 | } | |
144 | ||
6fe7ccc8 | 145 | void JSGlobalObject::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) |
9dae56ea | 146 | { |
6fe7ccc8 A |
147 | JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(cell); |
148 | ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(thisObject)); | |
9dae56ea | 149 | |
6fe7ccc8 | 150 | if (thisObject->symbolTablePut(exec, propertyName, value, slot.isStrictMode())) |
9dae56ea | 151 | return; |
6fe7ccc8 | 152 | JSVariableObject::put(thisObject, exec, propertyName, value, slot); |
9dae56ea A |
153 | } |
154 | ||
6fe7ccc8 | 155 | void JSGlobalObject::putDirectVirtual(JSObject* object, ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes) |
9dae56ea | 156 | { |
6fe7ccc8 A |
157 | JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(object); |
158 | ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(thisObject)); | |
9dae56ea | 159 | |
6fe7ccc8 | 160 | if (thisObject->symbolTablePutWithAttributes(exec->globalData(), propertyName, value, attributes)) |
9dae56ea A |
161 | return; |
162 | ||
6fe7ccc8 | 163 | JSValue valueBefore = thisObject->getDirect(exec->globalData(), propertyName); |
9dae56ea | 164 | PutPropertySlot slot; |
6fe7ccc8 | 165 | JSVariableObject::put(thisObject, exec, propertyName, value, slot); |
9dae56ea | 166 | if (!valueBefore) { |
6fe7ccc8 | 167 | JSValue valueAfter = thisObject->getDirect(exec->globalData(), propertyName); |
9dae56ea | 168 | if (valueAfter) |
6fe7ccc8 | 169 | JSObject::putDirectVirtual(thisObject, exec, propertyName, valueAfter, attributes); |
9dae56ea A |
170 | } |
171 | } | |
172 | ||
6fe7ccc8 | 173 | bool JSGlobalObject::defineOwnProperty(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool shouldThrow) |
9dae56ea | 174 | { |
6fe7ccc8 | 175 | JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(object); |
9dae56ea | 176 | PropertySlot slot; |
6fe7ccc8 A |
177 | // silently ignore attempts to add accessors aliasing vars. |
178 | if (descriptor.isAccessorDescriptor() && thisObject->symbolTableGet(propertyName, slot)) | |
179 | return false; | |
180 | return Base::defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow); | |
9dae56ea A |
181 | } |
182 | ||
9dae56ea A |
183 | |
184 | static inline JSObject* lastInPrototypeChain(JSObject* object) | |
185 | { | |
186 | JSObject* o = object; | |
187 | while (o->prototype().isObject()) | |
188 | o = asObject(o->prototype()); | |
189 | return o; | |
190 | } | |
191 | ||
ba379fdc | 192 | void JSGlobalObject::reset(JSValue prototype) |
9dae56ea A |
193 | { |
194 | ExecState* exec = JSGlobalObject::globalExec(); | |
195 | ||
6fe7ccc8 A |
196 | m_functionPrototype.set(exec->globalData(), this, FunctionPrototype::create(exec, this, FunctionPrototype::createStructure(exec->globalData(), this, jsNull()))); // The real prototype will be set once ObjectPrototype is created. |
197 | m_functionStructure.set(exec->globalData(), this, JSFunction::createStructure(exec->globalData(), this, m_functionPrototype.get())); | |
198 | m_boundFunctionStructure.set(exec->globalData(), this, JSBoundFunction::createStructure(exec->globalData(), this, m_functionPrototype.get())); | |
199 | m_namedFunctionStructure.set(exec->globalData(), this, Structure::addPropertyTransition(exec->globalData(), m_functionStructure.get(), exec->globalData().propertyNames->name, DontDelete | ReadOnly | DontEnum, 0, m_functionNameOffset)); | |
200 | m_internalFunctionStructure.set(exec->globalData(), this, InternalFunction::createStructure(exec->globalData(), this, m_functionPrototype.get())); | |
14957cd0 A |
201 | JSFunction* callFunction = 0; |
202 | JSFunction* applyFunction = 0; | |
6fe7ccc8 | 203 | m_functionPrototype->addFunctionProperties(exec, this, &callFunction, &applyFunction); |
14957cd0 A |
204 | m_callFunction.set(exec->globalData(), this, callFunction); |
205 | m_applyFunction.set(exec->globalData(), this, applyFunction); | |
6fe7ccc8 A |
206 | m_objectPrototype.set(exec->globalData(), this, ObjectPrototype::create(exec, this, ObjectPrototype::createStructure(exec->globalData(), this, jsNull()))); |
207 | GetterSetter* protoAccessor = GetterSetter::create(exec); | |
208 | protoAccessor->setGetter(exec->globalData(), JSFunction::create(exec, this, 0, Identifier(), globalFuncProtoGetter)); | |
209 | protoAccessor->setSetter(exec->globalData(), JSFunction::create(exec, this, 0, Identifier(), globalFuncProtoSetter)); | |
210 | m_objectPrototype->putDirectAccessor(exec->globalData(), exec->propertyNames().underscoreProto, protoAccessor, Accessor | DontEnum); | |
14957cd0 | 211 | m_functionPrototype->structure()->setPrototypeWithoutTransition(exec->globalData(), m_objectPrototype.get()); |
9dae56ea | 212 | |
14957cd0 | 213 | m_emptyObjectStructure.set(exec->globalData(), this, m_objectPrototype->inheritorID(exec->globalData())); |
6fe7ccc8 | 214 | m_nullPrototypeObjectStructure.set(exec->globalData(), this, createEmptyObjectStructure(exec->globalData(), this, jsNull())); |
9dae56ea | 215 | |
6fe7ccc8 A |
216 | m_callbackFunctionStructure.set(exec->globalData(), this, JSCallbackFunction::createStructure(exec->globalData(), this, m_functionPrototype.get())); |
217 | m_argumentsStructure.set(exec->globalData(), this, Arguments::createStructure(exec->globalData(), this, m_objectPrototype.get())); | |
218 | m_callbackConstructorStructure.set(exec->globalData(), this, JSCallbackConstructor::createStructure(exec->globalData(), this, m_objectPrototype.get())); | |
219 | m_callbackObjectStructure.set(exec->globalData(), this, JSCallbackObject<JSNonFinalObject>::createStructure(exec->globalData(), this, m_objectPrototype.get())); | |
9dae56ea | 220 | |
6fe7ccc8 A |
221 | m_arrayPrototype.set(exec->globalData(), this, ArrayPrototype::create(exec, this, ArrayPrototype::createStructure(exec->globalData(), this, m_objectPrototype.get()))); |
222 | m_arrayStructure.set(exec->globalData(), this, JSArray::createStructure(exec->globalData(), this, m_arrayPrototype.get())); | |
223 | m_regExpMatchesArrayStructure.set(exec->globalData(), this, RegExpMatchesArray::createStructure(exec->globalData(), this, m_arrayPrototype.get())); | |
9dae56ea | 224 | |
6fe7ccc8 A |
225 | m_stringPrototype.set(exec->globalData(), this, StringPrototype::create(exec, this, StringPrototype::createStructure(exec->globalData(), this, m_objectPrototype.get()))); |
226 | m_stringObjectStructure.set(exec->globalData(), this, StringObject::createStructure(exec->globalData(), this, m_stringPrototype.get())); | |
9dae56ea | 227 | |
6fe7ccc8 A |
228 | m_booleanPrototype.set(exec->globalData(), this, BooleanPrototype::create(exec, this, BooleanPrototype::createStructure(exec->globalData(), this, m_objectPrototype.get()))); |
229 | m_booleanObjectStructure.set(exec->globalData(), this, BooleanObject::createStructure(exec->globalData(), this, m_booleanPrototype.get())); | |
9dae56ea | 230 | |
6fe7ccc8 A |
231 | m_numberPrototype.set(exec->globalData(), this, NumberPrototype::create(exec, this, NumberPrototype::createStructure(exec->globalData(), this, m_objectPrototype.get()))); |
232 | m_numberObjectStructure.set(exec->globalData(), this, NumberObject::createStructure(exec->globalData(), this, m_numberPrototype.get())); | |
9dae56ea | 233 | |
6fe7ccc8 A |
234 | m_datePrototype.set(exec->globalData(), this, DatePrototype::create(exec, this, DatePrototype::createStructure(exec->globalData(), this, m_objectPrototype.get()))); |
235 | m_dateStructure.set(exec->globalData(), this, DateInstance::createStructure(exec->globalData(), this, m_datePrototype.get())); | |
9dae56ea | 236 | |
6fe7ccc8 | 237 | RegExp* emptyRegex = RegExp::create(exec->globalData(), "", NoFlags); |
14957cd0 | 238 | |
6fe7ccc8 A |
239 | m_regExpPrototype.set(exec->globalData(), this, RegExpPrototype::create(exec, this, RegExpPrototype::createStructure(exec->globalData(), this, m_objectPrototype.get()), emptyRegex)); |
240 | m_regExpStructure.set(exec->globalData(), this, RegExpObject::createStructure(exec->globalData(), this, m_regExpPrototype.get())); | |
9dae56ea | 241 | |
14957cd0 | 242 | m_methodCallDummy.set(exec->globalData(), this, constructEmptyObject(exec)); |
ba379fdc | 243 | |
6fe7ccc8 A |
244 | ErrorPrototype* errorPrototype = ErrorPrototype::create(exec, this, ErrorPrototype::createStructure(exec->globalData(), this, m_objectPrototype.get())); |
245 | m_errorStructure.set(exec->globalData(), this, ErrorInstance::createStructure(exec->globalData(), this, errorPrototype)); | |
9dae56ea | 246 | |
9dae56ea A |
247 | // Constructors |
248 | ||
6fe7ccc8 A |
249 | JSCell* objectConstructor = ObjectConstructor::create(exec, this, ObjectConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_objectPrototype.get()); |
250 | JSCell* functionConstructor = FunctionConstructor::create(exec, this, FunctionConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_functionPrototype.get()); | |
251 | JSCell* arrayConstructor = ArrayConstructor::create(exec, this, ArrayConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_arrayPrototype.get()); | |
252 | JSCell* stringConstructor = StringConstructor::create(exec, this, StringConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_stringPrototype.get()); | |
253 | JSCell* booleanConstructor = BooleanConstructor::create(exec, this, BooleanConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_booleanPrototype.get()); | |
254 | JSCell* numberConstructor = NumberConstructor::create(exec, this, NumberConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_numberPrototype.get()); | |
255 | JSCell* dateConstructor = DateConstructor::create(exec, this, DateConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_datePrototype.get()); | |
256 | ||
257 | m_regExpConstructor.set(exec->globalData(), this, RegExpConstructor::create(exec, this, RegExpConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), m_regExpPrototype.get())); | |
258 | ||
259 | m_errorConstructor.set(exec->globalData(), this, ErrorConstructor::create(exec, this, ErrorConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()), errorPrototype)); | |
260 | ||
261 | Structure* nativeErrorPrototypeStructure = NativeErrorPrototype::createStructure(exec->globalData(), this, errorPrototype); | |
262 | Structure* nativeErrorStructure = NativeErrorConstructor::createStructure(exec->globalData(), this, m_functionPrototype.get()); | |
263 | m_evalErrorConstructor.set(exec->globalData(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "EvalError")); | |
264 | m_rangeErrorConstructor.set(exec->globalData(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "RangeError")); | |
265 | m_referenceErrorConstructor.set(exec->globalData(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "ReferenceError")); | |
266 | m_syntaxErrorConstructor.set(exec->globalData(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "SyntaxError")); | |
267 | m_typeErrorConstructor.set(exec->globalData(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "TypeError")); | |
268 | m_URIErrorConstructor.set(exec->globalData(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, "URIError")); | |
269 | ||
270 | m_objectPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, objectConstructor, DontEnum); | |
271 | m_functionPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, functionConstructor, DontEnum); | |
272 | m_arrayPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, arrayConstructor, DontEnum); | |
273 | m_booleanPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, booleanConstructor, DontEnum); | |
274 | m_stringPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, stringConstructor, DontEnum); | |
275 | m_numberPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, numberConstructor, DontEnum); | |
276 | m_datePrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, dateConstructor, DontEnum); | |
277 | m_regExpPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, m_regExpConstructor.get(), DontEnum); | |
278 | errorPrototype->putDirectWithoutTransition(exec->globalData(), exec->propertyNames().constructor, m_errorConstructor.get(), DontEnum); | |
279 | ||
280 | putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Object"), objectConstructor, DontEnum); | |
281 | putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Function"), functionConstructor, DontEnum); | |
282 | putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Array"), arrayConstructor, DontEnum); | |
283 | putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Boolean"), booleanConstructor, DontEnum); | |
284 | putDirectWithoutTransition(exec->globalData(), Identifier(exec, "String"), stringConstructor, DontEnum); | |
285 | putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Number"), numberConstructor, DontEnum); | |
286 | putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Date"), dateConstructor, DontEnum); | |
287 | putDirectWithoutTransition(exec->globalData(), Identifier(exec, "RegExp"), m_regExpConstructor.get(), DontEnum); | |
288 | putDirectWithoutTransition(exec->globalData(), Identifier(exec, "Error"), m_errorConstructor.get(), DontEnum); | |
289 | putDirectWithoutTransition(exec->globalData(), Identifier(exec, "EvalError"), m_evalErrorConstructor.get(), DontEnum); | |
290 | putDirectWithoutTransition(exec->globalData(), Identifier(exec, "RangeError"), m_rangeErrorConstructor.get(), DontEnum); | |
291 | putDirectWithoutTransition(exec->globalData(), Identifier(exec, "ReferenceError"), m_referenceErrorConstructor.get(), DontEnum); | |
292 | putDirectWithoutTransition(exec->globalData(), Identifier(exec, "SyntaxError"), m_syntaxErrorConstructor.get(), DontEnum); | |
293 | putDirectWithoutTransition(exec->globalData(), Identifier(exec, "TypeError"), m_typeErrorConstructor.get(), DontEnum); | |
294 | putDirectWithoutTransition(exec->globalData(), Identifier(exec, "URIError"), m_URIErrorConstructor.get(), DontEnum); | |
295 | ||
296 | m_evalFunction.set(exec->globalData(), this, JSFunction::create(exec, this, 1, exec->propertyNames().eval, globalFuncEval)); | |
297 | putDirectWithoutTransition(exec->globalData(), exec->propertyNames().eval, m_evalFunction.get(), DontEnum); | |
298 | ||
299 | putDirectWithoutTransition(exec->globalData(), Identifier(exec, "JSON"), JSONObject::create(exec, this, JSONObject::createStructure(exec->globalData(), this, m_objectPrototype.get())), DontEnum); | |
14957cd0 | 300 | |
9dae56ea | 301 | GlobalPropertyInfo staticGlobals[] = { |
6fe7ccc8 | 302 | GlobalPropertyInfo(Identifier(exec, "Math"), MathObject::create(exec, this, MathObject::createStructure(exec->globalData(), this, m_objectPrototype.get())), DontEnum | DontDelete), |
14957cd0 | 303 | GlobalPropertyInfo(Identifier(exec, "NaN"), jsNaN(), DontEnum | DontDelete | ReadOnly), |
6fe7ccc8 A |
304 | GlobalPropertyInfo(Identifier(exec, "Infinity"), jsNumber(std::numeric_limits<double>::infinity()), DontEnum | DontDelete | ReadOnly), |
305 | GlobalPropertyInfo(Identifier(exec, "undefined"), jsUndefined(), DontEnum | DontDelete | ReadOnly) | |
9dae56ea | 306 | }; |
14957cd0 | 307 | addStaticGlobals(staticGlobals, WTF_ARRAY_LENGTH(staticGlobals)); |
9dae56ea | 308 | |
14957cd0 | 309 | resetPrototype(exec->globalData(), prototype); |
9dae56ea A |
310 | } |
311 | ||
6fe7ccc8 A |
312 | void JSGlobalObject::createThrowTypeError(ExecState* exec) |
313 | { | |
314 | JSFunction* thrower = JSFunction::create(exec, this, 0, Identifier(), globalFuncThrowTypeError); | |
315 | GetterSetter* getterSetter = GetterSetter::create(exec); | |
316 | getterSetter->setGetter(exec->globalData(), thrower); | |
317 | getterSetter->setSetter(exec->globalData(), thrower); | |
318 | m_throwTypeErrorGetterSetter.set(exec->globalData(), this, getterSetter); | |
319 | } | |
320 | ||
9dae56ea | 321 | // Set prototype, and also insert the object prototype at the end of the chain. |
14957cd0 | 322 | void JSGlobalObject::resetPrototype(JSGlobalData& globalData, JSValue prototype) |
9dae56ea | 323 | { |
14957cd0 | 324 | setPrototype(globalData, prototype); |
9dae56ea | 325 | |
ba379fdc | 326 | JSObject* oldLastInPrototypeChain = lastInPrototypeChain(this); |
14957cd0 | 327 | JSObject* objectPrototype = m_objectPrototype.get(); |
ba379fdc | 328 | if (oldLastInPrototypeChain != objectPrototype) |
14957cd0 | 329 | oldLastInPrototypeChain->setPrototype(globalData, objectPrototype); |
9dae56ea A |
330 | } |
331 | ||
6fe7ccc8 A |
332 | void JSGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor) |
333 | { | |
334 | JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(cell); | |
335 | ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info); | |
14957cd0 | 336 | COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); |
6fe7ccc8 A |
337 | ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); |
338 | JSVariableObject::visitChildren(thisObject, visitor); | |
339 | ||
340 | visitIfNeeded(visitor, &thisObject->m_globalScopeChain); | |
341 | visitIfNeeded(visitor, &thisObject->m_methodCallDummy); | |
342 | ||
343 | visitIfNeeded(visitor, &thisObject->m_regExpConstructor); | |
344 | visitIfNeeded(visitor, &thisObject->m_errorConstructor); | |
345 | visitIfNeeded(visitor, &thisObject->m_evalErrorConstructor); | |
346 | visitIfNeeded(visitor, &thisObject->m_rangeErrorConstructor); | |
347 | visitIfNeeded(visitor, &thisObject->m_referenceErrorConstructor); | |
348 | visitIfNeeded(visitor, &thisObject->m_syntaxErrorConstructor); | |
349 | visitIfNeeded(visitor, &thisObject->m_typeErrorConstructor); | |
350 | visitIfNeeded(visitor, &thisObject->m_URIErrorConstructor); | |
351 | ||
352 | visitIfNeeded(visitor, &thisObject->m_evalFunction); | |
353 | visitIfNeeded(visitor, &thisObject->m_callFunction); | |
354 | visitIfNeeded(visitor, &thisObject->m_applyFunction); | |
355 | visitIfNeeded(visitor, &thisObject->m_throwTypeErrorGetterSetter); | |
356 | ||
357 | visitIfNeeded(visitor, &thisObject->m_objectPrototype); | |
358 | visitIfNeeded(visitor, &thisObject->m_functionPrototype); | |
359 | visitIfNeeded(visitor, &thisObject->m_arrayPrototype); | |
360 | visitIfNeeded(visitor, &thisObject->m_booleanPrototype); | |
361 | visitIfNeeded(visitor, &thisObject->m_stringPrototype); | |
362 | visitIfNeeded(visitor, &thisObject->m_numberPrototype); | |
363 | visitIfNeeded(visitor, &thisObject->m_datePrototype); | |
364 | visitIfNeeded(visitor, &thisObject->m_regExpPrototype); | |
365 | ||
366 | visitIfNeeded(visitor, &thisObject->m_argumentsStructure); | |
367 | visitIfNeeded(visitor, &thisObject->m_arrayStructure); | |
368 | visitIfNeeded(visitor, &thisObject->m_booleanObjectStructure); | |
369 | visitIfNeeded(visitor, &thisObject->m_callbackConstructorStructure); | |
370 | visitIfNeeded(visitor, &thisObject->m_callbackFunctionStructure); | |
371 | visitIfNeeded(visitor, &thisObject->m_callbackObjectStructure); | |
372 | visitIfNeeded(visitor, &thisObject->m_dateStructure); | |
373 | visitIfNeeded(visitor, &thisObject->m_emptyObjectStructure); | |
374 | visitIfNeeded(visitor, &thisObject->m_nullPrototypeObjectStructure); | |
375 | visitIfNeeded(visitor, &thisObject->m_errorStructure); | |
376 | visitIfNeeded(visitor, &thisObject->m_functionStructure); | |
377 | visitIfNeeded(visitor, &thisObject->m_boundFunctionStructure); | |
378 | visitIfNeeded(visitor, &thisObject->m_namedFunctionStructure); | |
379 | visitIfNeeded(visitor, &thisObject->m_numberObjectStructure); | |
380 | visitIfNeeded(visitor, &thisObject->m_regExpMatchesArrayStructure); | |
381 | visitIfNeeded(visitor, &thisObject->m_regExpStructure); | |
382 | visitIfNeeded(visitor, &thisObject->m_stringObjectStructure); | |
383 | visitIfNeeded(visitor, &thisObject->m_internalFunctionStructure); | |
384 | ||
385 | if (thisObject->m_registerArray) { | |
14957cd0 A |
386 | // Outside the execution of global code, when our variables are torn off, |
387 | // we can mark the torn-off array. | |
6fe7ccc8 A |
388 | visitor.appendValues(thisObject->m_registerArray.get(), thisObject->m_registerArraySize); |
389 | } else if (thisObject->m_registers) { | |
14957cd0 A |
390 | // During execution of global code, when our variables are in the register file, |
391 | // the symbol table tells us how many variables there are, and registers | |
392 | // points to where they end, and the registers used for execution begin. | |
6fe7ccc8 | 393 | visitor.appendValues(thisObject->m_registers - thisObject->symbolTable().size(), thisObject->symbolTable().size()); |
14957cd0 | 394 | } |
9dae56ea A |
395 | } |
396 | ||
397 | ExecState* JSGlobalObject::globalExec() | |
398 | { | |
14957cd0 | 399 | return CallFrame::create(m_globalCallFrame + RegisterFile::CallFrameHeaderSize); |
9dae56ea A |
400 | } |
401 | ||
6fe7ccc8 | 402 | void JSGlobalObject::resizeRegisters(size_t newSize) |
14957cd0 | 403 | { |
6fe7ccc8 A |
404 | // Previous duplicate symbols may have created spare capacity in m_registerArray. |
405 | if (newSize <= m_registerArraySize) | |
14957cd0 | 406 | return; |
14957cd0 | 407 | |
6fe7ccc8 A |
408 | size_t oldSize = m_registerArraySize; |
409 | OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[newSize]); | |
410 | for (size_t i = 0; i < oldSize; ++i) | |
411 | registerArray[i].set(globalData(), this, m_registerArray[i].get()); | |
412 | for (size_t i = oldSize; i < newSize; ++i) | |
413 | registerArray[i].setUndefined(); | |
14957cd0 | 414 | |
6fe7ccc8 A |
415 | WriteBarrier<Unknown>* registers = registerArray.get(); |
416 | setRegisters(registers, registerArray.release(), newSize); | |
f9bf01c6 A |
417 | } |
418 | ||
14957cd0 A |
419 | void JSGlobalObject::addStaticGlobals(GlobalPropertyInfo* globals, int count) |
420 | { | |
6fe7ccc8 | 421 | resizeRegisters(symbolTable().size() + count); |
14957cd0 | 422 | |
6fe7ccc8 | 423 | for (int i = 0; i < count; ++i) { |
14957cd0 A |
424 | GlobalPropertyInfo& global = globals[i]; |
425 | ASSERT(global.attributes & DontDelete); | |
6fe7ccc8 A |
426 | |
427 | int index = symbolTable().size(); | |
14957cd0 A |
428 | SymbolTableEntry newEntry(index, global.attributes); |
429 | symbolTable().add(global.identifier.impl(), newEntry); | |
430 | registerAt(index).set(globalData(), this, global.value); | |
431 | } | |
432 | } | |
433 | ||
6fe7ccc8 | 434 | bool JSGlobalObject::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot) |
14957cd0 | 435 | { |
6fe7ccc8 A |
436 | JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(cell); |
437 | if (getStaticFunctionSlot<JSVariableObject>(exec, ExecState::globalObjectTable(exec), thisObject, propertyName, slot)) | |
14957cd0 | 438 | return true; |
6fe7ccc8 | 439 | return thisObject->symbolTableGet(propertyName, slot); |
14957cd0 A |
440 | } |
441 | ||
6fe7ccc8 | 442 | bool JSGlobalObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) |
14957cd0 | 443 | { |
6fe7ccc8 A |
444 | JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(object); |
445 | if (getStaticFunctionDescriptor<JSVariableObject>(exec, ExecState::globalObjectTable(exec), thisObject, propertyName, descriptor)) | |
14957cd0 | 446 | return true; |
6fe7ccc8 | 447 | return thisObject->symbolTableGet(propertyName, descriptor); |
14957cd0 A |
448 | } |
449 | ||
6fe7ccc8 | 450 | void JSGlobalObject::clearRareData(JSCell* cell) |
f9bf01c6 | 451 | { |
6fe7ccc8 | 452 | jsCast<JSGlobalObject*>(cell)->m_rareData.clear(); |
9dae56ea A |
453 | } |
454 | ||
14957cd0 A |
455 | DynamicGlobalObjectScope::DynamicGlobalObjectScope(JSGlobalData& globalData, JSGlobalObject* dynamicGlobalObject) |
456 | : m_dynamicGlobalObjectSlot(globalData.dynamicGlobalObject) | |
b80e6193 A |
457 | , m_savedDynamicGlobalObject(m_dynamicGlobalObjectSlot) |
458 | { | |
459 | if (!m_dynamicGlobalObjectSlot) { | |
14957cd0 A |
460 | #if ENABLE(ASSEMBLER) |
461 | if (ExecutableAllocator::underMemoryPressure()) | |
6fe7ccc8 | 462 | globalData.heap.discardAllCompiledCode(); |
b80e6193 | 463 | #endif |
14957cd0 | 464 | |
b80e6193 A |
465 | m_dynamicGlobalObjectSlot = dynamicGlobalObject; |
466 | ||
467 | // Reset the date cache between JS invocations to force the VM | |
468 | // to observe time zone changes. | |
14957cd0 | 469 | globalData.resetDateCache(); |
b80e6193 A |
470 | } |
471 | } | |
472 | ||
14957cd0 A |
473 | void slowValidateCell(JSGlobalObject* globalObject) |
474 | { | |
475 | if (!globalObject->isGlobalObject()) | |
476 | CRASH(); | |
477 | ASSERT_GC_OBJECT_INHERITS(globalObject, &JSGlobalObject::s_info); | |
478 | } | |
479 | ||
9dae56ea | 480 | } // namespace JSC |