| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "config.h" |
| 6 #include "bindings/core/v8/inspector/V8JavaScriptCallFrame.h" |
| 7 |
| 8 #include "wtf/RefPtr.h" |
| 9 |
| 10 namespace blink { |
| 11 |
| 12 namespace { |
| 13 |
| 14 void callerAttributeGetterCallback(v8::Local<v8::Name>, const v8::PropertyCallba
ckInfo<v8::Value>& info) |
| 15 { |
| 16 JavaScriptCallFrame* impl = V8JavaScriptCallFrame::unwrap(info.Holder()); |
| 17 JavaScriptCallFrame* caller = impl->caller(); |
| 18 if (!caller) |
| 19 return; |
| 20 v8::Isolate* isolate = info.GetIsolate(); |
| 21 v8::Local<v8::FunctionTemplate> wrapperTemplate = impl->wrapperTemplate(isol
ate); |
| 22 if (wrapperTemplate.IsEmpty()) |
| 23 return; |
| 24 info.GetReturnValue().Set(V8JavaScriptCallFrame::wrap(wrapperTemplate, isola
te->GetCurrentContext(), caller)); |
| 25 } |
| 26 |
| 27 void sourceIDAttributeGetterCallback(v8::Local<v8::Name>, const v8::PropertyCall
backInfo<v8::Value>& info) |
| 28 { |
| 29 JavaScriptCallFrame* impl = V8JavaScriptCallFrame::unwrap(info.Holder()); |
| 30 info.GetReturnValue().Set(impl->sourceID()); |
| 31 } |
| 32 |
| 33 void lineAttributeGetterCallback(v8::Local<v8::Name>, const v8::PropertyCallback
Info<v8::Value>& info) |
| 34 { |
| 35 JavaScriptCallFrame* impl = V8JavaScriptCallFrame::unwrap(info.Holder()); |
| 36 info.GetReturnValue().Set(impl->line()); |
| 37 } |
| 38 |
| 39 void columnAttributeGetterCallback(v8::Local<v8::Name>, const v8::PropertyCallba
ckInfo<v8::Value>& info) |
| 40 { |
| 41 JavaScriptCallFrame* impl = V8JavaScriptCallFrame::unwrap(info.Holder()); |
| 42 info.GetReturnValue().Set(impl->column()); |
| 43 } |
| 44 |
| 45 void scopeChainAttributeGetterCallback(v8::Local<v8::Name>, const v8::PropertyCa
llbackInfo<v8::Value>& info) |
| 46 { |
| 47 JavaScriptCallFrame* impl = V8JavaScriptCallFrame::unwrap(info.Holder()); |
| 48 info.GetReturnValue().Set(impl->scopeChain()); |
| 49 } |
| 50 |
| 51 void thisObjectAttributeGetterCallback(v8::Local<v8::Name>, const v8::PropertyCa
llbackInfo<v8::Value>& info) |
| 52 { |
| 53 JavaScriptCallFrame* impl = V8JavaScriptCallFrame::unwrap(info.Holder()); |
| 54 info.GetReturnValue().Set(impl->thisObject()); |
| 55 } |
| 56 |
| 57 void stepInPositionsAttributeGetterCallback(v8::Local<v8::Name>, const v8::Prope
rtyCallbackInfo<v8::Value>& info) |
| 58 { |
| 59 JavaScriptCallFrame* impl = V8JavaScriptCallFrame::unwrap(info.Holder()); |
| 60 CString cstr = impl->stepInPositions().utf8(); |
| 61 v8::Local<v8::Name> result = v8::String::NewFromUtf8(info.GetIsolate(), cstr
.data(), v8::NewStringType::kNormal, cstr.length()).ToLocalChecked(); |
| 62 info.GetReturnValue().Set(result); |
| 63 } |
| 64 |
| 65 void functionNameAttributeGetterCallback(v8::Local<v8::Name>, const v8::Property
CallbackInfo<v8::Value>& info) |
| 66 { |
| 67 JavaScriptCallFrame* impl = V8JavaScriptCallFrame::unwrap(info.Holder()); |
| 68 CString cstr = impl->functionName().utf8(); |
| 69 v8::Local<v8::Name> result = v8::String::NewFromUtf8(info.GetIsolate(), cstr
.data(), v8::NewStringType::kNormal, cstr.length()).ToLocalChecked(); |
| 70 info.GetReturnValue().Set(result); |
| 71 } |
| 72 |
| 73 void functionLineAttributeGetterCallback(v8::Local<v8::Name>, const v8::Property
CallbackInfo<v8::Value>& info) |
| 74 { |
| 75 JavaScriptCallFrame* impl = V8JavaScriptCallFrame::unwrap(info.Holder()); |
| 76 info.GetReturnValue().Set(impl->functionLine()); |
| 77 } |
| 78 |
| 79 void functionColumnAttributeGetterCallback(v8::Local<v8::Name>, const v8::Proper
tyCallbackInfo<v8::Value>& info) |
| 80 { |
| 81 JavaScriptCallFrame* impl = V8JavaScriptCallFrame::unwrap(info.Holder()); |
| 82 info.GetReturnValue().Set(impl->functionColumn()); |
| 83 } |
| 84 |
| 85 void isAtReturnAttributeGetterCallback(v8::Local<v8::Name>, const v8::PropertyCa
llbackInfo<v8::Value>& info) |
| 86 { |
| 87 JavaScriptCallFrame* impl = V8JavaScriptCallFrame::unwrap(info.Holder()); |
| 88 info.GetReturnValue().Set(impl->isAtReturn()); |
| 89 } |
| 90 |
| 91 void returnValueAttributeGetterCallback(v8::Local<v8::Name>, const v8::PropertyC
allbackInfo<v8::Value>& info) |
| 92 { |
| 93 JavaScriptCallFrame* impl = V8JavaScriptCallFrame::unwrap(info.Holder()); |
| 94 info.GetReturnValue().Set(impl->returnValue()); |
| 95 } |
| 96 |
| 97 void evaluateWithExceptionDetailsMethodCallback(const v8::FunctionCallbackInfo<v
8::Value>& info) |
| 98 { |
| 99 JavaScriptCallFrame* impl = V8JavaScriptCallFrame::unwrap(info.Holder()); |
| 100 info.GetReturnValue().Set(impl->evaluateWithExceptionDetails(info[0], info[1
])); |
| 101 } |
| 102 |
| 103 void restartMethodCallback(const v8::FunctionCallbackInfo<v8::Value>& info) |
| 104 { |
| 105 JavaScriptCallFrame* impl = V8JavaScriptCallFrame::unwrap(info.Holder()); |
| 106 v8::MaybeLocal<v8::Value> result = impl->restart(); |
| 107 v8::Local<v8::Value> value; |
| 108 if (result.ToLocal(&value)) |
| 109 info.GetReturnValue().Set(value); |
| 110 } |
| 111 |
| 112 void setVariableValueMethodCallback(const v8::FunctionCallbackInfo<v8::Value>& i
nfo) |
| 113 { |
| 114 JavaScriptCallFrame* impl = V8JavaScriptCallFrame::unwrap(info.Holder()); |
| 115 v8::Maybe<int32_t> maybeScopeIndex = info[0]->Int32Value(info.GetIsolate()->
GetCurrentContext()); |
| 116 if (maybeScopeIndex.IsNothing()) |
| 117 return; |
| 118 int scopeIndex = maybeScopeIndex.FromJust(); |
| 119 v8::MaybeLocal<v8::Value> result = impl->setVariableValue(scopeIndex, info[1
], info[2]); |
| 120 v8::Local<v8::Value> value; |
| 121 if (result.ToLocal(&value)) |
| 122 info.GetReturnValue().Set(value); |
| 123 |
| 124 } |
| 125 |
| 126 void scopeTypeMethodCallback(const v8::FunctionCallbackInfo<v8::Value>& info) |
| 127 { |
| 128 JavaScriptCallFrame* impl = V8JavaScriptCallFrame::unwrap(info.Holder()); |
| 129 v8::Maybe<int32_t> maybeScopeIndex = info[0]->Int32Value(info.GetIsolate()->
GetCurrentContext()); |
| 130 if (maybeScopeIndex.IsNothing()) |
| 131 return; |
| 132 int scopeIndex = maybeScopeIndex.FromJust(); |
| 133 info.GetReturnValue().Set(impl->scopeType(scopeIndex)); |
| 134 } |
| 135 |
| 136 struct V8AttributeConfiguration { |
| 137 const char* name; |
| 138 v8::AccessorNameGetterCallback callback; |
| 139 }; |
| 140 |
| 141 const V8AttributeConfiguration V8JavaScriptCallFrameAttributes[] = { |
| 142 {"scopeChain", scopeChainAttributeGetterCallback}, |
| 143 {"thisObject", thisObjectAttributeGetterCallback}, |
| 144 {"returnValue", returnValueAttributeGetterCallback}, |
| 145 |
| 146 {"caller", callerAttributeGetterCallback}, |
| 147 {"sourceID", sourceIDAttributeGetterCallback}, |
| 148 {"line", lineAttributeGetterCallback}, |
| 149 {"column", columnAttributeGetterCallback}, |
| 150 {"stepInPositions", stepInPositionsAttributeGetterCallback}, |
| 151 {"functionName", functionNameAttributeGetterCallback}, |
| 152 {"functionLine", functionLineAttributeGetterCallback}, |
| 153 {"functionColumn", functionColumnAttributeGetterCallback}, |
| 154 {"isAtReturn", isAtReturnAttributeGetterCallback}, |
| 155 }; |
| 156 |
| 157 struct V8MethodConfiguration { |
| 158 const char* name; |
| 159 v8::FunctionCallback callback; |
| 160 }; |
| 161 |
| 162 const V8MethodConfiguration V8JavaScriptCallFrameMethods[] = { |
| 163 {"evaluateWithExceptionDetails", evaluateWithExceptionDetailsMethodCallback}
, |
| 164 {"restart", restartMethodCallback}, |
| 165 {"setVariableValue", setVariableValueMethodCallback}, |
| 166 {"scopeType", scopeTypeMethodCallback}, |
| 167 }; |
| 168 |
| 169 class WeakCallbackData final { |
| 170 public: |
| 171 WeakCallbackData(v8::Isolate* isolate, PassRefPtr<JavaScriptCallFrame> frame
, v8::Local<v8::Object> wrapper) |
| 172 : m_frame(frame) |
| 173 , m_persistent(isolate, wrapper) |
| 174 { |
| 175 m_persistent.SetWeak(this, &WeakCallbackData::weakCallback, v8::WeakCall
backType::kParameter); |
| 176 } |
| 177 |
| 178 RefPtr<JavaScriptCallFrame> m_frame; |
| 179 |
| 180 private: |
| 181 static void weakCallback(const v8::WeakCallbackInfo<WeakCallbackData>& info) |
| 182 { |
| 183 delete info.GetParameter(); |
| 184 } |
| 185 |
| 186 v8::Global<v8::Object> m_persistent; |
| 187 }; |
| 188 |
| 189 } // namespace |
| 190 |
| 191 v8::Local<v8::FunctionTemplate> V8JavaScriptCallFrame::createWrapperTemplate(v8:
:Isolate* isolate) |
| 192 { |
| 193 v8::Local<v8::FunctionTemplate> functionTemplate = v8::FunctionTemplate::New
(isolate); |
| 194 |
| 195 functionTemplate->SetClassName(v8::String::NewFromUtf8(isolate, "JavaScriptC
allFrame", v8::NewStringType::kInternalized).ToLocalChecked()); |
| 196 v8::Local<v8::ObjectTemplate> instanceTemplate = functionTemplate->InstanceT
emplate(); |
| 197 for (auto& config : V8JavaScriptCallFrameAttributes) { |
| 198 v8::Local<v8::Name> v8name = v8::String::NewFromUtf8(isolate, config.nam
e, v8::NewStringType::kInternalized).ToLocalChecked(); |
| 199 instanceTemplate->SetAccessor(v8name, config.callback); |
| 200 } |
| 201 |
| 202 for (auto& config : V8JavaScriptCallFrameMethods) { |
| 203 v8::Local<v8::Name> v8name = v8::String::NewFromUtf8(isolate, config.nam
e, v8::NewStringType::kInternalized).ToLocalChecked(); |
| 204 v8::Local<v8::FunctionTemplate> functionTemplate = v8::FunctionTemplate:
:New(isolate, config.callback); |
| 205 functionTemplate->RemovePrototype(); |
| 206 instanceTemplate->Set(v8name, functionTemplate); |
| 207 } |
| 208 |
| 209 return functionTemplate; |
| 210 } |
| 211 |
| 212 v8::Local<v8::Object> V8JavaScriptCallFrame::wrap(v8::Local<v8::FunctionTemplate
> constructorTemplate, v8::Local<v8::Context> context, PassRefPtr<JavaScriptCall
Frame> frame) |
| 213 { |
| 214 RefPtr<JavaScriptCallFrame> impl(frame); |
| 215 v8::Local<v8::Function> function; |
| 216 if (!constructorTemplate->GetFunction(context).ToLocal(&function)) |
| 217 return v8::Local<v8::Object>(); |
| 218 |
| 219 v8::MaybeLocal<v8::Object> maybeResult = function->NewInstance(context); |
| 220 v8::Local<v8::Object> result; |
| 221 if (!maybeResult.ToLocal(&result)) |
| 222 return v8::Local<v8::Object>(); |
| 223 |
| 224 v8::Isolate* isolate = context->GetIsolate(); |
| 225 v8::Local<v8::External> objectReference = v8::External::New(isolate, new Wea
kCallbackData(isolate, impl, result)); |
| 226 result->SetHiddenValue(hiddenPropertyName(isolate), objectReference); |
| 227 |
| 228 // Store template for .caller callback |
| 229 impl->setWrapperTemplate(constructorTemplate, isolate); |
| 230 |
| 231 return result; |
| 232 } |
| 233 |
| 234 JavaScriptCallFrame* V8JavaScriptCallFrame::unwrap(v8::Local<v8::Object> object) |
| 235 { |
| 236 v8::Isolate* isolate = object->GetIsolate(); |
| 237 v8::Local<v8::Value> value = object->GetHiddenValue(hiddenPropertyName(isola
te)); |
| 238 if (value.IsEmpty()) |
| 239 return nullptr; |
| 240 if (!value->IsExternal()) |
| 241 return nullptr; |
| 242 void* data = value.As<v8::External>()->Value(); |
| 243 return reinterpret_cast<WeakCallbackData*>(data)->m_frame.get(); |
| 244 } |
| 245 |
| 246 v8::Local<v8::String> V8JavaScriptCallFrame::hiddenPropertyName(v8::Isolate* iso
late) |
| 247 { |
| 248 return v8::String::NewFromUtf8(isolate, "v8inspector::JavaScriptCallFrame",
v8::NewStringType::kInternalized).ToLocalChecked(); |
| 249 } |
| 250 |
| 251 } // namespace blink |
| OLD | NEW |