summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/runtime/JSScope.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-09-10 19:10:20 +0200
committerSimon Hausmann <simon.hausmann@nokia.com>2012-09-10 19:10:20 +0200
commit284837daa07b29d6a63a748544a90b1f5842ac5c (patch)
treeecd258180bde91fe741e0cfd2638beb3c6da7e8e /Source/JavaScriptCore/runtime/JSScope.cpp
parent2e2ba8ff45915f40ed3e014101269c175f2a89a0 (diff)
downloadqtwebkit-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.cpp262
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