By Adam Granicz on Saturday, March 28, 2015 — 0 comments

WebSharper forum enhancements Core team

In recent weeks we had been busy with a series of enhancements to the WebSharper website and some underlying FPish services.

These include, among others:

  1. Editing and marking-as-answer for forum entries. We took this opportunity to catch up on markdown support and use that as the main input format instead of the custom FPish markup (which has been obsoleted since then), and pushed that change through displaying on FPish properly as well. Editing directly on the WebSharper website makes it more convenient to respond to forum entries or tidying up your past comments if necessary.

    Editing and marking-as-answer on forum entries

    These features are enabled for your own content only. We at times edit/enhance forum topics and their comments by hand, as well. We ask that you submit content 1) without typos, 2) format your code blocks appropriately (setting the language on blocks and quoting identifiers inlined in paragraphs), and 3) use proper markdown for bullet or numbered lists and other elements. If unsure, consult the markdown reference by clicking the Help button in the editor.

  2. Feeding Github tickets into the forums. This makes it easier to track tickets and shows what's happening in the main repository. The underlying machinery feeds GitHub updates into FPish topics (hidden from the other content), allowing us to do interesting analytics on this growing content in FPish. You can't comment on these forum entries directly, so just follow the GitHub icon to the original ticket.

    GitHub issues are now fed into the WebSharper forums

    We are planning to integrate GitHub tickets from extension repositories as well in the near future, starting with UI.Next and the other open source extensions.

  3. Fixing authentication with FPish, so it doesn't expire after a minute. You may have noticed an annoying flickering of the Login menu and the posting controls earlier when commenting or adding new forum topics on the WebSharper website. This turned out was due to a bug in how FPish handled Oauth sessions and is now fixed. To circumvent the issue earlier, we had to code the interaction controls with a timer to renew authentication tokens with FPish every minute, causing a short visual flickering. This is now fixed.

More work is underway. In particular, we are streamlining how commenting works and doing a facelift to the forums in the next round of releases. This is in preparation of rolling out a support surface for WebSharper support customers where they can file tickets and track progress of various items more easily, etc. This has traditionally lived on FPish, but is now being reimplemented and moved to the WebSharper website to provide a more consistent and streamlined experience.

Overall, we hope you will find the new forums better, and will take the time to use it to find answers to your WebSharper and related questions. Happy coding!

By Loïc Denuzière on Wednesday, March 18, 2015 — 0 comments

WebSharper 3.0 RC released Core team

Today we just pushed out our release candidate for WebSharper 3.0. This means that WebSharper 3.0 is now in feature freeze, and we will only be releasing bug fixes until the stable release of WebSharper. So if you were holding out on switching to 3.0 because of continuous breaking changes, now is the time to try it out!

WebSharper 3.0-rc1 is available for download right now.

We also made large enhancements to the online documentation; check out the sections on Sitelets, HTML combinators, WIG and UI.Next. More will be coming until the stable release.

Change log

