-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathcmdl_repl.js
More file actions
114 lines (100 loc) · 3.27 KB
/
cmdl_repl.js
File metadata and controls
114 lines (100 loc) · 3.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
// A generic REPL for command-line runtimes. It uses a CMDL and serves modules
// from a dedicated HTTP server.
/*jslint node */
import http from "node:http";
import make_cmdl from "./cmdl.js";
import make_repl from "./repl.js";
// This should be "localhost", but we force IPv4 because, on Windows, Node.js
// seems unwilling to connect to Deno over IPv6.
const http_server_hostname = "127.0.0.1";
function make_cmdl_repl(capabilities, make_command, env) {
let repl;
// An HTTP server serves modules to the padawan, which imports them via the
// dynamic 'import' function. As such, the padawan is expected to support HTTP
// imports.
let http_server;
let http_server_port;
const cmdl = make_cmdl(
function spawn_padawan(tcp_host) {
const http_host = http_server_hostname + ":" + http_server_port;
return make_command(tcp_host, http_host).then(function (command) {
return capabilities.spawn(command, env, [tcp_host, http_host]);
});
},
function on_stdout(buffer) {
return capabilities.out(buffer.toString());
},
function on_stderr(buffer) {
return capabilities.err(buffer.toString());
}
);
function on_start() {
http_server = http.createServer(function (req, res) {
return repl.serve(
new URL(req.url, "http://" + req.host).href,
req.headers
).then(function ({body, headers}) {
Object.entries(headers).forEach(function ([key, value]) {
res.setHeader(key, value);
});
res.end(body);
}).catch(function fail(reason) {
capabilities.err(reason.stack + "\n");
res.statusCode = 500;
return res.end();
});
});
return Promise.all([
new Promise(function start_http_server(resolve, reject) {
http_server.on("error", reject);
return http_server.listen(0, http_server_hostname, function () {
http_server_port = http_server.address().port;
return resolve();
});
}),
cmdl.create()
]);
}
function on_eval(
on_result,
produce_script,
dynamic_specifiers,
import_specifiers,
wait
) {
return cmdl.eval(
produce_script(dynamic_specifiers),
import_specifiers,
wait
).then(function (report) {
return on_result(report.evaluation, report.exception);
});
}
function on_stop() {
return Promise.all([
new Promise(function (resolve) {
return http_server.close(resolve);
}),
cmdl.destroy()
]);
}
function specify(locator) {
return (
locator.startsWith("file:///")
? (
"http://" + http_server_hostname + ":" + http_server_port
+ locator.replace("file://", "")
)
: locator
);
}
repl = make_repl(
capabilities,
on_start,
on_eval,
on_stop,
specify
);
return repl;
}
export default Object.freeze(make_cmdl_repl);