My JavaScript book is out! Don't miss the opportunity to upgrade your beginner or average dev skills.

Tuesday, May 20, 2014

134 bytes for an optimized and very basic jQuery like function

TL;DR this fits in a tweet :-)

What's New Here

The most tiny, common and probably used utility for quick prototyping is usually even smaller:
function $(S,P){return [].slice.call((P||document).querySelectorAll(S))}
but it's a performance killer for all cases where we use #selectors or even body since the engine inevitably needs to check all nodes in the DOM.

The Handy :first Pseudo Selector

Hard to believe W3C preferred two different but similar methods instead of simply adding a pseudo :first selector which is not standard and on top of it, it does not work as :first-child or any other selector ... the purpose would be to select only the first occurrence and stop the DOM parsing in an efficient way; instead we need to use querySelector, which is different from querySelectorAll.

A Consistent Result

Not only two different methods to use, we cannot operate in a similar way with those results anyway since one is collection like, where the length would be the indicator for empty results, while the singular version would be eventually null.

Well, Scratch That!

With desktop and mobile browsers released between 2008 and today we can do already many things using native APIs and here we have a probably not always perfect qSA that might fail using some crazy selector I personally try to avoid anyway, plus many Array extras that today are not extras anymore thanks to any sort of polyfill.
Good news is, we might want to polyfill only for jurassic browsers querySelector/All too ... so here what we can do:
// set all click actions per each link
$('a')
  .forEach(function (link) {
    link.addEventListener('click', this);
  },
  function click(e) {
    // prevent default
    e.preventDefault();
    // and show the link
    alert(e.currentTarget.href);
  }
);

// only first occurrence
$('.logout:first').forEach( ... action ... );

Going Wild Extending

The temptation to extend Array.prototype in order to simplify listeners handling is huge ... but while I am not telling you some library did it already, I'd like to show some trick to be less obtrusive and still super productive:
// simple utility to add an event listener
$.on = function (CSS, parentNode, type, handler, capture) {
  // in case parentNode is missing
  if (typeof type !== 'string') {
    capture = handler;
    handler = type;
    type = parentNode;
    parentNode = null;
  }
  return $(CSS, parentNode).map(function (el) {
    el.addEventListener(type, handler, capture);
    return el;
  });
};

// example
$.on('a', 'click', function (e) {
  // prevent default
  e.preventDefault();
  // and show the link
  alert(e.currentTarget.href);
});

That's Pretty Much It

We have a tiny, yet performant utility, and many ways to make it better for what we need on a wide range of already supported browsers.

Friday, May 16, 2014

serving static files twice as fast in node.js

Having asynchronous I/O does not bring automatically "best performance ever" but it helps already.
However, regardless its amazing performance, node.js is also famous for not being a performant competitor when it comes to serving static files ... is there anything we can do?

Avoiding Multiple Reads

Every time we use fs.readFile we schedule a reading operation. This is non blocking and async, but what happens if two users ask for the same file in a fraction of time between the first read, and the second?
// simulating disk I/O
disk.read.push("file.txt");
  // .. while reading

disk.read.push("file.txt");

<< disk.read.shift();

  // .. while reading
<< disk.read.shift();
Wouldn't be better to have this kind of flow instead?
// simulating disk I/O
disk.read["file.txt"].readIfNotAlready();
  // .. while reading

disk.read["file.txt"].readIfNotAlready();

<< disk.read.shift();
We basically satisfied two read request to the same file at once.

Handled fs.readFile

During the refactoring of a personal project of mine, I've benchmarked the current piece of code:
//!@author Andrea Giammarchi
// @module file-read.js
// Concurrent I/O Handling
var
  // still needed, of course
  fs = require('fs'),
  // single shared module cache
  cache = Object.create(null)
;

// same fs.readFile API
this.readFile = function read(name, then) {
  // already requested, let I/O complete
  if (name in cache) {
    // and notify this callback after anyway
    cache[name].push(then);
  } else {
    // first time somebody asked for this
    // create the collection of callbacks
    cache[name] = [then];
    // perform the I/O operation 
    fs.readFile(name, function readFile(err, data) {
      var
        // grab all callbacks waiting for a result
        list = cache[name],
        // loop over such list
        i = 0,
        length = list.length
      ;
      // after erasing it
      delete cache[name];
      while (i < length) {
        // ditch a boring/slow try/catch
        // and notify all callbacks ^_^
        list[i++](err, data);
      }
    });
  }
};
The code used to benchmark is basically this one:
// bench.js
for (var
  // require another file or 'fs' by default
  fs = require(process.argv[2] || 'fs'),
  i = 0,
  // start time
  t = Date.now();
  // 25000 simultaneous requests
  i < 25000; i++
) {
  fs.readFile(__filename, function () {
    // end time if all requests have been satisfied
    // will be async anyway ^_^
    if (!--i) console.log(Date.now() - t);
  });
}
Here results on my MacBook Pro (lower is better):
  1. node bench.js fs: 505ms
  2. node bench.js ./read-file.js: 19ms

