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

Sunday, October 17, 2010

Pre Authorization Meta Tag Proposal

Under the HTML5 flag, browsers are bringing to our desktops or devices exciting features such GeoLocation, File, and many others such camera, microphone, system access, etc ...

The Problem

While this is good from possibilities point of view, the activation approach historically sucks. Flash and it's video or microphone activation shows a dialog that asks the user to authorize media access while browsers are lazily asking via JavaScript the same. The real life scenario we all know is definitively different when a page is using a screen reader, and this article and video about twitter UX should be enough to open our eyes: something is wrong.

Solutions

If we ever used an Android device, or we have download applications from whatever mobile store, we should be familiar with the installation warnings and confirmations we suppose to read and accept in order to grant application access to anything it needs to work properly.
This simply means that once we accept we won't be bothered anymore and the application can easily work as expected.
It's all about privileges and in my opinion it would be nice to have similar approach in our browsers as well, also to make web application even closer to native one.


Proposal

Following the "don't break the WEB" approach, all we could do is put a meta tag, as we do for viewports, specifying all those Technologies/API we would like to use in our webpage. This is an example:

<meta name="grant" content="GeoLocation,Camera" />
<meta name="grant" content="System" />

The proposal should ask at the very beginning and only once if the webpage could access these functionalities and the user can decide before what should be available and what should not.
The "before" action is important 'cause in this Ajax era it's extremely easy to loose focus runtime with whatever activation request and this is so wrong.
The list of granted API should be reachable via userAgent via specific method such:

navigator.hasGranted("GeoLocation")

or similar, so that eventually we can decide via JavaScript if we would like to ask again runtime, as we do now, or simply provide an alternative solution or message, maybe showing an "ask again to activate" button, remembering to put back the focus in the right context.

Alternative

Web developers could implement similar concept asking with the very first script access to one or more API and put the page focus back. With GeoLocation, as example, the user will chose immediately his preferences without having surprises in the middle of a session, or later.

// As Soon As Possible
var HAS_GEO_LOCATION = false;
try {
navigator.geolocation.getCurrentPosition(function (result) {
// so that other scripts could check if already available
HAS_GEO_LOCATION = true;
// notify the event in any case
var evt = document.createEvent("Event");
evt.initEvent("geolocationready", 1, 1);
evt.data = result;
// implicit window context
dispatchEvent(evt);
});
} catch(e) {}

A usage example could be something like:

// script loaded after a while ...

if (HAS_GEO_LOCATION) {
doFreakingCoolStuffWithGeo();
} else {
addEventListener(
"geolocationready",
doFreakingCoolStuffWithGeo,
false
);
}


We can eventually specify the handleError callback as well but actually this is part of the HAS_GEO_LOCATION value, if there is an error no reason to insist, simply assume that there is no geo location and go with the fallback, if any.

What do you think?

Friday, October 15, 2010

Technical Reviews: Bestsellers!

Just a quick one about two technical reviews out of two I have recently done for @stoyanstefanov and @cjno for these completely different books: JavaScript Patterns and Test-Driven JavaScript Development.

Right now these are both Top 10 Bestsellers and trust me: other JavaScript Jedis have been involved, you won't regret these lectures! ;-)



Tuesday, October 05, 2010

JavaScriptCore via Terminal

Just a quick one, maybe only for a new Mac comer as I am, I found truly annoying I have already Python, Ruby, and even PHP everywhere available in my command line but not JavaScript?

What The Fuck

Even Windows runs .js files natively and since ages, I wonder why on earth after I have downlaoded the whole XCode SDK "my JavaScript" was not there available for all my needs.

OK, OK, node.js is already on /bin, linked and working properly, but now I have the system default JavaScript Engine that comes automatically with WebKit or the "IE for Mac" aka Safari.

How to link jsc to bin folder

A title that produces zero outcome on Google, could be hopefully better addressed via this blog, and this is how I have solved:

