@naanlang/naan 1.7.0 → 1.7.1
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 +1 -1
- package/README.md +1 -1
- package/bin/index.js +2 -2
- package/dist/env_web.js +0 -1
- package/dist/naan.min.js +4 -4
- package/frameworks/browser/sworker.js +23 -23
- package/frameworks/browser/terminals.nlg +117 -90
- package/frameworks/browser/worker.nlg +16 -8
- package/frameworks/browser/ws_client.nlg +23 -87
- package/frameworks/client/apiclient.nlg +24 -21
- package/frameworks/client/client.nlg +22 -2
- package/frameworks/client/relaycon.nlg +1 -1
- package/frameworks/common/common.nlg +11 -9
- package/frameworks/node/apiserver.nlg +1 -1
- package/frameworks/node/worker.nlg +15 -7
- package/frameworks/node/ws_client.nlg +25 -84
- package/frameworks/project/build.nlg +29 -20
- package/frameworks/project/projects.nlg +2 -2
- package/frameworks/running/executors.nlg +23 -15
- package/frameworks/running/instances.nlg +34 -23
- package/frameworks/running/remote_req.nlg +2 -1
- package/frameworks/running/remote_res.nlg +1 -1
- package/frameworks/service/imp.nlg +22 -5
- package/frameworks/service/nubnode.nlg +4 -4
- package/frameworks/service/nubweb.nlg +6 -6
- package/lib/browser/env_web.js +7 -8
- package/lib/core/naanlib.js +4 -4
- package/package.json +1 -1
|
@@ -208,6 +208,7 @@ closure APIClient(imp, options, local client, url, guid) {
|
|
|
208
208
|
closure WebSocketClient(options, imp, local wesc, ws, pending) {
|
|
209
209
|
global(js)
|
|
210
210
|
wesc = new(object, this)
|
|
211
|
+
|
|
211
212
|
|
|
212
213
|
// reconnect
|
|
213
214
|
//
|
|
@@ -226,40 +227,29 @@ closure WebSocketClient(options, imp, local wesc, ws, pending) {
|
|
|
226
227
|
//
|
|
227
228
|
// Establish a websocket connection with the host.
|
|
228
229
|
//
|
|
229
|
-
wesc.connect = closure connect(local url, result) {
|
|
230
|
+
wesc.connect = closure connect(local url, result, error) {
|
|
230
231
|
if ws {
|
|
231
232
|
if pending
|
|
232
233
|
return (pending.wait()) // connect in process
|
|
233
234
|
if !wesc.fatal
|
|
234
235
|
return(list(false, { connected: true })) // already open
|
|
235
236
|
}
|
|
236
|
-
try {
|
|
237
|
-
url = xnew(js.w.URL, options.url)
|
|
238
|
-
} catch {
|
|
239
|
-
return(list(Error("invalid URL ${options.url}", exception)))
|
|
240
|
-
}
|
|
241
|
-
if url.protocol == "https:"
|
|
242
|
-
url.protocol = "wss:"
|
|
243
|
-
else
|
|
244
|
-
url.protocol = "ws:"
|
|
245
|
-
ws = xnew(js.w.WebSocket, url.href)
|
|
246
|
-
if wesc.fatal
|
|
247
|
-
debuglog("WebSocketClient reopen") // ### not pretty to see this
|
|
248
|
-
wesc.fatal = false
|
|
249
|
-
pending = new(nonce)
|
|
250
237
|
|
|
251
238
|
// onopen
|
|
252
239
|
// The WebSocket connection is now open.
|
|
253
|
-
|
|
240
|
+
function onopen(e) {
|
|
254
241
|
if wesc.impconn {
|
|
255
242
|
result = wesc.impconn.reopen()
|
|
256
243
|
pending.signal(result)
|
|
257
244
|
return
|
|
258
245
|
}
|
|
259
|
-
wesc.impconn = imp.requester(function(data) {
|
|
246
|
+
wesc.impconn = imp.requester(function(data, local error, text) {
|
|
260
247
|
if !pending && reconnect() // !pending means not opening/reopening
|
|
261
248
|
return // failed to reconnect
|
|
262
|
-
|
|
249
|
+
`(error, text) = JsonStringify(data)
|
|
250
|
+
if error
|
|
251
|
+
return (list(error))
|
|
252
|
+
ws.send(text)
|
|
263
253
|
list(false, { sent: true })
|
|
264
254
|
}, {
|
|
265
255
|
secret: options.guid
|
|
@@ -274,7 +264,7 @@ closure WebSocketClient(options, imp, local wesc, ws, pending) {
|
|
|
274
264
|
|
|
275
265
|
// onmessage
|
|
276
266
|
// A message was received via WebSockets.
|
|
277
|
-
|
|
267
|
+
function onmessage(e, local error, message) {
|
|
278
268
|
`(error, message) = JsonParse(e.data)
|
|
279
269
|
if !error {
|
|
280
270
|
message = new(message)
|
|
@@ -289,7 +279,7 @@ closure WebSocketClient(options, imp, local wesc, ws, pending) {
|
|
|
289
279
|
// onerror
|
|
290
280
|
// An error occurred on the WebSocket connection.
|
|
291
281
|
// This can happen in normal operation when the connection times out.
|
|
292
|
-
|
|
282
|
+
function onerror(e) {
|
|
293
283
|
if !wesc.fatal
|
|
294
284
|
wesc.fatal = Error("websocket failed", e)
|
|
295
285
|
pending.signal(list(wesc.fatal))
|
|
@@ -298,7 +288,7 @@ closure WebSocketClient(options, imp, local wesc, ws, pending) {
|
|
|
298
288
|
|
|
299
289
|
// onclose
|
|
300
290
|
// The WebSocket connection was closed.
|
|
301
|
-
|
|
291
|
+
function onclose(e) {
|
|
302
292
|
// if e.code != 1000 && e.code != 1001 && e.code != 1005 && e.code != 1006
|
|
303
293
|
debuglog("WebSocketClient: closed:", e.code, e.reason) // ### not pretty to see this
|
|
304
294
|
ws = false
|
|
@@ -308,6 +298,19 @@ closure WebSocketClient(options, imp, local wesc, ws, pending) {
|
|
|
308
298
|
pending = false
|
|
309
299
|
}
|
|
310
300
|
|
|
301
|
+
`(error, ws) = call(clirWebsocket(), options.url, {
|
|
302
|
+
onopen: onopen.proc
|
|
303
|
+
onmessage: onmessage.proc
|
|
304
|
+
onerror: onerror.proc
|
|
305
|
+
onclose: onclose.proc
|
|
306
|
+
})
|
|
307
|
+
if error
|
|
308
|
+
return (list(wesc.fatal = error)) // failed to even get started
|
|
309
|
+
|
|
310
|
+
if wesc.fatal
|
|
311
|
+
debuglog("WebSocketClient reopen") // ### not pretty to see this
|
|
312
|
+
wesc.fatal = false
|
|
313
|
+
pending = new(nonce)
|
|
311
314
|
result = pending.wait(10000, list(Error("IMP connection timeout")))
|
|
312
315
|
pending = false
|
|
313
316
|
result
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* column positioning: // // !
|
|
8
8
|
*
|
|
9
|
-
* Copyright (c) 2020-
|
|
9
|
+
* Copyright (c) 2020-2026 by Richard C. Zulch
|
|
10
10
|
*
|
|
11
11
|
*/
|
|
12
12
|
|
|
@@ -31,6 +31,26 @@ function clirRequester() {
|
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
|
|
34
|
+
/*
|
|
35
|
+
* clirWebsocket
|
|
36
|
+
*
|
|
37
|
+
* Return an appropriate Websocket client based on our environment.
|
|
38
|
+
*
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
clirWebsocketApi = false;
|
|
42
|
+
|
|
43
|
+
function clirWebsocket() {
|
|
44
|
+
if !clirWebsocketApi {
|
|
45
|
+
if js.w
|
|
46
|
+
clirWebsocketApi = require("naanlib:frameworks/browser/ws_client.nlg").WebSocket
|
|
47
|
+
else
|
|
48
|
+
clirWebsocketApi = require("naanlib:frameworks/node/ws_client.nlg").WebSocket
|
|
49
|
+
}
|
|
50
|
+
clirWebsocketApi
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
|
|
34
54
|
/*
|
|
35
55
|
* clirInit
|
|
36
56
|
*
|
|
@@ -40,7 +60,7 @@ function clirRequester() {
|
|
|
40
60
|
*/
|
|
41
61
|
|
|
42
62
|
function clirInit(local manifest) {
|
|
43
|
-
manifest = `(clirRequester, clirInit)
|
|
63
|
+
manifest = `(clirRequester, clirWebsocket, clirInit)
|
|
44
64
|
|
|
45
65
|
Naan.module.build(module.id, "client", function(modobj, compobj) {
|
|
46
66
|
require("../common/").LiveImport()
|
|
@@ -52,7 +52,7 @@ closure RelayCon(imp, options, local relay, nlregex)
|
|
|
52
52
|
serverID: "Workers"
|
|
53
53
|
workerID: "NideServer"
|
|
54
54
|
}, options.config)
|
|
55
|
-
relay.instanceID =
|
|
55
|
+
relay.instanceID = imp.getUUID("RelayCon(${options.name}) instanceID")
|
|
56
56
|
relay.exec = execsMod.ExecutorBase(false, "Host", options.name)
|
|
57
57
|
nlregex = RegExp("\\n", "g")
|
|
58
58
|
|
|
@@ -252,14 +252,16 @@ macro LiveExport() {
|
|
|
252
252
|
importList = []
|
|
253
253
|
//
|
|
254
254
|
// LiveImport
|
|
255
|
-
// Return a new LiveImport function to be exported by the module who called
|
|
255
|
+
// Return a new LiveImport function to be exported by the module who called LiveExport.
|
|
256
256
|
//
|
|
257
|
-
macro LiveImport(fixproc, local importingMod,
|
|
257
|
+
macro LiveImport(fixproc, local importingMod, item, updater) {
|
|
258
258
|
importingMod = car(nsrights().lookup("module"))
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
259
|
+
for item in importList
|
|
260
|
+
if item.proc.1.namespace === importingMod.namespace {
|
|
261
|
+
updater = item
|
|
262
|
+
break
|
|
263
|
+
}
|
|
264
|
+
if !updater {
|
|
263
265
|
updater = closure(importingMod, fixproc) { // create new updater
|
|
264
266
|
putproc(compress(updateImports), function updateImports(local goback) {
|
|
265
267
|
if importingMod !== exporterMod {
|
|
@@ -269,10 +271,10 @@ macro LiveExport() {
|
|
|
269
271
|
try {
|
|
270
272
|
call(fixproc, exporterMod) // let caller do any fixups
|
|
271
273
|
} catch {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
+
debuglog("LiveImport fixup failed in", nsrights(), "exception:", exception)
|
|
275
|
+
} finally {
|
|
276
|
+
goback()
|
|
274
277
|
}
|
|
275
|
-
goback()
|
|
276
278
|
})
|
|
277
279
|
updateImports
|
|
278
280
|
} (importingMod, eval(fixproc))
|
|
@@ -44,7 +44,7 @@ closure APIServer(options, local server, chroot) {
|
|
|
44
44
|
server.guid = options.guid
|
|
45
45
|
server.notifyq = []
|
|
46
46
|
server.responseq = []
|
|
47
|
-
server.instanceID =
|
|
47
|
+
server.instanceID = App.imp.getUUID("APIServer instanceID")
|
|
48
48
|
options = merge({
|
|
49
49
|
relpath: ""
|
|
50
50
|
name: "NaanServer"
|
|
@@ -44,7 +44,7 @@ closure CurBot(options, local curbot) {
|
|
|
44
44
|
curbot.guid = 1
|
|
45
45
|
curbot.host = js.t // our magic Naan controller reference
|
|
46
46
|
|
|
47
|
-
curbot.instanceID =
|
|
47
|
+
curbot.instanceID = App.imp.getUUID("CurBot(${options.name}) instanceID")
|
|
48
48
|
curbot.sender = App.imp.register(curbot, {
|
|
49
49
|
name: curbot.name
|
|
50
50
|
type: curbot.type
|
|
@@ -266,7 +266,7 @@ closure NowBot(options, local nowbot, nodeops, subChannel, ptySpawned) {
|
|
|
266
266
|
nowbot.thread.postMessage({ hereIsYourPort: subChannel.port1 }, [subChannel.port1])
|
|
267
267
|
nowbot.msgport = subChannel.port2
|
|
268
268
|
|
|
269
|
-
nowbot.instanceID =
|
|
269
|
+
nowbot.instanceID = App.imp.getUUID("NowBot(${options.name}) instanceID")
|
|
270
270
|
nowbot.sender = App.imp.register(nowbot, {
|
|
271
271
|
name: options.name
|
|
272
272
|
type: options.type
|
|
@@ -428,6 +428,16 @@ closure NowBot(options, local nowbot, nodeops, subChannel, ptySpawned) {
|
|
|
428
428
|
nowbot.thread = false
|
|
429
429
|
destroy()
|
|
430
430
|
})
|
|
431
|
+
|
|
432
|
+
// close
|
|
433
|
+
//
|
|
434
|
+
// Close and remove our IMP resources, but leave the worker alone.
|
|
435
|
+
//
|
|
436
|
+
nowbot.close = function close() {
|
|
437
|
+
nowbot.impconn.destroy()
|
|
438
|
+
nowbot.impconn = false
|
|
439
|
+
App.imp.unregister(nowbot.instanceID)
|
|
440
|
+
}
|
|
431
441
|
|
|
432
442
|
// destroy
|
|
433
443
|
//
|
|
@@ -436,9 +446,7 @@ closure NowBot(options, local nowbot, nodeops, subChannel, ptySpawned) {
|
|
|
436
446
|
nowbot.destroy = function destroy() {
|
|
437
447
|
terminate()
|
|
438
448
|
nowbot.thread = false
|
|
439
|
-
|
|
440
|
-
nowbot.impconn = false
|
|
441
|
-
App.imp.unregister(nowbot.instanceID)
|
|
449
|
+
close()
|
|
442
450
|
}
|
|
443
451
|
|
|
444
452
|
// NaaN message
|
|
@@ -446,7 +454,7 @@ closure NowBot(options, local nowbot, nodeops, subChannel, ptySpawned) {
|
|
|
446
454
|
// A message has been received from NaaN running on the worker thread.
|
|
447
455
|
//
|
|
448
456
|
nowbot.msgport.on("message", function (msg, local startmsg) {
|
|
449
|
-
if msg.id == "naan-imp-
|
|
457
|
+
if msg.id == "naan-imp-out" {
|
|
450
458
|
nowbot.impconn.dispatch(new(msg.data))
|
|
451
459
|
return
|
|
452
460
|
} else if msg.id == "loaded" {
|
|
@@ -542,7 +550,7 @@ closure NobBot(options, local nobbot)
|
|
|
542
550
|
|
|
543
551
|
nobbot.impconn = App.imp.responder(function(data) {
|
|
544
552
|
nobbot.msgport.postMessage({ // send to worker
|
|
545
|
-
id: "naan-imp-
|
|
553
|
+
id: "naan-imp-in" // scoped for NodeWorkerNub
|
|
546
554
|
data: data
|
|
547
555
|
})
|
|
548
556
|
list(false, { sent: true })
|
|
@@ -13,106 +13,47 @@
|
|
|
13
13
|
/*
|
|
14
14
|
* WebSocket
|
|
15
15
|
*
|
|
16
|
-
* Create a WebSocket client connection object.
|
|
16
|
+
* Create a WebSocket client connection object, returning a tuple.
|
|
17
17
|
*
|
|
18
18
|
* Required:
|
|
19
|
-
*
|
|
19
|
+
* urlstr: <string>
|
|
20
20
|
*
|
|
21
21
|
* Options:
|
|
22
22
|
* {
|
|
23
23
|
* wss: <boolean> // true to use secure connection
|
|
24
|
+
* query: <string> // query string starting with ?
|
|
24
25
|
* onopen: <proc>(e) // connection has opened
|
|
25
26
|
* onmessage: <proc>(e, message) // message received
|
|
26
27
|
* onerror: <proc>(e) // error occurred
|
|
27
28
|
* onclose: <proc>(e) // connection has closed
|
|
28
|
-
* query: <string> // query string starting with ? for insecure connections
|
|
29
|
-
* querys: <string> // query string starting with ? for secure connections
|
|
30
29
|
* }
|
|
31
30
|
*
|
|
32
31
|
*/
|
|
33
32
|
|
|
34
|
-
closure WebSocket(
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
closure WebSocket(urlstr, options, local error, wslib, url, ws) {
|
|
34
|
+
`(error, wslib) = await(js.i("ws"))
|
|
35
|
+
if error
|
|
36
|
+
return (list(error))
|
|
38
37
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
wsock.connect = closure connect(local error, ws, url, pending) {
|
|
44
|
-
if wsock.ws
|
|
45
|
-
return (list(false, { open: true }))
|
|
46
|
-
`(error, ws) = await(js.i("ws"))
|
|
47
|
-
if error
|
|
48
|
-
return (list(error))
|
|
49
|
-
if options.wss
|
|
50
|
-
url = "wss://${host}${options.querys||''}"
|
|
51
|
-
else
|
|
52
|
-
url = "ws://${host}${options.query||''}"
|
|
53
|
-
wsock.ws = xnew(ws.default, url)
|
|
54
|
-
pending = new(nonce)
|
|
55
|
-
|
|
56
|
-
// onopen
|
|
57
|
-
// The WebSocket connection is now open.
|
|
58
|
-
wsock.ws.onopen = closure onopen(e) {
|
|
59
|
-
pending.signal(list(false, { ok: true }))
|
|
60
|
-
options.onopen(e, e.target, e.type)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// onmessage
|
|
64
|
-
// A message was received from the worker via WebSockets.
|
|
65
|
-
wsock.ws.onmessage = closure onmessage(e, local message) {
|
|
66
|
-
try {
|
|
67
|
-
message = new(JSONparse(e.data))
|
|
68
|
-
} catch {
|
|
69
|
-
debuglog("can't decode incoming ws message:", exception)
|
|
70
|
-
options.onerror(Error("can't decode incoming message:", exception))
|
|
71
|
-
return
|
|
72
|
-
}
|
|
73
|
-
options.onmessage(e, message)
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// onerror
|
|
77
|
-
// An error occurred on the WebSocket connection.
|
|
78
|
-
wsock.ws.onerror = closure onerror(e, local error) {
|
|
79
|
-
error = Error("websocket failed", e)
|
|
80
|
-
options.onerror(e, error)
|
|
81
|
-
pending.signal(list(error)) // ensure connect completes
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// onclose
|
|
85
|
-
// The WebSocket connection was closed.
|
|
86
|
-
wsock.ws.onclose = closure onclose(e) {
|
|
87
|
-
options.onclose(e, e.code, e.reason)
|
|
88
|
-
pending.signal(list(Error("connection closed"))) // ensure connect completes
|
|
89
|
-
wsock.ws = false
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
pending.wait()
|
|
38
|
+
try {
|
|
39
|
+
url = xnew(js.g.URL, urlstr)
|
|
40
|
+
} catch {
|
|
41
|
+
return (list(Error("invalid URL ${urlstr}", exception)))
|
|
93
42
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
if !reason
|
|
109
|
-
reason = 1000 // normal close
|
|
110
|
-
wsock.ws.close(reason)
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// finis
|
|
114
|
-
|
|
115
|
-
wsock
|
|
43
|
+
options = merge({
|
|
44
|
+
query: url.search || ''
|
|
45
|
+
wss: url.protocol == "https:"
|
|
46
|
+
}, options)
|
|
47
|
+
if options.wss
|
|
48
|
+
url = "wss://${url.host}${options.query}"
|
|
49
|
+
else
|
|
50
|
+
url = "ws://${url.host}${options.query}"
|
|
51
|
+
ws = xnew(wslib.default, url)
|
|
52
|
+
ws.onopen = options.onopen
|
|
53
|
+
ws.onmessage = options.onmessage
|
|
54
|
+
ws.onerror = options.onerror
|
|
55
|
+
ws.onclose = options.onclose
|
|
56
|
+
list(false, ws)
|
|
116
57
|
};
|
|
117
58
|
|
|
118
59
|
|
|
@@ -304,18 +304,26 @@ closure Builder(rules, operation, fs, srcpath, destpath, track, local build, gro
|
|
|
304
304
|
//
|
|
305
305
|
// Apply substitutions from readSubstitutionFile to string, returning a tuple of the resulting
|
|
306
306
|
// text and the number of substitution patterns actually used from the supplied dictionary.
|
|
307
|
-
//
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
subst
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
307
|
+
// Specify iterative to repeat the substitution on the result until no more substitutions occur.
|
|
308
|
+
//
|
|
309
|
+
function applySubstitutions(text, subs, iterative, local count, subbed) {
|
|
310
|
+
count = 0
|
|
311
|
+
loop {
|
|
312
|
+
subbed = { }
|
|
313
|
+
text = text.replace(RegExp("[$][^$\\s]+[$]", "g"), function(match, local subst) {
|
|
314
|
+
subst = subs[match.slice(1,-1)]
|
|
315
|
+
if subst {
|
|
316
|
+
subbed[match] = true
|
|
317
|
+
subst
|
|
318
|
+
}
|
|
319
|
+
else
|
|
320
|
+
match
|
|
321
|
+
})
|
|
322
|
+
count += length(subbed)
|
|
323
|
+
if length(subbed) == 0 || !iterative
|
|
324
|
+
break
|
|
325
|
+
}
|
|
326
|
+
list(text, count)
|
|
319
327
|
}
|
|
320
328
|
|
|
321
329
|
//
|
|
@@ -1044,9 +1052,9 @@ closure Builder(rules, operation, fs, srcpath, destpath, track, local build, gro
|
|
|
1044
1052
|
}
|
|
1045
1053
|
else if ((`(error, content) = fs.readFile(entry.readpath, readOptions)) && !error) {
|
|
1046
1054
|
if entry.license
|
|
1047
|
-
`(content) = applySubstitutions(content, licFileDefs)
|
|
1055
|
+
`(content) = applySubstitutions(content, licFileDefs, true)
|
|
1048
1056
|
if entry.version
|
|
1049
|
-
`(content) = applySubstitutions(content, verFileDefs)
|
|
1057
|
+
`(content) = applySubstitutions(content, verFileDefs, true)
|
|
1050
1058
|
if entry.naanpack
|
|
1051
1059
|
`(error, content) = parseAndPack(content, entry.readpath, { naanpack: true })
|
|
1052
1060
|
else if entry.jspack
|
|
@@ -1251,7 +1259,8 @@ closure Builder(rules, operation, fs, srcpath, destpath, track, local build, gro
|
|
|
1251
1259
|
//
|
|
1252
1260
|
// Run the current build product by spawning a new worker.
|
|
1253
1261
|
//
|
|
1254
|
-
build.runSpawn = function runSpawn(
|
|
1262
|
+
build.runSpawn = function runSpawn(stage,
|
|
1263
|
+
local error, maintext, executor, vpath, site, dirpath) {
|
|
1255
1264
|
`(error, maintext) = fs.readFile(JSpath.join(build.destpath, build.runway.main))
|
|
1256
1265
|
if error
|
|
1257
1266
|
error = Error("Builder: cannot read main file", error)
|
|
@@ -1291,13 +1300,12 @@ closure Builder(rules, operation, fs, srcpath, destpath, track, local build, gro
|
|
|
1291
1300
|
//
|
|
1292
1301
|
// Run the current build product by opening a new window.
|
|
1293
1302
|
//
|
|
1294
|
-
build.runWindow = function runWindow(
|
|
1303
|
+
build.runWindow = function runWindow(stage,
|
|
1295
1304
|
local title, main, url, features, vpath, error, window, site) {
|
|
1296
1305
|
if !js.w
|
|
1297
1306
|
return (list(Error('Run method "window" requires browser host')))
|
|
1298
1307
|
if !build.runway."v-site"
|
|
1299
1308
|
return (list(Error('Run method "window" requires v-site specification')))
|
|
1300
|
-
title = rules.name.concat("-", build.buildnum)
|
|
1301
1309
|
main = build.runway.main
|
|
1302
1310
|
if !main
|
|
1303
1311
|
main = "index.html"
|
|
@@ -1313,6 +1321,7 @@ closure Builder(rules, operation, fs, srcpath, destpath, track, local build, gro
|
|
|
1313
1321
|
if error
|
|
1314
1322
|
return (list(Error("Builder: cannot create virtual site", error)))
|
|
1315
1323
|
sleep(1) // needed on Windows or it won't open, fiik why
|
|
1324
|
+
title = rules.name.concat("-", stage, "-", operation)
|
|
1316
1325
|
window = js.w.open(url, title, features)
|
|
1317
1326
|
list(false, { ok: true }) // we don't know the executor
|
|
1318
1327
|
}
|
|
@@ -1323,13 +1332,13 @@ closure Builder(rules, operation, fs, srcpath, destpath, track, local build, gro
|
|
|
1323
1332
|
// Run the current build product, which would be after the make call. Returns a standard result
|
|
1324
1333
|
// tuple.
|
|
1325
1334
|
//
|
|
1326
|
-
build.run = function run() {
|
|
1335
|
+
build.run = function run(stage) {
|
|
1327
1336
|
if build.runway.open
|
|
1328
1337
|
fs.shellOpen(JSpath.join(build.destpath, build.runway.open), build.runway.args)
|
|
1329
1338
|
else if build.runway.spawn
|
|
1330
|
-
build.runSpawn()
|
|
1339
|
+
build.runSpawn(stage)
|
|
1331
1340
|
else if build.runway.window
|
|
1332
|
-
build.runWindow()
|
|
1341
|
+
build.runWindow(stage)
|
|
1333
1342
|
else
|
|
1334
1343
|
list(false, { ok: true })
|
|
1335
1344
|
}
|
|
@@ -296,7 +296,7 @@ closure projConnector(projman, projtype, local connector, watch) {
|
|
|
296
296
|
*
|
|
297
297
|
* Nide.proj/
|
|
298
298
|
* nide_cliser.cfg - JSON definition of the project (see below)
|
|
299
|
-
* NaanIDE_version.txt - [default] substitution file defining 1.7.
|
|
299
|
+
* NaanIDE_version.txt - [default] substitution file defining 1.7.1+1 etc.
|
|
300
300
|
* NaanIDE_version_builds.txt - [default] contains current build number as decimal string
|
|
301
301
|
* build/ - [optional] default build output location
|
|
302
302
|
* NaanIDE.lic - [optional] defines Zulch Laboratories, Inc. and other license info
|
|
@@ -646,7 +646,7 @@ closure projConfig(projman, where, projID, local procon, fs, configpath) {
|
|
|
646
646
|
if builder.refresh()
|
|
647
647
|
buildonly = !buildonly // reverse if refresh
|
|
648
648
|
if !buildonly
|
|
649
|
-
`(error) = builder.run()
|
|
649
|
+
`(error) = builder.run(stage)
|
|
650
650
|
}
|
|
651
651
|
builder.destroy()
|
|
652
652
|
procon.builder = false
|
|
@@ -23,13 +23,21 @@ closure ExecutorBase(track, type, name, local exec) {
|
|
|
23
23
|
exec.type = type
|
|
24
24
|
exec.name = name
|
|
25
25
|
exec.contexts = { }
|
|
26
|
-
|
|
26
|
+
|
|
27
27
|
// execReset
|
|
28
28
|
//
|
|
29
29
|
// Initialize remote communications for a new or restarted instance.
|
|
30
30
|
//
|
|
31
|
-
exec.execReset = function execReset() {
|
|
31
|
+
exec.execReset = function execReset(error, local xid, pending) {
|
|
32
|
+
if !error
|
|
33
|
+
error = Error("execReset")
|
|
34
|
+
for `(xid, pending) in exec.pending {
|
|
35
|
+
pending.signal(list(error))
|
|
36
|
+
exec.pending[xid] = undefined
|
|
37
|
+
}
|
|
32
38
|
exec.pending = { }
|
|
39
|
+
exec.inst_ready = false
|
|
40
|
+
exec.inst_error = undefined
|
|
33
41
|
exec.nextSendID = toint(RandomBytes(3)) // keep our sequence code unique for shared servers
|
|
34
42
|
}
|
|
35
43
|
execReset()
|
|
@@ -52,7 +60,7 @@ closure ExecutorBase(track, type, name, local exec) {
|
|
|
52
60
|
pending.signal(Error("execSend failed", error))
|
|
53
61
|
pending
|
|
54
62
|
}
|
|
55
|
-
|
|
63
|
+
|
|
56
64
|
// execReceived
|
|
57
65
|
//
|
|
58
66
|
// The specified message was received from the instance, so signal it.
|
|
@@ -81,7 +89,7 @@ closure ExecutorBase(track, type, name, local exec) {
|
|
|
81
89
|
exec.pending[data.xid] = undefined
|
|
82
90
|
pending.signal(list(false, data))
|
|
83
91
|
}
|
|
84
|
-
|
|
92
|
+
|
|
85
93
|
// execSetStatus
|
|
86
94
|
//
|
|
87
95
|
// Received a status update from the instance. This makes a copy of the specified dictionary for
|
|
@@ -93,7 +101,7 @@ closure ExecutorBase(track, type, name, local exec) {
|
|
|
93
101
|
exec.execSetStatus = function execSetStatus(status) {
|
|
94
102
|
exec.xstatus = new(status) // for GC (!)
|
|
95
103
|
}
|
|
96
|
-
|
|
104
|
+
|
|
97
105
|
// execFailed
|
|
98
106
|
//
|
|
99
107
|
// Communication has failed.
|
|
@@ -103,19 +111,15 @@ closure ExecutorBase(track, type, name, local exec) {
|
|
|
103
111
|
for `(xid, pending) in exec.pending
|
|
104
112
|
pending.signal(list(error))
|
|
105
113
|
}
|
|
106
|
-
|
|
114
|
+
|
|
107
115
|
// execClosed
|
|
108
116
|
//
|
|
109
|
-
//
|
|
110
117
|
// Note that the connection has closed, so signal all the waiters.
|
|
111
118
|
//
|
|
112
|
-
exec.execClosed = closure execClosed(error
|
|
113
|
-
|
|
114
|
-
pending.signal(list(error))
|
|
115
|
-
exec.pending[xid] = undefined
|
|
116
|
-
}
|
|
119
|
+
exec.execClosed = closure execClosed(error) {
|
|
120
|
+
execReset(error)
|
|
117
121
|
}
|
|
118
|
-
|
|
122
|
+
|
|
119
123
|
// context
|
|
120
124
|
//
|
|
121
125
|
// Return a context object for the instance, or an error, in a result tuple. The optional state
|
|
@@ -157,7 +161,7 @@ closure ExecutorBase(track, type, name, local exec) {
|
|
|
157
161
|
exec.attention = function attention() {
|
|
158
162
|
track.attention(exec)
|
|
159
163
|
}
|
|
160
|
-
|
|
164
|
+
|
|
161
165
|
// finis
|
|
162
166
|
exec
|
|
163
167
|
};
|
|
@@ -220,6 +224,8 @@ closure ExecutorContext(exec, state, coder, local context, util) {
|
|
|
220
224
|
// an optional tuple of symbols to retrieve after evaluation.
|
|
221
225
|
//
|
|
222
226
|
context.eval = closure evalf(expr, put, get, local roots, pkg, data, pending, result) {
|
|
227
|
+
if !exec.inst_ready
|
|
228
|
+
return (list(Error("execution context closed")))
|
|
223
229
|
if tuple(put)
|
|
224
230
|
roots = cons(`expr, put)
|
|
225
231
|
else
|
|
@@ -288,6 +294,8 @@ closure ExecutorContext(exec, state, coder, local context, util) {
|
|
|
288
294
|
// The procedure must be specified as a symbol or string.
|
|
289
295
|
//
|
|
290
296
|
context.rpc = closure rpc(proc, args, local data, pending, result) {
|
|
297
|
+
if !exec.inst_ready
|
|
298
|
+
return (list(Error("execution context closed")))
|
|
291
299
|
data = {
|
|
292
300
|
contextID: state.contextID
|
|
293
301
|
proc: proc
|
|
@@ -611,7 +619,7 @@ closure ExecutorTracker(local xtrak) {
|
|
|
611
619
|
}
|
|
612
620
|
|
|
613
621
|
// add
|
|
614
|
-
// Add an execution instance
|
|
622
|
+
// Add an execution instance.
|
|
615
623
|
|
|
616
624
|
xtrak.add = closure add(executor, local instance) {
|
|
617
625
|
instance = new(nonce)
|