About 25X Faster On Concurrent Requestes!

Which I believe is a good achievement when it comes to static files serving since these files usually don't change often so there's actually no need at all to require them more than once per group of users ...
The best part of it? That an array creation compared to I/O operations means almost nothing for V8 so that even if the file is required only once per time and no concurrent connections are in place, the overall performance will be the same, at least in my Mac, and around 9ms per request.
enjoy

Wednesday, May 07, 2014

Touch Events for IE Mobile

Update Windows Phone 8.1 Update 1 seems to have implemented Touch Events natively.
This polyfill will not affect such version and will still work with IE11 for original WP 8.1 and IE10 for WP8.
There is a weird trend in the US, most websites, frameworks, libraries, etc etc do not consider IE Mobile, even if version 10 and 11 might offers way better experience than old Android 2.x phones, still a consistent slice of the Mobile market.

The Fail Behind PointerEvents

Regardless the good documentation, Microsoft did a mistake about events: it didn't consider simplicity and compatibility over adoption and more over, it didn't implement what was working already for the rest of the mobile world, and still from standards: Touch Events

The PointerEvents Utopia and Failure

There is a very simple reason Touch Events are the preferred and most of the time only choice for mobile web development: patterns between Mouse and Fingers are completely different!
As easy as it sounds, as human being and developer you cannot consider a moving action a generic one ... the mouse moves all the time, except when it scrolls through different mechanisms, while the finger moves only when it's touching the screen with an intentional initial target!
In few words, putting all events inside a single "stream" might sound a good move at first sight, but it's totally messed up the moment you try to use such API to define behaviors for Desktop and Mobile.

Augmented Complexity

Instead of simplifying user intent, touching the screen, and developers / application behavior, we need to maniacally filter every single event and behave differently if it's a Mouse one, a Touch one, a Pen one, or whatever touched that screen or is able to simulate even Multi touches with multiple devices ... in few words instead of two different kind of listeners, the Mouse one and the Touch one, we now need a split logic inside a single listener that at any time could confuse both user and application about the intent.
I honestly don't want or expect users to use both mouse and touches at the same time, so why should I be the one responsible to understand what's going on in my page, instead of the native Hardware/Metal close API which aim should be to simplify the higher level development as HTML and JS is?

Where Touch Events Win

Is very simple, if we set a touchstart event to a receiving DOM node, it does not matter if we then set the touchmove and touchend event in the same DOM node since it will keep triggering as we expect even if the little, medium, or fat finger, went out the initial related node ... we are basically simplifying a well known and annoying Mouse pattern where to drag things, after mousedown, we need to add events to the document because the user might be faster than the DOM moving the mouse and we don't want to deal with bloody never ended events over a drag operation ... right ? Well, try to set pointerdown, pointermove, and pointerup to a generic node and then try to drag it around ... I tell you already you will fail unless you don't change the currentTarget per each event using the document for move and up.

Don't Polyfill PointerEvents To Already Slow Browsers!

There are at least two projects which aim is to standardize PointerEvents for Touch Events compatible browsers ... well, the quick advice here is: dont' do that and the reason is simple: PointerEvents are some sort of over engineered Touch Events that will slow down consistently every cheap Android 2 phone which adoption is way larger than any Windows Phone and which performance are way more compromised by these kind of pointless libraries/polyfills when it comes to what the user meant to do: a bloody swipe or scroll and nothing else.

We don't need to know how much the Pen pressed the screen in that specific point and with which angle, we need to know that granny and mum swiped an article, end of the story for 99% of the cases!

Touch Events for IE Mobile

Taking the opposite direction of already mentioned libraries that I won't link for sanity of the mobile web sake, I've created something that slows down a little bit already modern, fast, good, and snappy Windows Phones 8 and 8.1 devices as I have and use on daily basis, through a repository which aim is to bring the easiness of Touch Events to any Windows Phone without you, developer, changing anything in your code base ... if not just adding ie-touch.js before any Touch Based logic you put in place.

Test Included

Check the source code of the basic test and try to replicate the same behavior with your PointerEvents logic and in a cross Mobile browser way ... I dare you!
After you failed trying to do so, check also my old Tesla multi-touch demo and see how it feels having Touch Events in windows Phones too ... have fun!

Sunday, May 04, 2014

Fixing Java Nashorn __proto__

update these guys react quickly, bug tracking here promptly opened by Jim Laskey: thank you!
all right, you might think __proto__ is my obsession but for f*$#k sake not a single engine got it right so far ... and it's perfectly spec'd in ES6 too so I don't know what is with nashorn here ...
// how to fix nashorn
Object.defineProperty(
  Object.prototype,
  '__proto__',
  {
    configurable: true,
    get: function () {
      return Object.getPrototypeOf(this);
    },
    set: function (proto) {
      Object.setPrototypeOf(this, proto);
    }
  }
);

