@naanlang/naan 1.0.16 → 1.1.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.
Files changed (41) hide show
  1. package/LICENSE.md +2 -2
  2. package/README.md +2 -2
  3. package/bin/index.js +4 -4
  4. package/dist/naan.min.js +6 -6
  5. package/frameworks/browser/https_request.nlg +23 -9
  6. package/frameworks/browser/sworker.js +26 -25
  7. package/frameworks/browser/terminals.nlg +56 -15
  8. package/frameworks/browser/ws_client.nlg +124 -0
  9. package/frameworks/client/apiclient.nlg +3 -2
  10. package/frameworks/client/psm_client.nlg +1 -1
  11. package/frameworks/client/relaycon.nlg +308 -0
  12. package/frameworks/common/common.nlg +1 -1
  13. package/frameworks/common/utils.nlg +40 -2
  14. package/frameworks/node/apiserver.nlg +342 -103
  15. package/frameworks/node/https_request.nlg +30 -5
  16. package/frameworks/node/node.nlg +60 -2
  17. package/frameworks/node/psm_server.nlg +9 -5
  18. package/frameworks/node/worker.nlg +22 -9
  19. package/frameworks/node/ws_client.nlg +127 -0
  20. package/frameworks/project/build.nlg +2 -2
  21. package/frameworks/project/projects.nlg +8 -2
  22. package/frameworks/running/debugnub.nlg +2 -2
  23. package/frameworks/running/debugutil.nlg +1 -1
  24. package/frameworks/running/executors.nlg +59 -12
  25. package/frameworks/running/sourcecode.nlg +2 -2
  26. package/frameworks/running/taskexec.nlg +23 -24
  27. package/frameworks/storage/dbt_pouch.nlg +8 -6
  28. package/frameworks/storage/file_manager.nlg +6 -3
  29. package/frameworks/storage/psm.nlg +3 -2
  30. package/frameworks/storage/psm_dbtables.nlg +53 -41
  31. package/frameworks/storage/resources.nlg +4 -2
  32. package/lib/browser/env_web.js +6 -6
  33. package/lib/browser/env_webworker.js +1 -1
  34. package/lib/core/naanlib.js +6 -6
  35. package/lib/env_node.js +97 -8
  36. package/lib/env_nodeworker.js +22 -4
  37. package/package.json +1 -1
  38. package/plugins/serviceAws/aws/lambda_rest_index.js +5 -1
  39. package/plugins/serviceAws/dbt_aws.nlg +2 -2
  40. package/plugins/serviceAws/psm_aws.nlg +2 -2
  41. package/test/test_01_core.nlg +30 -4
@@ -6,11 +6,66 @@
6
6
  *
7
7
  * column positioning: // // !
8
8
  *
9
- * Copyright (c) 2020-2021 by Richard C. Zulch
9
+ * Copyright (c) 2020-2024 by Richard C. Zulch
10
10
  *
11
11
  */
12
12
 
13
13
 