Here is the list of changes:

  • Homogenize WebSharper.Html.Client, WebSharper.Html.Server and WebSharper.UI.Next.Html: the HTML combinators are now generated from a list of standard HTML tag names and attributes, to ensure consistency between the client and server libraries.

  • #337: Exception when building WebSharper itself in debug mode.

  • Html.Client:
    • Mouse and keyboard events have an Event field to access the underlying Dom.Event.
    • Add OnEvent to bind a custom event by name.

  • UI.Next:
    • Doc now implements WebSharper.Web.IControlBody. This means that it can be used directly as the Body of a Web.Control:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      
      type MyControl() =
          inherit Web.Control()
      
          [<JavaScript>]
          override this.Body =
              let rvText = Var.Create ""
              Doc.Concat [
                  Doc.Input rvText
                  Label [] [Doc.TextView rvText.View]
              ]
              :> _
  • JQuery:
    • Make the types of .on(), .off() and .one() more consistent with other event handlers such as .click(), passing the element and the event to the callback and returning the JQuery:

      1
      2
      3
      4
      
      JQuery.Of("#my-input")
          .On("paste", fun el ev ->
              JS.Alert ("Text pasted, value is now: " + JQuery.Of(el).Val()))
          .Ignore
    • Add Event.AsDomEvent.
    • Fix JQuery.GetJSON inline.

  • WebSharper.JavaScript:
    • More accurate Dom.Event class hierarchy.
    • #206: Add JS.Prompt().
    • #356: Move |>! from WebSharper.JavaScript to WebSharper, as it can be useful in some server-side scenarios.

  • Sitelets:
    • #327: Allow using all standard integer, float and decimal types in Sitelet.Infer.
    • #355: Fix Sitelet.Embed deadlock.
    • #357: In JSON deserialization, null can be used to represent None.
    • #363: Fix Template.LoadFrequency.WhenChanged.

  • Remoting:
    • #361: Show a warning when using a synchronous [<Rpc>] function.
    • #362: Throw an error when an [<Rpc>] function has a generic type.

  • WIG:
    • Removed access modifiers, as only public makes sense in a WIG definition anyway.
    • Deprecated Type.New(). It was mainly used for two purposes:
      • Self-reference: you can use TSelf instead.
      • Mutually recursive types: the recommended way is to name classes first and add members later:

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        
        let Chicken' = Class "Chicken"
        let Egg =
            Class "Egg"
            |+> Instance [
                "hatch" => T<unit> ^-> Chicken'
            ]
        let Chicken =
            Chicken'
            |+> Instance [
                "lay" => T<unit> ^-> Egg
            ]
    • Added Pattern.RequiredFields, Pattern.OptionalFields and Pattern.ObsoleteFields to create configuration objects in a more compositional way:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      
      // Existing Pattern.Config:
      let MyConfig : Class =		     
          Pattern.Config "classname" {
              Required =        
              [		
                  "name", T<string>	
              ]
              Optional = 
              [		
                  "width", T<int>	
                  "height", T<int>	
              ]
          }
          
      // New API:
      let MyConfig : Class =
          Class "classname"
          |+> Pattern.RequiredFields [
              "name", T<string>
          ]
          |+> Pattern.OptionalFields [
              "width", T<int>
              "height", T<int>
          ]

Future plans

This release candidate means that the 3.0 stable will be coming soon. In fact, unless a big issue holds us up, we will be releasing WebSharper 3.0 as early as next week.

After that, here is a peek at what you can expect from future releases:

  • TypeScript declarations: we will be stabilizing the support for outputting .d.ts declarations for generated JavaScript modules, which was an experimental feature so far.
  • F# 4.0 support: as soon as F# 4.0 is finalized, we will provide proxies for the extended standard library.
  • Source mapping: we will improve the support for source maps, in particular reduce the need for many-to-many mapping which several browsers have trouble with.

Happy coding!

By Loïc Denuzière on Monday, March 2, 2015 — 0 comments

CloudSharper 0.9.29 released Core team

Here comes a new release of CloudSharper, with a bunch of bug fixes as well as the first steps of a big UI enhancement. We are updating CloudSharper to a clearer, slicker and more modern flat visual style.

In this first installment, the startup screen and the dashboard have been completely redesigned, and dialog windows are also restyled.

Other improvements

  • Autocomplete for F# now filters members.
  • WebSharper has been updated to 3.0.36-alpha, together with the online documentation.

Fixes

  • #594: Autocomplete should not trigger if there is no identifier before .
  • #595: An exception is raised when creating a new file
  • #596: FSI input uses UTF8 encoding now

Happy coding!

By Loïc Denuzière on Wednesday, February 25, 2015 — 3 comments

WebSharper 3.0-alpha for Xamarin Studio / MonoDevelop is now available! Core team

We have updated the WebSharper Xamarin Studio / MonoDevelop add-in for the latest WebSharper 3.0.36-alpha. It is now easier than ever to get started with WebSharper 3.0 on Mac or Linux!

Here is how to install it:

  • Open the add-in manager.

  • Make sure that you have the F# Language Binding installed.

  • In the Gallery, add a new repository with the following address:

    https://raw.githubusercontent.com/intellifactory/monodevelop.websharper/master/repository/

  • The WebSharper add-in is now available under the "Web Development" category. Select it and click "Install".

