]> git.saurik.com Git - apple/javascriptcore.git/blob - inspector/JSJavaScriptCallFrame.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / inspector / JSJavaScriptCallFrame.cpp
1 /*
2 * Copyright (C) 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 "JSJavaScriptCallFrame.h"
28
29 #include "DebuggerScope.h"
30 #include "Error.h"
31 #include "JSCJSValue.h"
32 #include "JSCellInlines.h"
33 #include "JSJavaScriptCallFramePrototype.h"
34 #include "StructureInlines.h"
35
36 using namespace JSC;
37
38 namespace Inspector {
39
40 const ClassInfo JSJavaScriptCallFrame::s_info = { "JavaScriptCallFrame", &Base::s_info, 0, CREATE_METHOD_TABLE(JSJavaScriptCallFrame) };
41
42 JSJavaScriptCallFrame::JSJavaScriptCallFrame(VM& vm, Structure* structure, PassRefPtr<JavaScriptCallFrame> impl)
43 : JSDestructibleObject(vm, structure)
44 , m_impl(impl.leakRef())
45 {
46 }
47
48 void JSJavaScriptCallFrame::finishCreation(VM& vm)
49 {
50 Base::finishCreation(vm);
51 ASSERT(inherits(info()));
52 }
53
54 JSObject* JSJavaScriptCallFrame::createPrototype(VM& vm, JSGlobalObject* globalObject)
55 {
56 return JSJavaScriptCallFramePrototype::create(vm, globalObject, JSJavaScriptCallFramePrototype::createStructure(vm, globalObject, globalObject->objectPrototype()));
57 }
58
59 void JSJavaScriptCallFrame::destroy(JSC::JSCell* cell)
60 {
61 JSJavaScriptCallFrame* thisObject = static_cast<JSJavaScriptCallFrame*>(cell);
62 thisObject->JSJavaScriptCallFrame::~JSJavaScriptCallFrame();
63 }
64
65 void JSJavaScriptCallFrame::releaseImpl()
66 {
67 if (auto impl = std::exchange(m_impl, nullptr))
68 impl->deref();
69 }
70
71 JSJavaScriptCallFrame::~JSJavaScriptCallFrame()
72 {
73 releaseImpl();
74 }
75
76 JSValue JSJavaScriptCallFrame::evaluate(ExecState* exec)
77 {
78 NakedPtr<Exception> exception;
79 JSValue result = impl().evaluate(exec->argument(0).toString(exec)->value(exec), exception);
80 if (exception)
81 exec->vm().throwException(exec, exception);
82
83 return result;
84 }
85
86 JSValue JSJavaScriptCallFrame::scopeType(ExecState* exec)
87 {
88 if (!impl().scopeChain())
89 return jsUndefined();
90
91 if (!exec->argument(0).isInt32())
92 return jsUndefined();
93 int index = exec->argument(0).asInt32();
94
95 DebuggerScope* scopeChain = impl().scopeChain();
96 DebuggerScope::iterator end = scopeChain->end();
97
98 bool foundLocalScope = false;
99 for (DebuggerScope::iterator iter = scopeChain->begin(); iter != end; ++iter) {
100 DebuggerScope* scope = iter.get();
101
102 if (!foundLocalScope && scope->isFunctionOrEvalScope()) {
103 // First function scope is the local scope, each successive one is a closure.
104 if (!index)
105 return jsNumber(JSJavaScriptCallFrame::LOCAL_SCOPE);
106 foundLocalScope = true;
107 }
108
109 if (!index) {
110 if (scope->isCatchScope())
111 return jsNumber(JSJavaScriptCallFrame::CATCH_SCOPE);
112 if (scope->isFunctionNameScope())
113 return jsNumber(JSJavaScriptCallFrame::FUNCTION_NAME_SCOPE);
114 if (scope->isWithScope())
115 return jsNumber(JSJavaScriptCallFrame::WITH_SCOPE);
116 if (scope->isGlobalScope()) {
117 ASSERT(++iter == end);
118 return jsNumber(JSJavaScriptCallFrame::GLOBAL_SCOPE);
119 }
120 ASSERT(scope->isFunctionOrEvalScope());
121 return jsNumber(JSJavaScriptCallFrame::CLOSURE_SCOPE);
122 }
123
124 --index;
125 }
126
127 ASSERT_NOT_REACHED();
128 return jsUndefined();
129 }
130
131 JSValue JSJavaScriptCallFrame::caller(ExecState* exec) const
132 {
133 return toJS(exec, globalObject(), impl().caller());
134 }
135
136 JSValue JSJavaScriptCallFrame::sourceID(ExecState*) const
137 {
138 return jsNumber(impl().sourceID());
139 }
140
141 JSValue JSJavaScriptCallFrame::line(ExecState*) const
142 {
143 return jsNumber(impl().line());
144 }
145
146 JSValue JSJavaScriptCallFrame::column(ExecState*) const
147 {
148 return jsNumber(impl().column());
149 }
150
151 JSValue JSJavaScriptCallFrame::functionName(ExecState* exec) const
152 {
153 return jsString(exec, impl().functionName());
154 }
155
156 JSValue JSJavaScriptCallFrame::scopeChain(ExecState* exec) const
157 {
158 if (!impl().scopeChain())
159 return jsNull();
160
161 DebuggerScope* scopeChain = impl().scopeChain();
162 DebuggerScope::iterator iter = scopeChain->begin();
163 DebuggerScope::iterator end = scopeChain->end();
164
165 // We must always have something in the scope chain.
166 ASSERT(iter != end);
167
168 MarkedArgumentBuffer list;
169 do {
170 list.append(iter.get());
171 ++iter;
172 } while (iter != end);
173
174 return constructArray(exec, nullptr, globalObject(), list);
175 }
176
177 JSValue JSJavaScriptCallFrame::thisObject(ExecState*) const
178 {
179 return impl().thisValue();
180 }
181
182 JSValue JSJavaScriptCallFrame::type(ExecState* exec) const
183 {
184 switch (impl().type()) {
185 case DebuggerCallFrame::FunctionType:
186 return jsNontrivialString(exec, ASCIILiteral("function"));
187 case DebuggerCallFrame::ProgramType:
188 return jsNontrivialString(exec, ASCIILiteral("program"));
189 }
190
191 ASSERT_NOT_REACHED();
192 return jsNull();
193 }
194
195 JSValue toJS(ExecState* exec, JSGlobalObject* globalObject, JavaScriptCallFrame* impl)
196 {
197 if (!impl)
198 return jsNull();
199
200 JSObject* prototype = JSJavaScriptCallFrame::createPrototype(exec->vm(), globalObject);
201 Structure* structure = JSJavaScriptCallFrame::createStructure(exec->vm(), globalObject, prototype);
202 JSJavaScriptCallFrame* javaScriptCallFrame = JSJavaScriptCallFrame::create(exec->vm(), structure, impl);
203
204 return javaScriptCallFrame;
205 }
206
207 JSJavaScriptCallFrame* toJSJavaScriptCallFrame(JSValue value)
208 {
209 return value.inherits(JSJavaScriptCallFrame::info()) ? jsCast<JSJavaScriptCallFrame*>(value) : nullptr;
210 }
211
212 } // namespace Inspector
213