Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 #!mojo mojo:js_content_handler | |
| 2 // Copyright 2015 The Chromium Authors. All rights reserved. | |
| 3 // Use of this source code is governed by a BSD-style license that can be | |
| 4 // found in the LICENSE file. | |
| 5 | |
| 6 // Simple JavaScript REPL example, using TerminalClient. | |
| 7 // | |
| 8 // To run this, do something like: | |
| 9 // | |
| 10 // $ sky/tools/skydb start out/Debug mojo:moterm_example_app | |
| 11 // | |
| 12 // At the moterm_example_app prompt: | |
| 13 // | |
| 14 // :) file:///absolute/path/to/repl.js | |
| 15 // | |
| 16 // Then, at the repl.js prompt, enter JavaScript, e.g.: | |
| 17 // | |
| 18 // > 1 + 2 | |
| 19 // 3 | |
| 20 // > function f(x, y) { return x + y; } | |
| 21 // undefined | |
| 22 // > f("abc", 123) | |
| 23 // "abc123" | |
| 24 // | |
| 25 // (Note that multiple simultaneous REPLs will share the same global state, that | |
| 26 // the global state will persist, etc. This is really just intended as a demo!) | |
| 27 | |
| 28 define("main", [ | |
| 29 "mojo/services/public/js/application", | |
| 30 "mojo/services/files/public/interfaces/types.mojom", | |
| 31 "mojo/services/terminal/public/interfaces/terminal_client.mojom", | |
| 32 ], function(application, files_types, terminal_client) { | |
| 33 const Application = application.Application; | |
| 34 const TerminalClient = terminal_client.TerminalClient; | |
| 35 const Whence = files_types.Whence; | |
| 36 | |
| 37 function stringToBytes(s) { | |
| 38 return s.split("").map(function (c) { return c.charCodeAt(0); }); | |
| 39 } | |
| 40 | |
| 41 class Repl { | |
| 42 constructor(terminal) { | |
| 43 this.terminal_ = terminal; | |
| 44 } | |
| 45 | |
| 46 start() { | |
| 47 // TODO(vtl): Handle errors. | |
| 48 var self = this; | |
| 49 this.terminal_.write(stringToBytes("> "), 0, Whence.FROM_CURRENT) | |
| 50 .then(function (result) { self.didWritePrompt_(result); }); | |
| 51 } | |
| 52 | |
| 53 didWritePrompt_(result) { | |
| 54 // TODO(vtl): Handle errors. | |
| 55 var self = this; | |
| 56 this.terminal_.read(1000, 0, Whence.FROM_CURRENT) | |
| 57 .then(function (result) { self.didRead_(result); }); | |
| 58 } | |
| 59 | |
| 60 didRead_(result) { | |
| 61 // TODO(vtl): Handle errors. | |
| 62 var s = String.fromCharCode.apply(String, result.bytes_read).trim(); | |
| 63 var r; | |
| 64 try { | |
| 65 // Note: Indirectly calling eval as follows leads to the evaluation | |
| 66 // working at global scope (as of ECMAScript 5). (This allows us to | |
| 67 // persist state across evals without doing any work.) | |
| 68 var geval = eval; | |
| 69 r = geval(s); | |
| 70 } catch (e) { | |
| 71 r = e; | |
| 72 } | |
| 73 var resultString; | |
| 74 if (typeof(r) == "string") { | |
| 75 resultString = "\"" + r + "\""; | |
| 76 } else if (r === null) { | |
| 77 resultString = "null"; | |
|
hansmuller
2015/05/12 22:33:01
I suppose you could deal with the other cases with
viettrungluu
2015/05/12 22:52:25
Oh, good point. (Silly JavaScript. I forgot that "
| |
| 78 } else if (r === undefined) { | |
| 79 resultString = "undefined"; | |
| 80 } else { | |
| 81 try { | |
| 82 resultString = r.toString(); | |
| 83 } catch (e) { | |
| 84 resultString = "Oops!"; | |
| 85 } | |
| 86 } | |
| 87 var self = this; | |
| 88 this.terminal_.write(stringToBytes(resultString + "\n"), 0, | |
| 89 Whence.FROM_CURRENT) | |
| 90 .then(function (result) { self.didWriteResult_(result); }); | |
| 91 } | |
| 92 | |
| 93 didWriteResult_(result) { | |
| 94 this.start(); | |
| 95 } | |
| 96 } | |
| 97 | |
| 98 class TerminalClientImpl { | |
| 99 connectToTerminal(terminal) { | |
| 100 (new Repl(terminal)).start(); | |
| 101 } | |
| 102 } | |
| 103 | |
| 104 class ReplApp extends Application { | |
| 105 acceptConnection(initiatorURL, initiatorServiceExchange) { | |
| 106 initiatorServiceExchange.provideService(TerminalClient, | |
| 107 TerminalClientImpl); | |
| 108 } | |
| 109 } | |
| 110 | |
| 111 return ReplApp; | |
| 112 }); | |
| OLD | NEW |