Monday, September 27, 2010

Opera, Inevitably Unexpected

Update


Opera fellas works at speed light, the problem described in this post has been patched already, great stuff and thanks!



Just a quick one, about what I have discovered with Opera 10.62 when I have tested wru against this browser ...

// host object
var xhr = new XMLHttpRequest;

// this is true
alert("addEventListener" in xhr);

// this is undefined
// not even null
// simply undefined!!!
alert(xhr.addEventListener);


The Problem

99% of libraries out there are assuming that key in object is one of the fastest and most reliable way to have features detection.
Today, we know that this assumption is wrong.
It's not about the reproducibility of the problem:

var o = {};
o.key = o.key;
"key" in o && o.key;

It's about an ...

Epic Fail (Already Fixed!)

The engine "behind the scene" is broken. Whatever it happens there, we have a broken chain through pseudo inheritance that exposes publicly a method that does not exist, which brings us down the assumption that host objects are not tested before the release ... or surely not their "apparently valid" methods.
Nothing else to say, come on guys, you've always been pioneer and good fellas, so please don't release these mistakes, thanks.

WRU: My New Tiny Unit Test Library

The last and only developer able to let me fully appreciate the beauty of Test-Driven JavaScript Development has been @cjno, but regular "fights" with @mrgnrdrck and @sleistner have always helped me as well ;)

This post is about my tiny wru library and general thoughts about JavaScript Unit Test Frameworks.

WRU: Essentials Asynchronous Tests

The wru library is a copy and paste matter, and it is possible to test it directly here.

Why Wru

Well, sometimes I write truly small projects during my free time, and a setup that takes "zero seconds" with still a visual result of my tests could be all I need. Also for my personal projects I rarely need a massive logic behind the UT framework ... simple things are often better, but I will explain why afterwards.

Look, if you refresh, it changes!

What I have learned from Christian while I was editing his book code is that order should not matter. In my opinion there are cases where order could matter, specially when a test may depend over the setup of another one. The discussion may be long and tedious, but basically while all frameworks I know follow a for or for/in order, based on current engine implementation since for/in order has never been granted by specs, wru may have random order, and it's easy to flag it as true.

Look, it uses setTimeout and XMLHttpRequest for tests and it works!

Pretty much, wru does not give a shit about asynchronous calls but if we implement the extra file, called async.js, wru will always wait that async variable will be false before it continues.
It is true that other test could be "coolly" executed in the meanwhile, but at the end of the day the result comes when all of them have been executed ... so ... why bother? Just wait, and wru will go on by itself.

Public or Privileged Setup and Teardown

A fresh new setup per test may be worth it, that's why wru checks for these properties in the current test first, and wru itself after. If there, these are called with a temporary object shared for the test lifetime where we could store whatever we need since it's just passed by reference, as every other JS object. Handy, hu?

Compatibility?

You can try your smart phone or whatever desktop browser in this list: IE7+ ... all others. wru should simply work.

Essential Is The Key

Christian smart framework a part, 90% of Unit Test frameworks I have seen are based on following bullshit:

  • with statement, the statement everybody is scared about is far away from our production code but unbelievably trusted for all major unit test frameworks I have seen ... no comments at all ... I am simply waiting ES5 and strict tests that will nicely fuck up all your effort to write tests so far with frameworks based on the with statement

  • function destructuration, another monster able to destroy the meaning of scope and everything else that starts with the name safe environment. If your framework parses functions and methods in order to understand them, throw it away

  • any sort of magic, where magic may be good for production code and exposed API, but rarely the way to go for unit tests

  • polluted environments, via with, native prototypes and whatsoever in order to speed up those few minutes we use to write a test ... the one we suppose to trust ...

  • assertWhatever, where "Whatever" is part of the magic assertion I will never get ... and I tell you why ...



The Number One UT Framework? The Console

console.assert is probably the only thing we truly need for whatever test we would like to run in an almost clean environment, where FireBug, as example, is able to screw up a basic selector like document.getElementsByTagName("div") polluting the DOM with it's console node (a freaky and custom <firebug> node element was too clever, isn't it?)
Unfortunately, console.assert may not be available in some environment and we prefer a visual green response, isn't it? Well, with wru we can use our own style for results so that we could make the testing page as cool as possible.

Decide What To Assert

The only thing wru would assert is a truish value, and we are the only one able to make the result true ... this sounds too boring, isn't it?
The classic assertTrue is in my opinion the most ambiguous thing ever in a dynamic typed language.
All objects are true, an eqeq rather than eqeqeq could be true as well and I would like to know which one the framework is considering true.

// false by specs
console.log(
{} == true
);

// true by specs
console.log(
{valueOf:function(){return true}} == true
);

In few words, are we really sure that assertion was the one I meant? Or we have to investigate and "test the testing framework" to remember what happens behind scene?
With wru, we write the assert and if it fails, it fails. Now, tell me that you trust more the magic behind your framework ...

Stubs And Mocks Gotchas

While a stub is usually tied to a function signature, a mock is usually tied to a whole object, or environment, behavior.
What we test in this case is what we expect ... and this is ... too easy, isn't it?
We are not considering that stubbing a behavior we may have on real world so many side effects we cannot even imagine.
First of all, we are not sure that our arguments are valid 'cause we don't care about "the scene behind" our test ... and this may be good, as far as we are sure that our code works perfectly without knowing that an argument or the expected result produced by those arguments created an anomaly in the environment, and maybe an expected one.
Stubs and Mocks have been one of the "major fights" I have done with Christian during the editing, and as I have said he has been able to enlightening me about the topic ... yeah, now I got it, but stubs and mocks are still something I don't want to deal with my little projects, while surely I need them on daily basis real world tests scenarios.
For these reason, the KISS approach, I have decided to leave stubs and mocks for serious cases/applications/frameworks, but you won't find them inside wru ... but of course, we can all implement our stubs and mocks using a wru.assert(...) when it necessary during that specific test.