sudo ln -F /System/Library/Frameworks/JavaScriptCore.framework/Versions/Current/Resources/jsc /usr/bin

The Current folde ris the link to the latest one, all those threads about the ..../A/... folder are not automatically updated if A becomes B, as example.
So, now I can type jsc wherever I am and use JavaScript power whenever I want, writing just quit() anytime I need.
I hope this helps, it took a while for me to sort it out.

Saturday, October 02, 2010

Apple UX Fails with Mac Mini

Update
Following Daniel suggestion (first comment), I have grabbed a cabled keyboard and a cabled mouse from a colleague and I have been able to finish the initial procedure. Happy to be a Mac Mini user now, it works like a charm!


as tweeted already, apparently there's no way I can buy a dishwasher. Last time I almost came back home with a pretty cool Samsung Blue Ray Player ... but I bought nothing, this time I did a mistake: I bought a Mac Mini.
The time my new Mac Mini has been switched on is no longer than 10 minutes, and right now I am still unable to use it ... and I would like to tell you the story ...

Nothing On The Package

It's clean and small, no requirements or dependencies specified anywhere. Being the package obviously close, I have not been able to RTFM.
The only thing I took care of was the absence of the HDMI cable ... not a big deal, I have bought one and this, at least, works like a charm!

Pretty Cool And Useless Gadgets

Wireless keyboard and wireless trackpad, these gadgets are a must have for my room configuration: a 32" LED Sony Bravia screen with Full HD capability and a comfortable (and cheap) sofa about 1 meter far away from the screen. The plan was perfect, the result still a disaster.

Totally Stuck On First Run



As you can see from this picture, there is nothing I can do. Trust me, both keyboard and trackpad are switched on, and the lovely King of Operating Systems is unable to recognize them and, for this reason, unable to let me use the consistent amount of money I have spent few minutes before.

Epic Fail

All Apple gadgets and products come ready and easy to use, this is a key for this company and the reason I gave up trying to avoid its products ... these are simply great.
I could never expect such problem using all official Apple/Mac stuff, and if this is a known issue either a marketing strategy (I should buy a mouse now, uh? I won't!) it's a massive hole in the whole UX excellence we think when we talk about Apple.
Please put massive cubic labels over each Mac Mini saying: without our mouse, you can't do anything!

wru against wru: version 1 ready

This shot has been token on 13th September 1923, when W.H. Murphy demonstrated the efficiency of his bulletproof vest, the one that sold later to NY Police Department.

Above image has been historically used for different topics and the current one is "how much we trust what we sell".

Do You Trust Your UT Framework?

I wasn't kidding that much when I wrote about "test the testing framework" in my precedent wru post. The overall Unit Test Frameworks code coverage is poor, specially those with all the magic behind the scene, magic that does not come for free.

Use The Framework Itself To Test The Framework

This is a common technique that may result in a reliability deadlock. If we trust our UT Framework and we use it to test itself, the moment we have a problem with the framework we'll never know ... or even worst, it will be too late.

Don't Trust "Magic" Too Much

If the framework is simple and it does not pollute each test with any sort of crap, we can surely use it to test the framework itself without problems while if this framework elaborates and transforms our tests, it may become impossible to test it via the framework itself due scope and possibly context conflicts for each executed test.
This may produce a lot of false positives for something in place theoretically to make our code more robust.

The wru KISS approach

With or without async.js, wru does few things and now it's proved that it does these things properly. I don't want to spend any extra time for a library that I should trust 100% and if I know that all things this library should do are working as expected, I can simply "forget to maintain it" (improve, eventually) and use it feeling safer.

99.9% Of Code And Cases Coverage

Loaded on top of whatever test, wru uses few native calls and the assumption is that these are already working as expected (accordingly with ES3 or ES5 specs).
The new wru test against wru covers all possible tests combination, where setup and teardown could fail on wru itself or for each test, and assert should simply work in a test life-cycle. This means we could assert inside setups and teardowns as well, simply because these calls are fundamental for a single test and, if present, must be part of the test result. A problem in a setup could compromise the whole test while a problem in a teardown could compromise other tests. Being sure that nothing went wrong is up to us but, at least, we can do it via wru.

Can you do the same with your UT Framework? Do you have the same coverage? Have fun with wru ;)

