Skip to content

Commit

Permalink
#150 read 4.0 server-side event handler logic as fallback, restore us…
Browse files Browse the repository at this point in the history
…e of `client` on the client
  • Loading branch information
Jand42 committed Jan 8, 2018
1 parent 98254c1 commit 282e35b
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 13 deletions.
32 changes: 24 additions & 8 deletions WebSharper.UI/Attr.fs
Expand Up @@ -61,7 +61,7 @@ module private Internal =
meta.Quotations.Keys
|> Seq.map (sprintf " %O")
|> String.concat "\n"
failwithf "Failed to find compiled quotation at position %O\nExisting ones:\n%s" p ex
None
| true, (declType, meth, argNames) ->
match meta.Classes.TryGetValue declType with
| false, _ -> failwithf "Error in Handler: Couldn't find JavaScript address for method %s.%s" declType.Value.FullName meth.Value.MethodName
Expand All @@ -75,7 +75,7 @@ module private Internal =
args.[i] <-
match value with
| :? Expr as q ->
let x, reqs' = compile !reqs q
let x, reqs' = compile !reqs q |> Option.get
reqs := reqs'
x
| value ->
Expand All @@ -97,10 +97,12 @@ module private Internal =
| _ -> failwithf "Error in Handler: Couldn't find JavaScript address for method %s.%s" declType.Value.FullName meth.Value.MethodName
let funcall = String.concat "." (List.rev addr)
let args = String.concat "," args
sprintf "%s(%s)" funcall args, !reqs
| None -> failwithf "Failed to find location of quotation: %A" q
let s, reqs = compile reqs q
s + "(this)(event)", activateNode :: reqs
Some (sprintf "%s(%s)" funcall args, !reqs)
| None -> None
compile reqs q
|> Option.map (fun (s, reqs) ->
s + "(this)(event)", activateNode :: reqs
)

// We would have wanted to use UseNullAsTrueValue so that EmptyAttr = null,
// which makes things much easier when it comes to optional arguments in Templating.
Expand Down Expand Up @@ -158,7 +160,17 @@ type Attr =
let value = ref None
let init meta =
if Option.isNone !value then
value := Some (Internal.compile meta json [] q)
value :=
match Internal.compile meta json [] q with
| Some _ as v -> v
| _ ->
let m =
match q with
| Lambda (x1, Lambda (y1, Call(None, m, [Var x2; (Var y2 | Coerce(Var y2, _))]))) when x1 = x2 && y1 = y2 -> m
| _ -> failwithf "Invalid handler function: %A" q
let loc = WebSharper.Web.ClientSideInternals.getLocation' q
let func, reqs = Attr.HandlerFallback(m, loc)
Some (func meta, reqs)
let getValue (meta: M.Info) =
init meta
fst (Option.get !value)
Expand All @@ -170,7 +182,7 @@ type Attr =
static member Handler (event: string) ([<JavaScript>] q: Expr<Dom.Element -> #Dom.Event -> unit>) =
Attr.HandlerImpl event q

static member HandlerLinqImpl(event, m, location) =
static member HandlerFallback(m, location) =
let meth = R.ReadMethod m
let declType = R.ReadTypeDefinition m.DeclaringType
let reqs = [M.MethodNode (declType, meth); M.TypeNode declType]
Expand All @@ -192,6 +204,10 @@ type Attr =
s
| _ -> fail()
| Some v -> v
func, reqs

static member HandlerLinqImpl(event, m, location) =
let func, reqs = Attr.HandlerFallback(m, location)
DepAttr ("on" + event, func, fun _ -> reqs :> _)

static member HandlerLinq (event: string) (q: Expression<Action<Dom.Element, #Dom.Event>>) =
Expand Down
7 changes: 3 additions & 4 deletions WebSharper.UI/Doc.Client.fs
Expand Up @@ -1424,10 +1424,9 @@ type private Doc' [<JavaScript>] (docNode, updates) =
static member TextNode (s: string) : Doc =
As (Doc'.TextNode' s)

// Not proxied for now so that JavaScript attribute on argument does its job on the server
//[<JavaScript; Inline>]
//static member ClientSide (expr: Microsoft.FSharp.Quotations.Expr<#IControlBody>) : Doc =
// As expr
[<JavaScript; Inline>]
static member ClientSide (expr: Microsoft.FSharp.Quotations.Expr<#IControlBody>) : Doc =
As expr

[<JavaScript; Inline; Name "VerbatimProxy">]
static member Verbatim (s: string) : Doc =
Expand Down
3 changes: 2 additions & 1 deletion WebSharper.UI/HTML.fs
Expand Up @@ -40,7 +40,8 @@ module Html =
let textView v = Client.Doc.TextView v

/// Insert a client-side Doc.
let client ([<ReflectedDefinition; JavaScript>] q) = Doc.ClientSideImpl q
[<JavaScript; Inline>]
let client ([<ReflectedDefinition; JavaScript>] q) = Doc.ClientSide q

// {{ tag normal
/// Create an HTML element <a> with attributes and children.
Expand Down

0 comments on commit 282e35b

Please sign in to comment.