The Ruby World

I have heard many times Ruby community is really focused on Unit Test. Unfortunately JavaScript is not Ruby, and most of the frameworks I have seen have been created by Ruby guys that most likely did not get entirely the difference, and the beauty, of JavaScript. Please don't fall in the "common" Java developers hole, where everything should be based on new Class, you can do better!

Conclusion

I am already using wru for simple local projects and I am quite happy with its simplicity and I hope somebody will be able to "grab the concept" and create an even better framework for JS community since right now ... things are not that perfect at all.
Christian Johansen library is probably following the same simplicity, bringing much more "in the house". I suggest you to have a look but even said that, I do believe the road for a complete and standard JSUT Framework, obviously compatible with both server and client, is still unfortunately long ... well, wru is my little attempt, but yeah, I have to mock the wru DOM node in a server side environment ... but will come soon ;)

Sunday, September 26, 2010

@jsconfeu after parties epilogue

too bad I wasn't planning to be in Berlin this week end for this conference, and too cool I have been able at least to meet such crowd of JS pirates after the conference!

This post is about what I have found in JSConf.eu "after events", and I do believe it should be shared.

Great To Meet You All

Heroes, colleagues, "just developers", it does not really matter! Everybody I have talked with was in the "friendly, shary, skilled, interested" mood, pretty cool for this JS community that is clearly growing up on daily basis in Europe as well ... Yeah, you simply have to accept that JavaScript is everywhere, client, server, whatsoever, and nobody will stop us!
You can still think it's a toy language, not a real programming one (scripting is part of the therm tho) and bla bla bla ... this community of real pirates will always be there to answer your questions and show how freaking cool is this programming language!

Twitter Is The One!

If you are following speakers and other participants as I have done, you would have felt somehow in the conference. Of course I have missed everything there, and twitter could not give me same feeling, but it's impressive how much devs share realtime and how easy is to virtually follow presentations via posted slides, comments, and all sort of links.

Party Time!

Good organization on both Friday*, Saturday, and Sunday, with almost every speaker there for the "after conference". Places, as well as number of JS folks, were really cool: an unexpected atmosphere for what somebody may simply define a "geek meeting": music, games, and inevitably #beers, great stuff!
*next Friday dinner please in a proper Schnitzel and Kartoffeln place!!!

Special Thanks

These are developers I have met the first time outside the Web and I would like to thank ... and if you don't follow them ... you better should!

  • @andrewdupont, the Prototype and script.aculo.us party man

  • @dalmaer ... uh wait, we met different times before :D

  • @jdalton, the "all you can dream about JS libraries" pirate

  • @paul_irish, the real HTML5 evangelist

  • @phiggins, a "crazy dude" you'll never recognize without his hat

  • @rmurphey, the one that "would never hire me and my WebReflection arrogance" :P

  • @robertnyman, the "JS and HTML5 buddy" you have to meet in person

  • @stoyanstefanov, the "kick ass" client/server performances man

  • @thomasfuchs and @amyhoy, the Scripty and "learn JS properly!" folks


Apologies if I forgot somebody but ... you know, I had few beers as well ;)

Thanks again everybody and see you soon!

Promote JS!

From JSConf.eu a nice initiative to better promote JSINJ thanks to MDC documentation.

JavaScript JS Documentation: JS Array indexOf, JavaScript Array indexOf, JS Array .indexOf, JavaScript Array .indexOf

I would like to share my thoughts about the initiative:

  • it's time for developers to understand that if they know a library (e.g. jQuery) it does not mean they know JavaScript. Too often I have talked with "JS Developers" unable to add a simple DOM listener in a W3/IE way. This initiative may eventually bring to all JS folks the beauty and simplicity of the language, which is not only inside this or that framework

  • MDC has always been a reference to me but it must be said it does not include everything and sometimes it has Gecko specific pages that may disorient us if our target is cross browser

  • MDC may contains errors as well and many examples are not optimized at all but for some reason took as "the only way to do that". In this case Array extras, as example, are not always the most logic or performances oriented

  • as I have done different time there, it is possible to edit the content adding hopefully valid contribution



Have fun Pirates!

Monday, September 20, 2010

Fragment and Vertex Shaders: My Way To Load

I have finally received the fifth and amazing version of the OpenGL SuperBible book and I have already started digging into it, really well done for what I can tell.

The book is mainly focused on "real OpenGL development", something surely more suitable for tough C/C++ developers rather than Web Monkeys like me but since the book includes an OpenGL ES 2.0 related part, and since latter spec is basically what we can find in WebGL, it's always better start learning what's next knowing history and background of the used technology ... and here I am :-)

Something Already Wrong

I am not completely sure about "who started this techniques", John Resig with his micro template inside script nodes with a type text/html may be the indirect responsible for a sort of growing "monster" we can see in almost every WebGL related example ...

HTML Embedded Shaders, the Web 3.0 NO-GO