Voilà! The "New Project" and "New Solution" dialogs now have a new category for WebSharper. In this category you can find the same templates that are provided by the Visual Studio extension and CloudSharper, to quickly start new projects using WebSharper.

You can check the sources for the addin here.

Happy coding!

By András Jankó on Wednesday, February 25, 2015 — 3 comments

WebSharper-3.0.36-alpha released Core team

This release brings the last batch of breaking changes we have planned before 3.0 stable. The three bigger items we have left are updating/fixing TypeScript output, reviewing code mapping and adding more documentation.

Namespace changes

We have shortened namespace names by changing every occurence of IntelliFactory.WebSharper to WebSharper. This affects base package and all extensions. Also IntelliFactory.JavaScript is renamed to WebSharper.Core.JavaScript. DLLs are similarly renamed with the exception of IntelliFactory.WebSharper.dll which is now WebSharper.Main.dll.

WebSharper.Formlets in a separate package

The Formlets library is now contained in the NuGet package WebSharper.Formlets. Its dependency, IntelliFactory.Reactive is in another new package IntelliFactory.Reactive.

JSON Sitelets

You can now create REST APIs easily by using F# types. See previous announcement.

User Session in Sitelets and Rpc functions

Up until now, the module WebSharper.Sitelets.UserSession could be used to manage user login. Unfortunately, functions in this module have two major drawbacks:

  • They use ASP.NET-specific functionality, and therefore cannot be used with other hosts such as self-hosted OWIN.
  • They assume that they run on the same thread that is responding to the request. This assumption is unreasonable, especially when using functions such as Content.PageContentAsync.

For these reasons, the following changes are made:

  • The module WebSharper.Sitelets.UserSession is marked as obsolete.
  • The type Sitelets.Context<'T> now contains a field UserSession, which can be safely used in asynchronous sitelets. Note that unlike the old UserSession, its methods are asynchronous.
  • The new function WebSharper.Web.Remoting.GetContext() can be used in Rpc functions to retrieve a thread-safe user session manager. It must be called from the Rpc function's thread, but the resulting object can be used asynchronously. For example:
1
2
3
4
5
6
7
8
9
[<Rpc>]
let DoSomethingIfLoggedIn() =
    let ctx = Web.Remoting.GetContext()
    async {
        let! loggedIn = ctx.UserSession.GetLoggedInUser()
        match loggedIn with
        | None -> return "Error: not logged in"
        | Some username -> return! DoSomething username
    }
  • This functionality is implemented both in the built-in ASP.NET module and in WebSharper.Owin.

JavaScript interop

  • Previous .ToEcma() methods for converting a .NET type to its EcmaScript binding equivalent has been obsoleted. Renamed to .JS property.
  • Previous .ToDotNet() methods are now a .Self property on WebShaper.JavaScript. types.
  • JavaScript.Function is now a base class for all JavaScript.FuncWith... types (giving strong typing to JavaScript functions).
  • Methods on JavaScript.Function has been renamed to ApplyUnsafe, CallUnsafe, BindUnsafe to avoid overloading with the strongly-typed methods on descendant classes.

WebSharper Interface Generator

  • The generic helper for more than 4 type parameter is now GenericN n - fun typeParamList -> ...
  • Generic % can be used to add the same type parameters to a list of members.
  • Generic * can be used to add the same type parameters to a to a ClassMembers value (created by Instance [...] or Static [...]).
  • These generic helpers all add type parameters in addition to previously defined ones on the members returned by the inner function, instead of overwriting the generics list.
  • Type parameters are automatically renamed on library generation to avoid name clashes.

Other improvements

  • A compile warning is given when a tupled or curried lambda or variable with the same types are coerced to obj. This can help avoiding some mistakes, for example writing

    1
    
    New [ "compare" => fun (a, b) -> a - b ] 

    and passing it to JavaScript code expecting a function that takes two arguments. However, this is translated to a JavaScript function taking a single 2-element array argument. The former is the much more common scenario, so on this warning, change it to

    1
    
    New [ "compare" => FuncWithArgs(fun (a, b) -> a - b) ] 

    to pass the right function. Otherwise, you can use the Function.As static method to wrap the lambda and and get rid of the warning.

  • [<OptionalField>] attribute now can be used on class or record types. This makes all option valued fields of the type represented as present/missing JavaScript properties in the translation.

