]>
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 | ||
9dae56ea A |
33 | #include "Arguments.h" |
34 | #include "ArrayConstructor.h" | |
35 | #include "ArrayPrototype.h" | |
36 | #include "BooleanConstructor.h" | |
37 | #include "BooleanPrototype.h" | |
38 | #include "CodeBlock.h" | |
93a37866 | 39 | #include "CodeCache.h" |
9dae56ea A |
40 | #include "DateConstructor.h" |
41 | #include "DatePrototype.h" | |
93a37866 | 42 | #include "Debugger.h" |
6fe7ccc8 | 43 | #include "Error.h" |
9dae56ea A |
44 | #include "ErrorConstructor.h" |
45 | #include "ErrorPrototype.h" | |
46 | #include "FunctionConstructor.h" | |
47 | #include "FunctionPrototype.h" | |
6fe7ccc8 | 48 | #include "GetterSetter.h" |
93a37866 A |
49 | #include "Interpreter.h" |
50 | #include "JSAPIWrapperObject.h" | |
51 | #include "JSActivation.h" | |
6fe7ccc8 | 52 | #include "JSBoundFunction.h" |
93a37866 A |
53 | #include "JSCallbackConstructor.h" |
54 | #include "JSCallbackFunction.h" | |
55 | #include "JSCallbackObject.h" | |
ba379fdc | 56 | #include "JSFunction.h" |
9dae56ea A |
57 | #include "JSGlobalObjectFunctions.h" |
58 | #include "JSLock.h" | |
93a37866 | 59 | #include "JSNameScope.h" |
ba379fdc | 60 | #include "JSONObject.h" |
93a37866 A |
61 | #include "JSWithScope.h" |
62 | #include "LegacyProfiler.h" | |
14957cd0 | 63 | #include "Lookup.h" |
9dae56ea | 64 | #include "MathObject.h" |
93a37866 A |
65 | #include "NameConstructor.h" |
66 | #include "NameInstance.h" | |
67 | #include "NamePrototype.h" | |
9dae56ea A |
68 | #include "NativeErrorConstructor.h" |
69 | #include "NativeErrorPrototype.h" | |
70 | #include "NumberConstructor.h" | |
71 | #include "NumberPrototype.h" | |
93a37866 | 72 | #include "ObjCCallbackFunction.h" |
9dae56ea A |
73 | #include "ObjectConstructor.h" |
74 | #include "ObjectPrototype.h" | |
93a37866 A |
75 | #include "Operations.h" |
76 | #include "ParserError.h" | |
9dae56ea A |
77 | #include "RegExpConstructor.h" |
78 | #include "RegExpMatchesArray.h" | |
79 | #include "RegExpObject.h" | |
80 | #include "RegExpPrototype.h" | |
93a37866 | 81 | #include "StrictEvalActivation.h" |
9dae56ea A |
82 | #include "StringConstructor.h" |
83 | #include "StringPrototype.h" | |
9dae56ea | 84 | |
14957cd0 A |
85 | #include "JSGlobalObject.lut.h" |
86 | ||
9dae56ea A |
87 | namespace JSC { |
88 | ||
93a37866 | 89 | const ClassInfo JSGlobalObject::s_info = { "GlobalObject", &Base::s_info, 0, ExecState::globalObjectTable, CREATE_METHOD_TABLE(JSGlobalObject) }; |
6fe7ccc8 | 90 | |
93a37866 A |
91 | const GlobalObjectMethodTable JSGlobalObject::s_globalObjectMethodTable = { &allowsAccessFrom, &supportsProfiling, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptExperimentsEnabled |
92 | #if PLATFORM(IOS) | |
6fe7ccc8 | 93 | , &shouldInterruptScriptBeforeTimeout |
93a37866 | 94 | #endif |
6fe7ccc8 | 95 | }; |
14957cd0 A |
96 | |
97 | /* Source for JSGlobalObject.lut.h | |
98 | @begin globalObjectTable | |
99 | parseInt globalFuncParseInt DontEnum|Function 2 | |
100 | parseFloat globalFuncParseFloat DontEnum|Function 1 | |
101 | isNaN globalFuncIsNaN DontEnum|Function 1 | |
102 | isFinite globalFuncIsFinite DontEnum|Function 1 | |
103 | escape globalFuncEscape DontEnum|Function 1 | |
104 | unescape globalFuncUnescape DontEnum|Function 1 | |
105 | decodeURI globalFuncDecodeURI DontEnum|Function 1 | |
106 | decodeURIComponent globalFuncDecodeURIComponent DontEnum|Function 1 | |
107 | encodeURI globalFuncEncodeURI DontEnum|Function 1 | |
108 | encodeURIComponent globalFuncEncodeURIComponent DontEnum|Function 1 | |
109 | @end | |
110 | */ | |
111 | ||
93a37866 A |
112 | JSGlobalObject::JSGlobalObject(VM& vm, Structure* structure, const GlobalObjectMethodTable* globalObjectMethodTable) |
113 | : Base(vm, structure, 0) | |
114 | , m_masqueradesAsUndefinedWatchpoint(adoptRef(new WatchpointSet(InitializedWatching))) | |
115 | , m_havingABadTimeWatchpoint(adoptRef(new WatchpointSet(InitializedWatching))) | |
116 | , m_weakRandom(Options::forceWeakRandomSeed() ? Options::forcedWeakRandomSeed() : static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0))) | |
117 | , m_evalEnabled(true) | |
118 | , m_globalObjectMethodTable(globalObjectMethodTable ? globalObjectMethodTable : &s_globalObjectMethodTable) | |
9dae56ea | 119 | { |
9dae56ea A |
120 | } |
121 | ||
122 | JSGlobalObject::~JSGlobalObject() | |
123 | { | |
14957cd0 A |
124 | if (m_debugger) |
125 | m_debugger->detach(this); | |
9dae56ea | 126 | |
93a37866 A |
127 | if (LegacyProfiler* profiler = vm().enabledProfiler()) |
128 | profiler->stopProfiling(this); | |
9dae56ea A |
129 | } |
130 | ||
6fe7ccc8 A |
131 | void JSGlobalObject::destroy(JSCell* cell) |
132 | { | |
93a37866 A |
133 | static_cast<JSGlobalObject*>(cell)->JSGlobalObject::~JSGlobalObject(); |
134 | } | |
135 | ||
136 | void JSGlobalObject::setGlobalThis(VM& vm, JSObject* globalThis) | |
137 | { | |
138 | m_globalThis.set(vm, this, globalThis); | |
6fe7ccc8 A |
139 | } |
140 | ||
9dae56ea A |
141 | void JSGlobalObject::init(JSObject* thisValue) |
142 | { | |
93a37866 | 143 | ASSERT(vm().apiLock().currentThreadIsHoldingLock()); |
9dae56ea | 144 | |
93a37866 A |
145 | setGlobalThis(vm(), thisValue); |
146 | JSGlobalObject::globalExec()->init(0, 0, this, CallFrame::noCaller(), 0, 0); | |
9dae56ea | 147 | |
14957cd0 | 148 | m_debugger = 0; |
9dae56ea | 149 | |
9dae56ea A |
150 | reset(prototype()); |
151 | } | |
152 | ||
93a37866 | 153 | void JSGlobalObject::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot) |
9dae56ea | 154 | { |
6fe7ccc8 A |
155 | JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(cell); |
156 | ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(thisObject)); | |
9dae56ea | 157 | |
93a37866 | 158 | if (symbolTablePut(thisObject, exec, propertyName, value, slot.isStrictMode())) |
9dae56ea | 159 | return; |
93a37866 | 160 | Base::put(thisObject, exec, propertyName, value, slot); |
9dae56ea A |
161 | } |
162 | ||
93a37866 | 163 | void JSGlobalObject::putDirectVirtual(JSObject* object, ExecState* exec, PropertyName propertyName, JSValue value, unsigned attributes) |
9dae56ea | 164 | { |
6fe7ccc8 A |
165 | JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(object); |
166 | ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(thisObject)); | |
9dae56ea | 167 | |
93a37866 | 168 | if (symbolTablePutWithAttributes(thisObject, exec->vm(), propertyName, value, attributes)) |
9dae56ea A |
169 | return; |
170 | ||
93a37866 | 171 | JSValue valueBefore = thisObject->getDirect(exec->vm(), propertyName); |
9dae56ea | 172 | PutPropertySlot slot; |
93a37866 | 173 | Base::put(thisObject, exec, propertyName, value, slot); |
9dae56ea | 174 | if (!valueBefore) { |
93a37866 | 175 | JSValue valueAfter = thisObject->getDirect(exec->vm(), propertyName); |
9dae56ea | 176 | if (valueAfter) |
6fe7ccc8 | 177 | JSObject::putDirectVirtual(thisObject, exec, propertyName, valueAfter, attributes); |
9dae56ea A |
178 | } |
179 | } | |
180 | ||
93a37866 | 181 | bool JSGlobalObject::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor, bool shouldThrow) |
9dae56ea | 182 | { |
6fe7ccc8 | 183 | JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(object); |
9dae56ea | 184 | PropertySlot slot; |
6fe7ccc8 | 185 | // silently ignore attempts to add accessors aliasing vars. |
93a37866 | 186 | if (descriptor.isAccessorDescriptor() && symbolTableGet(thisObject, propertyName, slot)) |
6fe7ccc8 A |
187 | return false; |
188 | return Base::defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow); | |
9dae56ea A |
189 | } |
190 | ||
9dae56ea A |
191 | |
192 | static inline JSObject* lastInPrototypeChain(JSObject* object) | |
193 | { | |
194 | JSObject* o = object; | |
195 | while (o->prototype().isObject()) | |
196 | o = asObject(o->prototype()); | |
197 | return o; | |
198 | } | |
199 | ||
ba379fdc | 200 | void JSGlobalObject::reset(JSValue prototype) |
9dae56ea A |
201 | { |
202 | ExecState* exec = JSGlobalObject::globalExec(); | |
203 | ||
93a37866 A |
204 | m_functionPrototype.set(exec->vm(), this, FunctionPrototype::create(exec, this, FunctionPrototype::createStructure(exec->vm(), this, jsNull()))); // The real prototype will be set once ObjectPrototype is created. |
205 | m_functionStructure.set(exec->vm(), this, JSFunction::createStructure(exec->vm(), this, m_functionPrototype.get())); | |
206 | m_boundFunctionStructure.set(exec->vm(), this, JSBoundFunction::createStructure(exec->vm(), this, m_functionPrototype.get())); | |
207 | m_namedFunctionStructure.set(exec->vm(), this, Structure::addPropertyTransition(exec->vm(), m_functionStructure.get(), exec->vm().propertyNames->name, DontDelete | ReadOnly | DontEnum, 0, m_functionNameOffset)); | |
208 | m_internalFunctionStructure.set(exec->vm(), this, InternalFunction::createStructure(exec->vm(), this, m_functionPrototype.get())); | |
14957cd0 A |
209 | JSFunction* callFunction = 0; |
210 | JSFunction* applyFunction = 0; | |
6fe7ccc8 | 211 | m_functionPrototype->addFunctionProperties(exec, this, &callFunction, &applyFunction); |
93a37866 A |
212 | m_callFunction.set(exec->vm(), this, callFunction); |
213 | m_applyFunction.set(exec->vm(), this, applyFunction); | |
214 | m_objectPrototype.set(exec->vm(), this, ObjectPrototype::create(exec, this, ObjectPrototype::createStructure(exec->vm(), this, jsNull()))); | |
6fe7ccc8 | 215 | GetterSetter* protoAccessor = GetterSetter::create(exec); |
93a37866 A |
216 | protoAccessor->setGetter(exec->vm(), JSFunction::create(exec, this, 0, String(), globalFuncProtoGetter)); |
217 | protoAccessor->setSetter(exec->vm(), JSFunction::create(exec, this, 0, String(), globalFuncProtoSetter)); | |
218 | m_objectPrototype->putDirectAccessor(exec, exec->propertyNames().underscoreProto, protoAccessor, Accessor | DontEnum); | |
219 | m_functionPrototype->structure()->setPrototypeWithoutTransition(exec->vm(), m_objectPrototype.get()); | |
220 | ||
221 | m_nameScopeStructure.set(exec->vm(), this, JSNameScope::createStructure(exec->vm(), this, jsNull())); | |
222 | m_activationStructure.set(exec->vm(), this, JSActivation::createStructure(exec->vm(), this, jsNull())); | |
223 | m_strictEvalActivationStructure.set(exec->vm(), this, StrictEvalActivation::createStructure(exec->vm(), this, jsNull())); | |
224 | m_withScopeStructure.set(exec->vm(), this, JSWithScope::createStructure(exec->vm(), this, jsNull())); | |
225 | ||
226 | m_nullPrototypeObjectStructure.set(exec->vm(), this, JSFinalObject::createStructure(vm(), this, jsNull(), JSFinalObject::defaultInlineCapacity())); | |
227 | ||
228 | m_callbackFunctionStructure.set(exec->vm(), this, JSCallbackFunction::createStructure(exec->vm(), this, m_functionPrototype.get())); | |
229 | m_argumentsStructure.set(exec->vm(), this, Arguments::createStructure(exec->vm(), this, m_objectPrototype.get())); | |
230 | m_callbackConstructorStructure.set(exec->vm(), this, JSCallbackConstructor::createStructure(exec->vm(), this, m_objectPrototype.get())); | |
231 | m_callbackObjectStructure.set(exec->vm(), this, JSCallbackObject<JSDestructibleObject>::createStructure(exec->vm(), this, m_objectPrototype.get())); | |
232 | #if JSC_OBJC_API_ENABLED | |
233 | m_objcCallbackFunctionStructure.set(exec->vm(), this, ObjCCallbackFunction::createStructure(exec->vm(), this, m_functionPrototype.get())); | |
234 | m_objcWrapperObjectStructure.set(exec->vm(), this, JSCallbackObject<JSAPIWrapperObject>::createStructure(exec->vm(), this, m_objectPrototype.get())); | |
235 | #endif | |
9dae56ea | 236 | |
93a37866 A |
237 | m_arrayPrototype.set(exec->vm(), this, ArrayPrototype::create(exec, this, ArrayPrototype::createStructure(exec->vm(), this, m_objectPrototype.get()))); |
238 | ||
239 | m_originalArrayStructureForIndexingShape[UndecidedShape >> IndexingShapeShift].set(exec->vm(), this, JSArray::createStructure(exec->vm(), this, m_arrayPrototype.get(), ArrayWithUndecided)); | |
240 | m_originalArrayStructureForIndexingShape[Int32Shape >> IndexingShapeShift].set(exec->vm(), this, JSArray::createStructure(exec->vm(), this, m_arrayPrototype.get(), ArrayWithInt32)); | |
241 | m_originalArrayStructureForIndexingShape[DoubleShape >> IndexingShapeShift].set(exec->vm(), this, JSArray::createStructure(exec->vm(), this, m_arrayPrototype.get(), ArrayWithDouble)); | |
242 | m_originalArrayStructureForIndexingShape[ContiguousShape >> IndexingShapeShift].set(exec->vm(), this, JSArray::createStructure(exec->vm(), this, m_arrayPrototype.get(), ArrayWithContiguous)); | |
243 | m_originalArrayStructureForIndexingShape[ArrayStorageShape >> IndexingShapeShift].set(exec->vm(), this, JSArray::createStructure(exec->vm(), this, m_arrayPrototype.get(), ArrayWithArrayStorage)); | |
244 | m_originalArrayStructureForIndexingShape[SlowPutArrayStorageShape >> IndexingShapeShift].set(exec->vm(), this, JSArray::createStructure(exec->vm(), this, m_arrayPrototype.get(), ArrayWithSlowPutArrayStorage)); | |
245 | for (unsigned i = 0; i < NumberOfIndexingShapes; ++i) | |
246 | m_arrayStructureForIndexingShapeDuringAllocation[i] = m_originalArrayStructureForIndexingShape[i]; | |
247 | ||
248 | m_regExpMatchesArrayStructure.set(exec->vm(), this, RegExpMatchesArray::createStructure(exec->vm(), this, m_arrayPrototype.get())); | |
9dae56ea | 249 | |
93a37866 A |
250 | m_stringPrototype.set(exec->vm(), this, StringPrototype::create(exec, this, StringPrototype::createStructure(exec->vm(), this, m_objectPrototype.get()))); |
251 | m_stringObjectStructure.set(exec->vm(), this, StringObject::createStructure(exec->vm(), this, m_stringPrototype.get())); | |
9dae56ea | 252 | |
93a37866 A |
253 | m_booleanPrototype.set(exec->vm(), this, BooleanPrototype::create(exec, this, BooleanPrototype::createStructure(exec->vm(), this, m_objectPrototype.get()))); |
254 | m_booleanObjectStructure.set(exec->vm(), this, BooleanObject::createStructure(exec->vm(), this, m_booleanPrototype.get())); | |
9dae56ea | 255 | |
93a37866 A |
256 | m_numberPrototype.set(exec->vm(), this, NumberPrototype::create(exec, this, NumberPrototype::createStructure(exec->vm(), this, m_objectPrototype.get()))); |
257 | m_numberObjectStructure.set(exec->vm(), this, NumberObject::createStructure(exec->vm(), this, m_numberPrototype.get())); | |
9dae56ea | 258 | |
93a37866 A |
259 | m_datePrototype.set(exec->vm(), this, DatePrototype::create(exec, this, DatePrototype::createStructure(exec->vm(), this, m_objectPrototype.get()))); |
260 | m_dateStructure.set(exec->vm(), this, DateInstance::createStructure(exec->vm(), this, m_datePrototype.get())); | |
9dae56ea | 261 | |
93a37866 | 262 | RegExp* emptyRegex = RegExp::create(exec->vm(), "", NoFlags); |
14957cd0 | 263 | |
93a37866 A |
264 | m_regExpPrototype.set(exec->vm(), this, RegExpPrototype::create(exec, this, RegExpPrototype::createStructure(exec->vm(), this, m_objectPrototype.get()), emptyRegex)); |
265 | m_regExpStructure.set(exec->vm(), this, RegExpObject::createStructure(exec->vm(), this, m_regExpPrototype.get())); | |
9dae56ea | 266 | |
93a37866 A |
267 | m_errorPrototype.set(exec->vm(), this, ErrorPrototype::create(exec, this, ErrorPrototype::createStructure(exec->vm(), this, m_objectPrototype.get()))); |
268 | m_errorStructure.set(exec->vm(), this, ErrorInstance::createStructure(exec->vm(), this, m_errorPrototype.get())); | |
9dae56ea | 269 | |
9dae56ea A |
270 | // Constructors |
271 | ||
93a37866 A |
272 | JSCell* objectConstructor = ObjectConstructor::create(exec, this, ObjectConstructor::createStructure(exec->vm(), this, m_functionPrototype.get()), m_objectPrototype.get()); |
273 | JSCell* functionConstructor = FunctionConstructor::create(exec, this, FunctionConstructor::createStructure(exec->vm(), this, m_functionPrototype.get()), m_functionPrototype.get()); | |
274 | JSCell* arrayConstructor = ArrayConstructor::create(exec, this, ArrayConstructor::createStructure(exec->vm(), this, m_functionPrototype.get()), m_arrayPrototype.get()); | |
275 | JSCell* stringConstructor = StringConstructor::create(exec, this, StringConstructor::createStructure(exec->vm(), this, m_functionPrototype.get()), m_stringPrototype.get()); | |
276 | JSCell* booleanConstructor = BooleanConstructor::create(exec, this, BooleanConstructor::createStructure(exec->vm(), this, m_functionPrototype.get()), m_booleanPrototype.get()); | |
277 | JSCell* numberConstructor = NumberConstructor::create(exec, this, NumberConstructor::createStructure(exec->vm(), this, m_functionPrototype.get()), m_numberPrototype.get()); | |
278 | JSCell* dateConstructor = DateConstructor::create(exec, this, DateConstructor::createStructure(exec->vm(), this, m_functionPrototype.get()), m_datePrototype.get()); | |
279 | ||
280 | m_regExpConstructor.set(exec->vm(), this, RegExpConstructor::create(exec, this, RegExpConstructor::createStructure(exec->vm(), this, m_functionPrototype.get()), m_regExpPrototype.get())); | |
281 | ||
282 | m_errorConstructor.set(exec->vm(), this, ErrorConstructor::create(exec, this, ErrorConstructor::createStructure(exec->vm(), this, m_functionPrototype.get()), m_errorPrototype.get())); | |
283 | ||
284 | Structure* nativeErrorPrototypeStructure = NativeErrorPrototype::createStructure(exec->vm(), this, m_errorPrototype.get()); | |
285 | Structure* nativeErrorStructure = NativeErrorConstructor::createStructure(exec->vm(), this, m_functionPrototype.get()); | |
286 | m_evalErrorConstructor.set(exec->vm(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, ASCIILiteral("EvalError"))); | |
287 | m_rangeErrorConstructor.set(exec->vm(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, ASCIILiteral("RangeError"))); | |
288 | m_referenceErrorConstructor.set(exec->vm(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, ASCIILiteral("ReferenceError"))); | |
289 | m_syntaxErrorConstructor.set(exec->vm(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, ASCIILiteral("SyntaxError"))); | |
290 | m_typeErrorConstructor.set(exec->vm(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, ASCIILiteral("TypeError"))); | |
291 | m_URIErrorConstructor.set(exec->vm(), this, NativeErrorConstructor::create(exec, this, nativeErrorStructure, nativeErrorPrototypeStructure, ASCIILiteral("URIError"))); | |
292 | ||
293 | m_objectPrototype->putDirectWithoutTransition(exec->vm(), exec->propertyNames().constructor, objectConstructor, DontEnum); | |
294 | m_functionPrototype->putDirectWithoutTransition(exec->vm(), exec->propertyNames().constructor, functionConstructor, DontEnum); | |
295 | m_arrayPrototype->putDirectWithoutTransition(exec->vm(), exec->propertyNames().constructor, arrayConstructor, DontEnum); | |
296 | m_booleanPrototype->putDirectWithoutTransition(exec->vm(), exec->propertyNames().constructor, booleanConstructor, DontEnum); | |
297 | m_stringPrototype->putDirectWithoutTransition(exec->vm(), exec->propertyNames().constructor, stringConstructor, DontEnum); | |
298 | m_numberPrototype->putDirectWithoutTransition(exec->vm(), exec->propertyNames().constructor, numberConstructor, DontEnum); | |
299 | m_datePrototype->putDirectWithoutTransition(exec->vm(), exec->propertyNames().constructor, dateConstructor, DontEnum); | |
300 | m_regExpPrototype->putDirectWithoutTransition(exec->vm(), exec->propertyNames().constructor, m_regExpConstructor.get(), DontEnum); | |
301 | m_errorPrototype->putDirectWithoutTransition(exec->vm(), exec->propertyNames().constructor, m_errorConstructor.get(), DontEnum); | |
302 | ||
303 | putDirectWithoutTransition(exec->vm(), exec->propertyNames().Object, objectConstructor, DontEnum); | |
304 | putDirectWithoutTransition(exec->vm(), exec->propertyNames().Function, functionConstructor, DontEnum); | |
305 | putDirectWithoutTransition(exec->vm(), exec->propertyNames().Array, arrayConstructor, DontEnum); | |
306 | putDirectWithoutTransition(exec->vm(), exec->propertyNames().Boolean, booleanConstructor, DontEnum); | |
307 | putDirectWithoutTransition(exec->vm(), exec->propertyNames().String, stringConstructor, DontEnum); | |
308 | putDirectWithoutTransition(exec->vm(), exec->propertyNames().Number, numberConstructor, DontEnum); | |
309 | putDirectWithoutTransition(exec->vm(), exec->propertyNames().Date, dateConstructor, DontEnum); | |
310 | putDirectWithoutTransition(exec->vm(), exec->propertyNames().RegExp, m_regExpConstructor.get(), DontEnum); | |
311 | putDirectWithoutTransition(exec->vm(), exec->propertyNames().Error, m_errorConstructor.get(), DontEnum); | |
312 | putDirectWithoutTransition(exec->vm(), exec->propertyNames().EvalError, m_evalErrorConstructor.get(), DontEnum); | |
313 | putDirectWithoutTransition(exec->vm(), exec->propertyNames().RangeError, m_rangeErrorConstructor.get(), DontEnum); | |
314 | putDirectWithoutTransition(exec->vm(), exec->propertyNames().ReferenceError, m_referenceErrorConstructor.get(), DontEnum); | |
315 | putDirectWithoutTransition(exec->vm(), exec->propertyNames().SyntaxError, m_syntaxErrorConstructor.get(), DontEnum); | |
316 | putDirectWithoutTransition(exec->vm(), exec->propertyNames().TypeError, m_typeErrorConstructor.get(), DontEnum); | |
317 | putDirectWithoutTransition(exec->vm(), exec->propertyNames().URIError, m_URIErrorConstructor.get(), DontEnum); | |
318 | ||
319 | m_evalFunction.set(exec->vm(), this, JSFunction::create(exec, this, 1, exec->propertyNames().eval.string(), globalFuncEval)); | |
320 | putDirectWithoutTransition(exec->vm(), exec->propertyNames().eval, m_evalFunction.get(), DontEnum); | |
321 | ||
322 | putDirectWithoutTransition(exec->vm(), exec->propertyNames().JSON, JSONObject::create(exec, this, JSONObject::createStructure(exec->vm(), this, m_objectPrototype.get())), DontEnum); | |
323 | putDirectWithoutTransition(exec->vm(), exec->propertyNames().Math, MathObject::create(exec, this, MathObject::createStructure(exec->vm(), this, m_objectPrototype.get())), DontEnum); | |
14957cd0 | 324 | |
9dae56ea | 325 | GlobalPropertyInfo staticGlobals[] = { |
93a37866 A |
326 | GlobalPropertyInfo(exec->propertyNames().NaN, jsNaN(), DontEnum | DontDelete | ReadOnly), |
327 | GlobalPropertyInfo(exec->propertyNames().Infinity, jsNumber(std::numeric_limits<double>::infinity()), DontEnum | DontDelete | ReadOnly), | |
328 | GlobalPropertyInfo(exec->propertyNames().undefinedKeyword, jsUndefined(), DontEnum | DontDelete | ReadOnly) | |
9dae56ea | 329 | }; |
14957cd0 | 330 | addStaticGlobals(staticGlobals, WTF_ARRAY_LENGTH(staticGlobals)); |
93a37866 A |
331 | |
332 | m_specialPointers[Special::CallFunction] = m_callFunction.get(); | |
333 | m_specialPointers[Special::ApplyFunction] = m_applyFunction.get(); | |
334 | m_specialPointers[Special::ObjectConstructor] = objectConstructor; | |
335 | m_specialPointers[Special::ArrayConstructor] = arrayConstructor; | |
336 | ||
337 | if (m_experimentsEnabled) { | |
338 | NamePrototype* privateNamePrototype = NamePrototype::create(exec, NamePrototype::createStructure(exec->vm(), this, m_objectPrototype.get())); | |
339 | m_privateNameStructure.set(exec->vm(), this, NameInstance::createStructure(exec->vm(), this, privateNamePrototype)); | |
340 | ||
341 | JSCell* privateNameConstructor = NameConstructor::create(exec, this, NameConstructor::createStructure(exec->vm(), this, m_functionPrototype.get()), privateNamePrototype); | |
342 | privateNamePrototype->putDirectWithoutTransition(exec->vm(), exec->propertyNames().constructor, privateNameConstructor, DontEnum); | |
343 | putDirectWithoutTransition(exec->vm(), Identifier(exec, "Name"), privateNameConstructor, DontEnum); | |
344 | } | |
345 | ||
346 | resetPrototype(exec->vm(), prototype); | |
347 | } | |
9dae56ea | 348 | |
93a37866 A |
349 | // Private namespace for helpers for JSGlobalObject::haveABadTime() |
350 | namespace { | |
351 | ||
352 | class ObjectsWithBrokenIndexingFinder : public MarkedBlock::VoidFunctor { | |
353 | public: | |
354 | ObjectsWithBrokenIndexingFinder(MarkedArgumentBuffer&, JSGlobalObject*); | |
355 | void operator()(JSCell*); | |
356 | ||
357 | private: | |
358 | MarkedArgumentBuffer& m_foundObjects; | |
359 | JSGlobalObject* m_globalObject; | |
360 | }; | |
361 | ||
362 | ObjectsWithBrokenIndexingFinder::ObjectsWithBrokenIndexingFinder( | |
363 | MarkedArgumentBuffer& foundObjects, JSGlobalObject* globalObject) | |
364 | : m_foundObjects(foundObjects) | |
365 | , m_globalObject(globalObject) | |
366 | { | |
367 | } | |
368 | ||
369 | inline bool hasBrokenIndexing(JSObject* object) | |
370 | { | |
371 | // This will change if we have more indexing types. | |
372 | IndexingType type = object->structure()->indexingType(); | |
373 | // This could be made obviously more efficient, but isn't made so right now, because | |
374 | // we expect this to be an unlikely slow path anyway. | |
375 | return hasUndecided(type) || hasInt32(type) || hasDouble(type) || hasContiguous(type) || hasFastArrayStorage(type); | |
376 | } | |
377 | ||
378 | void ObjectsWithBrokenIndexingFinder::operator()(JSCell* cell) | |
379 | { | |
380 | if (!cell->isObject()) | |
381 | return; | |
382 | ||
383 | JSObject* object = asObject(cell); | |
384 | ||
385 | // Run this filter first, since it's cheap, and ought to filter out a lot of objects. | |
386 | if (!hasBrokenIndexing(object)) | |
387 | return; | |
388 | ||
389 | // We only want to have a bad time in the affected global object, not in the entire | |
390 | // VM. But we have to be careful, since there may be objects that claim to belong to | |
391 | // a different global object that have prototypes from our global object. | |
392 | bool foundGlobalObject = false; | |
393 | for (JSObject* current = object; ;) { | |
394 | if (current->globalObject() == m_globalObject) { | |
395 | foundGlobalObject = true; | |
396 | break; | |
397 | } | |
398 | ||
399 | JSValue prototypeValue = current->prototype(); | |
400 | if (prototypeValue.isNull()) | |
401 | break; | |
402 | current = asObject(prototypeValue); | |
403 | } | |
404 | if (!foundGlobalObject) | |
405 | return; | |
406 | ||
407 | m_foundObjects.append(object); | |
408 | } | |
409 | ||
410 | } // end private namespace for helpers for JSGlobalObject::haveABadTime() | |
411 | ||
412 | void JSGlobalObject::haveABadTime(VM& vm) | |
413 | { | |
414 | ASSERT(&vm == &this->vm()); | |
415 | ||
416 | if (isHavingABadTime()) | |
417 | return; | |
418 | ||
419 | // Make sure that all allocations or indexed storage transitions that are inlining | |
420 | // the assumption that it's safe to transition to a non-SlowPut array storage don't | |
421 | // do so anymore. | |
422 | m_havingABadTimeWatchpoint->notifyWrite(); | |
423 | ASSERT(isHavingABadTime()); // The watchpoint is what tells us that we're having a bad time. | |
424 | ||
425 | // Make sure that all JSArray allocations that load the appropriate structure from | |
426 | // this object now load a structure that uses SlowPut. | |
427 | for (unsigned i = 0; i < NumberOfIndexingShapes; ++i) | |
428 | m_arrayStructureForIndexingShapeDuringAllocation[i].set(vm, this, originalArrayStructureForIndexingType(ArrayWithSlowPutArrayStorage)); | |
429 | ||
430 | // Make sure that all objects that have indexed storage switch to the slow kind of | |
431 | // indexed storage. | |
432 | MarkedArgumentBuffer foundObjects; // Use MarkedArgumentBuffer because switchToSlowPutArrayStorage() may GC. | |
433 | ObjectsWithBrokenIndexingFinder finder(foundObjects, this); | |
434 | vm.heap.objectSpace().forEachLiveCell(finder); | |
435 | while (!foundObjects.isEmpty()) { | |
436 | JSObject* object = asObject(foundObjects.last()); | |
437 | foundObjects.removeLast(); | |
438 | ASSERT(hasBrokenIndexing(object)); | |
439 | object->switchToSlowPutArrayStorage(vm); | |
440 | } | |
441 | } | |
442 | ||
443 | bool JSGlobalObject::arrayPrototypeChainIsSane() | |
444 | { | |
445 | return !hasIndexedProperties(m_arrayPrototype->structure()->indexingType()) | |
446 | && m_arrayPrototype->prototype() == m_objectPrototype.get() | |
447 | && !hasIndexedProperties(m_objectPrototype->structure()->indexingType()) | |
448 | && m_objectPrototype->prototype().isNull(); | |
9dae56ea A |
449 | } |
450 | ||
6fe7ccc8 A |
451 | void JSGlobalObject::createThrowTypeError(ExecState* exec) |
452 | { | |
93a37866 | 453 | JSFunction* thrower = JSFunction::create(exec, this, 0, String(), globalFuncThrowTypeError); |
6fe7ccc8 | 454 | GetterSetter* getterSetter = GetterSetter::create(exec); |
93a37866 A |
455 | getterSetter->setGetter(exec->vm(), thrower); |
456 | getterSetter->setSetter(exec->vm(), thrower); | |
457 | m_throwTypeErrorGetterSetter.set(exec->vm(), this, getterSetter); | |
6fe7ccc8 A |
458 | } |
459 | ||
9dae56ea | 460 | // Set prototype, and also insert the object prototype at the end of the chain. |
93a37866 | 461 | void JSGlobalObject::resetPrototype(VM& vm, JSValue prototype) |
9dae56ea | 462 | { |
93a37866 | 463 | setPrototype(vm, prototype); |
9dae56ea | 464 | |
ba379fdc | 465 | JSObject* oldLastInPrototypeChain = lastInPrototypeChain(this); |
14957cd0 | 466 | JSObject* objectPrototype = m_objectPrototype.get(); |
ba379fdc | 467 | if (oldLastInPrototypeChain != objectPrototype) |
93a37866 | 468 | oldLastInPrototypeChain->setPrototype(vm, objectPrototype); |
9dae56ea A |
469 | } |
470 | ||
6fe7ccc8 A |
471 | void JSGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor) |
472 | { | |
473 | JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(cell); | |
474 | ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info); | |
14957cd0 | 475 | COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); |
6fe7ccc8 | 476 | ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); |
93a37866 A |
477 | Base::visitChildren(thisObject, visitor); |
478 | ||
479 | visitor.append(&thisObject->m_globalThis); | |
480 | ||
481 | visitor.append(&thisObject->m_regExpConstructor); | |
482 | visitor.append(&thisObject->m_errorConstructor); | |
483 | visitor.append(&thisObject->m_evalErrorConstructor); | |
484 | visitor.append(&thisObject->m_rangeErrorConstructor); | |
485 | visitor.append(&thisObject->m_referenceErrorConstructor); | |
486 | visitor.append(&thisObject->m_syntaxErrorConstructor); | |
487 | visitor.append(&thisObject->m_typeErrorConstructor); | |
488 | visitor.append(&thisObject->m_URIErrorConstructor); | |
489 | ||
490 | visitor.append(&thisObject->m_evalFunction); | |
491 | visitor.append(&thisObject->m_callFunction); | |
492 | visitor.append(&thisObject->m_applyFunction); | |
493 | visitor.append(&thisObject->m_throwTypeErrorGetterSetter); | |
494 | ||
495 | visitor.append(&thisObject->m_objectPrototype); | |
496 | visitor.append(&thisObject->m_functionPrototype); | |
497 | visitor.append(&thisObject->m_arrayPrototype); | |
498 | visitor.append(&thisObject->m_booleanPrototype); | |
499 | visitor.append(&thisObject->m_stringPrototype); | |
500 | visitor.append(&thisObject->m_numberPrototype); | |
501 | visitor.append(&thisObject->m_datePrototype); | |
502 | visitor.append(&thisObject->m_regExpPrototype); | |
503 | visitor.append(&thisObject->m_errorPrototype); | |
504 | ||
505 | visitor.append(&thisObject->m_withScopeStructure); | |
506 | visitor.append(&thisObject->m_strictEvalActivationStructure); | |
507 | visitor.append(&thisObject->m_activationStructure); | |
508 | visitor.append(&thisObject->m_nameScopeStructure); | |
509 | visitor.append(&thisObject->m_argumentsStructure); | |
510 | for (unsigned i = 0; i < NumberOfIndexingShapes; ++i) | |
511 | visitor.append(&thisObject->m_originalArrayStructureForIndexingShape[i]); | |
512 | for (unsigned i = 0; i < NumberOfIndexingShapes; ++i) | |
513 | visitor.append(&thisObject->m_arrayStructureForIndexingShapeDuringAllocation[i]); | |
514 | visitor.append(&thisObject->m_booleanObjectStructure); | |
515 | visitor.append(&thisObject->m_callbackConstructorStructure); | |
516 | visitor.append(&thisObject->m_callbackFunctionStructure); | |
517 | visitor.append(&thisObject->m_callbackObjectStructure); | |
518 | #if JSC_OBJC_API_ENABLED | |
519 | visitor.append(&thisObject->m_objcCallbackFunctionStructure); | |
520 | visitor.append(&thisObject->m_objcWrapperObjectStructure); | |
521 | #endif | |
522 | visitor.append(&thisObject->m_dateStructure); | |
523 | visitor.append(&thisObject->m_nullPrototypeObjectStructure); | |
524 | visitor.append(&thisObject->m_errorStructure); | |
525 | visitor.append(&thisObject->m_functionStructure); | |
526 | visitor.append(&thisObject->m_boundFunctionStructure); | |
527 | visitor.append(&thisObject->m_namedFunctionStructure); | |
528 | visitor.append(&thisObject->m_numberObjectStructure); | |
529 | visitor.append(&thisObject->m_privateNameStructure); | |
530 | visitor.append(&thisObject->m_regExpMatchesArrayStructure); | |
531 | visitor.append(&thisObject->m_regExpStructure); | |
532 | visitor.append(&thisObject->m_stringObjectStructure); | |
533 | visitor.append(&thisObject->m_internalFunctionStructure); | |
9dae56ea A |
534 | } |
535 | ||
93a37866 | 536 | JSObject* JSGlobalObject::toThisObject(JSCell* cell, ExecState*) |
9dae56ea | 537 | { |
93a37866 | 538 | return jsCast<JSGlobalObject*>(cell)->globalThis(); |
9dae56ea A |
539 | } |
540 | ||
93a37866 | 541 | ExecState* JSGlobalObject::globalExec() |
14957cd0 | 542 | { |
93a37866 | 543 | return CallFrame::create(m_globalCallFrame + JSStack::CallFrameHeaderSize); |
f9bf01c6 A |
544 | } |
545 | ||
14957cd0 A |
546 | void JSGlobalObject::addStaticGlobals(GlobalPropertyInfo* globals, int count) |
547 | { | |
93a37866 | 548 | addRegisters(count); |
14957cd0 | 549 | |
6fe7ccc8 | 550 | for (int i = 0; i < count; ++i) { |
14957cd0 A |
551 | GlobalPropertyInfo& global = globals[i]; |
552 | ASSERT(global.attributes & DontDelete); | |
6fe7ccc8 | 553 | |
93a37866 | 554 | int index = symbolTable()->size(); |
14957cd0 | 555 | SymbolTableEntry newEntry(index, global.attributes); |
93a37866 A |
556 | symbolTable()->add(global.identifier.impl(), newEntry); |
557 | registerAt(index).set(vm(), this, global.value); | |
14957cd0 A |
558 | } |
559 | } | |
560 | ||
93a37866 | 561 | bool JSGlobalObject::getOwnPropertySlot(JSCell* cell, ExecState* exec, PropertyName propertyName, PropertySlot& slot) |
14957cd0 | 562 | { |
6fe7ccc8 | 563 | JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(cell); |
93a37866 | 564 | if (getStaticFunctionSlot<Base>(exec, ExecState::globalObjectTable(exec), thisObject, propertyName, slot)) |
14957cd0 | 565 | return true; |
93a37866 | 566 | return symbolTableGet(thisObject, propertyName, slot); |
14957cd0 A |
567 | } |
568 | ||
93a37866 | 569 | bool JSGlobalObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor) |
14957cd0 | 570 | { |
6fe7ccc8 | 571 | JSGlobalObject* thisObject = jsCast<JSGlobalObject*>(object); |
93a37866 | 572 | if (getStaticFunctionDescriptor<Base>(exec, ExecState::globalObjectTable(exec), thisObject, propertyName, descriptor)) |
14957cd0 | 573 | return true; |
93a37866 | 574 | return symbolTableGet(thisObject, propertyName, descriptor); |
14957cd0 A |
575 | } |
576 | ||
6fe7ccc8 | 577 | void JSGlobalObject::clearRareData(JSCell* cell) |
f9bf01c6 | 578 | { |
6fe7ccc8 | 579 | jsCast<JSGlobalObject*>(cell)->m_rareData.clear(); |
9dae56ea A |
580 | } |
581 | ||
93a37866 A |
582 | DynamicGlobalObjectScope::DynamicGlobalObjectScope(VM& vm, JSGlobalObject* dynamicGlobalObject) |
583 | : m_dynamicGlobalObjectSlot(vm.dynamicGlobalObject) | |
b80e6193 A |
584 | , m_savedDynamicGlobalObject(m_dynamicGlobalObjectSlot) |
585 | { | |
586 | if (!m_dynamicGlobalObjectSlot) { | |
14957cd0 A |
587 | #if ENABLE(ASSEMBLER) |
588 | if (ExecutableAllocator::underMemoryPressure()) | |
93a37866 | 589 | vm.heap.deleteAllCompiledCode(); |
b80e6193 | 590 | #endif |
14957cd0 | 591 | |
b80e6193 A |
592 | m_dynamicGlobalObjectSlot = dynamicGlobalObject; |
593 | ||
594 | // Reset the date cache between JS invocations to force the VM | |
595 | // to observe time zone changes. | |
93a37866 | 596 | vm.resetDateCache(); |
b80e6193 | 597 | } |
93a37866 A |
598 | // Clear the exception stack between entries |
599 | vm.clearExceptionStack(); | |
b80e6193 A |
600 | } |
601 | ||
14957cd0 A |
602 | void slowValidateCell(JSGlobalObject* globalObject) |
603 | { | |
93a37866 | 604 | RELEASE_ASSERT(globalObject->isGlobalObject()); |
14957cd0 A |
605 | ASSERT_GC_OBJECT_INHERITS(globalObject, &JSGlobalObject::s_info); |
606 | } | |
607 | ||
93a37866 A |
608 | UnlinkedProgramCodeBlock* JSGlobalObject::createProgramCodeBlock(CallFrame* callFrame, ProgramExecutable* executable, JSObject** exception) |
609 | { | |
610 | ParserError error; | |
611 | JSParserStrictness strictness = executable->isStrictMode() ? JSParseStrict : JSParseNormal; | |
612 | DebuggerMode debuggerMode = hasDebugger() ? DebuggerOn : DebuggerOff; | |
613 | ProfilerMode profilerMode = hasProfiler() ? ProfilerOn : ProfilerOff; | |
614 | UnlinkedProgramCodeBlock* unlinkedCode = vm().codeCache()->getProgramCodeBlock(vm(), executable, executable->source(), strictness, debuggerMode, profilerMode, error); | |
615 | ||
616 | if (hasDebugger()) | |
617 | debugger()->sourceParsed(callFrame, executable->source().provider(), error.m_line, error.m_message); | |
618 | ||
619 | if (error.m_type != ParserError::ErrorNone) { | |
620 | *exception = error.toErrorObject(this, executable->source()); | |
621 | return 0; | |
622 | } | |
623 | ||
624 | return unlinkedCode; | |
625 | } | |
626 | ||
627 | UnlinkedEvalCodeBlock* JSGlobalObject::createEvalCodeBlock(CodeCache* cache, CallFrame* callFrame, JSScope* scope, EvalExecutable* executable, JSObject** exception) | |
628 | { | |
629 | ParserError error; | |
630 | JSParserStrictness strictness = executable->isStrictMode() ? JSParseStrict : JSParseNormal; | |
631 | DebuggerMode debuggerMode = hasDebugger() ? DebuggerOn : DebuggerOff; | |
632 | ProfilerMode profilerMode = hasProfiler() ? ProfilerOn : ProfilerOff; | |
633 | UnlinkedEvalCodeBlock* unlinkedCode = cache->getEvalCodeBlock(vm(), scope, executable, executable->source(), strictness, debuggerMode, profilerMode, error); | |
634 | ||
635 | if (hasDebugger()) | |
636 | debugger()->sourceParsed(callFrame, executable->source().provider(), error.m_line, error.m_message); | |
637 | ||
638 | if (error.m_type != ParserError::ErrorNone) { | |
639 | *exception = error.toErrorObject(this, executable->source()); | |
640 | return 0; | |
641 | } | |
642 | ||
643 | return unlinkedCode; | |
644 | } | |
645 | ||
9dae56ea | 646 | } // namespace JSC |