Let me pass the therm, but 3D websites are not that far away from reality. Minefield, Chrome, WebKit, and probably others, are working hard with Khronos and WebGL and I do believe official support will come later this year with next browsers releases ( ... hoping IE9 final won't "block the world" avoiding WebGL support ... )
Back in the topic, the common examples technique is a step backward in 1999 where runtime loading did not exists (aka: Ajax or scripts injection) and an HTML page was a trash bin for any kind of rubbish.

A Better Technique

We are in 2010 and we want use latest technologies, so why should we use old and deprecated one? Let me show this simple getShader function alternative:

// our shaders base path
loadShaders.base = "shader/";

// our shaders loader
function loadShaders(gl, shaders, callback) {
// (C) WebReflection - Mit Style License
function onreadystatechange() {
var
xhr = this,
i = xhr.i
;
if (xhr.readyState == 4) {
shaders[i] = gl.createShader(
shaders[i].slice(0, 2) == "fs" ?
gl.FRAGMENT_SHADER :
gl.VERTEX_SHADER
);
gl.shaderSource(shaders[i], xhr.responseText);
gl.compileShader(shaders[i]);
if (!gl.getShaderParameter(shaders[i], gl.COMPILE_STATUS))
throw gl.getShaderInfoLog(shaders[i])
;
!--length && typeof callback == "function" && callback(shaders);
}
}
for (var
shaders = [].concat(shaders),
asynchronous = !!callback,
i = shaders.length,
length = i,
xhr;
i--;
) {
(xhr = new XMLHttpRequest).i = i;
xhr.open("get", loadShaders.base + shaders[i] + ".c", asynchronous);
if (asynchronous) {
xhr.onreadystatechange = onreadystatechange;
}
xhr.send(null);
onreadystatechange.call(xhr);
}
return shaders;
}

With above minifier friendly function we can avoid shaders on the page. The natural advantage is that we can properly organize shaders in a structure like this one:

root

shader

vs // vertex shaders

ShaderName.c

fs // fragment shaders

FragmentName.c

Having a proper extension means that we can edit these files with highlighted syntax and we can edit these files a part, without looking for id or scripts inside an HTML page. Fragment and Vertex Shaders are our "application templates", so why on earth should we include them in the layout? Via loadShaders we can use cached shaders, share shaders, etc etc, and here some usage example.


vra gl = canvas.getContext("experimental-webgl");

// synchronous order, one shader
var myFragmentShader = loadShaders(gl, "fs/myFragment");

// synch, more shaders
var shaders = loadShaders(gl, [
"vs/what",
"vs/ever"
]);
// [whatShader, everShader]


// asynchronous loading
loadShaders(gl, ["fs/what", "vs/ever"], function (shaders) {
var
fragmentWhatShader = shaders[0],
vertexEverShader = shaders[1];
;
});


// asynch in "don't care mode, just cache them"
loadShaders(gl, ["fs/what", "vs/ever"], true);



Features


  • Synchronous or Asynchronous loading

  • Multiple Loads (unordered compilation for each result)

  • Ordered Results, (order respected accordingly with paths)

If I have forgotten something please point it out but even more please, whatever you like or not this solution, do not include shaders in your HTML page (OK, OK, gotcha, for some example it may make life easier but ... you know how people get examples ... right?)

Cheers :)

Wednesday, September 15, 2010

The Rebecca Murphey's Challenge

What is the best/easiest way to understand if a {{ProgrammingLanguage}} developer is a {{ProgrammingLanguage}} dev and not simply a CV bloater?

A Technical Test

Nothing simpler than this, and this is what @rmurphey has recently done with a nice JavaScript challenge published on GitHub.
Unfortunately in some country (Italy as example) IT is still a matter of piece of paper for whatever {{ProgrammingLanguage}}, even those completely unrelated with the generic developer academic course/program, as often happens with JavaScript, the most used one and probably the less considered one at the same time ( ... hopefully it comes after VB ... )
Anyway, Rebecca comes from North Carolina and we all know in USA "they know something about IT", don't we? :)

Developers Rumors

I have probably arrived too late, but apparently lots of developers more updated than me knew about this test ... and this is good.
When developers are happy to be tested they demonstrate already to be brave, convinced about their knowledge, and ready for new challenges and I am pretty sure Rebecca will thank them all.
About me? I am just "challenges addicted" so even if I am not interested in Rebecca proposal, I could not avoid this test and this post aim is to describe question after question, pretending I would have applied ... are we ready? :)

Considerations

JavaScript is extremely flexible and expressive so there is rarely a universal solution for a single problem. Moreover, I did not know Rebecca and I have read nothing about this test when I have tried to consider that some answer may be redundant while I have re-thought some other to provide a better answer. Finally, to solve the test it's strictly necessary to make a lot of assumptions since questions are often too poor. Let's start now!


1: how could you rewrite the following to make it shorter?



if (foo) {
bar.doSomething(el);
} else {
bar.doSomethingElse(el);
}

Assumption #1: doSomething and doSomethingElse are truly named like that and this is the answer thinking in a non abstract way:

bar["doSomething"+(foo?"":"Else")](el);

Assumption #2: the method name is just indicative:

bar[foo?"doSomething":"doSomethingElse"](el);

Latest approach could be optimized if the same operation should be repeated after and using two strings references for method names so that minifiers can play well.

2: what is the faulty logic in the following code?



var foo = 'hello';

(function() {
var foo = foo || 'world';
console.log(foo);
})();

Do you remember my good old/shorter way to address the "undefined" string to a local variable?

var u = typeof u;

The logic is the same, but Rebecca does not know me so I think I should explain that once we declare local scope variables these have prevalence against the outer scope and a function scope is always invoked resolving in advance function declarations and knowing already declared scope variables.

(function () {

alert([onFnCall, notAfter]);

// tons of JavaScript and ...

for (var onFnCall = 1; 0;);
function notAfter(){}

alert([onFnCall, notAfter]);

}());

The first alert will be undefined, function notAfter(){} while the second one will show the onFnCall assigned value as well.
What is important to know is that no error occurs on the first alert and it will always be undefined, even if there is an outer scope variable with the same name.
I have an old IE related post about this, have fun :)

3: given the following code, demonstrate you know JS objects



var Thinger = function() {
return this;
};

Thinger.prototype = {
bar : 'baz'
};

var foo = new Thinger(),
bim = new Thinger();

The first thought after the very first line of code has been something like: Dude, you don't like the non (IE) standard but unbelievably helpful "name" property, don't ya? Neither you like saved bytes

function Thinger() {
return this;
}

