| 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" |
| 45 | #include "ErrorConstructor.h" |
| 46 | #include "ErrorPrototype.h" |
| 47 | #include "FunctionConstructor.h" |
| 48 | #include "FunctionPrototype.h" |
| 49 | #include "GlobalEvalFunction.h" |
| 50 | #include "JSFunction.h" |
| 51 | #include "JSGlobalObjectFunctions.h" |
| 52 | #include "JSLock.h" |
| 53 | #include "JSONObject.h" |
| 54 | #include "Interpreter.h" |
| 55 | #include "MathObject.h" |
| 56 | #include "NativeErrorConstructor.h" |
| 57 | #include "NativeErrorPrototype.h" |
| 58 | #include "NumberConstructor.h" |
| 59 | #include "NumberPrototype.h" |
| 60 | #include "ObjectConstructor.h" |
| 61 | #include "ObjectPrototype.h" |
| 62 | #include "Profiler.h" |
| 63 | #include "PrototypeFunction.h" |
| 64 | #include "RegExpConstructor.h" |
| 65 | #include "RegExpMatchesArray.h" |
| 66 | #include "RegExpObject.h" |
| 67 | #include "RegExpPrototype.h" |
| 68 | #include "ScopeChainMark.h" |
| 69 | #include "StringConstructor.h" |
| 70 | #include "StringPrototype.h" |
| 71 | #include "Debugger.h" |
| 72 | |
| 73 | namespace JSC { |
| 74 | |
| 75 | ASSERT_CLASS_FITS_IN_CELL(JSGlobalObject); |
| 76 | |
| 77 | // Default number of ticks before a timeout check should be done. |
| 78 | static const int initialTickCountThreshold = 255; |
| 79 | |
| 80 | // Preferred number of milliseconds between each timeout check |
| 81 | static const int preferredScriptCheckTimeInterval = 1000; |
| 82 | |
| 83 | static inline void markIfNeeded(MarkStack& markStack, JSValue v) |
| 84 | { |
| 85 | if (v) |
| 86 | markStack.append(value: v); |
| 87 | } |
| 88 | |
| 89 | static inline void markIfNeeded(MarkStack& markStack, const RefPtr<Structure>& s) |
| 90 | { |
| 91 | if (s) |
| 92 | markIfNeeded(markStack, v: s->storedPrototype()); |
| 93 | } |
| 94 | |
| 95 | JSGlobalObject::~JSGlobalObject() |
| 96 | { |
| 97 | ASSERT(JSLock::currentThreadIsHoldingLock()); |
| 98 | |
| 99 | if (d()->debugger) |
| 100 | d()->debugger->detach(this); |
| 101 | |
| 102 | Profiler** profiler = Profiler::enabledProfilerReference(); |
| 103 | if (UNLIKELY(*profiler != 0)) { |
| 104 | (*profiler)->stopProfiling(globalExec(), title: UString()); |
| 105 | } |
| 106 | |
| 107 | d()->next->d()->prev = d()->prev; |
| 108 | d()->prev->d()->next = d()->next; |
| 109 | JSGlobalObject*& headObject = head(); |
| 110 | if (headObject == this) |
| 111 | headObject = d()->next; |
| 112 | if (headObject == this) |
| 113 | headObject = 0; |
| 114 | |
| 115 | HashSet<GlobalCodeBlock*>::const_iterator end = codeBlocks().end(); |
| 116 | for (HashSet<GlobalCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it) |
| 117 | (*it)->clearGlobalObject(); |
| 118 | |
| 119 | RegisterFile& registerFile = globalData()->interpreter->registerFile(); |
| 120 | if (registerFile.globalObject() == this) { |
| 121 | registerFile.setGlobalObject(0); |
| 122 | registerFile.setNumGlobals(0); |
| 123 | } |
| 124 | d()->destructor(d()); |
| 125 | } |
| 126 | |
| 127 | void JSGlobalObject::init(JSObject* thisValue) |
| 128 | { |
| 129 | ASSERT(JSLock::currentThreadIsHoldingLock()); |
| 130 | |
| 131 | structure()->disableSpecificFunctionTracking(); |
| 132 | |
| 133 | d()->globalData = Heap::heap(c: this)->globalData(); |
| 134 | d()->globalScopeChain = ScopeChain(this, d()->globalData.get(), this, thisValue); |
| 135 | |
| 136 | JSGlobalObject::globalExec()->init(codeBlock: 0, vPC: 0, scopeChain: d()->globalScopeChain.node(), callerFrame: CallFrame::noCaller(), returnValueRegister: 0, argc: 0, callee: 0); |
| 137 | |
| 138 | if (JSGlobalObject*& headObject = head()) { |
| 139 | d()->prev = headObject; |
| 140 | d()->next = headObject->d()->next; |
| 141 | headObject->d()->next->d()->prev = this; |
| 142 | headObject->d()->next = this; |
| 143 | } else |
| 144 | headObject = d()->next = d()->prev = this; |
| 145 | |
| 146 | d()->recursion = 0; |
| 147 | d()->debugger = 0; |
| 148 | |
| 149 | d()->profileGroup = 0; |
| 150 | |
| 151 | reset(prototype: prototype()); |
| 152 | } |
| 153 | |
| 154 | void JSGlobalObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) |
| 155 | { |
| 156 | ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); |
| 157 | |
| 158 | if (symbolTablePut(propertyName, value)) |
| 159 | return; |
| 160 | JSVariableObject::put(exec, propertyName, value, slot); |
| 161 | } |
| 162 | |
| 163 | void JSGlobalObject::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes) |
| 164 | { |
| 165 | ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); |
| 166 | |
| 167 | if (symbolTablePutWithAttributes(propertyName, value, attributes)) |
| 168 | return; |
| 169 | |
| 170 | JSValue valueBefore = getDirect(propertyName); |
| 171 | PutPropertySlot slot; |
| 172 | JSVariableObject::put(exec, propertyName, value, slot); |
| 173 | if (!valueBefore) { |
| 174 | JSValue valueAfter = getDirect(propertyName); |
| 175 | if (valueAfter) |
| 176 | JSObject::putWithAttributes(exec, propertyName, value: valueAfter, attributes); |
| 177 | } |
| 178 | } |
| 179 | |
| 180 | void JSGlobalObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunc, unsigned attributes) |
| 181 | { |
| 182 | PropertySlot slot; |
| 183 | if (!symbolTableGet(propertyName, slot)) |
| 184 | JSVariableObject::defineGetter(exec, propertyName, getterFunction: getterFunc, attributes); |
| 185 | } |
| 186 | |
| 187 | void JSGlobalObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunc, unsigned attributes) |
| 188 | { |
| 189 | PropertySlot slot; |
| 190 | if (!symbolTableGet(propertyName, slot)) |
| 191 | JSVariableObject::defineSetter(exec, propertyName, setterFunction: setterFunc, attributes); |
| 192 | } |
| 193 | |
| 194 | static inline JSObject* lastInPrototypeChain(JSObject* object) |
| 195 | { |
| 196 | JSObject* o = object; |
| 197 | while (o->prototype().isObject()) |
| 198 | o = asObject(value: o->prototype()); |
| 199 | return o; |
| 200 | } |
| 201 | |
| 202 | void JSGlobalObject::reset(JSValue prototype) |
| 203 | { |
| 204 | ExecState* exec = JSGlobalObject::globalExec(); |
| 205 | |
| 206 | // Prototypes |
| 207 | |
| 208 | d()->functionPrototype = new (exec) FunctionPrototype(exec, FunctionPrototype::createStructure(proto: jsNull())); // The real prototype will be set once ObjectPrototype is created. |
| 209 | d()->prototypeFunctionStructure = PrototypeFunction::createStructure(proto: d()->functionPrototype); |
| 210 | NativeFunctionWrapper* callFunction = 0; |
| 211 | NativeFunctionWrapper* applyFunction = 0; |
| 212 | d()->functionPrototype->addFunctionProperties(exec, prototypeFunctionStructure: d()->prototypeFunctionStructure.get(), callFunction: &callFunction, applyFunction: &applyFunction); |
| 213 | d()->callFunction = callFunction; |
| 214 | d()->applyFunction = applyFunction; |
| 215 | d()->objectPrototype = new (exec) ObjectPrototype(exec, ObjectPrototype::createStructure(prototype: jsNull()), d()->prototypeFunctionStructure.get()); |
| 216 | d()->functionPrototype->structure()->setPrototypeWithoutTransition(d()->objectPrototype); |
| 217 | |
| 218 | d()->emptyObjectStructure = d()->objectPrototype->inheritorID(); |
| 219 | |
| 220 | d()->functionStructure = JSFunction::createStructure(prototype: d()->functionPrototype); |
| 221 | d()->callbackFunctionStructure = JSCallbackFunction::createStructure(proto: d()->functionPrototype); |
| 222 | d()->argumentsStructure = Arguments::createStructure(prototype: d()->objectPrototype); |
| 223 | d()->callbackConstructorStructure = JSCallbackConstructor::createStructure(proto: d()->objectPrototype); |
| 224 | d()->callbackObjectStructure = JSCallbackObject<JSObject>::createStructure(proto: d()->objectPrototype); |
| 225 | |
| 226 | d()->arrayPrototype = new (exec) ArrayPrototype(ArrayPrototype::createStructure(prototype: d()->objectPrototype)); |
| 227 | d()->arrayStructure = JSArray::createStructure(prototype: d()->arrayPrototype); |
| 228 | d()->regExpMatchesArrayStructure = RegExpMatchesArray::createStructure(prototype: d()->arrayPrototype); |
| 229 | |
| 230 | d()->stringPrototype = new (exec) StringPrototype(exec, StringPrototype::createStructure(prototype: d()->objectPrototype)); |
| 231 | d()->stringObjectStructure = StringObject::createStructure(prototype: d()->stringPrototype); |
| 232 | |
| 233 | d()->booleanPrototype = new (exec) BooleanPrototype(exec, BooleanPrototype::createStructure(prototype: d()->objectPrototype), d()->prototypeFunctionStructure.get()); |
| 234 | d()->booleanObjectStructure = BooleanObject::createStructure(prototype: d()->booleanPrototype); |
| 235 | |
| 236 | d()->numberPrototype = new (exec) NumberPrototype(exec, NumberPrototype::createStructure(prototype: d()->objectPrototype), d()->prototypeFunctionStructure.get()); |
| 237 | d()->numberObjectStructure = NumberObject::createStructure(prototype: d()->numberPrototype); |
| 238 | |
| 239 | d()->datePrototype = new (exec) DatePrototype(exec, DatePrototype::createStructure(prototype: d()->objectPrototype)); |
| 240 | d()->dateStructure = DateInstance::createStructure(prototype: d()->datePrototype); |
| 241 | |
| 242 | d()->regExpPrototype = new (exec) RegExpPrototype(exec, RegExpPrototype::createStructure(prototype: d()->objectPrototype), d()->prototypeFunctionStructure.get()); |
| 243 | d()->regExpStructure = RegExpObject::createStructure(prototype: d()->regExpPrototype); |
| 244 | |
| 245 | d()->methodCallDummy = constructEmptyObject(exec); |
| 246 | |
| 247 | ErrorPrototype* errorPrototype = new (exec) ErrorPrototype(exec, ErrorPrototype::createStructure(prototype: d()->objectPrototype), d()->prototypeFunctionStructure.get()); |
| 248 | d()->errorStructure = ErrorInstance::createStructure(prototype: errorPrototype); |
| 249 | |
| 250 | RefPtr<Structure> nativeErrorPrototypeStructure = NativeErrorPrototype::createStructure(prototype: errorPrototype); |
| 251 | |
| 252 | NativeErrorPrototype* evalErrorPrototype = new (exec) NativeErrorPrototype(exec, nativeErrorPrototypeStructure, "EvalError" , "EvalError" ); |
| 253 | NativeErrorPrototype* rangeErrorPrototype = new (exec) NativeErrorPrototype(exec, nativeErrorPrototypeStructure, "RangeError" , "RangeError" ); |
| 254 | NativeErrorPrototype* referenceErrorPrototype = new (exec) NativeErrorPrototype(exec, nativeErrorPrototypeStructure, "ReferenceError" , "ReferenceError" ); |
| 255 | NativeErrorPrototype* syntaxErrorPrototype = new (exec) NativeErrorPrototype(exec, nativeErrorPrototypeStructure, "SyntaxError" , "SyntaxError" ); |
| 256 | NativeErrorPrototype* typeErrorPrototype = new (exec) NativeErrorPrototype(exec, nativeErrorPrototypeStructure, "TypeError" , "TypeError" ); |
| 257 | NativeErrorPrototype* URIErrorPrototype = new (exec) NativeErrorPrototype(exec, nativeErrorPrototypeStructure, "URIError" , "URIError" ); |
| 258 | |
| 259 | // Constructors |
| 260 | |
| 261 | JSCell* objectConstructor = new (exec) ObjectConstructor(exec, ObjectConstructor::createStructure(proto: d()->functionPrototype), d()->objectPrototype, d()->prototypeFunctionStructure.get()); |
| 262 | JSCell* functionConstructor = new (exec) FunctionConstructor(exec, FunctionConstructor::createStructure(proto: d()->functionPrototype), d()->functionPrototype); |
| 263 | JSCell* arrayConstructor = new (exec) ArrayConstructor(exec, ArrayConstructor::createStructure(proto: d()->functionPrototype), d()->arrayPrototype, d()->prototypeFunctionStructure.get()); |
| 264 | JSCell* stringConstructor = new (exec) StringConstructor(exec, StringConstructor::createStructure(proto: d()->functionPrototype), d()->prototypeFunctionStructure.get(), d()->stringPrototype); |
| 265 | JSCell* booleanConstructor = new (exec) BooleanConstructor(exec, BooleanConstructor::createStructure(proto: d()->functionPrototype), d()->booleanPrototype); |
| 266 | JSCell* numberConstructor = new (exec) NumberConstructor(exec, NumberConstructor::createStructure(proto: d()->functionPrototype), d()->numberPrototype); |
| 267 | JSCell* dateConstructor = new (exec) DateConstructor(exec, DateConstructor::createStructure(proto: d()->functionPrototype), d()->prototypeFunctionStructure.get(), d()->datePrototype); |
| 268 | |
| 269 | d()->regExpConstructor = new (exec) RegExpConstructor(exec, RegExpConstructor::createStructure(prototype: d()->functionPrototype), d()->regExpPrototype); |
| 270 | |
| 271 | d()->errorConstructor = new (exec) ErrorConstructor(exec, ErrorConstructor::createStructure(proto: d()->functionPrototype), errorPrototype); |
| 272 | |
| 273 | RefPtr<Structure> nativeErrorStructure = NativeErrorConstructor::createStructure(proto: d()->functionPrototype); |
| 274 | |
| 275 | d()->evalErrorConstructor = new (exec) NativeErrorConstructor(exec, nativeErrorStructure, evalErrorPrototype); |
| 276 | d()->rangeErrorConstructor = new (exec) NativeErrorConstructor(exec, nativeErrorStructure, rangeErrorPrototype); |
| 277 | d()->referenceErrorConstructor = new (exec) NativeErrorConstructor(exec, nativeErrorStructure, referenceErrorPrototype); |
| 278 | d()->syntaxErrorConstructor = new (exec) NativeErrorConstructor(exec, nativeErrorStructure, syntaxErrorPrototype); |
| 279 | d()->typeErrorConstructor = new (exec) NativeErrorConstructor(exec, nativeErrorStructure, typeErrorPrototype); |
| 280 | d()->URIErrorConstructor = new (exec) NativeErrorConstructor(exec, nativeErrorStructure, URIErrorPrototype); |
| 281 | |
| 282 | d()->objectPrototype->putDirectFunctionWithoutTransition(propertyName: exec->propertyNames().constructor, value: objectConstructor, attributes: DontEnum); |
| 283 | d()->functionPrototype->putDirectFunctionWithoutTransition(propertyName: exec->propertyNames().constructor, value: functionConstructor, attributes: DontEnum); |
| 284 | d()->arrayPrototype->putDirectFunctionWithoutTransition(propertyName: exec->propertyNames().constructor, value: arrayConstructor, attributes: DontEnum); |
| 285 | d()->booleanPrototype->putDirectFunctionWithoutTransition(propertyName: exec->propertyNames().constructor, value: booleanConstructor, attributes: DontEnum); |
| 286 | d()->stringPrototype->putDirectFunctionWithoutTransition(propertyName: exec->propertyNames().constructor, value: stringConstructor, attributes: DontEnum); |
| 287 | d()->numberPrototype->putDirectFunctionWithoutTransition(propertyName: exec->propertyNames().constructor, value: numberConstructor, attributes: DontEnum); |
| 288 | d()->datePrototype->putDirectFunctionWithoutTransition(propertyName: exec->propertyNames().constructor, value: dateConstructor, attributes: DontEnum); |
| 289 | d()->regExpPrototype->putDirectFunctionWithoutTransition(propertyName: exec->propertyNames().constructor, value: d()->regExpConstructor, attributes: DontEnum); |
| 290 | errorPrototype->putDirectFunctionWithoutTransition(propertyName: exec->propertyNames().constructor, value: d()->errorConstructor, attributes: DontEnum); |
| 291 | |
| 292 | evalErrorPrototype->putDirect(propertyName: exec->propertyNames().constructor, value: d()->evalErrorConstructor, attributes: DontEnum); |
| 293 | rangeErrorPrototype->putDirect(propertyName: exec->propertyNames().constructor, value: d()->rangeErrorConstructor, attributes: DontEnum); |
| 294 | referenceErrorPrototype->putDirect(propertyName: exec->propertyNames().constructor, value: d()->referenceErrorConstructor, attributes: DontEnum); |
| 295 | syntaxErrorPrototype->putDirect(propertyName: exec->propertyNames().constructor, value: d()->syntaxErrorConstructor, attributes: DontEnum); |
| 296 | typeErrorPrototype->putDirect(propertyName: exec->propertyNames().constructor, value: d()->typeErrorConstructor, attributes: DontEnum); |
| 297 | URIErrorPrototype->putDirect(propertyName: exec->propertyNames().constructor, value: d()->URIErrorConstructor, attributes: DontEnum); |
| 298 | |
| 299 | // Set global constructors |
| 300 | |
| 301 | // FIXME: These properties could be handled by a static hash table. |
| 302 | |
| 303 | putDirectFunctionWithoutTransition(propertyName: Identifier(exec, "Object" ), value: objectConstructor, attributes: DontEnum); |
| 304 | putDirectFunctionWithoutTransition(propertyName: Identifier(exec, "Function" ), value: functionConstructor, attributes: DontEnum); |
| 305 | putDirectFunctionWithoutTransition(propertyName: Identifier(exec, "Array" ), value: arrayConstructor, attributes: DontEnum); |
| 306 | putDirectFunctionWithoutTransition(propertyName: Identifier(exec, "Boolean" ), value: booleanConstructor, attributes: DontEnum); |
| 307 | putDirectFunctionWithoutTransition(propertyName: Identifier(exec, "String" ), value: stringConstructor, attributes: DontEnum); |
| 308 | putDirectFunctionWithoutTransition(propertyName: Identifier(exec, "Number" ), value: numberConstructor, attributes: DontEnum); |
| 309 | putDirectFunctionWithoutTransition(propertyName: Identifier(exec, "Date" ), value: dateConstructor, attributes: DontEnum); |
| 310 | putDirectFunctionWithoutTransition(propertyName: Identifier(exec, "RegExp" ), value: d()->regExpConstructor, attributes: DontEnum); |
| 311 | putDirectFunctionWithoutTransition(propertyName: Identifier(exec, "Error" ), value: d()->errorConstructor, attributes: DontEnum); |
| 312 | putDirectFunctionWithoutTransition(propertyName: Identifier(exec, "EvalError" ), value: d()->evalErrorConstructor, attributes: DontEnum); |
| 313 | putDirectFunctionWithoutTransition(propertyName: Identifier(exec, "RangeError" ), value: d()->rangeErrorConstructor, attributes: DontEnum); |
| 314 | putDirectFunctionWithoutTransition(propertyName: Identifier(exec, "ReferenceError" ), value: d()->referenceErrorConstructor, attributes: DontEnum); |
| 315 | putDirectFunctionWithoutTransition(propertyName: Identifier(exec, "SyntaxError" ), value: d()->syntaxErrorConstructor, attributes: DontEnum); |
| 316 | putDirectFunctionWithoutTransition(propertyName: Identifier(exec, "TypeError" ), value: d()->typeErrorConstructor, attributes: DontEnum); |
| 317 | putDirectFunctionWithoutTransition(propertyName: Identifier(exec, "URIError" ), value: d()->URIErrorConstructor, attributes: DontEnum); |
| 318 | |
| 319 | // Set global values. |
| 320 | GlobalPropertyInfo staticGlobals[] = { |
| 321 | GlobalPropertyInfo(Identifier(exec, "Math" ), new (exec) MathObject(exec, MathObject::createStructure(prototype: d()->objectPrototype)), DontEnum | DontDelete), |
| 322 | GlobalPropertyInfo(Identifier(exec, "NaN" ), jsNaN(exec), DontEnum | DontDelete), |
| 323 | GlobalPropertyInfo(Identifier(exec, "Infinity" ), jsNumber(exec, d: Inf), DontEnum | DontDelete), |
| 324 | GlobalPropertyInfo(Identifier(exec, "undefined" ), jsUndefined(), DontEnum | DontDelete), |
| 325 | GlobalPropertyInfo(Identifier(exec, "JSON" ), new (exec) JSONObject(JSONObject::createStructure(prototype: d()->objectPrototype)), DontEnum | DontDelete) |
| 326 | }; |
| 327 | |
| 328 | addStaticGlobals(globals: staticGlobals, count: sizeof(staticGlobals) / sizeof(GlobalPropertyInfo)); |
| 329 | |
| 330 | // Set global functions. |
| 331 | |
| 332 | d()->evalFunction = new (exec) GlobalEvalFunction(exec, GlobalEvalFunction::createStructure(prototype: d()->functionPrototype), 1, exec->propertyNames().eval, globalFuncEval, this); |
| 333 | putDirectFunctionWithoutTransition(exec, function: d()->evalFunction, attr: DontEnum); |
| 334 | putDirectFunctionWithoutTransition(exec, function: new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 2, Identifier(exec, "parseInt" ), globalFuncParseInt), attr: DontEnum); |
| 335 | putDirectFunctionWithoutTransition(exec, function: new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "parseFloat" ), globalFuncParseFloat), attr: DontEnum); |
| 336 | putDirectFunctionWithoutTransition(exec, function: new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "isNaN" ), globalFuncIsNaN), attr: DontEnum); |
| 337 | putDirectFunctionWithoutTransition(exec, function: new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "isFinite" ), globalFuncIsFinite), attr: DontEnum); |
| 338 | putDirectFunctionWithoutTransition(exec, function: new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "escape" ), globalFuncEscape), attr: DontEnum); |
| 339 | putDirectFunctionWithoutTransition(exec, function: new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "unescape" ), globalFuncUnescape), attr: DontEnum); |
| 340 | putDirectFunctionWithoutTransition(exec, function: new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "decodeURI" ), globalFuncDecodeURI), attr: DontEnum); |
| 341 | putDirectFunctionWithoutTransition(exec, function: new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "decodeURIComponent" ), globalFuncDecodeURIComponent), attr: DontEnum); |
| 342 | putDirectFunctionWithoutTransition(exec, function: new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "encodeURI" ), globalFuncEncodeURI), attr: DontEnum); |
| 343 | putDirectFunctionWithoutTransition(exec, function: new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "encodeURIComponent" ), globalFuncEncodeURIComponent), attr: DontEnum); |
| 344 | #ifndef NDEBUG |
| 345 | #ifndef QT_BUILD_SCRIPT_LIB |
| 346 | putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, d()->prototypeFunctionStructure.get(), 1, Identifier(exec, "jscprint" ), globalFuncJSCPrint), DontEnum); |
| 347 | #endif |
| 348 | #endif |
| 349 | |
| 350 | resetPrototype(prototype); |
| 351 | } |
| 352 | |
| 353 | // Set prototype, and also insert the object prototype at the end of the chain. |
| 354 | void JSGlobalObject::resetPrototype(JSValue prototype) |
| 355 | { |
| 356 | setPrototype(prototype); |
| 357 | |
| 358 | JSObject* oldLastInPrototypeChain = lastInPrototypeChain(object: this); |
| 359 | JSObject* objectPrototype = d()->objectPrototype; |
| 360 | if (oldLastInPrototypeChain != objectPrototype) |
| 361 | oldLastInPrototypeChain->setPrototype(objectPrototype); |
| 362 | } |
| 363 | |
| 364 | void JSGlobalObject::markChildren(MarkStack& markStack) |
| 365 | { |
| 366 | JSVariableObject::markChildren(markStack); |
| 367 | |
| 368 | HashSet<GlobalCodeBlock*>::const_iterator end = codeBlocks().end(); |
| 369 | for (HashSet<GlobalCodeBlock*>::const_iterator it = codeBlocks().begin(); it != end; ++it) |
| 370 | (*it)->markAggregate(markStack); |
| 371 | |
| 372 | RegisterFile& registerFile = globalData()->interpreter->registerFile(); |
| 373 | if (registerFile.globalObject() == this) |
| 374 | registerFile.markGlobals(markStack, heap: &globalData()->heap); |
| 375 | |
| 376 | markIfNeeded(markStack, v: d()->regExpConstructor); |
| 377 | markIfNeeded(markStack, v: d()->errorConstructor); |
| 378 | markIfNeeded(markStack, v: d()->evalErrorConstructor); |
| 379 | markIfNeeded(markStack, v: d()->rangeErrorConstructor); |
| 380 | markIfNeeded(markStack, v: d()->referenceErrorConstructor); |
| 381 | markIfNeeded(markStack, v: d()->syntaxErrorConstructor); |
| 382 | markIfNeeded(markStack, v: d()->typeErrorConstructor); |
| 383 | markIfNeeded(markStack, v: d()->URIErrorConstructor); |
| 384 | |
| 385 | markIfNeeded(markStack, v: d()->evalFunction); |
| 386 | markIfNeeded(markStack, v: d()->callFunction); |
| 387 | markIfNeeded(markStack, v: d()->applyFunction); |
| 388 | |
| 389 | markIfNeeded(markStack, v: d()->objectPrototype); |
| 390 | markIfNeeded(markStack, v: d()->functionPrototype); |
| 391 | markIfNeeded(markStack, v: d()->arrayPrototype); |
| 392 | markIfNeeded(markStack, v: d()->booleanPrototype); |
| 393 | markIfNeeded(markStack, v: d()->stringPrototype); |
| 394 | markIfNeeded(markStack, v: d()->numberPrototype); |
| 395 | markIfNeeded(markStack, v: d()->datePrototype); |
| 396 | markIfNeeded(markStack, v: d()->regExpPrototype); |
| 397 | |
| 398 | markIfNeeded(markStack, v: d()->methodCallDummy); |
| 399 | |
| 400 | markIfNeeded(markStack, s: d()->errorStructure); |
| 401 | markIfNeeded(markStack, s: d()->argumentsStructure); |
| 402 | markIfNeeded(markStack, s: d()->arrayStructure); |
| 403 | markIfNeeded(markStack, s: d()->booleanObjectStructure); |
| 404 | markIfNeeded(markStack, s: d()->callbackConstructorStructure); |
| 405 | markIfNeeded(markStack, s: d()->callbackFunctionStructure); |
| 406 | markIfNeeded(markStack, s: d()->callbackObjectStructure); |
| 407 | markIfNeeded(markStack, s: d()->dateStructure); |
| 408 | markIfNeeded(markStack, s: d()->emptyObjectStructure); |
| 409 | markIfNeeded(markStack, s: d()->errorStructure); |
| 410 | markIfNeeded(markStack, s: d()->functionStructure); |
| 411 | markIfNeeded(markStack, s: d()->numberObjectStructure); |
| 412 | markIfNeeded(markStack, s: d()->prototypeFunctionStructure); |
| 413 | markIfNeeded(markStack, s: d()->regExpMatchesArrayStructure); |
| 414 | markIfNeeded(markStack, s: d()->regExpStructure); |
| 415 | markIfNeeded(markStack, s: d()->stringObjectStructure); |
| 416 | |
| 417 | // No need to mark the other structures, because their prototypes are all |
| 418 | // guaranteed to be referenced elsewhere. |
| 419 | |
| 420 | Register* registerArray = d()->registerArray.get(); |
| 421 | if (!registerArray) |
| 422 | return; |
| 423 | |
| 424 | size_t size = d()->registerArraySize; |
| 425 | markStack.appendValues(values: reinterpret_cast<JSValue*>(registerArray), count: size); |
| 426 | } |
| 427 | |
| 428 | ExecState* JSGlobalObject::globalExec() |
| 429 | { |
| 430 | return CallFrame::create(callFrameBase: d()->globalCallFrame + RegisterFile::CallFrameHeaderSize); |
| 431 | } |
| 432 | |
| 433 | bool JSGlobalObject::isDynamicScope() const |
| 434 | { |
| 435 | return true; |
| 436 | } |
| 437 | |
| 438 | void JSGlobalObject::copyGlobalsFrom(RegisterFile& registerFile) |
| 439 | { |
| 440 | ASSERT(!d()->registerArray); |
| 441 | ASSERT(!d()->registerArraySize); |
| 442 | |
| 443 | int numGlobals = registerFile.numGlobals(); |
| 444 | if (!numGlobals) { |
| 445 | d()->registers = 0; |
| 446 | return; |
| 447 | } |
| 448 | |
| 449 | Register* registerArray = copyRegisterArray(src: registerFile.lastGlobal(), count: numGlobals); |
| 450 | setRegisters(registers: registerArray + numGlobals, registerArray, count: numGlobals); |
| 451 | } |
| 452 | |
| 453 | void JSGlobalObject::copyGlobalsTo(RegisterFile& registerFile) |
| 454 | { |
| 455 | JSGlobalObject* lastGlobalObject = registerFile.globalObject(); |
| 456 | if (lastGlobalObject && lastGlobalObject != this) |
| 457 | lastGlobalObject->copyGlobalsFrom(registerFile); |
| 458 | |
| 459 | registerFile.setGlobalObject(this); |
| 460 | registerFile.setNumGlobals(symbolTable().size()); |
| 461 | |
| 462 | if (d()->registerArray) { |
| 463 | memcpy(dest: registerFile.start() - d()->registerArraySize, src: d()->registerArray.get(), n: d()->registerArraySize * sizeof(Register)); |
| 464 | setRegisters(registers: registerFile.start(), registerArray: 0, count: 0); |
| 465 | } |
| 466 | } |
| 467 | |
| 468 | void* JSGlobalObject::operator new(size_t size, JSGlobalData* globalData) |
| 469 | { |
| 470 | return globalData->heap.allocate(size); |
| 471 | } |
| 472 | |
| 473 | void JSGlobalObject::destroyJSGlobalObjectData(void* jsGlobalObjectData) |
| 474 | { |
| 475 | delete static_cast<JSGlobalObjectData*>(jsGlobalObjectData); |
| 476 | } |
| 477 | |
| 478 | } // namespace JSC |
| 479 | |