Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(9)

Side by Side Diff: third_party/WebKit/Source/platform/v8_inspector/V8RuntimeAgentImpl.cpp

Issue 2196003002: [DevTools] Add awaitPromise flag to Runtime.evaluate (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@add-promise-then
Patch Set: addressed comments Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2011 Google Inc. All rights reserved. 2 * Copyright (C) 2011 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 53
54 static bool hasInternalError(ErrorString* errorString, bool hasError) 54 static bool hasInternalError(ErrorString* errorString, bool hasError)
55 { 55 {
56 if (hasError) 56 if (hasError)
57 *errorString = "Internal error"; 57 *errorString = "Internal error";
58 return hasError; 58 return hasError;
59 } 59 }
60 60
61 namespace { 61 namespace {
62 62
63 template<typename Callback>
63 class ProtocolPromiseHandler { 64 class ProtocolPromiseHandler {
64 public: 65 public:
65 static void add(V8DebuggerImpl* debugger, int contextGroupId, const String16 & promiseObjectId, std::unique_ptr<protocol::Runtime::Backend::AwaitPromiseCallb ack> callback, bool returnByValue, bool generatePreview) 66 static void add(V8DebuggerImpl* debugger, int contextGroupId, const String16 & promiseObjectId, std::unique_ptr<Callback> callback, bool returnByValue, bool generatePreview)
66 { 67 {
67 ErrorString errorString; 68 ErrorString errorString;
68 InjectedScript::ObjectScope scope(&errorString, debugger, contextGroupId , promiseObjectId); 69 InjectedScript::ObjectScope scope(&errorString, debugger, contextGroupId , promiseObjectId);
69 if (!scope.initialize()) { 70 if (!scope.initialize()) {
70 callback->sendFailure(errorString); 71 callback->sendFailure(errorString);
71 return; 72 return;
72 } 73 }
73 if (!scope.object()->IsPromise()) { 74 if (!scope.object()->IsPromise()) {
74 callback->sendFailure("Could not find promise with given id"); 75 callback->sendFailure("Could not find promise with given id");
75 return; 76 return;
76 } 77 }
77 78
78 protocol::Runtime::Backend::AwaitPromiseCallback* rawCallback = callback .get(); 79 Callback* rawCallback = callback.get();
79 ProtocolPromiseHandler* handler = new ProtocolPromiseHandler(debugger, c ontextGroupId, promiseObjectId, std::move(callback), returnByValue, generatePrev iew); 80 ProtocolPromiseHandler<Callback>* handler = new ProtocolPromiseHandler(d ebugger, contextGroupId, promiseObjectId, std::move(callback), returnByValue, ge neratePreview);
80 v8::Local<v8::Value> wrapper = handler->m_wrapper.Get(debugger->isolate( )); 81 v8::Local<v8::Value> wrapper = handler->m_wrapper.Get(debugger->isolate( ));
81 v8::Local<v8::Promise> promise = v8::Local<v8::Promise>::Cast(scope.obje ct()); 82 v8::Local<v8::Promise> promise = v8::Local<v8::Promise>::Cast(scope.obje ct());
82 83
83 v8::Local<v8::Function> thenCallbackFunction = v8::Function::New(scope.c ontext(), thenCallback, wrapper, 0, v8::ConstructorBehavior::kThrow).ToLocalChec ked(); 84 v8::Local<v8::Function> thenCallbackFunction = v8::Function::New(scope.c ontext(), thenCallback, wrapper, 0, v8::ConstructorBehavior::kThrow).ToLocalChec ked();
84 if (promise->Then(scope.context(), thenCallbackFunction).IsEmpty()) { 85 if (promise->Then(scope.context(), thenCallbackFunction).IsEmpty()) {
85 rawCallback->sendFailure("Internal error"); 86 rawCallback->sendFailure("Internal error");
86 return; 87 return;
87 } 88 }
88 v8::Local<v8::Function> catchCallbackFunction = v8::Function::New(scope. context(), catchCallback, wrapper, 0, v8::ConstructorBehavior::kThrow).ToLocalCh ecked(); 89 v8::Local<v8::Function> catchCallbackFunction = v8::Function::New(scope. context(), catchCallback, wrapper, 0, v8::ConstructorBehavior::kThrow).ToLocalCh ecked();
89 if (promise->Catch(scope.context(), catchCallbackFunction).IsEmpty()) { 90 if (promise->Catch(scope.context(), catchCallbackFunction).IsEmpty()) {
90 rawCallback->sendFailure("Internal error"); 91 rawCallback->sendFailure("Internal error");
91 return; 92 return;
92 } 93 }
93 } 94 }
94 95
95 private: 96 private:
96 static void thenCallback(const v8::FunctionCallbackInfo<v8::Value>& info) 97 static void thenCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
97 { 98 {
98 ProtocolPromiseHandler* handler = static_cast<ProtocolPromiseHandler*>(i nfo.Data().As<v8::External>()->Value()); 99 ProtocolPromiseHandler<Callback>* handler = static_cast<ProtocolPromiseH andler<Callback>*>(info.Data().As<v8::External>()->Value());
99 DCHECK(handler); 100 DCHECK(handler);
100 v8::Local<v8::Value> value = info.Length() > 0 ? info[0] : v8::Local<v8: :Value>::Cast(v8::Undefined(info.GetIsolate())); 101 v8::Local<v8::Value> value = info.Length() > 0 ? info[0] : v8::Local<v8: :Value>::Cast(v8::Undefined(info.GetIsolate()));
101 handler->m_callback->sendSuccess(handler->wrapObject(value), Maybe<bool> (), Maybe<protocol::Runtime::ExceptionDetails>()); 102 handler->m_callback->sendSuccess(handler->wrapObject(value), Maybe<bool> (), Maybe<protocol::Runtime::ExceptionDetails>());
102 } 103 }
103 104
104 static void catchCallback(const v8::FunctionCallbackInfo<v8::Value>& info) 105 static void catchCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
105 { 106 {
106 ProtocolPromiseHandler* handler = static_cast<ProtocolPromiseHandler*>(i nfo.Data().As<v8::External>()->Value()); 107 ProtocolPromiseHandler<Callback>* handler = static_cast<ProtocolPromiseH andler<Callback>*>(info.Data().As<v8::External>()->Value());
107 DCHECK(handler); 108 DCHECK(handler);
108 v8::Local<v8::Value> value = info.Length() > 0 ? info[0] : v8::Local<v8: :Value>::Cast(v8::Undefined(info.GetIsolate())); 109 v8::Local<v8::Value> value = info.Length() > 0 ? info[0] : v8::Local<v8: :Value>::Cast(v8::Undefined(info.GetIsolate()));
109 110
110 std::unique_ptr<protocol::Runtime::ExceptionDetails> exceptionDetails; 111 std::unique_ptr<protocol::Runtime::ExceptionDetails> exceptionDetails;
111 std::unique_ptr<V8StackTraceImpl> stack = handler->m_debugger->captureSt ackTraceImpl(true); 112 std::unique_ptr<V8StackTraceImpl> stack = handler->m_debugger->captureSt ackTraceImpl(true);
112 if (stack) { 113 if (stack) {
113 exceptionDetails = protocol::Runtime::ExceptionDetails::create() 114 exceptionDetails = protocol::Runtime::ExceptionDetails::create()
114 .setText("Promise was rejected") 115 .setText("Promise was rejected")
115 .setLineNumber(!stack->isEmpty() ? stack->topLineNumber() : 0) 116 .setLineNumber(!stack->isEmpty() ? stack->topLineNumber() : 0)
116 .setColumnNumber(!stack->isEmpty() ? stack->topColumnNumber() : 0) 117 .setColumnNumber(!stack->isEmpty() ? stack->topColumnNumber() : 0)
117 .setScriptId(!stack->isEmpty() ? stack->topScriptId() : String16 ()) 118 .setScriptId(!stack->isEmpty() ? stack->topScriptId() : String16 ())
118 .setStackTrace(stack->buildInspectorObjectImpl()) 119 .setStackTrace(stack->buildInspectorObjectImpl())
119 .build(); 120 .build();
120 } 121 }
121 handler->m_callback->sendSuccess(handler->wrapObject(value), true, std:: move(exceptionDetails)); 122 handler->m_callback->sendSuccess(handler->wrapObject(value), true, std:: move(exceptionDetails));
122 } 123 }
123 124
124 ProtocolPromiseHandler(V8DebuggerImpl* debugger, int contextGroupId, const S tring16& promiseObjectId, std::unique_ptr<V8RuntimeAgentImpl::AwaitPromiseCallba ck> callback, bool returnByValue, bool generatePreview) 125 ProtocolPromiseHandler(V8DebuggerImpl* debugger, int contextGroupId, const S tring16& promiseObjectId, std::unique_ptr<Callback> callback, bool returnByValue , bool generatePreview)
125 : m_debugger(debugger) 126 : m_debugger(debugger)
126 , m_contextGroupId(contextGroupId) 127 , m_contextGroupId(contextGroupId)
127 , m_promiseObjectId(promiseObjectId) 128 , m_promiseObjectId(promiseObjectId)
128 , m_callback(std::move(callback)) 129 , m_callback(std::move(callback))
129 , m_returnByValue(returnByValue) 130 , m_returnByValue(returnByValue)
130 , m_generatePreview(generatePreview) 131 , m_generatePreview(generatePreview)
131 , m_wrapper(debugger->isolate(), v8::External::New(debugger->isolate(), this)) 132 , m_wrapper(debugger->isolate(), v8::External::New(debugger->isolate(), this))
132 { 133 {
133 m_wrapper.SetWeak(this, cleanup, v8::WeakCallbackType::kParameter); 134 m_wrapper.SetWeak(this, cleanup, v8::WeakCallbackType::kParameter);
134 } 135 }
135 136
136 static void cleanup(const v8::WeakCallbackInfo<ProtocolPromiseHandler>& data ) 137 static void cleanup(const v8::WeakCallbackInfo<ProtocolPromiseHandler<Callba ck>>& data)
137 { 138 {
138 if (!data.GetParameter()->m_wrapper.IsEmpty()) { 139 if (!data.GetParameter()->m_wrapper.IsEmpty()) {
139 data.GetParameter()->m_wrapper.Reset(); 140 data.GetParameter()->m_wrapper.Reset();
140 data.SetSecondPassCallback(cleanup); 141 data.SetSecondPassCallback(cleanup);
141 } else { 142 } else {
142 data.GetParameter()->m_callback->sendFailure("Promise was collected" ); 143 data.GetParameter()->m_callback->sendFailure("Promise was collected" );
143 delete data.GetParameter(); 144 delete data.GetParameter();
144 } 145 }
145 } 146 }
146 147
147 std::unique_ptr<protocol::Runtime::RemoteObject> wrapObject(v8::Local<v8::Va lue> value) 148 std::unique_ptr<protocol::Runtime::RemoteObject> wrapObject(v8::Local<v8::Va lue> value)
148 { 149 {
149 ErrorString errorString; 150 ErrorString errorString;
150 InjectedScript::ObjectScope scope(&errorString, m_debugger, m_contextGro upId, m_promiseObjectId); 151 InjectedScript::ObjectScope scope(&errorString, m_debugger, m_contextGro upId, m_promiseObjectId);
151 if (!scope.initialize()) { 152 if (!scope.initialize()) {
152 m_callback->sendFailure(errorString); 153 m_callback->sendFailure(errorString);
153 return nullptr; 154 return nullptr;
154 } 155 }
155 std::unique_ptr<protocol::Runtime::RemoteObject> wrappedValue = scope.in jectedScript()->wrapObject(&errorString, value, scope.objectGroupName(), m_retur nByValue, m_generatePreview); 156 std::unique_ptr<protocol::Runtime::RemoteObject> wrappedValue = scope.in jectedScript()->wrapObject(&errorString, value, scope.objectGroupName(), m_retur nByValue, m_generatePreview);
156 if (!wrappedValue) { 157 if (!wrappedValue) {
157 m_callback->sendFailure(errorString); 158 m_callback->sendFailure(errorString);
158 return nullptr; 159 return nullptr;
159 } 160 }
160 return wrappedValue; 161 return wrappedValue;
161 } 162 }
162 163
163 V8DebuggerImpl* m_debugger; 164 V8DebuggerImpl* m_debugger;
164 int m_contextGroupId; 165 int m_contextGroupId;
165 String16 m_promiseObjectId; 166 String16 m_promiseObjectId;
166 std::unique_ptr<V8RuntimeAgentImpl::AwaitPromiseCallback> m_callback; 167 std::unique_ptr<Callback> m_callback;
167 bool m_returnByValue; 168 bool m_returnByValue;
168 bool m_generatePreview; 169 bool m_generatePreview;
169 v8::Global<v8::External> m_wrapper; 170 v8::Global<v8::External> m_wrapper;
170 }; 171 };
171 172
172 } // namespace 173 } // namespace
173 174
174 V8RuntimeAgentImpl::V8RuntimeAgentImpl(V8InspectorSessionImpl* session, protocol ::FrontendChannel* FrontendChannel, protocol::DictionaryValue* state) 175 V8RuntimeAgentImpl::V8RuntimeAgentImpl(V8InspectorSessionImpl* session, protocol ::FrontendChannel* FrontendChannel, protocol::DictionaryValue* state)
175 : m_session(session) 176 : m_session(session)
176 , m_state(state) 177 , m_state(state)
(...skipping 10 matching lines...) Expand all
187 void V8RuntimeAgentImpl::evaluate( 188 void V8RuntimeAgentImpl::evaluate(
188 ErrorString* errorString, 189 ErrorString* errorString,
189 const String16& expression, 190 const String16& expression,
190 const Maybe<String16>& objectGroup, 191 const Maybe<String16>& objectGroup,
191 const Maybe<bool>& includeCommandLineAPI, 192 const Maybe<bool>& includeCommandLineAPI,
192 const Maybe<bool>& doNotPauseOnExceptionsAndMuteConsole, 193 const Maybe<bool>& doNotPauseOnExceptionsAndMuteConsole,
193 const Maybe<int>& executionContextId, 194 const Maybe<int>& executionContextId,
194 const Maybe<bool>& returnByValue, 195 const Maybe<bool>& returnByValue,
195 const Maybe<bool>& generatePreview, 196 const Maybe<bool>& generatePreview,
196 const Maybe<bool>& userGesture, 197 const Maybe<bool>& userGesture,
197 std::unique_ptr<RemoteObject>* result, 198 const Maybe<bool>& awaitPromise,
198 Maybe<bool>* wasThrown, 199 std::unique_ptr<EvaluateCallback> callback)
199 Maybe<ExceptionDetails>* exceptionDetails)
200 { 200 {
201 int contextId; 201 int contextId;
202 if (executionContextId.isJust()) { 202 if (executionContextId.isJust()) {
203 contextId = executionContextId.fromJust(); 203 contextId = executionContextId.fromJust();
204 } else { 204 } else {
205 v8::HandleScope handles(m_debugger->isolate()); 205 v8::HandleScope handles(m_debugger->isolate());
206 v8::Local<v8::Context> defaultContext = m_debugger->client()->ensureDefa ultContextInGroup(m_session->contextGroupId()); 206 v8::Local<v8::Context> defaultContext = m_debugger->client()->ensureDefa ultContextInGroup(m_session->contextGroupId());
207 if (defaultContext.IsEmpty()) { 207 if (defaultContext.IsEmpty()) {
208 *errorString = "Cannot find default execution context"; 208 callback->sendFailure("Cannot find default execution context");
209 return; 209 return;
210 } 210 }
211 contextId = V8DebuggerImpl::contextId(defaultContext); 211 contextId = V8DebuggerImpl::contextId(defaultContext);
212 } 212 }
213 213
214 InjectedScript::ContextScope scope(errorString, m_debugger, m_session->conte xtGroupId(), contextId); 214 InjectedScript::ContextScope scope(errorString, m_debugger, m_session->conte xtGroupId(), contextId);
215 if (!scope.initialize()) 215 if (!scope.initialize()) {
216 callback->sendFailure(*errorString);
216 return; 217 return;
218 }
217 219
218 if (doNotPauseOnExceptionsAndMuteConsole.fromMaybe(false)) 220 if (doNotPauseOnExceptionsAndMuteConsole.fromMaybe(false))
219 scope.ignoreExceptionsAndMuteConsole(); 221 scope.ignoreExceptionsAndMuteConsole();
220 if (userGesture.fromMaybe(false)) 222 if (userGesture.fromMaybe(false))
221 scope.pretendUserGesture(); 223 scope.pretendUserGesture();
222 224
223 if (includeCommandLineAPI.fromMaybe(false) && !scope.installCommandLineAPI() ) 225 if (includeCommandLineAPI.fromMaybe(false) && !scope.installCommandLineAPI() ) {
226 callback->sendFailure(*errorString);
224 return; 227 return;
228 }
225 229
226 bool evalIsDisabled = !scope.context()->IsCodeGenerationFromStringsAllowed() ; 230 bool evalIsDisabled = !scope.context()->IsCodeGenerationFromStringsAllowed() ;
227 // Temporarily enable allow evals for inspector. 231 // Temporarily enable allow evals for inspector.
228 if (evalIsDisabled) 232 if (evalIsDisabled)
229 scope.context()->AllowCodeGenerationFromStrings(true); 233 scope.context()->AllowCodeGenerationFromStrings(true);
230 234
231 v8::MaybeLocal<v8::Value> maybeResultValue; 235 v8::MaybeLocal<v8::Value> maybeResultValue;
232 v8::Local<v8::Script> script = m_debugger->compileScript(scope.context(), to V8String(m_debugger->isolate(), expression), String16(), false); 236 v8::Local<v8::Script> script = m_debugger->compileScript(scope.context(), to V8String(m_debugger->isolate(), expression), String16(), false);
233 if (!script.IsEmpty()) 237 if (!script.IsEmpty())
234 maybeResultValue = m_debugger->runCompiledScript(scope.context(), script ); 238 maybeResultValue = m_debugger->runCompiledScript(scope.context(), script );
235 239
236 if (evalIsDisabled) 240 if (evalIsDisabled)
237 scope.context()->AllowCodeGenerationFromStrings(false); 241 scope.context()->AllowCodeGenerationFromStrings(false);
238 242
239 // Re-initialize after running client's code, as it could have destroyed con text or session. 243 // Re-initialize after running client's code, as it could have destroyed con text or session.
240 if (!scope.initialize()) 244 if (!scope.initialize()) {
245 callback->sendFailure(*errorString);
241 return; 246 return;
247 }
248
249 std::unique_ptr<RemoteObject> result;
250 Maybe<bool> wasThrown;
251 Maybe<protocol::Runtime::ExceptionDetails> exceptionDetails;
252
242 scope.injectedScript()->wrapEvaluateResult(errorString, 253 scope.injectedScript()->wrapEvaluateResult(errorString,
243 maybeResultValue, 254 maybeResultValue,
244 scope.tryCatch(), 255 scope.tryCatch(),
245 objectGroup.fromMaybe(""), 256 objectGroup.fromMaybe(""),
246 returnByValue.fromMaybe(false), 257 returnByValue.fromMaybe(false) && !awaitPromise.fromMaybe(false),
247 generatePreview.fromMaybe(false), 258 generatePreview.fromMaybe(false) && !awaitPromise.fromMaybe(false),
248 result, 259 &result,
249 wasThrown, 260 &wasThrown,
250 exceptionDetails); 261 &exceptionDetails);
262 if (!errorString->isEmpty()) {
263 callback->sendFailure(*errorString);
264 return;
265 }
266
267 if (!awaitPromise.fromMaybe(false) || wasThrown.fromMaybe(false)) {
268 callback->sendSuccess(std::move(result), wasThrown, exceptionDetails);
269 return;
270 }
271
272 if (maybeResultValue.IsEmpty()) {
273 callback->sendFailure("Internal error");
274 return;
275 }
276
277 if (!maybeResultValue.ToLocalChecked()->IsPromise()) {
278 callback->sendFailure("Result of expression is not a promise.");
279 return;
280 }
281
282 ProtocolPromiseHandler<EvaluateCallback>::add(m_debugger, m_session->context GroupId(), result->getObjectId(String16()), std::move(callback), returnByValue.f romMaybe(false), generatePreview.fromMaybe(false));
251 } 283 }
252 284
253 void V8RuntimeAgentImpl::awaitPromise(ErrorString* errorString, 285 void V8RuntimeAgentImpl::awaitPromise(ErrorString* errorString,
254 const String16& promiseObjectId, 286 const String16& promiseObjectId,
255 const Maybe<bool>& returnByValue, 287 const Maybe<bool>& returnByValue,
256 const Maybe<bool>& generatePreview, 288 const Maybe<bool>& generatePreview,
257 std::unique_ptr<AwaitPromiseCallback> callback) 289 std::unique_ptr<AwaitPromiseCallback> callback)
258 { 290 {
259 ProtocolPromiseHandler::add(m_debugger, m_session->contextGroupId(), promise ObjectId, std::move(callback), returnByValue.fromMaybe(false), generatePreview.f romMaybe(false)); 291 ProtocolPromiseHandler<AwaitPromiseCallback>::add(m_debugger, m_session->con textGroupId(), promiseObjectId, std::move(callback), returnByValue.fromMaybe(fal se), generatePreview.fromMaybe(false));
260 } 292 }
261 293
262 void V8RuntimeAgentImpl::callFunctionOn(ErrorString* errorString, 294 void V8RuntimeAgentImpl::callFunctionOn(ErrorString* errorString,
263 const String16& objectId, 295 const String16& objectId,
264 const String16& expression, 296 const String16& expression,
265 const Maybe<protocol::Array<protocol::Runtime::CallArgument>>& optionalArgum ents, 297 const Maybe<protocol::Array<protocol::Runtime::CallArgument>>& optionalArgum ents,
266 const Maybe<bool>& doNotPauseOnExceptionsAndMuteConsole, 298 const Maybe<bool>& doNotPauseOnExceptionsAndMuteConsole,
267 const Maybe<bool>& returnByValue, 299 const Maybe<bool>& returnByValue,
268 const Maybe<bool>& generatePreview, 300 const Maybe<bool>& generatePreview,
269 const Maybe<bool>& userGesture, 301 const Maybe<bool>& userGesture,
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
560 reportMessage(message, true); 592 reportMessage(message, true);
561 } 593 }
562 594
563 void V8RuntimeAgentImpl::reportMessage(V8ConsoleMessage* message, bool generateP review) 595 void V8RuntimeAgentImpl::reportMessage(V8ConsoleMessage* message, bool generateP review)
564 { 596 {
565 message->reportToFrontend(&m_frontend, m_session, generatePreview); 597 message->reportToFrontend(&m_frontend, m_session, generatePreview);
566 m_frontend.flush(); 598 m_frontend.flush();
567 } 599 }
568 600
569 } // namespace blink 601 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698