The instant second thought on the instant second line has been something like: "... neither you present good example! Why on earth that bloody redundant and pointless return this which is worldwide recognized as implicit?"

function Thinger() {}

So now, accordingly with the rest of the code, I can at least go on reading it ...

3.1: how would you override the value of the bar property for the variable foo without affecting the value of the bar property for the variable bim?



foo.bar = foo.bar; // it's enough

The moment we assign a property to a generic instanceof Object is the moment we are sure that obj.hasOwnProperty("directly assigned") will return true, even if the assignment is for an undefined value.
Fair enough, the moment I execute latest line of code, is the moment I ask foo to access its prototype chain and assign the returned value, if any, to the property with the same name. Is bim affected by this operation? Not at all!

3.2: how would you affect the value of the bar property for both foo and bim?


Assumption #1: we are talking about the initial case, without operations in the middle (e.g. the foo.bar = foo.bar; I have written already)

Thinger.prototype.bar = "via chained properties";

Any JS developer knows that objects properties access look up for the chained prototype, where if this has no property but still a __proto__, the lookup will continue until we reach the null __proto__:

Object.prototype.__proto__ == null;

In this case life is easy, there is only one chain and the lookup stops immediatly.

Assumption #2: objects creation and the moment we would like to be sure both objects "bar" properties are changed could be performed after any sort of code, included the one posted at the beginning.
With latest assumption we have two options, the most obvious one:

// sub assumption, NO ES5 and defineProperty
foo.bar = bim.bar = "overwrite";

While the second one, still considering no ES5 in place where Object.defineProperty could avoid such operation, is the safer equivalent of the first one:

delete foo.bar;
delete bim.bar;
Thinger.prototype.bar = "via chained properties";

Latter approach could be used to change shared runtime properties or methods in those constructors that would like to track each instance, e.g.

var CrazyStuff = (function () {

// the constructor
function CrazyStuff() {
// with a register
_instances.push(this);
}

// the public magic method
CrazyStuff.defineInstancesProperty = function (name, value) {
_instances.forEach(deleteProperty, name);
this.prototype[name] = value;
};

// some chained property ...
CrazyStuff.prototype.bar = "buz";

// some prototype method ...
CrazyStuff.prototype.destroy = function () {
var i = _instances.indexOf(this);
if (-1 < i) {
_instances.splice(i, 1);
}
};

// the public magic method helper
function deleteProperty(instance) {
delete instance[this];
}

// instances container
var _instances = [];

// ensure indexOf method (quick version)
_instances.indexOf = _instances.indexOf || function (value) {
for (var i = this.length; i--; ) {
if (this[i] === value) break;
}
return i;
};

// same with forEach (quick version)
_instances.forEach = _instances.forEach || function (fn, context) {
for (var i = this.length; i--; ) fn.call(context, this[i]);
};

return CrazyStuff;

}());

var
foo = new CrazyStuff,
bim = new CrazyStuff
;

alert(foo.bar); // buz

foo.bar = "overwritten";
alert(foo.bar); // overwritten

CrazyStuff.defineInstancesProperty("bar", function () {
alert("YO, even methods!");
});

foo.bar(); // YO, even methods!

As I have said before and as you can see, it's never that easy to answer a generic JS question without thinking or creating different ways to obtain similar results.

3.3: how would you add a method to foo and bim to console.log the value of each object's bar property?

Surely avoiding runtime changes to the prototype, even if I have just showed some CrazyStuff.
I am not sure if the question is appositely wrongly formulated, but the only answer I could provide locally was changing the initial example:

Thinger.prototype = {
bar : 'baz',
logBar: function () {
console.log(this.bar);
}
};

It does not matter if Rebecca meant something else, I have already demonstrated how easy is to change runtime properties (and then methods) and I would never use the same technique for a simple method.
The Assumption, in any case, is that there is a public object called console and that this has a log method, otherwise the first instanceOfThinger.logBar() call will produce an Error.

3.4: how would you tell if the object's bar property had been overridden for the particular object?


At least in three ways, considering that ...
Assumption #1: no fools man, too easy

instanceOfThinger.hasOwnProperty("bar");

If you don't know hasOwnProperty method, I am pretty sure you have failed the whole test and you are not into JavaScript at all (yet). It is still probably worth it to keep reading this post to hopefully learn something new :)

The Assumption #2 is that we are talking about generic objects. In this case we cannot be sure that hasOwnProperty method is inherited from the Object.prototype (e.g. host objects) so, as safer solution, I would do something like:

Object.prototype.hasOwnProperty.call(object, "bar");


The last Assumption #3 is that I am a wannabe, but I am not a surrender, since in the Ninja code there is no space for loosers:

// optimistic, still ignorant, attempt
function hasOwnProperty(obj, name) {
var result = false, value;
if (name in obj) {
value = obj[name];
delete obj[name];
result = !(name in obj && obj[name] === value);
if (result) {
obj[name] = value;
}
}
return result;
}

hasOwnProperty(foo, "bar");

Latest attempt will easily fail if both instance and the generic prototypeOf have a property with the same value.

4: given the following code, destroy recursively



var myObjects = {
thinger : new myApp.Thinger(),
gizmo : new myApp.Gizmo(),
widget : new myApp.Widget()
};

Once again, to many assumptions to consider here. It's not specified if the environment is clean, or sandboxed, as it's not specified if myObjects life cycle ends up after the operation. To be sure about almost everything, here the code:

function destroyThemAll(obj) {

for(var key in obj) {
// the "PrototypeJS in da house" way
// if (myObjects.hasOwnProperty(key))
// slower and completely pointless
// for a "destroy" operation
// all we want is to call destroy
// if present
obj[key].destroy && obj[key].destroy();

// alternative:
// paranoid way, ensuring nobody
// attached a destroy property that
// is not a function
typeof obj[key].destroy == "function" &&
obj[key].destroy();

// the optional leaks paranoic way
delete obj[key];
}

}