Are You Asking Why?

Here the answer: nashorn is broken, since it does not expose __proto__ quirks anywhere.
'__proto__' in {} is false
Object.getOwnPropertyNames(Object.prototype).indexOf('__proto__') is a -1 negative
Object.getOwnPropertyDescriptor(Object.prototype, '__proto__') is null
Basically even most common basic features detections for '__proto__' are screwed, so that not a single library can trust its own code ... how cool is that ...

Broken null Objects Too

The worst of the worst comes with null objects, where the infamous property makes dictionaries pointless, not secure, and unreliable ... I start thinking the web world was not even ready for dictionaries, it's taking forever to have a reliable one
var o = Object.create(null);
// it's a null object
// nothing should affect it
o.__proto__ = [];

// but nashorn is brilliant
// as old Android 2.1 phones here
o instanceof Array; // true
Congratulation, you never understood what was the purpose of __proto__

Quick Specs Recap

So, since it's apparently the first rocket science problem ever, here a quick summary of how stupidly simple is the __proto__ spec:
  1. if it's a literal expression, not wrapped in quotes, it defines inheritance at runtime: {__proto__:[]} which is an instanceof Array VS {"__proto__":[]} which is just valid JSON and won't even affect inheritance
  2. if accessed through the Object.prototype, where whatever object that inherits from null should NOT be involved, and where __proto__ has not been defined as own property, it behaves as described in the first snippet I've created to fix nashorn
  3. everything else is an epic fail ... seriously, no difference between o.__proto__ or o["__proto__"] and similar madness, if it inherits from Object.prototype and the configurable behavior hasn't been deleted it passes through that get/set logic ... that's really it!
So please fix this madness once for all ... it's about reading specs and implementing them properly, even if Appendix B of whatever status ES6 is ... or GTFO!
</rant>

Saturday, May 03, 2014

micro-env: a tweet sized enriched environment

Probably the most minimalistic KISS approach to JavaScript environment pollution, micro-env is a funny "do more, with less" experiment entirely based on well known and commonly used APIs where each of them will fit in a tweet or better 140 plain chars once minified ... and not even gzipped!

A Micro Sized Rapid Prototype Development

Everything grouped in main topics per each folder is either a:
  • Basic Polyfill, where some caveat a part, the expected/needed behavior has been implemented
  • Partial Shim, where most common cases, performance, and YAGNI approach won over size
  • Feature, where handy, desired, and not that obtrusive ideas get into the env
On top of this, compatibility with every modern and very old browser has been the key so that migrating eventually to more features rich, complete, less obtrusive and more standard libraries such eddy.js will be painless.
Does it work in your browser or env? Feel free to test ;-)

About Objects

The most basic version includes utilities for any object:
// after including micro-env base.js
var obj = {
  set: function (key, value) {
    this.emit(
      'propertychange',
      key,
      this[key],
      this[key] = value
    );
  }
};

obj.on(
  'propertychange',
  function (key, oldValue, nevalue) {
    // do something more useful
    console.log(arguments);
  }
);

// test it
obj.set('key', 123); // key, undefined, 123
obj.set('key', 456); // key,       123, 456
Handlers creation is performed lazily so no actual RAM, CPU or GC extra work is ever involved until needed. Moreover, being the logic that simple to fit in 140 chars, the direct property will help avoiding memory leaks confining handlers within a single object.

About DOM

The DOM version enriches in a similar way only HTML elements, based to addEventListener and others W3C standard behaviors:
window.on('load', function load() {
  this.off('load', load);
  document.emit('loaded');
});
on, off, and emit do exactly what anyone would expect them to do via DOM nodes ;-)

About OOP Features

The Function is normalized with a partial shim for bind plus it's enriched with two very simple/basic utilities:
// Function#bind
window.on('load', app.init.bind(app));


// Function#inherit
// as utility
function Rectangle() {}
function Square() {}
Square.inherit(Rectangle);

// as inline utility
var Square = function(){}.inherit(Rectangle);


// Function#setPrototype
// as utility
function Person(name) {
  this.name = name;
}
Person.setPrototype({
  age: 0,
  growUp: function () {
    this.age++;
  }
});

// as inline declaration
var Person = function(name) {
  this.name = name;
}.setPrototype({
  age: 0,
  growUp: function () {
    this.age++;
  }
});

About Array

not only indexOf, commonly used forEach, some, every, map, and filter are in place too, and more might come soon as long as it fits in about 140 chars.

All Together

Either for node or browsers, we can easily test these features without requiring massive changes or libraries via a copy and paste based on one of the lightest and also fastest env utility out there ... enjoy ^_^