]>
Commit | Line | Data |
---|---|---|
ed1e77d3 A |
1 | /* |
2 | * Copyright (C) 2008-2009, 2014 Apple Inc. All rights reserved. | |
3 | * | |
4 | * Redistribution and use in source and binary forms, with or without | |
5 | * modification, are permitted provided that the following conditions | |
6 | * are met: | |
7 | * 1. Redistributions of source code must retain the above copyright | |
8 | * notice, this list of conditions and the following disclaimer. | |
9 | * 2. Redistributions in binary form must reproduce the above copyright | |
10 | * notice, this list of conditions and the following disclaimer in the | |
11 | * documentation and/or other materials provided with the distribution. | |
12 | * | |
13 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY | |
14 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR | |
17 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
18 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
20 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | |
21 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
23 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | */ | |
25 | ||
26 | #include "config.h" | |
27 | #include "DebuggerScope.h" | |
28 | ||
29 | #include "JSLexicalEnvironment.h" | |
30 | #include "JSCInlines.h" | |
31 | #include "JSNameScope.h" | |
32 | #include "JSWithScope.h" | |
33 | ||
34 | namespace JSC { | |
35 | ||
36 | STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(DebuggerScope); | |
37 | ||
38 | const ClassInfo DebuggerScope::s_info = { "DebuggerScope", &Base::s_info, 0, CREATE_METHOD_TABLE(DebuggerScope) }; | |
39 | ||
40 | DebuggerScope::DebuggerScope(VM& vm, JSScope* scope) | |
41 | : JSNonFinalObject(vm, scope->globalObject()->debuggerScopeStructure()) | |
42 | { | |
43 | ASSERT(scope); | |
44 | m_scope.set(vm, this, scope); | |
45 | } | |
46 | ||
47 | void DebuggerScope::finishCreation(VM& vm) | |
48 | { | |
49 | Base::finishCreation(vm); | |
50 | } | |
51 | ||
52 | void DebuggerScope::visitChildren(JSCell* cell, SlotVisitor& visitor) | |
53 | { | |
54 | DebuggerScope* thisObject = jsCast<DebuggerScope*>(cell); | |
55 | ASSERT_GC_OBJECT_INHERITS(thisObject, info()); | |
56 | JSObject::visitChildren(thisObject, visitor); | |
57 | visitor.append(&thisObject->m_scope); | |
58 | visitor.append(&thisObject->m_next); | |
59 | } | |
60 | ||
61 | String DebuggerScope::className(const JSObject* object) | |
62 | { | |
63 | const DebuggerScope* scope = jsCast<const DebuggerScope*>(object); | |
64 | ASSERT(scope->isValid()); | |
65 | if (!scope->isValid()) | |
66 | return String(); | |
67 | JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); | |
68 | return thisObject->methodTable()->className(thisObject); | |
69 | } | |
70 | ||
71 | bool DebuggerScope::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot) | |
72 | { | |
73 | DebuggerScope* scope = jsCast<DebuggerScope*>(object); | |
74 | ASSERT(scope->isValid()); | |
75 | if (!scope->isValid()) | |
76 | return false; | |
77 | JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); | |
78 | slot.setThisValue(JSValue(thisObject)); | |
79 | ||
80 | // By default, JSObject::getPropertySlot() will look in the DebuggerScope's prototype | |
81 | // chain and not the wrapped scope, and JSObject::getPropertySlot() cannot be overridden | |
82 | // to behave differently for the DebuggerScope. | |
83 | // | |
84 | // Instead, we'll treat all properties in the wrapped scope and its prototype chain as | |
85 | // the own properties of the DebuggerScope. This is fine because the WebInspector | |
86 | // does not presently need to distinguish between what's owned at each level in the | |
87 | // prototype chain. Hence, we'll invoke getPropertySlot() on the wrapped scope here | |
88 | // instead of getOwnPropertySlot(). | |
89 | return thisObject->getPropertySlot(exec, propertyName, slot); | |
90 | } | |
91 | ||
92 | void DebuggerScope::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot) | |
93 | { | |
94 | DebuggerScope* scope = jsCast<DebuggerScope*>(cell); | |
95 | ASSERT(scope->isValid()); | |
96 | if (!scope->isValid()) | |
97 | return; | |
98 | JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); | |
99 | slot.setThisValue(JSValue(thisObject)); | |
100 | thisObject->methodTable()->put(thisObject, exec, propertyName, value, slot); | |
101 | } | |
102 | ||
103 | bool DebuggerScope::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName) | |
104 | { | |
105 | DebuggerScope* scope = jsCast<DebuggerScope*>(cell); | |
106 | ASSERT(scope->isValid()); | |
107 | if (!scope->isValid()) | |
108 | return false; | |
109 | JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); | |
110 | return thisObject->methodTable()->deleteProperty(thisObject, exec, propertyName); | |
111 | } | |
112 | ||
113 | void DebuggerScope::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) | |
114 | { | |
115 | DebuggerScope* scope = jsCast<DebuggerScope*>(object); | |
116 | ASSERT(scope->isValid()); | |
117 | if (!scope->isValid()) | |
118 | return; | |
119 | JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); | |
120 | thisObject->methodTable()->getPropertyNames(thisObject, exec, propertyNames, mode); | |
121 | } | |
122 | ||
123 | bool DebuggerScope::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool shouldThrow) | |
124 | { | |
125 | DebuggerScope* scope = jsCast<DebuggerScope*>(object); | |
126 | ASSERT(scope->isValid()); | |
127 | if (!scope->isValid()) | |
128 | return false; | |
129 | JSObject* thisObject = JSScope::objectAtScope(scope->jsScope()); | |
130 | return thisObject->methodTable()->defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow); | |
131 | } | |
132 | ||
133 | DebuggerScope* DebuggerScope::next() | |
134 | { | |
135 | ASSERT(isValid()); | |
136 | if (!m_next && m_scope->next()) { | |
137 | VM& vm = *m_scope->vm(); | |
138 | DebuggerScope* nextScope = create(vm, m_scope->next()); | |
139 | m_next.set(vm, this, nextScope); | |
140 | } | |
141 | return m_next.get(); | |
142 | } | |
143 | ||
144 | void DebuggerScope::invalidateChain() | |
145 | { | |
146 | if (!isValid()) | |
147 | return; | |
148 | ||
149 | DebuggerScope* scope = this; | |
150 | while (scope) { | |
151 | DebuggerScope* nextScope = scope->m_next.get(); | |
152 | scope->m_next.clear(); | |
153 | scope->m_scope.clear(); // This also marks this scope as invalid. | |
154 | scope = nextScope; | |
155 | } | |
156 | } | |
157 | ||
158 | bool DebuggerScope::isCatchScope() const | |
159 | { | |
160 | return m_scope->isCatchScopeObject(); | |
161 | } | |
162 | ||
163 | bool DebuggerScope::isFunctionNameScope() const | |
164 | { | |
165 | return m_scope->isFunctionNameScopeObject(); | |
166 | } | |
167 | ||
168 | bool DebuggerScope::isWithScope() const | |
169 | { | |
170 | return m_scope->isWithScope(); | |
171 | } | |
172 | ||
173 | bool DebuggerScope::isGlobalScope() const | |
174 | { | |
175 | return m_scope->isGlobalObject(); | |
176 | } | |
177 | ||
178 | bool DebuggerScope::isFunctionOrEvalScope() const | |
179 | { | |
180 | // In the current debugger implementation, every function or eval will create an | |
181 | // lexical environment object. Hence, a lexical environment object implies a | |
182 | // function or eval scope. | |
183 | return m_scope->isActivationObject(); | |
184 | } | |
185 | ||
186 | JSValue DebuggerScope::caughtValue() const | |
187 | { | |
188 | ASSERT(isCatchScope()); | |
189 | return reinterpret_cast<JSNameScope*>(m_scope.get())->value(); | |
190 | } | |
191 | ||
192 | } // namespace JSC |