| /* |
| * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. |
| * Copyright (C) 2008 Cameron Zwarich (cwzwarich@uwaterloo.ca) |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of |
| * its contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
| * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "config.h" |
| #include "JSGlobalObject.h" |
| |
| #include "Activation.h" |
| #include "array_object.h" |
| #include "bool_object.h" |
| #include "date_object.h" |
| #include "debugger.h" |
| #include "error_object.h" |
| #include "function_object.h" |
| #include "math_object.h" |
| #include "number_object.h" |
| #include "object_object.h" |
| #include "regexp_object.h" |
| #include "SavedBuiltins.h" |
| #include "string_object.h" |
| |
| #if HAVE(SYS_TIME_H) |
| #include <sys/time.h> |
| #endif |
| |
| #if PLATFORM(WIN_OS) |
| #include <windows.h> |
| #endif |
| |
| #if PLATFORM(QT) |
| #include <QDateTime> |
| #endif |
| |
| namespace KJS { |
| |
| // Default number of ticks before a timeout check should be done. |
| static const int initialTickCountThreshold = 255; |
| |
| // Preferred number of milliseconds between each timeout check |
| static const int preferredScriptCheckTimeInterval = 1000; |
| |
| static inline void markIfNeeded(JSValue* v) |
| { |
| if (v && !v->marked()) |
| v->mark(); |
| } |
| |
| // Returns the current time in milliseconds |
| // It doesn't matter what "current time" is here, just as long as |
| // it's possible to measure the time difference correctly. |
| static inline unsigned getCurrentTime() |
| { |
| #if HAVE(SYS_TIME_H) |
| struct timeval tv; |
| gettimeofday(&tv, 0); |
| return tv.tv_sec * 1000 + tv.tv_usec / 1000; |
| #elif PLATFORM(QT) |
| QDateTime t = QDateTime::currentDateTime(); |
| return t.toTime_t() * 1000 + t.time().msec(); |
| #elif PLATFORM(WIN_OS) |
| return timeGetTime(); |
| #else |
| #error Platform does not have getCurrentTime function |
| #endif |
| } |
| |
| JSGlobalObject* JSGlobalObject::s_head = 0; |
| |
| void JSGlobalObject::deleteActivationStack() |
| { |
| ActivationStackNode* prevNode = 0; |
| for (ActivationStackNode* currentNode = d()->activations; currentNode; currentNode = prevNode) { |
| prevNode = currentNode->prev; |
| delete currentNode; |
| } |
| } |
| |
| JSGlobalObject::~JSGlobalObject() |
| { |
| ASSERT(JSLock::currentThreadIsHoldingLock()); |
| |
| if (d()->debugger) |
| d()->debugger->detach(this); |
| |
| d()->next->d()->prev = d()->prev; |
| d()->prev->d()->next = d()->next; |
| s_head = d()->next; |
| if (s_head == this) |
| s_head = 0; |
| |
| deleteActivationStack(); |
| |
| delete d(); |
| } |
| |
| void JSGlobalObject::init() |
| { |
| ASSERT(JSLock::currentThreadIsHoldingLock()); |
| |
| if (s_head) { |
| d()->prev = s_head; |
| d()->next = s_head->d()->next; |
| s_head->d()->next->d()->prev = this; |
| s_head->d()->next = this; |
| } else |
| s_head = d()->next = d()->prev = this; |
| |
| d()->compatMode = NativeMode; |
| |
| resetTimeoutCheck(); |
| d()->timeoutTime = 0; |
| d()->timeoutCheckCount = 0; |
| |
| d()->recursion = 0; |
| d()->debugger = 0; |
| |
| ActivationStackNode* newStackNode = new ActivationStackNode; |
| newStackNode->prev = 0; |
| d()->activations = newStackNode; |
| d()->activationCount = 0; |
| |
| reset(prototype()); |
| } |
| |
| bool JSGlobalObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) |
| { |
| if (symbolTableGet(propertyName, slot)) |
| return true; |
| return JSVariableObject::getOwnPropertySlot(exec, propertyName, slot); |
| } |
| |
| void JSGlobalObject::put(ExecState* exec, const Identifier& propertyName, JSValue* value, int attr) |
| { |
| if (symbolTablePut(propertyName, value, !(attr & ~DontDelete))) |
| return; |
| return JSVariableObject::put(exec, propertyName, value, attr); |
| } |
| |
| static inline JSObject* lastInPrototypeChain(JSObject* object) |
| { |
| JSObject* o = object; |
| while (o->prototype()->isObject()) |
| o = static_cast<JSObject*>(o->prototype()); |
| return o; |
| } |
| |
| void JSGlobalObject::reset(JSValue* prototype) |
| { |
| // Clear before inititalizing, to avoid calling mark() on stale pointers -- |
| // which would be wasteful -- or uninitialized pointers -- which would be |
| // dangerous. (The allocations below may cause a GC.) |
| |
| _prop.clear(); |
| localStorage().clear(); |
| symbolTable().clear(); |
| |
| // Prototypes |
| d()->functionPrototype = 0; |
| d()->objectPrototype = 0; |
| |
| d()->arrayPrototype = 0; |
| d()->stringPrototype = 0; |
| d()->booleanPrototype = 0; |
| d()->numberPrototype = 0; |
| d()->datePrototype = 0; |
| d()->regExpPrototype = 0; |
| d()->errorPrototype = 0; |
| |
| d()->evalErrorPrototype = 0; |
| d()->rangeErrorPrototype = 0; |
| d()->referenceErrorPrototype = 0; |
| d()->syntaxErrorPrototype = 0; |
| d()->typeErrorPrototype = 0; |
| d()->URIErrorPrototype = 0; |
| |
| // Constructors |
| d()->objectConstructor = 0; |
| d()->functionConstructor = 0; |
| d()->arrayConstructor = 0; |
| d()->stringConstructor = 0; |
| d()->booleanConstructor = 0; |
| d()->numberConstructor = 0; |
| d()->dateConstructor = 0; |
| d()->regExpConstructor = 0; |
| d()->errorConstructor = 0; |
| |
| d()->evalErrorConstructor = 0; |
| d()->rangeErrorConstructor = 0; |
| d()->referenceErrorConstructor = 0; |
| d()->syntaxErrorConstructor = 0; |
| d()->typeErrorConstructor = 0; |
| d()->URIErrorConstructor = 0; |
| |
| ExecState* exec = &d()->globalExec; |
| |
| // Prototypes |
| d()->functionPrototype = new FunctionPrototype(exec); |
| d()->objectPrototype = new ObjectPrototype(exec, d()->functionPrototype); |
| d()->functionPrototype->setPrototype(d()->objectPrototype); |
| |
| d()->arrayPrototype = new ArrayPrototype(exec, d()->objectPrototype); |
| d()->stringPrototype = new StringPrototype(exec, d()->objectPrototype); |
| d()->booleanPrototype = new BooleanPrototype(exec, d()->objectPrototype, d()->functionPrototype); |
| d()->numberPrototype = new NumberPrototype(exec, d()->objectPrototype, d()->functionPrototype); |
| d()->datePrototype = new DatePrototype(exec, d()->objectPrototype); |
| d()->regExpPrototype = new RegExpPrototype(exec, d()->objectPrototype, d()->functionPrototype); |
| d()->errorPrototype = new ErrorPrototype(exec, d()->objectPrototype, d()->functionPrototype); |
| |
| d()->evalErrorPrototype = new NativeErrorPrototype(exec, d()->errorPrototype, "EvalError", "EvalError"); |
| d()->rangeErrorPrototype = new NativeErrorPrototype(exec, d()->errorPrototype, "RangeError", "RangeError"); |
| d()->referenceErrorPrototype = new NativeErrorPrototype(exec, d()->errorPrototype, "ReferenceError", "ReferenceError"); |
| d()->syntaxErrorPrototype = new NativeErrorPrototype(exec, d()->errorPrototype, "SyntaxError", "SyntaxError"); |
| d()->typeErrorPrototype = new NativeErrorPrototype(exec, d()->errorPrototype, "TypeError", "TypeError"); |
| d()->URIErrorPrototype = new NativeErrorPrototype(exec, d()->errorPrototype, "URIError", "URIError"); |
| |
| // Constructors |
| d()->objectConstructor = new ObjectObjectImp(exec, d()->objectPrototype, d()->functionPrototype); |
| d()->functionConstructor = new FunctionObjectImp(exec, d()->functionPrototype); |
| d()->arrayConstructor = new ArrayObjectImp(exec, d()->functionPrototype, d()->arrayPrototype); |
| d()->stringConstructor = new StringObjectImp(exec, d()->functionPrototype, d()->stringPrototype); |
| d()->booleanConstructor = new BooleanObjectImp(exec, d()->functionPrototype, d()->booleanPrototype); |
| d()->numberConstructor = new NumberObjectImp(exec, d()->functionPrototype, d()->numberPrototype); |
| d()->dateConstructor = new DateObjectImp(exec, d()->functionPrototype, d()->datePrototype); |
| d()->regExpConstructor = new RegExpObjectImp(exec, d()->functionPrototype, d()->regExpPrototype); |
| d()->errorConstructor = new ErrorObjectImp(exec, d()->functionPrototype, d()->errorPrototype); |
| |
| d()->evalErrorConstructor = new NativeErrorImp(exec, d()->functionPrototype, d()->evalErrorPrototype); |
| d()->rangeErrorConstructor = new NativeErrorImp(exec, d()->functionPrototype, d()->rangeErrorPrototype); |
| d()->referenceErrorConstructor = new NativeErrorImp(exec, d()->functionPrototype, d()->referenceErrorPrototype); |
| d()->syntaxErrorConstructor = new NativeErrorImp(exec, d()->functionPrototype, d()->syntaxErrorPrototype); |
| d()->typeErrorConstructor = new NativeErrorImp(exec, d()->functionPrototype, d()->typeErrorPrototype); |
| d()->URIErrorConstructor = new NativeErrorImp(exec, d()->functionPrototype, d()->URIErrorPrototype); |
| |
| d()->functionPrototype->putDirect(exec->propertyNames().constructor, d()->functionConstructor, DontEnum); |
| |
| d()->objectPrototype->putDirect(exec->propertyNames().constructor, d()->objectConstructor, DontEnum | DontDelete | ReadOnly); |
| d()->functionPrototype->putDirect(exec->propertyNames().constructor, d()->functionConstructor, DontEnum | DontDelete | ReadOnly); |
| d()->arrayPrototype->putDirect(exec->propertyNames().constructor, d()->arrayConstructor, DontEnum | DontDelete | ReadOnly); |
| d()->booleanPrototype->putDirect(exec->propertyNames().constructor, d()->booleanConstructor, DontEnum | DontDelete | ReadOnly); |
| d()->stringPrototype->putDirect(exec->propertyNames().constructor, d()->stringConstructor, DontEnum | DontDelete | ReadOnly); |
| d()->numberPrototype->putDirect(exec->propertyNames().constructor, d()->numberConstructor, DontEnum | DontDelete | ReadOnly); |
| d()->datePrototype->putDirect(exec->propertyNames().constructor, d()->dateConstructor, DontEnum | DontDelete | ReadOnly); |
| d()->regExpPrototype->putDirect(exec->propertyNames().constructor, d()->regExpConstructor, DontEnum | DontDelete | ReadOnly); |
| d()->errorPrototype->putDirect(exec->propertyNames().constructor, d()->errorConstructor, DontEnum | DontDelete | ReadOnly); |
| d()->evalErrorPrototype->putDirect(exec->propertyNames().constructor, d()->evalErrorConstructor, DontEnum | DontDelete | ReadOnly); |
| d()->rangeErrorPrototype->putDirect(exec->propertyNames().constructor, d()->rangeErrorConstructor, DontEnum | DontDelete | ReadOnly); |
| d()->referenceErrorPrototype->putDirect(exec->propertyNames().constructor, d()->referenceErrorConstructor, DontEnum | DontDelete | ReadOnly); |
| d()->syntaxErrorPrototype->putDirect(exec->propertyNames().constructor, d()->syntaxErrorConstructor, DontEnum | DontDelete | ReadOnly); |
| d()->typeErrorPrototype->putDirect(exec->propertyNames().constructor, d()->typeErrorConstructor, DontEnum | DontDelete | ReadOnly); |
| d()->URIErrorPrototype->putDirect(exec->propertyNames().constructor, d()->URIErrorConstructor, DontEnum | DontDelete | ReadOnly); |
| |
| // Set global constructors |
| |
| // FIXME: kjs_window.cpp checks Internal/DontEnum as a performance hack, to |
| // see that these values can be put directly without a check for override |
| // properties. |
| |
| // FIXME: These properties should be handled by a static hash table. |
| |
| putDirect("Object", d()->objectConstructor, DontEnum); |
| putDirect("Function", d()->functionConstructor, DontEnum); |
| putDirect("Array", d()->arrayConstructor, DontEnum); |
| putDirect("Boolean", d()->booleanConstructor, DontEnum); |
| putDirect("String", d()->stringConstructor, DontEnum); |
| putDirect("Number", d()->numberConstructor, DontEnum); |
| putDirect("Date", d()->dateConstructor, DontEnum); |
| putDirect("RegExp", d()->regExpConstructor, DontEnum); |
| putDirect("Error", d()->errorConstructor, DontEnum); |
| putDirect("EvalError", d()->evalErrorConstructor, Internal); |
| putDirect("RangeError", d()->rangeErrorConstructor, Internal); |
| putDirect("ReferenceError", d()->referenceErrorConstructor, Internal); |
| putDirect("SyntaxError", d()->syntaxErrorConstructor, Internal); |
| putDirect("TypeError", d()->typeErrorConstructor, Internal); |
| putDirect("URIError", d()->URIErrorConstructor, Internal); |
| |
| // Set global values. |
| |
| putDirect("Math", new MathObjectImp(exec, d()->objectPrototype), DontEnum); |
| |
| putDirect("NaN", jsNaN(), DontEnum | DontDelete); |
| putDirect("Infinity", jsNumber(Inf), DontEnum | DontDelete); |
| putDirect("undefined", jsUndefined(), DontEnum | DontDelete); |
| |
| // Set global functions. |
| |
| putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "eval", globalFuncEval), DontEnum); |
| putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 2, "parseInt", globalFuncParseInt), DontEnum); |
| putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "parseFloat", globalFuncParseFloat), DontEnum); |
| putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "isNaN", globalFuncIsNaN), DontEnum); |
| putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "isFinite", globalFuncIsFinite), DontEnum); |
| putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "escape", globalFuncEscape), DontEnum); |
| putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "unescape", globalFuncUnescape), DontEnum); |
| putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "decodeURI", globalFuncDecodeURI), DontEnum); |
| putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "decodeURIComponent", globalFuncDecodeURIComponent), DontEnum); |
| putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "encodeURI", globalFuncEncodeURI), DontEnum); |
| putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "encodeURIComponent", globalFuncEncodeURIComponent), DontEnum); |
| #ifndef NDEBUG |
| putDirectFunction(new PrototypeFunction(exec, d()->functionPrototype, 1, "kjsprint", globalFuncKJSPrint), DontEnum); |
| #endif |
| |
| // Set prototype, and also insert the object prototype at the end of the chain. |
| |
| setPrototype(prototype); |
| lastInPrototypeChain(this)->setPrototype(d()->objectPrototype); |
| } |
| |
| void JSGlobalObject::startTimeoutCheck() |
| { |
| if (!d()->timeoutCheckCount) |
| resetTimeoutCheck(); |
| |
| ++d()->timeoutCheckCount; |
| } |
| |
| void JSGlobalObject::stopTimeoutCheck() |
| { |
| --d()->timeoutCheckCount; |
| } |
| |
| void JSGlobalObject::resetTimeoutCheck() |
| { |
| d()->tickCount = 0; |
| d()->ticksUntilNextTimeoutCheck = initialTickCountThreshold; |
| d()->timeAtLastCheckTimeout = 0; |
| d()->timeExecuting = 0; |
| } |
| |
| bool JSGlobalObject::checkTimeout() |
| { |
| d()->tickCount = 0; |
| |
| unsigned currentTime = getCurrentTime(); |
| |
| if (!d()->timeAtLastCheckTimeout) { |
| // Suspicious amount of looping in a script -- start timing it |
| d()->timeAtLastCheckTimeout = currentTime; |
| return false; |
| } |
| |
| unsigned timeDiff = currentTime - d()->timeAtLastCheckTimeout; |
| |
| if (timeDiff == 0) |
| timeDiff = 1; |
| |
| d()->timeExecuting += timeDiff; |
| d()->timeAtLastCheckTimeout = currentTime; |
| |
| // Adjust the tick threshold so we get the next checkTimeout call in the interval specified in |
| // preferredScriptCheckTimeInterval |
| d()->ticksUntilNextTimeoutCheck = (unsigned)((float)preferredScriptCheckTimeInterval / timeDiff) * d()->ticksUntilNextTimeoutCheck; |
| |
| // If the new threshold is 0 reset it to the default threshold. This can happen if the timeDiff is higher than the |
| // preferred script check time interval. |
| if (d()->ticksUntilNextTimeoutCheck == 0) |
| d()->ticksUntilNextTimeoutCheck = initialTickCountThreshold; |
| |
| if (d()->timeoutTime && d()->timeExecuting > d()->timeoutTime) { |
| if (shouldInterruptScript()) |
| return true; |
| |
| resetTimeoutCheck(); |
| } |
| |
| return false; |
| } |
| |
| void JSGlobalObject::saveBuiltins(SavedBuiltins& builtins) const |
| { |
| if (!builtins._internal) |
| builtins._internal = new SavedBuiltinsInternal; |
| |
| builtins._internal->objectConstructor = d()->objectConstructor; |
| builtins._internal->functionConstructor = d()->functionConstructor; |
| builtins._internal->arrayConstructor = d()->arrayConstructor; |
| builtins._internal->booleanConstructor = d()->booleanConstructor; |
| builtins._internal->stringConstructor = d()->stringConstructor; |
| builtins._internal->numberConstructor = d()->numberConstructor; |
| builtins._internal->dateConstructor = d()->dateConstructor; |
| builtins._internal->regExpConstructor = d()->regExpConstructor; |
| builtins._internal->errorConstructor = d()->errorConstructor; |
| builtins._internal->evalErrorConstructor = d()->evalErrorConstructor; |
| builtins._internal->rangeErrorConstructor = d()->rangeErrorConstructor; |
| builtins._internal->referenceErrorConstructor = d()->referenceErrorConstructor; |
| builtins._internal->syntaxErrorConstructor = d()->syntaxErrorConstructor; |
| builtins._internal->typeErrorConstructor = d()->typeErrorConstructor; |
| builtins._internal->URIErrorConstructor = d()->URIErrorConstructor; |
| |
| builtins._internal->objectPrototype = d()->objectPrototype; |
| builtins._internal->functionPrototype = d()->functionPrototype; |
| builtins._internal->arrayPrototype = d()->arrayPrototype; |
| builtins._internal->booleanPrototype = d()->booleanPrototype; |
| builtins._internal->stringPrototype = d()->stringPrototype; |
| builtins._internal->numberPrototype = d()->numberPrototype; |
| builtins._internal->datePrototype = d()->datePrototype; |
| builtins._internal->regExpPrototype = d()->regExpPrototype; |
| builtins._internal->errorPrototype = d()->errorPrototype; |
| builtins._internal->evalErrorPrototype = d()->evalErrorPrototype; |
| builtins._internal->rangeErrorPrototype = d()->rangeErrorPrototype; |
| builtins._internal->referenceErrorPrototype = d()->referenceErrorPrototype; |
| builtins._internal->syntaxErrorPrototype = d()->syntaxErrorPrototype; |
| builtins._internal->typeErrorPrototype = d()->typeErrorPrototype; |
| builtins._internal->URIErrorPrototype = d()->URIErrorPrototype; |
| } |
| |
| void JSGlobalObject::restoreBuiltins(const SavedBuiltins& builtins) |
| { |
| if (!builtins._internal) |
| return; |
| |
| d()->objectConstructor = builtins._internal->objectConstructor; |
| d()->functionConstructor = builtins._internal->functionConstructor; |
| d()->arrayConstructor = builtins._internal->arrayConstructor; |
| d()->booleanConstructor = builtins._internal->booleanConstructor; |
| d()->stringConstructor = builtins._internal->stringConstructor; |
| d()->numberConstructor = builtins._internal->numberConstructor; |
| d()->dateConstructor = builtins._internal->dateConstructor; |
| d()->regExpConstructor = builtins._internal->regExpConstructor; |
| d()->errorConstructor = builtins._internal->errorConstructor; |
| d()->evalErrorConstructor = builtins._internal->evalErrorConstructor; |
| d()->rangeErrorConstructor = builtins._internal->rangeErrorConstructor; |
| d()->referenceErrorConstructor = builtins._internal->referenceErrorConstructor; |
| d()->syntaxErrorConstructor = builtins._internal->syntaxErrorConstructor; |
| d()->typeErrorConstructor = builtins._internal->typeErrorConstructor; |
| d()->URIErrorConstructor = builtins._internal->URIErrorConstructor; |
| |
| d()->objectPrototype = builtins._internal->objectPrototype; |
| d()->functionPrototype = builtins._internal->functionPrototype; |
| d()->arrayPrototype = builtins._internal->arrayPrototype; |
| d()->booleanPrototype = builtins._internal->booleanPrototype; |
| d()->stringPrototype = builtins._internal->stringPrototype; |
| d()->numberPrototype = builtins._internal->numberPrototype; |
| d()->datePrototype = builtins._internal->datePrototype; |
| d()->regExpPrototype = builtins._internal->regExpPrototype; |
| d()->errorPrototype = builtins._internal->errorPrototype; |
| d()->evalErrorPrototype = builtins._internal->evalErrorPrototype; |
| d()->rangeErrorPrototype = builtins._internal->rangeErrorPrototype; |
| d()->referenceErrorPrototype = builtins._internal->referenceErrorPrototype; |
| d()->syntaxErrorPrototype = builtins._internal->syntaxErrorPrototype; |
| d()->typeErrorPrototype = builtins._internal->typeErrorPrototype; |
| d()->URIErrorPrototype = builtins._internal->URIErrorPrototype; |
| } |
| |
| void JSGlobalObject::mark() |
| { |
| JSVariableObject::mark(); |
| |
| markIfNeeded(d()->globalExec.exception()); |
| |
| markIfNeeded(d()->objectConstructor); |
| markIfNeeded(d()->functionConstructor); |
| markIfNeeded(d()->arrayConstructor); |
| markIfNeeded(d()->booleanConstructor); |
| markIfNeeded(d()->stringConstructor); |
| markIfNeeded(d()->numberConstructor); |
| markIfNeeded(d()->dateConstructor); |
| markIfNeeded(d()->regExpConstructor); |
| markIfNeeded(d()->errorConstructor); |
| markIfNeeded(d()->evalErrorConstructor); |
| markIfNeeded(d()->rangeErrorConstructor); |
| markIfNeeded(d()->referenceErrorConstructor); |
| markIfNeeded(d()->syntaxErrorConstructor); |
| markIfNeeded(d()->typeErrorConstructor); |
| markIfNeeded(d()->URIErrorConstructor); |
| |
| markIfNeeded(d()->objectPrototype); |
| markIfNeeded(d()->functionPrototype); |
| markIfNeeded(d()->arrayPrototype); |
| markIfNeeded(d()->booleanPrototype); |
| markIfNeeded(d()->stringPrototype); |
| markIfNeeded(d()->numberPrototype); |
| markIfNeeded(d()->datePrototype); |
| markIfNeeded(d()->regExpPrototype); |
| markIfNeeded(d()->errorPrototype); |
| markIfNeeded(d()->evalErrorPrototype); |
| markIfNeeded(d()->rangeErrorPrototype); |
| markIfNeeded(d()->referenceErrorPrototype); |
| markIfNeeded(d()->syntaxErrorPrototype); |
| markIfNeeded(d()->typeErrorPrototype); |
| markIfNeeded(d()->URIErrorPrototype); |
| } |
| |
| ExecState* JSGlobalObject::globalExec() |
| { |
| return &d()->globalExec; |
| } |
| |
| ActivationImp* JSGlobalObject::pushActivation(ExecState* exec) |
| { |
| if (d()->activationCount == activationStackNodeSize) { |
| ActivationStackNode* newNode = new ActivationStackNode; |
| newNode->prev = d()->activations; |
| d()->activations = newNode; |
| d()->activationCount = 0; |
| } |
| |
| StackActivation* stackEntry = &d()->activations->data[d()->activationCount++]; |
| stackEntry->activationStorage.init(exec); |
| return &stackEntry->activationStorage; |
| } |
| |
| inline void JSGlobalObject::checkActivationCount() |
| { |
| if (!d()->activationCount) { |
| ActivationStackNode* prev = d()->activations->prev; |
| ASSERT(prev); |
| delete d()->activations; |
| d()->activations = prev; |
| d()->activationCount = activationStackNodeSize; |
| } |
| } |
| |
| void JSGlobalObject::popActivation() |
| { |
| checkActivationCount(); |
| d()->activations->data[--d()->activationCount].activationDataStorage.localStorage.shrink(0); |
| } |
| |
| void JSGlobalObject::tearOffActivation(ExecState* exec, bool leaveRelic) |
| { |
| ActivationImp* oldActivation = exec->activationObject(); |
| if (!oldActivation || !oldActivation->isOnStack()) |
| return; |
| |
| ASSERT(exec->codeType() == FunctionCode); |
| ActivationImp* newActivation = new ActivationImp(*oldActivation->d(), leaveRelic); |
| |
| if (!leaveRelic) { |
| checkActivationCount(); |
| d()->activationCount--; |
| } |
| |
| oldActivation->d()->localStorage.shrink(0); |
| |
| exec->setActivationObject(newActivation); |
| exec->setVariableObject(newActivation); |
| exec->setLocalStorage(&newActivation->localStorage()); |
| exec->replaceScopeChainTop(newActivation); |
| } |
| |
| } // namespace KJS |