destroyThemAll(myObjects);

I am sure you got the fact I hate when problems lack of description details :)

5: given the following array, loop over it and do stuff



var myArray = [ 'foo', 'bar', 'baz' ];

This question has basically no answer since it's not specified what we would like to reach. Is it performances? is it readability, is it both? The only point clear is:
you can assume the library of your choice is available
Oh really? Dear Rebecca, I would seriously avoid to hire any developers that is not able to solve this problem without a library ... seriously!!!
In any case, I don't even need to comment this question since Morgan Roderick already created a test page where almost all possible solutions are in place, included my performances oriented in revision 25.
Despite those examples, one of my first attempt was to use the classic trick to repeat strings, instantly screwed up by that space in the middle.

// fast string repeat
function str_repeat(str, times) {
return new Array(++times).join(str);
}

str_repeat("a", 3); // aaa


6: how could you improve the following code?



$(document).ready(function() {
$('.foo #bar').css('color', 'red');
$('.foo #bar').css('border', '1px solid blue');
$('.foo #bar').text('new text!');
$('.foo #bar').click(function() {
$(this).attr('title', 'new title');
$(this).width('100px');
});

$('.foo #bar').click();
});

Here we are again, while I am sure somebody wrote the $.each loop for the precedent question, in this one it's not even mentioned that the library is jQuery ... so why should I think in a jQuery optimization way?
Even if my name is for some reason inside jQuery source code, my first thought, without knowing Rebecca and the fact she is into "jQuery world", has been something like: "dude, the dollar function has been showed via PrototypeJS before jQuery and has been used or re-invented from every developer, me included ... the chainability may be optional, you know that, don't ya ..."
So, this was Assumption #1: dollar does not mean jQuery and chainability.

// non jQuery way
$(document).ready(function() {
// cache the result once
var $el = $('.foo #bar');
// no chainability
// no knowledge of
// methods signature
// the example worked?
// this should work as well
$el.css('color', 'red');
$el.css('border', '1px solid blue');
$el.text('new text!');
$el.click(function() {
// $el refers to 1 element
$el.attr('title', 'new title');
$el.width('100px');
});
$el.click();
});

Then of course Assumption #2 has been jQuery oriented

// assuming jQuery
$(document).ready(function() {
var $el = $('.foo #bar')
.css({
color: "red",
border: "1px solid shit"
})
.text("new text")
.click(function () {
$el
.attr('title', 'new title')
.width('100px')
;
})
.click()
;
});

There is a sub assumption in latter case, the $el acts only to the first element of the CSS query, if not the $(this) inside click() is still necessary.
Now, you know what? Since Rebecca forgot to specify that jQuery was the library, I did not bother myself to check the API ... sorry if it's wrong, but the question is to me incomplete.

7: what issues do you see with the following code? how would you fix it?



(function() {
var foo;

dojo.xhrGet({
url : 'foo.php',
load : function(resp) {
foo = resp.foo;
}
});

if (foo) {
// run this important code
}
})();

Let's assume I am a framework user and I know that dojo is a framework with a xhrGet method ... the problem may be that the call is Asynchronous.
I say "may be" 'cause I am sure somebody could have changed the default behavior for whatever reason so ... Rebecca, are you looking for framework users or JavaScripters?
Anyway ...

(function() {
var foo;

dojo.xhrGet({
url : 'foo.php',
load : function(resp) {
// assuming foo is reused
// no need to assign otherwise
if (foo = resp.foo) {
// run important code
}
}
});

})();


8: how could you rewrite the following code to make it shorter?



(function(d, $){
$('li.foo a').attr('title', 'i am foo');
$('li.bar a').attr('title', 'i am bar');
$('li.baz a').attr('title', 'i am baz');
$('li.bop a').attr('title', 'i am bop');
})(dojo, dojo.query);

Shorter? Here I am:

// new lines for blog readability
["foo","bar","baz","bop"].forEach(function(c){
dojo.query("li."+c+" a").attr("title","i am "+c)
});

But since I have assumed that I could have used any library, even if 90% of the time all we need is just a bit deeper knowledge of JS to obtain the same faster result, it must be written instantly after the IE version:

for(var a=["foo","bar","baz","bop"],i=a.length;i--;)
dojo.query("li."+a[i]+" a").attr("title","i am "+a[i])
;

Shortest ever, isn't it? But maybe Rebecca would have liked to know that dojo argument was completely redundant, considering that dojo.query does not use this internally as dojo reference, otherwise the whole thing would not have runned at all?

9: how would you improve the following code?



