aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Adam Chlipala <adamc@hcoop.net>2009-03-10 11:18:01 -0400
committerGravatar Adam Chlipala <adamc@hcoop.net>2009-03-10 11:18:01 -0400
commit998ec0f6506d8b7065fbe277c253188b38bcac7c (patch)
tree99e4bdad36025df9b3bd37c782f9dd36f052307a
parent36b92359be479b92b5adcbdc669576e61d01f74a (diff)
React demo
-rw-r--r--demo/prose6
-rw-r--r--demo/react.ur6
-rw-r--r--demo/react.urp2
-rw-r--r--demo/react.urs1
-rw-r--r--include/urweb.h2
-rw-r--r--src/c/urweb.c6
-rw-r--r--src/cjr_print.sml5
-rw-r--r--src/scriptcheck.sml8
8 files changed, 27 insertions, 9 deletions
diff --git a/demo/prose b/demo/prose
index ab32a753..9c2639ff 100644
--- a/demo/prose
+++ b/demo/prose
@@ -191,3 +191,9 @@ alert.urp
<p>Ur/Web makes it easy to write code whose execution should be distributed between the web server and client web browsers. Server-side code is compiled to efficient native code, and client-side code is compiled to JavaScript. Ur/Web programmers don't need to worry about these details, because the language and standard library provide a uniform ML-like interface for the whole process.</p>
<p>Here's an example of a button that, when clicked, opens an alert dialog on the client.</p>
+
+react.urp
+
+<p>Most client-side JavaScript programs modify page contents imperatively, but Ur/Web is based on functional-reactive programming instead. Programs allocate data sources and then describe the page as a pure function of those data sources. When the sources change, the page changes automatically.</p>
+
+<p>Here's an example where a button modifies a data source that affects some text on the page. The affected portion of the page is indicated with the pseudo-HTML tag <tt>dyn</tt>, whose <tt>signal</tt> attribute specifies one of these pure functions over mutable sources. A source containing data of type <tt>t</tt> has type <tt>source t</tt> and is created with the <tt>source</tt> operation within the <tt>transaction</tt> monad. Functions over sources are represented in the monad <tt>signal</tt>. Like in Haskell, we overload monad notations, so that the same return and bind operators can be used to write signals and transactions. The <tt>signal</tt> function coerces a source to a signal.</p>
diff --git a/demo/react.ur b/demo/react.ur
new file mode 100644
index 00000000..0c460478
--- /dev/null
+++ b/demo/react.ur
@@ -0,0 +1,6 @@
+fun main () =
+ s <- source "You didn't click it yet.";
+ return <xml><body>
+ <button value="Click me!" onclick={set s "Now you clicked it."}/><br/>
+ <dyn signal={v <- signal s; return <xml>{[v]}</xml>}/>
+ </body></xml>
diff --git a/demo/react.urp b/demo/react.urp
new file mode 100644
index 00000000..80ed64e1
--- /dev/null
+++ b/demo/react.urp
@@ -0,0 +1,2 @@
+
+react
diff --git a/demo/react.urs b/demo/react.urs
new file mode 100644
index 00000000..6ac44e0b
--- /dev/null
+++ b/demo/react.urs
@@ -0,0 +1 @@
+val main : unit -> transaction page
diff --git a/include/urweb.h b/include/urweb.h
index fb3b5068..63066e20 100644
--- a/include/urweb.h
+++ b/include/urweb.h
@@ -40,7 +40,7 @@ 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);
void uw_set_script_header(uw_context, const char*);
-char *uw_Basis_get_script(uw_context, uw_unit);
+const char *uw_Basis_get_script(uw_context, uw_unit);
char *uw_Basis_htmlifyInt(uw_context, uw_Basis_int);
char *uw_Basis_htmlifyFloat(uw_context, uw_Basis_float);
diff --git a/src/c/urweb.c b/src/c/urweb.c
index 823e8824..d42cfaa6 100644
--- a/src/c/urweb.c
+++ b/src/c/urweb.c
@@ -382,11 +382,9 @@ void uw_write_script(uw_context ctx, uw_Basis_string s) {
ctx->script_front += len;
}
-char *uw_Basis_get_script(uw_context ctx, uw_unit u) {
+const char *uw_Basis_get_script(uw_context ctx, uw_unit u) {
if (ctx->script_front == ctx->script) {
- char *r = uw_malloc(ctx, 1);
- r[0] = 0;
- return r;
+ return ctx->script_header;
} else {
char *r = uw_malloc(ctx, 41 + (ctx->script_front - ctx->script) + strlen(ctx->script_header));
diff --git a/src/cjr_print.sml b/src/cjr_print.sml
index ab808426..4b6a56db 100644
--- a/src/cjr_print.sml
+++ b/src/cjr_print.sml
@@ -2349,7 +2349,10 @@ fun p_file env (ds, ps) =
newline,
string "uw_set_script_header(ctx, \"",
string (case side of
- ServerAndClient => "<script src=\\\"/app.js\\\"></script>\\n"
+ ServerAndClient => "<script src=\\\""
+ ^ OS.Path.joinDirFile {dir = !Monoize.urlPrefix,
+ file = "app.js"}
+ ^ "\\\"></script>\\n"
| ServerOnly => ""),
string "\");",
newline]),
diff --git a/src/scriptcheck.sml b/src/scriptcheck.sml
index bfe87766..fd4f4cd9 100644
--- a/src/scriptcheck.sml
+++ b/src/scriptcheck.sml
@@ -38,8 +38,10 @@ structure IS = IntBinarySet
val csBasis = SS.addList (SS.empty,
["new_client_source",
"get_client_source",
- "set_client_source",
- "alert"])
+ "set_client_source"])
+
+val scriptWords = ["<script",
+ " onclick="]
fun classify (ds, ps) =
let
@@ -54,7 +56,7 @@ fun classify (ds, ps) =
let
fun hasClient e =
case #1 e of
- EPrim (Prim.String s) => inString {needle = "<script", haystack = s}
+ EPrim (Prim.String s) => List.exists (fn n => inString {needle = n, haystack = s}) scriptWords
| EPrim _ => false
| ERel _ => false
| ENamed n => IS.member (csids, n)