@naanlang/naan 1.5.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +2 -2
- package/README.md +2 -2
- package/bin/index.js +7 -3
- package/dist/env_web.js +162 -20
- package/dist/naan.min.js +5 -5
- package/frameworks/browser/https_request.nlg +2 -2
- package/frameworks/browser/sworker.js +28 -26
- package/frameworks/browser/terminals.nlg +329 -693
- package/frameworks/browser/worker.nlg +255 -0
- package/frameworks/browser/workers.nlg +5 -5
- package/frameworks/browser/ws_client.nlg +15 -10
- package/frameworks/client/apiclient.nlg +181 -9
- package/frameworks/client/relaycon.nlg +87 -161
- package/frameworks/common/events.nlg +101 -0
- package/frameworks/common/repltools.nlg +80 -1
- package/frameworks/node/apiserver.nlg +39 -246
- package/frameworks/node/filesystem.nlg +31 -6
- package/frameworks/node/http_request.nlg +34 -13
- package/frameworks/node/https_request.nlg +8 -3
- package/frameworks/node/node.nlg +2 -0
- package/frameworks/node/pty.nlg +346 -0
- package/frameworks/node/worker.nlg +409 -539
- package/frameworks/node/ws_client.nlg +2 -2
- package/frameworks/project/build.nlg +1 -1
- package/frameworks/project/projects.nlg +1 -1
- package/frameworks/running/debugnub.nlg +17 -4
- package/frameworks/running/executors.nlg +27 -274
- package/frameworks/running/instances.nlg +393 -0
- package/frameworks/running/remote_req.nlg +143 -0
- package/frameworks/running/remote_res.nlg +89 -0
- package/frameworks/running/taskexec.nlg +2 -2
- package/frameworks/service/imp.nlg +736 -0
- package/frameworks/service/model.nlg +71 -0
- package/frameworks/service/nubnode.nlg +105 -0
- package/frameworks/service/nubweb.nlg +106 -0
- package/frameworks/service/service.nlg +28 -0
- package/lib/browser/env_web.js +169 -27
- package/lib/browser/env_webworker.js +91 -4
- package/lib/core/naanlib.js +5 -5
- package/lib/env_node.js +184 -8
- package/lib/env_nodeworker.js +74 -1
- package/package.json +1 -1
- package/plugins/serviceNexara/speechrec.nlg +10 -6
- package/test/test_02_context.nlg +24 -1
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* column positioning: // // !
|
|
8
8
|
*
|
|
9
|
-
* Copyright (c) 2019-
|
|
9
|
+
* Copyright (c) 2019-2026 by Richard C. Zulch
|
|
10
10
|
*
|
|
11
11
|
*/
|
|
12
12
|
|
|
@@ -18,6 +18,69 @@
|
|
|
18
18
|
gWorkers;
|
|
19
19
|
|
|
20
20
|
|
|
21
|
+
/*
|
|
22
|
+
* ioctl terminal control and events
|
|
23
|
+
*
|
|
24
|
+
* Example "raw" mode:
|
|
25
|
+
*
|
|
26
|
+
// rawTest
|
|
27
|
+
// echo typed keystrokes in BOLD until Control-C stops it.
|
|
28
|
+
//
|
|
29
|
+
closure rawTest(local dokey) {
|
|
30
|
+
dokey = xnew(function(msg, arg) {
|
|
31
|
+
if arg.key == "\x03" {
|
|
32
|
+
js.t.ioctl("raw", false)
|
|
33
|
+
js.t.ioctl_remove_listener("raw-key", dokey)
|
|
34
|
+
}
|
|
35
|
+
else
|
|
36
|
+
print("\x1b[1m${arg.key}\x1b[22m")
|
|
37
|
+
})
|
|
38
|
+
js.t.ioctl_add_listener("raw-key", dokey)
|
|
39
|
+
js.t.ioctl("raw", true)
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
rawTest();
|
|
43
|
+
*
|
|
44
|
+
*
|
|
45
|
+
* Example echo control:
|
|
46
|
+
*
|
|
47
|
+
js.t.ioctl("echo", 0) // no echo at all
|
|
48
|
+
js.t.ioctl("echo", 1) // echo newlines (best for hiding REPL commands)
|
|
49
|
+
js.t.ioctl("echo", 2) // normal echo
|
|
50
|
+
|
|
51
|
+
js.t.ioctl("sane") // restore echo and raw
|
|
52
|
+
*
|
|
53
|
+
*
|
|
54
|
+
* Example simulated keystrokes:
|
|
55
|
+
*
|
|
56
|
+
future(function(){ js.t.ioctl("keystroke", "joe") }, 10); // "joe" in keyboard buffer
|
|
57
|
+
*
|
|
58
|
+
*
|
|
59
|
+
* Example terminal resize notification:
|
|
60
|
+
*
|
|
61
|
+
doresize = xnew(function(msg, dim) { printline("(${dim.cols}, ${dim.rows})")})
|
|
62
|
+
js.t.ioctl_add_listener("term-resize", doresize);
|
|
63
|
+
*
|
|
64
|
+
*
|
|
65
|
+
* Example terminal connection notification:
|
|
66
|
+
*
|
|
67
|
+
// add removable listener:
|
|
68
|
+
listener = xnew(function(msg,arg) { debuglog("listener:", msg, arg) });
|
|
69
|
+
js.t.ioctl_add_listener("term-attach", listener);
|
|
70
|
+
js.t.ioctl_add_listener("term-detach", listener);
|
|
71
|
+
|
|
72
|
+
// remove the listeners:
|
|
73
|
+
js.t.ioctl_remove_listener("term-attach", listener);
|
|
74
|
+
js.t.ioctl_remove_listener("term-detach", listener);
|
|
75
|
+
*
|
|
76
|
+
* Note that js.t.ioctl(...) controls the *terminal* even if attached to a different instance. But
|
|
77
|
+
* ioctl event listeners are attached to an *instance* regardless of what terminal is connected.
|
|
78
|
+
* But in general it does the "right thing" for multiple terminals on a single instance, and when
|
|
79
|
+
* switching among instances.
|
|
80
|
+
*
|
|
81
|
+
*/
|
|
82
|
+
|
|
83
|
+
|
|
21
84
|
/*
|
|
22
85
|
* TermHost
|
|
23
86
|
*
|
|
@@ -27,387 +90,95 @@ gWorkers;
|
|
|
27
90
|
* {
|
|
28
91
|
* type: <string> // target category, e.g. "Host", "api.yyy.com"
|
|
29
92
|
* workerID: <string> // kind of worker in server subsystem
|
|
30
|
-
* dispatcher: <tuple> // dispatcher function for incoming messages
|
|
31
93
|
* startup: <dictionary> // startup options
|
|
32
|
-
* clientID: <string> // (rare) our identification on client
|
|
33
|
-
* serverID: <string> // (rare) server subsystem for us
|
|
34
94
|
* }
|
|
35
95
|
*
|
|
36
96
|
*/
|
|
37
97
|
|
|
38
|
-
closure TermHost(track,
|
|
98
|
+
closure TermHost(track, name, options,
|
|
99
|
+
local relay, error, destID, target, xc)
|
|
39
100
|
{
|
|
40
|
-
global(
|
|
41
|
-
options = merge({
|
|
42
|
-
type: "Host"
|
|
43
|
-
workerID: "myDebugWorker"
|
|
44
|
-
clientID: "DebugWorkers"
|
|
45
|
-
serverID: "Workers"
|
|
46
|
-
}, options)
|
|
47
|
-
target = require("../running/executors.nlg").ExecutorBase(track, options.type, name)
|
|
48
|
-
nlregex = RegExp("\\n", "g")
|
|
49
|
-
target.workerID = options.workerID
|
|
50
|
-
target.msgQueue = []
|
|
51
|
-
target.dispatcher = call(options.dispatcher)
|
|
101
|
+
global(App)
|
|
52
102
|
|
|
53
|
-
//
|
|
103
|
+
// findHostInstance
|
|
54
104
|
//
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
// Connect with the host if not already connected.
|
|
65
|
-
closure connect(local url, pending) {
|
|
66
|
-
if target.ws
|
|
67
|
-
return(list(false, { connected: true }))
|
|
68
|
-
try {
|
|
69
|
-
url = xnew(window.URL, api.url)
|
|
70
|
-
} catch {
|
|
71
|
-
return(list(Error("invalid URL ${api.url}", exception)))
|
|
105
|
+
// Find the host instance name/type, or create new remote worker. The default for no name/type is
|
|
106
|
+
// the server itself.
|
|
107
|
+
//
|
|
108
|
+
function findHostInstance(relay, name, type, local error, found, dest, worker) {
|
|
109
|
+
`(error, found) = relay.clients()
|
|
110
|
+
if !error {
|
|
111
|
+
dest = found.find(function(item) { item.name == "NaanIDE Server" && item.type == "Server IMP" })
|
|
112
|
+
if !dest
|
|
113
|
+
error = Error("cannot locate host")
|
|
72
114
|
}
|
|
73
|
-
if
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
// onopen
|
|
81
|
-
// The WebSocket connection is now open.
|
|
82
|
-
target.ws.onopen = function onopen(e, local info, spawner) {
|
|
83
|
-
info = {
|
|
84
|
-
name: name
|
|
85
|
-
workerID: target.workerID
|
|
115
|
+
if !error
|
|
116
|
+
`(error, found) = relay.clients(dest.destID)
|
|
117
|
+
if !error {
|
|
118
|
+
if name && type {
|
|
119
|
+
dest = found.find(function(item) { item.name == name && item.type == type })
|
|
120
|
+
if dest
|
|
121
|
+
return (list(false, dest.destID)) // found worker
|
|
86
122
|
}
|
|
87
|
-
if
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
spawner = new(options.startup) || { }
|
|
94
|
-
spawner.name = name
|
|
95
|
-
sendControl("spawn", spawner)
|
|
96
|
-
pending.signal(list(false, { ok: true }))
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// onmessage
|
|
100
|
-
// A message was received from the worker via WebSockets.
|
|
101
|
-
target.ws.onmessage = function onmessage(e, message, local msg) {
|
|
102
|
-
try {
|
|
103
|
-
message = new(window.JSON.parse(e.data))
|
|
104
|
-
} catch {
|
|
105
|
-
if true {
|
|
106
|
-
debuglog("can't decode incoming ws message:", exception)
|
|
107
|
-
return }
|
|
123
|
+
if !name || !type { // find main instance
|
|
124
|
+
dest = found.find(function(item) { item.name == "NaanIDE Server" && item.type == "NaaN Server" })
|
|
125
|
+
if !dest
|
|
126
|
+
return (list(Error("cannot locate NaanIDE Server")))
|
|
127
|
+
else
|
|
128
|
+
return (list(false, dest.destID))
|
|
108
129
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
dispatcher(message) // request from Host
|
|
132
|
-
else if message.respOp || message.id
|
|
133
|
-
debuglog("unknown host response message:", message.respOp || message.id)
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// dispatcher
|
|
137
|
-
// Respond to a host request while preserving context to permit reply routing
|
|
138
|
-
closure dispatcher(message) {
|
|
139
|
-
target.dispatcher(message.payload.data, function(reply) {
|
|
140
|
-
target.ws.send(window.JSON.stringify({
|
|
141
|
-
guid: api.guid
|
|
142
|
-
clientID: message.clientID
|
|
143
|
-
serverID: message.serverID
|
|
144
|
-
workerID: message.workerID
|
|
145
|
-
respOp: "msgout"
|
|
146
|
-
payload: {
|
|
147
|
-
id: "targetout",
|
|
148
|
-
data: reply
|
|
149
|
-
}
|
|
150
|
-
}))
|
|
151
|
-
})
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// onerror
|
|
155
|
-
// An error occurred on the WebSocket connection.
|
|
156
|
-
// This can happen in normal operation when the connection times out.
|
|
157
|
-
target.ws.onerror = function onerror(e) {
|
|
158
|
-
pending.signal(list(Error("websocket failed", e)))
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
// onclose
|
|
162
|
-
// The WebSocket connection was closed.
|
|
163
|
-
target.ws.onclose = function onclose(e) {
|
|
164
|
-
if e.code != 1000 && e.code != 1001 && e.code != 1005 && e.code != 1006
|
|
165
|
-
debuglog("ws close:", e.code, e.reason)
|
|
166
|
-
target.execClosed(Error("socket closed", e.code, e.reason))
|
|
167
|
-
target.ws = false
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
pending.wait()
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
//
|
|
174
|
-
// hostWorkerUpdate
|
|
175
|
-
//
|
|
176
|
-
// New workers created/discovered on this host.
|
|
177
|
-
//
|
|
178
|
-
function hostWorkerUpdate(msg, local localID, worker) {
|
|
179
|
-
if msg.id == "spawned" {
|
|
180
|
-
if !findWorker(msg.workerID)
|
|
181
|
-
TermHost(track, api, msg.name, { type: options.type, workerID: msg.workerID })
|
|
182
|
-
}
|
|
183
|
-
else if msg.id == "termination"
|
|
184
|
-
track.delete(findWorker(msg.workerID))
|
|
185
|
-
else if msg.id == "workerlist" {
|
|
186
|
-
for `(localID, worker) in msg.workers
|
|
187
|
-
if !findWorker(localID)
|
|
188
|
-
TermHost(track, api, worker.name, { type: options.type, workerID: localID })
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
//
|
|
193
|
-
// hostWorkerMatch
|
|
194
|
-
//
|
|
195
|
-
// True iff the specified information matches us.
|
|
196
|
-
//
|
|
197
|
-
target.hostWorkerMatch = function hostWorkerMatch(testApi, testID) {
|
|
198
|
-
testApi === api && testID == target.workerID
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
//
|
|
202
|
-
// doMessage
|
|
203
|
-
//
|
|
204
|
-
// Process the specified undecoded message.
|
|
205
|
-
target.doMessage = function doMessage(msg) {
|
|
206
|
-
if msg.id == "textout" {
|
|
207
|
-
target.written = true
|
|
208
|
-
target.term.Write(msg.text.replace(nlregex, "\r\n")) }
|
|
209
|
-
else if msg.id == "debugtext" {
|
|
210
|
-
target.written = true
|
|
211
|
-
target.debugWrite(msg.text, msg.level) }
|
|
212
|
-
else if msg.id == "targetout"
|
|
213
|
-
target.execReceived(msg.data)
|
|
214
|
-
else if msg.id == "started"
|
|
215
|
-
{ }
|
|
216
|
-
else if msg.id == "typed"
|
|
217
|
-
target.term.Write(msg.text.replace(nlregex, "\r\n"))
|
|
218
|
-
else if msg.id == "status"
|
|
219
|
-
target.statusCB(target, msg.status)
|
|
220
|
-
else if msg.id == "debugout"
|
|
221
|
-
target.debugger.debugData(target, msg.data)
|
|
222
|
-
else
|
|
223
|
-
debuglog("unknown host worker message:", msg.id)
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
//
|
|
227
|
-
// sendControl
|
|
228
|
-
//
|
|
229
|
-
// Send a message to the worker controller.
|
|
230
|
-
|
|
231
|
-
target.sendControl = function sendControl(workerOp, payload) {
|
|
232
|
-
target.ws.send(window.JSON.stringify({
|
|
233
|
-
guid: api.guid
|
|
234
|
-
clientID: options.clientID
|
|
235
|
-
serverID: options.serverID
|
|
236
|
-
workerID: target.workerID
|
|
237
|
-
workerOp: workerOp
|
|
238
|
-
payload: payload
|
|
239
|
-
}))
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
//
|
|
243
|
-
// send
|
|
244
|
-
//
|
|
245
|
-
// Send a message to the worker.
|
|
246
|
-
|
|
247
|
-
target.send = function send(msg) {
|
|
248
|
-
sendControl("msgin", msg)
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
//
|
|
252
|
-
// oninterrupt
|
|
253
|
-
//
|
|
254
|
-
|
|
255
|
-
function oninterrupt() {
|
|
256
|
-
send({ // send interrupt to worker
|
|
257
|
-
id: "interrupt"
|
|
258
|
-
})
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
//
|
|
262
|
-
// onreturn
|
|
263
|
-
//
|
|
264
|
-
|
|
265
|
-
function onreturn(local text) {
|
|
266
|
-
text = target.term.TakeText()
|
|
267
|
-
echotext(text)
|
|
268
|
-
send({ // send user-entered text to worker
|
|
269
|
-
id: "keyline",
|
|
270
|
-
text: text
|
|
271
|
-
})
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
// echotext
|
|
275
|
-
//
|
|
276
|
-
// Echo text to other terminals.
|
|
277
|
-
|
|
278
|
-
function echotext(text) {
|
|
279
|
-
sendControl("echo", { // send user-entered text to worker
|
|
280
|
-
id: "typed",
|
|
281
|
-
text: "\x1b[90m\x1b[3m".concat(text, "\x1b[0m\n") // dark-grey, italic
|
|
282
|
-
})
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
// target.KeyText
|
|
286
|
-
//
|
|
287
|
-
// Send text to the worker, with optional echo to terminal.
|
|
288
|
-
|
|
289
|
-
target.KeyText = function KeyText(text, echo) {
|
|
290
|
-
if echo {
|
|
291
|
-
target.term.WriteLn(text.trim())
|
|
292
|
-
echotext(text.trim())
|
|
130
|
+
dest = found.find(function(item) { item.name == "NaanIDE Server" && item.type == "Node Remote" })
|
|
131
|
+
if !dest
|
|
132
|
+
return (list(Error("cannot locate NaanIDE Server Remote")))
|
|
133
|
+
`(error, xc) = relay.context(dest.destID)
|
|
134
|
+
if !error {
|
|
135
|
+
`(error) = xc.evalq(chns("node"))
|
|
136
|
+
if error
|
|
137
|
+
return (list(Error("cannot switch namespace", error)))
|
|
138
|
+
}
|
|
139
|
+
if !error
|
|
140
|
+
closure (options) {
|
|
141
|
+
`(error, worker) = xc.evalq(NobBot(options), `(options))
|
|
142
|
+
}({
|
|
143
|
+
name: name
|
|
144
|
+
type: options.type
|
|
145
|
+
startup: options.startup
|
|
146
|
+
topOriginID: App.imp.us.instanceID
|
|
147
|
+
})
|
|
148
|
+
if error
|
|
149
|
+
error = Error("cannot spawn remote instance", error)
|
|
150
|
+
else
|
|
151
|
+
return (list(false, worker.instanceID))
|
|
293
152
|
}
|
|
294
|
-
|
|
295
|
-
id: "keyline",
|
|
296
|
-
text: text
|
|
297
|
-
})
|
|
153
|
+
list(error)
|
|
298
154
|
}
|
|
299
155
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
// Post a message to the target.
|
|
304
|
-
//
|
|
305
|
-
|
|
306
|
-
target.PostMessage = function PostMessage(data, local result) {
|
|
307
|
-
result = connect()
|
|
308
|
-
if result.0
|
|
309
|
-
return (result)
|
|
310
|
-
send({ // send data to worker
|
|
311
|
-
id: "targetin",
|
|
312
|
-
data: data
|
|
313
|
-
})
|
|
314
|
-
list(false, { posted: true })
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
//
|
|
318
|
-
// target.DebugCmd
|
|
319
|
-
//
|
|
320
|
-
// Post a debug command to the target.
|
|
321
|
-
//
|
|
322
|
-
|
|
323
|
-
target.DebugCmd = function DebugCmd(data) {
|
|
324
|
-
connect()
|
|
325
|
-
send({ // send debug command to worker
|
|
326
|
-
id: "debugin",
|
|
327
|
-
data: data
|
|
328
|
-
})
|
|
329
|
-
}
|
|
156
|
+
options = merge({
|
|
157
|
+
type: "Host"
|
|
158
|
+
}, options)
|
|
330
159
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
else if (level >= 3)
|
|
344
|
-
target.term.WriteLn(text, target.term.Red) // light red for warnings
|
|
345
|
-
else if (level >= 2)
|
|
346
|
-
target.term.WriteLn(text, target.term.Green) // green for Naan.debug.debuglog logging
|
|
347
|
-
else
|
|
348
|
-
target.term.WriteLn(text, target.term.Red+target.term.Bold) // heavy red for errors
|
|
349
|
-
}
|
|
160
|
+
target = findIDEtarget(track, name, options.workerID)
|
|
161
|
+
if target
|
|
162
|
+
return (list(false, target)) // already exists
|
|
163
|
+
|
|
164
|
+
relay = require("naanlib:frameworks/client/relaycon.nlg").RelayCon(App.imp)
|
|
165
|
+
if options.workerID == "NideServer" // server main thread
|
|
166
|
+
`(error, destID) = findHostInstance(relay)
|
|
167
|
+
else
|
|
168
|
+
`(error, destID) = findHostInstance(relay, name, options.type)
|
|
169
|
+
relay.close()
|
|
170
|
+
if error
|
|
171
|
+
return (list(error))
|
|
350
172
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
target.termAttach = function termAttach(repl, db, statusCB, local msg) {
|
|
357
|
-
target.term = repl
|
|
358
|
-
target.debugger = db
|
|
359
|
-
target.statusCB = statusCB
|
|
360
|
-
if target.termSaved {
|
|
361
|
-
target.term.StateLoad(target.termSaved)
|
|
362
|
-
target.termSaved = false }
|
|
363
|
-
else
|
|
364
|
-
target.term.Reset()
|
|
365
|
-
target.debugger.attach(target)
|
|
366
|
-
while target.msgQueue.length > 0 {
|
|
367
|
-
for msg in target.msgQueue.splice(0) // all current messages
|
|
368
|
-
target.doMessage(msg)
|
|
369
|
-
}
|
|
370
|
-
target.msgQueue = false
|
|
371
|
-
target.term.On("interrupt", oninterrupt.proc)
|
|
372
|
-
target.term.On("return", onreturn.proc)
|
|
373
|
-
target.term.Focus()
|
|
374
|
-
connect() // ensure we are connected
|
|
375
|
-
target
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
//
|
|
379
|
-
// termDetach
|
|
380
|
-
//
|
|
381
|
-
// The terminal is being deattached from our instance.
|
|
382
|
-
|
|
383
|
-
target.termDetach = function termDetach(repl, db) {
|
|
384
|
-
target.term.On("interrupt")
|
|
385
|
-
target.term.On("return")
|
|
386
|
-
target.msgQueue = []
|
|
387
|
-
target.debugger.detach(target)
|
|
388
|
-
target.termSaved = target.term.StateSave()
|
|
389
|
-
target.term.Reset()
|
|
390
|
-
target.statusCB = false
|
|
391
|
-
target.debugger = false
|
|
392
|
-
target.term = false
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
// destroy
|
|
396
|
-
//
|
|
397
|
-
// Destroy the execution instance.
|
|
398
|
-
|
|
399
|
-
target.destroy = function destroy() {
|
|
400
|
-
track.delete(target)
|
|
401
|
-
termDetach()
|
|
402
|
-
sendControl("terminate", { })
|
|
403
|
-
target.ws.close(1000) // 1000: normal close
|
|
404
|
-
}
|
|
173
|
+
target = require("../running/instances.nlg").InTop(track, {
|
|
174
|
+
name: name
|
|
175
|
+
type: options.type
|
|
176
|
+
})
|
|
177
|
+
target.workerID = options.workerID
|
|
405
178
|
|
|
406
|
-
|
|
407
|
-
if
|
|
408
|
-
return (list(
|
|
409
|
-
track.add(target)
|
|
410
|
-
connect() // connect right away to start receiving messages
|
|
179
|
+
`(error) = target.open(destID)
|
|
180
|
+
if error
|
|
181
|
+
return (list(Error("cannot create InTop", error)))
|
|
411
182
|
|
|
412
183
|
// finis
|
|
413
184
|
|
|
@@ -424,14 +195,13 @@ closure TermHost(track, api, name, options, local target, nlregex, xtarg)
|
|
|
424
195
|
* {
|
|
425
196
|
* workerID: <string> // kind of worker in server subsystem
|
|
426
197
|
* // "NaanIDE" for local IDE
|
|
427
|
-
* // "NaanIDE-Debug" for browser debug target
|
|
428
198
|
* startup: <dictionary> // startup options
|
|
429
199
|
* type: <string> // (rare) target category, e.g. "Local"
|
|
430
200
|
* }
|
|
431
201
|
*
|
|
432
202
|
*/
|
|
433
203
|
|
|
434
|
-
closure TermLocal(track, name, options, local target,
|
|
204
|
+
closure TermLocal(track, name, options, local target, worker, inbot, error)
|
|
435
205
|
{
|
|
436
206
|
global(js, window, gWorkers)
|
|
437
207
|
if !dictionary(gWorkers)
|
|
@@ -442,293 +212,28 @@ closure TermLocal(track, name, options, local target, nlregex, listener)
|
|
|
442
212
|
if options.workerID == "NaanIDE" {
|
|
443
213
|
if !js.t
|
|
444
214
|
return (list(Error("Cannot access Local IDE executor")))
|
|
445
|
-
termInstallVirtualWatcher(track,
|
|
215
|
+
termInstallVirtualWatcher(track, window)
|
|
446
216
|
return (termIDE(track, name, options.workerID, js.t)) // connect to IDE execution instance itself
|
|
447
217
|
}
|
|
448
|
-
target = require("../running/executors.nlg").ExecutorBase(track, options.type, name)
|
|
449
|
-
nlregex = RegExp("\\n", "g")
|
|
450
|
-
target.workerID = options.workerID
|
|
451
|
-
target.msgQueue = []
|
|
452
|
-
if options.workerID == "NaanIDE-Debug" {
|
|
453
|
-
target.worker = window.open(window.location.href, "_blank")
|
|
454
|
-
target.worker.addEventListener("beforeunload", function(e) { // our target is closing
|
|
455
|
-
destroy()
|
|
456
|
-
})
|
|
457
|
-
window.addEventListener("beforeunload", function(e) { // we are closing
|
|
458
|
-
// ### tell target we are closing (if needed)
|
|
459
|
-
})
|
|
460
|
-
listener = window
|
|
461
|
-
target.guid = 1
|
|
462
|
-
} else {
|
|
463
|
-
if not window.Worker
|
|
464
|
-
return (list(Error("Local environment does not support workers")))
|
|
465
|
-
target.worker = xnew(window.Worker, "env_webworker.js")
|
|
466
|
-
listener = target.worker
|
|
467
|
-
target.guid = UUID()
|
|
468
|
-
}
|
|
469
|
-
gWorkers[target.guid] = target
|
|
470
218
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
listener.addEventListener("message", function(e, msg) {
|
|
475
|
-
msg = new(e.data)
|
|
476
|
-
if msg.id == "termination" {
|
|
477
|
-
destroy()
|
|
478
|
-
return }
|
|
479
|
-
else if msg.id != "targetout" && msg.id != "loaded" {
|
|
480
|
-
if msg.id == "status" {
|
|
481
|
-
target.lastStatus = milliseconds()
|
|
482
|
-
target.execSetStatus(msg.status)
|
|
483
|
-
}
|
|
484
|
-
if target.msgQueue {
|
|
485
|
-
if msg.id != "status"
|
|
486
|
-
target.msgQueue.push(msg)
|
|
487
|
-
return } }
|
|
488
|
-
target.doMessage(msg)
|
|
489
|
-
})
|
|
219
|
+
target = findIDEtarget(track, name, options.workerID)
|
|
220
|
+
if target
|
|
221
|
+
return (list(false, target)) // already exists
|
|
490
222
|
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
target.execClosed(Error("instance error", e.message))
|
|
223
|
+
worker = xnew(window.Worker, "env_webworker.js")
|
|
224
|
+
inbot = NubBot(worker, {
|
|
225
|
+
name: name
|
|
226
|
+
type: options.workerID
|
|
227
|
+
startup: options.startup
|
|
497
228
|
})
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
})
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
//
|
|
510
|
-
// onreturn
|
|
511
|
-
//
|
|
512
|
-
|
|
513
|
-
function onreturn() {
|
|
514
|
-
target.worker.postMessage({ // send user-entered text to worker
|
|
515
|
-
id: "keyline",
|
|
516
|
-
text: target.term.TakeText()
|
|
517
|
-
})
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
// target.KeyText
|
|
521
|
-
//
|
|
522
|
-
// Send text to the worker, with optional echo to terminal.
|
|
523
|
-
|
|
524
|
-
target.KeyText = function KeyText(text, echo) {
|
|
525
|
-
if echo
|
|
526
|
-
target.term.WriteLn(text.trim())
|
|
527
|
-
target.worker.postMessage({ // send text to worker
|
|
528
|
-
id: "keyline",
|
|
529
|
-
text: text
|
|
530
|
-
})
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
//
|
|
534
|
-
// doMessage
|
|
535
|
-
//
|
|
536
|
-
// Process the specified undecoded message.
|
|
537
|
-
|
|
538
|
-
target.doMessage = function doMessage(msg) {
|
|
539
|
-
if msg.id == "textout"
|
|
540
|
-
target.term.Write(msg.text.replace(nlregex, "\r\n"))
|
|
541
|
-
else if msg.id == "debugtext"
|
|
542
|
-
target.debugWrite(msg.text, msg.level)
|
|
543
|
-
else if msg.id == "targetout"
|
|
544
|
-
target.execReceived(msg.data)
|
|
545
|
-
else if msg.id == "status"
|
|
546
|
-
target.statusCB(target, msg.status)
|
|
547
|
-
else if msg.id == "debugout"
|
|
548
|
-
target.debugger.debugData(target, msg.data)
|
|
549
|
-
else if msg.id == "download"
|
|
550
|
-
FileDownload(xnew(window.File, msg.bits, msg.name, msg.options))
|
|
551
|
-
else if msg.id == "loaded" {
|
|
552
|
-
if !target.started
|
|
553
|
-
target.worker.postMessage({
|
|
554
|
-
id: "start",
|
|
555
|
-
state: false // resume state, if we have any
|
|
556
|
-
altcmd: options.startup.initcmds
|
|
557
|
-
workerID: target.workerID
|
|
558
|
-
workerGUID: target.guid
|
|
559
|
-
})
|
|
560
|
-
target.started = true
|
|
561
|
-
} else if msg.id == "targetsend" {
|
|
562
|
-
msg.data._guid = target.guid
|
|
563
|
-
js.t.DispatchMessage(msg.data)
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
//
|
|
568
|
-
// target.DebugCmd
|
|
569
|
-
//
|
|
570
|
-
// Post a debug command to the target.
|
|
571
|
-
//
|
|
572
|
-
|
|
573
|
-
target.DebugCmd = function DebugCmd(data) {
|
|
574
|
-
target.worker.postMessage({ // send data to worker
|
|
575
|
-
id: "debugin"
|
|
576
|
-
data: data
|
|
577
|
-
})
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
//
|
|
581
|
-
// target.PostMessage
|
|
582
|
-
//
|
|
583
|
-
// Post a message to the target, if it has registered a listener.
|
|
584
|
-
//
|
|
585
|
-
|
|
586
|
-
target.PostMessage = function PostMessage(data) {
|
|
587
|
-
target.worker.postMessage({ // send data to worker
|
|
588
|
-
id: "targetin",
|
|
589
|
-
data: data
|
|
590
|
-
})
|
|
591
|
-
list(false, { posted: true })
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
//
|
|
595
|
-
// target.debugWrite
|
|
596
|
-
//
|
|
597
|
-
// Write a debug message to the repl.
|
|
598
|
-
//
|
|
599
|
-
|
|
600
|
-
target.debugWrite = function(text, level) {
|
|
601
|
-
text = text.replaceAll("\n", "\r\n")
|
|
602
|
-
if (level >= 5)
|
|
603
|
-
target.term.WriteLn(text, target.term.Cyan) // cyan for builtin logging
|
|
604
|
-
else if (level >= 4)
|
|
605
|
-
target.term.WriteLn(text, target.term.Blue) // blue for Naan function logging
|
|
606
|
-
else if (level >= 3)
|
|
607
|
-
target.term.WriteLn(text, target.term.Red) // light red for warnings
|
|
608
|
-
else if (level >= 2)
|
|
609
|
-
target.term.WriteLn(text, target.term.Green) // green for Naan.debug.debuglog logging
|
|
610
|
-
else
|
|
611
|
-
target.term.WriteLn(text, target.term.Red+target.term.Bold) // heavy red for errors
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
//
|
|
615
|
-
// termAttach
|
|
616
|
-
//
|
|
617
|
-
// A terminal was attached to our instance.
|
|
618
|
-
|
|
619
|
-
target.termAttach = function termAttach(repl, db, statusCB, local msg) {
|
|
620
|
-
target.term = repl
|
|
621
|
-
target.debugger = db
|
|
622
|
-
target.statusCB = statusCB
|
|
623
|
-
if target.termSaved {
|
|
624
|
-
target.term.StateLoad(target.termSaved)
|
|
625
|
-
target.termSaved = false }
|
|
626
|
-
else
|
|
627
|
-
target.term.Reset()
|
|
628
|
-
target.debugger.attach(target)
|
|
629
|
-
while target.msgQueue.length > 0 {
|
|
630
|
-
for msg in target.msgQueue.splice(0) // all current messages
|
|
631
|
-
target.doMessage(msg)
|
|
632
|
-
}
|
|
633
|
-
target.msgQueue = false
|
|
634
|
-
target.term.On("interrupt", oninterrupt.proc)
|
|
635
|
-
target.term.On("return", onreturn.proc)
|
|
636
|
-
target.term.Focus()
|
|
637
|
-
target
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
//
|
|
641
|
-
// termDetach
|
|
642
|
-
//
|
|
643
|
-
// The terminal is being deattached from our instance.
|
|
644
|
-
|
|
645
|
-
target.termDetach = function termDetach() {
|
|
646
|
-
target.term.On("interrupt")
|
|
647
|
-
target.term.On("return")
|
|
648
|
-
target.msgQueue = []
|
|
649
|
-
target.debugger.detach(target)
|
|
650
|
-
target.termSaved = target.term.StateSave()
|
|
651
|
-
target.statusCB = false
|
|
652
|
-
target.debugger = false
|
|
653
|
-
target.term = false
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
// destroy
|
|
657
|
-
//
|
|
658
|
-
// Destroy the execution instance.
|
|
659
|
-
|
|
660
|
-
target.destroy = function destroy() {
|
|
661
|
-
gWorkers[target.guid] = undefined
|
|
662
|
-
target.execClosed(Error("instance destroyed"))
|
|
663
|
-
track.delete(target)
|
|
664
|
-
termDetach()
|
|
665
|
-
target.worker.terminate() // kill without saving
|
|
666
|
-
target.worker = false
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
track.add(target)
|
|
670
|
-
|
|
671
|
-
// finis
|
|
672
|
-
|
|
673
|
-
list(false, target)
|
|
674
|
-
};
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
/*
|
|
678
|
-
* WorkerConnect
|
|
679
|
-
*
|
|
680
|
-
* Return the existing web worker for a workerGUID, or false if it does not exist.
|
|
681
|
-
*
|
|
682
|
-
*/
|
|
683
|
-
|
|
684
|
-
function WorkerConnect(workerGUID) {
|
|
685
|
-
gWorkers[workerGUID]
|
|
686
|
-
};
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
/*
|
|
690
|
-
* termMainProxy
|
|
691
|
-
*
|
|
692
|
-
* Make a browser proxy representing the main thread. This runs inside the worker and allows it
|
|
693
|
-
* to do remote execution with Main.
|
|
694
|
-
*
|
|
695
|
-
*/
|
|
696
|
-
|
|
697
|
-
closure termMainProxy(track, name, options, local target) {
|
|
698
|
-
global(js)
|
|
699
|
-
target = require("../running/executors.nlg").ExecutorBase(track, "mainProxy", name)
|
|
700
|
-
target.name = name
|
|
701
|
-
|
|
702
|
-
//
|
|
703
|
-
// target.PostMessage
|
|
704
|
-
//
|
|
705
|
-
// Post a message to the main thread.
|
|
706
|
-
//
|
|
707
|
-
target.PostMessage = function PostMessage(data) {
|
|
708
|
-
js.t.DispatchMessage(data)
|
|
709
|
-
list(false, { posted: true })
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
//
|
|
713
|
-
// onreceive
|
|
714
|
-
//
|
|
715
|
-
// Process a received message from the main thread, typically in response.
|
|
716
|
-
//
|
|
717
|
-
function onreceive(data) {
|
|
718
|
-
target.execReceived(data)
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
// destroy
|
|
722
|
-
//
|
|
723
|
-
// Destroy the execution instance.
|
|
724
|
-
//
|
|
725
|
-
target.destroy = function destroy() {
|
|
726
|
-
target.execClosed(Error("instance destroyed"))
|
|
727
|
-
track.delete(target)
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
js.t.OnReceive(onreceive.proc)
|
|
731
|
-
track.add(target)
|
|
229
|
+
target = require("../running/instances.nlg").InTop(track, {
|
|
230
|
+
name: name
|
|
231
|
+
type: options.type
|
|
232
|
+
workerID: options.workerID
|
|
233
|
+
})
|
|
234
|
+
`(error) = target.open(inbot.instanceID)
|
|
235
|
+
if error
|
|
236
|
+
return (list(Error("cannot create InTop", error)))
|
|
732
237
|
|
|
733
238
|
// finis
|
|
734
239
|
|
|
@@ -736,31 +241,6 @@ closure termMainProxy(track, name, options, local target) {
|
|
|
736
241
|
};
|
|
737
242
|
|
|
738
243
|
|
|
739
|
-
/*
|
|
740
|
-
* WorkerToMain
|
|
741
|
-
*
|
|
742
|
-
* Connect our worker to the main thread, returning a result tuple with an executor representing
|
|
743
|
-
* Main. Use this to create a context object for Main, allowing remote evaluation.
|
|
744
|
-
*
|
|
745
|
-
*/
|
|
746
|
-
|
|
747
|
-
closure WorkerToMain(local nideRunning, track) {
|
|
748
|
-
// mainProxy -- link tracker to main thread proxy
|
|
749
|
-
function mainProxy(track, name, options) {
|
|
750
|
-
termMainProxy(track, name, options)
|
|
751
|
-
}
|
|
752
|
-
|
|
753
|
-
if !js.s {
|
|
754
|
-
error = Error("WorkerToMain only available in browser workers")
|
|
755
|
-
return (list(error))
|
|
756
|
-
}
|
|
757
|
-
nideRunning = require("naanlib:frameworks/running/executors.nlg")
|
|
758
|
-
track = nideRunning.ExecutorTracker()
|
|
759
|
-
track.register(mainProxy, "proxy")
|
|
760
|
-
track.spawn("proxy") // returns result tuple
|
|
761
|
-
};
|
|
762
|
-
|
|
763
|
-
|
|
764
244
|
/*
|
|
765
245
|
* findIDEtarget
|
|
766
246
|
*
|
|
@@ -806,6 +286,7 @@ closure termIDE(track, name, workerID, naancont, title, local target, connected)
|
|
|
806
286
|
target.title = title
|
|
807
287
|
target.workerID = workerID
|
|
808
288
|
target.naancont = naancont
|
|
289
|
+
naancont.ioctl_open(ioctl_callback.proc)
|
|
809
290
|
connected = []
|
|
810
291
|
|
|
811
292
|
// replyHook
|
|
@@ -820,6 +301,20 @@ closure termIDE(track, name, workerID, naancont, title, local target, connected)
|
|
|
820
301
|
})
|
|
821
302
|
}
|
|
822
303
|
|
|
304
|
+
// ioctl_callback
|
|
305
|
+
//
|
|
306
|
+
// Ioctl from our instance.
|
|
307
|
+
//
|
|
308
|
+
function ioctl_callback(op, arg) { // where ioctls go when they have nowhere to go
|
|
309
|
+
debuglog("no-terminal ioctl:", op, arg)
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// ioctl_event
|
|
313
|
+
//
|
|
314
|
+
target.ioctl_event = function ioctl_event(msg, arg) {
|
|
315
|
+
naancont.ioctl_event(msg, arg)
|
|
316
|
+
}
|
|
317
|
+
|
|
823
318
|
// target.DebugCmd
|
|
824
319
|
//
|
|
825
320
|
// Post a debug command to the target, ourselves.
|
|
@@ -841,15 +336,16 @@ closure termIDE(track, name, workerID, naancont, title, local target, connected)
|
|
|
841
336
|
//
|
|
842
337
|
// Create a closure for an attaching terminal.
|
|
843
338
|
//
|
|
844
|
-
target.termAttach = closure termAttach(term, db,
|
|
339
|
+
target.termAttach = closure termAttach(term, db, notify, local connection, jsterm, inbound) {
|
|
845
340
|
connection = new(object, this)
|
|
341
|
+
jsterm = term.jsAcquire() // termIDE must be direct
|
|
846
342
|
|
|
847
343
|
function oninterrupt() {
|
|
848
344
|
naancont.Interrupt(inbound)
|
|
849
345
|
}
|
|
850
346
|
|
|
851
347
|
function onreturn() {
|
|
852
|
-
naancont.Return(
|
|
348
|
+
naancont.Return(jsterm.TakeText(), inbound)
|
|
853
349
|
}
|
|
854
350
|
|
|
855
351
|
function onstatus(status) {
|
|
@@ -867,7 +363,7 @@ closure termIDE(track, name, workerID, naancont, title, local target, connected)
|
|
|
867
363
|
|
|
868
364
|
connection.KeyText = function KeyText(text, echo) { // send text to instance
|
|
869
365
|
if echo
|
|
870
|
-
|
|
366
|
+
jsterm.WriteLn(text.trim()) // echo to terminal
|
|
871
367
|
naancont.Return(text, inbound)
|
|
872
368
|
}
|
|
873
369
|
|
|
@@ -877,16 +373,15 @@ closure termIDE(track, name, workerID, naancont, title, local target, connected)
|
|
|
877
373
|
}
|
|
878
374
|
|
|
879
375
|
connection.WriteLn = function WriteLn(text) {
|
|
880
|
-
|
|
376
|
+
jsterm.WriteLn(text)
|
|
881
377
|
}
|
|
882
378
|
|
|
883
379
|
connection.termDetach = function termDetach() { // disconnect the terminal
|
|
884
380
|
db.detach(target)
|
|
885
|
-
term.On("interrupt")
|
|
886
|
-
term.On("return")
|
|
887
381
|
if inbound
|
|
888
382
|
naancont.Detach(inbound)
|
|
889
383
|
connected = connected.filter(function(conn) { conn !== connection })
|
|
384
|
+
term.jsRelease()
|
|
890
385
|
}
|
|
891
386
|
|
|
892
387
|
connection.popup = true // we can handle multiple terminals
|
|
@@ -894,15 +389,15 @@ closure termIDE(track, name, workerID, naancont, title, local target, connected)
|
|
|
894
389
|
let (replstate) {
|
|
895
390
|
replstate = naancont.StateGet()
|
|
896
391
|
if (replstate)
|
|
897
|
-
|
|
392
|
+
jsterm.StateLoad(replstate)
|
|
898
393
|
else
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
394
|
+
jsterm.Reset()
|
|
395
|
+
jsterm.On("interrupt", oninterrupt.proc)
|
|
396
|
+
jsterm.On("return", onreturn.proc)
|
|
397
|
+
jsterm.Focus()
|
|
903
398
|
inbound = xnew({
|
|
904
|
-
OnMessage:
|
|
905
|
-
StateSave:
|
|
399
|
+
OnMessage: jsterm.OnMessage
|
|
400
|
+
StateSave: jsterm.StateSave
|
|
906
401
|
OnStatus: onstatus.proc
|
|
907
402
|
OnMessageOut: onmessageout.proc
|
|
908
403
|
OnDebugOut: ondebugout.proc
|
|
@@ -913,7 +408,33 @@ closure termIDE(track, name, workerID, naancont, title, local target, connected)
|
|
|
913
408
|
connected.push(connection)
|
|
914
409
|
db.attach(target)
|
|
915
410
|
} ()
|
|
916
|
-
|
|
411
|
+
|
|
412
|
+
naancont.ioctl_open(function (op, arg) {
|
|
413
|
+
if op == "sane"
|
|
414
|
+
jsterm.Sane()
|
|
415
|
+
else if op == "raw" {
|
|
416
|
+
if arg // enable raw mode
|
|
417
|
+
jsterm.OnRaw(function(str, origin) {
|
|
418
|
+
ioctl_event("raw-key", {
|
|
419
|
+
key: str
|
|
420
|
+
origin: origin
|
|
421
|
+
})
|
|
422
|
+
})
|
|
423
|
+
else // else disable raw
|
|
424
|
+
jsterm.OnRaw()
|
|
425
|
+
} else if op == "keystroke"
|
|
426
|
+
jsterm.PutKey(arg) // simulate a keystroke
|
|
427
|
+
else if op == "echo"
|
|
428
|
+
jsterm.EchoSet(arg) // echo: 0, 1, 2
|
|
429
|
+
})
|
|
430
|
+
|
|
431
|
+
jsterm.OnResize(function(columns, rows) {
|
|
432
|
+
ioctl_event("term-resize", {
|
|
433
|
+
cols: columns
|
|
434
|
+
rows: rows
|
|
435
|
+
})
|
|
436
|
+
})
|
|
437
|
+
|
|
917
438
|
// finis
|
|
918
439
|
connection
|
|
919
440
|
}
|
|
@@ -923,7 +444,9 @@ closure termIDE(track, name, workerID, naancont, title, local target, connected)
|
|
|
923
444
|
// Update the naan controller on this target, which means updating for all the terminals.
|
|
924
445
|
//
|
|
925
446
|
target.updateController = function updateController(newnc, local conn) {
|
|
447
|
+
naancont.ioctl_close()
|
|
926
448
|
naancont = newnc
|
|
449
|
+
naancont.ioctl_open(ioctl_callback.proc)
|
|
927
450
|
target.naancont = newnc
|
|
928
451
|
for conn in connected {
|
|
929
452
|
if naancont {
|
|
@@ -946,6 +469,7 @@ closure termIDE(track, name, workerID, naancont, title, local target, connected)
|
|
|
946
469
|
conn.WriteLn("\x1b[90m\x1b[3m".concat("\ntarget closed", "\x1b[0m"))
|
|
947
470
|
}
|
|
948
471
|
target.execReset()
|
|
472
|
+
naancont.ioctl_close()
|
|
949
473
|
target.naancont = naancont = false
|
|
950
474
|
}
|
|
951
475
|
|
|
@@ -1033,6 +557,120 @@ closure termInstallVirtualWatcher(track, naancont) {
|
|
|
1033
557
|
};
|
|
1034
558
|
|
|
1035
559
|
|
|
560
|
+
/*
|
|
561
|
+
* testTab
|
|
562
|
+
*
|
|
563
|
+
* Quick test of the InTop/InBot connection.
|
|
564
|
+
*
|
|
565
|
+
*/
|
|
566
|
+
|
|
567
|
+
closure testTab(destID,
|
|
568
|
+
local comMod, relay, error, found, dest, xc, inbotDestID, intop) {
|
|
569
|
+
|
|
570
|
+
// findBottomID
|
|
571
|
+
//
|
|
572
|
+
// Find the inbot destID that goes with our desired workerID.
|
|
573
|
+
//
|
|
574
|
+
function findBottomID(found, workerID, local item) {
|
|
575
|
+
for item in found
|
|
576
|
+
if item.name == "Play" && item.type == workerID
|
|
577
|
+
return (item.destID)
|
|
578
|
+
false
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
comMod = require("naanlib:frameworks/client/relaycon.nlg")
|
|
582
|
+
relay = comMod.RelayCon(App.imp)
|
|
583
|
+
`(error, found) = relay.clients(destID)
|
|
584
|
+
dest = found.find(function(item) { item.name == "NaanIDE" && item.services.indexOf("naan-remote-responder") >= 0 })
|
|
585
|
+
if !dest
|
|
586
|
+
return (list(Error("cannot locate remoting")))
|
|
587
|
+
`(error, xc)= relay.context(dest.destID)
|
|
588
|
+
if error
|
|
589
|
+
return (list(Error("cannot access remoting", error)))
|
|
590
|
+
inbotDestID = findBottomID(found, "Webworker-Play")
|
|
591
|
+
if !inbotDestID
|
|
592
|
+
return (list(Error("cannot find web worker")))
|
|
593
|
+
intop = require("../running/instances.nlg").InTop(App.nide.track, {
|
|
594
|
+
name: "NaanIDE-Play"
|
|
595
|
+
type: "Relay"
|
|
596
|
+
})
|
|
597
|
+
`(error) = intop.open(inbotDestID)
|
|
598
|
+
if error
|
|
599
|
+
return (list(Error("cannot create InTop", error)))
|
|
600
|
+
list(false, xc, intop)
|
|
601
|
+
};
|
|
602
|
+
|
|
603
|
+
|
|
604
|
+
/*
|
|
605
|
+
* relayTab
|
|
606
|
+
*
|
|
607
|
+
* Open a relay tab for the first peer NaanIDE found on the same server.
|
|
608
|
+
*
|
|
609
|
+
*/
|
|
610
|
+
|
|
611
|
+
closure relayTab(destID, local comMod, relay, error, found, dest, xc, reterm, originID, inbot) {
|
|
612
|
+
|
|
613
|
+
// remoteFindTerm
|
|
614
|
+
//
|
|
615
|
+
// Executes on remote to give us a (proxy) terminal.
|
|
616
|
+
//
|
|
617
|
+
function remoteFindTerm(name, workerID, local target) {
|
|
618
|
+
for target in App.nide.track.enumlist()
|
|
619
|
+
if target.name == name && target.workerID == workerID
|
|
620
|
+
return (target)
|
|
621
|
+
false
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
comMod = require("naanlib:frameworks/client/relaycon.nlg")
|
|
625
|
+
relay = comMod.RelayCon(App.imp)
|
|
626
|
+
if !destID {
|
|
627
|
+
`(error, found) = relay.clients()
|
|
628
|
+
if !error {
|
|
629
|
+
dest = found.find(function(item) { item.name == "NaanIDE Server" && item.type == "Server IMP" })
|
|
630
|
+
if !dest
|
|
631
|
+
error = Error("cannot locate server")
|
|
632
|
+
}
|
|
633
|
+
if !error
|
|
634
|
+
`(error, found) = relay.clients(dest.destID)
|
|
635
|
+
if !error {
|
|
636
|
+
dest = found.find(function(item) { item.name == "NaanIDE"
|
|
637
|
+
&& item.type == "Client IMP" && item.destID != App.imp.us.instanceID })
|
|
638
|
+
if !dest
|
|
639
|
+
error = Error("cannot locate peer tab")
|
|
640
|
+
else
|
|
641
|
+
destID = dest.destID
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
if error
|
|
645
|
+
return (list(Error("cannot locate target", error)))
|
|
646
|
+
`(error, xc) = relay.context(destID)
|
|
647
|
+
if error
|
|
648
|
+
return (list(Error("cannot access remoting", error)))
|
|
649
|
+
`(error) = xc.evalq(chns("browser"))
|
|
650
|
+
if error
|
|
651
|
+
return (list(Error("cannot switch namespace", error)))
|
|
652
|
+
`(error, reterm) = xc.evalq(remoteFindTerm("NaanIDE", "NaanIDE"), `(remoteFindTerm))
|
|
653
|
+
if error
|
|
654
|
+
return (list(Error("cannot get remote terminal", error)))
|
|
655
|
+
originID = App.imp.us.instanceID
|
|
656
|
+
`(error, inbot) = xc.evalq(InBot(window, {
|
|
657
|
+
name: "inbot"
|
|
658
|
+
type: reterm.workerID
|
|
659
|
+
topOriginID: originID
|
|
660
|
+
}), `(reterm, originID))
|
|
661
|
+
if error
|
|
662
|
+
return (list(Error("cannot create inBot", error)))
|
|
663
|
+
intop = require("../running/instances.nlg").InTop(App.nide.track, {
|
|
664
|
+
name: "NaanIDE Relay"
|
|
665
|
+
type: "Relay"
|
|
666
|
+
})
|
|
667
|
+
`(error) = intop.open(inbot.instanceID)
|
|
668
|
+
if error
|
|
669
|
+
return (list(Error("cannot create InTop", error)))
|
|
670
|
+
list(false, xc, intop)
|
|
671
|
+
};
|
|
672
|
+
|
|
673
|
+
|
|
1036
674
|
/*
|
|
1037
675
|
* termInit
|
|
1038
676
|
*
|
|
@@ -1041,15 +679,13 @@ closure termInstallVirtualWatcher(track, naancont) {
|
|
|
1041
679
|
*/
|
|
1042
680
|
|
|
1043
681
|
function termInit(local manifest) {
|
|
1044
|
-
manifest = `(TermHost, TermLocal,
|
|
1045
|
-
termIDE, termInstallVirtualWatcher, termInit)
|
|
682
|
+
manifest = `(TermHost, TermLocal,
|
|
683
|
+
findIDEtarget, termIDE, termInstallVirtualWatcher, testTab, relayTab, termInit)
|
|
1046
684
|
|
|
1047
685
|
Naan.module.build(module.id, "terminals", function(modobj, compobj) {
|
|
1048
|
-
require("./
|
|
686
|
+
require("./worker.nlg")
|
|
1049
687
|
compobj.manifest = manifest
|
|
1050
688
|
modobj.exports.TermLocal = TermLocal
|
|
1051
689
|
modobj.exports.TermHost = TermHost
|
|
1052
|
-
modobj.exports.WorkerConnect = WorkerConnect
|
|
1053
|
-
modobj.exports.WorkerToMain = WorkerToMain
|
|
1054
690
|
})
|
|
1055
691
|
} ();
|