HomeBlogCategory: “node.js”

Showing only posts in category “node.js”.

Show all


What's missing from NodeJS

Every now and then I keep thinking of this. What got me started to write it all down was this thread on the mailing list. Some guy who enjoys pain takes the trouble to write an E4X extension to Node (it really should be an extension to V8, but let alone that). Then another guy replies:

“We aren't interested in language features, we're building a platform and not concerning ourselves with the language and vm allows us to build and iterate on this platform significantly faster than if we were building a language.”  (Mikeal Rogers)

“We aren't interested in language features”! I'm not personally a fan of E4X and don't care much about having that in the language, but I do think that JavaScript needs to evolve. When I say needs I mean right now, it's not good enough.

[ read more... ]


On Automatic Semicolon Insertion

(this started as a reply to this thread in NodeJS, but it got rather long so I'm posting it here)

Before doing JavaScript, I was doing C/C++. There semicolons were required, and you got an error from the compiler when they were missing. I rarely got such errors though because when a semicolon was missing, Emacs would indent badly the following line; bad indentation was always a sign of syntax errors.

So when I moved to JavaScript, semicolons at end of statements made very much sense. The Emacs JS options at that time weren't nearly as good as the C/C++ mode, so sometimes I forgot the semicolon.  Although usually the program ran fine, I still went through all sorts of scary bugs because of the automatic semicolon insertion. Oh how I missed that compiler error!

So I got quite religious about using semicolons (also because I was using a simple regexp-based scanner to minify JS, and that was easily screwed by missing semicolons). Nowadays I use Emacs with js2-mode, which contains a full JS parser, and is able to warn about various things during editing, such as missing semicolons.

As a matter of taste, I find code that uses semicolons at the beginning of lines a bit silly:

;(x || y).doSomething()
;[a, b, c].forEach(doSomething)
for (var i = 0; i < 10; i ++) {

I'm doing a lot of Lisp hacking lately, and the first two lines look like comments to me (intentionally turned off syntax highlighting above).

Using the comma at BOL looks a bit better, because it makes it possible to comment out the line without forgetting a trailing comma:

var magicWords = [ "abracadabra"
                 , "gesundheit"
                 //, "ventrilo"

but still (continuing paste from npm's coding style):

  , spells = { "fireball" : function () { setOnFire() }
             , "water" : function () { putOut() }

you can't comment out the spells = line in the same way, because it spans multiple lines. So this argument fades away and let's just say it looks silly.

So as far as my advice goes:

  1. Use an editor with good JS support. If it's just decent, it doesn't qualify. GEdit is decent, but not good enough. Emacs is supremely great.

  2. Configure your editor to warn you about “poor practice”. Again, in Emacs it's possible to do that. For example, my setup warns me if I assign to a variable that's not defined (creating globals is almost always a source of errors), if I forget semicolons, or if I assign in a conditional (where most likely the case is that you want "==" instead of "="). Details on my setup here.

  3. Do insert semicolons and save yourself from the pain of debugging "automatic semicolon insertion".

  4. Be happy. ;-)


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! :-)


          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... ]

          See also