Glue-free JSCall#

One of my goals during this rewriting of VandalSniper as a more general-purpose browser has been to reduce or eliminate the dependency on platform-specific glue libraries. JSCall# uses a C/C++ library to interact with the DOM, and this is just one more hurdle to be jumped over on the road to portability. Who wants to set up a build environment against Mozilla on Windows? Not me.

So I started fiddling around with Gecko# some, and discovered that it’s possible — and simple, really — to eliminate the glue library. To place a call to JavaScript from the CLI, it’s as simple as calling WebControl.LoadUrl() passing a string like “javascript:someFunction()”. This does change the return from WebControl.Location, but this can be worked around easily enough.

To make calls back, I copied an idea from JSCall#. The call is placed by constructing a string containing the function name and argument list, and the document title is set to this string, then immediately set back to what it was. This is picked up by the WebControl.TitleChange event handler, where the pieces are pulled apart into an array, the function name mapped to a delegate, and the delegate invoked with the arguments.

One of the cool things about the “javascript:” method of calling functions is that it seems to work just as well for whole function libraries, even those with newlines in them. The only caveat I’ve discovered is that if there is any //-style comment in the JavaScript, everything after it will be ignored. It seems that while embedded newlines are okay, they aren’t really treated as newlines. WikiBench does nothing to correct for this; it’s assumed that addins know about this. While I’d love to have it strip such comments out, that would require some parsing work (“//” can be embedded in a string safely, for example).

It’s one big kludge, but it works remarkably well.

10 Replies to “Glue-free JSCall#”

  1. Hi the idea is really nice and comments are quite easy to strip (along with the excessive new lines and breaks) take a look here: There is one more issue here, however. The ‘%’ sign which in JS is used as a modulo operator or when converting from ASCII codes. Firefox will try to escape everything that follows breaking the script. The only solution is to change the ‘%’ into ‘%25’ before injecting the script. Jsmin.cs can be altered to do it as well. Cheers.

    PS Hutch: Your JSCall has got that issue, please test your code!

  2. Basically the way I solved the comment issue is I don’t use single-line comments in any of my scripts. 🙂 Not exactly clean, but I didn’t feel like writing a context-free JavaScript parser just to strip them.

    As for the modulo operator, good catch. I didn’t account for that since I’m not really using that operator at all.

  3. Hi
    (I’ve tried to post before but nothing happened, so I try again now).

    I’ve put in place the mechanism as you described and it works pretty well.
    The only thing I cannot do is to return a value back to javascript.
    In other words, in javascript I change the document.title to a formatted string with command name and args. In c# I listen to the TitleChange event and I parse the new title. Up to here everything is ok.
    Now, I want my TitleChange event handler to return a value back to the javascript but if I do myMoz.LoadUrl(“javascript:SomeFunction(Some Args)”) this is not executed. If I do the same somewhere else, like for example when pressing a button in my Gtk# window, the same javascript code is executed normally.
    It seems that, after setting document.title in js, it waits until the c# event handler function is completed, but while waiting, the webcontrol is not able to execute any other javasrcipt call.
    Can you help me?
    Thanks in advance!!!

  4. Viggio: It doesn’t work because JavaScript is not truly multi-threaded. At the point that the TitleChanged handler is executing, the JavaScript interpreter is suspended, waiting for it to return. If you try to execute a function then, there is no way for the interpreter to actually run it. It would be nice if Mozilla would queue the call, but instead it just ignores it.

    You will have to deal with threads if you want to accomplish this. A better option might be to ensure that the script has all of the data it needs to accomplish its work. Interaction between C# and JavaScript should be kept minimal, and back-and-forth exchanges should be avoided for the very issue you have encountered.

  5. Hi Chris,
    although I understand that this is not the best place where to post this question (we’re talking about JSCall here), I cannot find any other place where to find support.
    This is my problem:
    I’m running Ubunto 8.04. I’ve embed mozilla through Gecko# in my mono application. Everithing works, I can also see pages with Flash contents.
    Unfortunatelly I cannot see pdf files, neither direclty opening the pdf itself, nor embedding them into html pages. In firefox 3 I can see them in both ways, with also pdf 3D support. What do I miss?
    Thanks for you help!

  6. Hi Chris, I’s me again… please forget my last question. I could solve the problem by using the .tag.gz installer from Adobe rather than .deb package from the same site.

  7. Thank you very much.
    I’ve stucked into problem of calling current loaded webpage (document) function (or any javascript code in current context), and wasn’t able to find solution for calling anything through Gecko api (everything is sooo decorated). Althrough I’m doing this at other conditions (win32 c# application, geckofx layer between .net and gecko), it seems .LoadUrl or .Navigate with (“javascript:”) is also the only simple solution available (it seems that can be also possible over nsiScriptContext etc. interfaces, but that is a very overcomplicated, and even more from .net).
    so thank you very much for this simple and nice solution 🙂
    p.s. I like ff very much, but still don’t understand why that simple task is SO complicated 🙁

Comments are closed.