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

Tuesday, August 21, 2012

A Safer JS Environment

Oh well, apparently I wasn't joking here and I went even further ... so here I am with a weird hack you probably never thought about before ;)

A Globally Frozen Environment

Have you ever thought about this in the global context?

Object.freeze(this);

Apparently not even browser vendors such Chrome or Safari since this condition, today, is always false: Object.isFrozen(Object.freeze(this));, and even if it works as expected after freezing.
Firefox and node.js got it right while Opera Next throws an error .. but latter a part ...

Stop Any Global Pollution

That's right, if you freeze the window or global object, guess what happens here:

Object.freeze(this);

var a = 123;
alert(this.a); // undefined
alert(a); // error: a is not defined

We cannot even by mistake create a global variable ... there's no lint that could miss that.

Moreover, if you are worried about malicious code able to change some global function or constructor, you can stop worrying with proposed freeze call: that will break instantly and any manual quick test will instantly fail rather than keep going.

What About Namespaces

Well, if global namespaces, this hack will prevent the creation of any namespace.
However, we are in RequireJS and AMD module loader era where a module is imported inline through require() or inside a callback with AMD. The only important thing, is that at least the require function must be defined before this hack is performed or even that one cannot be used.

Once we have require() things are that easy, you create your own private scope and you do your own stuff in that scope being still sure that you won't pollute the global scope plus you won't be scared about other scripts ... you have your virtual sandbox

Object.freeze(this) && function (global) {
// here all local variables you want
var
fs = require("fs"),
mymodule = require("./mymodule")
;
// do the hack you want
}(this);

// AMD style
require(["fs", "./mymodule"], function (fs, mymodule) {
// already in a closure so ...
// do the hack you want
});


Too Restrictive? Object.prototype Then!

At least we can think about freezing the Object.prototype as the very first script in any webpage so the nightmare JSLint is talking about, the slow, boring, and probably already not necessary since no recent library is extending the Object.prototype since ages, hasOwnProperty() check, does not need to be in every bloody for/in 'cause you know what? Nobody can change, add, pollute, the global Object.prototype!

Object.freeze(Object.prototype);

// everything else after

for (var key in {}) {
// screw {}.hasOwnProperty, IT'S NOT NEEDED!
}



How About Both

If you are the only owner of your scripts, if you load node.js modules, by default with the ability to screw things up in the global context, or if you use AMD where global pollution should never be necessary, you might decide that this script is your best friend.

try {
// (C) WebReflection - Mit Style License
!function(global, Object){"use strict";
// buggy in both Chrome and Safari
// always false
if (!Object.isFrozen(global)) {
var freeze = Object.freeze;
Object.getOwnPropertyNames(
global
).forEach(function (prop) {
var tmp = global[prop];
switch(typeof tmp) {
case "function":
tmp = tmp.prototype;
case "object":
if (tmp) {
// console might not be freezable
// same is for String.prototype
// if applied twice and only in Safari
try {freeze(tmp)} catch(o_O) {}
}
break;
}
});
// Opera Next has some problem here
try {freeze(global)} catch(o_O) {}
}
}(this, Object);
} catch(o_O) { /* still in IE < 9 browser ... */ }

As summary, let's write down benefits of this technique:
  1. global context is free from pollution, no missed var will work anymore so it's instantly fixed before the eventual usage of a linter
  2. for/in loops could have a massive boost over object literals since nobody can possibly change the Object.prototype
  3. ES5 enabled browsers, which means all current browsers for desktop and mobile except desktop IE < 9, will prevent greedy or outdated scripts, to make the environment less secure
  4. nobody can redefine eval or Function, used sometimes for reasons but the most insecure global functions we have in JS
  5. we are forced to think in modules, 'cause there won't be any other way to load external script or dependency
  6. the only script that needs, eventually, to be loaded, will be the require() one, which means faster bootstrap by default thanks to smaller amount of synchronous bytes required to initialized our project
  7. in node.js, we are forced to write in a function even the main program, rather than polluting global object with stuff that might disturb required modules (which is true for all require/AMD based solutions too)

