No announcement yet.

Javascript interop

  • Filter
  • Time
  • Show
Clear All
new posts

    Javascript interop

    ​​​After having read through the docs, I am a bit lost on what my options are for Javascript interop. In particular, I need to:
    • import modules (default, members, etc)
    • dynamically get/set and invoke methods
    • create pojos
    • emitting raw javascript when needed
    From the docs, I have gathered the following:
    • import modules
      • The docs only ever cover interacting with a javascript file under the assumption that you include it globally. This will simply not work when working with numerous NPM pacakges. For instance, let's pretend for a second that there isn't a Retyped definition for left-pad. How could I use the javascript interop features of Bridge.NET to accomplish the example from the left-pad Github page?
        		const leftPad = require('left-pad')
        		leftPad('foo', 5)
        		// => "  foo"
        		leftPad('foobar', 6)
        		// => "foobar"
        		leftPad(1, 2, '0')
        		// => "01"
        		leftPad(17, 5, 0)
        		// => "00017"
    • dynamically get/set and invoke methods
      • The docs don't mention this very much, but I am guessing that I can simply use the C# dynamic type.
      • Playing around with this in, it seems to work pretty well.
    • create pojos
      • From what I can tell, I can use C# anonymous typed objects via new { ... }, but I must set
        "rules": { "anonymousType": "Plain" },
        in my bridge.json file.
      • This seems a bit fragile to me, if someone decided to change the bridge.json file, things would break down. Is there a better way to consistently create a simple pojo inline without declaring any classes/structs/whatever?
    • emitting raw javascript
      • The docs describe this pretty well, and it seems that I can simply use the Script or Template attributes from here (
      • However, I did run into some weird, undocumented syntax using //@ as special comments that emit javascript directly as well. How many other ways to emit javascript exist in Bridge.NET?

    For a frame of reference, I am coming from Fable ( which compiles F# to Javascript. They support all of the above interop scenarios as described here ( One big difference is that they compile import statements into the appropriate module import or require statements in each file, rather than assuming global context for everything. They also have built-in methods for creating pojos and attributes for emitting javascript, etc.

    I would say this is my last hurdle in order to jump in and start using for my project, as everything else has come together rather nicely.

    Hello again, @SirUppyPancakes!

    I will try to get into some topics you seemed not fully enjoy and provide some feedback. Bridge has lots of possibility so this won't be the absolute best way to solve or handle that aspect, though.

    import modules
    Well, Bridge does not really handle that part yet. And the index.html generation you mentioned in the feature request thread you started came in just to help out with that. Its intended usage is as a shortcut to be able to easily have the include lines from what is output from a project. As Bridge's client side code usage scenarios differs from the diversity of different project types, there's just no easy way to guess that. An option could be created and types of output determined; not impossible yet just not implemented in the code.

    From your test code, if you had a simple framework, you could just wrap it in classes, marked external, sometimes with [Template()] attributes when the C# to JS default translation does not work (or to improve C# syntax), pretty much as the Bridge frameworks are written. Maybe the WebGL one would do a simple project to understand what I'm talking about. If you have just one or two calls to make, you can but wrap the prototype class/members in the main project instead of making a dedicated library.

    So, in short, the modules importing is currently not supported (automatically guessing includes) in Bridge and are worked out by crafting code to do so, depending on the situation.

    Here, it 'requires' Bridge's main js and the other ones are included as they are used: Retyped demos: NodeJS+ExpressJS Demo. You'll probably find other interesting examples therein!

    You can set up bridge rules at definition time with the Rules attribute. This way setting at bridge.json would be overridden by what is specified in the exact location (a class, or a class member, depending on where the rule apply). Rules can also be at AssemblyInfo level as an alternative to cover the whole application instead of bridge.json.

    emitting raw javascript
    The //@ comments were made to allow adding arbitrary JavaScript code regardless of the context. A convenience that also allowed some specific cases where the other ways didn't allow code to be output where it was meant to. It can also be a block comment /*@ */, to allow for a nicer approach to keep a multi-line javascript code within the c# source file.

    Well, I hope this helps!


      Thanks for indulging all of my questions again, and so quickly at that!

      I think this cleared things up a good deal. I did stumble across the samples you referenced and have ended up using syntax with node.require.Self.

      While I have you here, any idea if either of the following two ways of using node.require.Self are preferable over the other?

      I saw this style in the Electron demo app:

      This seems to work just as well, however, and is shorter and more obvious for my use case:

      Thanks again for all of the help! I think I will start running with Bridge.NET and see where it takes me 😁


        Hello @SirUppyPancakes,

        I believe the difference in the two approaches are just in the scope where Electron is defined, so it really would depend on your project. So that's both a personal opinion on what's best and also a design choice for the project.

        I don't think there's one better than the other. It just depends on how you are thinking and willing your project to work.

        Glad you're having fun with Bridge, hope it helps you build awesome projects!



          Just for anyone else who comes across this in the future for reference, you don't need to use node.require.Self most of the time (especially when using Retyped), since it will generate the module imports automatically, however you do need to set the loader property ( in bridge.json in order to use the right module loader that you want (in my case I wanted CommonJS for NodeJS + Electron).

          It would only be needed to use node.require.Self when using a module fully dynamically, without any bindings (you'll also need to use the dynamic C# type/keyword to make it work).