summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/request.h2
-rw-r--r--include/types.h5
-rw-r--r--include/urweb.h9
-rw-r--r--lib/js/urweb.js8
-rw-r--r--src/c/cgi.c2
-rw-r--r--src/c/fastcgi.c2
-rw-r--r--src/c/http.c2
-rw-r--r--src/c/request.c15
-rw-r--r--src/c/urweb.c61
-rw-r--r--src/cjr_print.sml6
-rw-r--r--src/cjrize.sml2
-rw-r--r--src/jscomp.sml3
-rw-r--r--src/mono_opt.sml3
-rw-r--r--tests/rs.ur15
-rw-r--r--tests/rs.urs1
15 files changed, 102 insertions, 34 deletions
diff --git a/include/request.h b/include/request.h
index d2385af7..dd0359c9 100644
--- a/include/request.h
+++ b/include/request.h
@@ -22,7 +22,7 @@ request_result uw_request(uw_request_context, uw_context,
int (*send)(int sockfd, const void *buf, ssize_t len),
int (*close)(int fd));
-uw_context uw_request_new_context(uw_app*, void *logger_data, uw_logger log_error, uw_logger log_debug);
+uw_context uw_request_new_context(int id, uw_app*, void *logger_data, uw_logger log_error, uw_logger log_debug);
typedef struct {
uw_app *app;
diff --git a/include/types.h b/include/types.h
index 28658862..1e479398 100644
--- a/include/types.h
+++ b/include/types.h
@@ -35,6 +35,11 @@ typedef struct {
unsigned cli, chn;
} uw_Basis_channel;
+typedef struct {
+ int context;
+ unsigned long long source;
+} uw_Basis_source;
+
typedef struct uw_Basis_file {
uw_Basis_string name, type;
uw_Basis_blob data;
diff --git a/include/urweb.h b/include/urweb.h
index 30db875b..15ef33e5 100644
--- a/include/urweb.h
+++ b/include/urweb.h
@@ -20,7 +20,7 @@ void uw_client_connect(unsigned id, int pass, int sock,
void uw_prune_clients(uw_context);
failure_kind uw_initialize(uw_context);
-uw_context uw_init(void *logger_data, uw_logger log_debug);
+uw_context uw_init(int id, void *logger_data, uw_logger log_debug);
void uw_close(uw_context);
int uw_set_app(uw_context, uw_app*);
uw_app *uw_get_app(uw_context);
@@ -71,12 +71,13 @@ int uw_next_entry(uw_context);
void uw_write(uw_context, const char*);
-uw_Basis_int uw_Basis_new_client_source(uw_context, uw_Basis_string);
-uw_unit uw_Basis_set_client_source(uw_context, uw_Basis_int, uw_Basis_string);
+uw_Basis_source uw_Basis_new_client_source(uw_context, uw_Basis_string);
+uw_unit uw_Basis_set_client_source(uw_context, uw_Basis_source, uw_Basis_string);
void uw_set_script_header(uw_context, const char*);
const char *uw_Basis_get_settings(uw_context, uw_unit);
const char *uw_Basis_get_script(uw_context, uw_unit);
+const char *uw_get_real_script(uw_context);
uw_Basis_string uw_Basis_maybe_onload(uw_context, uw_Basis_string);
uw_Basis_string uw_Basis_maybe_onunload(uw_context, uw_Basis_string);
@@ -90,6 +91,7 @@ char *uw_Basis_htmlifyString(uw_context, uw_Basis_string);
char *uw_Basis_htmlifyBool(uw_context, uw_Basis_bool);
char *uw_Basis_htmlifyTime(uw_context, uw_Basis_time);
char *uw_Basis_htmlifySpecialChar(uw_context, unsigned char);
+char *uw_Basis_htmlifySource(uw_context, uw_Basis_source);
uw_unit uw_Basis_htmlifyInt_w(uw_context, uw_Basis_int);
uw_unit uw_Basis_htmlifyFloat_w(uw_context, uw_Basis_float);
@@ -97,6 +99,7 @@ uw_unit uw_Basis_htmlifyString_w(uw_context, uw_Basis_string);
uw_unit uw_Basis_htmlifyBool_w(uw_context, uw_Basis_bool);
uw_unit uw_Basis_htmlifyTime_w(uw_context, uw_Basis_time);
uw_unit uw_Basis_htmlifySpecialChar_w(uw_context, unsigned char);
+uw_unit uw_Basis_htmlifySource_w(uw_context, uw_Basis_source);
char *uw_Basis_attrifyInt(uw_context, uw_Basis_int);
char *uw_Basis_attrifyFloat(uw_context, uw_Basis_float);
diff --git a/lib/js/urweb.js b/lib/js/urweb.js
index 3cb667d6..f5764896 100644
--- a/lib/js/urweb.js
+++ b/lib/js/urweb.js
@@ -734,8 +734,14 @@ function rc(prefix, uri, parse, k, needsSig) {
} catch (e) { }
if (isok) {
+ var lines = xhr.responseText.split("\n");
+ if (lines.length != 2)
+ whine("Bad RPC response lines");
+
+ eval(lines[0]);
+
try {
- k(parse(xhr.responseText));
+ k(parse(lines[1]));
} catch (v) {
doExn(v);
}
diff --git a/src/c/cgi.c b/src/c/cgi.c
index 50d64f58..52d122ca 100644
--- a/src/c/cgi.c
+++ b/src/c/cgi.c
@@ -56,7 +56,7 @@ static void log_debug(void *data, const char *fmt, ...) {
}
int main(int argc, char *argv[]) {
- uw_context ctx = uw_request_new_context(&uw_application, NULL, log_error, log_debug);
+ uw_context ctx = uw_request_new_context(0, &uw_application, NULL, log_error, log_debug);
uw_request_context rc = uw_new_request_context();
request_result rr;
char *method = getenv("REQUEST_METHOD"),
diff --git a/src/c/fastcgi.c b/src/c/fastcgi.c
index ec1afb8e..161cb834 100644
--- a/src/c/fastcgi.c
+++ b/src/c/fastcgi.c
@@ -322,7 +322,7 @@ int fastcgi_send_normal(int sock, const void *buf, ssize_t len) {
static void *worker(void *data) {
FCGI_Input *in = fastcgi_input();
FCGI_Output *out = fastcgi_output();
- uw_context ctx = uw_request_new_context(&uw_application, out, log_error, log_debug);
+ uw_context ctx = uw_request_new_context(*(int *)data, &uw_application, out, log_error, log_debug);
uw_request_context rc = uw_new_request_context();
headers hs;
size_t body_size = 0;
diff --git a/src/c/http.c b/src/c/http.c
index 7ba06871..579c874e 100644
--- a/src/c/http.c
+++ b/src/c/http.c
@@ -63,7 +63,7 @@ static void log_debug(void *data, const char *fmt, ...) {
static void *worker(void *data) {
int me = *(int *)data;
- uw_context ctx = uw_request_new_context(&uw_application, NULL, log_error, log_debug);
+ uw_context ctx = uw_request_new_context(me, &uw_application, NULL, log_error, log_debug);
size_t buf_size = 2;
char *buf = malloc(buf_size);
uw_request_context rc = uw_new_request_context();
diff --git a/src/c/request.c b/src/c/request.c
index 2d0d0dc7..3fd12ff6 100644
--- a/src/c/request.c
+++ b/src/c/request.c
@@ -32,8 +32,8 @@ static int try_rollback(uw_context ctx, int will_retry, void *logger_data, uw_lo
return r;
}
-uw_context uw_request_new_context(uw_app *app, void *logger_data, uw_logger log_error, uw_logger log_debug) {
- uw_context ctx = uw_init(logger_data, log_debug);
+uw_context uw_request_new_context(int id, uw_app *app, void *logger_data, uw_logger log_error, uw_logger log_debug) {
+ uw_context ctx = uw_init(id, logger_data, log_debug);
int retries_left = MAX_RETRIES;
uw_set_app(ctx, app);
@@ -84,13 +84,14 @@ typedef struct {
} loggers;
typedef struct {
+ int id;
loggers *ls;
uw_periodic pdic;
} periodic;
static void *periodic_loop(void *data) {
periodic *p = (periodic *)data;
- uw_context ctx = uw_request_new_context(p->ls->app, p->ls->logger_data, p->ls->log_error, p->ls->log_debug);
+ uw_context ctx = uw_request_new_context(p->id, p->ls->app, p->ls->logger_data, p->ls->log_error, p->ls->log_debug);
if (!ctx)
exit(1);
@@ -127,6 +128,7 @@ void uw_request_init(uw_app *app, void *logger_data, uw_logger log_error, uw_log
failure_kind fk;
uw_periodic *ps;
loggers *ls = malloc(sizeof(loggers));
+ int id;
ls->app = app;
ls->logger_data = logger_data;
@@ -145,7 +147,7 @@ void uw_request_init(uw_app *app, void *logger_data, uw_logger log_error, uw_log
}
}
- ctx = uw_request_new_context(app, logger_data, log_error, log_debug);
+ ctx = uw_request_new_context(0, app, logger_data, log_error, log_debug);
if (!ctx)
exit(1);
@@ -164,9 +166,11 @@ void uw_request_init(uw_app *app, void *logger_data, uw_logger log_error, uw_log
uw_free(ctx);
+ id = 1;
for (ps = app->periodics; ps->callback; ++ps) {
pthread_t thread;
periodic *arg = malloc(sizeof(periodic));
+ arg->id = id++;
arg->ls = ls;
arg->pdic = *ps;
@@ -218,6 +222,7 @@ request_result uw_request(uw_request_context rc, uw_context ctx,
char errmsg[ERROR_BUF_LEN];
uw_reset(ctx);
+
rc->queryString[0] = 0;
for (s = path; *s; ++s) {
@@ -546,7 +551,7 @@ request_result uw_request(uw_request_context rc, uw_context ctx,
void *client_pruner(void *data) {
loggers *ls = (loggers *)data;
- uw_context ctx = uw_request_new_context(ls->app, ls->logger_data, ls->log_error, ls->log_debug);
+ uw_context ctx = uw_request_new_context(0, ls->app, ls->logger_data, ls->log_error, ls->log_debug);
if (!ctx)
exit(1);
diff --git a/src/c/urweb.c b/src/c/urweb.c
index 27dfd909..582aaf29 100644
--- a/src/c/urweb.c
+++ b/src/c/urweb.c
@@ -399,6 +399,7 @@ typedef struct {
struct uw_context {
uw_app *app;
+ int id;
char *(*get_header)(void *, const char *);
void *get_header_data;
@@ -408,7 +409,7 @@ struct uw_context {
input *inputs, *subinputs, *cur_container;
size_t sz_inputs, n_subinputs, used_subinputs;
- int source_count;
+ unsigned long long source_count;
void *db;
@@ -454,10 +455,11 @@ size_t uw_page_max = SIZE_MAX;
size_t uw_heap_max = SIZE_MAX;
size_t uw_script_max = SIZE_MAX;
-uw_context uw_init(void *logger_data, uw_logger log_debug) {
+uw_context uw_init(int id, void *logger_data, uw_logger log_debug) {
uw_context ctx = malloc(sizeof(struct uw_context));
ctx->app = NULL;
+ ctx->id = id;
ctx->get_header = NULL;
ctx->get_header_data = NULL;
@@ -584,7 +586,6 @@ void uw_reset_keep_error_message(uw_context ctx) {
uw_buffer_reset(&ctx->heap);
ctx->regions = NULL;
ctx->cleanup_front = ctx->cleanup;
- ctx->source_count = 0;
ctx->used_deltas = 0;
ctx->client = NULL;
ctx->cur_container = NULL;
@@ -621,6 +622,10 @@ void uw_close(uw_context ctx) {
ctx->app->db_close(ctx);
}
+uw_Basis_string uw_Basis_requestHeader(uw_context ctx, uw_Basis_string h) {
+ return ctx->get_header(ctx->get_header_data, h);
+}
+
void uw_set_headers(uw_context ctx, char *(*get_header)(void *, const char *), void *get_header_data) {
ctx->get_header = get_header;
ctx->get_header_data = get_header_data;
@@ -680,10 +685,6 @@ void uw_push_cleanup(uw_context ctx, void (*func)(void *), void *arg) {
++ctx->cleanup_front;
}
-uw_Basis_string uw_Basis_requestHeader(uw_context ctx, uw_Basis_string h) {
- return ctx->get_header(ctx->get_header_data, h);
-}
-
char *uw_Basis_htmlifyString(uw_context, const char *);
void uw_login(uw_context ctx) {
@@ -1296,6 +1297,10 @@ const char *uw_Basis_get_script(uw_context ctx, uw_unit u) {
return "<sc>";
}
+const char *uw_get_real_script(uw_context ctx) {
+ return ctx->script.start;
+}
+
uw_Basis_string uw_Basis_maybe_onload(uw_context ctx, uw_Basis_string s) {
if (s[0] == 0)
return "";
@@ -1345,7 +1350,7 @@ const char *uw_Basis_get_settings(uw_context ctx, uw_unit u) {
uw_Basis_string uw_Basis_jsifyString(uw_context ctx, uw_Basis_string s) {
char *r, *s2;
- uw_check_heap(ctx, strlen(s) * 4 + 2);
+ uw_check_heap(ctx, strlen(s) * 4 + 3);
r = s2 = ctx->heap.front;
*s2++ = '"';
@@ -1385,7 +1390,7 @@ uw_Basis_string uw_Basis_jsifyChar(uw_context ctx, uw_Basis_char c1) {
unsigned char c = c1;
char *r, *s2;
- uw_check_heap(ctx, 6);
+ uw_check_heap(ctx, 7);
r = s2 = ctx->heap.front;
*s2++ = '"';
@@ -1420,7 +1425,7 @@ uw_Basis_string uw_Basis_jsifyChar(uw_context ctx, uw_Basis_char c1) {
uw_Basis_string uw_Basis_jsifyString_ws(uw_context ctx, uw_Basis_string s) {
char *r, *s2;
- uw_check_script(ctx, strlen(s) * 4 + 2);
+ uw_check_script(ctx, strlen(s) * 4 + 3);
r = s2 = ctx->script.front;
*s2++ = '"';
@@ -1467,27 +1472,28 @@ char *uw_Basis_jsifyChannel(uw_context ctx, uw_Basis_channel chn) {
}
}
-uw_Basis_int uw_Basis_new_client_source(uw_context ctx, uw_Basis_string s) {
+uw_Basis_source uw_Basis_new_client_source(uw_context ctx, uw_Basis_string s) {
int len;
size_t s_len = strlen(s);
- uw_check_script(ctx, 18 + INTS_MAX + s_len);
- sprintf(ctx->script.front, "var s%d=sc(exec(%n", ctx->source_count, &len);
+ uw_check_script(ctx, 15 + 2 * INTS_MAX + s_len);
+ sprintf(ctx->script.front, "s%d_%llu=sc(exec(%n", ctx->id, ctx->source_count, &len);
ctx->script.front += len;
strcpy(ctx->script.front, s);
ctx->script.front += s_len;
strcpy(ctx->script.front, "));");
ctx->script.front += 3;
- return ctx->source_count++;
+ uw_Basis_source r = {ctx->id, ctx->source_count++};
+ return r;
}
-uw_unit uw_Basis_set_client_source(uw_context ctx, uw_Basis_int n, uw_Basis_string s) {
+uw_unit uw_Basis_set_client_source(uw_context ctx, uw_Basis_source src, uw_Basis_string s) {
int len;
size_t s_len = strlen(s);
- uw_check_script(ctx, 12 + INTS_MAX + s_len);
- sprintf(ctx->script.front, "sv(s%d,exec(%n", (int)n, &len);
+ uw_check_script(ctx, 15 + 2 * INTS_MAX + s_len);
+ sprintf(ctx->script.front, "sv(s%d_%llu,exec(%n", src.context, src.source, &len);
ctx->script.front += len;
strcpy(ctx->script.front, s);
ctx->script.front += s_len;
@@ -2128,6 +2134,27 @@ uw_unit uw_Basis_htmlifyTime_w(uw_context ctx, uw_Basis_time t) {
return uw_unit_v;
}
+char *uw_Basis_htmlifySource(uw_context ctx, uw_Basis_source src) {
+ int len;
+ char *r;
+
+ uw_check_heap(ctx, 2 * INTS_MAX + 2);
+ r = ctx->heap.front;
+ sprintf(r, "s%d_%llu%n", src.context, src.source, &len);
+ ctx->heap.front += len+1;
+ return r;
+}
+
+uw_unit uw_Basis_htmlifySource_w(uw_context ctx, uw_Basis_source src) {
+ int len;
+
+ uw_check(ctx, 2 * INTS_MAX + 1);
+ sprintf(ctx->page.front, "s%d_%llu%n", src.context, src.source, &len);
+ ctx->page.front += len;
+
+ return uw_unit_v;
+}
+
uw_Basis_char uw_Basis_strsub(uw_context ctx, uw_Basis_string s, uw_Basis_int n) {
while (n >= 0) {
if (*s == 0)
diff --git a/src/cjr_print.sml b/src/cjr_print.sml
index d6c0db98..3988a921 100644
--- a/src/cjr_print.sml
+++ b/src/cjr_print.sml
@@ -2723,7 +2723,11 @@ fun p_file env (ds, ps) =
string ", 0);",
newline,
box (case ek of
- Core.Rpc _ => [urlify env ran]
+ Core.Rpc _ => [string "uw_write(ctx, uw_get_real_script(ctx));",
+ newline,
+ string "uw_write(ctx, \"\\n\");",
+ newline,
+ urlify env ran]
| _ => [string "uw_write(ctx, \"</html>\");",
newline]),
string "return;",
diff --git a/src/cjrize.sml b/src/cjrize.sml
index 2c13e494..b48a4ebd 100644
--- a/src/cjrize.sml
+++ b/src/cjrize.sml
@@ -161,7 +161,7 @@ fun cifyTyp x =
in
((L'.TList (t', si), loc), sm)
end
- | L.TSource => ((L'.TFfi ("Basis", "int"), loc), sm)
+ | L.TSource => ((L'.TFfi ("Basis", "source"), loc), sm)
| L.TSignal _ => raise Fail "Cjrize: TSignal remains"
in
cify IM.empty x
diff --git a/src/jscomp.sml b/src/jscomp.sml
index ce64c11b..d8b2d661 100644
--- a/src/jscomp.sml
+++ b/src/jscomp.sml
@@ -91,8 +91,7 @@ fun process file =
fun quoteExp loc (t : typ) (e, st) =
case #1 t of
- TSource => (strcat loc [str loc "s",
- (EFfiApp ("Basis", "htmlifyInt", [e]), loc)], st)
+ TSource => ((EFfiApp ("Basis", "htmlifySource", [e]), loc), st)
| TRecord [] => (str loc "null", st)
| TRecord [(x, t)] =>
diff --git a/src/mono_opt.sml b/src/mono_opt.sml
index 12a811cb..34c13e82 100644
--- a/src/mono_opt.sml
+++ b/src/mono_opt.sml
@@ -249,6 +249,9 @@ fun exp e =
| EFfiApp ("Basis", "htmlifyString_w", [(EPrim (Prim.String s), loc)]) =>
EWrite (EPrim (Prim.String (htmlifyString s)), loc)
+ | EWrite (EFfiApp ("Basis", "htmlifySource", [e]), _) =>
+ EFfiApp ("Basis", "htmlifySource_w", [e])
+
| EFfiApp ("Basis", "attrifyInt", [(EPrim (Prim.Int n), _)]) =>
EPrim (Prim.String (attrifyInt n))
| EWrite (EFfiApp ("Basis", "attrifyInt", [(EPrim (Prim.Int n), _)]), loc) =>
diff --git a/tests/rs.ur b/tests/rs.ur
new file mode 100644
index 00000000..ae5ff85f
--- /dev/null
+++ b/tests/rs.ur
@@ -0,0 +1,15 @@
+fun bobo () =
+ n1 <- source 0;
+ n2 <- source 1;
+ return <xml>
+ <dyn signal={n1 <- signal n1; n2 <- signal n2; return <xml>{[n1 + n2]}</xml>}/>
+ <button value="Increment1" onclick={v <- get n1; set n1 (v + 1)}/>
+ <button value="Increment2" onclick={v <- get n2; set n2 (v + 1)}/>
+ </xml>
+
+fun main () =
+ x <- source <xml/>;
+ return <xml><body>
+ <dyn signal={signal x}/>
+ <button value="Grab" onclick={y <- rpc (bobo ()); set x y}/>
+ </body></xml>
diff --git a/tests/rs.urs b/tests/rs.urs
new file mode 100644
index 00000000..6ac44e0b
--- /dev/null
+++ b/tests/rs.urs
@@ -0,0 +1 @@
+val main : unit -> transaction page