What do you think?

Sunday, August 19, 2012

Why JSON Won ... And Is Good As It Is

I keep seeing developers complaining about different things with JSON protocol and don't get me wrong, I've been the first one trying to implement any sort of alternative starting from JSOMON and many others ... OK?

Well, after so many years of client/server development is not that I've given up on thinking "something could be better or different", is just that I have learned on my skin all reasons JSON is damn good as it is, and here just a few of these reasons.

Reliable Serialization ?

No, 'cause YAGNI. There are few serialization processes I know that kinda work as expected and since ever, PHP serialize is a good example.
Recursion is not a problem, is part of the serialization process to solve it, as well as classes together with protected and private properties. You can save almost any object within its state, even if this object won't be, as reference, the same you serialized .. and I would say: of course!
There are also two handy methods, __sleep and __wakeup, able to let you save an object state in a meaningful way and retrieve it back or perform some action during deserialization.

Are these things available in JSON ? Thanks gosh NO! JSON should not take care of recursive objects ... or better, it's freaking OK if it's not compatible 'cause recursion is a developer matter or issue, not a protocol one!
All JSON can do is to provide a way to intercept serialization so that any object with a .toJSON() method can return it's own state and any time JSON.parse() is performed, it could bring back, if truly necessary, its recursive property.

So, at the end of the day, JSON implementations might provide already a similar way to __sleep and __wakeup objects but it should be the JSON string owner, the service, the developer, to take care of these problems, and simply because ....

Universal Compatibility

JSON is a protocol and as a protocol it should be as compatible as possible with all languages, not only those C like or others with similar comments ... there won't be comments ever in JSON, 'cause the moment you need comments, you don't need a transport protocol 'cause programming languages have always ignored developers comments ... and also, for compatibility reasons, not all programming languages would like to have // or /* */ or even # as inline or multiline comment ... why would they?

Specially in .NET world most of documentation is written in a pseudo XML, can you imagine you bothering yourself to write such redundant markup language to write something often ignored by developers ? Would you like to have that "crap" as part of the data you are sending or receiving via JSON as part of that protocol? I personally don't ... thanks! 'cause I believe a transport protocol should be as compact as possible and without problems.
Here JSON wins once again 'cause it's compatible, with its few universal rules, with basically everything.

Different Environments

This is the best goal ever reached from a protocol, the fact that every programming language can represent somehow what JSON transports.
Lists, Arrays, Dictionaries, Objects, Maps, Hashes, call them as you want, these are the most used and cross language entities we all deal with on daily bases, together with booleans, strings, and numbers.

OK, OK, specially numbers are quite generic but you might admit that the world is still OK with a generic Int32 or Float32 number and with 64bits compatible environments, these numbers could be of a different type but only if you will never deal with 32 bits environments ... make you choice ... you want a truly big number? Go for it, and loose the possibility to "talk" with any other 32 bit env ... not a big deal if you own your data, kinda pointless memory and CPU consumption if you deserialize everything as 64 bits ... but I am pretty sure you know what you are doing so ... JSON is good in that case too.

No Classes

And again thanks gosh! You don't want a protocol that deals with classes, trust me, 'cause you cannot write a class in all possible programming languages, can you? If you can, even in those programming languages where classes never existed 'cause classes are simply an abstract concept represented by the word "class" but representable in billion ways with other languages (e.g. via just objects in JavaScript).
Classes and namespaces issues, if you want, are there in any case.
The good part of JSON, once again, is the ability to intercept serialize and unserialize process so that if you like to send instances, rather than just objects, you can use all tools provided by the implementation, and I am showing in this case a JavaScript example;

function MyClass() {
// doesn't matter what we do here
// for post purpose, we do something
this.initialized = true;
}
MyClass.prototype.toJSON = function () {
this.__class__ = "window.MyClass";
return this;
};

var myClassObject = JSON.stringify(new MyClass);
// "{"initialized":true,"__class__":"window.MyClass"}"

Once we send this serialized version of our instance to any other client, the .__class__ property could be ignored or simply used to understand what kind of object was it.

