@naanlang/naan 1.1.0 → 1.2.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.
@@ -90,7 +90,7 @@ closure HttpsApiRequest(url, options,
90
90
  debuglog("HttpsApiRequest error:", url, "error:", error)
91
91
  return (list(Error("HttpsApiRequest fetch failed:", error, url)))
92
92
  }
93
- if response.status < 200 || response.status >= 300 {
93
+ if response.status < 200 || response.status >= 299 { // 299 is "cancelled"
94
94
  if options.debug
95
95
  debuglog("HttpsApiRequest status:", url, response.statusCode)
96
96
  error = Error("HttpsApiRequest status:", url, response.status, {
@@ -104,7 +104,8 @@ closure HttpsApiRequest(url, options,
104
104
  break
105
105
  }
106
106
  contentType = response.headers.get("content-type")
107
- if contentType.startsWith("application/json") {
107
+ if contentType.startsWith("application/json")
108
+ || contentType.startsWith("application/octet-stream") && options.encoding == "json" {
108
109
  `(error, content) = await(response.text())
109
110
  if !error
110
111
  `(error, content) = JsonParse(content)
@@ -129,6 +130,7 @@ closure HttpsApiRequest(url, options,
129
130
  list(error, content, {
130
131
  headers: headers
131
132
  status: response.status
133
+ contentType: contentType
132
134
  })
133
135
  };
134
136
 
@@ -36,7 +36,7 @@
36
36
  *
37
37
  */
38
38
 
39
- var CurrentCacheName = "Naanlang-1.1.0+1";
39
+ var CurrentCacheName = "Naanlang-1.2.1+1";
40
40
 
41
41
 
42
42
  //
@@ -92,18 +92,18 @@ var terminated; // flag that this service worker
92
92
  var pubVersion = event.data.hereIsMyVersion;
93
93
  var sourceId = event.source.id; // client id of sender of message
94
94
  msgPorts[sourceId] = msgport;
95
- console.log("[1.1.0+1] received new msgport for", sourceId, pubID, "-", pubVersion);
96
- if (pubVersion != "1.1.0+1") {
95
+ console.log("[1.2.1+1] received new msgport for", sourceId, pubID, "-", pubVersion);
96
+ if (pubVersion != "1.2.1+1") {
97
97
  if (upgradeMsgPorts) { // if not activated
98
- console.log("[1.1.0+1] update pending for", sourceId);
98
+ console.log("[1.2.1+1] update pending for", sourceId);
99
99
  upgradeMsgPorts[sourceId] = msgport;
100
100
  }
101
101
  else {
102
102
  msgport.postMessage({ // notify new version available
103
103
  id: "upgrade",
104
- version: "1.1.0+1"
104
+ version: "1.2.1+1"
105
105
  });
106
- console.log("[1.1.0+1] update sent for:", sourceId);
106
+ console.log("[1.2.1+1] update sent for:", sourceId);
107
107
  }
108
108
  }
109
109
  Reaper(); // clean up obsolete info
@@ -134,10 +134,10 @@ var terminated; // flag that this service worker
134
134
  msgport.onmessage = function(msg) {
135
135
  msg = msg.data;
136
136
  if (msg.id == "skipWaiting") { // try to activate this SW now
137
- console.log("[1.1.0+1] attempting skipWaiting");
137
+ console.log("[1.2.1+1] attempting skipWaiting");
138
138
  self.skipWaiting();
139
139
  } else if (msg.id == "terminate") { // termiante this SW now
140
- console.log("[1.1.0+1] terminated");
140
+ console.log("[1.2.1+1] terminated");
141
141
  terminate();
142
142
  } else if (msg.id == "abortURL") { // abort an I/O transaction
143
143
  var href = new URL(msg.url).href;
@@ -150,7 +150,7 @@ var terminated; // flag that this service worker
150
150
  } else if (msg.id == "response") // response from fetch request
151
151
  processResponse(msg);
152
152
  else if (msg.id == "text") // just log some text
153
- console.log("[1.1.0+1] msg received:", msg.text);
153
+ console.log("[1.2.1+1] msg received:", msg.text);
154
154
  };
155
155
 
156
156
  // send text to IDE log
@@ -161,7 +161,7 @@ var terminated; // flag that this service worker
161
161
  // don't clutter the log
162
162
  msgport.postMessage({
163
163
  id: "text",
164
- text: "port received by 1.1.0+1",
164
+ text: "port received by 1.2.1+1",
165
165
  });
166
166
  */
167
167
  if (--pending === 0)
@@ -178,7 +178,7 @@ var terminated; // flag that this service worker
178
178
  includeUncontrolled: true
179
179
  }).then(function(clientList) {
180
180
  clientList.every(function(client) {
181
- console.log("[1.1.0+1] requesting new msgport for", client.id);
181
+ console.log("[1.2.1+1] requesting new msgport for", client.id);
182
182
  ++pending;
183
183
  client.postMessage({ // tell client(s) we need this fetch source
184
184
  msg: "Naan_need_fetch_port",
@@ -224,12 +224,12 @@ function Reaper() {
224
224
  clients[clientList[clidex].id] = clientList[clidex];
225
225
  for (var sourceId in msgPorts)
226
226
  if (!clients[sourceId]) {
227
- console.log("[1.1.0+1] source gone:", sourceId);
227
+ console.log("[1.2.1+1] source gone:", sourceId);
228
228
  delete msgPorts[sourceId]; // no longer a source
229
229
  }
230
230
  for (var clientId in fetchPorts)
231
231
  if (!clients[clientId]) {
232
- console.log("[1.1.0+1] client gone:", clientId);
232
+ console.log("[1.2.1+1] client gone:", clientId);
233
233
  delete fetchPorts[clientId]; // no longer a client
234
234
  }
235
235
  for (var fqdex = 0; fqdex < fetchQueue.length; ++fqdex) {
@@ -263,16 +263,16 @@ function ClearCaches() {
263
263
  return (Promise.all(
264
264
  cacheNames.map(function(cacheName) {
265
265
  if (cacheName != CurrentCacheName) {
266
- console.log('[1.1.0+1] deleting old cache:', cacheName);
266
+ console.log('[1.2.1+1] deleting old cache:', cacheName);
267
267
  return (caches.delete(cacheName));
268
268
  }
269
269
  })
270
270
  ));
271
271
  }).then(function() { // claim all clients
272
- console.log('[1.1.0+1] claiming clients');
272
+ console.log('[1.2.1+1] claiming clients');
273
273
  return (self.clients.claim());
274
274
  }).then(function() {
275
- console.log('[1.1.0+1] clients claimed');
275
+ console.log('[1.2.1+1] clients claimed');
276
276
  return (Promise.resolve(true));
277
277
  });
278
278
  return (promise);
@@ -315,7 +315,7 @@ function GetClientResponse(event, urlpath) {
315
315
  msgport.postMessage({
316
316
  id: "fetch",
317
317
  seq: seqno,
318
- version: "1.1.0+1",
318
+ version: "1.2.1+1",
319
319
  request: {
320
320
  method: event.request.method,
321
321
  url: event.request.url
@@ -363,7 +363,7 @@ function GetClientResponse(event, urlpath) {
363
363
  */
364
364
 
365
365
  self.addEventListener('install', function(event) {
366
- console.log("[1.1.0+1] install");
366
+ console.log("[1.2.1+1] install");
367
367
  self.skipWaiting();
368
368
  });
369
369
 
@@ -376,20 +376,20 @@ self.addEventListener('install', function(event) {
376
376
  */
377
377
 
378
378
  self.addEventListener('activate', function(event) {
379
- console.log("[1.1.0+1] activate");
379
+ console.log("[1.2.1+1] activate");
380
380
  self.clients.matchAll({ // for debugging, list controlled clients
381
381
  includeUncontrolled: true
382
382
  }).then(function(clientList) {
383
383
  var urls = clientList.map(function(client) {
384
384
  return (client.url);
385
385
  });
386
- console.log('[1.1.0+1] matching clients:', urls.join(', '));
386
+ console.log('[1.2.1+1] matching clients:', urls.join(', '));
387
387
  });
388
388
  var promise = ClearCaches().then(function() {
389
389
  for (var sourceId in upgradeMsgPorts) {
390
390
  upgradeMsgPorts[sourceId].postMessage({ // notify new version available
391
391
  id: "upgrade",
392
- version: "1.1.0+1"
392
+ version: "1.2.1+1"
393
393
  });
394
394
  }
395
395
  upgradeMsgPorts = false;
@@ -421,7 +421,7 @@ self.addEventListener('fetch', function(event) {
421
421
  var promise;
422
422
  var url = new URL(request.url);
423
423
  var nocache = request.method != "GET"
424
- || url.search.length !== 0 && url.searchParams.get("naanver") !== "0edbbbd718a57553ff0a5c178f4dd389"
424
+ || url.search.length !== 0 && url.searchParams.get("naanver") !== "ecffb6bced5a08a6d2fdd188410b1b50"
425
425
  || request.headers.get('range');
426
426
  if (url.pathname.startsWith("/run/")) {
427
427
  nocache = true;
@@ -455,7 +455,7 @@ self.addEventListener('fetch', function(event) {
455
455
  statusText: "Request Cancelled"
456
456
  }));
457
457
  }
458
- console.log("[1.1.0+1] fetch failed", request.url, e);
458
+ console.log("[1.2.1+1] fetch failed", request.url, e);
459
459
  return (new Response(undefined, {
460
460
  status: 404,
461
461
  statusText: "Fetch Failed"
@@ -14,30 +14,58 @@
14
14
  /*
15
15
  * TermHost
16
16
  *
17
- * Make a host debugger target.
17
+ * Make an Nide API Server debugger target.
18
+ *
19
+ * Options:
20
+ * {
21
+ * type: <string> // target category, e.g. "Host", "api.yyy.com"
22
+ * workerID: <string> // kind of worker in server subsystem
23
+ * dispatcher: <tuple> // dispatcher function for incoming messages
24
+ * startup: <dictionary> // startup options
25
+ * clientID: <string> // (rare) our identification on client
26
+ * serverID: <string> // (rare) server subsystem for us
27
+ * }
18
28
  *
19
29
  */
20
30
 
21
- closure TermHost(track, api, name, workerID, options,
22
- local target, nlregex, clientID, serverID)
31
+ closure TermHost(track, api, name, options, local target, nlregex, xtarg)
23
32
  {
24
33
  global(window)
25
- target = require("../running/executors.nlg").ExecutorBase(track, "Host", name)
26
- clientID = "DebugWorkers"
27
- serverID = "Workers"
34
+ options = merge({
35
+ type: "Host"
36
+ workerID: "myDebugWorker"
37
+ clientID: "DebugWorkers"
38
+ serverID: "Workers"
39
+ }, options)
40
+ target = require("../running/executors.nlg").ExecutorBase(track, options.type, name)
28
41
  nlregex = RegExp("\\n", "g")
29
- if !workerID
30
- workerID = "myDebugWorker"
31
- target.workerID = workerID
42
+ target.workerID = options.workerID
32
43
  target.msgQueue = []
33
44
  target.dispatcher = call(options.dispatcher, function(reply) { reply })
34
-
45
+
46
+ // findWorker
47
+ //
48
+ function findWorker(testID, local instance) {
49
+ for instance in track.instances {
50
+ if instance.executor.hostWorkerMatch(api, testID)
51
+ return (instance.executor)
52
+ }
53
+ false
54
+ }
55
+
35
56
  // connect
36
57
  // Connect with the host if not already connected.
37
- closure connect(local pending) {
58
+ closure connect(local host, url, pending) {
38
59
  if target.ws
39
- return
40
- target.ws = xnew(window.WebSocket,"ws://${window.location.host}")
60
+ return(list(false, { connected: true }))
61
+ host = xnew(window.URL, api.url).host
62
+ if !host || host == ""
63
+ return(list(Error("invalid URL ${api.url}")))
64
+ if window.location.protocol == "https:"
65
+ url = "wss://${host}"
66
+ else
67
+ url = "ws://${host}"
68
+ target.ws = xnew(window.WebSocket, url)
41
69
  pending = new(nonce)
42
70
 
43
71
  // onopen
@@ -45,7 +73,7 @@ closure TermHost(track, api, name, workerID, options,
45
73
  target.ws.onopen = function onopen(e, local info, spawner) {
46
74
  info = {
47
75
  name: name
48
- workerID: workerID
76
+ workerID: target.workerID
49
77
  }
50
78
  if options.dispatcher
51
79
  info.destID = api.instanceID // valid destination for relay
@@ -61,7 +89,6 @@ closure TermHost(track, api, name, workerID, options,
61
89
 
62
90
  // onmessage
63
91
  // A message was received from the worker via WebSockets.
64
-
65
92
  target.ws.onmessage = function onmessage(e, message, local msg) {
66
93
  try {
67
94
  message = new(window.JSON.parse(e.data))
@@ -75,8 +102,10 @@ closure TermHost(track, api, name, workerID, options,
75
102
  if msg.id == "spawned" || msg.id == "workerlist" || msg.id == "termination"
76
103
  return (hostWorkerUpdate(msg))
77
104
  if msg.id != "targetout" {
78
- if msg.id == "status"
105
+ if msg.id == "status" {
79
106
  target.lastStatus = milliseconds()
107
+ target.execSetStatus(msg.status)
108
+ }
80
109
  if target.msgQueue {
81
110
  if msg.id != "status"
82
111
  target.msgQueue.push(msg)
@@ -137,27 +166,16 @@ closure TermHost(track, api, name, workerID, options,
137
166
  // New workers created/discovered on this host.
138
167
  //
139
168
  function hostWorkerUpdate(msg, local localID, worker) {
140
-
141
- // findWorker
142
- //
143
- function findWorker(testID, local instance) {
144
- for instance in track.instances {
145
- if instance.executor.hostWorkerMatch(api, testID)
146
- return (instance.executor)
147
- }
148
- false
149
- }
150
-
151
169
  if msg.id == "spawned" {
152
170
  if !findWorker(msg.workerID)
153
- TermHost(track, api, msg.name, msg.workerID)
171
+ TermHost(track, api, msg.name, { type: options.type, workerID: msg.workerID })
154
172
  }
155
173
  else if msg.id == "termination"
156
174
  track.delete(findWorker(msg.workerID))
157
- else {
175
+ else if msg.id == "workerlist" {
158
176
  for `(localID, worker) in msg.workers
159
177
  if !findWorker(localID)
160
- TermHost(track, api, worker.name, localID)
178
+ TermHost(track, api, worker.name, { type: options.type, workerID: localID })
161
179
  }
162
180
  }
163
181
 
@@ -167,7 +185,7 @@ closure TermHost(track, api, name, workerID, options,
167
185
  // True iff the specified information matches us.
168
186
  //
169
187
  target.hostWorkerMatch = function hostWorkerMatch(testApi, testID) {
170
- testApi === api && testID == workerID
188
+ testApi === api && testID == target.workerID
171
189
  }
172
190
 
173
191
  //
@@ -203,8 +221,8 @@ closure TermHost(track, api, name, workerID, options,
203
221
  target.sendControl = function sendControl(workerOp, payload) {
204
222
  target.ws.send(window.JSON.stringify({
205
223
  guid: api.guid
206
- clientID: clientID
207
- serverID: serverID
224
+ clientID: options.clientID
225
+ serverID: options.serverID
208
226
  workerID: target.workerID
209
227
  workerOp: workerOp
210
228
  payload: payload
@@ -374,6 +392,9 @@ closure TermHost(track, api, name, workerID, options,
374
392
  target.ws.close(1000) // 1000: normal close
375
393
  }
376
394
 
395
+ xtarg = findWorker(target.workerID)
396
+ if xtarg
397
+ return (list(false, xtarg)) // already exists
377
398
  track.add(target)
378
399
  connect() // connect right away to start receiving messages
379
400
 
@@ -388,27 +409,34 @@ closure TermHost(track, api, name, workerID, options,
388
409
  *
389
410
  * Make a local debugger target, returning a standard (error, object) tuple.
390
411
  *
412
+ * Options:
413
+ * {
414
+ * workerID: <string> // kind of worker in server subsystem
415
+ * // "NaanIDE" for local IDE
416
+ * // "NaanIDE-Debug" for browser debug target
417
+ * startup: <dictionary> // startup options
418
+ * type: <string> // (rare) target category, e.g. "Local"
419
+ * }
420
+ *
391
421
  */
392
422
 
393
- closure TermLocal(track, name, workerID, options,
394
- local target, nlregex, listener)
423
+ closure TermLocal(track, name, options, local target, nlregex, listener)
395
424
  {
396
425
  global(js, window)
397
- if workerID == "NaanIDE" {
426
+ options = merge({
427
+ type: "Local"
428
+ }, options)
429
+ if options.workerID == "NaanIDE" {
398
430
  if !js.t
399
431
  return (list(Error("Cannot access Local IDE executor")))
400
432
  termInstallVirtualWatcher(track, js.t)
401
- return (termIDE(track, name, workerID, js.t)) // connect to IDE execution instance itself
433
+ return (termIDE(track, name, options.workerID, js.t)) // connect to IDE execution instance itself
402
434
  }
403
- if dictionary(options)
404
- options = new(options)
405
- else
406
- options = { }
407
- target = require("../running/executors.nlg").ExecutorBase(track, "Local", name)
435
+ target = require("../running/executors.nlg").ExecutorBase(track, options.type, name)
408
436
  nlregex = RegExp("\\n", "g")
409
- target.workerID = workerID
437
+ target.workerID = options.workerID
410
438
  target.msgQueue = []
411
- if workerID == "NaanIDE-Debug" {
439
+ if options.workerID == "NaanIDE-Debug" {
412
440
  target.worker = window.open(window.location.href, "_blank")
413
441
  target.worker.addEventListener("beforeunload", function(e) { // our target is closing
414
442
  destroy()
@@ -433,8 +461,10 @@ closure TermLocal(track, name, workerID, options,
433
461
  destroy()
434
462
  return }
435
463
  else if msg.id != "targetout" && msg.id != "loaded" {
436
- if msg.id == "status"
464
+ if msg.id == "status" {
437
465
  target.lastStatus = milliseconds()
466
+ target.execSetStatus(msg.status)
467
+ }
438
468
  if target.msgQueue {
439
469
  if msg.id != "status"
440
470
  target.msgQueue.push(msg)
@@ -446,6 +476,7 @@ closure TermLocal(track, name, workerID, options,
446
476
  // The worker had an error.
447
477
 
448
478
  target.worker.addEventListener("error", function(e) {
479
+ debuglog("TermLocal worker error:", e.message)
449
480
  target.execClosed(Error("instance error", e.message))
450
481
  })
451
482
 
@@ -698,6 +729,7 @@ closure termIDE(track, name, workerID, naancont, title, local target, connected)
698
729
  }
699
730
 
700
731
  function onstatus(status) {
732
+ target.execSetStatus(status)
701
733
  statusCB(target, status)
702
734
  }
703
735
 
@@ -37,10 +37,14 @@ closure WebSocket(options, local wsock) {
37
37
  //
38
38
  // Connect with the host if not already connected, returning a result tuple.
39
39
  //
40
- wsock.connect = closure connect(local pending) {
40
+ wsock.connect = closure connect(local url, pending) {
41
41
  if wsock.ws
42
42
  return (list(false, { open: true }))
43
- wsock.ws = xnew(window.WebSocket, "ws://${options.host}")
43
+ if window.location.protocol == "https:"
44
+ url = "wss://${options.host}"
45
+ else
46
+ url = "ws://${options.host}"
47
+ wsock.ws = xnew(window.WebSocket, url)
44
48
  pending = new(nonce)
45
49
 
46
50
  // onopen