From 9004192101f071429d0c7ea2f4eac273bc6ed433 Mon Sep 17 00:00:00 2001 From: "commit-bot@chromium.org" Date: Tue, 22 Apr 2014 21:13:45 +0000 Subject: [PATCH] Factor out common template code. Send stdout back to web page. BUG=skia: R=mtklein@google.com Author: jcgregorio@google.com Review URL: https://codereview.chromium.org/246823004 git-svn-id: http://skia.googlecode.com/svn/trunk@14317 2bbb7eff-a529-9590-31e7-b0007b416f81 --- experimental/webtry/TODO.md | 2 - experimental/webtry/css/webtry.css | 7 ++- experimental/webtry/js/run.js | 14 ++++++ experimental/webtry/templates/content.html | 25 ++++++++++ experimental/webtry/templates/iframe.html | 12 +---- experimental/webtry/templates/index.html | 20 +------- experimental/webtry/templates/template.cpp | 2 +- experimental/webtry/templates/workspace.html | 33 ++++--------- experimental/webtry/webtry.go | 52 ++++++++++++++------ 9 files changed, 91 insertions(+), 76 deletions(-) create mode 100644 experimental/webtry/templates/content.html diff --git a/experimental/webtry/TODO.md b/experimental/webtry/TODO.md index 049f476ec0..b42149a5d9 100644 --- a/experimental/webtry/TODO.md +++ b/experimental/webtry/TODO.md @@ -1,6 +1,5 @@ Public facing feature requests ------------------------------ - - return printf output - ability to render against multiple targets (gpu/cpu) - versioning (which version of skia was this run against) - magnifying glass (both client side and server side) @@ -15,4 +14,3 @@ Implementation details - Add font support in the c++ template. - Add inline links to doxygen. - Add monitoring and probing (nagios). - - sanitize the file name in the output. diff --git a/experimental/webtry/css/webtry.css b/experimental/webtry/css/webtry.css index dcc2540292..70a2c5e38e 100644 --- a/experimental/webtry/css/webtry.css +++ b/experimental/webtry/css/webtry.css @@ -35,13 +35,12 @@ template { display: none; } -pre, code { - padding: 0; +code { color: green; } -#output { - color: #333; +pre, code { + padding: 0; } .tries { diff --git a/experimental/webtry/js/run.js b/experimental/webtry/js/run.js index c69e2bcc22..d44e81817b 100644 --- a/experimental/webtry/js/run.js +++ b/experimental/webtry/js/run.js @@ -43,6 +43,7 @@ var embedButton = document.getElementById('embedButton'); var code = document.getElementById('code'); var output = document.getElementById('output'); + var stdout = document.getElementById('stdout'); var img = document.getElementById('img'); var tryHistory = document.getElementById('tryHistory'); var parser = new DOMParser(); @@ -70,11 +71,20 @@ alert('Something bad happened: ' + e); } + function clearOutput() { + output.innerText = ""; + if (stdout) { + stdout.innerText = ""; + } + embed.style.display='none'; + } + /** * Called when an image in the workspace history is clicked. */ function historyClick() { beginWait(); + clearOutput(); var req = new XMLHttpRequest(); req.addEventListener('load', historyComplete); req.addEventListener('error', xhrError); @@ -132,6 +142,9 @@ console.log(e.target.response); body = JSON.parse(e.target.response); output.innerText = body.message; + if (stdout) { + stdout.innerText = body.stdout; + } if (body.hasOwnProperty('img')) { img.src = 'data:image/png;base64,' + body.img; } else { @@ -159,6 +172,7 @@ function onSubmitCode() { beginWait(); + clearOutput(); var req = new XMLHttpRequest(); req.addEventListener('load', codeComplete); req.addEventListener('error', xhrError); diff --git a/experimental/webtry/templates/content.html b/experimental/webtry/templates/content.html new file mode 100644 index 0000000000..77e68e3d49 --- /dev/null +++ b/experimental/webtry/templates/content.html @@ -0,0 +1,25 @@ + +
+
#include "SkCanvas.h"
+
+void draw(SkCanvas* canvas) {
+  
+}
+
+ + + + + + + +