for (i = 0; i <= 100; i++) {
$('#thinger').append('

i am thinger ' + i + '

');
$('#gizmo').append('

i am gizmo ' + i + '

');
}

I really would like another Morgan like page for this test, assuming we are still talking about performances.
The number one thing to do is to avoid DOM manipulation inside loops, whatever library we are using. So, for sure, append should be moved after the loop, then we can talk about performances.

var
i = 0,
re = /\{name\}/g, // ES5 friendly
str = new Array(102).join(
'

i am {name} {i}

'
).replace(/\{i\}/g, function () {
return i++;
})
;
$('#thinger').append(str.replace(re, "thinger"));
$('#gizmo').append(str.replace(re, "gizmo"));

In my attempt I don't even use a loop at all but append() a part, I really would like to compare different ways to create those 2 similar strings ... maybe I should create one ...

10: a user enters their desired tip into a text box; the baseTotal, tax, and fee values are provided by the application. Find issues ...



function calculateTotal(baseTotal, tip, tax, fee) {
return baseTotal + tip + tax + fee;
}

This question has been the most ridiculous one I have found in this test since it is a complete nonsense.
First of all, the number of assumptions are unlimited, nothing is clear and ... the design is crap!
Seriously, why on bloody earth I would create a function that accepts 3 variables from an abstract "application" that I suppose I should trust (should i?) and the only argument provided anyhow from the user is ... the second one?
calculateTotal(fromApp1, fromUser, fromApp2, fromApp3) ... I don't really know what you think, but this is one of the crappiest signature I have ever seen ... so Rebecca, please don't be mad at me, but can I rewrite the whole thingy?

10++: a user enters their desired tip into a text box that is gonna be summed with the rest of spent money. Write a function able to return the sum of the user tip, provided via input.value, and a generic number, this time provided by the application.


Now we talk ...
Since I do believe this task is about security, I am quite sure few developers provided this kind of solution for the tip parsing:

function getTotal(tip, amount) {
// cast float compatible
// without function calls
tip *= 1;
if (
// isNaN is not reliable
// what we know by specs
// is that NaN != NaN ... so
tip != tip ||
// if tip is negative
// the user is trying
// to fuck the bill!
tip < 0
) {
// in both cases
// we don't want to go on ..
throw "invalid tip";
// muda-h-acker !!!
}
return amount + tip;
}

If it comes to JavaScript and user exposed runtime changeable code, the word security is a sort of joke.
Security must be on server side, but it is surely true we can help the latter one improving client side security as much as possible.
So, why I have created that function?

// makes every number negative
var parseFloat = (function (parseFloat) {
return function (f) {
f = parseFloat(f);
return f < 0 ? f : -f;
};
}(parseFloat));

// makes every integer negative
var parseInt = (function (parseInt) {
return function (i, base) {
i = parseInt(i, base);
return i < 0 ? i : -i;
};
}(parseInt));

// negative abs
Math.abs = (function (abs) {
return function (n) {
return -abs(n);
};
}(Math.abs));

// always false
var isNaN = function () {
return false;
};

I could go on forever so ... we don't want to trust anymore online forms, do we?
Even worse, if we put the secure logic inside a closure, we could always find the user with an older Firefox version able to reach the private scope and change things there ... scary, uh? Now try to make my attempt fail, since not a single call is changeable (expect the function itself via older Firefox and the scope, private or not).
Repeat with me: security is never enough and on client side it's almost absent :P

11: given the following data structure, do stuff with properties



var menuItems = [
{
id : 1,
name : 'Salad',
extras : [
'Chicken', 'Steak', 'Shrimp'
]
},

{
id : 2,
name : 'Potato',
extras : [
'Bacon', 'Sour Cream', 'Shrimp'
]
},

{
id : 3,
name : 'Sandwich',
extras : [
'Turkey', 'Bacon'
]
},

{
id : 4,
name : 'Bread'
}
];

We can assume any library we like ... and that's why I have chosen JavaScript, you gotta love it :D

var result = menuItems.map(function (item) {
return item.name + (item.extras ? " (" + item.extras.join(", ") + ")" : "");
});

Too easy task at number 11, I feel like I have missed something here ... benchmarks Morgan? :)

BONUS 1: write code such that the following alerts "Hello World"



say('Hello')('World');

... am I missing something here?

// solution one
// the easy one
var say = function (hello) {
return function (world) {
alert(hello + " " + world);
};
};

// solution two
// the less memory one
var say = function (content) {
if (say.content) {
alert(say.content + " " + content);
content = "";
}
say.content = content;
return say;
};


BONUS 2: what is the faulty logic in the following code? how would you fix it?



var date = new Date(),
day = date.getDate(),
month = date.getMonth(),
dates = [];

for (var i = 0; i <= 5; i++) {
dates.push(month + '/' + (day + i));
}

console.log('The next five days are ', dates.join(', '));

At my first try I did a mistake ... I stopped reading inside the for loop!
If like me you have database and server side experience, including Ajax/ActionScript calendars manipulation, you know which one is the first problem ever with dates: we cannot sum days or months that easily.
That's it, whatever this task asks, the first date I have thought, being the day incremented, has been the new year, aka: 31st December.

In few words, every end of the month above loop will populate the dates array with values like:

...
12/32
12/33
12/34
...

Does that Date make any sense? No it does not, no reason to investigate more ... the logic is already crap.
Let's fix it:

// incomplete!
for (var i = 0; i <= 5; i++) {
date.setDate(day + i);
if (month != date.getMonth()) {
day = -i;
month = date.getMonth();
}
dates.push(month + '/' + (day + i));
}

However, another thing we should always remember is that months and days, unless properly formatted, are almost always from 0 to 11, for months, and 0 to 30 for day of the month.
This means that while the day can be increased, the month should be showed properly adding the classic plus one.
This is the first part of the problem, and I am pretty sure the reason this challenge has been placed online at the beginning of the month is not a coincidence, nice trap Rebecca ;)

If we keep reading we can spot something else we could consider as faulty logic:
The next five days are
OK, so we have a loop that goes from 0 to 5 included, which means 6 values: 0,1,2,3,4,5
We can already spot there is something wrong here, so we either fix the string writing "next six days" ... or we simply fix the loop.
However, we should be carefully, because if we talk about next days, the current one should NOT be included.
This is the proper solution for this last task:

var date = new Date,
day = date.getDate(),
month = date.getMonth(),
dates = [];

// next 5 days
for (var i = 1; i < 6; i++) {
// set the next day
date.setDate(day + i);
// verify that the month did not change
if (month != date.getMonth()) {
// if it did, set day as -i
// removing from "i" the loop start: 1
day = -(i - 1);
// re assign the month
month = date.getMonth();
}
// month + 1 AND day + i
dates.push((month + 1) + '/' + (day + i));
}

console.log('The next five days are ', dates.join(', '));


Conclusion

