blob: 759daa73a1baa7f0bf6dc7d196931dd2bae11461 [file] [log] [blame]
#!mojo mojo:js_content_handler
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Simple JavaScript REPL example, using TerminalClient.
//
// To run this, do something like:
//
// $ sky/tools/mojodb start out/Debug mojo:moterm_example_app
//
// At the moterm_example_app prompt:
//
// :) file:///absolute/path/to/repl.js
//
// Then, at the repl.js prompt, enter JavaScript, e.g.:
//
// > 1 + 2
// 3
// > function f(x, y) { return x + y; }
// undefined
// > f("abc", 123)
// "abc123"
//
// (Note that multiple simultaneous REPLs will share the same global state, that
// the global state will persist, etc. This is really just intended as a demo!)
define("main", [
"mojo/services/public/js/application",
"mojo/services/files/interfaces/types.mojom",
"mojo/services/terminal/interfaces/terminal_client.mojom",
], function(application, files_types, terminal_client) {
const Application = application.Application;
const TerminalClient = terminal_client.TerminalClient;
const Whence = files_types.Whence;
function stringToBytes(s) {
return s.split("").map(function (c) { return c.charCodeAt(0); });
}
class Repl {
constructor(terminal) {
this.terminal_ = terminal;
}
start() {
// TODO(vtl): Handle errors.
var self = this;
this.terminal_.write(stringToBytes("> "), 0, Whence.FROM_CURRENT)
.then(function (result) { self.didWritePrompt_(result); });
}
didWritePrompt_(result) {
// TODO(vtl): Handle errors.
var self = this;
this.terminal_.read(1000, 0, Whence.FROM_CURRENT)
.then(function (result) { self.didRead_(result); });
}
didRead_(result) {
// TODO(vtl): Handle errors.
var s = String.fromCharCode.apply(String, result.bytes_read).trim();
var r;
try {
// Note: Indirectly calling eval as follows leads to the evaluation
// working at global scope (as of ECMAScript 5). (This allows us to
// persist state across evals without doing any work.)
var geval = eval;
r = geval(s);
} catch (e) {
r = e;
}
var resultString;
try {
if (typeof(r) == "string") {
resultString = "\"" + r + "\"";
} else if (Array.isArray(r)) {
resultString = "[" + r + "]";
} else {
resultString = "" + r;
}
} catch (e) {
resultString = "Oops!";
}
var self = this;
this.terminal_.write(stringToBytes(resultString + "\n"), 0,
Whence.FROM_CURRENT)
.then(function (result) { self.didWriteResult_(result); });
}
didWriteResult_(result) {
this.start();
}
}
class TerminalClientImpl {
connectToTerminal(terminal) {
(new Repl(terminal)).start();
}
}
class ReplApp extends Application {
acceptConnection(initiatorURL, initiatorServiceExchange) {
initiatorServiceExchange.provideService(TerminalClient,
TerminalClientImpl);
}
}
return ReplApp;
});