+ +

+ +

Errors

+
+

Runtime output

+

+
+
diff --git a/experimental/webtry/templates/iframe.html b/experimental/webtry/templates/iframe.html index 01e529acbc..d7b165db2f 100644 --- a/experimental/webtry/templates/iframe.html +++ b/experimental/webtry/templates/iframe.html @@ -6,17 +6,7 @@ -
-
- - - - -

- -
- -
+ {{template "content.html" .}} -
-
- {{else}} -

Create

- Create a new workspace: -
-

-
-{{end}} +
+

Create

+ Create a new workspace: +
+

+
+{{end}} diff --git a/experimental/webtry/webtry.go b/experimental/webtry/webtry.go index 73e9fda993..8e02a751a3 100644 --- a/experimental/webtry/webtry.go +++ b/experimental/webtry/webtry.go @@ -135,12 +135,14 @@ func init() { indexTemplate, err = htemplate.ParseFiles( filepath.Join(cwd, "templates/index.html"), filepath.Join(cwd, "templates/titlebar.html"), + filepath.Join(cwd, "templates/content.html"), ) if err != nil { panic(err) } iframeTemplate, err = htemplate.ParseFiles( filepath.Join(cwd, "templates/iframe.html"), + filepath.Join(cwd, "templates/content.html"), ) if err != nil { panic(err) @@ -155,6 +157,7 @@ func init() { workspaceTemplate, err = htemplate.ParseFiles( filepath.Join(cwd, "templates/workspace.html"), filepath.Join(cwd, "templates/titlebar.html"), + filepath.Join(cwd, "templates/content.html"), ) if err != nil { panic(err) @@ -220,8 +223,8 @@ func init() { // userCode is used in template expansion. type userCode struct { - UserCode string - Hash string + Code string + Hash string } // expandToFile expands the template and writes the result to the file. @@ -231,7 +234,7 @@ func expandToFile(filename string, code string, t *template.Template) error { return err } defer f.Close() - return t.Execute(f, userCode{UserCode: code}) + return t.Execute(f, userCode{Code: code}) } // expandCode expands the template into a file and calculate the MD5 hash. @@ -249,6 +252,7 @@ func expandCode(code string) (string, error) { // response is serialized to JSON as a response to POSTs. type response struct { Message string `json:"message"` + StdOut string `json:"stdout"` Img string `json:"img"` Hash string `json:"hash"` } @@ -298,8 +302,15 @@ func doCmd(commandLine string, moveToDebug bool) (string, error) { // reportError formats an HTTP error response and also logs the detailed error message. func reportError(w http.ResponseWriter, r *http.Request, err error, message string) { + log.Printf("Error: %s\n%s", message, err.Error()) + http.Error(w, message, 500) +} + +// reportTryError formats an HTTP error response in JSON and also logs the detailed error message. +func reportTryError(w http.ResponseWriter, r *http.Request, err error, message, hash string) { m := response{ Message: message, + Hash: hash, } log.Printf("Error: %s\n%s", message, err.Error()) resp, err := json.Marshal(m) @@ -499,7 +510,7 @@ func iframeHandler(w http.ResponseWriter, r *http.Request) { return } // Expand the template. - if err := iframeTemplate.Execute(w, userCode{UserCode: code, Hash: hash}); err != nil { + if err := iframeTemplate.Execute(w, userCode{Code: code, Hash: hash}); err != nil { log.Printf("ERROR: Failed to expand template: %q\n", err) } } @@ -540,6 +551,12 @@ func tryInfoHandler(w http.ResponseWriter, r *http.Request) { w.Write(resp) } +func cleanCompileOutput(s, hash string) string { + old := "../../../cache/" + hash + ".cpp:" + log.Printf("INFO: replacing %q\n", old) + return strings.Replace(s, old, "usercode.cpp:", -1) +} + // mainHandler handles the GET and POST of the main page. func mainHandler(w http.ResponseWriter, r *http.Request) { log.Printf("Main Handler: %q\n", r.URL.Path) @@ -560,7 +577,7 @@ func mainHandler(w http.ResponseWriter, r *http.Request) { } } // Expand the template. - if err := indexTemplate.Execute(w, userCode{UserCode: code, Hash: hash}); err != nil { + if err := indexTemplate.Execute(w, userCode{Code: code, Hash: hash}); err != nil { log.Printf("ERROR: Failed to expand template: %q\n", err) } } else if r.Method == "POST" { @@ -568,38 +585,40 @@ func mainHandler(w http.ResponseWriter, r *http.Request) { buf := bytes.NewBuffer(make([]byte, 0, MAX_TRY_SIZE)) n, err := buf.ReadFrom(r.Body) if err != nil { - reportError(w, r, err, "Failed to read a request body.") + reportTryError(w, r, err, "Failed to read a request body.", "") return } if n == MAX_TRY_SIZE { err := fmt.Errorf("Code length equal to, or exceeded, %d", MAX_TRY_SIZE) - reportError(w, r, err, "Code too large.") + reportTryError(w, r, err, "Code too large.", "") return } request := TryRequest{} if err := json.Unmarshal(buf.Bytes(), &request); err != nil { - reportError(w, r, err, "Coulnd't decode JSON.") + reportTryError(w, r, err, "Coulnd't decode JSON.", "") return } if hasPreProcessor(request.Code) { err := fmt.Errorf("Found preprocessor macro in code.") - reportError(w, r, err, "Preprocessor macros aren't allowed.") + reportTryError(w, r, err, "Preprocessor macros aren't allowed.", "") return } hash, err := expandCode(LineNumbers(request.Code)) if err != nil { - reportError(w, r, err, "Failed to write the code to compile.") + reportTryError(w, r, err, "Failed to write the code to compile.", hash) return } writeToDatabase(hash, request.Code, request.Name) message, err := doCmd(fmt.Sprintf(RESULT_COMPILE, hash, hash), true) if err != nil { - reportError(w, r, err, "Failed to compile the code:\n"+message) + message = cleanCompileOutput(message, hash) + reportTryError(w, r, err, message, hash) return } linkMessage, err := doCmd(fmt.Sprintf(LINK, hash, hash), true) if err != nil { - reportError(w, r, err, "Failed to link the code:\n"+linkMessage) + linkMessage = cleanCompileOutput(linkMessage, hash) + reportTryError(w, r, err, linkMessage, hash) return } message += linkMessage @@ -609,7 +628,7 @@ func mainHandler(w http.ResponseWriter, r *http.Request) { } else { abs, err := filepath.Abs("../../../inout") if err != nil { - reportError(w, r, err, "Failed to find executable directory.") + reportTryError(w, r, err, "Failed to find executable directory.", hash) return } cmd = abs + "/" + cmd @@ -617,23 +636,24 @@ func mainHandler(w http.ResponseWriter, r *http.Request) { execMessage, err := doCmd(cmd, false) if err != nil { - reportError(w, r, err, "Failed to run the code:\n"+execMessage) + reportTryError(w, r, err, "Failed to run the code:\n"+execMessage, hash) return } png, err := ioutil.ReadFile("../../../inout/" + hash + ".png") if err != nil { - reportError(w, r, err, "Failed to open the generated PNG.") + reportTryError(w, r, err, "Failed to open the generated PNG.", hash) return } m := response{ Message: message, + StdOut: execMessage, Img: base64.StdEncoding.EncodeToString([]byte(png)), Hash: hash, } resp, err := json.Marshal(m) if err != nil { - reportError(w, r, err, "Failed to serialize a response.") + reportTryError(w, r, err, "Failed to serialize a response.", hash) return } w.Write(resp) -- 2.34.1