summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Adam Chlipala <adam@chlipala.net>2011-04-09 20:00:52 -0400
committerGravatar Adam Chlipala <adam@chlipala.net>2011-04-09 20:00:52 -0400
commitec9e1e78b0b0dc8c6766bd1ec2ec1ea5c2b291ca (patch)
treeafc1aa975eca7a387cdc88de716b920780ba4c89
parenta9d63c44fad31322477b51c11655adfb7002712e (diff)
Send newly created sources with messages to clients
-rw-r--r--lib/js/urweb.js65
-rw-r--r--src/c/http.c2
-rw-r--r--src/c/urweb.c15
-rw-r--r--tests/ms.ur35
-rw-r--r--tests/ms.urp4
-rw-r--r--tests/ms.urs1
6 files changed, 91 insertions, 31 deletions
diff --git a/lib/js/urweb.js b/lib/js/urweb.js
index f5764896..5a6ce21f 100644
--- a/lib/js/urweb.js
+++ b/lib/js/urweb.js
@@ -817,7 +817,7 @@ function listener() {
} catch (e) { }
if (isok) {
- var text = xhr.responseText
+ var text = xhr.responseText;
if (text == "")
return;
var lines = text.split("\n");
@@ -827,36 +827,47 @@ function listener() {
return;
}
- for (var i = 0; i+1 < lines.length; i += 2) {
- var chn = lines[i];
- var msg = lines[i+1];
-
- if (chn < 0)
- whine("Out-of-bounds channel in message from remote server");
-
- var ch;
-
- if (chn >= channels.length || channels[chn] == null) {
- ch = newChannel();
- channels[chn] = ch;
- } else
- ch = channels[chn];
-
- var listener = dequeue(ch.listeners);
- if (listener == null) {
- enqueue(ch.msgs, msg);
- } else {
- try {
- listener(msg);
- } catch (v) {
- doExn(v);
+ var messageReader = function(i) {
+ if (i+1 >= lines.length) {
+ xhrFinished(xhr);
+ connect();
+ }
+ else {
+ var chn = lines[i];
+ var msg = lines[i+1];
+
+ if (chn == "E") {
+ eval(msg);
+ window.setTimeout(function() { messageReader(i+2); }, 0);
+ } else {
+ if (chn < 0)
+ whine("Out-of-bounds channel in message from remote server");
+
+ var ch;
+
+ if (chn >= channels.length || channels[chn] == null) {
+ ch = newChannel();
+ channels[chn] = ch;
+ } else
+ ch = channels[chn];
+
+ var listener = dequeue(ch.listeners);
+ if (listener == null) {
+ enqueue(ch.msgs, msg);
+ } else {
+ try {
+ listener(msg);
+ } catch (v) {
+ doExn(v);
+ }
+ }
+
+ messageReader(i+2);
}
}
}
- xhrFinished(xhr);
-
- connect();
+ messageReader(0);
}
else {
try {
diff --git a/src/c/http.c b/src/c/http.c
index 579c874e..4b2f0576 100644
--- a/src/c/http.c
+++ b/src/c/http.c
@@ -198,7 +198,7 @@ static void *worker(void *data) {
on_success, on_failure,
NULL, log_error, log_debug,
sock, uw_really_send, close);
- uw_send(ctx, sock);
+ if (rr != KEEP_OPEN) uw_send(ctx, sock);
if (rr == SERVED || rr == FAILED)
close(sock);
diff --git a/src/c/urweb.c b/src/c/urweb.c
index 582aaf29..0bc739fc 100644
--- a/src/c/urweb.c
+++ b/src/c/urweb.c
@@ -311,16 +311,25 @@ static uw_Basis_channel new_channel(client *c) {
return ch;
}
-static void client_send(client *c, uw_buffer *msg) {
+static void client_send(client *c, uw_buffer *msg, const char *script, int script_len) {
pthread_mutex_lock(&c->lock);
if (c->sock != -1) {
c->send(c->sock, on_success, strlen(on_success));
c->send(c->sock, begin_msgs, sizeof(begin_msgs) - 1);
+ if (script_len > 0) {
+ c->send(c->sock, "E\n", 2);
+ c->send(c->sock, script, script_len);
+ c->send(c->sock, "\n", 1);
+ }
c->send(c->sock, msg->start, uw_buffer_used(msg));
c->close(c->sock);
c->sock = -1;
- } else if (uw_buffer_append(&c->msgs, msg->start, uw_buffer_used(msg)))
+ } else if ((script_len > 0
+ && (c->send(c->sock, "E\n", 2)
+ || c->send(c->sock, script, script_len)
+ || c->send(c->sock, "\n", 1)))
+ || uw_buffer_append(&c->msgs, msg->start, uw_buffer_used(msg)))
fprintf(stderr, "Client message buffer size exceeded");
pthread_mutex_unlock(&c->lock);
@@ -3167,7 +3176,7 @@ void uw_commit(uw_context ctx) {
assert (c != NULL && c->mode == USED);
- client_send(c, &d->msgs);
+ client_send(c, &d->msgs, ctx->script.start, uw_buffer_used(&ctx->script));
}
if (ctx->client)
diff --git a/tests/ms.ur b/tests/ms.ur
new file mode 100644
index 00000000..3dcc48cf
--- /dev/null
+++ b/tests/ms.ur
@@ -0,0 +1,35 @@
+table ms : {Client : client, Channel : channel xbody}
+
+val hitMe =
+ me <- self;
+ ch <- oneRowE1 (SELECT (ms.Channel)
+ FROM ms
+ WHERE ms.Client = {[me]});
+
+ s <- source 0;
+ send ch <xml>
+ <dyn signal={n <- signal s; return <xml>{[n]}</xml>}/>
+ <button value="Inc" onclick={n <- get s; set s (n + 1)}/>
+ </xml>
+
+fun main' () =
+ me <- self;
+ ch <- channel;
+ dml (INSERT INTO ms (Client, Channel) VALUES ({[me]}, {[ch]}));
+
+ s <- source <xml/>;
+
+ return <xml><body onload={let
+ fun loop () =
+ x <- recv ch;
+ set s x;
+ loop ()
+ in
+ loop ()
+ end}>
+ <button value="Another" onclick={rpc hitMe}/>
+ <dyn signal={signal s}/>
+ </body></xml>
+
+fun main () =
+ return <xml><body><form><submit action={main'}/></form></body></xml>
diff --git a/tests/ms.urp b/tests/ms.urp
new file mode 100644
index 00000000..83ae5847
--- /dev/null
+++ b/tests/ms.urp
@@ -0,0 +1,4 @@
+database dbname=test
+sql ms.sql
+
+ms
diff --git a/tests/ms.urs b/tests/ms.urs
new file mode 100644
index 00000000..6ac44e0b
--- /dev/null
+++ b/tests/ms.urs
@@ -0,0 +1 @@
+val main : unit -> transaction page