5 #include "src/inspector/custom-preview.h" 7 #include "src/debug/debug-interface.h" 8 #include "src/inspector/injected-script.h" 9 #include "src/inspector/inspected-context.h" 10 #include "src/inspector/string-util.h" 11 #include "src/inspector/v8-console-message.h" 12 #include "src/inspector/v8-inspector-impl.h" 13 #include "src/inspector/v8-stack-trace-impl.h" 17 using protocol::Runtime::CustomPreview;
21 DCHECK(tryCatch.HasCaught());
22 v8::Isolate* isolate = context->GetIsolate();
23 V8InspectorImpl* inspector =
24 static_cast<V8InspectorImpl*
>(v8::debug::GetInspector(isolate));
25 int contextId = InspectedContext::contextId(context);
26 int groupId = inspector->contextGroupId(contextId);
29 toV8String(isolate,
"Custom Formatter Failed: ");
31 std::vector<v8::Local<v8::Value>> arguments;
32 arguments.push_back(message);
33 V8ConsoleMessageStorage* storage =
34 inspector->ensureConsoleMessageStorage(groupId);
36 storage->addMessage(V8ConsoleMessage::createForConsoleAPI(
37 context, contextId, groupId, inspector,
38 inspector->client()->currentTimeMS(), ConsoleAPIType::kError, arguments,
39 String16(),
nullptr));
43 const String16& message) {
44 v8::Isolate* isolate = context->GetIsolate();
45 isolate->ThrowException(toV8String(isolate, message));
46 reportError(context, tryCatch);
51 v8::Isolate* isolate = context->GetIsolate();
52 V8InspectorImpl* inspector =
53 static_cast<V8InspectorImpl*
>(v8::debug::GetInspector(isolate));
54 InspectedContext* inspectedContext =
55 inspector->getContext(InspectedContext::contextId(context));
56 if (!inspectedContext)
return nullptr;
57 return inspectedContext->getInjectedScript(sessionId);
60 bool substituteObjectTags(
int sessionId,
const String16& groupName,
63 if (!jsonML->Length())
return true;
64 v8::Isolate* isolate = context->GetIsolate();
65 v8::TryCatch tryCatch(isolate);
68 reportError(context, tryCatch,
69 "Too deep hierarchy of inlined custom previews");
74 if (!jsonML->Get(context, 0).
ToLocal(&firstValue)) {
75 reportError(context, tryCatch);
79 if (jsonML->Length() == 2 && firstValue->
IsString() &&
80 firstValue.
As<
v8::String>()->StringEquals(objectLiteral)) {
82 if (!jsonML->Get(context, 1).
ToLocal(&attributesValue)) {
83 reportError(context, tryCatch);
87 reportError(context, tryCatch,
"attributes should be an Object");
92 if (!attributes->Get(context, objectLiteral).
ToLocal(&originValue)) {
93 reportError(context, tryCatch);
96 if (originValue->IsUndefined()) {
97 reportError(context, tryCatch,
98 "obligatory attribute \"object\" isn't specified");
103 if (!attributes->Get(context, toV8String(isolate,
"config"))
105 reportError(context, tryCatch);
109 InjectedScript* injectedScript = getInjectedScript(context, sessionId);
110 if (!injectedScript) {
111 reportError(context, tryCatch,
"cannot find context with specified id");
114 std::unique_ptr<protocol::Runtime::RemoteObject> wrapper;
115 protocol::Response response =
116 injectedScript->wrapObject(originValue, groupName, WrapMode::kNoPreview,
117 configValue, maxDepth - 1, &wrapper);
118 if (!response.isSuccess() || !wrapper) {
119 reportError(context, tryCatch,
"cannot wrap value");
123 String16 serialized = wrapper->serialize();
124 if (!v8::JSON::Parse(context, toV8String(isolate, serialized))
125 .ToLocal(&jsonWrapper)) {
126 reportError(context, tryCatch,
"cannot wrap value");
129 if (jsonML->Set(context, 1, jsonWrapper).IsNothing()) {
130 reportError(context, tryCatch);
136 if (!jsonML->Get(context,
i).
ToLocal(&value)) {
137 reportError(context, tryCatch);
140 if (value->IsArray() && value.As<
v8::Array>()->Length() > 0 &&
141 !substituteObjectTags(sessionId, groupName, context,
152 v8::TryCatch tryCatch(isolate);
157 if (!bodyConfig->Get(context, toV8String(isolate,
"object"))
159 reportError(context, tryCatch);
162 if (!objectValue->IsObject()) {
163 reportError(context, tryCatch,
"object should be an Object");
169 if (!bodyConfig->Get(context, toV8String(isolate,
"formatter"))
171 reportError(context, tryCatch);
174 if (!formatterValue->IsObject()) {
175 reportError(context, tryCatch,
"formatter should be an Object");
181 if (!formatter->Get(context, toV8String(isolate,
"body"))
183 reportError(context, tryCatch);
186 if (!bodyValue->IsFunction()) {
187 reportError(context, tryCatch,
"body should be a Function");
193 if (!bodyConfig->Get(context, toV8String(isolate,
"config"))
195 reportError(context, tryCatch);
200 if (!bodyConfig->Get(context, toV8String(isolate,
"sessionId"))
202 reportError(context, tryCatch);
205 if (!sessionIdValue->
IsInt32()) {
206 reportError(context, tryCatch,
"sessionId should be an Int32");
211 if (!bodyConfig->Get(context, toV8String(isolate,
"groupName"))
213 reportError(context, tryCatch);
217 reportError(context, tryCatch,
"groupName should be a string");
223 if (!bodyFunction->Call(context, formatter, 2, args)
225 reportError(context, tryCatch);
228 if (!formattedValue->
IsArray()) {
229 reportError(context, tryCatch,
"body should return an Array");
233 if (jsonML->Length() &&
234 !substituteObjectTags(
236 toProtocolString(isolate, groupNameValue.
As<
v8::String>()), context,
237 jsonML, kMaxCustomPreviewDepth)) {
244 void generateCustomPreview(
int sessionId,
const String16& groupName,
248 std::unique_ptr<CustomPreview>* preview) {
249 v8::Isolate* isolate = context->GetIsolate();
250 v8::MicrotasksScope microtasksScope(isolate,
251 v8::MicrotasksScope::kDoNotRunMicrotasks);
252 v8::TryCatch tryCatch(isolate);
255 if (!maybeConfig.
ToLocal(&configValue)) configValue = v8::Undefined(isolate);
259 if (!global->Get(context, toV8String(isolate,
"devtoolsFormatters"))
261 reportError(context, tryCatch);
264 if (!formattersValue->
IsArray())
return;
268 for (
uint32_t i = 0;
i < formatters->Length(); ++
i) {
270 if (!formatters->Get(context,
i).
ToLocal(&formatterValue)) {
271 reportError(context, tryCatch);
275 reportError(context, tryCatch,
"formatter should be an Object");
281 if (!formatter->Get(context, headerLiteral).
ToLocal(&headerValue)) {
282 reportError(context, tryCatch);
285 if (!headerValue->IsFunction()) {
286 reportError(context, tryCatch,
"header should be a Function");
293 if (!headerFunction->Call(context, formatter, 2, args)
295 reportError(context, tryCatch);
298 if (!formattedValue->IsArray())
continue;
302 if (!formatter->Get(context, hasBodyLiteral)
303 .
ToLocal(&hasBodyFunctionValue)) {
304 reportError(context, tryCatch);
307 if (!hasBodyFunctionValue->IsFunction())
continue;
311 if (!hasBodyFunction->Call(context, formatter, 2, args)
313 reportError(context, tryCatch);
316 bool hasBody = hasBodyValue->ToBoolean(isolate)->Value();
318 if (jsonML->Length() && !substituteObjectTags(sessionId, groupName, context,
325 reportError(context, tryCatch);
333 ->CreateDataProperty(context, toV8String(isolate,
"sessionId"),
334 v8::Integer::New(isolate, sessionId))
336 reportError(context, tryCatch);
340 ->CreateDataProperty(context, toV8String(isolate,
"formatter"),
343 reportError(context, tryCatch);
347 ->CreateDataProperty(context, toV8String(isolate,
"groupName"),
348 toV8String(isolate, groupName))
350 reportError(context, tryCatch);
354 ->CreateDataProperty(context, toV8String(isolate,
"config"),
357 reportError(context, tryCatch);
361 ->CreateDataProperty(context, toV8String(isolate,
"object"),
364 reportError(context, tryCatch);
368 .ToLocal(&bodyFunction)) {
369 reportError(context, tryCatch);
373 *preview = CustomPreview::create()
374 .setHeader(toProtocolString(isolate, header))
377 InjectedScript* injectedScript = getInjectedScript(context, sessionId);
378 if (!injectedScript) {
379 reportError(context, tryCatch,
"cannot find context with specified id");
382 (*preview)->setBodyGetterId(
383 injectedScript->bindObject(bodyFunction, groupName));
static V8_WARN_UNUSED_RESULT MaybeLocal< String > Stringify(Local< Context > context, Local< Value > json_object, Local< String > gap=Local< String >())
V8_INLINE bool IsString() const
V8_INLINE bool IsEmpty() const
static MaybeLocal< Function > New(Local< Context > context, FunctionCallback callback, Local< Value > data=Local< Value >(), int length=0, ConstructorBehavior behavior=ConstructorBehavior::kAllow, SideEffectType side_effect_type=SideEffectType::kHasSideEffect)
V8_INLINE Local< S > As() const
V8_WARN_UNUSED_RESULT V8_INLINE bool ToLocal(Local< S > *out) const
V8_INLINE Local< Value > Data() const
V8_INLINE ReturnValue< T > GetReturnValue() const
V8_INLINE Isolate * GetIsolate() const
static Local< String > Concat(Isolate *isolate, Local< String > left, Local< String > right)