Tuesday, September 28, 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.

Monday, September 27, 2010

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 ;)

@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!

Sunday, September 26, 2010

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 09, 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.

Friday, August 20, 2010

Object.defineProperty ... but Strict!

In my precedent post entitled A Pascal record via JavaScript I have showed a basic function able to emulate type hints behavior via JavaScript.
Even if that was a proof of concept, I consider other languages simulation of unsupported features an error, first of all because the behavior will rarely be exactly the expected one, secondly because our curent programming language may already have something similar to better learn and use.

A new ES5( direction )

As soon as I have written the Pascal example, I have realized that the good "old" Object.defineProperty, implemented in all major browsers (IE < 9 sucks, you know that ...), has basically the same meaning: define object accessors.

The only missing part, intrinsic in the JavaScript nature, is the property type, where this type could be eventually used for arguments or returns checks when the property is a method.

My Early Attempts

Back in May 2007, my JavaStrict experiment was already trying to do something similar, something implemented after 2 years even in dojo framework as well.
This may tell us that "somebody" would really like to put this kind of checks on daily code, even if performances cannot obviously be the best possible one.

Production VS Deployment

Keeping always in mind that performances matter, the new little monster I am going to show here can be flagged with a boolean, nothing different from:

Object.defineStrictProperty.production = true;

Once in place, the whole logic will switch from "strict type" to "free type" and the used function will be the native Object.defineProperty respecting basically the same behavior.

Object.defineStrictProperty / ies

I have put the code in devpro.it, while I am going to show how it works here.

How to declare a type

Next piece of code is the most basic usage of this method.

var myObject = Object.defineStrictProperty({}, "name", {
type: "string"
});

myObject.name = "it's a me!";

alert(myObject.name);

myObject.name = 123;

// throw new TypeError("wrong type");
//
// console.log =>
// Object
// > expected: "string"
// > received: 123



The meaning of "type"

The type property can contain any of these values:
  • string, where the check will be performed against the typeof value (e.g. "string", "number", "boolean", etc)

  • function, where the check will be performed against the value instanceof type (e.g. Function, Object, Array, Date, etc)

  • object, where the check will be performed against the type.isPrototypeOf(value) (e.g. Array.prototype, others ...)

The only exceptions are null and undefined.

How to declare a returned value

If the property type is "function" or Function there are other extra properties we could define such returns and arguments. Here there is a returns example:

var myObject = Object.defineStrictProperties({}, {
name: {
type: "string",
value: "it's a me!"
},
toString: {
type: "function",
returns: "string",
value: function () {
return this.name;
}
}
});

alert(myObject); // it's a me!

myObject.toString = function () {
return 456;
};

alert(myObject);

// throw new TypeError("wrong return");
//
// console.log =>
// Object
// > expected: ["string"]
// > received: 456


Multiple returns

Since JavaScript is dynamic, there is nothing wrong, logic a part, into different returns. To make it possible we simply need to specify an array with all expected types.

// precedent code with this difference
...
toString: {
type: "function",
returns: ["string", "number"],
value: function () {
return this.name;
}
}

// precedent example won't fail now


How to declare expected arguments

Similar returns concept applied to arguments, so that we can specify a single argument type, a list of arguments type, a list of arguments. Here the difference:

...
setName: {
type: "function",
// checks if a single argument
// with typeof string has been sent
arguments: "string",
// same as above
arguments: ["string"],
// checks if two arguments
// with typeof string and number
// has been sent, order matters!
arguments: ["string", "number"],
// checks if one argument
// with typeof string OR number
// has been sent
arguments: [["string"], ["number"]],
value: function (name) {
this.name = name;
}
}
...