Still in JavaScript, we can deserialize easily the string in such way:

function myReviver(key, value) {
if (!key) {
var instance = myReviver.instance;
delete instance.__class__;
delete myReviver.instance;
return instance;
}
if (key == "__class__") {
myReviver.instance = myReviver.createInstance(
this, this.__class__
);
}
return value;
}

myReviver.createInstance = "__proto__" in {} ?
function (obj, className) {
obj.__proto__ = myReviver.getPrototype(className);
return obj;
} :
function(Bridge) {
return function (obj, className) {
Bridge.prototype = myReviver.getPrototype(className);
return new Bridge(obj);
};
}(function(obj){
for (var key in obj) this[key] = obj[key];
})
;

myReviver.getPrototype = function (global) {
return function (className) {
for (var
Class = global,
nmsp = className.split("."),
i = 0; i < nmsp.length; i++
) {
// simply throws errors if does not exists
Class = Class[nmsp[i]];
}
return Class.prototype;
};
}(this);

JSON.parse(myClassObject, myReviver) instanceof MyClass;
// true

Just imagine that __class__ could be any property name, prefixed as @class could be, or with your own namespace value @my.name.Space ... so no conflicts if more than a JSON user is performing same operations, isn't it?

Simulating __wakeup Call

Since last example is about __sleep, at least in JavaScript easily implemented through .toJSON() method, you might decide to implement a __wakeup mechanism and here what you could add in the proposed revival method:

function myReviver(key, value) {
if (!key) {
var instance = myReviver.instance;
delete instance.__class__;
delete myReviver.instance;
// this is basically last call before the return
// if __wakeup was set during serialization
if (instance.__wakeup) {
// we can remove the prototype shadowing
delete instance.__wakeup;
// and invoke it
instance.__wakeup();
}
return instance;
}
if (key == "__class__") {
myReviver.instance = myReviver.createInstance(
this, this.__class__
);
}
return value;
}

Confused ? Oh well, it's easier than it looks like ...

// JSON cannot bring functions
// a prototype can have methods, of course!
MyClass.prototype.__wakeup = function () {
// do what you need to do here
alert("Good Morning!");
};

// slightly modified toJSON method
MyClass.prototype.toJSON = function () {
this.__class__ = "window.MyClass";
// add __wakeup own property
this.__wakeup = true;
return this;
};

Once again, any other environment can understand what's traveling in therms of data, but we can recreate a proper instance whenever we want.

How To Serialize

This is a good question you should ask yourself. Do you want to obtain exactly the same object once unserialized? Is that important for the purpose of your application? Yes? Follow my examples ... no? Don't bother, the less you preprocess in both serializing and unserializing objects, the faster, easier, slimmer, will be the data.

If you use weird objects and you expect your own thing to happen ... just use tools you have to intercept before and after JSON serialization and put there everything you want, otherwise just try to deal with things that any other language could understand or you risk to think JSON is your own protocol that's missing this or that, while you are probably, and simply, overcomplicating whatever you are doing.

You Own Your Logic

Last chapter simply demonstrates that with a tiny effort we can achieve basically everything we want to ... and the cool part is that JSON, as it is, does not limit us to create more complex structures to pass once stringified or recreate once parsed and this is the beauty of this protocol so please, if you think there's something missing, think twice before proposing yet another JSON alternative: it works, everywhere, properly, and it's a protocol, not a JS protocol, not a X language protocol ... just, a bloody, protocol!

Thanks for your patience

Thursday, August 16, 2012

JavaScript recent Bits and Bobs

Quick post about few things landed, or not yet, in JavaScript world.

preciseTime()

In this era loads of +new Date, JSC offers since quite a while a handy global function called preciseTime().
Since this function offers more accuracy than milliseconds, and I am talking about microseconds, which is 1/1000 of a millisecond, it's the best option we have to measure benchmarks or be sure that some time elapsed between two statements in a synchronous code flow.