Fixes

  • #340: Generic methods of a generic type used wrong type parameters for generating the member. This could have affected some of our extensions.
By András Jankó on Wednesday, February 18, 2015 — 0 comments

CloudSharper 0.9.28 released Core team

This release fixes some issues introduced in last release, and improves tooltips and autocomplete.

Fixes

  • #588: Pressing Tab/Shift-Tab with a single cursor works now as in Visual Studio.
  • #589: Pressing . for autocomplete fixed, also works for (.
  • #587: Autocomplete works for .fsx files.
  • #591: Save in File menu and Ctrl+S fixed.

Happy coding!

By Loïc Denuzière on Friday, February 13, 2015 — 5 comments

Upcoming in WebSharper 3.0: serving REST APIs, easy as pie! Core team

WebSharper Sitelets are a wonderful way to build websites quickly and safely. They can automatically manage your URLs in a type-safe way, and generate HTML markup using simple F# combinators. In WebSharper 3.0, we are extending Sitelets with the capability to create REST APIs with unrivaled simplicity.

Requests

Just like you can currently type these lines in F#:

1
2
3
type Action =
	| [<CompiledName "listing">] Listing of pagenum: int
    | [<CompiledName "article">] Article of id: int * slug: string

to tell WebSharper that your site will be served on these URLs:

1
2
/listing/1
/article/135/upcoming-in-websharper-30

You can now also specify all the information necessary to serve a web API on a given HTTP method and with the given JSON body, simply by using a couple attributes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
type Action =
	| [<Method "GET"; CompiledName "article">]
    	GetArticle of id: int
    | [<Method "POST"; CompiledName "article"; Json "data">]
    	PostArticle of data: ArticleData

and ArticleData =
	{
    	author: string
        title: string
        tags: Set<string>
        summary: option<string>
        body: string
    }

The following requests are now accepted:

1
GET /article/135

1
2
3
4
5
6
7
8
9
POST /article

{
  "author": "loic.denuziere",
  "title": "Upcoming in WebSharper 3.0: serving REST APIs, easy as pie!",
  "tags": ["websharper", "fsharp"],
  "summary": "WebSharper 3.0 is coming with an (...)",
  "body": "WebSharper Sitelets are a wonderful way to (...)"
}

The JSON serialization provides all the niceties possible to be friendly with F# types:

  • F# records are represented as JSON objects;
  • list<'T>, 'T[] and Set<'T> are representad as JSON arrays;
  • Map<string, 'T> is represented as a flat JSON object;
  • F# fields of type option<'T> are represented as a JSON field that is present if Some or absent if None;
  • F# unions are represented as JSON objects using the union field names, and a separate named field to indicate the union case (the name of this field is specified in an attribute).

Responses

Of course, a REST API is not just parsing requests, but also writing responses. For this too, WebSharper 3.0 has you covered. A new function Content.JsonContent allows you to serve any F# value as JSON with zero hassle:

1
2
3
4
5
6
7
let mySite = Sitelet.Infer <| function
	| GetArticle id ->
    	Content.JsonContent <| fun ctx ->
        	{ author = "loic.denuziere"; (* ... *) }
    | PostArticle articleData ->
    	Content.JsonContent <| fun ctx ->
        	SaveArticle articleData

Want to see a full example? How about a full CRUD API serving an in-memory database of people information, with all interactions perfectly type-safe, in less than fifty lines?

Look for this new WebSharper 3.0 pre-release on NuGet early next week, or build it right now from source!

By Loïc Denuzière on Wednesday, February 11, 2015 — 0 comments

CloudSharper 0.9.27 released Core team