The number of arguments and relative overload per call is arbitrary. As example, we could have a method defined with these arguments without problems.

// generic object for Ajax calls
...
get: {
type: "function",
returns: "string",
arguments: [["string"], ["string", "string", "string"]],
value: function (uri, user, pass) {
this.open("get", uri, false, pass && user, pass);
this.send(null);
return this.responseText;
}
}
...

With a simple logic like that we can "enforce" the program to send one argument or three when, if three, all of them will be checked as strings.

Unlimited arguments

We may decide that the first argument is the only one we would like to check. Well, in this case we can simply create a group of allowed types and ignore the rest.
The arguments logic should be flexible enough due JavaScript nature where overloads can only be simulated via number or tye of arguments checks.

Getters and Setters

The whole logic behind is based on get/set property descriptor, where a nice fallback to __defineGetter__ or __defineSetter__ will be used when Object.defineProperty is missing.
This means that we can describe properties the same way we could do via Object.defineProperty, using enumerable and others as well to make the whole code gracefully degradable when the production flag is set to true.

As Summary

Unless developers won't be interested into this approach, I think this method is basically complete as is and we can use it at own risk.
The whole script stays in about 870 bytes minified and gzipped, not a big deal for what it offers.
In any case, I am looking forward for your feedback!

Wednesday, August 18, 2010

A Pascal record via JavaScript

... all right, I am off for holidays and I won't have probably time to write the post I have twitted a few days ago since it could take a whole day ... however, I am "cleaning" my good old room here in Italy and I have found an Italian book titled "ALGORITMI IN PASCAL" (Pascal Algorithms) a back in 1987 IT book for secondary school.

I could not resist to read it entirely, just to see what kind of Algo I could have found there ... but "surprise", it was not about algos, more about (T)Pascal itself.

Since at the of the day Pascal is somehow the basis for all we can write today, I thought it would have been a nice experiment to try to reproduce the record concept via JavaScript.

What Is a Record

Nothing different from a predefined structure of types, similar to a classic literal object in JS except the structure defines type hints.

// simple Pascal function example
function personToString(self:person);
begin
writeln(self.name, ' is ', self.age, ' years old')
end;

// basic record example
type person = record
name:string[20];
age:integer
end;

// record usage
var me:person;

begin
me.name := "Andrea";
me.age := 32;
personToString(me)
end.

Please note I don't even know if above program will ever run so take it just as an example.

Record VS Prototype

As we can see the record is not that different from a "class" description via prototype, except rather than values we can specify the type of these values.
This approach may be handy even in JavaScript since there is no type hint but sometimes we may desire to make some behavior consistent and hopefully safer.

A first JavaScript record example

Using some ES5 feature, we could be able to write something like this:

function record(description) {
// (C) WebReflection - Mit Style License
var
shadow = {},
self = {}
;
Object.keys(description).forEach(function (key) {
var
type = description[key],
check
;
if (!type) {
throw new TypeError("unable to check a type for property: " + key);
}
switch (typeof type) {
case "string":
check = function (value) {
return typeof value == type;
};
break;
case "function":
type = type.prototype;
default:
check = function (value) {
return type.isPrototypeOf(value);
};
break;
}
this(self, key, {
get: function () {
return shadow[key];
},
set: function (value) {
if (!check(value)) {
throw new TypeError("type violation for property: " + key);
}
shadow[key] = value;
},
configurable: false
});
}, Object.defineProperty);
return self;
}

Here a basic usage example for above function:

var person = record({
name: "string",
age: "number",
toString: Function
});

person.name = "Andrea";
person.age = 32;
person.toString = function () {
return this.name + " is " + this.age + " years old";
};

alert(person);
// Andrea is 32 years old

Following the same concept we may decide to add arbitrary types and relatives checks such "integer", "real", or whatever we need.
Here there is a version compatible with almost all browsers but IE:

