From d2e54920a67d5ea23cebc3a89b953ed676c24d19 Mon Sep 17 00:00:00 2001 From: Ruben Daniels Date: Tue, 21 May 2013 18:33:42 +0200 Subject: [PATCH 1/3] * Added PTY support --- consumer.js | 32 ++++++++++++++++++++++++++------ package.json | 2 +- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/consumer.js b/consumer.js index 6d84985..0c0e984 100644 --- a/consumer.js +++ b/consumer.js @@ -1,6 +1,6 @@ ( // Module boilerplate to support browser globals, node.js and AMD. (typeof module !== "undefined" && function (m) { module.exports = m(require('stream'), require('events'), require('smith')); }) || - (typeof define === "function" && function (m) { define("vfs-socket/consumer", ["./stream-amd", "./events-amd", "smith"], m); }) || + (typeof define === "function" && function (m) { define(["./stream-amd", "./events-amd", "smith"], m); }) || (function (m) { window.consumer = m(window.stream, window.events, window.smith); }) )(function (stream, events, smith) { "use strict"; @@ -74,6 +74,7 @@ function Consumer() { watch: route("watch"), connect: route("connect"), spawn: route("spawn"), + pty: route("pty"), execFile: route("execFile"), extend: route("extend"), unextend: route("unextend"), @@ -124,6 +125,10 @@ function Consumer() { proxyApi.emit("error", err); }); }); + + this.on("error", function(err){ + this.emit("error", err); + }) var nextStreamID = 1; function storeStream(stream) { @@ -137,9 +142,9 @@ function Consumer() { stream.pause && stream.pause(); } }); - stream.on("end", function () { + stream.on("end", function (chunk) { delete streams[id]; - remote.onEnd(id); + remote.onEnd(id, chunk); nextStreamID = id; }); } @@ -194,6 +199,19 @@ function Consumer() { }; return process; } + function makePtyProxy(token){ + var pty = makeStreamProxy(token); + var pid = token.pid; + pty.pid = pid; + proxyProcesses[pid] = pty; + pty.kill = function (signal) { + remote.kill(pid, signal); + }; + pty.resize = function (cols, rows) { + remote.resize(pid, cols, rows); + }; + return pty; + } function makeWatcherProxy(token) { var watcher = new EventEmitter(); @@ -249,13 +267,13 @@ function Consumer() { if (!stream) return; stream.emit("data", chunk); } - function onEnd(id) { + function onEnd(id, chunk) { var stream = proxyStreams[id]; if (!stream) return; // TODO: not delete proxy if close is going to be called later. // but somehow do delete proxy if close won't be called later. delete proxyStreams[id]; - stream.emit("end"); + stream.emit("end", chunk); } function onClose(id) { var stream = proxyStreams[id]; @@ -361,6 +379,9 @@ function Consumer() { if (meta.process) { meta.process = makeProcessProxy(meta.process); } + if (meta.pty) { + meta.pty = makePtyProxy(meta.pty); + } if (meta.watcher) { meta.watcher = makeWatcherProxy(meta.watcher); } @@ -393,7 +414,6 @@ inherits(Consumer, Agent); // Emit the wrapped API, not the raw one Consumer.prototype._emitConnect = function () { - this.vfs.env = this.remoteEnv; this.emit("connect", this.vfs); }; diff --git a/package.json b/package.json index 384626b..3bb77d2 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ ], "name": "vfs-socket", "description": "A vfs helper library that communicates through a serialized socket", - "version": "0.3.12", + "version": "0.3.13", "repository": { "type": "git", "url": "git://github.com/c9/vfs-socket.git" From 40fcf145c9e43a9271b4cd89354e9f142a1bbf24 Mon Sep 17 00:00:00 2001 From: Ruben Daniels Date: Tue, 21 May 2013 18:33:59 +0200 Subject: [PATCH 2/3] * including the worker --- worker.js | 43 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/worker.js b/worker.js index 04811d2..8a4895a 100644 --- a/worker.js +++ b/worker.js @@ -30,6 +30,9 @@ function Worker(vfs) { // Endpoints for processes at meta.process kill: kill, + // Endpoints for processes at meta.pty + resize: resize, + // Endpoint for watchers at meta.watcher close: closeWatcher, @@ -59,6 +62,7 @@ function Worker(vfs) { watch: route("watch"), connect: route("connect"), spawn: route("spawn"), + pty: route("pty"), execFile: route("execFile"), extend: route("extend"), unextend: route("unextend"), @@ -162,9 +166,9 @@ function Worker(vfs) { stream.pause && stream.pause(); } }); - stream.on("end", function () { + stream.on("end", function (chunk) { delete streams[id]; - remote.onEnd(id); + remote.onEnd(id, chunk); nextStreamID = id; }); } @@ -179,7 +183,7 @@ function Worker(vfs) { return token; } - function storeProcess(process) { + function storeProcess(process, onlyPid) { var pid = process.pid; processes[pid] = process; process.on("exit", function (code, signal) { @@ -188,15 +192,20 @@ function Worker(vfs) { }); process.on("close", function () { delete processes[pid]; - delete streams[process.stdout.id]; - delete streams[process.stderr.id]; - delete streams[process.stdin.id]; + if (!onlyPid) { + delete streams[process.stdout.id]; + delete streams[process.stderr.id]; + delete streams[process.stdin.id]; + } remote.onProcessClose(pid); }); process.kill = function(code) { killtree(pid, code); }; + + if (onlyPid) + return pid; var token = {pid: pid}; token.stdin = storeStream(process.stdin); @@ -204,6 +213,14 @@ function Worker(vfs) { token.stderr = storeStream(process.stderr); return token; } + + function storePty(pty) { + var pid = storeProcess(pty, true); + var token = storeStream(pty); + token.pid = pid; + + return token; + } function killtree(pid, code) { childrenOfPid(pid, function(err, pidlist){ @@ -293,6 +310,15 @@ function Worker(vfs) { process.kill(code); } + function resize(pid, cols, rows) { + var process = processes[pid]; + if (!process) return; + + // Resize can throw + try { process.resize(cols, rows); } + catch(e) {}; + } + function closeWatcher(id) { var watcher = watchers[id]; if (!watcher) return; @@ -324,13 +350,13 @@ function Worker(vfs) { if (!stream) return; stream.emit("data", chunk); } - function onEnd(id) { + function onEnd(id, chunk) { var stream = proxyStreams[id]; if (!stream) return; // TODO: not delete proxy if close is going to be called later. // but somehow do delete proxy if close won't be called later. delete proxyStreams[id]; - stream.emit("end"); + stream.emit("end", chunk); } function onClose(id) { var stream = proxyStreams[id]; @@ -361,6 +387,7 @@ function Worker(vfs) { switch (key) { case "stream": token.stream = storeStream(meta.stream); break; case "process": token.process = storeProcess(meta.process); break; + case "pty": token.pty = storePty(meta.pty); break; case "watcher": token.watcher = storeWatcher(meta.watcher); break; case "api": token.api = storeApi(meta.api); break; default: token[key] = meta[key]; break; From 13e57932603bda7d4440b622c6b1a1394ad153c7 Mon Sep 17 00:00:00 2001 From: Ruben Daniels Date: Tue, 21 May 2013 18:38:23 +0200 Subject: [PATCH 3/3] * Reverted accidental change --- consumer.js | 1 + 1 file changed, 1 insertion(+) diff --git a/consumer.js b/consumer.js index 0c0e984..55dc12c 100644 --- a/consumer.js +++ b/consumer.js @@ -414,6 +414,7 @@ inherits(Consumer, Agent); // Emit the wrapped API, not the raw one Consumer.prototype._emitConnect = function () { + this.vfs.env = this.remoteEnv; this.emit("connect", this.vfs); };