protected virtual Task <bool> AcceptCommand(MessageId id, JObject args, CancellationToken token) { return(Task.FromResult(false)); }
public virtual void SendResponse(MessageId id, Result result, CancellationToken token) { SendResponseInternal(id, result, token); }
protected override async Task <bool> AcceptCommand(MessageId id, string method, JObject args, CancellationToken token) { // Inspector doesn't use the Target domain or sessions // so we try to init immediately if (hideWebDriver && id == SessionId.Null) { await DeleteWebDriver(id, token); } if (!contexts.TryGetValue(id, out var context)) { return(false); } switch (method) { case "Target.attachToTarget": { var resp = await SendCommand(id, method, args, token); await DeleteWebDriver(new SessionId(resp.Value["sessionId"]?.ToString()), token); break; } case "Debugger.enable": { var resp = await SendCommand(id, method, args, token); context.DebuggerId = resp.Value["debuggerId"]?.ToString(); if (await IsRuntimeAlreadyReadyAlready(id, token)) { await RuntimeReady(id, token); } SendResponse(id, resp, token); return(true); } case "Debugger.getScriptSource": { var script = args?["scriptId"]?.Value <string>(); return(await OnGetScriptSource(id, script, token)); } case "Runtime.compileScript": { var exp = args?["expression"]?.Value <string>(); if (exp.StartsWith("//dotnet:", StringComparison.Ordinal)) { OnCompileDotnetScript(id, token); return(true); } break; } case "Debugger.getPossibleBreakpoints": { var resp = await SendCommand(id, method, args, token); if (resp.IsOk && resp.Value["locations"].HasValues) { SendResponse(id, resp, token); return(true); } var start = SourceLocation.Parse(args?["start"] as JObject); //FIXME support variant where restrictToFunction=true and end is omitted var end = SourceLocation.Parse(args?["end"] as JObject); if (start != null && end != null && await GetPossibleBreakpoints(id, start, end, token)) { return(true); } SendResponse(id, resp, token); return(true); } case "Debugger.setBreakpoint": { break; } case "Debugger.setBreakpointByUrl": { var resp = await SendCommand(id, method, args, token); if (!resp.IsOk) { SendResponse(id, resp, token); return(true); } var bpid = resp.Value["breakpointId"]?.ToString(); var locations = resp.Value["locations"]?.Values <object>(); var request = BreakpointRequest.Parse(bpid, args); // is the store done loading? var loaded = context.Source.Task.IsCompleted; if (!loaded) { // Send and empty response immediately if not // and register the breakpoint for resolution context.BreakpointRequests[bpid] = request; SendResponse(id, resp, token); } if (await IsRuntimeAlreadyReadyAlready(id, token)) { var store = await RuntimeReady(id, token); Log("verbose", $"BP req {args}"); await SetBreakpoint(id, store, request, !loaded, token); } if (loaded) { // we were already loaded so we should send a response // with the locations included and register the request context.BreakpointRequests[bpid] = request; var result = Result.OkFromObject(request.AsSetBreakpointByUrlResponse(locations)); SendResponse(id, result, token); } return(true); } case "Debugger.removeBreakpoint": { await RemoveBreakpoint(id, args, token); break; } case "Debugger.resume": { await OnResume(id, token); break; } case "Debugger.stepInto": { return(await Step(id, StepKind.Into, token)); } case "Debugger.stepOut": { return(await Step(id, StepKind.Out, token)); } case "Debugger.stepOver": { return(await Step(id, StepKind.Over, token)); } case "Debugger.evaluateOnCallFrame": { if (!DotnetObjectId.TryParse(args?["callFrameId"], out var objectId)) { return(false); } switch (objectId.Scheme) { case "scope": return(await OnEvaluateOnCallFrame(id, int.Parse(objectId.Value), args?["expression"]?.Value <string>(), token)); default: return(false); } } case "Runtime.getProperties": { if (!DotnetObjectId.TryParse(args?["objectId"], out var objectId)) { break; } var result = await RuntimeGetProperties(id, objectId, args, token); SendResponse(id, result, token); return(true); } case "Runtime.releaseObject": { if (!(DotnetObjectId.TryParse(args["objectId"], out var objectId) && objectId.Scheme == "cfo_res")) { break; } await SendMonoCommand(id, MonoCommands.ReleaseObject(objectId), token); SendResponse(id, Result.OkFromObject(new { }), token); return(true); } case "Debugger.setPauseOnExceptions": { string state = args["state"].Value <string>(); await SendMonoCommand(id, MonoCommands.SetPauseOnExceptions(state), token); // Pass this on to JS too return(false); } // Protocol extensions case "DotnetDebugger.addSymbolServerUrl": { string url = args["url"]?.Value <string>(); if (!String.IsNullOrEmpty(url) && !urlSymbolServerList.Contains(url)) { urlSymbolServerList.Add(url); } return(true); } case "DotnetDebugger.getMethodLocation": { Console.WriteLine("set-breakpoint-by-method: " + id + " " + args); var store = await RuntimeReady(id, token); string aname = args["assemblyName"]?.Value <string>(); string typeName = args["typeName"]?.Value <string>(); string methodName = args["methodName"]?.Value <string>(); if (aname == null || typeName == null || methodName == null) { SendResponse(id, Result.Err("Invalid protocol message '" + args + "'."), token); return(true); } // GetAssemblyByName seems to work on file names var assembly = store.GetAssemblyByName(aname); if (assembly == null) { assembly = store.GetAssemblyByName(aname + ".exe"); } if (assembly == null) { assembly = store.GetAssemblyByName(aname + ".dll"); } if (assembly == null) { SendResponse(id, Result.Err("Assembly '" + aname + "' not found."), token); return(true); } var type = assembly.GetTypeByName(typeName); if (type == null) { SendResponse(id, Result.Err($"Type '{typeName}' not found."), token); return(true); } var methodInfo = type.Methods.FirstOrDefault(m => m.Name == methodName); if (methodInfo == null) { // Maybe this is an async method, in which case the debug info is attached // to the async method implementation, in class named: // `{type_name}/<method_name>::MoveNext` methodInfo = assembly.TypesByName.Values.SingleOrDefault(t => t.FullName.StartsWith($"{typeName}/<{methodName}>"))? .Methods.FirstOrDefault(mi => mi.Name == "MoveNext"); } if (methodInfo == null) { SendResponse(id, Result.Err($"Method '{typeName}:{methodName}' not found."), token); return(true); } var src_url = methodInfo.Assembly.Sources.Single(sf => sf.SourceId == methodInfo.SourceId).Url; SendResponse(id, Result.OkFromObject(new { result = new { line = methodInfo.StartLocation.Line, column = methodInfo.StartLocation.Column, url = src_url } }), token); return(true); } case "Runtime.callFunctionOn": { if (!DotnetObjectId.TryParse(args["objectId"], out var objectId)) { return(false); } if (objectId.Scheme == "scope") { SendResponse(id, Result.Exception(new ArgumentException( $"Runtime.callFunctionOn not supported with scope ({objectId}).")), token); return(true); } var res = await SendMonoCommand(id, MonoCommands.CallFunctionOn(args), token); var res_value_type = res.Value?["result"]?["value"]?.Type; if (res.IsOk && res_value_type == JTokenType.Object || res_value_type == JTokenType.Object) { res = Result.OkFromObject(new { result = res.Value["result"]["value"] }); } SendResponse(id, res, token); return(true); } } return(false); }
void OnCompileDotnetScript(MessageId msg_id, CancellationToken token) { SendResponse(msg_id, Result.OkFromObject(new { }), token); }
public async Task <SyntaxTree> ReplaceVars(SyntaxTree syntaxTree, MonoProxy proxy, MessageId msg_id, int scope_id, CancellationToken token) { CompilationUnitSyntax root = syntaxTree.GetCompilationUnitRoot(); foreach (var var in variables) { ClassDeclarationSyntax classDeclaration = root.Members.ElementAt(0) as ClassDeclarationSyntax; MethodDeclarationSyntax method = classDeclaration.Members.ElementAt(0) as MethodDeclarationSyntax; JToken value = await proxy.TryGetVariableValue(msg_id, scope_id, var.Identifier.Text, false, token); if (value == null) { throw new Exception($"The name {var.Identifier.Text} does not exist in the current context"); } values.Add(ConvertJSToCSharpType(value["value"])); var updatedMethod = method.AddParameterListParameters( SyntaxFactory.Parameter( SyntaxFactory.Identifier(var.Identifier.Text)) .WithType(SyntaxFactory.ParseTypeName(GetTypeFullName(value["value"])))); root = root.ReplaceNode(method, updatedMethod); } syntaxTree = syntaxTree.WithRootAndOptions(root, syntaxTree.Options); return(syntaxTree); }
internal static async Task <string> CompileAndRunTheExpression(MonoProxy proxy, MessageId msg_id, int scope_id, string expression, CancellationToken token) { FindVariableNMethodCall findVarNMethodCall = new FindVariableNMethodCall(); string retString; SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(@" using System; public class CompileAndRunTheExpression { public string Evaluate() { return (" + expression + @").ToString(); } }" ); FindThisExpression findThisExpression = new FindThisExpression(syntaxTree); var expressionTree = GetExpressionFromSyntaxTree(syntaxTree); findThisExpression.Visit(expressionTree); await findThisExpression.CheckIfIsProperty(proxy, msg_id, scope_id, token); syntaxTree = findThisExpression.syntaxTree; expressionTree = GetExpressionFromSyntaxTree(syntaxTree); findVarNMethodCall.Visit(expressionTree); syntaxTree = await findVarNMethodCall.ReplaceVars(syntaxTree, proxy, msg_id, scope_id, token); MetadataReference[] references = new MetadataReference[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location), MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location) }; CSharpCompilation compilation = CSharpCompilation.Create( "compileAndRunTheExpression", syntaxTrees: new[] { syntaxTree }, references: references, options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); using (var ms = new MemoryStream()) { EmitResult result = compilation.Emit(ms); ms.Seek(0, SeekOrigin.Begin); Assembly assembly = Assembly.Load(ms.ToArray()); Type type = assembly.GetType("CompileAndRunTheExpression"); object obj = Activator.CreateInstance(type); var ret = type.InvokeMember("Evaluate", BindingFlags.Default | BindingFlags.InvokeMethod, null, obj, findVarNMethodCall.values.ToArray()); retString = ret.ToString(); } return(retString); }