-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathjson-rpc.js
119 lines (112 loc) · 2.84 KB
/
json-rpc.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/**
* TODO: Integrate this with tlrobinson's json-rpc project
* Module for interacting with a WebWorker through JSON-RPC.
* You can make a module accessible through JSON-RPC as easily as:
* some-module.js:
* require("./json-rpc-worker").server(exports);
*
* And to create this worker and fire it off:
* var Worker = require("worker"),
* client = require("./json-rpc-worker").client;
* var workerInterface = client(new Worker("some-module"));
* workerInterface.call("foo", [1, 3]).then(function(result){
* ... do something with the result ...
* });
*
*/
var observe = require("promised-io/observe").observe,
print = require("promised-io/process").print,
when = require("promised-io/promise").when,
currentMetadata;
var invoke = exports.invoke = function(target, rpc, metadata){
currentMetadata = metadata;
try{
return when(when(target, function(target){
var result;
if(target[rpc.method] || !target.__noSuchMethod__){
return target[rpc.method].apply(target, rpc.params);
}
else{
return target.__noSuchMethod__.call(target, rpc.method, rpc.params);
}
}), function(result){
if(result instanceof Response){
result.body = {
result: result.body,
error: null,
id: rpc.id
}
return result;
}
return {
result: result,
error: null,
id: rpc.id
};
}, error);
}
catch(e){
return error(e);
}
function error(e){
print(e.stack || (e.rhinoException && e.rhinoException.printStackTrace()) || (e.name + ": " + e.message));
return {
result: null,
error: e.message,
id: rpc.id
};
};
};
exports.server = function(rpcObject){
Titanium.API.debug("json-rpc exports.server global");
if (global.onmessage) // dedicated worker
observe(global, "onmessage", handleMessage);
else // shared worker
observe(global, "onconnect", function (e) { e.port.onmessage = handleMessage; });
function handleMessage(event){
var data = event.data;
if("id" in data && "method" in data && "params" in data){
postMessage(invoke(rpcObject, event.data));
}
}
};
var nextId = 1;
exports.client = function(worker){
if(worker.port){
worker = worker.port;
}
var requestsWaiting = {};
observe(worker, "onmessage", function(event){
var data = event.data;
if(requestsWaiting[data.id]){
if(data.error === null){
requestsWaiting[data.id].fulfill(data.result);
}
else{
requestsWaiting[data.id].error(data.error);
}
delete requestsWaiting[data.id];
}
});
return {
call: function(method, params){
var id = nextId++;
worker.postMessage({
id: id,
method: method,
params: params
});
promise = new Promise();
requestsWaiting[id] = promise;
return promise;
}
};
};
try{
var Response = require("pintura/jsgi/response").Response;
}catch(e){
Response = function(){};
}
exports.getMetadata = function(){
return currentMetadata;
};