function record(description) {
// (C) WebReflection - Mit Style License
function getter(key) {
return function () {
return shadow[key];
};
}
function setter(key) {
var
type = description[key],
check
;
if (!type) {
throw new TypeError("unable to check a type for property: " + key);
}
switch (typeof type) {
case "string":
check = function (value) {
return typeof value == type;
};
break;
case "function":
type = type.prototype;
default:
check = function (value) {
return type.isPrototypeOf(value);
};
break;
}
return function (value) {
if (!check(value)) {
throw new TypeError("type violation for property: " + key);
}
shadow[key] = value;
};
}
var
shadow = {},
self = {}
;
for (var key in description) {
if (description.hasOwnProperty(key)) {
self.__defineGetter__(key, getter(key));
self.__defineSetter__(key, setter(key));
}
}
return self;
}


Record And Prototype Problem

Unfortunately we cannot use this strategy to create constructors prototypes since the shared object (singleton) will use a single shadow for every instance.

function Person(name, age) {
this.name = name;
this.age = age;
}

Person.prototype = record({
name: "string",
age: "number",
toString: Function
});

Person.prototype.toString = function () {
return this.name + " is " + this.age + " years old";
};

var me = new Person("Andrea", 32);
var other = new Person("unknown", 29);

alert(me); // unknown is 29 years old

To avoid this problem we should use return this["@" + key]; in the getter and this["@" + key] = value; in the setter, setting if possible the property as enumerable:false if we have an ES5 friendly environment.
This should make the trick but still there is something not that friendly for JS developers.

A Proper JSRecord


A more flexible approach would let us define at the same time both type and default value, so that prototype definition and type hint could be done in one single call.
How could we write something similar? Here my last revision (done while I was writing this post):

function JSRecord(description) {
// (C) WebReflection - Mit Style License
var
self = {},
cDONTwe = {configurable: true, writable: false, enumerable: false},
hasOwnProperty = self.hasOwnProperty,
defineProperty = Object.defineProperty
;
Object.keys(description).forEach(function (key) {
var
current = description[key],
type = hasOwnProperty.call(current, "type") ? current.type : current,
enumerable = hasOwnProperty.call(current, "enumerable") ? current.enumerable : true,
$key = "@" + key,
check
;
if (!type) {
throw new TypeError("unable to check a type for property: " + key);
}
switch (typeof type) {
case "string":
check = function (value) {
return typeof value == type;
};
break;
case "function":
type = type.prototype;
default:
check = function (value) {
return type.isPrototypeOf(value);
};
break;
}
defineProperty(self, key, {
get: function () {
return this[$key];
},
set: function (value) {
if (!check(value)) {
throw new TypeError("type violation for property: " + key);
}
cDONTwe.value = value;
defineProperty(this, $key, cDONTwe);
},
configurable: false,
enumerable: enumerable
});
if (hasOwnProperty.call(current, "value")) {
self[key] = current.value;
}
});
return self;
}

How things changed:

// we can have defaults
function Person(name, age) {
this.name = name;
if (age) this.age = age;
}

// we can define a type hint
// or we can define both hint
// and value plus enumerable

Person.prototype = JSRecord({
name: "string",
age: {
type: "number",
value: 0
},
toString: {
enumerable: false,
type: Function,
value: function () {
return this.name + " is " + this.age + " years old";
}
}
});

// we can test everything now
var me = new Person("Andrea", 32);
var other = new Person("unknown");

alert(me); // Andrea is 32 years old
alert(other); // unknown is 0 years old

alert(me instanceof Person); // true

for (var key in me) alert(key);
// name, age

What do you think? Here my partial list of pros and cons:

Pros

  • easy type hint implementation
  • safer objects, properties and methods
  • usable as record or prototype without shared vars problems


Cons

  • requires ES5 compatible environment
  • getters and setters are slower than direct access due function overload
  • type hint is slower due checks for each set