HomeBlog

Aug
15
2010
23:18

UglifyJS — a JS parser/compressor/beautifier

... for NodeJS.

With minimal changes it should work on any JavaScript engine, but currently NodeJS is the main development platform.

It implements a JavaScript parser which produces a clean abstract syntax tree from JS code (this part is ported from parse-js, a great JS parser for Common Lisp).  Then it contains a few functions that manipulate the AST to compress variable names to single characters, and provide various other compression techniques such as:

  • join consecutive var declarations:

    var a = 10; var b = 20;  ==>  var a = 10, b = 20;
  • remove block brackets {} where possible

  • transform foo["bar"] into foo.bar

  • various optimizations for IF statements:

    • remove "else" where possible (when the last statement in an IF block is "return", "throw", "break" or "continue")

    • transform simple IF-s like:

      if (foo) bar(); else baz();  ==>  foo?bar():baz();
      if (!foo) bar(); else baz();  ==>  foo?baz():bar();
      if (foo) bar();  ==>  foo&&bar();
      if (!foo) bar();  ==>  foo||bar();

and some others.

It compresses better than the YUI compressor, and safer than Google Closure.  And it's a lot faster than any of these.

Get the code here: http://github.com/mishoo/UglifyJS and spread the word! :-)

          Jul
          10
          2010
          12:15

          Writing a Redis client library for Node.js

          I'm playing with Node.js lately.  Node is an asynchronous environment that allow you to use JavaScript on the server.  The asynchronous nature makes it a bit different from other programming environments, and I'll describe in this article how I'm using some obvious features of the language (closures and exceptions) to accomplish something not-quite-trivial.  In short, I've written a Redis client library and a WebSocket library (and yes, I know these things exist already, but I suffer from the NIH syndrome).

          JavaScript has exceptions, and JavaScript has closures—combining them you can get “restarts”.  It's not the same as Lisp's condition/restarts system, in that once it throws an exception a function can not return anymore.

          In order to make use of this technique you have to write your code in “continuation-passing style” and avoid iterative loops.  While this might seem too complicated, it's easier and more natural than it sounds (and it's almost a requirement in environments such as NodeJS).

          [ read more... ]

          Jun
          19
          2010
          15:58

          No fixed width fonts in GMail?

          I rarely use GMail, so I didn't care to look into this so far.  I don't care much today either, but I sent a plain text message to someone, and I carefully formatted it in Emacs, and I know that this someone is using GMail and that by default GMail displays text messages in a variable-width font, so I thought — let's check to see if there is an easy way to display text messages the way they should be, that is, in a mono spaced font.

          Looks like there was a way, but not anymore.  Now you have to resort to all sorts of hacks, like using GreaseMonkey and writing a custom CSS for GMail.  How to explain this to someone I write to, or how could I expect anyone I write to to be able to master Firefox so well that they are able to customize GMail by writing CSS?

          I also found a Firefox extension (which is too much as well to ask from recipients, but just wanted to look into it).  But the last release was sometime in 2008 and it no longer works with the current Firefox.

          Why is there so much silence about it, and why is there no obvious reason why they would remove such a simple feature?  Any other email client on the planet knows that plain text should be displayed in a fixed font.

          I wonder if the real reason has to do with the fact that the default font makes all emails look like Adsense :-(

          May
          30
          2010
          20:54

          Yet Another JavaScript Template Engine

          I had to do this. :-)

          I mean, I don't like any existing template systems.

          I don't like mine either.  But still I think it's better than others.  I was looking at Tenjin and they have something like this:

          <?js for (var i = 0; i < list.length; ++i) { ?>
          <?js     var el = list[i] ?>
               <li>#{el}</li>
          <?js } ?>

          Functional, maybe, but downright ugly.  In YAJET, we can write it like this:

          $(FOREACH (el => list)  <li>$el</li>  $)

          which I think is a lot better.  YAJET compiles the templates into JavaScript code, so for your template you get a function that runs blazing fast.  It tries hard to do this The Right Way, so you don't have weird variable name clashes, or side effects.

          Give it a try.  There's a jQuery plugin too, for those who can't live without jQuery. :-)

          May
          23
          2010
          19:05

          The Bazon Fractal

          Here is a JavaScript implementation (using the <canvas> element) of an idea that my father discovered like 20 years ago. To the best of our knowledge, the idea wasn't known at the time. We recently found a similar image in Knuth's “The Art of Programming”, vol. 4, which according to Wikipedia was not published until 2005. Hence, in lack of a better name, I'm going to call this “the Bazon fractal”.

          The idea is simple. To draw the pixel (x, y) of the image, you compute the value of some function and select a color based on that value. Certain functions lead to impressive results. But you need to be either too lucky, or a truly passionated mathematician, to discover a function that returns something meaningful.

          [ read more... ]

          Dec
          26
          2009
          11:41

          Howto: multi-threaded TCP server in Common Lisp

          I'm writing this howto because I spent some considerable time on implementing a TCP server in CL; my lack of Lisp experience contributed to this, but also no quick guides or howtos seem to exist in this area.  And an undocumented argument to a function in usocket has a default value which defeats the documented behavior, making me spend lots of time to figure out what's broken (:ready-only in usocket:wait-for-input).  Poor documentation and lack of resources is a pretty bad situation for Common Lisp. :-(

          The task is to write a simple TCP server class using a worker thread pool for handling the requests.  There is one listener thread that clients connect to.  The listener would read data from the socket, then when a full command is available for a certain client, it will send it to a worker thread to be handled.  (The idea was that there could be multiple listeners as well, but at this time it's buggy.)

          [ read more... ]

          Dec
          19
          2009
          18:32

          The greatest programmer in the universe

          Want to know who that is?  It's me. ;-)

          I submitted my Ymacs project to Ohloh (Ymacs project page at Ohloh).  They have a nice feature that gives some statistics, based on the source code (they can understand some source control repositories, including Mercurial, which is what I use).  The Ymacs statistics say the following (the whole source taken into consideration):

          • estimated effort: 4 person-years
          • project cost: $210,926 (for a $55000/year salary)

            Counting only the JavaScript files, which is the main programming language, we have:

            • estimated effort: 1 person-years
            • project cost: $61,739 (same $55000/year salary)

            The fact is: I did this myself in a bit more than 2 months (work on the website and infrastructure included).

            It's true that Ymacs includes a build of DynarchLIB in it's source repository, and DynarchLIB started in 2005 (I didn't work on it full-time, though, far from it).  However, Ohloh counts DynarchLIB as a single line of code, because the code is minified, so it probably doesn't add much in the 1 person-years estimation.

            Once I put up a public code repository for DynarchLIB, it will be interesting to see how much Ohloh underestimates me. :-)

                Nov
                10
                2009
                23:00

                Ymacs — AJAX source code editor

                I just released a new project that I've been working on for about a month: Ymacs is an AJAX text editor, suitable for editing source code (currently there is support for JavaScript and XML, but more modes could be easily implemented).

                Ymacs is a DynarchLIB widget, which makes it easily embeddable into any DynarchLIB application.  This doesn't sound impressive, isn't it, but here's the real good news: I've decided to open source DynarchLIB and release it under a BSD-style license.  Some folks might believe this project is already dead, but this isn't so; it is true that there was no new release in almost two years, but the thing kept being improved and there are people using it in successful commercial applications.

                Well..  This should happen any minute, but I'm running out of time, as usual.  So it could take a few more days to push a new DL release.  In the mean time, go check Ymacs, it's pretty cool.  It has Emacs key bindings too. ;-)

                Oct
                20
                2009
                15:27

                JavaScript: Unicode letters (in RegExps?)

                As you probably know already, Firefox's browsers' regexp engines don't "know" Unicode.  The \w specifier seems to be equivalent to [a-zA-Z0-9_], which is far from sufficient to match word characters.  After some googling I found XRegExp, a pretty cool library that extends the basic JS RegExp object.  It adds some useful magic, and—surprise—unicode support is available as a plugin.

                Nice going, but since I need this in a very time intensive operation, it was rather slow.  (As you will see below, it's quite possible that XRegExp isn't to blame for the slowness).

                So I thought I'd copy the bits that I need from the source code, and use them with standard JS regexps, rather than XRegExp.  If you look at the source code, it has a huge line for a "L" property (it's lowercase in the code) in a hash which defines the Unicode ranges for characters that are letters.  Later in the code, with a for loop it constructs the actual regexp.

                [ read more... ]

                Sep
                12
                2009
                16:09

                Hashes and raw strings in Common Lisp

                So I'm learning Common Lisp.  Why would I do that?  Well, for one thing, I don't have much work to do lately, which is pretty bad because it directly translates in a poor financial situation (wanna hire me?).  But on the other hand, because Lisp is cool and I've long wanted to learn it.  Friends of mine keep asking "What can you do with Lisp?  Can you find a job?  Can you make any money with it?" — I haven't got an answer to these questions yet, but one thing is certain: I can use it myself and finally replace Perl for my server-side needs.

                I'm writing in this article how I solved two of the things that bothered me.  It's probably not useful for experienced Lisp hackers. ;-)

                (read 'more)

                See also