| 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 try { |
| 75 if (typeof(r) == "string") { |
| 76 resultString = "\"" + r + "\""; |
| 77 } else if (Array.isArray(r)) { |
| 78 resultString = "[" + r + "]"; |
| 79 } else { |
| 80 resultString = "" + r; |
| 81 } |
| 82 } catch (e) { |
| 83 resultString = "Oops!"; |
| 84 } |
| 85 var self = this; |
| 86 this.terminal_.write(stringToBytes(resultString + "\n"), 0, |
| 87 Whence.FROM_CURRENT) |
| 88 .then(function (result) { self.didWriteResult_(result); }); |
| 89 } |
| 90 |
| 91 didWriteResult_(result) { |
| 92 this.start(); |
| 93 } |
| 94 } |
| 95 |
| 96 class TerminalClientImpl { |
| 97 connectToTerminal(terminal) { |
| 98 (new Repl(terminal)).start(); |
| 99 } |
| 100 } |
| 101 |
| 102 class ReplApp extends Application { |
| 103 acceptConnection(initiatorURL, initiatorServiceExchange) { |
| 104 initiatorServiceExchange.provideService(TerminalClient, |
| 105 TerminalClientImpl); |
| 106 } |
| 107 } |
| 108 |
| 109 return ReplApp; |
| 110 }); |
| OLD | NEW |