The description of a problem/task is fundamental, no discussions about it. We all know sometimes our customers don't even know what they want ... it's true, but if we do not insist asking details, anything could become a massive mess. A single detail could make the difference, the real goal is even more important ... in this case we had to guess a lot, make assumptions, spend more time than necessary to be sure our "customer", in this case Rebecca, would have been satisfied.
It does not matter if Rebecca will ever consider us, the thing that matters is that we learn to take things carefully and we remember that 2 similar solutions, logically speaking, could have completely different performances impact in a more complex/structured application.
We should chose carefully, analyzing implications, browser features, security model, and whatever is necessary to do our task as good as possible and our goal will be already closer.

I hope you have appreciated this post, maybe learned something or, even better, corrected me where I have done wrong, and also suggestions are welcome :)

Last, but not least, I do hope Rebecca will spend some time to read this post and "judge me" properly but AFAIK she gonna write about this test tomorrow so stay tuned in her blog.



Update
That was fast and ... I did not pass the test!
Alex S wrote the reason, anticipating Rebecca thoughts, fair enough :)

Thursday, September 9, 2010

JavaScript Protected Properties

Imagine this simple piece of code:

var obj = {
_name: "protected",
gimmeName: function () {
return this._name;
}
};

obj.gimmeName(); // "protected"
obj._name; // throws new Errror

now, imagine I have the simplest solution ever, compatible with both ES5 and ES3 genric implementations ... now please keep reading to know a bit of background :)


The JS Meaning Of Protected

JS developers know that in JavaScript properties are always public and that it is possible to attach/detach properties in any moment to a generic object. Regardless this fact, many libraries consider protected, by naming convention, all those properties whose name start with "_".


You Are Doing It Wrong

First of all I keep saying that is a common error trying to bring classical Object Oriented concepts into a completely different language as JavaScript is, but it does not matter ... we want protected stuff, right?
Due dynamic nature, the common protected meaning is pointless. See this example:

var obj = {
_name: "",
getName: function () {
return this._name;
},
setName: function (_name) {
this._name = _name;
}
};

getName and setName method are theoretically the only one able to change the _name property ... correct? Why, 'cause these are object methods ???

var obj.iCreateAnotherMethod = function (_whateverIWant) {
this._name = _whateverIWant;
};
obj.iCreateAnotherMethod(
"JS protected JOKE"
);

Now try to argue that a dynamic object with a dynamic associated method should not be able to perform the same operation setName does ...


At Least Do It Better!

All protected I have seen so far are quite prolix, inefficient, or pointless.
First of all, let's analyze the problem: what protected should be.
For protected we may consider all those properties or methods that should not be accessed directly but that can be accesses by public (or protected) methods of the same instance.
In few words, we would like to be sure that these properties are not easily accessible outside the object.


An ES5 Friendly Implementation



Object.defineProtectedProperty = (function (
defineProperty // from Object
) {
// (C) WebReflection - Mit Style License

// check that a caller is an object method
function check(object, caller) {
// this function accesses enumerable
// properties.
// returns instantly if check()
// was the property accessor
// (avoid recursion)
if (caller === check) {
return;
}
// avoid direct calls
// in the global scope
// ( or via apply/call )
if (caller) {
for (var key in object) {
if (
// the caller is a method
// ( property wrapper )
object[key] === caller
) {
return;
}
}
}
// if the method was not attached/inherited
// fuck up the execution with an error
throw "access denied";
}

// named expression (we like debugging)
return function defineProtectedProperty(
object, // the generic object
key, // the generic key
description // the ES5 style description
) {
// cache the value
var value = description.value;
// remove it since get/set + value
// does not make sense
delete description.value;
// define the getter
description.get = function get() {
check(object, get.caller);
return value;
};
// define the setter
description.set = function set($value) {
check(object, set.caller);
value = $value;
};
// define and return
return defineProperty(object, key, description);
};
}(Object.defineProperty));

Here some usage example:

// generic object
var o = {
greetings: function () {
this._sayHello();
}
};

// protected property
Object.defineProtectedProperty(
o, "_hello",
{value: "Hello World"}
);

// protected method
Object.defineProtectedProperty(
o, "_sayHello",
{enumerable: true, value: function () {
alert(this._hello);
}}
);

// method call
try {
o._sayHello();
} catch(e) {
alert(e); // access denied
}

// property access
try {
o._hello = "no way";
} catch(e) {
alert(e); // access denied
}

o.greetings(); // Hello World

The only thing to remember is that by default, enumerable is false so, if we would like to access a protected property inside a protected method, we must set it as enumerable so the for/in loop can discover it and verify it as object method.
Pros: compatible with all latest browsers, included IE9, with the only exception of WebKit and Safari (but I have already filed a bug there). It is possible to specify all defineProperty description, in this case except get and set.

Cons: not compatible with less recent browsers plus the check may cost if protected properties are constantly accessed. Address these properties once if it's needed to use them multiple time. Set them once as well if it's needed to change their value.


An ES3 Friendly Implementation

Here the version compatible with many other browsers, witohut the possibility to set ES5 properties such enumerable, configurable, and writable. It is also not possible to avoid a delete operation, which could cause problems.

Object.defineProtectedProperty = (function () {

// (C) WebReflection - Mit Style License

// check that a caller is an object method
function check(object, caller) {
// this function accesses enumerable
// properties.
// returns instantly if check()
// was the property accessor
// (avoid recursion)
if (caller === check) {
return;
}
// avoid direct calls
// in the global scope
if (caller) {
for (var key in object) {
if (
// the caller is a method
// ( property wrapper )
object[key] === caller
) {
return;
}
}
}
// if the method was not attached/inherited
// fuck up the execution with an error
throw "access denied";
}
return function defineProtectedProperty(
object, // the generic object
key, // the generic key
value // the generic description
// only value is considered
) {
value = value.value;
// define the getter
object.__defineGetter__(key, function get() {
check(object, get.caller);
return value;
});
// define the setter
object.__defineSetter__(key, function set($value) {
check(object, set.caller);
value = $value;
});
// return the object
return object;
};
}());