You might don't know that a loop between new Date and another new Date could produce completely unexpected results such a negative integer which is kinda unexpected since zero is the best case we would consider.

This behavior is behind ticks and clocks, more or less same reason setTimeout or setInterval have never been accurate in therms of delay.

preciseTime, this is the obvious name of my latest git repository, could be shimmed or polyfilled quite easily via a node module I can't npm install for some reason, or through java.lang.System.nanoTime for Rhino.

enjoy!

Object.getPropertyNames()

In MDN Proxy Fundamental Traps chapter there are two functions I was kinda waiting for, and one of these is Object.getPropertyNames().

As you might know, Object.keys(object) returns an array of enumerable object properties.
A similar behavior could be obtained via this shim:

// warning: this is not fully ES5 standard
"keys" in Object || !function(hasOwnProperty){
Object.keys = function keys(object) {
var keys = [], key;
for (key in object)
// not considering IE < 9 quirks
hasOwnProperty.call(object, key) && keys.push(key);
;
return keys;
};
}({}.hasOwnProperty);


On the other hand, Object.getOwnPropertyNames returns an Array of all properties defined in the object, even those not enumerable or as getters/setters, but without considering inherited properties.
For all ES3 browsers is basically the same of above Object.keys() shim since it's not possible to define not enumerable properties in a meaningful way.
To be really honest, probably all IE < 9 browsers should use the check over isPropertyEnumerable() check via Object.keys, and leave the provided shim as it is since actually, those not enumerable properties are those that this function could return in a meaningful way, and talking about shims ... never mind ...

In ES5 world there's no other way to retrieve all properties names defined in an object so this methods is pure awesomeness!

Right ... What About Object.getPropertyNames()

What is not possible right now, and in a world where inheritance is all over the place as JS world is, is the ability to retrieve not only own properties, but inherited properties too.
In a duck typed system we need to know all characteristics of an object to be sure "it's a duck". Right now there's no standard way to obtain all properties an object could use, and this is where Object.getPropertyNames() becomes handy: you receive all inherited properties of an object too, together, of course, with own properties.
In my shim, this is obtained through the __proto__ de facto standard property.


At this point we can recognize a duck properly, the only method eventually missing is the one able to give us a list of not enumerable properties per each object ... but with these tools, we can create one, if truly necessary.

Object.getPropertyDescriptor()

Oh well, this is about another annoying thing ... the fact we know that obj instanceof Class but we have to be upside-down to know if a property, defined as default in the Class.prototype has been redefined or it's simply that bloody default.
This is about this method, shimmed in the previous gist as well, and able to retrieve the descriptor of a property that might, or might not, be inherited. How cool is that?

The only thing I am not sure about, is if the method should consider up to prototype === null, including Object.prototype or not ... right now is not, since I believe nobody would ever check for hasownProperty descriptor, as example, with a generic object.

global methods, classes, and shit

This is more a hint, whenever you are curious about what's exposed through your global object, you can simply perform this check, and inside an about:blank page:

console.log(
Object.getOwnPropertyNames(this).sort().join("\n")
);

Where if you want alphabetic order, you might consider this elaborated version if previous one did not work as expected.
Run it once in your browser, environment, console:

!function(global){
function alphabetically(a, b){
var
alen = a.length,
blen = b.length,
len = Math.min(alen, blen),
i = 0,
ac, bc, c
;
while (i < len) {
ac = a.charCodeAt(i);
bc = b.charCodeAt(i);
c = ac - bc;
if (c) return c;
++i;
}
return alen - blen;
}
var getOwnPropertyNames = Object.getOwnPropertyNames;
if (!getOwnPropertyNames) {
getOwnPropertyNames = function getOwnPropertyNames(object) {
var hasOwnProperty = {}.hasOwnproperty, keys = [], key;
for (key in object)
hasOwnProperty.call(object, key) && keys.push(key)
;
return keys;
};
}
function getAllKeys(object, ordered) {
var keys = getOwnPropertyNames(object);
ordered && keys.sort(alphabetically);
return keys;
}
console.log(getAllKeys(global,1).join("\n"));
}(this);