@naanlang/naan 1.3.2 → 1.4.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 +25 -15
- package/dist/naan.min.js +5 -5
- package/frameworks/browser/sworker.js +23 -23
- package/frameworks/browser/terminals.nlg +26 -11
- package/frameworks/browser/ws_client.nlg +1 -1
- package/frameworks/client/psm_client.nlg +3 -1
- package/frameworks/client/relaycon.nlg +3 -2
- package/frameworks/common/common.nlg +5 -2
- package/frameworks/common/preferences.nlg +1 -1
- package/frameworks/node/apiserver.nlg +3 -3
- package/frameworks/node/filesystem.nlg +5 -4
- package/frameworks/node/psm_server.nlg +1 -1
- package/frameworks/node/shell.nlg +134 -0
- package/frameworks/node/worker.nlg +104 -46
- package/frameworks/project/build.nlg +1 -2
- package/frameworks/project/jszip.js +0 -0
- package/frameworks/project/projects.nlg +1 -1
- package/frameworks/running/debugnub.nlg +102 -12
- package/frameworks/running/debugutil.nlg +30 -13
- package/frameworks/running/executors.nlg +64 -28
- package/frameworks/running/running.nlg +85 -3
- package/frameworks/running/sourcecode.nlg +3 -1
- package/frameworks/running/taskexec.nlg +24 -4
- package/frameworks/storage/dbt_pouch.nlg +30 -17
- package/frameworks/storage/file_manager.nlg +1 -1
- package/frameworks/storage/psm.nlg +11 -1
- package/frameworks/storage/psm_dbtables.nlg +21 -22
- package/frameworks/storage/resources.nlg +12 -4
- package/frameworks/storage/storage.nlg +2 -2
- package/lib/browser/env_web.js +6 -6
- package/lib/browser/env_webworker.js +2 -0
- package/lib/core/naanlib.js +5 -5
- package/lib/env_nodeworker.js +2 -0
- package/package.json +1 -1
- package/plugins/gitClient/gitClient.nlg +3 -3
- package/plugins/gitClient/gitutils.nlg +2 -2
- package/plugins/nodeLib/node_https.nlg +2 -2
- package/plugins/openSearch/openSearch.nlg +2 -2
- package/plugins/serviceAws/lambda_naan_control.nlg +3 -3
- package/plugins/serviceAws/psm_aws.nlg +4 -2
- package/plugins/serviceAws/serviceAws.nlg +1 -1
- package/plugins/serviceGC/gc_api.nlg +5 -5
- package/plugins/serviceGitHub/gitops.nlg +4 -3
- package/plugins/serviceGitHub/psm_github.nlg +1 -1
- package/plugins/serviceGitHub/serviceGitHub.nlg +1 -1
- package/plugins/serviceGitLab/gitops.nlg +2 -1
- package/plugins/serviceGitLab/psm_gitlab.nlg +2 -2
- package/plugins/serviceGitLab/serviceGitLab.nlg +1 -1
- package/plugins/serviceYC/yc_vm.nlg +1 -1
- package/test/harness.nlg +9 -9
- package/test/test_01_core.nlg +24 -2
- package/test/test_02_context.nlg +2 -2
- package/test/test_07_lingo.nlg +3 -3
- package/plugins/serviceGC/russian_trusted_root_ca_pem.crt +0 -33
|
@@ -24,19 +24,20 @@ closure ExecutorBase(track, type, name, local exec) {
|
|
|
24
24
|
exec.name = name
|
|
25
25
|
|
|
26
26
|
// execReset
|
|
27
|
+
//
|
|
27
28
|
// Initialize remote communications for a new or restarted instance.
|
|
28
|
-
|
|
29
|
+
//
|
|
29
30
|
exec.execReset = function execReset() {
|
|
30
31
|
exec.pending = { }
|
|
31
32
|
exec.nextSendID = toint(RandomBytes(3)) // keep our sequence code unique for shared servers
|
|
32
|
-
exec.nextContextID = 1
|
|
33
33
|
}
|
|
34
34
|
execReset()
|
|
35
35
|
|
|
36
36
|
// execSend
|
|
37
|
+
//
|
|
37
38
|
// Send a message to the running instance and return a nonce to wait on. If data is not a
|
|
38
39
|
// dictionary then it is ignored.
|
|
39
|
-
|
|
40
|
+
//
|
|
40
41
|
exec.execSend = closure execSend(msg, data, local pending, error) {
|
|
41
42
|
if !dictionary(data)
|
|
42
43
|
data = { }
|
|
@@ -52,8 +53,9 @@ closure ExecutorBase(track, type, name, local exec) {
|
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
// execReceived
|
|
56
|
+
//
|
|
55
57
|
// The specified message was received from the instance, so signal it.
|
|
56
|
-
|
|
58
|
+
//
|
|
57
59
|
exec.execReceived = closure execReceived(data, local pending) {
|
|
58
60
|
pending = exec.pending[data.xid]
|
|
59
61
|
if !pending { // not waiting on message
|
|
@@ -68,15 +70,17 @@ closure ExecutorBase(track, type, name, local exec) {
|
|
|
68
70
|
}
|
|
69
71
|
|
|
70
72
|
// execSetStatus
|
|
73
|
+
//
|
|
71
74
|
// Received a status update from the instance.
|
|
72
|
-
|
|
75
|
+
//
|
|
73
76
|
exec.execSetStatus = function execSetStatus(status) {
|
|
74
77
|
exec.xstatus = status
|
|
75
78
|
}
|
|
76
79
|
|
|
77
80
|
// execFailed
|
|
81
|
+
//
|
|
78
82
|
// Communication has failed.
|
|
79
|
-
|
|
83
|
+
//
|
|
80
84
|
exec.execFailed = closure execFailed(error, local xid, pending) {
|
|
81
85
|
exec.pending.error = error
|
|
82
86
|
for `(xid, pending) in exec.pending
|
|
@@ -84,8 +88,10 @@ closure ExecutorBase(track, type, name, local exec) {
|
|
|
84
88
|
}
|
|
85
89
|
|
|
86
90
|
// execClosed
|
|
91
|
+
//
|
|
92
|
+
//
|
|
87
93
|
// Note that the connection has closed, so signal all the waiters.
|
|
88
|
-
|
|
94
|
+
//
|
|
89
95
|
exec.execClosed = closure execClosed(error, local xid, pending) {
|
|
90
96
|
for `(xid, pending) in exec.pending {
|
|
91
97
|
pending.signal(list(error))
|
|
@@ -94,10 +100,13 @@ closure ExecutorBase(track, type, name, local exec) {
|
|
|
94
100
|
}
|
|
95
101
|
|
|
96
102
|
// context
|
|
97
|
-
//
|
|
98
|
-
//
|
|
99
|
-
|
|
100
|
-
|
|
103
|
+
//
|
|
104
|
+
// Return a context object for the instance, or an error, in a result tuple. The optional state
|
|
105
|
+
// dictionary argument initializes the context with the state of a previous one to facilitate
|
|
106
|
+
// persistent reconnection. Currently this does not ever reclaim old contexts on the instance
|
|
107
|
+
// end of things, but it should. ###
|
|
108
|
+
//
|
|
109
|
+
exec.context = closure context(state, local error, retries, ms, delta, excon) {
|
|
101
110
|
retries = 0
|
|
102
111
|
ms = milliseconds()
|
|
103
112
|
delta = 1
|
|
@@ -114,13 +123,14 @@ closure ExecutorBase(track, type, name, local exec) {
|
|
|
114
123
|
sleep(delta)
|
|
115
124
|
if delta < 100
|
|
116
125
|
delta *= 2 }
|
|
117
|
-
excon = ExecutorContext(exec,
|
|
126
|
+
excon = ExecutorContext(exec, state)
|
|
118
127
|
excon.register()
|
|
119
128
|
}
|
|
120
129
|
|
|
121
130
|
// attention
|
|
131
|
+
//
|
|
122
132
|
// Focus the UI on this instance because something needs attention.
|
|
123
|
-
|
|
133
|
+
//
|
|
124
134
|
exec.attention = function attention() {
|
|
125
135
|
track.attention(exec)
|
|
126
136
|
}
|
|
@@ -141,20 +151,37 @@ closure ExecutorBase(track, type, name, local exec) {
|
|
|
141
151
|
* ability to track namespace changes as the result of evaluating an expression. They do not override
|
|
142
152
|
* normal namespace protections. The contexts exposed here preserve the active namespace after the
|
|
143
153
|
* expression is evaluated.
|
|
154
|
+
* The optional state argument preserves the context state so that it can be restored for
|
|
155
|
+
* resuming persistent connections.
|
|
144
156
|
*
|
|
145
157
|
*/
|
|
146
158
|
|
|
147
|
-
closure ExecutorContext(exec,
|
|
159
|
+
closure ExecutorContext(exec, state, local context, coder, util) {
|
|
148
160
|
global(apply)
|
|
149
161
|
context = new(object, this)
|
|
162
|
+
if !state || !state.contextID
|
|
163
|
+
state = {
|
|
164
|
+
contextID: UUID()
|
|
165
|
+
}
|
|
166
|
+
context.state = state
|
|
167
|
+
coder = packageCoder(evalf)
|
|
150
168
|
util = modlist().Util.exports
|
|
151
169
|
|
|
170
|
+
// getState
|
|
171
|
+
//
|
|
172
|
+
// Get context state for future initialization
|
|
173
|
+
//
|
|
174
|
+
context.getState = function getState() {
|
|
175
|
+
context.state
|
|
176
|
+
}
|
|
177
|
+
|
|
152
178
|
// register
|
|
179
|
+
//
|
|
153
180
|
// Register or re-register our context with the worker.
|
|
154
|
-
|
|
181
|
+
//
|
|
155
182
|
context.register = closure register(local pending, result) {
|
|
156
183
|
pending = exec.execSend("register", {
|
|
157
|
-
contextID: contextID
|
|
184
|
+
contextID: state.contextID
|
|
158
185
|
})
|
|
159
186
|
result = pending.wait()
|
|
160
187
|
if result.1
|
|
@@ -164,10 +191,11 @@ closure ExecutorContext(exec, contextID, local context, util) {
|
|
|
164
191
|
}
|
|
165
192
|
|
|
166
193
|
// eval
|
|
194
|
+
//
|
|
167
195
|
// Evaluate the specified expression in the current worker context. The optional put argument
|
|
168
196
|
// if non-false is a tuple of symbols that should be transfered to the remote end, while get is
|
|
169
197
|
// an optional tuple of symbols to retrieve after evaluation.
|
|
170
|
-
|
|
198
|
+
//
|
|
171
199
|
context.eval = closure evalf(expr, put, get, local roots, pkg, data, pending, result) {
|
|
172
200
|
if tuple(put)
|
|
173
201
|
roots = cons(`expr, put)
|
|
@@ -175,9 +203,11 @@ closure ExecutorContext(exec, contextID, local context, util) {
|
|
|
175
203
|
roots = `(expr)
|
|
176
204
|
pkg = util.pkgSave(`expr, roots, {
|
|
177
205
|
nsignore: true
|
|
178
|
-
comments: true
|
|
206
|
+
comments: true
|
|
207
|
+
objectEncoder: coder.encodeObject
|
|
208
|
+
})
|
|
179
209
|
data = {
|
|
180
|
-
contextID: contextID
|
|
210
|
+
contextID: state.contextID
|
|
181
211
|
expr: pkg }
|
|
182
212
|
if tuple(get)
|
|
183
213
|
data.get = get
|
|
@@ -190,22 +220,25 @@ closure ExecutorContext(exec, contextID, local context, util) {
|
|
|
190
220
|
localroots: false
|
|
191
221
|
intern: false
|
|
192
222
|
execute: false
|
|
223
|
+
objectDecoder: coder.decodeObject
|
|
193
224
|
})))
|
|
194
225
|
else
|
|
195
226
|
result
|
|
196
227
|
}
|
|
197
|
-
|
|
228
|
+
|
|
198
229
|
// evalq
|
|
230
|
+
//
|
|
199
231
|
// Evaluate the specified QUOTED expression in the current worker context.
|
|
200
|
-
|
|
232
|
+
//
|
|
201
233
|
context.evalq = macro evalq(expr, put, get) {
|
|
202
234
|
evalf(expr, eval(put), eval(get))
|
|
203
235
|
}
|
|
204
|
-
|
|
236
|
+
|
|
205
237
|
// apply
|
|
238
|
+
//
|
|
206
239
|
// Apply list of arguments to the specified procure evaluated remotely. If the procedure is a
|
|
207
240
|
// not a tuple then this uses the tuple definition if there is one.
|
|
208
|
-
|
|
241
|
+
//
|
|
209
242
|
context.apply = closure applyf(proc, args, put, get) {
|
|
210
243
|
if !tuple(proc) && tuple(proc.proc)
|
|
211
244
|
proc = proc.proc
|
|
@@ -213,9 +246,10 @@ closure ExecutorContext(exec, contextID, local context, util) {
|
|
|
213
246
|
}
|
|
214
247
|
|
|
215
248
|
// call
|
|
249
|
+
//
|
|
216
250
|
// Call the specified function remotely using local arguments:
|
|
217
251
|
// context.call(proc, args...)
|
|
218
|
-
|
|
252
|
+
//
|
|
219
253
|
context.call = macro callf args {
|
|
220
254
|
closure (proc, arglist, local eargs) {
|
|
221
255
|
while arglist
|
|
@@ -225,13 +259,14 @@ closure ExecutorContext(exec, contextID, local context, util) {
|
|
|
225
259
|
}
|
|
226
260
|
|
|
227
261
|
// rpc
|
|
262
|
+
//
|
|
228
263
|
// Execute a remote procedure call without package translation, to reduce overhead. This will not
|
|
229
264
|
// properly transfer Naan-specific types like symbols, and the results will be native JavaScript.
|
|
230
265
|
// The procedure must be specified as a symbol or string.
|
|
231
|
-
|
|
266
|
+
//
|
|
232
267
|
context.rpc = closure rpc(proc, args, local data, pending, result) {
|
|
233
268
|
data = {
|
|
234
|
-
contextID: contextID
|
|
269
|
+
contextID: state.contextID
|
|
235
270
|
proc: proc
|
|
236
271
|
args: args }
|
|
237
272
|
pending = exec.execSend("rpc", data)
|
|
@@ -647,7 +682,7 @@ closure ExecutorTracker(local xtrak) {
|
|
|
647
682
|
*/
|
|
648
683
|
|
|
649
684
|
closure execLambda(track, url, name, workerID, local target, nlregex, clientID, serverID) {
|
|
650
|
-
global()
|
|
685
|
+
global(js)
|
|
651
686
|
target = ExecutorBase(track, "Lambda", name)
|
|
652
687
|
clientID = "DebugWorkers"
|
|
653
688
|
serverID = "Workers"
|
|
@@ -896,7 +931,8 @@ closure execLambda(track, url, name, workerID, local target, nlregex, clientID,
|
|
|
896
931
|
*/
|
|
897
932
|
|
|
898
933
|
function execInit(local manifest) {
|
|
899
|
-
manifest = `(ExecutorBase, ExecutorContext, ExecutorParallel, ExecutorTracker, execLambda,
|
|
934
|
+
manifest = `(ExecutorBase, ExecutorContext, ExecutorParallel, ExecutorTracker, execLambda,
|
|
935
|
+
execInit)
|
|
900
936
|
|
|
901
937
|
Naan.module.build(module.id, "executors", function(modobj, compobj) {
|
|
902
938
|
require("./running.nlg")
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
* column positioning: // // !
|
|
8
8
|
*
|
|
9
|
-
* Copyright (c) 2021-
|
|
9
|
+
* Copyright (c) 2021-2024 by Richard C. Zulch
|
|
10
10
|
*
|
|
11
11
|
*/
|
|
12
12
|
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
21
|
function rootproc(procdef, local parent) {
|
|
22
|
+
global()
|
|
22
23
|
loop { // can only find out proc
|
|
23
24
|
parent = procdef.1@\.parent
|
|
24
25
|
if !parent
|
|
@@ -38,6 +39,7 @@ function rootproc(procdef, local parent) {
|
|
|
38
39
|
*/
|
|
39
40
|
|
|
40
41
|
function baseproc(procdef) {
|
|
42
|
+
global()
|
|
41
43
|
if procdef.1@\.base.proc
|
|
42
44
|
{ }
|
|
43
45
|
else
|
|
@@ -58,6 +60,7 @@ function baseproc(procdef) {
|
|
|
58
60
|
*/
|
|
59
61
|
|
|
60
62
|
function pathmatch(parent, path, local segment, nth, child) {
|
|
63
|
+
global()
|
|
61
64
|
if empty(path)
|
|
62
65
|
return (parent)
|
|
63
66
|
segment = pop(path)
|
|
@@ -83,6 +86,7 @@ function pathmatch(parent, path, local segment, nth, child) {
|
|
|
83
86
|
*/
|
|
84
87
|
|
|
85
88
|
function procpath(procdef, local path, segment, parent, peers, nth, peer) {
|
|
89
|
+
global()
|
|
86
90
|
loop {
|
|
87
91
|
segment = procdef.1
|
|
88
92
|
parent = segment@\.parent
|
|
@@ -114,6 +118,7 @@ function procpath(procdef, local path, segment, parent, peers, nth, peer) {
|
|
|
114
118
|
*/
|
|
115
119
|
|
|
116
120
|
function procname(name, local parent) {
|
|
121
|
+
global()
|
|
117
122
|
parent = name@\.parent
|
|
118
123
|
name = tostring(name)
|
|
119
124
|
if parent
|
|
@@ -136,6 +141,7 @@ function procname(name, local parent) {
|
|
|
136
141
|
*/
|
|
137
142
|
|
|
138
143
|
function procstring(procdef, options, local name, output, parm) {
|
|
144
|
+
global()
|
|
139
145
|
if options.fullname || !defined(options, `fullname)
|
|
140
146
|
name = procname(procdef.1) // default is full name
|
|
141
147
|
else
|
|
@@ -156,6 +162,82 @@ function procstring(procdef, options, local name, output, parm) {
|
|
|
156
162
|
}
|
|
157
163
|
|
|
158
164
|
|
|
165
|
+
/*
|
|
166
|
+
* packageCoder
|
|
167
|
+
*
|
|
168
|
+
* Encode and decode objects for the NaaN packager to establish proxies for remote access.
|
|
169
|
+
*
|
|
170
|
+
*/
|
|
171
|
+
|
|
172
|
+
closure packageCoder(evalf, local coder) {
|
|
173
|
+
global()
|
|
174
|
+
coder = new(object, this)
|
|
175
|
+
coder.wmapEncoding = new(weakmap)
|
|
176
|
+
coder.mapDecoding = { }
|
|
177
|
+
|
|
178
|
+
// encodeObject
|
|
179
|
+
//
|
|
180
|
+
// Encode an object into the ident dictionary so that the remote end can create a proxy.
|
|
181
|
+
//
|
|
182
|
+
coder.encodeObject = closure encodeObject(obj, local objectID) {
|
|
183
|
+
if coder.wmapEncoding[obj]
|
|
184
|
+
{ }
|
|
185
|
+
else {
|
|
186
|
+
objectID = UUID()
|
|
187
|
+
coder.mapDecoding[objectID] = obj
|
|
188
|
+
coder.wmapEncoding[obj] = {
|
|
189
|
+
name: obj@\.closure || undefined
|
|
190
|
+
objectID: objectID
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// decodeObject
|
|
196
|
+
//
|
|
197
|
+
// Decode the ident dictionary into a proxy object allowing method invocation.
|
|
198
|
+
//
|
|
199
|
+
coder.decodeObject = closure decodeObject(ident, local x, obj) {
|
|
200
|
+
if coder.mapDecoding[ident.objectID]
|
|
201
|
+
{ }
|
|
202
|
+
else if ident.name {
|
|
203
|
+
putproc(ident.name, false)
|
|
204
|
+
obj = coder.mapDecoding[ident.objectID] = closure(nn, objectID) {
|
|
205
|
+
call(enclose(list(`closure, nn, list(`local, `x),
|
|
206
|
+
quote(x=new(object, nn)),
|
|
207
|
+
quote(x@\.tostring = function() { "{proxy ${nn}}" }),
|
|
208
|
+
quote(x@\.undefined = closure undef args {
|
|
209
|
+
let (result) {
|
|
210
|
+
result = evalf(list(`\.execute\-method, objectID, args))
|
|
211
|
+
if result.0
|
|
212
|
+
throw("remoting failure: ${ErrorString(result.0)}")
|
|
213
|
+
else
|
|
214
|
+
result.1
|
|
215
|
+
} ()
|
|
216
|
+
}), `x)))
|
|
217
|
+
} (ident.name, ident.objectID)
|
|
218
|
+
coder.wmapEncoding[obj] = ident
|
|
219
|
+
obj
|
|
220
|
+
} else
|
|
221
|
+
coder.mapDecoding[ident.objectID] = new(object)
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// invokeMethod
|
|
225
|
+
//
|
|
226
|
+
// Invoke a local object method from the remote proxy, returning a result tuple.
|
|
227
|
+
//
|
|
228
|
+
coder.invokeMethod = closure invokeMethod(objectID, args, local obj) {
|
|
229
|
+
obj = coder.mapDecoding[objectID]
|
|
230
|
+
if obj
|
|
231
|
+
eval(list(deref, obj, pop(args), args))
|
|
232
|
+
else
|
|
233
|
+
throw("remoting error: object ${objectID} not found")
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// finis
|
|
237
|
+
coder
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
|
|
159
241
|
/*
|
|
160
242
|
* runnInit
|
|
161
243
|
*
|
|
@@ -164,8 +246,8 @@ function procstring(procdef, options, local name, output, parm) {
|
|
|
164
246
|
*/
|
|
165
247
|
|
|
166
248
|
function runnInit(local manifest) {
|
|
167
|
-
manifest = `(rootproc, baseproc, pathmatch, procpath, procname, procstring,
|
|
168
|
-
|
|
249
|
+
manifest = `(rootproc, baseproc, pathmatch, procpath, procname, procstring, packageCoder,
|
|
250
|
+
runnInit)
|
|
169
251
|
Naan.module.build(module.id, "running", closure(modobj, compobj) {
|
|
170
252
|
require("../common").LiveImport()
|
|
171
253
|
compobj.manifest = manifest
|
|
@@ -87,12 +87,14 @@ closure CodeManager(options, local coman, cache)
|
|
|
87
87
|
output.push(false)
|
|
88
88
|
continue
|
|
89
89
|
}
|
|
90
|
+
if text.startsWith("!")
|
|
91
|
+
text = "(${text})" // no shell escapes here
|
|
90
92
|
try {
|
|
91
93
|
source = new(textstream, text.concat(" ;")) // avoid EOF
|
|
92
94
|
if locals
|
|
93
95
|
source.setsymbols(locals)
|
|
94
96
|
registry = modlist().Lib.exports.Registry // dialect registry
|
|
95
|
-
dialect = registry.findName(registry.dialects().0) // ### default
|
|
97
|
+
dialect = registry.findName(registry.dialects().0) // ### default dialect
|
|
96
98
|
output.push(dialect.parse(source))
|
|
97
99
|
} catch {
|
|
98
100
|
if true {
|
|
@@ -19,12 +19,27 @@
|
|
|
19
19
|
*
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
closure TaskDispatcher(replier, local contexts, gohome, util) {
|
|
22
|
+
closure TaskDispatcher(replier, local contexts, gohome, coder, util) {
|
|
23
23
|
global()
|
|
24
24
|
contexts = { }
|
|
25
25
|
gohome = makeActivator()
|
|
26
|
+
coder = packageCoder(evalf)
|
|
26
27
|
util = modlist().Util.exports
|
|
27
|
-
|
|
28
|
+
|
|
29
|
+
// sendEval
|
|
30
|
+
//
|
|
31
|
+
// Send an evaluation request to the original execution context.
|
|
32
|
+
//
|
|
33
|
+
closure evalf(expr) {
|
|
34
|
+
debuglog("TaskDispatcher doesn't yet implement reverse proxy objects")
|
|
35
|
+
list(Error("### reverse object proxy not implemented"))
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// dispatcher
|
|
39
|
+
//
|
|
40
|
+
// Return a new task dispatcher.
|
|
41
|
+
//
|
|
42
|
+
closure dispatcher(data, local reply, restorens, context, expr, roots, proc, args, result) {
|
|
28
43
|
reply = {
|
|
29
44
|
xmsg: "error"
|
|
30
45
|
xid: data.xid
|
|
@@ -70,10 +85,14 @@ closure TaskDispatcher(replier, local contexts, gohome, util) {
|
|
|
70
85
|
intern: true // intern symbols
|
|
71
86
|
localroots: true // make roots local if needed to intern
|
|
72
87
|
execute: true // execute auto-running procedures
|
|
88
|
+
objectDecoder: coder.decodeObject
|
|
73
89
|
})
|
|
74
90
|
expr = caar(expr)
|
|
91
|
+
if expr.0 == `\.execute\-method
|
|
92
|
+
expr = coder.invokeMethod(expr.1, expr.2) // object method, args
|
|
93
|
+
else
|
|
94
|
+
expr = evalactive(expr) // evaluate expression
|
|
75
95
|
reply.error = undefined
|
|
76
|
-
expr = evalactive(expr)
|
|
77
96
|
if data.get
|
|
78
97
|
roots = new(data.get).map(function(sym){ // new() to get symbol from compress
|
|
79
98
|
compress(sym)
|
|
@@ -84,7 +103,8 @@ closure TaskDispatcher(replier, local contexts, gohome, util) {
|
|
|
84
103
|
roots = `(expr)
|
|
85
104
|
reply.result = util.pkgSave(`expr, roots, {
|
|
86
105
|
nsignore: true // don't report namespace errors
|
|
87
|
-
comments: true
|
|
106
|
+
comments: true
|
|
107
|
+
objectEncoder: coder.encodeObject}) // include comments
|
|
88
108
|
if context.namespace !== nsactive().0
|
|
89
109
|
{ // evaluation changed namespace
|
|
90
110
|
context.namespace = nsactive().0
|
|
@@ -34,13 +34,17 @@
|
|
|
34
34
|
*
|
|
35
35
|
*/
|
|
36
36
|
|
|
37
|
-
closure dapoTable(database,
|
|
37
|
+
closure dapoTable(database, rootpath, local table, prefix) {
|
|
38
38
|
global()
|
|
39
|
+
if !database || !string(rootpath)
|
|
40
|
+
return (list(Error("invalid arguments")))
|
|
39
41
|
table = new(object, this)
|
|
40
42
|
table.type = database.type
|
|
41
43
|
table.db = database
|
|
42
|
-
|
|
43
|
-
|
|
44
|
+
if rootpath != "" && rootpath.slice(-1) != "/"
|
|
45
|
+
rootpath = rootpath.concat("/") // "" or "<path>/"
|
|
46
|
+
table.rootpath = rootpath
|
|
47
|
+
table.prefix = makePrefix(rootpath)
|
|
44
48
|
|
|
45
49
|
// makePrefix
|
|
46
50
|
//
|
|
@@ -80,7 +84,7 @@ closure dapoTable(database, path, local table, prefix) {
|
|
|
80
84
|
return (syncAdapter(add, key, content, metadata))
|
|
81
85
|
id = makeID(key)
|
|
82
86
|
if !string(id)
|
|
83
|
-
return (asyncResult(callback, id))
|
|
87
|
+
return (asyncResult(callback, id)) // error from makeID
|
|
84
88
|
if metadata && !dictionary(metadata)
|
|
85
89
|
return (asyncResult(callback, Error("invalid arguments")))
|
|
86
90
|
if !database.pouch
|
|
@@ -291,7 +295,7 @@ closure dapoTable(database, path, local table, prefix) {
|
|
|
291
295
|
// only immediate children are listed, with directories at the end--and no metadata for them.
|
|
292
296
|
//
|
|
293
297
|
|
|
294
|
-
table.records = closure records(options, callback, local prefix, pouchOpts, output) {
|
|
298
|
+
table.records = closure records(options, callback, local prefix, prelen, pouchOpts, output) {
|
|
295
299
|
if !callback
|
|
296
300
|
return (syncAdapter(records, options))
|
|
297
301
|
output = {
|
|
@@ -300,9 +304,11 @@ closure dapoTable(database, path, local table, prefix) {
|
|
|
300
304
|
if !string(options.prefix)
|
|
301
305
|
return (asyncResult(callback, Error("prefix option must be string")))
|
|
302
306
|
output.prefix = options.prefix
|
|
303
|
-
prefix = table.prefix.concat(makePrefix(options.prefix))
|
|
304
|
-
|
|
307
|
+
prefix = table.prefix.concat(makePrefix(options.prefix))
|
|
308
|
+
prelen = options.prefix.length }
|
|
309
|
+
else {
|
|
305
310
|
prefix = table.prefix
|
|
311
|
+
prelen = 0 }
|
|
306
312
|
if !database.pouch
|
|
307
313
|
return (asyncResult(callback, Error("database closed")))
|
|
308
314
|
pouchOpts = {
|
|
@@ -321,19 +327,24 @@ closure dapoTable(database, path, local table, prefix) {
|
|
|
321
327
|
key = obj.id.substring(table.prefix.length)
|
|
322
328
|
else
|
|
323
329
|
key = "*key error*" // should not happen
|
|
324
|
-
if !options.deep {
|
|
325
|
-
offset = key.indexOf("/", prefix.length)
|
|
326
|
-
if offset >= 0 {
|
|
327
|
-
key = key.substring(0, offset+1) // child directory name
|
|
328
|
-
if !firstkids[key]
|
|
329
|
-
firstkids[key] = key // first time we've seen this child directory
|
|
330
|
-
else
|
|
331
|
-
continue } } // ignore deeper child
|
|
332
330
|
item = {
|
|
333
331
|
key: key
|
|
334
332
|
_id: obj.id
|
|
335
333
|
_rev: obj.value.rev
|
|
336
334
|
}
|
|
335
|
+
if !options.deep {
|
|
336
|
+
offset = key.indexOf("/", prelen) // start looking past options.prefix
|
|
337
|
+
if offset >= 0 { // directory child
|
|
338
|
+
if length(key) > offset+1 { // transitive child (not directory itself)
|
|
339
|
+
obj.doc = undefined // just record directory name
|
|
340
|
+
item._id = undefined
|
|
341
|
+
item._rev = undefined }
|
|
342
|
+
key = key.substring(0, offset+1) // child directory name
|
|
343
|
+
if !firstkids[key]
|
|
344
|
+
firstkids[key] = key // first time we've seen this child directory
|
|
345
|
+
else
|
|
346
|
+
continue // ignore deeper child
|
|
347
|
+
item.key = key } }
|
|
337
348
|
if obj.doc { // docs were requested
|
|
338
349
|
if obj.doc.content {
|
|
339
350
|
item._md5 = HashMD5(obj.doc.content)
|
|
@@ -508,7 +519,7 @@ closure ListBrowserDBs(local pending, output, item) {
|
|
|
508
519
|
*/
|
|
509
520
|
|
|
510
521
|
closure DbConnector(psm, local connClassID, connector, watch) {
|
|
511
|
-
global()
|
|
522
|
+
global(js)
|
|
512
523
|
connClassID = "PouchDB"
|
|
513
524
|
connector = new(object, this)
|
|
514
525
|
connector.psm = psm
|
|
@@ -741,6 +752,8 @@ closure DbConnector(psm, local connClassID, connector, watch) {
|
|
|
741
752
|
//
|
|
742
753
|
// Connect to a database, returning a PSM view.
|
|
743
754
|
connector.connect = function connect(resID, service, args, local error, creds, db, rootpath, table) {
|
|
755
|
+
if !resID || args && !tuple(args)
|
|
756
|
+
return (list(Error("invalid arguments")))
|
|
744
757
|
`(error, creds) = connector.access(resID)
|
|
745
758
|
if !error
|
|
746
759
|
`(error, db) = PouchDB(creds)
|
|
@@ -751,7 +764,7 @@ closure DbConnector(psm, local connClassID, connector, watch) {
|
|
|
751
764
|
else if service == "NideFS" {
|
|
752
765
|
rootpath = args.0 // connect to a NideFS filesystem
|
|
753
766
|
if !rootpath
|
|
754
|
-
return (Error("mandatory rootpath missing"))
|
|
767
|
+
return (list(Error("mandatory rootpath missing")))
|
|
755
768
|
`(error, table) = db.table(rootpath)
|
|
756
769
|
if error
|
|
757
770
|
list(error)
|
|
@@ -766,7 +766,7 @@ function fimaInit(local manifest) {
|
|
|
766
766
|
|
|
767
767
|
manifest = `(FileManager, fimaStore, fimaInit)
|
|
768
768
|
|
|
769
|
-
Naan.module.build(module.id, "
|
|
769
|
+
Naan.module.build(module.id, "file_manager", function(modobj, compobj) {
|
|
770
770
|
require("./storage.nlg")
|
|
771
771
|
commonWatching = require("../common/watching.nlg")
|
|
772
772
|
compobj.manifest = manifest
|
|
@@ -260,6 +260,16 @@ closure MakePSMutil(fs, local util) {
|
|
|
260
260
|
|
|
261
261
|
util.deepcopy = closure deepcopy(inpath, sources, outfs, outpath, options, callback,
|
|
262
262
|
local errors, copies, fsopt, folders) {
|
|
263
|
+
|
|
264
|
+
// fixpath
|
|
265
|
+
// Fix the path to match the destination.
|
|
266
|
+
function fixpath(path) {
|
|
267
|
+
if fs.path.sep == outfs.path.sep
|
|
268
|
+
path
|
|
269
|
+
else
|
|
270
|
+
path.replaceAll(fs.path.sep, outfs.path.sep)
|
|
271
|
+
}
|
|
272
|
+
|
|
263
273
|
if !callback
|
|
264
274
|
return (syncAdapter(deepcopy, inpath, sources, outfs, outpath, options))
|
|
265
275
|
if sources && !array(sources) || !string(inpath) || !string(outpath)
|
|
@@ -281,7 +291,7 @@ closure MakePSMutil(fs, local util) {
|
|
|
281
291
|
asyncArray(sources, 10, closure mklist(entry,
|
|
282
292
|
local srcpath, destpath, epath, error, stat, folder, node) {
|
|
283
293
|
srcpath = fs.path.join(inpath, entry)
|
|
284
|
-
destpath = outfs.path.join(outpath, entry)
|
|
294
|
+
destpath = fixpath(outfs.path.join(outpath, entry))
|
|
285
295
|
if destpath == "."
|
|
286
296
|
destpath = "" // joined empty strings
|
|
287
297
|
`(error, stat) = fs.info(srcpath, fsopt)
|