clientside 0.2.1 → 0.3
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.
- data/lib/__clientside_res__/clientside.js +6 -3
- data/lib/clientside.rb +51 -16
- metadata +1 -1
@@ -4,7 +4,7 @@ var makeClientsideProxy = (function() {
|
|
4
4
|
};
|
5
5
|
|
6
6
|
var remoteInvoke = function(socket, obj, method, args) {
|
7
|
-
var request = {"receiver": obj, "
|
7
|
+
var request = {"receiver": obj, "method_": method, "arguments": args};
|
8
8
|
var id = request.id = Date.now();
|
9
9
|
var promise = new Promise(function(resolve, reject) {
|
10
10
|
socket.pending[id] = [resolve, reject];
|
@@ -42,7 +42,7 @@ var makeClientsideSocket = (function() {
|
|
42
42
|
}
|
43
43
|
}
|
44
44
|
}
|
45
|
-
|
45
|
+
else if (obj instanceof Object) {
|
46
46
|
for (key in obj) {
|
47
47
|
if (obj[key].__clientside__) {
|
48
48
|
obj[key] = makeClientsideProxy(socket, obj[key]);
|
@@ -58,6 +58,7 @@ var makeClientsideSocket = (function() {
|
|
58
58
|
socket.onmessage = function(event) {
|
59
59
|
var response = JSON.parse(event.data);
|
60
60
|
var callbacks = socket.pending[response.id];
|
61
|
+
delete socket.pending[response.id];
|
61
62
|
if (!callbacks) {
|
62
63
|
return;
|
63
64
|
}
|
@@ -66,7 +67,7 @@ var makeClientsideSocket = (function() {
|
|
66
67
|
callbacks[0](response.result); // resolve
|
67
68
|
}
|
68
69
|
else {
|
69
|
-
callbacks[1](); // reject
|
70
|
+
callbacks[1](response.message); // reject
|
70
71
|
}
|
71
72
|
};
|
72
73
|
return socket;
|
@@ -75,3 +76,5 @@ var makeClientsideSocket = (function() {
|
|
75
76
|
return socketMaker;
|
76
77
|
})();
|
77
78
|
|
79
|
+
// vim:tabstop=4 shiftwidth=4 expandtab:
|
80
|
+
|
data/lib/clientside.rb
CHANGED
@@ -2,8 +2,9 @@ require 'json'
|
|
2
2
|
require 'faye/websocket'
|
3
3
|
require 'rack/static'
|
4
4
|
require 'securerandom'
|
5
|
+
require 'ostruct'
|
5
6
|
|
6
|
-
|
7
|
+
module Clientside
|
7
8
|
module Accessible
|
8
9
|
class << self
|
9
10
|
attr_accessor :cur_os
|
@@ -37,7 +38,8 @@ class Clientside
|
|
37
38
|
def to_json(*args)
|
38
39
|
name = self.class.name
|
39
40
|
methods = self.class.js_allowed
|
40
|
-
h = {__clientside__: true, __clientside_id__: object_id,
|
41
|
+
h = {__clientside__: true, __clientside_id__: object_id,
|
42
|
+
methods: methods}
|
41
43
|
h.to_json *args
|
42
44
|
end
|
43
45
|
end
|
@@ -45,8 +47,10 @@ class Clientside
|
|
45
47
|
class NoResMiddleware
|
46
48
|
RPATH = '/__clientside_sock__/'
|
47
49
|
MAX_OBJECTS = 256
|
50
|
+
PENDING_TTL = 5 * 60
|
48
51
|
|
49
52
|
@@pending_sockets = {}
|
53
|
+
@@pending_expiries = []
|
50
54
|
@@sockets = {}
|
51
55
|
|
52
56
|
def initialize(app)
|
@@ -58,11 +62,18 @@ class Clientside
|
|
58
62
|
end
|
59
63
|
|
60
64
|
def handle_message(cmd, ws)
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
65
|
+
can_receive = cmd.receiver.kind_of? Accessible
|
66
|
+
raise "receiver is not js-accessible" unless can_receive
|
67
|
+
is_name = cmd.method_.respond_to? :to_sym
|
68
|
+
raise "not a method name: #{cmd.method_}" unless is_name
|
69
|
+
allowed = cmd.receiver.class.js_allowed.include? cmd.method_.to_sym
|
70
|
+
raise "unknown method: #{cmd.method_}" unless allowed
|
71
|
+
|
72
|
+
begin
|
73
|
+
result = cmd.receiver.send cmd.method_, *cmd.arguments
|
74
|
+
rescue ArgumentError => e
|
75
|
+
raise e.message
|
76
|
+
end
|
66
77
|
o_tj_source = JSON::Ext::Generator::GeneratorMethods::Object
|
67
78
|
result = nil if result.method(:to_json).owner.equal? o_tj_source
|
68
79
|
|
@@ -70,14 +81,16 @@ class Clientside
|
|
70
81
|
unless @@sockets[ws].length >= MAX_OBJECTS
|
71
82
|
register_obj ws, result
|
72
83
|
else
|
73
|
-
raise
|
84
|
+
raise "too many objects allocated"
|
74
85
|
end
|
75
86
|
end
|
76
|
-
ws.send JSON.dump({status: 'success', id: cmd
|
87
|
+
ws.send JSON.dump({status: 'success', id: cmd.id, result: result})
|
77
88
|
end
|
78
89
|
|
79
90
|
def call(env)
|
80
|
-
|
91
|
+
is_websocket = Faye::WebSocket.websocket? env
|
92
|
+
for_us = env['REQUEST_PATH'].start_with? RPATH
|
93
|
+
if is_websocket and for_us
|
81
94
|
env['REQUEST_PATH'] =~ %r(\A#{RPATH}(.+)\Z)
|
82
95
|
cid = $1
|
83
96
|
objs = @@pending_sockets.delete(cid)
|
@@ -92,10 +105,27 @@ class Clientside
|
|
92
105
|
ws.on :message do |event|
|
93
106
|
begin
|
94
107
|
cmd = JSON.parse event.data, symbolize_names: true
|
95
|
-
|
108
|
+
needed = [:receiver, :method_, :arguments, :id]
|
109
|
+
unless needed.all? {|k| cmd.key? k}
|
110
|
+
if cmd.key? :id
|
111
|
+
ws.send JSON.dump({status: 'error',
|
112
|
+
message: 'invalid request', id: cmd[:id]})
|
113
|
+
end
|
114
|
+
next
|
115
|
+
end
|
116
|
+
cmd = Accessible.reinflate cmd, @@sockets[ws]
|
117
|
+
cmd = OpenStruct.new cmd
|
96
118
|
handle_message cmd, ws
|
97
|
-
rescue
|
98
|
-
|
119
|
+
rescue JSON::ParserError
|
120
|
+
rescue KeyError => e
|
121
|
+
e.message =~ /\Akey not found: (.+)\Z/
|
122
|
+
missing_id = $1
|
123
|
+
message = "unknown object id: #{missing_id}"
|
124
|
+
ws.send JSON.dump({status: 'error',
|
125
|
+
message: message, id: cmd.id})
|
126
|
+
rescue RuntimeError => e
|
127
|
+
ws.send JSON.dump({status: 'error',
|
128
|
+
message: e.message, id: cmd.id})
|
99
129
|
end
|
100
130
|
end
|
101
131
|
|
@@ -114,6 +144,11 @@ class Clientside
|
|
114
144
|
objs = Hash[objs.map {|o| [o.object_id, o]}]
|
115
145
|
cid = SecureRandom.hex
|
116
146
|
@@pending_sockets[cid] = objs
|
147
|
+
@@pending_expiries << [cid, Time.now + PENDING_TTL]
|
148
|
+
until @@pending_expiries.first[1] > Time.now
|
149
|
+
ecid, _ = @@pending_expiries.shift
|
150
|
+
@@pending_sockets.delete ecid
|
151
|
+
end
|
117
152
|
cid
|
118
153
|
end
|
119
154
|
end
|
@@ -128,9 +163,9 @@ class Clientside
|
|
128
163
|
|
129
164
|
def self.embed(objs)
|
130
165
|
objs.each do |var, obj|
|
131
|
-
raise ArgumentError, "invalid
|
166
|
+
raise ArgumentError, "invalid var name" unless var =~ /\A[a-zA-Z_]\w*\Z/
|
132
167
|
end
|
133
|
-
cid =
|
168
|
+
cid = Middleware.add_pending objs.values
|
134
169
|
sock_var = '$__clientside_socket__'
|
135
170
|
js = ""
|
136
171
|
js << %Q(<script src="/__clientside_res__/promise.min.js"></script>\n)
|
@@ -150,5 +185,5 @@ class Clientside
|
|
150
185
|
end
|
151
186
|
end
|
152
187
|
|
153
|
-
# vim:tabstop=2 shiftwidth=2
|
188
|
+
# vim:tabstop=2 shiftwidth=2 expandtab:
|
154
189
|
|