The same usage showed in the precedent example so that migration to ES5 version will be less painful.

Pros: compatible with almost all current browsers except IE family and WebKit/Safari due same bug reported before.

Cons: less secure than ES5 version since delete operation is allowed and properties then re-configurable. Other cons from ES5 version.


The caller Is Dead, Long Life to the Caller

In ES5 they keep removing powerful stuff considering all developers idiots unable to understand JS ... at least this is my feeling when I read things like "the with statement is dangerous" and "with 'use strict' caller should throw an error".
I don't really mind if they remove arguments.callee, we can always use function expressions (IE < 9 a part), but the genericFunction.caller is one of the most fundamental properties every function could possible have.
As instance, it wouldn't be even possible to think about my protected proposal without the caller, while internally all engines know who is the first level outer scope since they need it for variables resolution (e.g. when an inner scope uses an outer scope variable). Is this truly a performances issue? I don't think so, but I have not yet tested it so ... let's see ...


A Scoped Alternative For Every Browser

The only real private thing in JavaScript is a function scope, where this is private only from its outer scope, unless we don't hack it bringing there stuff via eval:

function toOuterScope($) {

var x = 1;

return eval($);
}

alert(toOuterScope("++x")); // 2
alert(typeof x); // undefined

Accordingly, the best way ever to ensure some sort of protection is to store properties into a private scope.
This is the alternative that works with every browser:

var scoped = (function () {

// (C) WebReflection - Mit Style License

// the only real private thing in JS
// is a function scope, like this one
// variables here are private/scoped as well
var
stack = [], // objects collection
id = [], // objects ids
n = -1, // object not found
// minifier shortcuts
indexOf = "indexOf",
push = "push",
splice = "splice"
;

// speed up the get(self, key)
// if indexOf returns -1 we don't care
// we return something from Object.prototype
stack[n] = {};

// ensure that outside nobody can change
// id or stack used Array.prototype methods
// (assignment rather than inherited chain)
id[push] = id[push];
id[splice] = (stack[splice] = id[splice]);
// for Jurassic browser implement a quick indexOf
id[indexOf] = id[indexOf] || function (value) {
for (var i = id.length; i--;) {
if (id[i] === value) {
break;
}
}
return i;
};

// unregister the object
// and all scoped properties
function clear(self) {
var i = id[indexOf](self);
if (n < i) {
id[splice](i, 1);
stack[splice](i, 1);
}
}

// retrieve the scoped property value
function get(self, key) {
// no shortcut to avoid lookup
// slightly better performances
return stack[id.indexOf(self)][key];
}

// set the scoped property value
function set(self, key, value) {
var i = id[indexOf](self);
if (n == i) {
stack[i = id[push](self) - 1] = {};
}
stack[i][key] = value;
}

// named function (we like debugging, don't we?)
function scoped(key, value) {
var
// verify who called the scoped function
caller = scoped.caller,
// improve minifier ratio
self = this,
// one var is enough, undefined is safer
property, undefined
;
// avoid direct calls
// e.g. obj.scoped()
// in a global context
if (caller) {
// loop them all
for (property in self) {
// check if object's method is the caller
if (self[property] === caller) {
// undefined or null key means clear(self)
return key == null ? clear(self) :
// value === undefined means get(self, key)
// otherwise means set(self, key, value)
value === undefined ?
get(self, key) :
set(self, key, value)
;
}
}
}
// if the method was not attached/inherited
// fuck up the execution with an error
throw "access denied";
}

// ready to go
return scoped;

}());

Above variable can be used as object property (method) or as prototype method without problems, and here we have some usage example:

// generic constructor
function F() {}

// scoped as prototype
F.prototype._scoped = scoped;
// getter
F.prototype.getProtected = function (key) {
return this._scoped(key);
};
// setter
F.prototype.setProtected = function (key, value) {
this._scoped(key, value);
};
// clear all scoped properties
F.prototype.clearProtected = function () {
this._scoped();
};

// generic instance
var f = new F;

// set protected
f.setProtected("test", 123);
alert(f.getProtected("test")); // 123

// re-set
f.setProtected("test", 456);
alert(f.getProtected("test")); // 456

// clear all
f.clearProtected();

alert(f.getProtected("test")); // undefined

// try to access scoped
try {
f._scoped();
//scoped.call(f, "whatever");
} catch(e) {
alert(e); // access denied
}

Less Magic With Methods

If we would like to reproduce initial code example, we should tweak the object in a weird way, e.g.


var o = {
_scoped: scoped,
init: function () {
var self = this;
self._scoped("_hello", "Hello World");
self._scoped("_sayHello", function _sayHello() {
self._sayHello = _sayHello;
alert(self._scoped("_hello"));
delete self._sayHello;
});
},
greetings: function () {
this._scoped("_sayHello")();
}
};

// call the init to set scoped properties
o.init();

try {
o._scoped("_sayHello")();
} catch(e) {
alert(e); // access denied
}

try {
o._scoped("_hello", "no way");
} catch(e) {
alert(e); // access denied
}

o.greetings(); // Hello World

This latest alternative is indeed ideal for properties but not methods.
Pros: compatible with basically every browser. No enumeration at all, detached properties.
Cons: not intuitive as other options. Properties must be set via init. We need to clear properties when we don't need the object anymore. Performances are not better than other options.


As Summary

Protected properties are closer here but still we should remember the runtime method that should logically be able to set a protected property ... this is JavaScript, not Java or C#, so probably we should be stuck with the idea that protected and private, in latter case scope talking a part, do not make sense and whatever we do can only decrease overall performances, too often granting a slightly better security.