@naanlang/naan 1.4.4 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/LICENSE.md +2 -2
  2. package/README.md +4 -4
  3. package/bin/index.js +25 -3
  4. package/dist/env_web.js +164 -22
  5. package/dist/naan.min.js +5 -5
  6. package/frameworks/browser/browser.nlg +2 -2
  7. package/frameworks/browser/https_request.nlg +2 -2
  8. package/frameworks/browser/sworker.js +28 -26
  9. package/frameworks/browser/terminals.nlg +342 -700
  10. package/frameworks/browser/worker.nlg +255 -0
  11. package/frameworks/browser/workers.nlg +5 -5
  12. package/frameworks/browser/ws_client.nlg +15 -10
  13. package/frameworks/client/apiclient.nlg +204 -19
  14. package/frameworks/client/client.nlg +22 -2
  15. package/frameworks/client/psm_client.nlg +12 -3
  16. package/frameworks/client/relaycon.nlg +87 -161
  17. package/frameworks/common/events.nlg +101 -0
  18. package/frameworks/common/repltools.nlg +80 -1
  19. package/frameworks/node/apiserver.nlg +39 -246
  20. package/frameworks/node/filesystem.nlg +39 -12
  21. package/frameworks/node/gitter.nlg +9 -7
  22. package/frameworks/node/http_request.nlg +34 -13
  23. package/frameworks/node/https_request.nlg +8 -3
  24. package/frameworks/node/node.nlg +2 -0
  25. package/frameworks/node/pty.nlg +346 -0
  26. package/frameworks/node/shell.nlg +4 -4
  27. package/frameworks/node/worker.nlg +409 -539
  28. package/frameworks/node/ws_client.nlg +2 -2
  29. package/frameworks/project/build.nlg +1 -1
  30. package/frameworks/project/projects.nlg +2 -1
  31. package/frameworks/running/debugnub.nlg +17 -4
  32. package/frameworks/running/executors.nlg +27 -274
  33. package/frameworks/running/instances.nlg +393 -0
  34. package/frameworks/running/remote_req.nlg +143 -0
  35. package/frameworks/running/remote_res.nlg +89 -0
  36. package/frameworks/running/taskexec.nlg +2 -2
  37. package/frameworks/service/imp.nlg +736 -0
  38. package/frameworks/service/model.nlg +71 -0
  39. package/frameworks/service/nubnode.nlg +105 -0
  40. package/frameworks/service/nubweb.nlg +106 -0
  41. package/frameworks/service/service.nlg +28 -0
  42. package/frameworks/storage/dbt_pouch.nlg +26 -13
  43. package/frameworks/storage/psm.nlg +39 -5
  44. package/frameworks/storage/psm_dbtables.nlg +10 -2
  45. package/lib/browser/env_web.js +171 -29
  46. package/lib/browser/env_webworker.js +91 -5
  47. package/lib/core/naanlib.js +5 -5
  48. package/lib/env_node.js +184 -8
  49. package/lib/env_nodeworker.js +74 -1
  50. package/package.json +1 -1
  51. package/plugins/serviceAws/aws_cloudwatchlogs.nlg +2 -1
  52. package/plugins/serviceAws/aws_dynamo.nlg +1 -0
  53. package/plugins/serviceAws/aws_s3.nlg +3 -3
  54. package/plugins/serviceAws/aws_sqs.nlg +3 -1
  55. package/plugins/serviceAws/aws_utils.nlg +3 -1
  56. package/plugins/serviceAws/dbt_aws.nlg +22 -20
  57. package/plugins/serviceAws/psm_aws.nlg +2 -1
  58. package/plugins/serviceNexara/speechrec.nlg +10 -6
  59. package/test/test_02_context.nlg +24 -1
  60. package/test/test_03_jsinterop.nlg +32 -3
  61. package/plugins/serviceGC/russian_trusted_root_ca_pem.crt +0 -33
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * column positioning: // // !
7
7
  *
