@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
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * column positioning: // // !
8
8
  *
9
- * Copyright (c) 2017-2024 by Richard C. Zulch
9
+ * Copyright (c) 2017-2026 by Richard C. Zulch
10
10
  *
11
11
  */
12
12
 
@@ -69,6 +69,7 @@ exports.NaanControllerWeb = function() {
69
69
 
70
70
  var naanlib = new exports.Naanlib();
71
71
  var dontSaveUntilWorking; // true when state loaded, must be reset to save state again
72
+ var dontSave; // true to avoid saving, i.e. in debugger
72
73
  var contSelf = this; // this is us, for access within nested functions
73
74
  exports.naancon = this; // access to this instance
74
75
  contSelf.anaan = naanlib.js.n;
@@ -93,8 +94,8 @@ exports.NaanControllerWeb = function() {
93
94
  function termTextOut(text, level) {
94
95
  if (!text)
95
96
  return;
96
- if (termlist.length === 0) {
97
- console.log(text); // make sure we can see early errors
97
+ if (termlist.length === 0) { // make sure we can see early errors
98
+ console.log(text.replace(/(?:\x1B[@-Z\\-_]|\x1B\[[0-?]*[ -/]*[@-~])/g, ''));
98
99
  if (!replqueue)
99
100
  replqueue = [];
100
101
  replqueue.push({text:text, level:level});
@@ -137,7 +138,7 @@ exports.NaanControllerWeb = function() {
137
138
 
138
139
 
139
140
  //==========================================================================
140
- // New Terminal Interface
141
+ // Direct Terminal Interface
141
142
  //--------------------------------------------------------------------------
142
143
 
143
144
  //
@@ -170,6 +171,7 @@ exports.NaanControllerWeb = function() {
170
171
  if (repdex < 0)
171
172
  termlist.push(terminal);
172
173
  takePending(); // output all pending terminal messages
174
+ this.ioctl_event("term-attach", "");
173
175
  };
174
176
 
175
177
  //
@@ -184,6 +186,7 @@ exports.NaanControllerWeb = function() {
184
186
  termlist.splice(repdex, 1);
185
187
  if (termlist.length === 0)
186
188
  replstate = terminal.StateSave(); // save ultimate repl state
189
+ this.ioctl_event("term-detach", "");
187
190
  };
188
191
 
189
192
  //
@@ -339,13 +342,14 @@ exports.NaanControllerWeb = function() {
339
342
  function ConsoleDebugTerminal() {
340
343
  var termSelf = this;
341
344
  //
342
- // OnMessageOut
345
+ // OnMessage
343
346
  //
344
347
  this.OnMessage = function OnMessage(msg) {
348
+ var text = msg.text.replace(/(?:\x1B[@-Z\\-_]|\x1B\[[0-?]*[ -/]*[@-~])/g, '');
345
349
  if (msg.id == "debugtext")
346
- console.log("dbug-" + msg.level + " " + msg.text);
350
+ console.log("dbug-" + msg.level + " " + text);
347
351
  else if (msg.id == "textout")
348
- console.log(msg.text);
352
+ console.log(text);
349
353
  };
350
354
  //
351
355
  // cmd
@@ -391,25 +395,31 @@ exports.NaanControllerWeb = function() {
391
395
  exports.debug = debug;
392
396
 
393
397
  //==========================================================================
394
- // Clone Debug Interface
398
+ // MessageTerminal
395
399
  //--------------------------------------------------------------------------
396
400
 
397
- function CloneDebugTerminal()
401
+ function MessageTerminal(windest, origin)
398
402
  {
399
403
  var termSelf = this;
400
404
  //
401
405
  // listen for messages
402
406
  //
403
407
  window.addEventListener("message", function (event) {
404
- if (event.origin !== window.origin)
408
+ if (origin && event.origin !== origin)
405
409
  return; // only talk with our peers
406
410
  var msg = event.data;
411
+ if (msg.scope != "naan-env-web")
412
+ return;
407
413
  if (msg.id == "interrupt")
408
414
  contSelf.Interrupt();
409
415
  else if (msg.id == "keyline")
410
416
  contSelf.Return(msg.text, termSelf); // keyboard text from terminal
411
- else if (msg.id == "start")
412
- contSelf.Attach(term); // opener is ready
417
+ else if (msg.id == "typed")
418
+ echoTyped(msg.text);
419
+ else if (msg.id == "attached")
420
+ contSelf.Attach(messageTerm); // start using the terminal
421
+ else if (msg.id == "detached")
422
+ contSelf.Detach(messageTerm); // done using the terminal
413
423
  else if (msg.id == "import")
414
424
  { // for workers
415
425
  }
@@ -423,13 +433,16 @@ exports.NaanControllerWeb = function() {
423
433
  if (debugListener)
424
434
  debugListener(msg.data); // target received a message
425
435
  }
436
+ else if (msg.id == "ioctl-event")
437
+ contSelf.ioctl_event(msg.msg, msg.arg);
426
438
  });
427
439
 
428
440
  //
429
441
  // report messages back to opener
430
442
  //
431
443
  termSelf.OnMessage = function OnMessage(msg) {
432
- window.opener.postMessage(msg, window.origin);
444
+ msg.scope = "naan-env-web";
445
+ windest.postMessage(msg, origin);
433
446
  return (msg);
434
447
  };
435
448
 
@@ -437,7 +450,7 @@ exports.NaanControllerWeb = function() {
437
450
  // report messages back to opener
438
451
  //
439
452
  termSelf.OnMessageOut = function OnMessageOut(data) {
440
- var msg = { // target is sending debug data
453
+ var msg = { // target is sending debug data
441
454
  id: "targetout",
442
455
  data: data
443
456
  };
@@ -448,7 +461,7 @@ exports.NaanControllerWeb = function() {
448
461
  // report debug messages back to opener
449
462
  //
450
463
  termSelf.OnDebugOut = function OnDebugOut(data) {
451
- var msg = { // target is sending debug data
464
+ var msg = { // target is sending debug data
452
465
  id: "debugout",
453
466
  data: data
454
467
  };
@@ -459,14 +472,129 @@ exports.NaanControllerWeb = function() {
459
472
  // report status back to opener
460
473
  //
461
474
  termSelf.OnStatus = function OnStatus(status) {
462
- var msg = { // target is sending debug data
475
+ var msg = { // target is sending debug data
463
476
  id: "status",
464
477
  status: status
465
478
  };
466
479
  return (termSelf.OnMessage(msg));
467
480
  };
481
+
482
+ //
483
+ // stub to ignore call
484
+ //
485
+ termSelf.StateSave = function StateSave() {
486
+ return (false);
487
+ };
488
+
489
+ //
490
+ // send ioctl back to terminal
491
+ //
492
+ termSelf.ioctl = function ioctl(op, arg) {
493
+ var msg = {
494
+ id: "ioctl",
495
+ op: op,
496
+ arg: arg
497
+ };
498
+ return (termSelf.OnMessage(msg));
499
+ };
500
+
501
+ listen_all.push(function(imsg, arg) {
502
+ var msg = { // target is sending ioctl event
503
+ id: "ioctl_event",
504
+ msg: imsg,
505
+ arg: arg
506
+ };
507
+ return (termSelf.OnMessage(msg));
508
+ });
468
509
  }
469
510
 
511
+ //==========================================================================
512
+ // ioctl terminal control
513
+ //--------------------------------------------------------------------------
514
+
515
+ var listen_all = [];
516
+ var listeners = { };
517
+ var ioctl_callback;
518
+
519
+ //
520
+ // ioctl_open
521
+ //
522
+ // A terminal controller is now open on our instance.
523
+ //
524
+
525
+ this.ioctl_open = function ioctl_open(callback) {
526
+ ioctl_callback = callback;
527
+ return (true);
528
+ };
529
+
530
+ //
531
+ // ioctl_close
532
+ //
533
+ // The terminal controller is no longer open on our instance.
534
+ //
535
+
536
+ this.ioctl_close = function ioctl_close() {
537
+ ioctl_callback = false;
538
+ return (true);
539
+ };
540
+
541
+ //
542
+ // ioctl_event
543
+ //
544
+ // Events incoming from terminal.
545
+ //
546
+
547
+ this.ioctl_event = function ioctl_event(msg, arg) {
548
+ listen_all.forEach(function(proc) {
549
+ proc(msg, arg);
550
+ });
551
+ if (listeners[msg])
552
+ listeners[msg].forEach(function(proc) {
553
+ proc(msg, arg);
554
+ });
555
+ };
556
+
557
+ //
558
+ // ioctl_add_listener
559
+ // ioctl_remove_listener
560
+ //
561
+ // Add a listener for a terminal event.
562
+ //
563
+
564
+ this.ioctl_add_listener = function ioctl_add_listener(msg, proc) {
565
+ if (typeof(msg) != "string" || typeof(proc) != "function")
566
+ return (false);
567
+ this.ioctl_remove_listener(msg, proc);
568
+ if (!listeners[msg])
569
+ listeners[msg] = [];
570
+ listeners[msg].push(proc);
571
+ return (true);
572
+ };
573
+
574
+ this.ioctl_remove_listener = function ioctl_remove_listener(msg, proc) {
575
+ if (typeof(msg) != "string" || typeof(proc) != "function")
576
+ return (false);
577
+ if (listeners[msg]) {
578
+ var index = listeners[msg].indexOf(proc);
579
+ if (index >= 0)
580
+ listeners[msg].splice(index, 1);
581
+ }
582
+ return (true);
583
+ };
584
+
585
+ //
586
+ // ioctl
587
+ //
588
+ // Control of terminals (and their controller.)
589
+ //
590
+
591
+ this.ioctl = function ioctl(op, arg) {
592
+ if (ioctl_callback)
593
+ ioctl_callback(op, arg);
594
+ messageTerm.ioctl(op, arg);
595
+ return (true);
596
+ };
597
+
470
598
  //==========================================================================
471
599
  // Host Environment
472
600
  //--------------------------------------------------------------------------
@@ -501,6 +629,16 @@ exports.NaanControllerWeb = function() {
501
629
  dontSaveUntilWorking = false;
502
630
  };
503
631
 
632
+ //
633
+ // Saving
634
+ //
635
+ // Turn state saving on or off; on by default.
636
+ //
637
+
638
+ this.Saving = function Saving(onOff) {
639
+ dontSave = !onOff;
640
+ };
641
+
504
642
  window.document.addEventListener("visibilitychange", function (e) {
505
643
  virtualVisibilityChange();
506
644
  if (window.document.visibilityState == "hidden") {
@@ -514,7 +652,7 @@ exports.NaanControllerWeb = function() {
514
652
  statedoc.curversion = kStateCurrentVersion;
515
653
  statedoc.firstver = kStateFirstVersion;
516
654
  statedoc.licensee = "MIT-License";
517
- statedoc.verstring = "1.4.4+1";
655
+ statedoc.verstring = "1.6.0+1";
518
656
  statedoc.date = new Date().toISOString();
519
657
  statedoc.prefs = prefs;
520
658
  statedoc.naan = naanlib.saveState(false); // true to optimize, which is a bit slower
@@ -532,7 +670,7 @@ exports.NaanControllerWeb = function() {
532
670
  || statedoc.firstver > kStateCurrentVersion
533
671
  || statedoc.curversion < kStateFirstVersion
534
672
  || statedoc.licensee != "MIT-License"
535
- || statedoc.verstring != "1.4.4+1"
673
+ || statedoc.verstring != "1.6.0+1"
536
674
  || !(naanstate = statedoc.naan))
537
675
  {
538
676
  localStorage.removeItem("NaanState_Hosted");
@@ -550,8 +688,12 @@ exports.NaanControllerWeb = function() {
550
688
  localStorage.removeItem("NaanState_Hosted");
551
689
  return (false);
552
690
  }
553
- if (querystrings["nosave"])
691
+ if (dontSave)
692
+ return (false); // not saving right now
693
+ if ("nosave" in querystrings)
554
694
  return (false);
695
+ if (window.opener)
696
+ return (false); // don't save running under NaanIDE
555
697
  var statedoc = makeState();
556
698
  var statestr = JSON.stringify(statedoc);
557
699
  try {
@@ -591,7 +733,7 @@ exports.NaanControllerWeb = function() {
591
733
  op: "VsiteOpen",
592
734
  name: vsiteName,
593
735
  naancont: contSelf,
594
- title: vsiteName + " 1.4.4+1"
736
+ title: vsiteName + " 1.6.0+1"
595
737
  });
596
738
  }
597
739
  } catch (e) {
@@ -605,7 +747,7 @@ exports.NaanControllerWeb = function() {
605
747
  op: "VsiteClose",
606
748
  name: vsiteName,
607
749
  naancont: contSelf,
608
- title: vsiteName + " 1.4.4+1"
750
+ title: vsiteName + " 1.6.0+1"
609
751
  });
610
752
  termTextOut("\x1b[90m\x1b[3m".concat("\nwindow closed", "\x1b[0m\n"));
611
753
  }
@@ -621,7 +763,7 @@ exports.NaanControllerWeb = function() {
621
763
  op: "VsiteVisibilityChange",
622
764
  name: vsiteName,
623
765
  naancont: contSelf,
624
- title: vsiteName + " 1.4.4+1",
766
+ title: vsiteName + " 1.6.0+1",
625
767
  hidden: window.document.visibilityState == "hidden",
626
768
  window: window
627
769
  });
@@ -631,13 +773,13 @@ exports.NaanControllerWeb = function() {
631
773
  }
632
774
 
633
775
  /*jshint sub:true */
634
- if (querystrings["restart"] || !loadLocal())
776
+ if ("restart" in querystrings || !loadLocal())
635
777
  { // don't load state or can't load state
636
778
  naanlib.banner();
637
779
  var hostpath = window.location.origin.concat(naanlib.js.r("path").dirname(window.location.pathname));
638
780
  naanlib.start({
639
- cmd: 'App.version = "1.4.4+1";;\r\n'
640
- + 'App.cache = "c0da8251995ca3b0d26c3c5513b98f41";;\r\n'
781
+ cmd: 'App.version = "1.6.0+1";;\r\n'
782
+ + 'App.cache = "b39f039cddbcaf1570ae6008ea3bbeb6";;\r\n'
641
783
  + 'Naan.module.requireQuery({ naanver: App.cache });;\r\n'
642
784
  + 'Naan.module.webparse("naan_init.nlg", "' + hostpath + '", { naanver: App.cache });;\r\n'
643
785
  });
@@ -655,11 +797,11 @@ exports.NaanControllerWeb = function() {
655
797
 
656
798
  if (window.opener) {
657
799
  virtualOpen();
658
- var term = new CloneDebugTerminal();
659
- term.OnMessage({
660
- id: "loaded"
661
- });
662
800
  }
801
+ var messageTerm = new MessageTerminal(window, window.origin);
802
+ messageTerm.OnMessage({
803
+ id: "loaded"
804
+ });
663
805
  };
664
806
 
665
807
  /*jshint sub:true */
@@ -6,7 +6,7 @@
6
6
  *
7
7
  * column positioning: // // !
8
8
  *
9
- * Copyright (c) 2019-2024 by Richard C. Zulch
9
+ * Copyright (c) 2019-2026 by Richard C. Zulch
10
10
  *
11
11
  */
12
12
 
@@ -18,7 +18,6 @@
18
18
 
19
19
  importScripts(
20
20
 
21
- "lib/core/naanlib.js"
22
21
  );
23
22
 
24
23
 
@@ -46,20 +45,27 @@ exports.NaanControllerWebWorker = function NaanControllerWebWorker() {
46
45
  var targSelf = this; // this is us, for access within nested functions
47
46
  targSelf.anaan = naanlib.js.n;
48
47
  naanlib.js.t = targSelf;
49
-
48
+ var workerMetadata = { };
49
+
50
50
  //
51
51
  // Communications
52
52
  //
53
53
 
54
+ targSelf.metadata = function metadata() { // our creation metadata
55
+ return (workerMetadata);
56
+ };
57
+
54
58
  naanlib.onText(function(text, level) {
55
59
  if (level)
56
60
  postMessage({
61
+ scope: "naan-env-web",
57
62
  id: "debugtext",
58
63
  text: text,
59
64
  level: level
60
65
  });
61
66
  else
62
67
  postMessage({
68
+ scope: "naan-env-web",
63
69
  id: "textout",
64
70
  text: text
65
71
  });
@@ -69,6 +75,7 @@ exports.NaanControllerWebWorker = function NaanControllerWebWorker() {
69
75
  var samples = naanlib.status(1);
70
76
  if (samples.length > 0)
71
77
  postMessage({ // periodic worker status
78
+ scope: "naan-env-web",
72
79
  id: "status",
73
80
  status: {
74
81
  sample: samples[0]
@@ -78,6 +85,7 @@ exports.NaanControllerWebWorker = function NaanControllerWebWorker() {
78
85
 
79
86
  targSelf.ReplyMessage = function ReplyMessage(data) {
80
87
  postMessage({ // target is sending a message
88
+ scope: "naan-env-web",
81
89
  id: "targetout",
82
90
  data: data
83
91
  });
@@ -92,6 +100,7 @@ exports.NaanControllerWebWorker = function NaanControllerWebWorker() {
92
100
 
93
101
  this.DispatchMessage = function DispatchMessage(data) {
94
102
  postMessage({ // target is sending a message
103
+ scope: "naan-env-web",
95
104
  id: "targetsend",
96
105
  data: data
97
106
  });
@@ -106,6 +115,7 @@ exports.NaanControllerWebWorker = function NaanControllerWebWorker() {
106
115
 
107
116
  targSelf.ReplyDebugger = function ReplyDebugger(data) {
108
117
  postMessage({ // target is sending debug data
118
+ scope: "naan-env-web",
109
119
  id: "debugout",
110
120
  data: data
111
121
  });
@@ -120,6 +130,7 @@ exports.NaanControllerWebWorker = function NaanControllerWebWorker() {
120
130
 
121
131
  targSelf.Download = function Download(bits, name, options) {
122
132
  postMessage({ // tell browser host to download a file
133
+ scope: "naan-env-web",
123
134
  id: "download",
124
135
  bits: bits,
125
136
  name: name,
@@ -130,6 +141,7 @@ exports.NaanControllerWebWorker = function NaanControllerWebWorker() {
130
141
 
131
142
  targSelf.Terminate = function Terminate(result) {
132
143
  postMessage({ // terminate this worker from worker
144
+ scope: "naan-env-web",
133
145
  id: "termination",
134
146
  result: result
135
147
  });
@@ -137,16 +149,21 @@ exports.NaanControllerWebWorker = function NaanControllerWebWorker() {
137
149
  return (result);
138
150
  };
139
151
 
140
- onmessage = function(e) {
152
+ addEventListener("message", function(e) {
141
153
  var msg = e.data;
154
+ if (msg.scope != "naan-env-web")
155
+ return;
142
156
  if (msg.id == "interrupt")
143
157
  naanlib.escape();
144
158
  else if (msg.id == "keyline")
145
159
  naanlib.textLine(msg.text); // keyboard text from terminal
160
+ else if (msg.id == "typed")
161
+ echoTyped(msg.text);
146
162
  else if (msg.id == "start")
147
163
  { // start execution with optional state
148
164
  targSelf.workerID = msg.workerID;
149
165
  targSelf.workerGUID = msg.workerGUID;
166
+ workerMetadata = msg.metadata || { };
150
167
  naanlib.banner();
151
168
  naanlib.start({
152
169
  state: msg.state,
@@ -170,13 +187,82 @@ exports.NaanControllerWebWorker = function NaanControllerWebWorker() {
170
187
  if (targetReceiver)
171
188
  targetReceiver(msg.data);
172
189
  }
190
+ else if (msg.id == "attached")
191
+ targSelf.ioctl_event("term-attach", msg.guid);
192
+ else if (msg.id == "detached")
193
+ targSelf.ioctl_event("term-detach", msg.guid);
194
+ else if (msg.id == "ioctl-event")
195
+ targSelf.ioctl_event(msg.msg, msg.arg);
196
+ });
197
+
198
+ //==========================================================================
199
+ // ioctl terminal control
200
+ //--------------------------------------------------------------------------
201
+
202
+ var listeners = { };
203
+
204
+ //
205
+ // ioctl_event
206
+ //
207
+ // Events incoming from terminal.
208
+ //
209
+
210
+ targSelf.ioctl_event = function ioctl_event(msg, arg) {
211
+ if (listeners[msg])
212
+ listeners[msg].forEach(function(proc) {
213
+ proc(msg, arg);
214
+ });
173
215
  };
174
-
216
+
217
+ //
218
+ // ioctl_add_listener
219
+ // ioctl_remove_listener
220
+ //
221
+ // Add a listener for a terminal event.
222
+ //
223
+
224
+ targSelf.ioctl_add_listener = function ioctl_add_listener(msg, proc) {
225
+ if (typeof(msg) != "string" || typeof(proc) != "function")
226
+ return (false);
227
+ targSelf.ioctl_remove_listener(msg, proc);
228
+ if (!listeners[msg])
229
+ listeners[msg] = [];
230
+ listeners[msg].push(proc);
231
+ return (true);
232
+ };
233
+
234
+ targSelf.ioctl_remove_listener = function ioctl_remove_listener(msg, proc) {
235
+ if (typeof(msg) != "string" || typeof(proc) != "function")
236
+ return (false);
237
+ if (listeners[msg]) {
238
+ var index = listeners[msg].indexOf(proc);
239
+ if (index >= 0)
240
+ listeners[msg].splice(index, 1);
241
+ }
242
+ return (true);
243
+ };
244
+
245
+ //
246
+ // ioctl
247
+ //
248
+ // Control of terminals (and their controller.)
249
+ //
250
+
251
+ targSelf.ioctl = function ioctl(op, arg) {
252
+ postMessage({
253
+ scope: "naan-env-web",
254
+ id: "ioctl",
255
+ op: op,
256
+ arg: arg
257
+ });
258
+ };
259
+
175
260
  //
176
261
  // Initialization complete
177
262
  //
178
263
 
179
264
  postMessage({
265
+ scope: "naan-env-web",
180
266
  id: "loaded"
181
267
  });
182
268
  };