1 /* 2 * Copyright (C) 2007-2011 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 "config.h" 32 #include "bindings/core/v8/V8InjectedScriptHost.h" 33 34 #include "bindings/core/v8/BindingSecurity.h" 35 #include "bindings/core/v8/ExceptionState.h" 36 #include "bindings/core/v8/ScriptDebugServer.h" 37 #include "bindings/core/v8/ScriptValue.h" 38 #include "bindings/core/v8/V8AbstractEventListener.h" 39 #include "bindings/core/v8/V8Binding.h" 40 #include "bindings/core/v8/V8DOMTokenList.h" 41 #include "bindings/core/v8/V8EventTarget.h" 42 #include "bindings/core/v8/V8HTMLAllCollection.h" 43 #include "bindings/core/v8/V8HTMLCollection.h" 44 #include "bindings/core/v8/V8Node.h" 45 #include "bindings/core/v8/V8NodeList.h" 46 #include "bindings/core/v8/V8ScriptRunner.h" 47 #include "bindings/core/v8/V8Storage.h" 48 #include "bindings/core/v8/custom/V8Float32ArrayCustom.h" 49 #include "bindings/core/v8/custom/V8Float64ArrayCustom.h" 50 #include "bindings/core/v8/custom/V8Int16ArrayCustom.h" 51 #include "bindings/core/v8/custom/V8Int32ArrayCustom.h" 52 #include "bindings/core/v8/custom/V8Int8ArrayCustom.h" 53 #include "bindings/core/v8/custom/V8Uint16ArrayCustom.h" 54 #include "bindings/core/v8/custom/V8Uint32ArrayCustom.h" 55 #include "bindings/core/v8/custom/V8Uint8ArrayCustom.h" 56 #include "bindings/core/v8/custom/V8Uint8ClampedArrayCustom.h" 57 #include "core/events/EventTarget.h" 58 #include "core/frame/LocalDOMWindow.h" 59 #include "core/inspector/InjectedScript.h" 60 #include "core/inspector/InjectedScriptHost.h" 61 #include "core/inspector/InspectorDOMAgent.h" 62 #include "core/inspector/JavaScriptCallFrame.h" 63 #include "platform/JSONValues.h" 64 65 namespace blink { 66 67 Node* InjectedScriptHost::scriptValueAsNode(ScriptState* scriptState, ScriptValue value) 68 { 69 ScriptState::Scope scope(scriptState); 70 if (!value.isObject() || value.isNull()) 71 return 0; 72 return V8Node::toImpl(v8::Handle<v8::Object>::Cast(value.v8Value())); 73 } 74 75 ScriptValue InjectedScriptHost::nodeAsScriptValue(ScriptState* scriptState, Node* node) 76 { 77 ScriptState::Scope scope(scriptState); 78 v8::Isolate* isolate = scriptState->isolate(); 79 ExceptionState exceptionState(ExceptionState::ExecutionContext, "nodeAsScriptValue", "InjectedScriptHost", scriptState->context()->Global(), isolate); 80 if (!BindingSecurity::shouldAllowAccessToNode(isolate, node, exceptionState)) 81 return ScriptValue(scriptState, v8::Null(isolate)); 82 return ScriptValue(scriptState, toV8(node, scriptState->context()->Global(), isolate)); 83 } 84 85 void V8InjectedScriptHost::inspectedObjectMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 86 { 87 if (info.Length() < 1) 88 return; 89 90 if (!info[0]->IsInt32()) { 91 V8ThrowException::throwTypeError("argument has to be an integer", info.GetIsolate()); 92 return; 93 } 94 95 InjectedScriptHost* host = V8InjectedScriptHost::toImpl(info.Holder()); 96 InjectedScriptHost::InspectableObject* object = host->inspectedObject(info[0]->ToInt32()->Value()); 97 v8SetReturnValue(info, object->get(ScriptState::current(info.GetIsolate())).v8Value()); 98 } 99 100 static v8::Handle<v8::String> functionDisplayName(v8::Handle<v8::Function> function) 101 { 102 v8::Handle<v8::Value> value = function->GetDisplayName(); 103 if (value->IsString() && v8::Handle<v8::String>::Cast(value)->Length()) 104 return v8::Handle<v8::String>::Cast(value); 105 106 value = function->GetName(); 107 if (value->IsString() && v8::Handle<v8::String>::Cast(value)->Length()) 108 return v8::Handle<v8::String>::Cast(value); 109 110 value = function->GetInferredName(); 111 if (value->IsString() && v8::Handle<v8::String>::Cast(value)->Length()) 112 return v8::Handle<v8::String>::Cast(value); 113 114 return v8::Handle<v8::String>(); 115 } 116 117 void V8InjectedScriptHost::internalConstructorNameMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 118 { 119 if (info.Length() < 1 || !info[0]->IsObject()) 120 return; 121 122 v8::Local<v8::Object> object = info[0]->ToObject(); 123 v8::Local<v8::String> result = object->GetConstructorName(); 124 125 if (!result.IsEmpty() && toCoreStringWithUndefinedOrNullCheck(result) == "Object") { 126 v8::Local<v8::String> constructorSymbol = v8AtomicString(info.GetIsolate(), "constructor"); 127 if (object->HasRealNamedProperty(constructorSymbol) && !object->HasRealNamedCallbackProperty(constructorSymbol)) { 128 v8::TryCatch tryCatch; 129 v8::Local<v8::Value> constructor = object->GetRealNamedProperty(constructorSymbol); 130 if (!constructor.IsEmpty() && constructor->IsFunction()) { 131 v8::Local<v8::String> constructorName = functionDisplayName(v8::Handle<v8::Function>::Cast(constructor)); 132 if (!constructorName.IsEmpty() && !tryCatch.HasCaught()) 133 result = constructorName; 134 } 135 } 136 } 137 138 v8SetReturnValue(info, result); 139 } 140 141 void V8InjectedScriptHost::isHTMLAllCollectionMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 142 { 143 if (info.Length() < 1) 144 return; 145 146 if (!info[0]->IsObject()) { 147 v8SetReturnValue(info, false); 148 return; 149 } 150 151 v8SetReturnValue(info, V8HTMLAllCollection::hasInstance(info[0], info.GetIsolate())); 152 } 153 154 void V8InjectedScriptHost::subtypeMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 155 { 156 if (info.Length() < 1) 157 return; 158 v8::Isolate* isolate = info.GetIsolate(); 159 160 v8::Handle<v8::Value> value = info[0]; 161 if (value->IsArray() || value->IsTypedArray() || value->IsArgumentsObject()) { 162 v8SetReturnValue(info, v8AtomicString(isolate, "array")); 163 return; 164 } 165 if (value->IsDate()) { 166 v8SetReturnValue(info, v8AtomicString(isolate, "date")); 167 return; 168 } 169 if (value->IsRegExp()) { 170 v8SetReturnValue(info, v8AtomicString(isolate, "regexp")); 171 return; 172 } 173 if (value->IsMap() || value->IsWeakMap()) { 174 v8SetReturnValue(info, v8AtomicString(isolate, "map")); 175 return; 176 } 177 if (value->IsSet() || value->IsWeakSet()) { 178 v8SetReturnValue(info, v8AtomicString(isolate, "set")); 179 return; 180 } 181 if (V8Node::hasInstance(value, isolate)) { 182 v8SetReturnValue(info, v8AtomicString(isolate, "node")); 183 return; 184 } 185 if (V8NodeList::hasInstance(value, isolate) 186 || V8DOMTokenList::hasInstance(value, isolate) 187 || V8HTMLCollection::hasInstance(value, isolate) 188 || V8HTMLAllCollection::hasInstance(value, isolate)) { 189 v8SetReturnValue(info, v8AtomicString(isolate, "array")); 190 return; 191 } 192 } 193 194 void V8InjectedScriptHost::functionDetailsMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 195 { 196 if (info.Length() < 1 || !info[0]->IsFunction()) 197 return; 198 199 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(info[0]); 200 int lineNumber = function->GetScriptLineNumber(); 201 int columnNumber = function->GetScriptColumnNumber(); 202 203 v8::Isolate* isolate = info.GetIsolate(); 204 v8::Local<v8::Object> location = v8::Object::New(isolate); 205 location->Set(v8AtomicString(isolate, "lineNumber"), v8::Integer::New(isolate, lineNumber)); 206 location->Set(v8AtomicString(isolate, "columnNumber"), v8::Integer::New(isolate, columnNumber)); 207 location->Set(v8AtomicString(isolate, "scriptId"), v8::Integer::New(isolate, function->ScriptId())->ToString()); 208 209 v8::Local<v8::Object> result = v8::Object::New(isolate); 210 result->Set(v8AtomicString(isolate, "location"), location); 211 212 v8::Handle<v8::String> name = functionDisplayName(function); 213 result->Set(v8AtomicString(isolate, "functionName"), name.IsEmpty() ? v8AtomicString(isolate, "") : name); 214 215 InjectedScriptHost* host = V8InjectedScriptHost::toImpl(info.Holder()); 216 ScriptDebugServer& debugServer = host->scriptDebugServer(); 217 v8::Handle<v8::Value> scopes = debugServer.functionScopes(function); 218 if (!scopes.IsEmpty() && scopes->IsArray()) 219 result->Set(v8AtomicString(isolate, "rawScopes"), scopes); 220 221 v8SetReturnValue(info, result); 222 } 223 224 void V8InjectedScriptHost::collectionEntriesMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 225 { 226 if (info.Length() < 1 || !info[0]->IsObject()) 227 return; 228 229 v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(info[0]); 230 231 InjectedScriptHost* host = V8InjectedScriptHost::toImpl(info.Holder()); 232 ScriptDebugServer& debugServer = host->scriptDebugServer(); 233 v8SetReturnValue(info, debugServer.collectionEntries(object)); 234 } 235 236 void V8InjectedScriptHost::getInternalPropertiesMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 237 { 238 if (info.Length() < 1 || !info[0]->IsObject()) 239 return; 240 241 v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(info[0]); 242 243 InjectedScriptHost* host = V8InjectedScriptHost::toImpl(info.Holder()); 244 ScriptDebugServer& debugServer = host->scriptDebugServer(); 245 v8SetReturnValue(info, debugServer.getInternalProperties(object)); 246 } 247 248 static v8::Handle<v8::Array> getJSListenerFunctions(ExecutionContext* executionContext, const EventListenerInfo& listenerInfo, v8::Isolate* isolate) 249 { 250 v8::Local<v8::Array> result = v8::Array::New(isolate); 251 size_t handlersCount = listenerInfo.eventListenerVector.size(); 252 for (size_t i = 0, outputIndex = 0; i < handlersCount; ++i) { 253 RefPtr<EventListener> listener = listenerInfo.eventListenerVector[i].listener; 254 if (listener->type() != EventListener::JSEventListenerType) { 255 ASSERT_NOT_REACHED(); 256 continue; 257 } 258 V8AbstractEventListener* v8Listener = static_cast<V8AbstractEventListener*>(listener.get()); 259 v8::Local<v8::Context> context = toV8Context(executionContext, v8Listener->world()); 260 // Hide listeners from other contexts. 261 if (context != isolate->GetCurrentContext()) 262 continue; 263 v8::Local<v8::Object> function; 264 { 265 // getListenerObject() may cause JS in the event attribute to get compiled, potentially unsuccessfully. 266 v8::TryCatch block; 267 function = v8Listener->getListenerObject(executionContext); 268 if (block.HasCaught()) 269 continue; 270 } 271 ASSERT(!function.IsEmpty()); 272 v8::Local<v8::Object> listenerEntry = v8::Object::New(isolate); 273 listenerEntry->Set(v8AtomicString(isolate, "listener"), function); 274 listenerEntry->Set(v8AtomicString(isolate, "useCapture"), v8::Boolean::New(isolate, listenerInfo.eventListenerVector[i].useCapture)); 275 result->Set(v8::Number::New(isolate, outputIndex++), listenerEntry); 276 } 277 return result; 278 } 279 280 void V8InjectedScriptHost::getEventListenersMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 281 { 282 if (info.Length() < 1) 283 return; 284 285 286 v8::Local<v8::Value> value = info[0]; 287 EventTarget* target = V8EventTarget::toImplWithTypeCheck(info.GetIsolate(), value); 288 289 // We need to handle a LocalDOMWindow specially, because a LocalDOMWindow wrapper exists on a prototype chain. 290 if (!target) 291 target = toDOMWindow(value, info.GetIsolate()); 292 293 if (!target || !target->executionContext()) 294 return; 295 296 InjectedScriptHost* host = V8InjectedScriptHost::toImpl(info.Holder()); 297 Vector<EventListenerInfo> listenersArray; 298 host->getEventListenersImpl(target, listenersArray); 299 300 v8::Local<v8::Object> result = v8::Object::New(info.GetIsolate()); 301 for (size_t i = 0; i < listenersArray.size(); ++i) { 302 v8::Handle<v8::Array> listeners = getJSListenerFunctions(target->executionContext(), listenersArray[i], info.GetIsolate()); 303 if (!listeners->Length()) 304 continue; 305 AtomicString eventType = listenersArray[i].eventType; 306 result->Set(v8String(info.GetIsolate(), eventType), listeners); 307 } 308 309 v8SetReturnValue(info, result); 310 } 311 312 void V8InjectedScriptHost::inspectMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 313 { 314 if (info.Length() < 2) 315 return; 316 317 InjectedScriptHost* host = V8InjectedScriptHost::toImpl(info.Holder()); 318 ScriptState* scriptState = ScriptState::current(info.GetIsolate()); 319 ScriptValue object(scriptState, info[0]); 320 ScriptValue hints(scriptState, info[1]); 321 host->inspectImpl(object.toJSONValue(scriptState), hints.toJSONValue(scriptState)); 322 } 323 324 void V8InjectedScriptHost::evalMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 325 { 326 v8::Isolate* isolate = info.GetIsolate(); 327 if (info.Length() < 1) { 328 isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "One argument expected."))); 329 return; 330 } 331 332 v8::Handle<v8::String> expression = info[0]->ToString(); 333 if (expression.IsEmpty()) { 334 isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "The argument must be a string."))); 335 return; 336 } 337 338 ASSERT(isolate->InContext()); 339 v8::TryCatch tryCatch; 340 v8::Handle<v8::Value> result = V8ScriptRunner::compileAndRunInternalScript(expression, info.GetIsolate()); 341 if (tryCatch.HasCaught()) { 342 v8SetReturnValue(info, tryCatch.ReThrow()); 343 return; 344 } 345 v8SetReturnValue(info, result); 346 } 347 348 void V8InjectedScriptHost::evaluateWithExceptionDetailsMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 349 { 350 v8::Isolate* isolate = info.GetIsolate(); 351 if (info.Length() < 1) { 352 isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "One argument expected."))); 353 return; 354 } 355 356 v8::Handle<v8::String> expression = info[0]->ToString(); 357 if (expression.IsEmpty()) { 358 isolate->ThrowException(v8::Exception::Error(v8::String::NewFromUtf8(isolate, "The argument must be a string."))); 359 return; 360 } 361 362 ASSERT(isolate->InContext()); 363 v8::TryCatch tryCatch; 364 v8::Handle<v8::Value> result = V8ScriptRunner::compileAndRunInternalScript(expression, info.GetIsolate()); 365 366 v8::Local<v8::Object> wrappedResult = v8::Object::New(isolate); 367 if (tryCatch.HasCaught()) { 368 wrappedResult->Set(v8::String::NewFromUtf8(isolate, "result"), tryCatch.Exception()); 369 wrappedResult->Set(v8::String::NewFromUtf8(isolate, "exceptionDetails"), JavaScriptCallFrame::createExceptionDetails(tryCatch.Message(), isolate)); 370 } else { 371 wrappedResult->Set(v8::String::NewFromUtf8(isolate, "result"), result); 372 wrappedResult->Set(v8::String::NewFromUtf8(isolate, "exceptionDetails"), v8::Undefined(isolate)); 373 } 374 v8SetReturnValue(info, wrappedResult); 375 } 376 377 void V8InjectedScriptHost::setFunctionVariableValueMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 378 { 379 if (info.Length() < 4 || !info[0]->IsFunction() || !info[1]->IsInt32() || !info[2]->IsString()) 380 return; 381 382 v8::Handle<v8::Value> functionValue = info[0]; 383 int scopeIndex = info[1]->Int32Value(); 384 String variableName = toCoreStringWithUndefinedOrNullCheck(info[2]); 385 v8::Handle<v8::Value> newValue = info[3]; 386 387 InjectedScriptHost* host = V8InjectedScriptHost::toImpl(info.Holder()); 388 ScriptDebugServer& debugServer = host->scriptDebugServer(); 389 v8SetReturnValue(info, debugServer.setFunctionVariableValue(functionValue, scopeIndex, variableName, newValue)); 390 } 391 392 static bool getFunctionLocation(const v8::FunctionCallbackInfo<v8::Value>& info, String* scriptId, int* lineNumber, int* columnNumber) 393 { 394 if (info.Length() < 1 || !info[0]->IsFunction()) 395 return false; 396 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(info[0]); 397 *lineNumber = function->GetScriptLineNumber(); 398 *columnNumber = function->GetScriptColumnNumber(); 399 if (*lineNumber == v8::Function::kLineOffsetNotFound || *columnNumber == v8::Function::kLineOffsetNotFound) 400 return false; 401 *scriptId = String::number(function->ScriptId()); 402 return true; 403 } 404 405 void V8InjectedScriptHost::debugFunctionMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 406 { 407 String scriptId; 408 int lineNumber; 409 int columnNumber; 410 if (!getFunctionLocation(info, &scriptId, &lineNumber, &columnNumber)) 411 return; 412 413 InjectedScriptHost* host = V8InjectedScriptHost::toImpl(info.Holder()); 414 host->debugFunction(scriptId, lineNumber, columnNumber); 415 } 416 417 void V8InjectedScriptHost::undebugFunctionMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 418 { 419 String scriptId; 420 int lineNumber; 421 int columnNumber; 422 if (!getFunctionLocation(info, &scriptId, &lineNumber, &columnNumber)) 423 return; 424 425 InjectedScriptHost* host = V8InjectedScriptHost::toImpl(info.Holder()); 426 host->undebugFunction(scriptId, lineNumber, columnNumber); 427 } 428 429 void V8InjectedScriptHost::monitorFunctionMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 430 { 431 String scriptId; 432 int lineNumber; 433 int columnNumber; 434 if (!getFunctionLocation(info, &scriptId, &lineNumber, &columnNumber)) 435 return; 436 437 v8::Handle<v8::Value> name; 438 if (info.Length() > 0 && info[0]->IsFunction()) { 439 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(info[0]); 440 name = function->GetName(); 441 if (!name->IsString() || !v8::Handle<v8::String>::Cast(name)->Length()) 442 name = function->GetInferredName(); 443 } 444 445 InjectedScriptHost* host = V8InjectedScriptHost::toImpl(info.Holder()); 446 host->monitorFunction(scriptId, lineNumber, columnNumber, toCoreStringWithUndefinedOrNullCheck(name)); 447 } 448 449 void V8InjectedScriptHost::unmonitorFunctionMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 450 { 451 String scriptId; 452 int lineNumber; 453 int columnNumber; 454 if (!getFunctionLocation(info, &scriptId, &lineNumber, &columnNumber)) 455 return; 456 457 InjectedScriptHost* host = V8InjectedScriptHost::toImpl(info.Holder()); 458 host->unmonitorFunction(scriptId, lineNumber, columnNumber); 459 } 460 461 void V8InjectedScriptHost::callFunctionMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 462 { 463 if (info.Length() < 2 || info.Length() > 3 || !info[0]->IsFunction()) { 464 ASSERT_NOT_REACHED(); 465 return; 466 } 467 468 v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(info[0]); 469 v8::Handle<v8::Value> receiver = info[1]; 470 471 if (info.Length() < 3 || info[2]->IsUndefined()) { 472 v8::Local<v8::Value> result = function->Call(receiver, 0, 0); 473 v8SetReturnValue(info, result); 474 return; 475 } 476 477 if (!info[2]->IsArray()) { 478 ASSERT_NOT_REACHED(); 479 return; 480 } 481 482 v8::Handle<v8::Array> arguments = v8::Handle<v8::Array>::Cast(info[2]); 483 size_t argc = arguments->Length(); 484 OwnPtr<v8::Handle<v8::Value>[]> argv = adoptArrayPtr(new v8::Handle<v8::Value>[argc]); 485 for (size_t i = 0; i < argc; ++i) 486 argv[i] = arguments->Get(i); 487 488 v8::Local<v8::Value> result = function->Call(receiver, argc, argv.get()); 489 v8SetReturnValue(info, result); 490 } 491 492 void V8InjectedScriptHost::suppressWarningsAndCallFunctionMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 493 { 494 InjectedScriptHost* host = V8InjectedScriptHost::toImpl(info.Holder()); 495 ScriptDebugServer& debugServer = host->scriptDebugServer(); 496 debugServer.muteWarningsAndDeprecations(); 497 498 callFunctionMethodCustom(info); 499 500 debugServer.unmuteWarningsAndDeprecations(); 501 } 502 503 void V8InjectedScriptHost::setNonEnumPropertyMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) 504 { 505 if (info.Length() < 3 || !info[0]->IsObject() || !info[1]->IsString()) 506 return; 507 508 v8::Local<v8::Object> object = info[0]->ToObject(); 509 object->ForceSet(info[1], info[2], v8::DontEnum); 510 } 511 512 } // namespace blink 513