Here comes another release of CloudSharper! Version 0.9.27 comes with a number of enhancements:

  • It is now possible to write RPC functions in F# interactive. When you call an [<Rpc>]-annotated function from the client side, the arguments are serialized and sent through the WebSocket used by F# Interactive, passed to the function, and the response is sent back the same way.
    Here is an example where two separate widgets share a common server-side state:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    
    let serverSideCounter = ref 0
    
    [<Rpc>]
    let increment() =
        serverSideCounter := !serverSideCounter + 1
    
    [<Rpc>]
    let get() =
        async { return !serverSideCounter }
    
    let x =
        <@ Button [Text "Increment"]
            |>! OnClick (fun _ _ -> increment()) @>
    
    let y =
        <@ Button [Text "Get the current value"]
            |>! OnClick (fun button _ ->
                async {
                    let! value = get()
                    button.Text <- "The value is " + string value
                }
                |> Async.Start) @>
  • The first time experience is largely improved. When entering CloudSharper without a local component running, instead of a message that could easily be mistaken for an error, CloudSharper now displays a friendly screen with install instructions.
  • The project templates are updated to the latest WebSharper (3.0.26-alpha).

We are now planning a major rework of the dashboard screen which will contain a lot of cool new features, including GitHub integration and statistics about your workspaces. We can't wait to have them ready for you to enjoy!

Happy coding!

By András Jankó on Tuesday, February 10, 2015 — 0 comments

WebSharper.3.0.26-alpha released Core team

This release of WebSharper 3.0 alpha ships several major and breaking changes: introducing strongly-typed JavaScript function interoperability, various WebSharper Interface Generator (WIG) API enhancements and revisions, bringing the JQuery binding up to date (to 1.11.2) and more type-safe, and lots of other small fixes and improvements.

If you update WebSharper, be sure to update all your other WebSharper-based packages and rebuild all your projects with the new version because of metadata incompatibility.

Strongly-typed JavaScript function interoperability

Summary of the visible changes

This change standardizes the way functions passed to and from JavaScript libraries (eg. callbacks) are represented. Those used to be inconsistent depending on whether the function was expected to use the this value: a delegate was used if it was, and an F# function with tupled arguments if it wasn't. Now the type of JavaScript callbacks is as follows:

1
fun this (arg1, arg2, ..., argn) -> result

If the function is not expected to use the this value, then the first argument is omitted, and the function is identical to previous versions of WebSharper. Conversely, if this is used and the JavaScript function takes no argument, then the second argument is omitted.

If the JavaScript function is variadic (ie. it takes n fixed arguments and a variable number of extra arguments), then the corresponding F# function takes a tuple of n + 1 arguments, where the last argument is an array of the variable arguments.

In some rare cases (eg. when using arrays of functions), the function needs to be wrapped in one of the types described below in "New function types".

In-depth explanation