14
+ /*
15
+ * NaanlangDir
16
+ *
17
+ * Ensure the naanlang directory exists, returning a result tuple.
18
+ *
19
+ */
20
+
21
+ closure NaanlangDir(local path, errmkdir, errstat, stat) {
22
+ global(JSpath, os, App, fs)
23
+ path = JSpath.join(os.homedir(), ".naanlang/")
24
+ `(errmkdir) = await(fs.promises.mkdir(path))
25
+ if errmkdir.code == "EEXIST" {
26
+ `(errstat, stat) = await(fs.promises.stat(path))
27
+ if errstat || !stat.isDirectory()
28
+ return (list(Error("mkdir conflict:", errmkdir))) // file in the way
29
+ }
30
+ else if errmkdir
31
+ return (list(Error("mkdir failed:", errmkdir)))
32
+ await(fs.promises.mkdir(JSpath.join(path, "nidecom"))) // ignore errors here
33
+ App.config = merge({
34
+ prefsdir: path
35
+ })
36
+ list(false, path)
37
+ };
38
+
39
+
40
+ /*
41
+ * NaanlangRC
42
+ *
43
+ * Return the naanlang RC file if found, or an empty dictionary otherwise.
44
+ *
45
+ */
46
+
47
+ closure NaanlangRC(local path, error, config) {
48
+ global(JSpath, fs, App)
49
+ `(error, path) = NaanlangDir()
50
+ if path {
51
+ path = JSpath.join(path, "naanlangrc")
52
+ `(error, config) = await(fs.promises.readFile(path, {
53
+ encoding: "utf8"
54
+ }))
55
+ if !error
56
+ `(error, config) = JsonParse(config)
57
+ }
58
+ if config
59
+ App.config = merge({
60
+ rcpath: path
61
+ config: config
62
+ })
63
+ else
64
+ config = { }
65
+ config
66
+ };
67
+
68
+
14
69
  /*
15
70
  * NodeStreamLiner
16
71
  *
@@ -63,7 +118,7 @@ closure NodeStreamLiner(endings, local liner) {
63
118
  */
64
119
 
65
120
  function nodrInit(local manifest) {
66
- manifest = `(NodeStreamLiner, nodrInit)
121
+ manifest = `(NaanlangDir, NaanlangRC, NodeStreamLiner, nodrInit)
67
122
 
68
123
  if !js.g
69
124
  throw("module frameworks/node cannot be used from a browser")
@@ -77,7 +132,10 @@ function nodrInit(local manifest) {
77
132
  stream = js.r("stream")
78
133
  nodeHttps = js.r("https")
79
134
  nodeUrl= js.r("url")
135
+ threads = js.r("worker_threads")
80
136
  }()
81
137
  module.reload = nodrReload
138
+ module.exports.NaanlangDir = NaanlangDir
139
+ module.exports.NaanlangRC = NaanlangRC
82
140
  })
83
141
  } ();
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * column positioning: // // !
8
8
  *
9
- * Copyright (c) 2019-2022 by Richard C. Zulch
9
+ * Copyright (c) 2019-2023 by Richard C. Zulch
10
10
  *
11
11
  */
12
12
 
@@ -517,13 +517,17 @@ closure psmsFsConnector(psm, api, local connClassID, connector, watch) {
517
517
  *
518
518
  */
519
519
 
520
- function MakeServerPSM(api, local importPSM) {
520
+ function MakeServerPSM(api, name, local importPSM, error, path, psm) {
521
521
  importPSM = require("../storage/psm.nlg")
522
- App.psm = importPSM.MakePSM(JSpath.resolve(js.d, "NideDB")).1
523
- if App.psm {
522
+ `(error, path) = NaanlangDir() // put database in ~/.naanlang/
523
+ if !error
524
+ `(error, psm) = importPSM.MakePSM(JSpath.join(path, "${name}DB_${api.port.tostring}"))
525
+ if !error {
526
+ App.psm = psm
524
527
  psmsFsConnector(App.psm, api)
525
528
  require("frameworks/storage/dbt_pouch.nlg").DbConnector(App.psm) // Pouch databases as filesystems
526
- }
529
+ } else
530
+ ErrorDebuglog("Cannot create PSM", error)
527
531
  App.psm
528
532
  };
529
533
 
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * column positioning: // // !
8
8
  *
9
- * Copyright (c) 2019-2021 by Richard C. Zulch
9
+ * Copyright (c) 2019-2024 by Richard C. Zulch
10
10
  *
11
11
  */
12
12
 
@@ -18,9 +18,11 @@
18
18
  *
19
19
  */
20
20
 
21
- closure workCurrent(workerID, local current) {
21
+ closure workCurrent(workerID, startup, local current) {
22
+ global()
22
23
  current = new(object, this)
23
24
  current.workerID = workerID
25
+ current.name = startup.name
24
26
  current.links = []
25
27
  current.termif = xnew({
26
28
  textout: ONtextOut.proc
@@ -177,14 +179,17 @@ closure workCurrent(workerID, local current) {
177
179
  *
178
180
  */
179
181
 
180
- closure workThread(workerID, startup, local worker, subChannel, deathWatcher) {
182
+ closure workThread(workerID, startup, local worker, options, subChannel, deathWatcher) {
183
+ global(threads, JSpath)
181
184
  worker = new(object, this)
185
+ worker.name = startup.name
182
186
  worker.workerID = workerID
183
187
  worker.links = []
184
188
 
185
189
  // create our worker thread
186
190
 
187
- worker.thread = xnew(threads.Worker, JSpath.resolve(js.d, "node_worker.js"))
191
+ // options = { execArgv: ["--inspect-brk"] } // uncomment for NodeJS debugging
192
+ worker.thread = xnew(threads.Worker, JSpath.resolve(js.d, "node_worker.js"), options)
188
193
  subChannel = xnew(threads.MessageChannel)
189
194
  worker.thread.postMessage({ hereIsYourPort: subChannel.port1 }, [subChannel.port1])
190
195
  worker.msgport = subChannel.port2
@@ -224,7 +229,7 @@ closure workThread(workerID, startup, local worker, subChannel, deathWatcher) {
224
229
 
225
230
  worker.thread.on("error", function onerror(error) {
226
231
  debuglog("worker terminated with error", workerID, error)
227
- exitNotify(exitCode)
232
+ exitNotify(-1)
228
233
  })
229
234
 
230
235
  //
@@ -341,6 +346,7 @@ closure workThread(workerID, startup, local worker, subChannel, deathWatcher) {
341
346
  */
342
347
 
343
348
  closure workLink(workco, conn, worker, sender, local link) {
349
+ global()
344
350
  link = new(object, this)
345
351
 
346
352
  //
@@ -393,6 +399,7 @@ closure workLink(workco, conn, worker, sender, local link) {
393
399
  */
394
400
 
395
401
  closure workController(api, local workco) {
402
+ global()
396
403
  workco = new(object, this)
397
404
  workco.serverID = "Workers" // our serverID, used for communications
398
405
  workco.workers = { } // dictionary of workers by workerID
@@ -480,7 +487,7 @@ closure workController(api, local workco) {
480
487
  else if message.workerOp == "spawn" {
481
488
  if !worker { // create worker if needed
482
489
  if message.workerID == "NideServer"
483
- worker = workco.current = workCurrent(message.workerID)
490
+ worker = workco.current = workCurrent(message.workerID, message.payload)
484
491
  else
485
492
  worker = workThread(message.workerID, message.payload)
486
493
  workco.workers[message.workerID] = worker }
@@ -489,7 +496,14 @@ closure workController(api, local workco) {
489
496
  if message.workerID == "NideServer"
490
497
  workco.current.vitalUpdate({
491
498
  id: "workerlist", // send the initial list of workers
492
- workerIDs: workco.workers.*
499
+ workers: let(workers, workerID, worker) {
500
+ workers = { }
501
+ for `(workerID, worker) in workco.workers
502
+ workers[workerID] = {
503
+ name: worker.name
504
+ }
505
+ workers
506
+ }()
493
507
  })
