Changeset 142114 in webkit
- Timestamp:
- Feb 7, 2013 7:00:13 AM (11 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 20 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r142113 r142114 1 2013-02-07 Peter Rybin <prybin@chromium.org> 2 3 Web Inspector: support JavaScript variable mutation in protocol and V8 bindings 4 https://bugs.webkit.org/show_bug.cgi?id=107829 5 6 Reviewed by Pavel Feldman. 7 8 * inspector-protocol/debugger-setVariableValue-expected.txt: Added. 9 * inspector-protocol/debugger-setVariableValue.html: Added. 10 * inspector/console/command-line-api-expected.txt: 11 * platform/chromium/inspector-protocol/debugger-setVariableValue-expected.txt: Added. 12 1 13 2013-02-07 Yury Semikhatsky <yurys@chromium.org> 2 14 -
trunk/LayoutTests/inspector/console/command-line-api-expected.txt
r141766 r142114 1 CONSOLE MESSAGE: line 1 060: The console function $() has changed from $=getElementById(id) to $=querySelector(selector). You might try $("#%s")1 CONSOLE MESSAGE: line 1121: The console function $() has changed from $=getElementById(id) to $=querySelector(selector). You might try $("#%s") 2 2 Tests that command line api works. 3 3 -
trunk/Source/WebCore/ChangeLog
r142112 r142114 1 2013-02-07 Peter Rybin <prybin@chromium.org> 2 3 Web Inspector: support JavaScript variable mutation in protocol and V8 bindings 4 https://bugs.webkit.org/show_bug.cgi?id=107829 5 6 A new command is added to protocol description and the call is passed through 7 debugger agent through injected script and debugger script down to V8 mirror 8 API. JSC bindings got a thorw exception stub. 9 10 Only declarative JavaScript scopes are supported (local, closure, catch). Other 11 scopes (global, with) are not supported by V8 and not supported by protocol, because 12 manual approach (direct property assigment) is available for them in form of evaluate 13 commands and is more desirable because of a complex nature of operation (it can throw 14 exception in several cases such as exception in setter function). 15 16 Reviewed by Pavel Feldman. 17 18 Test: inspector-protocol/debugger-setVariableValue.html 19 20 * bindings/js/JSInjectedScriptHostCustom.cpp: 21 (WebCore::JSInjectedScriptHost::setFunctionVariableValue): 22 (WebCore): 23 * bindings/js/JSJavaScriptCallFrameCustom.cpp: 24 (WebCore::JSJavaScriptCallFrame::setVariableValue): 25 (WebCore): 26 * bindings/v8/DebuggerScript.js: 27 (.): 28 * bindings/v8/JavaScriptCallFrame.cpp: 29 (WebCore::JavaScriptCallFrame::setVariableValue): 30 (WebCore): 31 * bindings/v8/JavaScriptCallFrame.h: 32 (JavaScriptCallFrame): 33 * bindings/v8/ScriptDebugServer.cpp: 34 (WebCore::ScriptDebugServer::setFunctionVariableValue): 35 (WebCore): 36 * bindings/v8/ScriptDebugServer.h: 37 (ScriptDebugServer): 38 * bindings/v8/custom/V8InjectedScriptHostCustom.cpp: 39 (WebCore::V8InjectedScriptHost::setFunctionVariableValueCallback): 40 (WebCore): 41 * bindings/v8/custom/V8JavaScriptCallFrameCustom.cpp: 42 (WebCore::V8JavaScriptCallFrame::setVariableValueCallback): 43 (WebCore): 44 * inspector/InjectedScript.cpp: 45 (WebCore::InjectedScript::setVariableValue): 46 (WebCore): 47 * inspector/InjectedScript.h: 48 (InjectedScript): 49 * inspector/InjectedScriptHost.idl: 50 * inspector/InjectedScriptSource.js: 51 (.): 52 * inspector/Inspector.json: 53 * inspector/InspectorDebuggerAgent.cpp: 54 (WebCore::InspectorDebuggerAgent::getFunctionDetails): 55 (WebCore::InspectorDebuggerAgent::setVariableValue): 56 (WebCore): 57 * inspector/InspectorDebuggerAgent.h: 58 (InspectorDebuggerAgent): 59 * inspector/JavaScriptCallFrame.idl: 60 1 61 2013-02-07 Caio Marcelo de Oliveira Filho <caio.oliveira@openbossa.org> 2 62 -
trunk/Source/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp
r141050 r142114 308 308 } 309 309 310 JSValue JSInjectedScriptHost::setFunctionVariableValue(JSC::ExecState* exec) 311 { 312 // FIXME: implement this. https://bugs.webkit.org/show_bug.cgi?id=107830 313 throwError(exec, createTypeError(exec, "Variable value mutation is not supported")); 314 return jsUndefined(); 315 } 316 310 317 } // namespace WebCore 311 318 -
trunk/Source/WebCore/bindings/js/JSJavaScriptCallFrameCustom.cpp
r133953 r142114 131 131 } 132 132 133 JSValue JSJavaScriptCallFrame::setVariableValue(JSC::ExecState* exec) 134 { 135 // FIXME: implement this. https://bugs.webkit.org/show_bug.cgi?id=107830 136 throwError(exec, createTypeError(exec, "Variable value mutation is not supported")); 137 return jsUndefined(); 138 } 139 133 140 } // namespace WebCore 134 141 -
trunk/Source/WebCore/bindings/v8/DebuggerScript.js
r139405 r142114 94 94 } 95 95 96 DebuggerScript.setFunctionVariableValue = function(functionValue, scopeIndex, variableName, newValue) 97 { 98 var mirror = MakeMirror(functionValue); 99 if (!mirror.isFunction()) 100 throw new Error("Function value has incorrect type"); 101 return DebuggerScript._setScopeVariableValue(mirror, scopeIndex, variableName, newValue); 102 } 103 104 DebuggerScript._setScopeVariableValue = function(scopeHolder, scopeIndex, variableName, newValue) 105 { 106 var scopeMirror = scopeHolder.scope(scopeIndex); 107 if (!scopeMirror) 108 throw new Error("Incorrect scope index"); 109 scopeMirror.setVariableValue(variableName, newValue); 110 return undefined; 111 } 112 96 113 DebuggerScript.getScripts = function(contextData) 97 114 { … … 296 313 } 297 314 315 function setVariableValue(scopeNumber, variableName, newValue) 316 { 317 return DebuggerScript._setScopeVariableValue(frameMirror, scopeNumber, variableName, newValue); 318 } 319 298 320 return { 299 321 "sourceID": sourceID, … … 306 328 "evaluate": evaluate, 307 329 "caller": callerFrame, 308 "restart": restart 330 "restart": restart, 331 "setVariableValue": setVariableValue 309 332 }; 310 333 } -
trunk/Source/WebCore/bindings/v8/JavaScriptCallFrame.cpp
r140611 r142114 135 135 } 136 136 137 v8::Handle<v8::Value> JavaScriptCallFrame::setVariableValue(int scopeNumber, const String& variableName, v8::Handle<v8::Value> newValue) 138 { 139 v8::Handle<v8::Function> setVariableValueFunction = v8::Handle<v8::Function>::Cast(m_callFrame.get()->Get(v8::String::NewSymbol("setVariableValue"))); 140 v8::Handle<v8::Value> argv[] = { 141 v8::Handle<v8::Value>(v8::Integer::New(scopeNumber)), 142 v8String(variableName, m_debuggerContext->GetIsolate()), 143 newValue 144 }; 145 return setVariableValueFunction->Call(m_callFrame.get(), 3, argv); 146 } 147 137 148 } // namespace WebCore 138 149 -
trunk/Source/WebCore/bindings/v8/JavaScriptCallFrame.h
r127757 r142114 62 62 v8::Handle<v8::Value> evaluate(const String& expression); 63 63 v8::Handle<v8::Value> restart(); 64 v8::Handle<v8::Value> setVariableValue(int scopeNumber, const String& variableName, v8::Handle<v8::Value> newValue); 64 65 65 66 private: -
trunk/Source/WebCore/bindings/v8/ScriptDebugServer.cpp
r140611 r142114 558 558 } 559 559 560 v8::Local<v8::Value> ScriptDebugServer::setFunctionVariableValue(v8::Handle<v8::Value> functionValue, int scopeNumber, const String& variableName, v8::Handle<v8::Value> newValue) 561 { 562 v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); 563 if (m_debuggerScript.get().IsEmpty()) 564 return *(v8::ThrowException(v8::String::New("Debugging is not enabled."))); 565 566 v8::Handle<v8::Value> argv[] = { 567 functionValue, 568 v8::Handle<v8::Value>(v8::Integer::New(scopeNumber)), 569 v8String(variableName, debuggerContext->GetIsolate()), 570 newValue 571 }; 572 return callDebuggerMethod("setFunctionVariableValue", 4, argv); 573 } 574 560 575 561 576 bool ScriptDebugServer::isPaused() -
trunk/Source/WebCore/bindings/v8/ScriptDebugServer.h
r139621 r142114 102 102 v8::Local<v8::Value> functionScopes(v8::Handle<v8::Function>); 103 103 v8::Local<v8::Value> getInternalProperties(v8::Handle<v8::Object>&); 104 v8::Local<v8::Value> setFunctionVariableValue(v8::Handle<v8::Value> functionValue, int scopeNumber, const String& variableName, v8::Handle<v8::Value> newValue); 105 104 106 105 107 virtual void compileScript(ScriptState*, const String& expression, const String& sourceURL, String* scriptId, String* exceptionMessage); -
trunk/Source/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp
r141719 r142114 322 322 } 323 323 324 v8::Handle<v8::Value> V8InjectedScriptHost::setFunctionVariableValueCallback(const v8::Arguments& args) 325 { 326 v8::Handle<v8::Value> functionValue = args[0]; 327 int scopeIndex = args[1]->Int32Value(); 328 String variableName = toWebCoreStringWithUndefinedOrNullCheck(args[2]); 329 v8::Handle<v8::Value> newValue = args[3]; 330 331 InjectedScriptHost* host = V8InjectedScriptHost::toNative(args.Holder()); 332 ScriptDebugServer& debugServer = host->scriptDebugServer(); 333 return debugServer.setFunctionVariableValue(functionValue, scopeIndex, variableName, newValue); 334 } 335 336 324 337 } // namespace WebCore 325 338 -
trunk/Source/WebCore/bindings/v8/custom/V8JavaScriptCallFrameCustom.cpp
r138665 r142114 51 51 } 52 52 53 v8::Handle<v8::Value> V8JavaScriptCallFrame::setVariableValueCallback(const v8::Arguments& args) 54 { 55 JavaScriptCallFrame* impl = V8JavaScriptCallFrame::toNative(args.Holder()); 56 int scopeIndex = args[0]->Int32Value(); 57 String variableName = toWebCoreStringWithUndefinedOrNullCheck(args[1]); 58 v8::Handle<v8::Value> newValue = args[2]; 59 return impl->setVariableValue(scopeIndex, variableName, newValue); 60 } 61 53 62 v8::Handle<v8::Value> V8JavaScriptCallFrame::scopeChainAccessorGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info) 54 63 { -
trunk/Source/WebCore/inspector/InjectedScript.cpp
r140893 r142114 117 117 } 118 118 119 void InjectedScript::setVariableValue(ErrorString* errorString, const ScriptValue& callFrames, const String* callFrameIdOpt, const String* functionObjectIdOpt, int scopeNumber, const String& variableName, const String& newValueStr) 120 { 121 ScriptFunctionCall function(injectedScriptObject(), "setVariableValue"); 122 if (callFrameIdOpt) { 123 function.appendArgument(callFrames); 124 function.appendArgument(*callFrameIdOpt); 125 } else { 126 function.appendArgument(false); 127 function.appendArgument(false); 128 } 129 if (functionObjectIdOpt) 130 function.appendArgument(*functionObjectIdOpt); 131 else 132 function.appendArgument(false); 133 function.appendArgument(scopeNumber); 134 function.appendArgument(variableName); 135 function.appendArgument(newValueStr); 136 RefPtr<InspectorValue> resultValue; 137 makeCall(function, &resultValue); 138 if (!resultValue) { 139 *errorString = "Internal error"; 140 return; 141 } 142 if (resultValue->type() == InspectorValue::TypeString) { 143 resultValue->asString(errorString); 144 return; 145 } 146 // Normal return. 147 } 148 119 149 void InjectedScript::getFunctionDetails(ErrorString* errorString, const String& functionId, RefPtr<FunctionDetails>* result) 120 150 { -
trunk/Source/WebCore/inspector/InjectedScript.h
r140893 r142114 81 81 TypeBuilder::OptOutput<bool>* wasThrown); 82 82 void restartFrame(ErrorString*, const ScriptValue& callFrames, const String& callFrameId, RefPtr<InspectorObject>* result); 83 void setVariableValue(ErrorString*, const ScriptValue& callFrames, const String* callFrameIdOpt, const String* functionObjectIdOpt, int scopeNumber, const String& variableName, const String& newValueStr); 83 84 void getFunctionDetails(ErrorString*, const String& functionId, RefPtr<TypeBuilder::Debugger::FunctionDetails>* result); 84 85 void getProperties(ErrorString*, const String& objectId, bool ownProperties, RefPtr<TypeBuilder::Array<TypeBuilder::Runtime::PropertyDescriptor> >* result); -
trunk/Source/WebCore/inspector/InjectedScriptHost.idl
r141034 r142114 50 50 [Custom] DOMString storageId(in DOMObject storage); 51 51 [Custom] DOMObject evaluate(in DOMString text); 52 // Only declarative scope (local, with and catch) is accepted. Returns undefined. 53 [Custom] DOMObject setFunctionVariableValue(in DOMObject functionObject, in int scopeIndex, in DOMString variableName, DOMObject newValue); 52 54 }; -
trunk/Source/WebCore/inspector/InjectedScriptSource.js
r141766 r142114 428 428 args = InjectedScriptHost.evaluate(args); 429 429 for (var i = 0; i < args.length; ++i) { 430 objectId = args[i].objectId; 431 if (objectId) { 432 var parsedArgId = this._parseObjectId(objectId); 433 if (!parsedArgId || parsedArgId["injectedScriptId"] !== injectedScriptId) 434 return "Arguments should belong to the same JavaScript world as the target object."; 435 436 var resolvedArg = this._objectForId(parsedArgId); 437 if (!this._isDefined(resolvedArg)) 438 return "Could not find object with given id"; 439 440 resolvedArgs.push(resolvedArg); 441 } else if ("value" in args[i]) 442 resolvedArgs.push(args[i].value); 443 else 444 resolvedArgs.push(undefined); 430 var resolvedCallArgument; 431 try { 432 resolvedCallArgument = this._resolveCallArgument(args[i]); 433 } catch (e) { 434 return String(e); 435 } 436 resolvedArgs.push(resolvedCallArgument) 445 437 } 446 438 } … … 457 449 return this._createThrownValue(e, objectGroup); 458 450 } 451 }, 452 453 /** 454 * Resolves a value from CallArgument description. 455 * @param {RuntimeAgent.CallArgument} callArgumentJson 456 * @return {*} resolved value 457 * @throw {string} error message 458 */ 459 _resolveCallArgument: function(callArgumentJson) { 460 var objectId = callArgumentJson.objectId; 461 if (objectId) { 462 var parsedArgId = this._parseObjectId(objectId); 463 if (!parsedArgId || parsedArgId["injectedScriptId"] !== injectedScriptId) 464 throw "Arguments should belong to the same JavaScript world as the target object."; 465 466 var resolvedArg = this._objectForId(parsedArgId); 467 if (!this._isDefined(resolvedArg)) 468 throw "Could not find object with given id"; 469 470 return resolvedArg; 471 } else if ("value" in callArgumentJson) 472 return callArgumentJson.value; 473 else 474 return undefined; 459 475 }, 460 476 … … 574 590 result = "Restart frame is not supported"; 575 591 return result; 592 }, 593 594 /** 595 * Either callFrameId or functionObjectId must be specified. 596 * @param {Object} topCallFrame 597 * @param {string|boolean} callFrameId or false 598 * @param {string|boolean} functionObjectId or false 599 * @param {integer} scopeNumber 600 * @param {string} variableName 601 * @param {string} newValueJsonString RuntimeAgent.CallArgument structure serialized as string 602 * @return {string|undefined} undefined if success or an error message 603 */ 604 setVariableValue: function(topCallFrame, callFrameId, functionObjectId, scopeNumber, variableName, newValueJsonString) 605 { 606 var setter; 607 if (callFrameId) { 608 var callFrame = this._callFrameForId(topCallFrame, callFrameId); 609 if (!callFrame) 610 return "Could not find call frame with given id"; 611 setter = callFrame.setVariableValue.bind(callFrame); 612 } else { 613 var parsedFunctionId = this._parseObjectId(functionObjectId); 614 var func = this._objectForId(parsedFunctionId); 615 if (typeof func !== "function") 616 return "Cannot resolve function by id."; 617 setter = InjectedScriptHost.setFunctionVariableValue.bind(InjectedScriptHost, func); 618 } 619 var newValueJson; 620 try { 621 newValueJson = InjectedScriptHost.evaluate("(" + newValueJsonString + ")"); 622 } catch (e) { 623 return "Failed to parse new value JSON " + newValueJsonString + " : " + e; 624 } 625 var resolvedValue; 626 try { 627 resolvedValue = this._resolveCallArgument(newValueJson); 628 } catch (e) { 629 return String(e); 630 } 631 try { 632 setter(scopeNumber, variableName, resolvedValue); 633 } catch (e) { 634 return "Failed to change variable value: " + e; 635 } 636 return undefined; 576 637 }, 577 638 -
trunk/Source/WebCore/inspector/Inspector.json
r142074 r142114 2934 2934 "hidden": true, 2935 2935 "description": "Sets overlay message." 2936 }, 2937 { 2938 "name": "setVariableValue", 2939 "parameters": [ 2940 { "name": "callFrameId", "$ref": "CallFrameId", "optional": true, "description": "Id of callframe that holds variable." }, 2941 { "name": "functionObjectId", "$ref": "Runtime.RemoteObjectId", "optional": true, "description": "Object id of closure (function) that holds variable." }, 2942 { "name": "scopeNumber", "type": "integer", "description": "0-based number of scope as was listed in scope chain. Only 'local', 'closure' and 'catch' scope types are allowed. Other scopes could be manipulated manually." }, 2943 { "name": "variableName", "type": "string", "description": "Variable name." }, 2944 { "name": "newValue", "$ref": "Runtime.CallArgument", "description": "New variable value." } 2945 ], 2946 "hidden": true, 2947 "description": "Changes value of variable in a callframe or a closure. Either callframe or function must be specified. Object-based scopes are not supported and must be mutated manually." 2936 2948 } 2937 2949 ], -
trunk/Source/WebCore/inspector/InspectorDebuggerAgent.cpp
r141570 r142114 412 412 InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(functionId); 413 413 if (injectedScript.hasNoValue()) { 414 *errorString = " Inspected frame has gone";414 *errorString = "Function object id is obsolete"; 415 415 return; 416 416 } … … 579 579 void InspectorDebuggerAgent::setOverlayMessage(ErrorString*, const String*) 580 580 { 581 } 582 583 void InspectorDebuggerAgent::setVariableValue(ErrorString* errorString, const String* callFrameId, const String* functionObjectId, int scopeNumber, const String& variableName, const RefPtr<InspectorObject>& newValue) 584 { 585 InjectedScript injectedScript; 586 if (callFrameId) { 587 injectedScript = m_injectedScriptManager->injectedScriptForObjectId(*callFrameId); 588 if (injectedScript.hasNoValue()) { 589 *errorString = "Inspected frame has gone"; 590 return; 591 } 592 } else if (functionObjectId) { 593 injectedScript = m_injectedScriptManager->injectedScriptForObjectId(*functionObjectId); 594 if (injectedScript.hasNoValue()) { 595 *errorString = "Function object id cannot be resolved"; 596 return; 597 } 598 } else { 599 *errorString = "Either call frame or function object must be specified"; 600 return; 601 } 602 String newValueString = newValue->toJSONString(); 603 604 injectedScript.setVariableValue(errorString, m_currentCallStack, callFrameId, functionObjectId, scopeNumber, variableName, newValueString); 581 605 } 582 606 -
trunk/Source/WebCore/inspector/InspectorDebuggerAgent.h
r139416 r142114 114 114 void runScript(ErrorString*, const TypeBuilder::Debugger::ScriptId&, const int* executionContextId, const String* objectGroup, const bool* doNotPauseOnExceptionsAndMuteConsole, RefPtr<TypeBuilder::Runtime::RemoteObject>& result, TypeBuilder::OptOutput<bool>* wasThrown); 115 115 virtual void setOverlayMessage(ErrorString*, const String*); 116 virtual void setVariableValue(ErrorString*, const String* in_callFrame, const String* in_functionObjectId, int in_scopeNumber, const String& in_variableName, const RefPtr<InspectorObject>& in_newValue); 116 117 117 118 void schedulePauseOnNextStatement(InspectorFrontend::Debugger::Reason::Enum breakReason, PassRefPtr<InspectorObject> data); -
trunk/Source/WebCore/inspector/JavaScriptCallFrame.idl
r141034 r142114 40 40 [Custom] void evaluate(in DOMString script); 41 41 [Custom] DOMObject restart(); 42 43 // Only declarative scope (local, with and catch) is accepted. Returns undefined. 44 [Custom] DOMObject setVariableValue(in int scopeIndex, in DOMString variableName, DOMObject newValue); 42 45 43 46 readonly attribute JavaScriptCallFrame caller;
Note: See TracChangeset
for help on using the changeset viewer.