1 /* 2 * Copyright (C) 2012 Google 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 are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "src/inspector/injected-script.h" 32 33 #include "src/inspector/injected-script-native.h" 34 #include "src/inspector/injected-script-source.h" 35 #include "src/inspector/inspected-context.h" 36 #include "src/inspector/protocol/Protocol.h" 37 #include "src/inspector/remote-object-id.h" 38 #include "src/inspector/string-util.h" 39 #include "src/inspector/v8-console.h" 40 #include "src/inspector/v8-function-call.h" 41 #include "src/inspector/v8-injected-script-host.h" 42 #include "src/inspector/v8-inspector-impl.h" 43 #include "src/inspector/v8-inspector-session-impl.h" 44 #include "src/inspector/v8-stack-trace-impl.h" 45 #include "src/inspector/v8-value-copier.h" 46 47 #include "include/v8-inspector.h" 48 49 namespace v8_inspector { 50 51 using protocol::Array; 52 using protocol::Runtime::PropertyDescriptor; 53 using protocol::Runtime::InternalPropertyDescriptor; 54 using protocol::Runtime::RemoteObject; 55 using protocol::Maybe; 56 57 std::unique_ptr<InjectedScript> InjectedScript::create( 58 InspectedContext* inspectedContext) { 59 v8::Isolate* isolate = inspectedContext->isolate(); 60 v8::HandleScope handles(isolate); 61 v8::Local<v8::Context> context = inspectedContext->context(); 62 v8::Context::Scope scope(context); 63 64 std::unique_ptr<InjectedScriptNative> injectedScriptNative( 65 new InjectedScriptNative(isolate)); 66 v8::Local<v8::Object> scriptHostWrapper = 67 V8InjectedScriptHost::create(context, inspectedContext->inspector()); 68 injectedScriptNative->setOnInjectedScriptHost(scriptHostWrapper); 69 70 // Inject javascript into the context. The compiled script is supposed to 71 // evaluate into 72 // a single anonymous function(it's anonymous to avoid cluttering the global 73 // object with 74 // inspector's stuff) the function is called a few lines below with 75 // InjectedScriptHost wrapper, 76 // injected script id and explicit reference to the inspected global object. 77 // The function is expected 78 // to create and configure InjectedScript instance that is going to be used by 79 // the inspector. 80 String16 injectedScriptSource( 81 reinterpret_cast<const char*>(InjectedScriptSource_js), 82 sizeof(InjectedScriptSource_js)); 83 v8::Local<v8::Value> value; 84 if (!inspectedContext->inspector() 85 ->compileAndRunInternalScript( 86 context, toV8String(isolate, injectedScriptSource)) 87 .ToLocal(&value)) 88 return nullptr; 89 DCHECK(value->IsFunction()); 90 v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(value); 91 v8::Local<v8::Object> windowGlobal = context->Global(); 92 v8::Local<v8::Value> info[] = { 93 scriptHostWrapper, windowGlobal, 94 v8::Number::New(isolate, inspectedContext->contextId())}; 95 v8::MicrotasksScope microtasksScope(isolate, 96 v8::MicrotasksScope::kDoNotRunMicrotasks); 97 98 int contextGroupId = inspectedContext->contextGroupId(); 99 int contextId = inspectedContext->contextId(); 100 V8InspectorImpl* inspector = inspectedContext->inspector(); 101 v8::Local<v8::Value> injectedScriptValue; 102 if (!function->Call(context, windowGlobal, arraysize(info), info) 103 .ToLocal(&injectedScriptValue)) 104 return nullptr; 105 if (inspector->getContext(contextGroupId, contextId) != inspectedContext) 106 return nullptr; 107 if (!injectedScriptValue->IsObject()) return nullptr; 108 return wrapUnique(new InjectedScript(inspectedContext, 109 injectedScriptValue.As<v8::Object>(), 110 std::move(injectedScriptNative))); 111 } 112 113 InjectedScript::InjectedScript( 114 InspectedContext* context, v8::Local<v8::Object> object, 115 std::unique_ptr<InjectedScriptNative> injectedScriptNative) 116 : m_context(context), 117 m_value(context->isolate(), object), 118 m_native(std::move(injectedScriptNative)) {} 119 120 InjectedScript::~InjectedScript() {} 121 122 Response InjectedScript::getProperties( 123 v8::Local<v8::Object> object, const String16& groupName, bool ownProperties, 124 bool accessorPropertiesOnly, bool generatePreview, 125 std::unique_ptr<Array<PropertyDescriptor>>* properties, 126 Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) { 127 v8::HandleScope handles(m_context->isolate()); 128 v8::Local<v8::Context> context = m_context->context(); 129 V8FunctionCall function(m_context->inspector(), m_context->context(), 130 v8Value(), "getProperties"); 131 function.appendArgument(object); 132 function.appendArgument(groupName); 133 function.appendArgument(ownProperties); 134 function.appendArgument(accessorPropertiesOnly); 135 function.appendArgument(generatePreview); 136 137 v8::TryCatch tryCatch(m_context->isolate()); 138 v8::Local<v8::Value> resultValue = function.callWithoutExceptionHandling(); 139 if (tryCatch.HasCaught()) { 140 Response response = createExceptionDetails( 141 tryCatch, groupName, generatePreview, exceptionDetails); 142 if (!response.isSuccess()) return response; 143 // FIXME: make properties optional 144 *properties = Array<PropertyDescriptor>::create(); 145 return Response::OK(); 146 } 147 if (resultValue.IsEmpty()) return Response::InternalError(); 148 std::unique_ptr<protocol::Value> protocolValue; 149 Response response = toProtocolValue(context, resultValue, &protocolValue); 150 if (!response.isSuccess()) return response; 151 protocol::ErrorSupport errors; 152 std::unique_ptr<Array<PropertyDescriptor>> result = 153 Array<PropertyDescriptor>::parse(protocolValue.get(), &errors); 154 if (errors.hasErrors()) return Response::Error(errors.errors()); 155 *properties = std::move(result); 156 return Response::OK(); 157 } 158 159 void InjectedScript::releaseObject(const String16& objectId) { 160 std::unique_ptr<protocol::Value> parsedObjectId = 161 protocol::parseJSON(objectId); 162 if (!parsedObjectId) return; 163 protocol::DictionaryValue* object = 164 protocol::DictionaryValue::cast(parsedObjectId.get()); 165 if (!object) return; 166 int boundId = 0; 167 if (!object->getInteger("id", &boundId)) return; 168 m_native->unbind(boundId); 169 } 170 171 Response InjectedScript::wrapObject( 172 v8::Local<v8::Value> value, const String16& groupName, bool forceValueType, 173 bool generatePreview, 174 std::unique_ptr<protocol::Runtime::RemoteObject>* result) const { 175 v8::HandleScope handles(m_context->isolate()); 176 v8::Local<v8::Value> wrappedObject; 177 v8::Local<v8::Context> context = m_context->context(); 178 Response response = wrapValue(value, groupName, forceValueType, 179 generatePreview, &wrappedObject); 180 if (!response.isSuccess()) return response; 181 protocol::ErrorSupport errors; 182 std::unique_ptr<protocol::Value> protocolValue; 183 response = toProtocolValue(context, wrappedObject, &protocolValue); 184 if (!response.isSuccess()) return response; 185 186 *result = 187 protocol::Runtime::RemoteObject::parse(protocolValue.get(), &errors); 188 if (!result->get()) return Response::Error(errors.errors()); 189 return Response::OK(); 190 } 191 192 Response InjectedScript::wrapObjectProperty(v8::Local<v8::Object> object, 193 v8::Local<v8::Name> key, 194 const String16& groupName, 195 bool forceValueType, 196 bool generatePreview) const { 197 v8::Local<v8::Value> property; 198 v8::Local<v8::Context> context = m_context->context(); 199 if (!object->Get(context, key).ToLocal(&property)) 200 return Response::InternalError(); 201 v8::Local<v8::Value> wrappedProperty; 202 Response response = wrapValue(property, groupName, forceValueType, 203 generatePreview, &wrappedProperty); 204 if (!response.isSuccess()) return response; 205 v8::Maybe<bool> success = 206 createDataProperty(context, object, key, wrappedProperty); 207 if (success.IsNothing() || !success.FromJust()) 208 return Response::InternalError(); 209 return Response::OK(); 210 } 211 212 Response InjectedScript::wrapPropertyInArray(v8::Local<v8::Array> array, 213 v8::Local<v8::String> property, 214 const String16& groupName, 215 bool forceValueType, 216 bool generatePreview) const { 217 V8FunctionCall function(m_context->inspector(), m_context->context(), 218 v8Value(), "wrapPropertyInArray"); 219 function.appendArgument(array); 220 function.appendArgument(property); 221 function.appendArgument(groupName); 222 function.appendArgument(forceValueType); 223 function.appendArgument(generatePreview); 224 bool hadException = false; 225 function.call(hadException); 226 return hadException ? Response::InternalError() : Response::OK(); 227 } 228 229 Response InjectedScript::wrapValue(v8::Local<v8::Value> value, 230 const String16& groupName, 231 bool forceValueType, bool generatePreview, 232 v8::Local<v8::Value>* result) const { 233 V8FunctionCall function(m_context->inspector(), m_context->context(), 234 v8Value(), "wrapObject"); 235 function.appendArgument(value); 236 function.appendArgument(groupName); 237 function.appendArgument(forceValueType); 238 function.appendArgument(generatePreview); 239 bool hadException = false; 240 *result = function.call(hadException); 241 if (hadException || result->IsEmpty()) return Response::InternalError(); 242 return Response::OK(); 243 } 244 245 std::unique_ptr<protocol::Runtime::RemoteObject> InjectedScript::wrapTable( 246 v8::Local<v8::Value> table, v8::Local<v8::Value> columns) const { 247 v8::HandleScope handles(m_context->isolate()); 248 v8::Local<v8::Context> context = m_context->context(); 249 V8FunctionCall function(m_context->inspector(), context, v8Value(), 250 "wrapTable"); 251 function.appendArgument(table); 252 if (columns.IsEmpty()) 253 function.appendArgument(false); 254 else 255 function.appendArgument(columns); 256 bool hadException = false; 257 v8::Local<v8::Value> r = function.call(hadException); 258 if (hadException || r.IsEmpty()) return nullptr; 259 std::unique_ptr<protocol::Value> protocolValue; 260 Response response = toProtocolValue(context, r, &protocolValue); 261 if (!response.isSuccess()) return nullptr; 262 protocol::ErrorSupport errors; 263 return protocol::Runtime::RemoteObject::parse(protocolValue.get(), &errors); 264 } 265 266 Response InjectedScript::findObject(const RemoteObjectId& objectId, 267 v8::Local<v8::Value>* outObject) const { 268 *outObject = m_native->objectForId(objectId.id()); 269 if (outObject->IsEmpty()) 270 return Response::Error("Could not find object with given id"); 271 return Response::OK(); 272 } 273 274 String16 InjectedScript::objectGroupName(const RemoteObjectId& objectId) const { 275 return m_native->groupName(objectId.id()); 276 } 277 278 void InjectedScript::releaseObjectGroup(const String16& objectGroup) { 279 m_native->releaseObjectGroup(objectGroup); 280 if (objectGroup == "console") m_lastEvaluationResult.Reset(); 281 } 282 283 void InjectedScript::setCustomObjectFormatterEnabled(bool enabled) { 284 v8::HandleScope handles(m_context->isolate()); 285 V8FunctionCall function(m_context->inspector(), m_context->context(), 286 v8Value(), "setCustomObjectFormatterEnabled"); 287 function.appendArgument(enabled); 288 bool hadException = false; 289 function.call(hadException); 290 DCHECK(!hadException); 291 } 292 293 v8::Local<v8::Value> InjectedScript::v8Value() const { 294 return m_value.Get(m_context->isolate()); 295 } 296 297 v8::Local<v8::Value> InjectedScript::lastEvaluationResult() const { 298 if (m_lastEvaluationResult.IsEmpty()) 299 return v8::Undefined(m_context->isolate()); 300 return m_lastEvaluationResult.Get(m_context->isolate()); 301 } 302 303 Response InjectedScript::resolveCallArgument( 304 protocol::Runtime::CallArgument* callArgument, 305 v8::Local<v8::Value>* result) { 306 if (callArgument->hasObjectId()) { 307 std::unique_ptr<RemoteObjectId> remoteObjectId; 308 Response response = 309 RemoteObjectId::parse(callArgument->getObjectId(""), &remoteObjectId); 310 if (!response.isSuccess()) return response; 311 if (remoteObjectId->contextId() != m_context->contextId()) 312 return Response::Error( 313 "Argument should belong to the same JavaScript world as target " 314 "object"); 315 return findObject(*remoteObjectId, result); 316 } 317 if (callArgument->hasValue() || callArgument->hasUnserializableValue()) { 318 String16 value = 319 callArgument->hasValue() 320 ? callArgument->getValue(nullptr)->toJSONString() 321 : "Number(\"" + callArgument->getUnserializableValue("") + "\")"; 322 if (!m_context->inspector() 323 ->compileAndRunInternalScript( 324 m_context->context(), toV8String(m_context->isolate(), value)) 325 .ToLocal(result)) { 326 return Response::Error("Couldn't parse value object in call argument"); 327 } 328 return Response::OK(); 329 } 330 *result = v8::Undefined(m_context->isolate()); 331 return Response::OK(); 332 } 333 334 Response InjectedScript::createExceptionDetails( 335 const v8::TryCatch& tryCatch, const String16& objectGroup, 336 bool generatePreview, Maybe<protocol::Runtime::ExceptionDetails>* result) { 337 if (!tryCatch.HasCaught()) return Response::InternalError(); 338 v8::Local<v8::Message> message = tryCatch.Message(); 339 v8::Local<v8::Value> exception = tryCatch.Exception(); 340 String16 messageText = 341 message.IsEmpty() ? String16() : toProtocolString(message->Get()); 342 std::unique_ptr<protocol::Runtime::ExceptionDetails> exceptionDetails = 343 protocol::Runtime::ExceptionDetails::create() 344 .setExceptionId(m_context->inspector()->nextExceptionId()) 345 .setText(exception.IsEmpty() ? messageText : String16("Uncaught")) 346 .setLineNumber( 347 message.IsEmpty() 348 ? 0 349 : message->GetLineNumber(m_context->context()).FromMaybe(1) - 350 1) 351 .setColumnNumber( 352 message.IsEmpty() 353 ? 0 354 : message->GetStartColumn(m_context->context()).FromMaybe(0)) 355 .build(); 356 if (!message.IsEmpty()) { 357 exceptionDetails->setScriptId(String16::fromInteger( 358 static_cast<int>(message->GetScriptOrigin().ScriptID()->Value()))); 359 v8::Local<v8::StackTrace> stackTrace = message->GetStackTrace(); 360 if (!stackTrace.IsEmpty() && stackTrace->GetFrameCount() > 0) 361 exceptionDetails->setStackTrace(m_context->inspector() 362 ->debugger() 363 ->createStackTrace(stackTrace) 364 ->buildInspectorObjectImpl()); 365 } 366 if (!exception.IsEmpty()) { 367 std::unique_ptr<protocol::Runtime::RemoteObject> wrapped; 368 Response response = 369 wrapObject(exception, objectGroup, false /* forceValueType */, 370 generatePreview && !exception->IsNativeError(), &wrapped); 371 if (!response.isSuccess()) return response; 372 exceptionDetails->setException(std::move(wrapped)); 373 } 374 *result = std::move(exceptionDetails); 375 return Response::OK(); 376 } 377 378 Response InjectedScript::wrapEvaluateResult( 379 v8::MaybeLocal<v8::Value> maybeResultValue, const v8::TryCatch& tryCatch, 380 const String16& objectGroup, bool returnByValue, bool generatePreview, 381 std::unique_ptr<protocol::Runtime::RemoteObject>* result, 382 Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) { 383 v8::Local<v8::Value> resultValue; 384 if (!tryCatch.HasCaught()) { 385 if (!maybeResultValue.ToLocal(&resultValue)) 386 return Response::InternalError(); 387 Response response = wrapObject(resultValue, objectGroup, returnByValue, 388 generatePreview, result); 389 if (!response.isSuccess()) return response; 390 if (objectGroup == "console") 391 m_lastEvaluationResult.Reset(m_context->isolate(), resultValue); 392 } else { 393 v8::Local<v8::Value> exception = tryCatch.Exception(); 394 Response response = 395 wrapObject(exception, objectGroup, false, 396 generatePreview && !exception->IsNativeError(), result); 397 if (!response.isSuccess()) return response; 398 // We send exception in result for compatibility reasons, even though it's 399 // accessible through exceptionDetails.exception. 400 response = createExceptionDetails(tryCatch, objectGroup, generatePreview, 401 exceptionDetails); 402 if (!response.isSuccess()) return response; 403 } 404 return Response::OK(); 405 } 406 407 v8::Local<v8::Object> InjectedScript::commandLineAPI() { 408 if (m_commandLineAPI.IsEmpty()) 409 m_commandLineAPI.Reset(m_context->isolate(), 410 V8Console::createCommandLineAPI(m_context)); 411 return m_commandLineAPI.Get(m_context->isolate()); 412 } 413 414 InjectedScript::Scope::Scope(V8InspectorImpl* inspector, int contextGroupId) 415 : m_inspector(inspector), 416 m_contextGroupId(contextGroupId), 417 m_injectedScript(nullptr), 418 m_handleScope(inspector->isolate()), 419 m_tryCatch(inspector->isolate()), 420 m_ignoreExceptionsAndMuteConsole(false), 421 m_previousPauseOnExceptionsState(v8::DebugInterface::NoBreakOnException), 422 m_userGesture(false) {} 423 424 Response InjectedScript::Scope::initialize() { 425 cleanup(); 426 // TODO(dgozman): what if we reattach to the same context group during 427 // evaluate? Introduce a session id? 428 V8InspectorSessionImpl* session = 429 m_inspector->sessionForContextGroup(m_contextGroupId); 430 if (!session) return Response::InternalError(); 431 Response response = findInjectedScript(session); 432 if (!response.isSuccess()) return response; 433 m_context = m_injectedScript->context()->context(); 434 m_context->Enter(); 435 return Response::OK(); 436 } 437 438 void InjectedScript::Scope::installCommandLineAPI() { 439 DCHECK(m_injectedScript && !m_context.IsEmpty() && 440 !m_commandLineAPIScope.get()); 441 m_commandLineAPIScope.reset(new V8Console::CommandLineAPIScope( 442 m_context, m_injectedScript->commandLineAPI(), m_context->Global())); 443 } 444 445 void InjectedScript::Scope::ignoreExceptionsAndMuteConsole() { 446 DCHECK(!m_ignoreExceptionsAndMuteConsole); 447 m_ignoreExceptionsAndMuteConsole = true; 448 m_inspector->client()->muteMetrics(m_contextGroupId); 449 m_inspector->muteExceptions(m_contextGroupId); 450 m_previousPauseOnExceptionsState = 451 setPauseOnExceptionsState(v8::DebugInterface::NoBreakOnException); 452 } 453 454 v8::DebugInterface::ExceptionBreakState 455 InjectedScript::Scope::setPauseOnExceptionsState( 456 v8::DebugInterface::ExceptionBreakState newState) { 457 if (!m_inspector->debugger()->enabled()) return newState; 458 v8::DebugInterface::ExceptionBreakState presentState = 459 m_inspector->debugger()->getPauseOnExceptionsState(); 460 if (presentState != newState) 461 m_inspector->debugger()->setPauseOnExceptionsState(newState); 462 return presentState; 463 } 464 465 void InjectedScript::Scope::pretendUserGesture() { 466 DCHECK(!m_userGesture); 467 m_userGesture = true; 468 m_inspector->client()->beginUserGesture(); 469 } 470 471 void InjectedScript::Scope::cleanup() { 472 m_commandLineAPIScope.reset(); 473 if (!m_context.IsEmpty()) { 474 m_context->Exit(); 475 m_context.Clear(); 476 } 477 } 478 479 InjectedScript::Scope::~Scope() { 480 if (m_ignoreExceptionsAndMuteConsole) { 481 setPauseOnExceptionsState(m_previousPauseOnExceptionsState); 482 m_inspector->client()->unmuteMetrics(m_contextGroupId); 483 m_inspector->unmuteExceptions(m_contextGroupId); 484 } 485 if (m_userGesture) m_inspector->client()->endUserGesture(); 486 cleanup(); 487 } 488 489 InjectedScript::ContextScope::ContextScope(V8InspectorImpl* inspector, 490 int contextGroupId, 491 int executionContextId) 492 : InjectedScript::Scope(inspector, contextGroupId), 493 m_executionContextId(executionContextId) {} 494 495 InjectedScript::ContextScope::~ContextScope() {} 496 497 Response InjectedScript::ContextScope::findInjectedScript( 498 V8InspectorSessionImpl* session) { 499 return session->findInjectedScript(m_executionContextId, m_injectedScript); 500 } 501 502 InjectedScript::ObjectScope::ObjectScope(V8InspectorImpl* inspector, 503 int contextGroupId, 504 const String16& remoteObjectId) 505 : InjectedScript::Scope(inspector, contextGroupId), 506 m_remoteObjectId(remoteObjectId) {} 507 508 InjectedScript::ObjectScope::~ObjectScope() {} 509 510 Response InjectedScript::ObjectScope::findInjectedScript( 511 V8InspectorSessionImpl* session) { 512 std::unique_ptr<RemoteObjectId> remoteId; 513 Response response = RemoteObjectId::parse(m_remoteObjectId, &remoteId); 514 if (!response.isSuccess()) return response; 515 InjectedScript* injectedScript = nullptr; 516 response = session->findInjectedScript(remoteId.get(), injectedScript); 517 if (!response.isSuccess()) return response; 518 m_objectGroupName = injectedScript->objectGroupName(*remoteId); 519 response = injectedScript->findObject(*remoteId, &m_object); 520 if (!response.isSuccess()) return response; 521 m_injectedScript = injectedScript; 522 return Response::OK(); 523 } 524 525 InjectedScript::CallFrameScope::CallFrameScope(V8InspectorImpl* inspector, 526 int contextGroupId, 527 const String16& remoteObjectId) 528 : InjectedScript::Scope(inspector, contextGroupId), 529 m_remoteCallFrameId(remoteObjectId) {} 530 531 InjectedScript::CallFrameScope::~CallFrameScope() {} 532 533 Response InjectedScript::CallFrameScope::findInjectedScript( 534 V8InspectorSessionImpl* session) { 535 std::unique_ptr<RemoteCallFrameId> remoteId; 536 Response response = RemoteCallFrameId::parse(m_remoteCallFrameId, &remoteId); 537 if (!response.isSuccess()) return response; 538 m_frameOrdinal = static_cast<size_t>(remoteId->frameOrdinal()); 539 return session->findInjectedScript(remoteId.get(), m_injectedScript); 540 } 541 542 } // namespace v8_inspector 543