494
508
  else {
495
509
  worker.vitalWatch(termination)
@@ -516,7 +530,7 @@ closure workController(api, local workco) {
516
530
  // Note that the connection with the client was closed.
517
531
  //
518
532
 
519
- workco.wsClose = function wsClose(conn, local workerID) {
533
+ workco.wsClose = function wsClose(conn, local workerID, link) {
520
534
  for workerID in workco.workers {
521
535
  link = workco.links[conn][workerID]
522
536
  if link
@@ -553,7 +567,6 @@ function workInit(local manifest) {
553
567
 
554
568
  Naan.module.build(module.id, "worker", function(modobj, compobj) {
555
569
  require("./node.nlg")
556
- threads = js.r("worker_threads") // ### should be on reload
557
570
  compobj.manifest = manifest
558
571
  modobj.exports.WorkerController = workController
559
572
  })
@@ -0,0 +1,127 @@
1
+ /*
2
+ * ws_client.nlg
3
+ *
4
+ * WebSocket client operations for NodeJS.
5
+ *
6
+ * column positioning: // // !
7
+ *
8
+ * Copyright (c) 2023 by Richard C. Zulch
9
+ *
10
+ */
11
+
12
+
13
+ /*
14
+ * WebSocket
15
+ *
16
+ * Create a WebSocket client connection object using the existing HTTPS connection.
17
+ *
18
+ * Required:
19
+ * host: <string> // host:port
20
+ *
21
+ * Options:
22
+ * {
23
+ * onopen: <proc>(e) // connection has opened
24
+ * onmessage: <proc>(e, message) // message received
25
+ * onerror: <proc>(e) // error occurred
26
+ * onclose: <proc>(e) // connection has closed
27
+ * }
28
+ *
29
+ */
30
+
31
+ closure WebSocket(host, options, local wsock) {
32
+ global(js)
33
+ wsock = new(object, this)
34
+ options = new(options) || { }
35
+
36
+ // connect
37
+ //
38
+ // Connect with the host if not already connected, returning a result tuple.
39
+ //
40
+ wsock.connect = closure connect(local pending, error, ws) {
41
+ if wsock.ws
42
+ return (list(false, { open: true }))
43
+ `(error, ws) = await(js.i("ws"))
44
+ if error
45
+ return (list(error))
46
+ wsock.ws = xnew(ws.default, "ws://${host}")
47
+ pending = new(nonce)
48
+
49
+ // onopen
50
+ // The WebSocket connection is now open.
51
+ wsock.ws.onopen = closure onopen(e) {
52
+ pending.signal(list(false, { ok: true }))
53
+ options.onopen(e, e.target, e.type)
54
+ }
55
+
56
+ // onmessage
57
+ // A message was received from the worker via WebSockets.
58
+ wsock.ws.onmessage = closure onmessage(e, local message) {
59
+ try {
60
+ message = new(JSONparse(e.data))
61
+ } catch {
62
+ debuglog("can't decode incoming ws message:", exception)
63
+ options.onerror(Error("can't decode incoming message:", exception))
64
+ return
65
+ }
66
+ options.onmessage(e, message)
67
+ }
68
+
69
+ // onerror
70
+ // An error occurred on the WebSocket connection.
71
+ wsock.ws.onerror = closure onerror(e, local error) {
72
+ error = Error("websocket failed", e)
73
+ options.onerror(e, error)
74
+ pending.signal(list(error)) // ensure connect completes
75
+ }
76
+
77
+ // onclose
78
+ // The WebSocket connection was closed.
79
+ wsock.ws.onclose = closure onclose(e) {
80
+ options.onclose(e, e.code, e.reason)
81
+ pending.signal(list(Error("connection closed"))) // ensure connect completes
82
+ wsock.ws = false
83
+ }
84
+
85
+ pending.wait()
86
+ }
87
+
88
+ // send
89
+ //
90
+ // Send a message dictionary.
91
+ //
92
+ wsock.send = function send(message) {
93
+ wsock.ws.send(JSONstringify(message))
94
+ }
95
+
96
+ // close
97
+ //
98
+ // Close the connection.
99
+ //
100
+ wsock.close = function close(reason) {
101
+ if !reason
102
+ reason = 1000 // normal close
103
+ wsock.ws.close(reason)
104
+ }
105
+
106
+ // finis
107
+
108
+ wsock
109
+ };
110
+
111
+
112
+ /*
113
+ * ws_clientInit
114
+ *
115
+ * Initialize WebSocket client operations for browsers.
116
+ *
117
+ */
118
+
119
+ function ws_clientInit(local manifest) {
120
+ manifest = `(WebSocket, ws_clientInit)
121
+
122
+ Naan.module.build(module.id, "ws_client", function(modobj, compobj) {
123
+ require("node.nlg")
124
+ compobj.manifest = manifest
125
+ modobj.exports.WebSocket = WebSocket
126
+ })
127
+ }();
@@ -933,7 +933,7 @@ closure Builder(rules, operation, fs, srcpath, destpath, local build, group, new
933
933
  xvrFileDefs = { }
934
934
  xvrFileDefs.BuildNumber = buildno
935
935
  `(error, verFileDefs) = readSubstitutionFile(build.verfilepath, xvrFileDefs)
936
- build.version = verFileDefs["Version"]
936
+ build.version = verFileDefs["Version"].trim()
937
937
  verFileDefs["CacheBuster"] = HashMD5(build.version.concat(Math.random()))
938
938
  }
939
939
  if build.tasks.catenate > 0 || build.tasks.zip > 0 {
@@ -1195,7 +1195,7 @@ closure Builder(rules, operation, fs, srcpath, destpath, local build, group, new
1195
1195
  if error
1196
1196
  error = Error("Builder: cannot read main file", error)
1197
1197
  else {
1198
- `(error, executor) = track.spawn(build.runway.spawn.0, build.runway.spawn.1, "Build-".concat(build.buildnum), {
1198
+ `(error, executor) = track.spawn(build.runway.spawn.0, "${rules.name} ${build.version}", "Run-${build.buildnum}", {
1199
1199
  startup: {
1200
1200
  initcmds: maintext
1201
1201
  dirpath: fs.path.resolve(fs.path.sep, fs.rootpath, build.destpath)
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * column positioning: // // !
8
8
  *
9
- * Copyright (c) 2016-2022 by Richard C. Zulch
9
+ * Copyright (c) 2016-2024 by Richard C. Zulch
10
10
  *
11
11
  */
12
12
 
@@ -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.0.16+1 etc.
299
+ * NaanIDE_version.txt - [default] substitution file defining 1.1.0+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
@@ -602,6 +602,8 @@ closure projConfig(projman, where, projID, local procon, fs, configpath) {
602
602
  //
603
603
  procon.run = closure run(stage, buildonly,
604
604
  local error, rules, builder, buildpath, buildnum) {
605
+ if procon.builder
606
+ return (list(Error("build in progress")))
605
607
  `(error, rules) = buildrules(stage)
606
608
  if error
607
609
  return (list(error))
@@ -615,6 +617,7 @@ closure projConfig(projman, where, projID, local procon, fs, configpath) {
615
617
  `(error, builder) = Builder(rules, rules.operation, fs, "", buildpath)
616
618
  if error
617
619
  return (list(error))
620
+ procon.builder = builder
618
621
  `(error, buildnum) = builder.increment()
619
622
  if error {
620
623
  ErrorDebuglog("build number increment failed", error)
@@ -631,6 +634,7 @@ closure projConfig(projman, where, projID, local procon, fs, configpath) {
631
634
  `(error) = builder.run(projman.track)
632
635
  }
633
636
  builder.destroy()
637
+ procon.builder = false
634
638
  if error
635
639
  list(error)
636
640
  else
@@ -650,6 +654,8 @@ closure projConfig(projman, where, projID, local procon, fs, configpath) {
650
654
  //
651
655
  procon.publish = closure publish(stage,
652
656
  local error, rules, where, publish, outOptions, outfs, inpath) {
657
+ if procon.builder
658
+ return (list(Error("cannot publish while building")))
653
659
  `(error, rules) = buildrules(stage)
654
660
  if error
655
661
  return (list(error))
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * column positioning: // // !
7
7
  *
8
- * Copyright (c) 2021 by Richard C. Zulch
8
+ * Copyright (c) 2021-2024 by Richard C. Zulch
9
9
  *
10
10
  */
11
11
 
@@ -480,7 +480,7 @@ closure DebugNub(local nub, debug, paused) {
480
480
  locals = localist(frame)
481
481
  ns = frame.3.1.namespace
482
482
  if ns !== nsactive().0 {
483
- mod = module.owner.findModule(ns)
483
+ mod = module.owner.find(function(mod){ mod.namespace === ns })
484
484
  if mod {
485
485
  gohome = makeActivator(nsactive())
486
486
  chns(mod.id)
@@ -458,7 +458,7 @@ closure DebugRemote(commander, local remoter, here, there, library) {
458
458
  // .undefined
459
459
  // Execute methods remotely, returning a standard `(error, data) tuple.
460
460
 
461
- remoter[".undefined"] = closure remoter args {
461
+ remoter@[".undefined"] = closure remoter args {
462
462
  closure (selector, arglist, local error, context, result) {
463
463
  if !there[selector] { // not over there yet
464
464
  proc = here[selector]
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * column positioning: // // !
7
7
  *
8
- * Copyright (c) 2020-2021 by Richard C. Zulch
8
+ * Copyright (c) 2020-2023 by Richard C. Zulch
9
9
  *
10
10
  */
11
11
 
@@ -36,7 +36,7 @@ closure ExecutorBase(track, type, name, local exec) {
36
36
  // Send a message to the running instance and return a nonce to wait on. If data is not a
37
37
  // dictionary then it is ignored.
38
38
 
39
- exec.execSend = closure execSend(msg, data, local pending) {
39
+ exec.execSend = closure execSend(msg, data, local pending, error) {
40
40
  if !dictionary(data)
41
41
  data = { }
42
42
  data.xmsg = msg
@@ -44,7 +44,9 @@ closure ExecutorBase(track, type, name, local exec) {
44
44
  pending = new(nonce)
45
45
  pending.msgout = data
46
46
  exec.pending[data.xid] = pending
47
- exec.PostMessage(data)
47
+ `(error) = exec.PostMessage(data)
48
+ if error
49
+ pending.signal(Error("execSend failed", error))
48
50
  pending
49
51
  }
50
52
 
@@ -62,6 +64,15 @@ closure ExecutorBase(track, type, name, local exec) {
62
64
  pending.signal(list(false, data))
63
65
  }
64
66
 
67
+ // execFailed
68
+ // Communication has failed.
69
+
70
+ exec.execFailed = closure execFailed(error, local xid, pending) {
71
+ exec.pending.error = error
72
+ for `(xid, pending) in exec.pending
73
+ pending.signal(list(error))
74
+ }
75
+
65
76
  // execClosed
66
77
  // Note that the connection has closed, so signal all the waiters.
67
78
 
@@ -76,18 +87,25 @@ closure ExecutorBase(track, type, name, local exec) {
76
87
  // Return a context object for the instance, or an error, in a result tuple. Currently this does
77
88
  // not ever reclaim old contexts on the instance end of things, but it should. ###
78
89
 
79
- exec.context = closure context(local context, retries, ms) {
90
+ exec.context = closure context(local error, retries, ms, delta, excon) {
80
91
  retries = 0
81
92
  ms = milliseconds()
93
+ delta = 1
82
94
  while !exec.pending.ready {
83
- exec.PostMessage({
95
+ `(error) = exec.PostMessage({
84
96
  xmsg: "xstart"
85
97
  })
98
+ if error
99
+ return (Error("exec.context failed", error))
86
100
  if ++retries > 100
87
- return (list(Error("timeout creating remote worker context", type, name)))
88
- sleep(100) }
89
- context = ExecutorContext(exec, exec.nextContextID++)
90
- context.register()
101
+ return (list(Error("timeout creating remote context", type, name)))
102
+ if exec.pending.error
103
+ return (list(Error("cannot create remote context", exec.pending.error)))
104
+ sleep(delta)
105
+ if delta < 100
106
+ delta *= 2 }
107
+ excon = ExecutorContext(exec, exec.nextContextID++)
108
+ excon.register()
91
109
  }
92
110
 
93
111
  // attention
@@ -172,7 +190,28 @@ closure ExecutorContext(exec, contextID, local context, util) {
172
190
  context.evalq = macro evalq(expr, put, get) {
173
191
  evalf(expr, eval(put), eval(get))
174
192
  }
193
+
194
+ // apply
195
+ // Apply list of arguments to the specified procure evaluated remotely. If the procedure is a
196
+ // not a tuple then this uses the tuple definition if there is one.
197
+
198
+ context.apply = closure applyf(proc, args, put, get) {
199
+ if !tuple(proc) && tuple(proc.proc)
200
+ proc = proc.proc
201
+ evalf(list(apply, proc, args), eval(put), eval(get))
202
+ }
203
+
204
+ // call
205
+ // Call the specified function remotely using local arguments:
206
+ // context.call(proc, args...)
175
207
 
208
+ context.call = macro callf args {
209
+ closure (proc, arglist, local eargs) {
210
+ while arglist
211
+ push(eval(pop(arglist)), eargs)
212
+ applyf(eval(proc), eargs)
213
+ } (pop(args), reverse(args))
214
+ }
176
215
  // rpc
177
216
  // Execute a remote procedure call without package translation, to reduce overhead. This will not
178
217
  // properly transfer Naan-specific types like symbols, and the results will be native JavaScript.
@@ -187,8 +226,12 @@ closure ExecutorContext(exec, contextID, local context, util) {
187
226
  result = pending.wait()
188
227
  if result.1.error
189
228
  list(Error(result.1.error))
190
- else
191
- list(false, totuple(result.1.result))
229
+ else {
230
+ result = result.1.result
231
+ if Array.isArray(result)
232
+ result = totuple(result)
233
+ list(false, result)
234
+ }
192
235
  }
193
236
 
194
237
  // finis
@@ -670,11 +713,15 @@ closure execLambda(track, url, name, workerID, local target, nlregex, clientID,
670
713
  // Post a message to the target.
671
714
  //
672
715
 
673
- target.PostMessage = function PostMessage(data) {
716
+ target.PostMessage = function PostMessage(data, local result) {
717
+ result = connect()
718
+ if result.0
719
+ return (result)
674
720
  target.ws.send({ // send user-entered text to worker
675
721
  id: "msgin",
676
722
  data: data
677
723
  })
724
+ list(false, { posted: true })
678
725
  }
679
726
 
680
727
  //
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * column positioning: // // !
7
7
  *
8
- * Copyright (c) 2021 by Richard C. Zulch
8
+ * Copyright (c) 2021-2024 by Richard C. Zulch
9
9
  *
10
10
  */
11
11
 
@@ -59,7 +59,7 @@ closure CodeManager(options, local coman, cache)
59
59
  coman.procComponent = function procComponent(procdef, local sym, mod, modname, compname, component) {
60
60
  procdef = baseproc(rootproc(procdef)) // only work with the bases, not instances
61
61
  sym = procdef.1
62
- mod = module.owner.findModule(sym.namespace)
62
+ mod = module.owner.find(function(mod){ mod.namespace === sym.namespace })
63
63
  for `(compname, component) in mod.components
64
64
  if member(sym, component.manifest)
65
65
  return (CodeComposite(coman, component.manifest, mod.id, compname))