8
- * Copyright (c) 2023-2024 by Richard C. Zulch
8
+ * Copyright (c) 2023-2026 by Richard C. Zulch
9
9
  *
10
10
  */
11
11
 
@@ -13,7 +13,7 @@
13
13
  /*
14
14
  * WebSocket
15
15
  *
16
- * Create a WebSocket client connection object using the existing HTTPS connection.
16
+ * Create a WebSocket client connection object.
17
17
  *
18
18
  * Required:
19
19
  * host: <string> // host:port
@@ -1217,7 +1217,7 @@ closure Builder(rules, operation, fs, srcpath, destpath, track, local build, gro
1217
1217
  error = Error("Builder: cannot read main file", error)
1218
1218
  else {
1219
1219
  `(error, executor) = track.spawn(build.runway.spawn.0, "${rules.name} ${build.version}", {
1220
- workerID: "Run-${build.buildnum}"
1220
+ workerID: "Run-${build.version}+${build.buildnum}"
1221
1221
  startup: {
1222
1222
  initcmds: maintext
1223
1223
  dirpath: fs.path.resolve("/", fs.rootpath, build.destpath)
@@ -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.4.4+1 etc.
299
+ * NaanIDE_version.txt - [default] substitution file defining 1.6.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
@@ -692,6 +692,7 @@ closure projConfig(projman, where, projID, local procon, fs, configpath) {
692
692
  erase: true
693
693
  overwrite: true
694
694
  follow: true
695
+ cacheControl: publish.cacheControlFiles
695
696
  })
696
697
  }
697
698
 
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * column positioning: // // !
7
7
  *
8
- * Copyright (c) 2021-2024 by Richard C. Zulch
8
+ * Copyright (c) 2021-2026 by Richard C. Zulch
9
9
  *
10
10
  */
11
11
 
