diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-09-10 19:10:20 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-09-10 19:10:20 +0200 |
commit | 284837daa07b29d6a63a748544a90b1f5842ac5c (patch) | |
tree | ecd258180bde91fe741e0cfd2638beb3c6da7e8e /Source/JavaScriptCore/runtime/JSScope.cpp | |
parent | 2e2ba8ff45915f40ed3e014101269c175f2a89a0 (diff) | |
download | qtwebkit-284837daa07b29d6a63a748544a90b1f5842ac5c.tar.gz |
Imported WebKit commit 68645295d2e3e09af2c942f092556f06aa5f8b0d (http://svn.webkit.org/repository/webkit/trunk@128073)
New snapshot
Diffstat (limited to 'Source/JavaScriptCore/runtime/JSScope.cpp')
-rw-r--r-- | Source/JavaScriptCore/runtime/JSScope.cpp | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/runtime/JSScope.cpp b/Source/JavaScriptCore/runtime/JSScope.cpp new file mode 100644 index 000000000..b22211970 --- /dev/null +++ b/Source/JavaScriptCore/runtime/JSScope.cpp @@ -0,0 +1,262 @@ +/* + * Copyright (C) 2012 Apple Inc. All Rights Reserved. + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR + * 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 "JSScope.h" + +#include "JSActivation.h" +#include "JSGlobalObject.h" +#include "JSNameScope.h" +#include "JSWithScope.h" + +namespace JSC { + +ASSERT_CLASS_FITS_IN_CELL(JSScope); + +void JSScope::visitChildren(JSCell* cell, SlotVisitor& visitor) +{ + JSScope* thisObject = jsCast<JSScope*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info); + COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); + ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); + + Base::visitChildren(thisObject, visitor); + visitor.append(&thisObject->m_next); +} + +bool JSScope::isDynamicScope(bool& requiresDynamicChecks) const +{ + switch (structure()->typeInfo().type()) { + case GlobalObjectType: + return static_cast<const JSGlobalObject*>(this)->isDynamicScope(requiresDynamicChecks); + case ActivationObjectType: + return static_cast<const JSActivation*>(this)->isDynamicScope(requiresDynamicChecks); + case NameScopeObjectType: + return static_cast<const JSNameScope*>(this)->isDynamicScope(requiresDynamicChecks); + default: + ASSERT_NOT_REACHED(); + break; + } + + return false; +} + +JSObject* JSScope::objectAtScope(JSScope* scope) +{ + JSObject* object = scope; + if (object->structure()->typeInfo().type() == WithScopeType) + return jsCast<JSWithScope*>(object)->object(); + + return object; +} + +int JSScope::localDepth() +{ + int scopeDepth = 0; + ScopeChainIterator iter = this->begin(); + ScopeChainIterator end = this->end(); + while (!iter->inherits(&JSActivation::s_info)) { + ++iter; + if (iter == end) + break; + ++scopeDepth; + } + return scopeDepth; +} + +JSValue JSScope::resolve(CallFrame* callFrame, const Identifier& identifier) +{ + JSScope* scope = callFrame->scope(); + ASSERT(scope); + + do { + JSObject* object = JSScope::objectAtScope(scope); + PropertySlot slot(object); + if (object->getPropertySlot(callFrame, identifier, slot)) + return slot.getValue(callFrame, identifier); + } while ((scope = scope->next())); + + return throwError(callFrame, createUndefinedVariableError(callFrame, identifier)); +} + +JSValue JSScope::resolveSkip(CallFrame* callFrame, const Identifier& identifier, int skip) +{ + JSScope* scope = callFrame->scope(); + ASSERT(scope); + + CodeBlock* codeBlock = callFrame->codeBlock(); + + bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain(); + ASSERT(skip || !checkTopLevel); + if (checkTopLevel && skip--) { + if (callFrame->uncheckedR(codeBlock->activationRegister()).jsValue()) + scope = scope->next(); + } + while (skip--) { + scope = scope->next(); + ASSERT(scope); + } + + do { + JSObject* object = JSScope::objectAtScope(scope); + PropertySlot slot(object); + if (object->getPropertySlot(callFrame, identifier, slot)) + return slot.getValue(callFrame, identifier); + } while ((scope = scope->next())); + + return throwError(callFrame, createUndefinedVariableError(callFrame, identifier)); +} + +JSValue JSScope::resolveGlobal( + CallFrame* callFrame, + const Identifier& identifier, + JSGlobalObject* globalObject, + WriteBarrierBase<Structure>* cachedStructure, + PropertyOffset* cachedOffset +) +{ + if (globalObject->structure() == cachedStructure->get()) + return globalObject->getDirectOffset(*cachedOffset); + + PropertySlot slot(globalObject); + if (!globalObject->getPropertySlot(callFrame, identifier, slot)) + return throwError(callFrame, createUndefinedVariableError(callFrame, identifier)); + + JSValue result = slot.getValue(callFrame, identifier); + if (callFrame->globalData().exception) + return JSValue(); + + if (slot.isCacheableValue() && !globalObject->structure()->isUncacheableDictionary() && slot.slotBase() == globalObject) { + cachedStructure->set(callFrame->globalData(), callFrame->codeBlock()->ownerExecutable(), globalObject->structure()); + *cachedOffset = slot.cachedOffset(); + } + return result; +} + +JSValue JSScope::resolveGlobalDynamic( + CallFrame* callFrame, + const Identifier& identifier, + int skip, + WriteBarrierBase<Structure>* cachedStructure, + PropertyOffset* cachedOffset +) +{ + JSScope* scope = callFrame->scope(); + ASSERT(scope); + + CodeBlock* codeBlock = callFrame->codeBlock(); + + bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain(); + ASSERT(skip || !checkTopLevel); + if (checkTopLevel && skip--) { + if (callFrame->uncheckedR(codeBlock->activationRegister()).jsValue()) + scope = scope->next(); + } + while (skip--) { + JSObject* object = JSScope::objectAtScope(scope); + if (!object->hasCustomProperties()) + continue; + + PropertySlot slot(object); + if (!object->getPropertySlot(callFrame, identifier, slot)) + continue; + + JSValue result = slot.getValue(callFrame, identifier); + if (callFrame->globalData().exception) + return JSValue(); + return result; + } + + return resolveGlobal(callFrame, identifier, callFrame->lexicalGlobalObject(), cachedStructure, cachedOffset); +} + +JSValue JSScope::resolveBase(CallFrame* callFrame, const Identifier& identifier, bool isStrict) +{ + JSScope* scope = callFrame->scope(); + ASSERT(scope); + + do { + JSObject* object = JSScope::objectAtScope(scope); + + PropertySlot slot(object); + if (!object->getPropertySlot(callFrame, identifier, slot)) + continue; + + return JSValue(object); + } while ((scope = scope->next())); + + if (!isStrict) + return callFrame->lexicalGlobalObject(); + + return throwError(callFrame, createErrorForInvalidGlobalAssignment(callFrame, identifier.string())); +} + +JSValue JSScope::resolveWithBase(CallFrame* callFrame, const Identifier& identifier, Register* base) +{ + JSScope* scope = callFrame->scope(); + ASSERT(scope); + + do { + JSObject* object = JSScope::objectAtScope(scope); + + PropertySlot slot(object); + if (!object->getPropertySlot(callFrame, identifier, slot)) + continue; + + JSValue value = slot.getValue(callFrame, identifier); + if (callFrame->globalData().exception) + return JSValue(); + + *base = JSValue(object); + return value; + } while ((scope = scope->next())); + + return throwError(callFrame, createUndefinedVariableError(callFrame, identifier)); +} + +JSValue JSScope::resolveWithThis(CallFrame* callFrame, const Identifier& identifier, Register* base) +{ + JSScope* scope = callFrame->scope(); + ASSERT(scope); + + do { + JSObject* object = JSScope::objectAtScope(scope); + + PropertySlot slot(object); + if (!object->getPropertySlot(callFrame, identifier, slot)) + continue; + + JSValue value = slot.getValue(callFrame, identifier); + if (callFrame->globalData().exception) + return JSValue(); + + *base = object->structure()->typeInfo().isEnvironmentRecord() ? jsUndefined() : JSValue(object); + return value; + } while ((scope = scope->next())); + + return throwError(callFrame, createUndefinedVariableError(callFrame, identifier)); +} + +} // namespace JSC |