The FSharpFunc<'TArg, 'TRes> type (which is used for lambdas by the F# compiler) always take one parameter (which can be a tuple). In WebSharper translation, these become JavaScript functions taking a single fixed-length array (although curried functions only used in local scope are optimized). However, it is often required that we pass functions defined in F# to a JavaScript library (for example event handlers, callbacks, functional-style libraries).

Previous versions of WebSharper used a wrapper function called Runtime.Tupled for this. This created a function that passed along its arguments to the inner function if it was called with 0 or 1 arguments, otherwise passing the arguments object. This meant that Runtime.Tupled-wrapped functions had a double calling convention: with a single array or with multiple arguments.

Although this solution was a performance hit (tuple-argument lambdas got wrapped even if they were never passed to outside JavaScript code), it covered most cases. But if the JavaScript library would sometimes call the function with one argument and sometimes more, Runtime.Tupled would cause errors. Also there was no strongly typed way to handle functions returned by outside JavaScript libraries, or function-typed properties on objects.

This release introduces a one-to-one relation between new F# types describing functions and how they are to be called/treated in JavaScript. WIG is also expanded with support for interop transformations, including automatically converting between function calling conventions. F#-defined lambdas used only in passing to outside JavaScript code are now optimized in the output to be straight functions with multiple arguments, not a wrapped function. This means then a lambda like fun (a, b) -> a + b would be translated to function(tupledArg) { return tupledArg[0] + tupledArg[1]; } but if you have this lambda passed to a JavaScript library expecting a function with two arguments, it will become function(a, b) { return a + b; }.

New function types

In the IntelliFactory.WebSharper.JavaScript namespace you can find several new types corresponding to JavaScript functions. These have constructors for creating them from F# functions, and methods to call them. As described in the WIG section, in most cases these types are not needed, because WIG is creating inlines which convert to and from F# functions. However if you need to pass an array of JavaScript functions, it will use one of these types as automatically mapping an array would be confusing (arrays are mutable, we need to preserve identity).

  • For JavaScript functions with 0 or 1 parameters, that do not use the this value, simply use F# functions ('a -> 'b).
  • FuncWithArgs<'TArgs, 'TResult>: Represents a JavaScript function with more than one argument. The 'TArgs type parameter must be a tuple.
  • FuncWithThis<'TThis, 'TFunc>: Represents a JavaScript function that cares about the this value. 'TFunc can be a straight F# function or other interop type.
  • FuncWithRest<..., 'TRest, 'TResult>: Represents a JavaScript function that takes some fixed arguments, and then rest arguments. The number of fixed arguments can be between 0 and 6.
  • FuncWithArgsRest<'TArgs, 'TRest, 'TResult>: This is for covering the probably rare case of more than 6 fixed arguments. 'TArgs must be a tuple type of the fixed arguments. Its .Call method also takes the fixed arguments as a tuple.
  • Delegate types are no longer supported for creating JavaScript functions using the this argument. Only explicitly proxied delegate types are translated. (WebSharper currently only defines proxy for System.Action which is used by CancellationToken.Register.)

Interface Generator API changes

  • We felt that using |+> [...] and |+> Protocol [...] to add static and instance members accordingly is a bit non-intuitive, and also an easy source of errors, because forgetting Protocol would give no warning. Adding a list of members to a type definition is now recommended using |+> Static [...] and |+> Instance [...]. Previous syntax will give deprecated warning. Also: constructors can be in the Instance list and they will still get handled correctly.
  • Adding members to an interface is still done with |+> [...].
  • There have been functions called Static and Instance operating on a single method definition. These would have no use now and have been removed.
  • You can use the TSelf value as a placeholder in member declarations and will be resolved to the declaring type.
  • The WithMacro helper adds a WebSharper macro to a method/constructor. Currently the macro type itself must be defined in another assembly than the WIG generator assembly.
  • ObjectConstructor creates a constructor where the inline is a simple JavaScript object expression. This functionality was previously exposed only by the Pattern.Config helper.
  • Generic type definitions also use Generic – now instead of Generic /, and produce a single CodeModel.TypeDefinition value. This can be directly inserted into CodeModel.Namespace member lists. When you want to add specify type arguments, use the item syntax MyTypeDef.[T1, T2, ...] as you can with other types. The number of applied type parameters is not checked by the type system currently, but will give a detailed error when compiling with WIG. This includes wrongly parameterizing external types which would previously generate invalid IL.
  • Use Generic + ["T1"; "T2"] - ... to specify the names of the type parameters.
  • Generic – now takes a function with arguments of type CodeModel.TypeParameter. In some cases, explicitly declaring the argument type can be required for type inference. Also, sometimes using p.Type to convert a CodeModel.TypeParameter to a Type.Type is needed.
  • There is a new overload of Generic – which takes an int * (list<CodeModel.TypeParameter> -> #CodeModel.Entity), where the first value is the number of type parameters. This allows creating generic type declarations or members with more than 4 type parameters.
  • You can now set type constraints on parameters using p.Constraints <- [...] inside the lambda passed to Generic -. Previous WithConstraints helper is removed as we want to have all helper functions named With... to be non-destructive.
  • You can add a custom defined inline transformation with the WithInterop helper. This takes a record with an In and an Out field, both string -> string. For example:

    1
    2
    3
    4
    5
    
    let Index = 
        T<int> |> WithInterop { 
            In  = fun s -> s + " - 1"
            Out = fun s -> s + " + 1"
        }

    You can then use this Type.Type value instead of T<int> in your member declarations where you want to handle an index as 1-based in your code, but pass it to and get it from a 0-based value in a JavaScript library. On method parameters and property setters the In function will be used on the parameter or property value in the automatic inline. On method return values and property getters the Out function will be used on the whole inline of the method or property getter.

  • You can use the WithNoInterop helper to (non-destructively) clean any automatic and custom inline transformations from a Type.Type value.
  • To define a custom inline for a method that still makes use of the default or custom inline transformations on parameters and return value, use the WithInteropInline helper. It takes a function typed (string -> string) -> string, use the provided function on a parameter name or index to get its transformed inline. For example, defining an on event setter with function argument detupling:

    1
    2
    
    "onChange" => (T<int> * T<obj> ^-> T<unit>)?callback ^-> T<unit>
    |> WithInteropInline (fun tr -> "$this.on('change', " + tr "callback" + ")"
  • Similar helpers exists for property getters and setters: WithInteropGetterInline and WithInteropSetterInline. For getters, provided function is only usable for transforming "index" in the case of an indexed property, and for setters transforming "value" or "index".
  • You can now use the !? operator on types too, not just parameters. Existing method definitions work without change as before, producing method overloads of different arity. On properties the option type is converted to and from an existing or missing field on a JavaScript object. On method returns, undefined is converted to None, all other values (including null) to Some ....
  • Union types (for example T<int> + T<string>) was used previously for creating method overloads, but defaulted to T<obj> when used on a property or method return type. Now these get automatically transformed to Choice types when the cases can be distinguished in JavaScript using the typeof, Array.isArray and the arr.length functions. In F# this means either at most one array case or possibly multiple tuple cases with all different length, at most one number type (including DateTime and TimeSpan, which are proxied as a Number), string, bool, and at most one other object type. If there are cases which can't be separated, the type will still default to obj.

Other improvements

  • The IntelliFactory.WebSharper.JavaScript.Object type is now generic. Object<obj> is equivalent to previous Object type. Now, if relevant, you can specify the types of all fields, for example Object<string> for a JavaScript string map.
  • You can use the [<OptionalField>] attribute on a class or record field with an option type to represent it with an existing/nonexisting field in the JavaScript translation. (Planned: [<OptionalField>] on a class or record will apply to all fields with an option type.)
  • The [<Name "">] attribute now works on class fields.
  • JQuery binding updated with better typing for AJAX operations.

Fixes

  • WIG couldn't create tuple types with length more than 7.
  • Bug #323 Derived classes defining a field with the same name as a base class don't overlap in JavaScript translation.
  • Bug #330 withCredentials should not be used in synchronous requests. Thanks to ca-ta for the report and pull request.

Known issues

  • Currently the TypeScript definition output can be off from the generated JavaScript as it was not reviewed yet with the latest changes.
  • Source mapping at the current state is not as usable as we would like. Many-to-many mapping is not handled well by either IE11 or Chrome.

By Loïc Denuzière on Thursday, January 29, 2015 — 0 comments

WebSharper 3.0.15-alpha released Core team

Here comes another release of WebSharper 3.0 alpha! This release focuses on small fixes and improvements, as well as a couple new proxies for useful classes such as System.Random and System.Guid.

Changes

Improvements:

  • WIG: The (?) operator for naming a method argument now properly overrides the JavaScript field access operator. This means that you can now open IntelliFactory.WebSharper.JavaScript in a WIG project, provided that you do it before open IntelliFactory.WebSharper.InterfaceGenerator.
  • Added xml documentation for attributes and sitelets.
  • Added Sitelets.UserSession.LoginPersistent to create login sessions that persist beyond the current browser session.
  • Added client-side Remoting.UseHttps() which forces all RPC calls to use HTTPS.

New proxies:

The following classes and methods can now be used from the client side.

  • System.Random
  • System.Guid
  • System.String.TrimStart/End

Fixes:

  • Fix #315: Sitelet.Protect login redirect now uses RedirectTemporary instead of Redirect.
  • Fix #322: Compile-time error when a project's Name and AssemblyName are different.
  • Fix #323: Fields for primary constructor arguments shadow inherited ones
  • Fix #325: Add Console.Log overload with a single argument

Future plans

We have two final major changes to push for WebSharper 3.0, which affect the typing conventions for tupled and multiple argument functions (see the work in progress) and the interface generator API. Our current plan is to have another alpha release for this (and other, smaller changes), and ideally to release the first stable version of WebSharper 3.0 before the end of February.

Happy coding!