@@ -33,7 +33,6 @@ closure DebugNub(local nub, debug, paused) {
33
33
  nub.codemgr = CodeManager()
34
34
  nub.exenable = true
35
35
  nub.watches = []
36
- nub.contIDs = new(weakmap)
37
36
  nub.stacks = { }
38
37
  nub.usage = { }
39
38
 
@@ -405,8 +404,17 @@ closure DebugNub(local nub, debug, paused) {
405
404
  // Get the location of a procdef.
406
405
 
407
406
  nub.procLoc = function procLoc(procdef, task, local comp, position) {
408
- if !task
407
+ if !task {
408
+ if nub.procLocs[procdef]
409
+ return // use the cached value
409
410
  task = rrrest(procdef)
411
+ if task {
412
+ if !nub.procLocs
413
+ nub.procLocs = new(weakmap) // make sure we have a weakmap
414
+ nub.procLocs[procdef] = procLoc(procdef, task) // cache a new location
415
+ return
416
+ }
417
+ }
410
418
  comp = nub.codemgr.procComponent(procdef)
411
419
  position = comp.textpos(procdef, task)
412
420
  {
@@ -424,8 +432,11 @@ closure DebugNub(local nub, debug, paused) {
424
432
 
425
433
  nub.getContID = function getContID(cont, local contID, frames) {
426
434
  contID = nub.contIDs[cont]
427
- if !contID
435
+ if !contID {
436
+ if !nub.contIDs
437
+ nub.contIDs = new(weakmap) // make sure we have a weakmap
428
438
  nub.contIDs[cont] = contID = UUID()
439
+ }
429
440
  frames = cont.stacktrace().toarray
430
441
  if frames.slice(-1).0 == `interrupt
431
442
  frames.pop()
@@ -580,6 +591,8 @@ closure DebugNub(local nub, debug, paused) {
580
591
  frames = new(nub.stacks[contID])
581
592
  else
582
593
  frames = new(debug.frames)
594
+ if !array(frames)
595
+ return (false) // invalid frames array
583
596
  loop {
584
597
  if frames.length == 0
585
598
  break
@@ -338,7 +338,7 @@ closure ExecutorContext(exec, state, coder, local context, util) {
338
338
  *
339
339
  */
340
340
 
341
- closure ExecutorParallel(track, options, local maxcount, parallel, exqueue, crValue) {
341
+ closure ExecutorParallel(track, options, local maxcount, parallel, state, exqueue, crValue) {
342
342
  global()
343
343
  options = merge({
344
344
  spawnLoc: "Local"
@@ -348,9 +348,10 @@ closure ExecutorParallel(track, options, local maxcount, parallel, exqueue, crVa
348
348
  maxcount = options.maxcount
349
349
  exqueue = [] // waiting for execution
350
350
  parallel = new(object, this)
351
- parallel.workers = [] // array of worker executors
351
+ parallel.state = state = new(nonce) // volatile state
352
352
  parallel.contexts = new(weakmap) // map workers to contexts
353
- parallel.available = [] // array of available workers
353
+ state.workers = [] // array of worker executors
354
+ state.available = [] // array of available workers
354
355
 
355
356
  // acquireWorker
356
357
  //
@@ -359,31 +360,31 @@ closure ExecutorParallel(track, options, local maxcount, parallel, exqueue, crVa
359
360
  // returns { wait: true }.
360
361
 
361
362
  closure acquireWorker(local workdex, name, worker, context, result) {
362
- if parallel.available.length > 0
363
- return (list(false, parallel.available.pop()))
364
- workdex = parallel.workers.length
363
+ if state.available.length > 0
364
+ return (list(false, state.available.pop()))
365
+ workdex = state.workers.length
365
366
  if workdex >= maxcount
366
367
  return (list(false, { wait: true }))
367
- parallel.workers[workdex] = false // reserve our spot
368
+ state.workers[workdex] = false // reserve our spot
368
369
  name = options.basename.concat("-", workdex+1)
369
370
  worker = track.spawn(options.spawnLoc, name, {
370
371
  workerID: "ExecutorParallel"
371
372
  })
372
373
  if worker.0 {
373
- parallel.workers.splice(workdex, 1)
374
+ state.workers.splice(workdex, 1)
374
375
  debuglog("execParallel: cannot spawn worker:", ErrorString(worker.0))
375
376
  return (list(worker.0))
376
377
  }
377
378
  worker = worker.1
378
379
  context = worker.context()
379
380
  if context.0 {
380
- parallel.workers.splice(workdex, 1)
381
+ state.workers.splice(workdex, 1)
381
382
  worker.destroy()
382
383
  debuglog("execParallel: cannot create worker context:", ErrorString(context.0))
383
384
  return (list(context.0))
384
385
  }
385
386
  context = context.1
386
- parallel.workers[workdex] = worker
387
+ state.workers[workdex] = worker
387
388
  parallel.contexts[worker] = context
388
389
  if tuple(options.initeval) {
389
390
  result = apply(context.eval, options.initeval)
@@ -398,7 +399,7 @@ closure ExecutorParallel(track, options, local maxcount, parallel, exqueue, crVa
398
399
  // Release the specified worker to the pool.
399
400
 
400
401
  closure releaseWorker(worker) {
401
- parallel.available.push(worker)
402
+ state.available.push(worker)
402
403
  }
403
404
 
404
405
  // execNext
@@ -414,7 +415,7 @@ closure ExecutorParallel(track, options, local maxcount, parallel, exqueue, crVa
414
415
  if exqueue.length > 0 {
415
416
  `(error, worker) = acquireWorker()
416
417
  if error {
417
- if maxcount > 0 && parallel.workers.length == 0 {
418
+ if maxcount > 0 && state.workers.length == 0 {
418
419
  exqueue = []
419
420
  throw("execParallel: cannot allocate any workers at all") }
420
421
  return // one failed, so try again later
@@ -448,8 +449,10 @@ closure ExecutorParallel(track, options, local maxcount, parallel, exqueue, crVa
448
449
  //
449
450
 
450
451
  parallel.eval = closure evalf(expr, put, get, local pending) {
451
- if maxcount == 0
452
+ if maxcount == 0 || !parallel.state {
453
+ destroy(list(Error("volatile execution terminated"))) // in case of no state
452
454
  return (crValue) // already destroyed
455
+ }
453
456
  pending = new(nonce)
454
457
  exqueue.push({
455
458
  eval: list(expr, put, get)
@@ -516,8 +519,10 @@ closure ExecutorParallel(track, options, local maxcount, parallel, exqueue, crVa
516
519
  //
517
520
 
518
521
  parallel.rpc = closure rpc(proc, args, local pending) {
519
- if maxcount == 0
522
+ if maxcount == 0 || !parallel.state {
523
+ destroy(list(Error("volatile execution terminated"))) // in case of no state
520
524
  return (crValue) // already destroyed
525
+ }
521
526
  pending = new(nonce)
522
527
  exqueue.push({
523
528
  proc: proc
@@ -539,11 +544,11 @@ closure ExecutorParallel(track, options, local maxcount, parallel, exqueue, crVa
539
544
 
540
545
  parallel.status = function status(local output, worker) {
541
546
  output = []
542
- for worker in parallel.workers {
547
+ for worker in state.workers {
543
548
  output.push({
544
549
  name: worker.name
545
550
  type: worker.type
546
- state: if parallel.available.indexOf(worker) >= 0
551
+ state: if state.available.indexOf(worker) >= 0
547
552
  "idle" else "active"
548
553
  status: worker.xstatus
549
554
  })
@@ -561,10 +566,10 @@ closure ExecutorParallel(track, options, local maxcount, parallel, exqueue, crVa
561
566
  return (false) // already destroyed
562
567
  crValue = cancelResult
563
568
  maxcount = 0
564
- parallel.available = false
569
+ state.available = false
565
570
  parallel.contexts = false
566
- while parallel.workers.length > 0 {
567
- worker = parallel.workers.pop()
571
+ while state.workers.length > 0 {
572
+ worker = state.workers.pop()
568
573
  parallel.contexts[worker] = false
569
574
  worker.destroy()
570
575
  }
@@ -584,7 +589,7 @@ closure ExecutorParallel(track, options, local maxcount, parallel, exqueue, crVa
584
589
  /*
585
590
  * ExecutorTracker
586
591
  *
587
- * Track Naan execution instances.
592
+ * Track Naan execution instances.
588
593
  *
589
594
  */
590
595
 
@@ -667,7 +672,7 @@ closure ExecutorTracker(local xtrak) {
667
672
  // register
668
673
  // Register an executor type.
669
674
 
670
- xtrak.register = function register(maker, type) {
675
+ xtrak.register = function register(type, maker) {
671
676
  xtrak.makers[type] = maker
672
677
  }
673
678
 
@@ -690,262 +695,11 @@ closure ExecutorTracker(local xtrak) {
690
695
  ExecutorParallel(xtrak, options)
691
696
  }
692
697
 
693
- xtrak.register(execLambda, "Lambda")
694
-
695
698
  // finis
696
699
  xtrak
697
700
  };
698
701
 
699
702
 
700
- /*
701
- * execLambda
702
- *
703
- * Make a Lambda executor connected through web sockets.
704
- *
705
- */
706
-
707
- closure execLambda(track, url, name, workerID, local target, nlregex, clientID, serverID) {
708
- global(js)
709
- target = ExecutorBase(track, "Lambda", name)
710
- clientID = "DebugWorkers"
711
- serverID = "Workers"
712
- nlregex = RegExp("\\n", "g")
713
- if !workerID
714
- workerID = "myAwsDebugWorker"
715
- target.workerID = workerID
716
- target.msgQueue = []
717
-
718
- // connect
719
- // Connect with the host if not already connected.
720
- function connect() {
721
- if !target.ws
722
- target.ws = xnew(js.w.WebSocket, "wss://8h5htw8bfj.execute-api.us-east-1.amazonaws.com/dev")
723
-
724
- // onopen
725
- // The WebSocket connection is now open.
726
- target.ws.onopen = function onopen(e) {
727
- target.msgCounter = 1
728
- sendControl("spawn", {
729
- reset: true
730
- options: {
731
- }
732
- })
733
- }
734
-
735
- // onmessage
736
- // A message was received from the worker via WebSockets.
737
-
738
- target.ws.onmessage = function onmessage(e) {
739
- if target.msgQueue
740
- target.msgQueue.push(e.data)
741
- else
742
- target.doMessage(e.data)
743
- }
744
-
745
- // onerror
746
- // An error occurred on the WebSocket connection.
747
- target.ws.onerror = function onerror(e) {
748
- target.debugWrite("connection error: ".concat(e.toString()), 3)
749
- }
750
-
751
- // onclose
752
- // The WebSocket connection was closed.
753
- target.ws.onclose = function onclose(e) {
754
- target.debugWrite("connection closed: ".concat(e.code, " ", e.reason), 3)
755
- target.ws = false
756
- }
757
- }
758
-
759
- //
760
- // doOneMessage
761
- //
762
- // Process the specified undecoded message.
763
- function doOneMessage(message, local msg) {
764
- if message.respOp == "msgarray" {
765
- for msg in message.payload
766
- doOneMessage(msg)
767
- } else if message.respOp == "msgout" {
768
- msg = message.payload
769
- if msg.id == "textout" {
770
- target.written = true
771
- target.term.Write(msg.text.replace(nlregex, "\r\n")) }
772
- else if msg.id == "debugtext" {
773
- target.written = true
774
- target.debugWrite(msg.text, msg.level) }
775
- else if msg.id == "msgout"
776
- target.listener(msg.data)
777
- else if msg.id == "started"
778
- { }
779
- else if msg.id == "typed"
780
- target.term.Write(msg.text.replace(nlregex, "\r\n"))
781
- else if msg.id == "status"
782
- target.statusCB(target, msg.status)
783
- else
784
- debuglog("unknown AWS worker message:", msg.id)
785
- } else if message.respOp == "error"
786
- debuglog("worker controller error:", ErrorString(message.payload[0]))
787
- else if message.respOp == "linked"
788
- future(function termLinked(){
789
- if !target.written
790
- target.term.WriteLn("(reconnected)")
791
- }, 1000).run()
792
- else
793
- debuglog("unknown AWS response message:", message.respOp)
794
- }
795
-
796
- //
797
- // doMessage
798
- //
799
- // Process the specified undecoded message.
800
- target.doMessage = function doMessage(text, local message) {
801
- try {
802
- message = new(js.w.JSON.parse(text))
803
- if message.connectionId && string(message.message)
804
- target.debugWrite("AWS response: ".concat(message.message), 3)
805
- else if message.clientID != clientID || message.serverID != serverID || message.workerID != target.workerID
806
- debuglog("AWS response doesn't match:", message.clientID, message.serverID, message.workerID)
807
- else
808
- doOneMessage(message)
809
- } catch {
810
- if true
811
- return (debuglog("can't decode incoming ws message:", exception))
812
- }
813
- }
814
-
815
- //
816
- // sendControl
817
- //
818
- // Send a message to the worker controller.
819
-
820
- target.sendControl = function sendControl(workerOp, payload) {
821
- target.ws.send(js.w.JSON.stringify({
822
- clientID: clientID
823
- serverID: serverID
824
- workerID: target.workerID
825
- workerOp: workerOp
826
- payload: payload
827
- msgCounter: target.msgCounter++
828
- }))
829
- }
830
-
831
- //
832
- // send
833
- //
834
- // Send a message to the worker.
835
-
836
- target.send = function send(msg) {
837
- // msg.save = true // save state for this invocation
838
- sendControl("msgin", msg)
839
- }
840
-
841
- //
842
- // oninterrupt
843
- //
844
-
845
- function oninterrupt() {
846
- send({ // send interrupt to worker
847
- id: "interrupt"
848
- })
849
- }
850
-
851
- //
852
- // onreturn
853
- //
854
-
855
- function onreturn(local text) {
856
- text = target.term.TakeText()
857
- send({ // send user-entered text to worker
858
- id: "keyline",
859
- text: text,
860
- typed: "\x1b[90m\x1b[3m".concat(text, "\x1b[0m\n") // dark-grey, italic
861
- })
862
- }
863
-
864
- //
865
- // target.PostMessage
866
- //
867
- // Post a message to the target.
868
- //
869
-
870
- target.PostMessage = function PostMessage(data, local result) {
871
- result = connect()
872
- if result.0
873
- return (result)
874
- target.ws.send({ // send user-entered text to worker
875
- id: "msgin",
876
- data: data
877
- })
878
- list(false, { posted: true })
879
- }
880
-
881
- //
882
- // target.debugWrite
883
- //
884
- // Write a debug message to the repl.
885
- //
886
-
887
- target.debugWrite = function(text, level) {
888
- if (level >= 5)
889
- target.term.WriteLn(text, target.term.Cyan) // cyan for builtin logging
890
- else if (level >= 4)
891
- target.term.WriteLn(text, target.term.Blue) // blue for Naan function logging
892
- else if (level >= 3)
893
- target.term.WriteLn(text, target.term.Red) // light red for warnings
894
- else if (level >= 2)
895
- target.term.WriteLn(text, target.term.Green) // green for Naan.debug.debuglog logging
896
- else
897
- target.term.WriteLn(text, target.term.Red+target.term.Bold) // heavy red for errors
898
- }
899
-
900
- //
901
- // termAttach
902
- //
903
- // A terminal was attached to our instance.
904
-
905
- target.termAttach = function termAttach(repl, db, statusCB, local msg) {
906
- connect() // ensure we are connected
907
- target.term = repl
908
- target.debugger = db
909
- target.statusCB = statusCB
910
- if target.termSaved {
911
- target.term.StateLoad(target.termSaved)
912
- target.termSaved = false }
913
- else
914
- target.term.Reset()
915
- while target.msgQueue.length > 0 {
916
- for msg in target.msgQueue.splice(0) // all current messages
917
- target.doMessage(msg)
918
- }
919
- target.msgQueue = false
920
- target.term.On("interrupt", oninterrupt.proc)
921
- target.term.On("return", onreturn.proc)
922
- target.term.Focus()
923
- }
924
-
925
- //
926
- // termDetach
927
- //
928
- // The terminal is being deattached from our instance.
929
-
930
- target.termDetach = function termDetach(repl) {
931
- target.term.On("interrupt")
932
- target.term.On("return")
933
- target.msgQueue = []
934
- target.termSaved = target.term.StateSave()
935
- target.statusCB = false
936
- target.debugger = false
937
- target.term = false
938
- }
939
-
940
- track.add(target)
941
- connect() // connect right away to start receiving messages
942
-
943
- // finis
944
-
945
- list(false, target)
946
- };
947
-
948
-
949
703
  /*
950
704
  * execInit
951
705
  *
@@ -954,8 +708,7 @@ closure execLambda(track, url, name, workerID, local target, nlregex, clientID,
954
708
  */
955
709
 
956
710
  function execInit(local manifest) {
957
- manifest = `(ExecutorBase, ExecutorContext, ExecutorParallel, ExecutorTracker, execLambda,
958
- execInit)
711
+ manifest = `(ExecutorBase, ExecutorContext, ExecutorParallel, ExecutorTracker, execInit)
959
712
 
960
713
  Naan.module.build(module.id, "executors", function(modobj, compobj) {
961
714
  require("./running.nlg")