@naanlang/naan 1.5.0 → 1.7.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 -48
- package/dist/naan.min.js +11 -11
- package/frameworks/browser/https_request.nlg +2 -2
- package/frameworks/browser/sworker.js +28 -26
- package/frameworks/browser/terminals.nlg +295 -737
- package/frameworks/browser/worker.nlg +295 -0
- package/frameworks/browser/workers.nlg +6 -6
- package/frameworks/browser/ws_client.nlg +15 -10
- package/frameworks/client/apiclient.nlg +211 -9
- package/frameworks/client/psm_client.nlg +10 -14
- package/frameworks/client/relaycon.nlg +87 -161
- package/frameworks/common/common.nlg +2 -0
- package/frameworks/common/events.nlg +101 -0
- package/frameworks/common/repltools.nlg +80 -1
- package/frameworks/node/apiserver.nlg +38 -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 +3 -0
- package/frameworks/node/pty.nlg +346 -0
- package/frameworks/node/shell.nlg +26 -3
- package/frameworks/node/worker.nlg +504 -560
- package/frameworks/node/ws_client.nlg +2 -2
- package/frameworks/project/build.nlg +56 -14
- package/frameworks/project/projects.nlg +1 -1
- package/frameworks/running/debugcom.nlg +20 -3
- package/frameworks/running/debugnub.nlg +33 -11
- package/frameworks/running/executors.nlg +40 -285
- package/frameworks/running/instances.nlg +394 -0
- package/frameworks/running/remote_req.nlg +139 -0
- package/frameworks/running/remote_res.nlg +89 -0
- package/frameworks/running/sourcecode.nlg +3 -2
- package/frameworks/running/taskexec.nlg +16 -59
- package/frameworks/service/imp.nlg +751 -0
- package/frameworks/service/model.nlg +71 -0
- package/frameworks/service/nubnode.nlg +136 -0
- package/frameworks/service/nubweb.nlg +124 -0
- package/frameworks/service/service.nlg +28 -0
- package/frameworks/storage/file_manager.nlg +3 -2
- package/lib/browser/env_web.js +169 -55
- package/lib/browser/env_webworker.js +89 -31
- package/lib/core/naanlib.js +11 -11
- package/lib/env_node.js +186 -27
- package/lib/env_nodeworker.js +82 -44
- package/lib/node_server_init.nlg +149 -0
- package/lib/node_worker.js +36 -0
- package/lib/node_worker_init.nlg +43 -0
- package/package.json +1 -1
- package/plugins/openSearch/openSearch.nlg +3 -2
- package/plugins/openSearch/os_dynamo.nlg +3 -2
- package/plugins/serviceAws/aws_cloudwatchlogs.nlg +44 -2
- package/plugins/serviceAws/aws_dynamo.nlg +144 -63
- package/plugins/serviceAws/aws_utils.nlg +6 -11
- package/plugins/serviceAws/serviceAws.nlg +3 -2
- package/plugins/serviceNexara/speechrec.nlg +10 -6
- package/test/test_01_core.nlg +2 -2
- package/test/test_02_context.nlg +32 -9
- package/test/test_03_jsinterop.nlg +3 -3
- package/test/test_07_lingo.nlg +1 -1
|
@@ -6,408 +6,118 @@
|
|
|
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
|
|
|
13
|
-
/*
|
|
14
|
-
* globals
|
|
15
|
-
*
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
gWorkers;
|
|
19
|
-
|
|
20
13
|
|
|
21
14
|
/*
|
|
22
15
|
* TermHost
|
|
23
16
|
*
|
|
24
|
-
* Make
|
|
17
|
+
* Make a debugger target on our Host NaanIDE Server or a remote one.
|
|
25
18
|
*
|
|
26
19
|
* Options:
|
|
27
20
|
* {
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* startup:
|
|
32
|
-
* clientID: <string> // (rare) our identification on client
|
|
33
|
-
* serverID: <string> // (rare) server subsystem for us
|
|
21
|
+
* serverID: <string> // target server if not our Host
|
|
22
|
+
* type: <string> // target category, e.g. "Remote", "api.yyy.com"
|
|
23
|
+
* workerID: <string> // kind of worker in server subsystem
|
|
24
|
+
* startup: <dictionary> // startup options
|
|
34
25
|
* }
|
|
35
26
|
*
|
|
36
27
|
*/
|
|
37
28
|
|
|
38
|
-
closure TermHost(track,
|
|
29
|
+
closure TermHost(track, name, options,
|
|
30
|
+
local relay, error, serverID, targetID, target, xc)
|
|
39
31
|
{
|
|
40
|
-
global(
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if instance.executor.hostWorkerMatch(api, testID)
|
|
58
|
-
return (instance.executor)
|
|
59
|
-
}
|
|
60
|
-
false
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// connect
|
|
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)))
|
|
72
|
-
}
|
|
73
|
-
if url.protocol == "https:"
|
|
74
|
-
url.protocol = "wss:"
|
|
75
|
-
else
|
|
76
|
-
url.protocol = "ws:"
|
|
77
|
-
target.ws = xnew(window.WebSocket, url.href)
|
|
78
|
-
pending = new(nonce)
|
|
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
|
|
32
|
+
global(App)
|
|
33
|
+
|
|
34
|
+
// findHostInstance
|
|
35
|
+
//
|
|
36
|
+
// Find the host instance name/type, or create new remote worker. The default for no name/type is
|
|
37
|
+
// the server itself.
|
|
38
|
+
//
|
|
39
|
+
function findHostInstance(relay, name, type,
|
|
40
|
+
local error, found, dest, worker) {
|
|
41
|
+
if !serverID {
|
|
42
|
+
`(error, found) = relay.clients()
|
|
43
|
+
if !error {
|
|
44
|
+
dest = found.find(function(item) { item.name == "NaanIDE Server" && item.type == "Server IMP" })
|
|
45
|
+
if dest
|
|
46
|
+
serverID = dest.destID
|
|
47
|
+
else
|
|
48
|
+
error = Error("cannot locate host")
|
|
86
49
|
}
|
|
87
|
-
if options.dispatcher
|
|
88
|
-
info.destID = api.instanceID // valid destination for relay
|
|
89
|
-
target.ws.send(window.JSON.stringify({
|
|
90
|
-
guid: api.guid
|
|
91
|
-
init: info
|
|
92
|
-
}))
|
|
93
|
-
spawner = new(options.startup) || { }
|
|
94
|
-
spawner.name = name
|
|
95
|
-
sendControl("spawn", spawner)
|
|
96
|
-
pending.signal(list(false, { ok: true }))
|
|
97
50
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
if true {
|
|
106
|
-
debuglog("can't decode incoming ws message:", exception)
|
|
107
|
-
return }
|
|
51
|
+
if !error
|
|
52
|
+
`(error, found) = relay.clients(serverID)
|
|
53
|
+
if !error {
|
|
54
|
+
if name && type {
|
|
55
|
+
dest = found.find(function(item) { item.name == name && item.type == type })
|
|
56
|
+
if dest
|
|
57
|
+
return (list(false, dest.destID)) // found worker
|
|
108
58
|
}
|
|
109
|
-
if
|
|
110
|
-
|
|
111
|
-
if
|
|
112
|
-
return (
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
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())
|
|
59
|
+
if !name || !type { // find main instance
|
|
60
|
+
dest = found.find(function(item) { item.name == "NaanIDE Server" && item.type == "NaaN Server" })
|
|
61
|
+
if !dest
|
|
62
|
+
return (list(Error("cannot locate NaanIDE Server")))
|
|
63
|
+
else
|
|
64
|
+
return (list(false, dest.destID))
|
|
65
|
+
}
|
|
66
|
+
dest = found.find(function(item) { item.name == "NaanIDE Server" && item.type == "Node Remote" })
|
|
67
|
+
if !dest
|
|
68
|
+
return (list(Error("cannot locate NaanIDE Server Remote")))
|
|
69
|
+
`(error, xc) = relay.context(dest.destID)
|
|
70
|
+
if !error {
|
|
71
|
+
`(error) = xc.evalq(chns("node"))
|
|
72
|
+
if error
|
|
73
|
+
return (list(Error("cannot switch namespace", error)))
|
|
74
|
+
}
|
|
75
|
+
if !error
|
|
76
|
+
closure (options) {
|
|
77
|
+
`(error, worker) = xc.evalq(NobBot(options), `(options))
|
|
78
|
+
}({
|
|
79
|
+
name: name
|
|
80
|
+
type: options.type
|
|
81
|
+
startup: options.startup
|
|
82
|
+
rootPath: options.rootPath || undefined
|
|
83
|
+
topOriginID: App.imp.us.instanceID
|
|
84
|
+
})
|
|
85
|
+
if error
|
|
86
|
+
error = Error("cannot spawn remote instance", error)
|
|
87
|
+
else
|
|
88
|
+
return (list(false, worker.instanceID))
|
|
293
89
|
}
|
|
294
|
-
|
|
295
|
-
id: "keyline",
|
|
296
|
-
text: text
|
|
297
|
-
})
|
|
90
|
+
list(error)
|
|
298
91
|
}
|
|
299
92
|
|
|
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
|
-
}
|
|
93
|
+
options = merge({
|
|
94
|
+
type: "Host"
|
|
95
|
+
}, options)
|
|
330
96
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
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
|
-
}
|
|
97
|
+
target = findIDEtarget(track, name, options.workerID)
|
|
98
|
+
if target
|
|
99
|
+
return (list(false, target)) // already exists
|
|
100
|
+
|
|
101
|
+
relay = require("naanlib:frameworks/client/relaycon.nlg").RelayCon(App.imp)
|
|
102
|
+
serverID = options.serverID
|
|
103
|
+
if options.workerID == "NideServer" // server main thread
|
|
104
|
+
`(error, targetID) = findHostInstance(relay)
|
|
105
|
+
else
|
|
106
|
+
`(error, targetID) = findHostInstance(relay, name, options.type)
|
|
107
|
+
relay.close()
|
|
108
|
+
if error
|
|
109
|
+
return (list(error))
|
|
350
110
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
target.
|
|
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
|
-
}
|
|
111
|
+
target = require("../running/instances.nlg").InTop(track, {
|
|
112
|
+
name: name
|
|
113
|
+
type: options.type
|
|
114
|
+
})
|
|
115
|
+
target.serverID = serverID // server instanceID
|
|
116
|
+
target.workerID = options.workerID // worker on server instanceID
|
|
405
117
|
|
|
406
|
-
|
|
407
|
-
if
|
|
408
|
-
return (list(
|
|
409
|
-
track.add(target)
|
|
410
|
-
connect() // connect right away to start receiving messages
|
|
118
|
+
`(error) = target.open(targetID)
|
|
119
|
+
if error
|
|
120
|
+
return (list(Error("cannot create InTop", error)))
|
|
411
121
|
|
|
412
122
|
// finis
|
|
413
123
|
|
|
@@ -424,311 +134,43 @@ closure TermHost(track, api, name, options, local target, nlregex, xtarg)
|
|
|
424
134
|
* {
|
|
425
135
|
* workerID: <string> // kind of worker in server subsystem
|
|
426
136
|
* // "NaanIDE" for local IDE
|
|
427
|
-
* // "NaanIDE-Debug" for browser debug target
|
|
428
137
|
* startup: <dictionary> // startup options
|
|
429
138
|
* type: <string> // (rare) target category, e.g. "Local"
|
|
430
139
|
* }
|
|
431
140
|
*
|
|
432
141
|
*/
|
|
433
142
|
|
|
434
|
-
closure TermLocal(track, name, options, local target,
|
|
143
|
+
closure TermLocal(track, name, options, local target, worker, wowbot, error)
|
|
435
144
|
{
|
|
436
|
-
global(js, window
|
|
437
|
-
if !dictionary(gWorkers)
|
|
438
|
-
gWorkers = {}
|
|
145
|
+
global(js, window)
|
|
439
146
|
options = merge({
|
|
440
147
|
type: "Local"
|
|
441
148
|
}, options)
|
|
442
149
|
if options.workerID == "NaanIDE" {
|
|
443
150
|
if !js.t
|
|
444
151
|
return (list(Error("Cannot access Local IDE executor")))
|
|
445
|
-
termInstallVirtualWatcher(track,
|
|
152
|
+
termInstallVirtualWatcher(track, window)
|
|
446
153
|
return (termIDE(track, name, options.workerID, js.t)) // connect to IDE execution instance itself
|
|
447
154
|
}
|
|
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
155
|
|
|
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
|
-
})
|
|
156
|
+
target = findIDEtarget(track, name, options.workerID)
|
|
157
|
+
if target
|
|
158
|
+
return (list(false, target)) // already exists
|
|
490
159
|
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
target.execClosed(Error("instance error", e.message))
|
|
160
|
+
worker = xnew(window.Worker, "env_webworker.js")
|
|
161
|
+
wowbot = WowBot(worker, {
|
|
162
|
+
name: name
|
|
163
|
+
type: options.workerID
|
|
164
|
+
startup: options.startup
|
|
497
165
|
})
|
|
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)
|
|
166
|
+
target = require("../running/instances.nlg").InTop(track, {
|
|
167
|
+
name: name
|
|
168
|
+
type: options.type
|
|
169
|
+
workerID: options.workerID
|
|
170
|
+
})
|
|
171
|
+
`(error) = target.open(wowbot.instanceID)
|
|
172
|
+
if error
|
|
173
|
+
return (list(Error("cannot create InTop", error)))
|
|
732
174
|
|
|
733
175
|
// finis
|
|
734
176
|
|
|
@@ -736,31 +178,6 @@ closure termMainProxy(track, name, options, local target) {
|
|
|
736
178
|
};
|
|
737
179
|
|
|
738
180
|
|
|
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
181
|
/*
|
|
765
182
|
* findIDEtarget
|
|
766
183
|
*
|
|
@@ -791,7 +208,7 @@ closure findIDEtarget(track, name, workerID, title, naancont, local target) {
|
|
|
791
208
|
*/
|
|
792
209
|
|
|
793
210
|
closure termIDE(track, name, workerID, naancont, title, local target, connected) {
|
|
794
|
-
global(js
|
|
211
|
+
global(js)
|
|
795
212
|
target = findIDEtarget(track, name, workerID, title, naancont)
|
|
796
213
|
if target { // new naancont on existing target
|
|
797
214
|
if target.naancont && naancont !== target.naancont
|
|
@@ -802,63 +219,66 @@ closure termIDE(track, name, workerID, naancont, title, local target, connected)
|
|
|
802
219
|
return (target)
|
|
803
220
|
}
|
|
804
221
|
target = require("../running/executors.nlg").ExecutorBase(track, "Local", name)
|
|
222
|
+
target.dispatcher = require("../running/taskexec.nlg").TaskDispatcher(false, false, "termIDE")
|
|
805
223
|
target.name = name
|
|
806
224
|
target.title = title
|
|
807
225
|
target.workerID = workerID
|
|
808
226
|
target.naancont = naancont
|
|
227
|
+
naancont.ioctl_open(ioctl_callback.proc)
|
|
809
228
|
connected = []
|
|
810
|
-
|
|
811
|
-
//
|
|
229
|
+
|
|
230
|
+
// PostMessage
|
|
812
231
|
//
|
|
813
|
-
//
|
|
232
|
+
// Process a message through the dispatcher.
|
|
814
233
|
//
|
|
815
|
-
function
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
})
|
|
234
|
+
target.PostMessage = function PostMessage(data) {
|
|
235
|
+
target.dispatcher(data, function(reply) {
|
|
236
|
+
target.execReceived(reply)
|
|
237
|
+
})
|
|
238
|
+
list(false, { posted: true })
|
|
821
239
|
}
|
|
822
240
|
|
|
823
|
-
//
|
|
241
|
+
// ioctl_callback
|
|
824
242
|
//
|
|
825
|
-
//
|
|
243
|
+
// Ioctl from our instance.
|
|
826
244
|
//
|
|
827
|
-
|
|
828
|
-
|
|
245
|
+
function ioctl_callback(op, arg) { // where ioctls go when they have nowhere to go
|
|
246
|
+
debuglog("no-terminal ioctl:", op, arg)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// ioctl_event
|
|
250
|
+
//
|
|
251
|
+
target.ioctl_event = function ioctl_event(msg, arg) {
|
|
252
|
+
naancont.ioctl_event(msg, arg)
|
|
829
253
|
}
|
|
830
254
|
|
|
831
|
-
// target.
|
|
255
|
+
// target.DebugCmd
|
|
832
256
|
//
|
|
833
|
-
// Post a
|
|
257
|
+
// Post a debug command to the target, ourselves.
|
|
834
258
|
//
|
|
835
|
-
target.
|
|
836
|
-
naancont.
|
|
837
|
-
list(false, { posted: true })
|
|
259
|
+
target.DebugCmd = function DebugCmd(data) {
|
|
260
|
+
naancont.DispatchDebugger(data)
|
|
838
261
|
}
|
|
839
262
|
|
|
840
263
|
// termAttach
|
|
841
264
|
//
|
|
842
265
|
// Create a closure for an attaching terminal.
|
|
843
266
|
//
|
|
844
|
-
target.termAttach = closure termAttach(term, db,
|
|
267
|
+
target.termAttach = closure termAttach(term, db, notify, local connection, jsterm, inbound) {
|
|
845
268
|
connection = new(object, this)
|
|
269
|
+
jsterm = term.jsAcquire() // termIDE must be direct
|
|
846
270
|
|
|
847
271
|
function oninterrupt() {
|
|
848
272
|
naancont.Interrupt(inbound)
|
|
849
273
|
}
|
|
850
274
|
|
|
851
275
|
function onreturn() {
|
|
852
|
-
naancont.Return(
|
|
276
|
+
naancont.Return(jsterm.TakeText(), inbound)
|
|
853
277
|
}
|
|
854
278
|
|
|
855
279
|
function onstatus(status) {
|
|
856
280
|
target.execSetStatus(status)
|
|
857
|
-
|
|
858
|
-
}
|
|
859
|
-
|
|
860
|
-
function onmessageout(data) {
|
|
861
|
-
target.execReceived(data)
|
|
281
|
+
notify.execStatus(target, status)
|
|
862
282
|
}
|
|
863
283
|
|
|
864
284
|
function ondebugout(data) {
|
|
@@ -867,7 +287,7 @@ closure termIDE(track, name, workerID, naancont, title, local target, connected)
|
|
|
867
287
|
|
|
868
288
|
connection.KeyText = function KeyText(text, echo) { // send text to instance
|
|
869
289
|
if echo
|
|
870
|
-
|
|
290
|
+
jsterm.WriteLn(text.trim()) // echo to terminal
|
|
871
291
|
naancont.Return(text, inbound)
|
|
872
292
|
}
|
|
873
293
|
|
|
@@ -877,16 +297,15 @@ closure termIDE(track, name, workerID, naancont, title, local target, connected)
|
|
|
877
297
|
}
|
|
878
298
|
|
|
879
299
|
connection.WriteLn = function WriteLn(text) {
|
|
880
|
-
|
|
300
|
+
jsterm.WriteLn(text)
|
|
881
301
|
}
|
|
882
302
|
|
|
883
303
|
connection.termDetach = function termDetach() { // disconnect the terminal
|
|
884
304
|
db.detach(target)
|
|
885
|
-
term.On("interrupt")
|
|
886
|
-
term.On("return")
|
|
887
305
|
if inbound
|
|
888
306
|
naancont.Detach(inbound)
|
|
889
307
|
connected = connected.filter(function(conn) { conn !== connection })
|
|
308
|
+
term.jsRelease()
|
|
890
309
|
}
|
|
891
310
|
|
|
892
311
|
connection.popup = true // we can handle multiple terminals
|
|
@@ -894,17 +313,16 @@ closure termIDE(track, name, workerID, naancont, title, local target, connected)
|
|
|
894
313
|
let (replstate) {
|
|
895
314
|
replstate = naancont.StateGet()
|
|
896
315
|
if (replstate)
|
|
897
|
-
|
|
316
|
+
jsterm.StateLoad(replstate)
|
|
898
317
|
else
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
318
|
+
jsterm.Reset()
|
|
319
|
+
jsterm.On("interrupt", oninterrupt.proc)
|
|
320
|
+
jsterm.On("return", onreturn.proc)
|
|
321
|
+
jsterm.Focus()
|
|
903
322
|
inbound = xnew({
|
|
904
|
-
OnMessage:
|
|
905
|
-
StateSave:
|
|
323
|
+
OnMessage: jsterm.OnMessage
|
|
324
|
+
StateSave: jsterm.StateSave
|
|
906
325
|
OnStatus: onstatus.proc
|
|
907
|
-
OnMessageOut: onmessageout.proc
|
|
908
326
|
OnDebugOut: ondebugout.proc
|
|
909
327
|
})
|
|
910
328
|
naancont.Attach(inbound)
|
|
@@ -913,7 +331,33 @@ closure termIDE(track, name, workerID, naancont, title, local target, connected)
|
|
|
913
331
|
connected.push(connection)
|
|
914
332
|
db.attach(target)
|
|
915
333
|
} ()
|
|
916
|
-
|
|
334
|
+
|
|
335
|
+
naancont.ioctl_open(function (op, arg) {
|
|
336
|
+
if op == "sane"
|
|
337
|
+
jsterm.Sane()
|
|
338
|
+
else if op == "raw" {
|
|
339
|
+
if arg // enable raw mode
|
|
340
|
+
jsterm.OnRaw(function(str, origin) {
|
|
341
|
+
ioctl_event("raw-key", {
|
|
342
|
+
key: str
|
|
343
|
+
origin: origin
|
|
344
|
+
})
|
|
345
|
+
})
|
|
346
|
+
else // else disable raw
|
|
347
|
+
jsterm.OnRaw()
|
|
348
|
+
} else if op == "keystroke"
|
|
349
|
+
jsterm.PutKey(arg) // simulate a keystroke
|
|
350
|
+
else if op == "echo"
|
|
351
|
+
jsterm.EchoSet(arg) // echo: 0, 1, 2
|
|
352
|
+
})
|
|
353
|
+
|
|
354
|
+
jsterm.OnResize(function(columns, rows) {
|
|
355
|
+
ioctl_event("term-resize", {
|
|
356
|
+
cols: columns
|
|
357
|
+
rows: rows
|
|
358
|
+
})
|
|
359
|
+
})
|
|
360
|
+
|
|
917
361
|
// finis
|
|
918
362
|
connection
|
|
919
363
|
}
|
|
@@ -923,7 +367,9 @@ closure termIDE(track, name, workerID, naancont, title, local target, connected)
|
|
|
923
367
|
// Update the naan controller on this target, which means updating for all the terminals.
|
|
924
368
|
//
|
|
925
369
|
target.updateController = function updateController(newnc, local conn) {
|
|
370
|
+
naancont.ioctl_close()
|
|
926
371
|
naancont = newnc
|
|
372
|
+
naancont.ioctl_open(ioctl_callback.proc)
|
|
927
373
|
target.naancont = newnc
|
|
928
374
|
for conn in connected {
|
|
929
375
|
if naancont {
|
|
@@ -946,6 +392,7 @@ closure termIDE(track, name, workerID, naancont, title, local target, connected)
|
|
|
946
392
|
conn.WriteLn("\x1b[90m\x1b[3m".concat("\ntarget closed", "\x1b[0m"))
|
|
947
393
|
}
|
|
948
394
|
target.execReset()
|
|
395
|
+
naancont.ioctl_close()
|
|
949
396
|
target.naancont = naancont = false
|
|
950
397
|
}
|
|
951
398
|
|
|
@@ -992,7 +439,6 @@ closure termIDE(track, name, workerID, naancont, title, local target, connected)
|
|
|
992
439
|
track.delete(target)
|
|
993
440
|
}
|
|
994
441
|
|
|
995
|
-
js.t.OnReplyHook(replyHook.proc)
|
|
996
442
|
track.add(target)
|
|
997
443
|
|
|
998
444
|
// finis
|
|
@@ -1010,7 +456,7 @@ closure termIDE(track, name, workerID, naancont, title, local target, connected)
|
|
|
1010
456
|
*/
|
|
1011
457
|
|
|
1012
458
|
closure termInstallVirtualWatcher(track, naancont) {
|
|
1013
|
-
global()
|
|
459
|
+
global(js)
|
|
1014
460
|
|
|
1015
461
|
function watchVsites(msg, local error, target) {
|
|
1016
462
|
if msg.op == "VsiteOpen" {
|
|
@@ -1029,7 +475,121 @@ closure termInstallVirtualWatcher(track, naancont) {
|
|
|
1029
475
|
}
|
|
1030
476
|
}
|
|
1031
477
|
|
|
1032
|
-
|
|
478
|
+
js.t.OnMessage(watchVsites.proc)
|
|
479
|
+
};
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
/*
|
|
483
|
+
* testTab
|
|
484
|
+
*
|
|
485
|
+
* Quick test of the InTop/InBot connection.
|
|
486
|
+
*
|
|
487
|
+
*/
|
|
488
|
+
|
|
489
|
+
closure testTab(destID,
|
|
490
|
+
local comMod, relay, error, found, dest, xc, inbotDestID, intop) {
|
|
491
|
+
|
|
492
|
+
// findBottomID
|
|
493
|
+
//
|
|
494
|
+
// Find the inbot destID that goes with our desired workerID.
|
|
495
|
+
//
|
|
496
|
+
function findBottomID(found, workerID, local item) {
|
|
497
|
+
for item in found
|
|
498
|
+
if item.name == "Play" && item.type == workerID
|
|
499
|
+
return (item.destID)
|
|
500
|
+
false
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
comMod = require("naanlib:frameworks/client/relaycon.nlg")
|
|
504
|
+
relay = comMod.RelayCon(App.imp)
|
|
505
|
+
`(error, found) = relay.clients(destID)
|
|
506
|
+
dest = found.find(function(item) { item.name == "NaanIDE" && item.services.indexOf("naan-remote-responder") >= 0 })
|
|
507
|
+
if !dest
|
|
508
|
+
return (list(Error("cannot locate remoting")))
|
|
509
|
+
`(error, xc)= relay.context(dest.destID)
|
|
510
|
+
if error
|
|
511
|
+
return (list(Error("cannot access remoting", error)))
|
|
512
|
+
inbotDestID = findBottomID(found, "Webworker-Play")
|
|
513
|
+
if !inbotDestID
|
|
514
|
+
return (list(Error("cannot find web worker")))
|
|
515
|
+
intop = require("../running/instances.nlg").InTop(App.nide.track, {
|
|
516
|
+
name: "NaanIDE-Play"
|
|
517
|
+
type: "Relay"
|
|
518
|
+
})
|
|
519
|
+
`(error) = intop.open(inbotDestID)
|
|
520
|
+
if error
|
|
521
|
+
return (list(Error("cannot create InTop", error)))
|
|
522
|
+
list(false, xc, intop)
|
|
523
|
+
};
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
/*
|
|
527
|
+
* relayTab
|
|
528
|
+
*
|
|
529
|
+
* Open a relay tab for the first peer NaanIDE found on the same server.
|
|
530
|
+
*
|
|
531
|
+
*/
|
|
532
|
+
|
|
533
|
+
closure relayTab(destID, local comMod, relay, error, found, dest, xc, reterm, originID, inbot) {
|
|
534
|
+
|
|
535
|
+
// remoteFindTerm
|
|
536
|
+
//
|
|
537
|
+
// Executes on remote to give us a (proxy) terminal.
|
|
538
|
+
//
|
|
539
|
+
function remoteFindTerm(name, workerID, local target) {
|
|
540
|
+
for target in App.nide.track.enumlist()
|
|
541
|
+
if target.name == name && target.workerID == workerID
|
|
542
|
+
return (target)
|
|
543
|
+
false
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
comMod = require("naanlib:frameworks/client/relaycon.nlg")
|
|
547
|
+
relay = comMod.RelayCon(App.imp)
|
|
548
|
+
if !destID {
|
|
549
|
+
`(error, found) = relay.clients()
|
|
550
|
+
if !error {
|
|
551
|
+
dest = found.find(function(item) { item.name == "NaanIDE Server" && item.type == "Server IMP" })
|
|
552
|
+
if !dest
|
|
553
|
+
error = Error("cannot locate server")
|
|
554
|
+
}
|
|
555
|
+
if !error
|
|
556
|
+
`(error, found) = relay.clients(dest.destID)
|
|
557
|
+
if !error {
|
|
558
|
+
dest = found.find(function(item) { item.name == "NaanIDE"
|
|
559
|
+
&& item.type == "Client IMP" && item.destID != App.imp.us.instanceID })
|
|
560
|
+
if !dest
|
|
561
|
+
error = Error("cannot locate peer tab")
|
|
562
|
+
else
|
|
563
|
+
destID = dest.destID
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
if error
|
|
567
|
+
return (list(Error("cannot locate target", error)))
|
|
568
|
+
`(error, xc) = relay.context(destID)
|
|
569
|
+
if error
|
|
570
|
+
return (list(Error("cannot access remoting", error)))
|
|
571
|
+
`(error) = xc.evalq(chns("browser"))
|
|
572
|
+
if error
|
|
573
|
+
return (list(Error("cannot switch namespace", error)))
|
|
574
|
+
`(error, reterm) = xc.evalq(remoteFindTerm("NaanIDE", "NaanIDE"), `(remoteFindTerm))
|
|
575
|
+
if error
|
|
576
|
+
return (list(Error("cannot get remote terminal", error)))
|
|
577
|
+
originID = App.imp.us.instanceID
|
|
578
|
+
`(error, inbot) = xc.evalq(MewBot(window, {
|
|
579
|
+
name: "mewbot"
|
|
580
|
+
type: reterm.workerID
|
|
581
|
+
topOriginID: originID
|
|
582
|
+
}), `(reterm, originID))
|
|
583
|
+
if error
|
|
584
|
+
return (list(Error("cannot create inBot", error)))
|
|
585
|
+
intop = require("../running/instances.nlg").InTop(App.nide.track, {
|
|
586
|
+
name: "NaanIDE Relay"
|
|
587
|
+
type: "Relay"
|
|
588
|
+
})
|
|
589
|
+
`(error) = intop.open(inbot.instanceID)
|
|
590
|
+
if error
|
|
591
|
+
return (list(Error("cannot create InTop", error)))
|
|
592
|
+
list(false, xc, intop)
|
|
1033
593
|
};
|
|
1034
594
|
|
|
1035
595
|
|
|
@@ -1041,15 +601,13 @@ closure termInstallVirtualWatcher(track, naancont) {
|
|
|
1041
601
|
*/
|
|
1042
602
|
|
|
1043
603
|
function termInit(local manifest) {
|
|
1044
|
-
manifest = `(TermHost, TermLocal,
|
|
1045
|
-
termIDE, termInstallVirtualWatcher, termInit)
|
|
604
|
+
manifest = `(TermHost, TermLocal,
|
|
605
|
+
findIDEtarget, termIDE, termInstallVirtualWatcher, testTab, relayTab, termInit)
|
|
1046
606
|
|
|
1047
607
|
Naan.module.build(module.id, "terminals", function(modobj, compobj) {
|
|
1048
|
-
require("./
|
|
608
|
+
require("./worker.nlg")
|
|
1049
609
|
compobj.manifest = manifest
|
|
1050
610
|
modobj.exports.TermLocal = TermLocal
|
|
1051
611
|
modobj.exports.TermHost = TermHost
|
|
1052
|
-
modobj.exports.WorkerConnect = WorkerConnect
|
|
1053
|
-
modobj.exports.WorkerToMain = WorkerToMain
|
|
1054
612
|
})
|
|
1055
613
|
} ();
|