Once again, not everything is wrong with TypeScript, but this is how I have really felt as soon as I have heard about this yet another JS superset and after a quick analysis through examples.
behind the design
My JavaScript book is out!
Don't miss the opportunity to upgrade your beginner or average dev skills.
Friday, October 12, 2012
All Right, Gentlemen!
... this is after my latest post, just to summarize with a bit of humor my thoughts on developers getting easily excited with new stuff :D
Once again, not everything is wrong with TypeScript, but this is how I have really felt as soon as I have heard about this yet another JS superset and after a quick analysis through examples.
Once again, not everything is wrong with TypeScript, but this is how I have really felt as soon as I have heard about this yet another JS superset and after a quick analysis through examples.
Thursday, October 11, 2012
JavaScript Made Everyone Crazy
Nobody seems to be happy, nobody seems to understand it ... everyone is trying to change it, pretending to make it better ... and again, nobody seems to realize it has been here since ever, it has been working in any field, it does everything, and it keeps getting faster!
One Scripting To Rule Them All
As simple as that: Dart compiles into JavaScript so does Java, CoffeeScript, C, C++ and any LLVM compatible/compilable language via Emscripten ... and now TypeScript too ... how cool is that? As tweeted before, if every programming language can be basically translated into JavaScript which is already an extremely high level scripting language, don't ya think that maybe is not exactly JavaScript the problem ? Don't ya think maybe it's time to learn it rather than keep moaning about it ? Hasn't this language already demonstrated to be one of the most malleable, powerful, adaptable, reusable, recyclable, expressive out there ? So why everyone is trying to pretend this language is not good? Why everybody wants this language to be something nobody needed until now or something that different?What Is Wrong With TypeScript
I don't know where to start here ... but I'll try to make few points based on examples, OK? Please bear with me, you'll get it too.Type Inconsistencies
Ironically, this is the very first point. Consider these two functions:
// note that string is written lowercase
function primitive(s:string):void {
console.log(s);
}
// note that String is written PascalCase
function wrapper(s:String):void {
console.log(s);
}
Now, with this "revolutionary brand new language" I ask you two simple questions and you should be able to answer me without testing, OK?- will this call produce an error?
primitive(new String("")) - how about this one?
wrapper("")
string accepts primitives only, those that typeof(s) === "string" but String accepts both primitives and wrappers ... so basically, the most basic problem about JS is still there and developers are not encouraged to understand the difference between new String and just "string", they will put String everywhere feeling like they know what they are doing ... they are using classes ... WOOOOOOOW!
Even more funny is the usage of bool rather than boolean, so that even what you know about JS does not work anymore ... so I guess Bool would be at least available, right?
The name 'Bool' does not exist in the current scopeExactly,
Boolean is the wrapper for bool: congrats!
What do you say? It was to speed up typing? ... that's why you wanted types, to write less? ... wait ... what?
Fake Security
If you believe that typed code means better code quality, you are wrong. Typed code usually means that the developer knows types in advance ... that's pretty much it. In this attempt, where code is not resolved runtime, only types are, the feeling you are safer than before is natural ... well, you are not
function wtf(s:string):number {
return s.charCodeAt(0);
}
Above function contract is extremely simple for both input and output ... too bad TypeScript cannot do much when it comes to calling the function, understanding that maybe that input has no char in index 0 so that wtf("") will produce a lovely NaN able to screw the rest of the logic because guess what ... NaN is considered a number: congrats again, another problem kept with TypeScript!
Anyway, the latter example shows that it does not matter if input and output types are OK, it matters the logic. The fact String#charCodeAt returns a number does not mean that using it is safe. Same thing is with function s(o:Object):string {return o.toString();} which can easily fail with an object created through a null prototype, you know what I mean?
This cannot be solved during translation time ... sorry for that!
Getting Worst On Security
In order to maintain decent performances, TypeScript tries to translate potatoes in potatoes ... which means, not too much magic, neither 17.000 lines of JavaScript are needed to simulate something JS is not, bothES3 and ES5.
This time, I am talking about private attribute in classes and here an example:
class Point {
// private they say ...
private test:bool = false;
constructor(
public x:number,
public y:number
) {}
method():number {
return this.x * this.y;
}
}
class ColoredPoint extends Point {
constructor(
x:number,
y:number,
public color:string
) {
super(x, y);
}
method():number {
return 2 * super.method();
}
}
What I am going to show you, is the demonstration that private in TypeScript is the last thing ever you can rely on:
// a lovely colored point var cp = new ColoredPoint( 10, 10, "test" ); console.log(cp.color); // test // accessing the private property // from an extend, so not from the // class it has been defined private console.log(cp[cp.color]); // false // setting the private property cp[cp.color] = true; // funny enough, this would be the same cp["test"] = true; console.log(cp[cp.color]); // trueEt voilĂ , mesdames et messieurs,
private in TypeScript is and will always be a lie, for the simple reason JavaScript is that highly dynamic language you don't want to learn which is highly dynamic indeed. If you know JavaScript, you know also how to make things truly private when necessary ... in a much more reliable, secure, and meaningful way than what is offered here.
Repeated History? This kind of attack to private properties,obj.pvtVSobj["pvt"], was possible with ActionScript 2 as well ( damn it ... was it 2003 or 4? can't remember ). Adobe in that case did something similar TypeScript, Dart, or CofeeScript are trying to do to JavaScript but with ActionScript 1: it added sugar on top that was giving nothing to the language. This was because AS1 could already represent basically everything AS2 was able to do (AS2 was based on ECMAScript 4 same as C#, Silverlight, Air, and AS3). Moreover, AS2 has never been safer, better, smaller, or faster. It has been actually an epic fail since it has been replaced by AS3 the year after which was incompatible with AS1 and the reason I have abandoned Flash development: nothing better, just more pain in the ass! Cross platform problems were still there but a whole new language and namespaces to learn ... WOHOAW, and goodbye! ActionScript 1 has been a great product and it was 99% like JavaScript. This language that made Flash the most powerful and popular plugin ever changed, and the plugin is slowly dying since that time indeed ... I hope JavaScript won't do the same because for more than 12 years it has been just awesome and is still there, today more than ever, catching up with everyday modern/real-world challenges and without a glitch!
Translated Parent Accessor
One thing TypeScript got right about classes! Thanks gosh it did not attach anything to the prototype or each instance suchthis.super() and similar bullshit ... well done! But suddenly, "le wild WTF appears": super in the generated JS code, is the function, the constructor, and not the prototype, so that any super.methodName() call is translated into ParentFunction.prototype.nethodName.call(this)!
This means that every super call will perform two lookups and will not ensure that the parent prototype cannot and should not be redefined runtime ... is that what TypeScript would like to be compatible with? I hope no ... so that constructor a part, in this way, every method of every class is penalized with performances and only the constructor has direct access: potentially O(methods * eachClass) rather than just O(classes) prototype lookups.
The Increased Performance Myth
The funny thing about TypeScript, is that basically the only real and concrete advantage of typed languages, the cost free and great improvement performance speaking, is completely absent. Not only all these typed checks are performed during translation and never again, but the tiny abstraction of the syntax requires more code than needed, as more closures than needed, as more memory, operations, function calls than needed so, in few words, performance is worst than before. OK, is not as bad as the whole Dart library moved in mobile devices, but still slower than good old JavaScript with or without common, well known, libraries.No Benefits At All
After this analysis of "the latest coolest hybrid version of JavaScript", I believe things are clear:- more to write because of types (that's OK), more to learn, because of a new behavior specified in a 0.8 draft (that's not OK)
- no concrete advantages over common JavaScript and its well known shenanigans: DOM still a mess, wrapper VS primitives, undefined and null or NaN, operators and other stuff too ... just YAGNI sugar that supposes to make us happy and dunno why
- new shenanigans as it is for every bloody programming language ... so we have to be careful with both TypeScript and double check the equivalent generated JavaScript to be sure things are OK and as expected for real: double learning, OMG!
- performance is worst ... maybe JIT compilers could somehow take advantage of TypeScript generated code but I don't think so plus is more code than needed as it is for every translator: not optimized, rarely faster
- we can have mapped source code with TypeScript, we cannot have double mapped source code to understand errors if we would like to chose a different minifier over the TypeScript generated JS code
- more I haven't talked about ...
Not All Wrong Neither
I know this post looks like I am throwing stones to MS intent and effort over this TypeScript tool / thing / language / proposal / whateveritis but I am not, I swear. I love the direction Microsoft is taking since IE9 but I have also said, and it wasn't just me, that the Web needs something else which is not sugar. Cool tools for debugging are all welcome ... new tools for something that does not solve a thing are a waste of time. We would like tools to make the Web better for every browser, faster for every CPU, graphically shiny for every screen ... classes for massive apps won't help anyone to make this happen and we all have the proof today that JavaScript never needed classes to scale, what we need are developers that know the language, use it properly, and move the web forward, rather than being stuck with sugar and sugar and sugar and sugar ... IMHO!Everyone Is Crazy
Scripting Languages suppose to be easy, expressive and powerful, and JavaScript is one of them. The fact it has no classical inheritance is driving people crazy since ever: they need classes, that seems to be the only way they can think programming ... meanwhile, we all created what is the Web today and is far away from perfect but it's a great place and it's getting better on daily basis. Look what has been done ... think if strict types and classical OOP was the missing thing ... look again, and now move forward with your next, awesome, JavaScript based thing that will simply work everywhere and will satisfy your expectations! Thanks for reading, appreciated.Friday, September 21, 2012
Web Viewport Size
if you ever had to deal with the full size of an HTML document, I know that feeling bro!
What basically every single Web app is doing wrong right now, is to increase the full screen size by those (in)famous 60 pixels so that after they can call
The Most Difficult Thing To Get Right Ever!
I mean, even google maps had some problem with that, preferring a user agent sniffing like technique rather than finding the real size of the window. This image is directly from latest Maximiliano Firtman post, a post you should read regardless this single topic!The Useless window.screen
The object you might decide to check for is completely pointless for this purpose ... and the reason is simple: screen does not give any meaningful number to the Web field. The size of the screen in pixel means nothing when the viewport meta tag is set to scale 1, as example. The size means nothing in any case since it's about the full size of the screen and not the current DOM, viewport, window, size. TheavailWidth/Height property isn't that trustable neither, URL bar on the top or on the bottom, or both, could be in place ... how you gonna deal with that ...
Not only screen Problems
The webOS browser is a freaking cool one and still more recent than many other Webkit stock browsers stuck in some android 2.3.something ... so why would you drop webOS support now? Most likely, is gonna be just another slice of compatible devices you gonna have in your portfolio. Well, webOS, and I am talking about Palm Pre 1 and 2, has an horrible bug: you change orientation, things start zooming in and out out of control ... WHY??? Gosh it tok a while to understand how to fix it ... still no idea "why" thought!Full Screen and iOS 6 safari Mobile
Problems ain't solved with latest Apple Operating System, actually ... problems are more than expected. The new 'full screen" feature provided by iOS6 does not obviously fire the"orientationchange" event, it fires "resize" one once in full screen and does not fire a thing once it goes back ... here again google maps trusting user agent sniffing like based approach:
How lovely is that massive, wasted, white rectangle at the bottom ?
window.scroll(0, 0); ... well, all these software must be updated in order to understand that full screen, does not mean navigator.standalone neither means that the height of the document should be increased by 60 ... got it?
IE 6, 7, 8, and 9 Mobile WTFucks!!!
Best part is about these browsers ... specially the mobile one, at least in my Samsung WP7 Omnia Phone, I had to decrease the height by 75 pixels when in portrait, and 5 pixels while in landscape ... and that was completely random but ... you know, it worked :D For all other Desktop IE < 9 versions well ... many fixes and shit about scroll bars but hey ... I don't care, I think I have solved almost everything!The Test Case
Well it's kinda simple, you check this page, and you see a 1 red pixel as full screen border no matter what Mobile or Desktop browser you are using ... it should just work and please let me know if it does not, thanks!The Module
It's part of a repository I am keeping updated with completely random, but tested, stuff ... here it is, a 1.57KB (843 bytes gzipped) piece of code that could make your full screen life much easier, isn't it?How Does It Work
Well, theindex.html source code should give you some hint but here the basic:
window.addEventListener("viewportsize", function (e) {
// here you change what you want
// the 'e' object will have a 'result' property
// containing width and height, e.g.
myCanvas.width = e.result.width;
myCanvas.height = e.result.height;
}, false);
Above example will make your canvas full screen no matter which device is running it .. aint that cool!
Freaking Flicking
Oh well, unfortunately to avoid problems in many good old Androids and webOS, plus Windows Phones too, the hidden body is necessary. Just try to imagine and consider that switching between landscape and portrait orientation is not such common thing ... usually that's performed when there's something wrong with the layout so ... you rather improve your layout skills here ;)Android URL Bar
Yeah, I don't care ... I mean, Android phones have bigger screens than iPhone and iPod, so if iphone full screen once pinned is enough, Androids phones are OK as they are too. Thing is, ther eis no standard between stock and non stock browsers with the URL bar size so, rather than guessing or thinking cool, it's this Android, must go for N pixels I prefer focus actually only on those Androids phones that eventually have really no space at all, in therms of pixels, to show something meaningful. Small screens are welcome for tests and debug, Galaxy S3 with full screen option .. YAGNI!Why Is This Important
Well, I guess if you reached this part you know already but here the thing ... sometimes you don't want the browser to scroll, the body to grow, your app to be unmanaged by the default browser scroll system, your game to be moved around, your designe to not be full screen ... did I forget anything here? :) Have fun with full screen Web Apps and please let me know if your device doesn't work, thanks!Wednesday, September 12, 2012
wannaqu.it - one button web app to track activities
This is a truly simple web application I am still improving but I believe it's ready to be tested for all of you :)
The purpose of this app is to track an activity.
First of all, if you want to take full advantage and be able to use this app offline, pin it into your Home and you'll be free by network problems forever.
That's correct, there is nothing, absolutely nothing stored online ... it's your data, it's you tracking it ... no magic behind and 100% anonymous.
The graph is based on absolute time, rather than relative, and it keeps changing over the week, hours, month.
The goal of your activity is to reduce it to zero so ... a good graph, is a graph that does not exist.
This is if you really want to quit, otherwise you can play with your data without problems.
Well, this graph should never give you the illusion you are doing OK ... which means, at midnight, there's no way you gonna have a fresh new clean column ... no, the purpose is to reduce, and to reduce over the time.
This time, your last 24 hours, is considering all those cigarettes ... deal with that, it's you smoking!
Happy WebApp, and take care!
wannaqu.it
The purpose of this app is to track an activity.
First of all, if you want to take full advantage and be able to use this app offline, pin it into your Home and you'll be free by network problems forever.
That's correct, there is nothing, absolutely nothing stored online ... it's your data, it's you tracking it ... no magic behind and 100% anonymous.
How Does It Work
As easy as that: you press the button once when you do something. By default, something is smoking, but it could be drinking or really, anything else you can imagine.How To Read Data
The graph will look weird at the very beginning ... well, you have to feed your own data in a meaningful way so it takes a while ...The graph is based on absolute time, rather than relative, and it keeps changing over the week, hours, month.
The goal of your activity is to reduce it to zero so ... a good graph, is a graph that does not exist.
This is if you really want to quit, otherwise you can play with your data without problems.
Why Absolute Time
Let's imagine you really would like to cut down cigarettes, OK? Now, it's Friday, 11:55pm, you had already few drinks, and you have a cigarette. Surely over a night out that graph will increase, you know it's true ... right?Well, this graph should never give you the illusion you are doing OK ... which means, at midnight, there's no way you gonna have a fresh new clean column ... no, the purpose is to reduce, and to reduce over the time.
This time, your last 24 hours, is considering all those cigarettes ... deal with that, it's you smoking!
What If I Cheat
This is your problem, I cannot help if you cheat your same data, sorry.Does It Work
I don't know ... I quitted smoking last Friday and I am pretty happy to have a clean graph ... but I swear I have tried to cut down before and every week end was again a mess ... so yeah, the best way to quit, is just quit I guess, but if you want to try cutting down and see if that works for you, now you have the easiest way ever to do it :)Happy WebApp, and take care!
Wednesday, September 05, 2012
A Meaningful Client Side Alternative To node require()
TL;DR
Here you have the solution to all your problems ... no? So take a break, and read through :)Current Status
Using a generic "module loader" for JavaScript files is becoming a common technique, and full of wins, not only on the node.js server side. There are different client side alternatives, not entirely based over the module concept, and apparently only one concrete proposal, called AMD, able to work in both server and client following a build/parsing procedure.However, as somebody pointed out already ...
AMD is Not the Answer
This post does not even tell everything bad about AMD problems, and I am getting there, but it's surely a good starting point.Tobie article is another resource that inspired somehow what I am going to propose here, so before discriminating this or that technique, I hope you'll find time to understand the whole problem ... found it? Let's go on then :)
The Beauty Of node.js require Function
I don't think I should even spend many words here ...
// module: compress
// in the global scope, it's just a module
// so no pollution to the global/window object
// no need to put everything in yet another closure
var fs = require("fs");
// just as example
this.compress = function (file, fn) {
fs
.createReadStream(file)
.pipe(
// check this out!
require("zlib").createGzip()
)
.pipe(
fs.createWriteStream(file + ".gz")
).on("close", function () {
var content = fs.readFileSync(file + ".gz");
fs.unlinkSync(file + ".gz");
fn(content);
})
;
};
So basically, with a synchronous
require(module) call we can decide whenever we want where that module should be included in our logic. This means we don't need to think in advance to all needed dependencies for our current module, as well as this doesn't require to split in many nested functions our asynchronous logic.Look at above example ... in node world the
require("fs") is performed basically in every single module ... the FileSystem is that important, hell yeah!We dont' care much about requiring it at the very beginning of above stupid module 'cause surely that operation will cost nothing! Each module is cached indeed so there's actually zero impact if we use a require hundreds of time inline ... really, it's that fast, but the very first one might cost a bit.
This is why
require("zlib") is loaded only once, and only when it's needed ... so that memory, disk, cpu, and everything else, can live in peace before the very first call of that exported method while after that, that call will cost again nothing.Is a mandatory nested function call through AMD logic as fast as above example? I tell you, NO, but this is not the real problem, is it?
AMD Does Not Truly Scale
... as simple as that. If you need a build process behind something that could fail in any case, I would say you are doing it wrong. I am talking about current era, where internet connection could be there or not ... I am talking about mobile and I give you a very basic example.I have created my freaking cool website or webapp that loads asynchronously everything and I am on the road with my supa-dupa smart phone.
When "suddenly, le wild spot without internet coverage appears"!
Now I press that lovely button in the lovely application that loads asynchronously the lovely next part of my action and guess what happens ... are you there? Nothing!
That instant without my mobile network will screw up my flow, will break my action, will let me wait "forever" and in most common cases, it will block me to use properly the app.
Of course, if that action required server side interaction, that action won't work in any case ... but how come I don't even see a notification? How come pieces of my application are not showing up telling me that there is actually a problem, rather than letting me wait without any notification, 'couse probably even notification logic was created as AMD module?
And what if connection is simply bad? The whole application or website is responding decently but that part, oh gosh how much I was planning to use that app part, is taking ages to load! How would you feel in front of such program?
AMD Resolves Lazy/Circular Load Synchronously
That's correct ... gotcha! Have you ever read what you should do in order to resolve modules that load asynchronously other modules inside themselves?
//Inside b.js:
define(["require", "a"],
function(require, a) {
//"a" in this case will be null if a also asked for b,
//a circular dependency.
return function(title) {
// me: Excuse me ... WUT?
return require("a").doSomething();
}
}
);
So here the thing, if "by accident" you have a circular dependency you should use
require() as node.js does ... oh well ...On Circular Dependencies / Cycles
This topic is one of the biggest paradox about programming ... we try to decouple everything, specially when it comes to write modules, so that not a single part of the app should be aware of the surrounding environment ... isn't it? Then someone said that circular dependencies are bad ... but how come?Here an example, a truly stupid one:
Hi, I am a human, the human module, and I am completely sufficient, but I need to go in a place that would take too much by my own ... so I need the module car.
Hi, I am a car, the module car, and I am fabulous by my own, but I need the module human to be able to go somewhere.
A partner, better than a car, could also explain the fact we actually think in circular references all the time ... am I wrong?
The AMD take in this case is that "we should change the require logic when this happens and we should be aware in advance in order to solve this" ... yeah, nice, so now in AMD we have two ways to require and return what we export ... and once again, in my humble opinion, this does not scale ... at all!
Double Effort, Double Code!
With AMD we don't only need to change our AMD code/style/logic when things are not known in advance, as showed before ... we also need to write code for modules that is not compatible with node.js, resulting in such piece of redundant code that I believe nobody truly want to write more than once in a programmer life.Take an excellent library as lodash is, and check what it has to do in order to be compatible with AMD too ...
// expose Lo-Dash
// some AMD build optimizers, like r.js, check for specific condition patterns like the following:
if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
// Expose Lo-Dash to the global object even when an AMD loader is present in
// case Lo-Dash was injected by a third-party script and not intended to be
// loaded as a module. The global assignment can be reverted in the Lo-Dash
// module via its `noConflict()` method.
window._ = lodash;
// define as an anonymous module so, through path mapping, it can be
// referenced as the "underscore" module
define(function() {
return lodash;
});
}
// check for `exports` after `define` in case a build optimizer adds an `exports` object
else if (freeExports) {
// in Node.js or RingoJS v0.8.0+
if (typeof module == 'object' && module && module.exports == freeExports) {
(module.exports = lodash)._ = lodash;
}
// in Narwhal or RingoJS v0.7.0-
else {
freeExports._ = lodash;
}
}
else {
// in a browser or Rhino
window._ = lodash;
}
Now ... ask yourself, is this what you want to write for every single module you gonna create that might work in both server and client side?
Combined AMD Modules
Here another possibility, super cool ... we can combine all modules together into a single file: YEAH! But if this what you do for your project, don't you wonder what is the point then to use all those "asynchronous ready" callbacks if these will be executed in a synchronous way in production? Was that different syntax truly needed? And what about JS engines parsing time? Is processing the whole project at once in a single file a good thing for both Desktop and Mobile?Why are you developing asynchronously with all those nested callbacks if you provide a synchronous build? Is the code size affected? Does all this make any sense?
AMD, The Good Part... Maybe
OK, there must be some part of this logic that conquered many developers out there .. and I must admit AMD "solved with nonchalance" the fact JavaScript, in the client side, has always had problems with the global scope pollution.The fact AMD forces us to write the module inside a function that receives already arguments with other needed modules, is a win ... but wait a second, wasn't that boring before that nobody until now wrote a single bloody closure to avoid global scope pollution?
I think AMD is a side effect, with all possible noble and good purpose, of a general misunderstanding of how is JS code sharing across libraries.
Let's remember we never even thought about modules until we started clashing with all possible each other polluting namespaces, global variables, Object.prototype, and any sort of crap, thinking we are the only script ever running in a web page ... isn't it?
So kudos for AMD, at least there is a function, but where the hack is the
"use strict" directive suggested for every single bloody AMD module in any example you can find in the documentation? where is the global pollution problem solver, if developers are not educated or warned about the problem itself?node.js require ain't gold neither
When network, roundtrips and latency come into the game, the node.jsrequire() solution does not fit, scale, work, neither.If you understand how Loading from node_modules Folders logic works, and you have an extra look into All Together diagram, you will realize that all those checks, performed through an HTTP connection, won't ever make sense on the client side.
Are we stuck then? Or there's some tiny little brick in the middle that is not used, common, public, or discussed yet?
A node require() Like, For Client Side
Eventually, here where I was heading since the beginning: my require_client proposal ... gosh it took long!Rewind ... How about having the best from all techniques described "here and there" in order to:
- avoid big files parsing, everything is parsed once and on demand
- provide an easy to use builder for production ready single file code
- use one single syntax/model/style to define modules for both node or client side
- solve cycles exactly as node does
- forget 10 lines of checks to export a bloody module
- organize namespaces in folders
- obtain excellent performance
- make a single file distributable
Here, the AMD loader, versus the inline and DOM script injection loader, versus the dev version of my proposal, and finally the production/compiled version of my proposal ... how about that? You can use any console, profiler, dev tool/thing you want, to compare results, it's about a 150Kb total amount of scripts with most of them loaded ASAP, and one loaded on
"load" event.You can measure jquery, underscore, backbonejs, and the ironically added as last script head.js script there within their loading/parsing/ready time.
Reading Results
If you think nowadays theDOMContentLoaded event is all you need to startup faster your web page/app, you are probably wrong. DOMContentLoaded event means almost nothing for real UX, because a user that has a DOM ready but can't use, because modules and logic are not loaded yet, or see, because CSS and images have not been resolved yet, the page/app, is simply a "user waiting" rather than interacting and nothing else.Accordingly, if you consider the code flow and the time everything is ready to be used, the compiled
require() method is the best option you have: it's freaking fast!"use strict" included
The best part I could think about, is the"use strict"; directive by default automatically prepended to any module that is going to be parsed.This is a huge advantage for client side code because while we are able to create as many
var as we want in the module scope, the engine parser and compiler will instantly raise an error the line and column we forgot a variable declaration. All other safer things are in place and working but .. you know, maybe you don't want this?That's why the
require_client compiler makes the strict configuration property easy to spot, configure, and change ... as long as you know why you are doing that, everything is fine.How Does It Work
The compiler includes a 360 bytes once minzipped function that when is not optimized simply works through XHR.This function could be the very only global function you need, since every module is evaluated sandboxed and with all node.js module behaviors.
You can export a function itself, you can export a module, you can require inside a module, you can do 90% of what you could do in a node.js environment.
You don't need to take care of global variables definition, those won't affect other modules.
What you should do, is to remember that this is the client so the path you choose in the development version, is the root, as any
node_modules folder would be.If you clone the repository, you can test via copy and paste the resulting
build/require.js in whatever browser console traps such require_client ~/folder_you_put_staff/require_client/js or require_client ~/folder_you_put_staff/require_client/cycles.require("a") in the first case and require("main") in the second.In order to obtain a similar portable function you should create a folder with all scripts and point to that folder via
require_client so that a script with all inclusions will be created.A Basic Example
So here what's therequire_client script is able to produce.Let's imagine this is our project folder structure:
project/
css/
js/
require.dev.js
index.html
The
index.html file can simply have a single script in its header that includes require.dev.js and the bootstrap module through require("main");, as example.So, let's imagine we have module a, b, and main inside the js folder, OK?
require_client project/js project/require.jsThis call will produce the require.js file such as:
Now the
/*! (C) Andrea Giammarchi */
var require=function(c,d,e){function l(n,m){return m?n:g[n]}function b(o){var m=a[o]={},n={id:o,parent:c,filename:l(o,h),web:h};n[k]=m;d("global","module",k,(e.strict?"'use strict';":"")+l(o)).call(m,c,n,m);j.call(m=n[k],i)||(m[i]=h);return m}function f(m){return j.call(a,m)?a[m]:a[m]=b(m)}var k="exports",i="loaded",h=!0,a={},j=a.hasOwnProperty,g={
"a": "console.log(\"a starting\");exports.done=false;var b=require(\"b\");console.log(\"in a, b.done = \"+b.done);exports.done=true;console.log(\"a done\");",
"main": "console.log(\"main starting\");var a=require(\"a\");var b=require(\"b\");console.log(\"in main, a.done=\"+a.done+\", b.done=\"+b.done);",
"b": "console.log(\"b starting\");exports.done=false;var a=require(\"a\");console.log(\"in b, a.done = \"+a.done);exports.done=true;console.log(\"b done\");"
};f.config=e;f.main=c;return f}(this,Function,{
strict:true
});
index.html could simply include reuiqre.js rather than the dev version ;)Above program is the same showed in node.js API documentation about cycles. If you copy and paste this code in any console and you write after
require("main"); you'll see the expected result.As summary,
require_client is able to minify and place inline all your scripts, creating modules names based on files and folders hierarchy.All modules will be evaluated with a
global object, already available, as well as module, exports, and the latter used as the module context.The simple object based cache system will ensure these modules are evaluated once and never again.
What's YAGNI
Few things, that could change, are not in on purpose. As example, themodule.parent is always the global object, since in fact, it's in the global scope, through Function compilation, that the module will be parsed the very first time. Not sure we need a complicated mechanism to chain calls and also this mechanism is error prone.If you have 2 scripts requiring the same module, first come, first serve. The second one should not affect runtime the already parsed module changing suddenly the
module.parent property ... you know what I mean?The path resolution is a no-go, rather than trying to fix all possible messes with paths and OS, put your files in a single JS folder and consider that one your virtual
node_modules one for clients.If you have folder links inside the JS folder it's OK, but if you have recursive links you are screwed. Please keep it simple while I think how to avoid such problem within the
require_client logic, thanks.What Is Not There Yet
If your project is more than a megabyte minzipped, you might want to be able to split in different chunks the code so that the second, last, injected, require, won't disturb the first one.UpdateJust landed a version that does not cause conflicts with require itself. The first defined require will be the one used everywhere so it's now possible to name a project and include it in the main page so ... parallel projects are now available ;)
If you would like to reuse node modules that work in the client side too, you needto copy them inside the path folder.
The configuration object is the one you can find at the end of the require.js file ... there are two defaults there, but you can always change them via
require.config.path = "different"; as well as you can drop the require.config.strict = false; directive so that modules will be evaluated without "use strict"; directive.Anything else? Dunno ... you might come up with some hint, question, suggestion. And thanks for reading :), I know it was a long one!
Last Thoughts
If AMD and RequireJS comes with a compiler able to make everything already available somehow, think how much pointless become the optimization once you can have already available all dependencies without needing to write JS code in a different way, regardless it's for node.js or the client web normal code.There are NOT really many excuse to keep polluting the global scope with variables, we have so may alternatives today that keep doing it would result as evil as any worst technique you can embrace in JS world.
Tuesday, August 21, 2012
A Safer JS Environment
Oh well, apparently I wasn't joking here and I went even further ... so here I am with a weird hack you probably never thought about before ;)
Apparently not even browser vendors such Chrome or Safari since this condition, today, is always false:
Firefox and node.js got it right while Opera Next throws an error .. but latter a part ...
We cannot even by mistake create a global variable ... there's no lint that could miss that.
Moreover, if you are worried about malicious code able to change some global function or constructor, you can stop worrying with proposed freeze call: that will break instantly and any manual quick test will instantly fail rather than keep going.
However, we are in RequireJS and AMD module loader era where a module is imported inline through
Once we have
As summary, let's write down benefits of this technique:
What do you think?
A Globally Frozen Environment
Have you ever thought about this in the global context?
Object.freeze(this);
Apparently not even browser vendors such Chrome or Safari since this condition, today, is always false:
Object.isFrozen(Object.freeze(this));, and even if it works as expected after freezing.Firefox and node.js got it right while Opera Next throws an error .. but latter a part ...
Stop Any Global Pollution
That's right, if you freeze the window or global object, guess what happens here:
Object.freeze(this);
var a = 123;
alert(this.a); // undefined
alert(a); // error: a is not defined
We cannot even by mistake create a global variable ... there's no lint that could miss that.
Moreover, if you are worried about malicious code able to change some global function or constructor, you can stop worrying with proposed freeze call: that will break instantly and any manual quick test will instantly fail rather than keep going.
What About Namespaces
Well, if global namespaces, this hack will prevent the creation of any namespace.However, we are in RequireJS and AMD module loader era where a module is imported inline through
require() or inside a callback with AMD. The only important thing, is that at least the require function must be defined before this hack is performed or even that one cannot be used.Once we have
require() things are that easy, you create your own private scope and you do your own stuff in that scope being still sure that you won't pollute the global scope plus you won't be scared about other scripts ... you have your virtual sandbox
Object.freeze(this) && function (global) {
// here all local variables you want
var
fs = require("fs"),
mymodule = require("./mymodule")
;
// do the hack you want
}(this);
// AMD style
require(["fs", "./mymodule"], function (fs, mymodule) {
// already in a closure so ...
// do the hack you want
});
Too Restrictive? Object.prototype Then!
At least we can think about freezing theObject.prototype as the very first script in any webpage so the nightmare JSLint is talking about, the slow, boring, and probably already not necessary since no recent library is extending the Object.prototype since ages, hasOwnProperty() check, does not need to be in every bloody for/in 'cause you know what? Nobody can change, add, pollute, the global Object.prototype!
Object.freeze(Object.prototype);
// everything else after
for (var key in {}) {
// screw {}.hasOwnProperty, IT'S NOT NEEDED!
}
How About Both
If you are the only owner of your scripts, if you load node.js modules, by default with the ability to screw things up in the global context, or if you use AMD where global pollution should never be necessary, you might decide that this script is your best friend.
try {
// (C) WebReflection - Mit Style License
!function(global, Object){"use strict";
// buggy in both Chrome and Safari
// always false
if (!Object.isFrozen(global)) {
var freeze = Object.freeze;
Object.getOwnPropertyNames(
global
).forEach(function (prop) {
var tmp = global[prop];
switch(typeof tmp) {
case "function":
tmp = tmp.prototype;
case "object":
if (tmp) {
// console might not be freezable
// same is for String.prototype
// if applied twice and only in Safari
try {freeze(tmp)} catch(o_O) {}
}
break;
}
});
// Opera Next has some problem here
try {freeze(global)} catch(o_O) {}
}
}(this, Object);
} catch(o_O) { /* still in IE < 9 browser ... */ }
As summary, let's write down benefits of this technique:
- global context is free from pollution, no missed
varwill work anymore so it's instantly fixed before the eventual usage of a linter for/inloops could have a massive boost over object literals since nobody can possibly change the Object.prototype- ES5 enabled browsers, which means all current browsers for desktop and mobile except desktop IE < 9, will prevent greedy or outdated scripts, to make the environment less secure
- nobody can redefine
evalorFunction, used sometimes for reasons but the most insecure global functions we have in JS - we are forced to think in modules, 'cause there won't be any other way to load external script or dependency
- the only script that needs, eventually, to be loaded, will be the
require()one, which means faster bootstrap by default thanks to smaller amount of synchronous bytes required to initialized our project - in node.js, we are forced to write in a function even the main program, rather than polluting global object with stuff that might disturb required modules (which is true for all require/AMD based solutions too)
What do you think?
Sunday, August 19, 2012
Why JSON Won ... And Is Good As It Is
I keep seeing developers complaining about different things with JSON protocol and don't get me wrong, I've been the first one trying to implement any sort of alternative starting from JSOMON and many others ... OK?
Well, after so many years of client/server development is not that I've given up on thinking "something could be better or different", is just that I have learned on my skin all reasons JSON is damn good as it is, and here just a few of these reasons.
Recursion is not a problem, is part of the serialization process to solve it, as well as classes together with protected and private properties. You can save almost any object within its state, even if this object won't be, as reference, the same you serialized .. and I would say: of course!
There are also two handy methods, __sleep and __wakeup, able to let you save an object state in a meaningful way and retrieve it back or perform some action during deserialization.
Are these things available in JSON ? Thanks gosh NO! JSON should not take care of recursive objects ... or better, it's freaking OK if it's not compatible 'cause recursion is a developer matter or issue, not a protocol one!
All JSON can do is to provide a way to intercept serialization so that any object with a
So, at the end of the day, JSON implementations might provide already a similar way to
Specially in .NET world most of documentation is written in a pseudo XML, can you imagine you bothering yourself to write such redundant markup language to write something often ignored by developers ? Would you like to have that "crap" as part of the data you are sending or receiving via JSON as part of that protocol? I personally don't ... thanks! 'cause I believe a transport protocol should be as compact as possible and without problems.
Here JSON wins once again 'cause it's compatible, with its few universal rules, with basically everything.
Lists, Arrays, Dictionaries, Objects, Maps, Hashes, call them as you want, these are the most used and cross language entities we all deal with on daily bases, together with booleans, strings, and numbers.
OK, OK, specially numbers are quite generic but you might admit that the world is still OK with a generic Int32 or Float32 number and with 64bits compatible environments, these numbers could be of a different type but only if you will never deal with 32 bits environments ... make you choice ... you want a truly big number? Go for it, and loose the possibility to "talk" with any other 32 bit env ... not a big deal if you own your data, kinda pointless memory and CPU consumption if you deserialize everything as 64 bits ... but I am pretty sure you know what you are doing so ... JSON is good in that case too.
Classes and namespaces issues, if you want, are there in any case.
The good part of JSON, once again, is the ability to intercept serialize and unserialize process so that if you like to send instances, rather than just objects, you can use all tools provided by the implementation, and I am showing in this case a JavaScript example;
Once we send this serialized version of our instance to any other client, the
Still in JavaScript, we can deserialize easily the string in such way:
Just imagine that
Confused ? Oh well, it's easier than it looks like ...
Once again, any other environment can understand what's traveling in therms of data, but we can recreate a proper instance whenever we want.
If you use weird objects and you expect your own thing to happen ... just use tools you have to intercept before and after JSON serialization and put there everything you want, otherwise just try to deal with things that any other language could understand or you risk to think JSON is your own protocol that's missing this or that, while you are probably, and simply, overcomplicating whatever you are doing.
Thanks for your patience
Well, after so many years of client/server development is not that I've given up on thinking "something could be better or different", is just that I have learned on my skin all reasons JSON is damn good as it is, and here just a few of these reasons.
Reliable Serialization ?
No, 'cause YAGNI. There are few serialization processes I know that kinda work as expected and since ever, PHP serialize is a good example.Recursion is not a problem, is part of the serialization process to solve it, as well as classes together with protected and private properties. You can save almost any object within its state, even if this object won't be, as reference, the same you serialized .. and I would say: of course!
There are also two handy methods, __sleep and __wakeup, able to let you save an object state in a meaningful way and retrieve it back or perform some action during deserialization.
Are these things available in JSON ? Thanks gosh NO! JSON should not take care of recursive objects ... or better, it's freaking OK if it's not compatible 'cause recursion is a developer matter or issue, not a protocol one!
All JSON can do is to provide a way to intercept serialization so that any object with a
.toJSON() method can return it's own state and any time JSON.parse() is performed, it could bring back, if truly necessary, its recursive property.So, at the end of the day, JSON implementations might provide already a similar way to
__sleep and __wakeup objects but it should be the JSON string owner, the service, the developer, to take care of these problems, and simply because ....Universal Compatibility
JSON is a protocol and as a protocol it should be as compatible as possible with all languages, not only those C like or others with similar comments ... there won't be comments ever in JSON, 'cause the moment you need comments, you don't need a transport protocol 'cause programming languages have always ignored developers comments ... and also, for compatibility reasons, not all programming languages would like to have// or /* */ or even # as inline or multiline comment ... why would they?Specially in .NET world most of documentation is written in a pseudo XML, can you imagine you bothering yourself to write such redundant markup language to write something often ignored by developers ? Would you like to have that "crap" as part of the data you are sending or receiving via JSON as part of that protocol? I personally don't ... thanks! 'cause I believe a transport protocol should be as compact as possible and without problems.
Here JSON wins once again 'cause it's compatible, with its few universal rules, with basically everything.
Different Environments
This is the best goal ever reached from a protocol, the fact that every programming language can represent somehow what JSON transports.Lists, Arrays, Dictionaries, Objects, Maps, Hashes, call them as you want, these are the most used and cross language entities we all deal with on daily bases, together with booleans, strings, and numbers.
OK, OK, specially numbers are quite generic but you might admit that the world is still OK with a generic Int32 or Float32 number and with 64bits compatible environments, these numbers could be of a different type but only if you will never deal with 32 bits environments ... make you choice ... you want a truly big number? Go for it, and loose the possibility to "talk" with any other 32 bit env ... not a big deal if you own your data, kinda pointless memory and CPU consumption if you deserialize everything as 64 bits ... but I am pretty sure you know what you are doing so ... JSON is good in that case too.
No Classes
And again thanks gosh! You don't want a protocol that deals with classes, trust me, 'cause you cannot write a class in all possible programming languages, can you? If you can, even in those programming languages where classes never existed 'cause classes are simply an abstract concept represented by the word "class" but representable in billion ways with other languages (e.g. via just objects in JavaScript).Classes and namespaces issues, if you want, are there in any case.
The good part of JSON, once again, is the ability to intercept serialize and unserialize process so that if you like to send instances, rather than just objects, you can use all tools provided by the implementation, and I am showing in this case a JavaScript example;
function MyClass() {
// doesn't matter what we do here
// for post purpose, we do something
this.initialized = true;
}
MyClass.prototype.toJSON = function () {
this.__class__ = "window.MyClass";
return this;
};
var myClassObject = JSON.stringify(new MyClass);
// "{"initialized":true,"__class__":"window.MyClass"}"
Once we send this serialized version of our instance to any other client, the
.__class__ property could be ignored or simply used to understand what kind of object was it.Still in JavaScript, we can deserialize easily the string in such way:
function myReviver(key, value) {
if (!key) {
var instance = myReviver.instance;
delete instance.__class__;
delete myReviver.instance;
return instance;
}
if (key == "__class__") {
myReviver.instance = myReviver.createInstance(
this, this.__class__
);
}
return value;
}
myReviver.createInstance = "__proto__" in {} ?
function (obj, className) {
obj.__proto__ = myReviver.getPrototype(className);
return obj;
} :
function(Bridge) {
return function (obj, className) {
Bridge.prototype = myReviver.getPrototype(className);
return new Bridge(obj);
};
}(function(obj){
for (var key in obj) this[key] = obj[key];
})
;
myReviver.getPrototype = function (global) {
return function (className) {
for (var
Class = global,
nmsp = className.split("."),
i = 0; i < nmsp.length; i++
) {
// simply throws errors if does not exists
Class = Class[nmsp[i]];
}
return Class.prototype;
};
}(this);
JSON.parse(myClassObject, myReviver) instanceof MyClass;
// true
Just imagine that
__class__ could be any property name, prefixed as @class could be, or with your own namespace value @my.name.Space ... so no conflicts if more than a JSON user is performing same operations, isn't it?Simulating __wakeup Call
Since last example is about__sleep, at least in JavaScript easily implemented through .toJSON() method, you might decide to implement a __wakeup mechanism and here what you could add in the proposed revival method:
function myReviver(key, value) {
if (!key) {
var instance = myReviver.instance;
delete instance.__class__;
delete myReviver.instance;
// this is basically last call before the return
// if __wakeup was set during serialization
if (instance.__wakeup) {
// we can remove the prototype shadowing
delete instance.__wakeup;
// and invoke it
instance.__wakeup();
}
return instance;
}
if (key == "__class__") {
myReviver.instance = myReviver.createInstance(
this, this.__class__
);
}
return value;
}
Confused ? Oh well, it's easier than it looks like ...
// JSON cannot bring functions
// a prototype can have methods, of course!
MyClass.prototype.__wakeup = function () {
// do what you need to do here
alert("Good Morning!");
};
// slightly modified toJSON method
MyClass.prototype.toJSON = function () {
this.__class__ = "window.MyClass";
// add __wakeup own property
this.__wakeup = true;
return this;
};
Once again, any other environment can understand what's traveling in therms of data, but we can recreate a proper instance whenever we want.
How To Serialize
This is a good question you should ask yourself. Do you want to obtain exactly the same object once unserialized? Is that important for the purpose of your application? Yes? Follow my examples ... no? Don't bother, the less you preprocess in both serializing and unserializing objects, the faster, easier, slimmer, will be the data.If you use weird objects and you expect your own thing to happen ... just use tools you have to intercept before and after JSON serialization and put there everything you want, otherwise just try to deal with things that any other language could understand or you risk to think JSON is your own protocol that's missing this or that, while you are probably, and simply, overcomplicating whatever you are doing.
You Own Your Logic
Last chapter simply demonstrates that with a tiny effort we can achieve basically everything we want to ... and the cool part is that JSON, as it is, does not limit us to create more complex structures to pass once stringified or recreate once parsed and this is the beauty of this protocol so please, if you think there's something missing, think twice before proposing yet another JSON alternative: it works, everywhere, properly, and it's a protocol, not a JS protocol, not a X language protocol ... just, a bloody, protocol!Thanks for your patience
Thursday, August 16, 2012
JavaScript recent Bits and Bobs
Quick post about few things landed, or not yet, in JavaScript world.
Since this function offers more accuracy than milliseconds, and I am talking about microseconds, which is 1/1000 of a millisecond, it's the best option we have to measure benchmarks or be sure that some time elapsed between two statements in a synchronous code flow.
You might don't know that a loop between
This behavior is behind ticks and clocks, more or less same reason
preciseTime, this is the obvious name of my latest git repository, could be shimmed or polyfilled quite easily via a node module I can't npm install for some reason, or through
enjoy!
As you might know,
A similar behavior could be obtained via this shim:
On the other hand, Object.getOwnPropertyNames returns an Array of all properties defined in the object, even those not enumerable or as getters/setters, but without considering inherited properties.
For all ES3 browsers is basically the same of above
To be really honest, probably all IE < 9 browsers should use the check over
In ES5 world there's no other way to retrieve all properties names defined in an object so this methods is pure awesomeness!
In a duck typed system we need to know all characteristics of an object to be sure "it's a duck". Right now there's no standard way to obtain all properties an object could use, and this is where
In my shim, this is obtained through the
At this point we can recognize a duck properly, the only method eventually missing is the one able to give us a list of not enumerable properties per each object ... but with these tools, we can create one, if truly necessary.
This is about this method, shimmed in the previous gist as well, and able to retrieve the descriptor of a property that might, or might not, be inherited. How cool is that?
The only thing I am not sure about, is if the method should consider up to
Where if you want alphabetic order, you might consider this elaborated version if previous one did not work as expected.
Run it once in your browser, environment, console:
preciseTime()
In this era loads of+new Date, JSC offers since quite a while a handy global function called preciseTime().Since this function offers more accuracy than milliseconds, and I am talking about microseconds, which is 1/1000 of a millisecond, it's the best option we have to measure benchmarks or be sure that some time elapsed between two statements in a synchronous code flow.
You might don't know that a loop between
new Date and another new Date could produce completely unexpected results such a negative integer which is kinda unexpected since zero is the best case we would consider.This behavior is behind ticks and clocks, more or less same reason
setTimeout or setInterval have never been accurate in therms of delay.preciseTime, this is the obvious name of my latest git repository, could be shimmed or polyfilled quite easily via a node module I can't npm install for some reason, or through
java.lang.System.nanoTime for Rhino.enjoy!
Object.getPropertyNames()
In MDN Proxy Fundamental Traps chapter there are two functions I was kinda waiting for, and one of these isObject.getPropertyNames().As you might know,
Object.keys(object) returns an array of enumerable object properties.A similar behavior could be obtained via this shim:
// warning: this is not fully ES5 standard
"keys" in Object || !function(hasOwnProperty){
Object.keys = function keys(object) {
var keys = [], key;
for (key in object)
// not considering IE < 9 quirks
hasOwnProperty.call(object, key) && keys.push(key);
;
return keys;
};
}({}.hasOwnProperty);
On the other hand, Object.getOwnPropertyNames returns an Array of all properties defined in the object, even those not enumerable or as getters/setters, but without considering inherited properties.
For all ES3 browsers is basically the same of above
Object.keys() shim since it's not possible to define not enumerable properties in a meaningful way.To be really honest, probably all IE < 9 browsers should use the check over
isPropertyEnumerable() check via Object.keys, and leave the provided shim as it is since actually, those not enumerable properties are those that this function could return in a meaningful way, and talking about shims ... never mind ...In ES5 world there's no other way to retrieve all properties names defined in an object so this methods is pure awesomeness!
Right ... What About Object.getPropertyNames()
What is not possible right now, and in a world where inheritance is all over the place as JS world is, is the ability to retrieve not only own properties, but inherited properties too.In a duck typed system we need to know all characteristics of an object to be sure "it's a duck". Right now there's no standard way to obtain all properties an object could use, and this is where
Object.getPropertyNames() becomes handy: you receive all inherited properties of an object too, together, of course, with own properties.In my shim, this is obtained through the
__proto__ de facto standard property.At this point we can recognize a duck properly, the only method eventually missing is the one able to give us a list of not enumerable properties per each object ... but with these tools, we can create one, if truly necessary.
Object.getPropertyDescriptor()
Oh well, this is about another annoying thing ... the fact we know thatobj instanceof Class but we have to be upside-down to know if a property, defined as default in the Class.prototype has been redefined or it's simply that bloody default.This is about this method, shimmed in the previous gist as well, and able to retrieve the descriptor of a property that might, or might not, be inherited. How cool is that?
The only thing I am not sure about, is if the method should consider up to
prototype === null, including Object.prototype or not ... right now is not, since I believe nobody would ever check for hasownProperty descriptor, as example, with a generic object.global methods, classes, and shit
This is more a hint, whenever you are curious about what's exposed through your global object, you can simply perform this check, and inside an about:blank page:
console.log(
Object.getOwnPropertyNames(this).sort().join("\n")
);
Where if you want alphabetic order, you might consider this elaborated version if previous one did not work as expected.
Run it once in your browser, environment, console:
!function(global){
function alphabetically(a, b){
var
alen = a.length,
blen = b.length,
len = Math.min(alen, blen),
i = 0,
ac, bc, c
;
while (i < len) {
ac = a.charCodeAt(i);
bc = b.charCodeAt(i);
c = ac - bc;
if (c) return c;
++i;
}
return alen - blen;
}
var getOwnPropertyNames = Object.getOwnPropertyNames;
if (!getOwnPropertyNames) {
getOwnPropertyNames = function getOwnPropertyNames(object) {
var hasOwnProperty = {}.hasOwnproperty, keys = [], key;
for (key in object)
hasOwnProperty.call(object, key) && keys.push(key)
;
return keys;
};
}
function getAllKeys(object, ordered) {
var keys = getOwnPropertyNames(object);
ordered && keys.sort(alphabetically);
return keys;
}
console.log(getAllKeys(global,1).join("\n"));
}(this);
Wednesday, July 11, 2012
(က) Polpetta, any folder is served spiced
The quick version is: have you ever thought about using node.js to make any folder as a web-server and in a PHPish way where .njs files are required and executed runtime as node modules ?
Oh well, I did, and this is the result in Github: polpetta ... enjoy!
Oh well, I did, and this is the result in Github: polpetta ... enjoy!
Sunday, June 24, 2012
The JavaScript typeof Operator Problem
TL;DR don't even try to normalize or shim newer
Whenever it was a mistake or not to consider
However, we can still use methods through
The only way to find a method in a primitive value is to extend its own
Back to the previous chapter, a situation like this might mislead as well:
Now you can play adding
Doing the same with an argument, rather than context injection, will produce the same output, regardless the function has or not the strict directive.
As example, let's imagine we have a list of unique IDs, and we would like to flag them, relate them, or use them, as objects.
With above example we might use the variable
This is actually awesome since we can always tell if that string/object has been created using
As summary, knowing in advance how an object has been created, will let us understand if whatever property/method changed or attached to a generic
If we remove
As we have seen before, when
When latter case happens, the check against the triple equality operator will fail as well.
If null is not the only problem, just consider that if an engineer created a variable using
If you use a framework that does this wrapping by default there's only one thing to do: change framework!
Strings are immutable while Objects are always freshly baked ... since a list of strings as objects cannot even use
If you never use
If you need
A feature detection like this one could help:
To simplify above code you might trust the generic strict directive behaviour, through undefined, via this snippet:
Followed by the rarely seen check:
Above check does not simply tell us if the the browser can handle the strict directive, it also tells us if we are already under use strict.
If we wrap everything in our own closure we might not care in any case ... so, back to the topic, we might understand through these checks if we are under strict directive but what we cannot normalize in any case is something like:
In ECMAScript 3rd Edition latest snippet will return
If your normalizer is "so cool" that transform any
Can we say now there's more mess than before? Oh well ...
However, all you gonna have in this case is a function that removes a new feature from the next version of JavaScript.
I have aded this script just to give you a chance if you wanna believe that using methods across primitive wrappers does not make sense ( subclassing anybody ? at that point you gonna have another problem ... oh well, again ... )
typeof via code: you simply can't!Whenever it was a mistake or not to consider
typeof null == "object", many libraries that tried to normalize this operator failed to understand that null is not the only problem.The JS Polymorphism Nature
We can borrow methods for basically everything but primitives values, such booleans, numbers, and strings, do not accept indeed any sort of property or method attached runtime.
var s = "hello";
s.greetings = true;
alert(s.greetings);
// "undefined"
However, we can still use methods through
call() or apply():
function isGreetings() {
return /^(?:ciao|hello|hi)$/.test(this);
}
alert(isGreetings.call("hello"));
// true
The only way to find a method in a primitive value is to extend its own
constructor.prototype:
String.prototype.isGreetings = function () {
return /^(?:ciao|hello|hi)$/.test(this);
};
alert("hello".isGreetings());
// true
What Happens When We Invoke A Method
In ECMAScript 3 up to 5.1, when "use strict" directive is not in place, any primitive value will be temporarily converted into an object, where onlynull and undefined will be converted into the original global object.
alert(function () {
return this === window;
}.call(null));
// ... and here a tiny winy problem ...
alert(function () {
return this ? true : false;
}.call(false)); // true
alert(function () {
return Boolean(this);
}.call(false)); // true
alert(function () {
return !!this;
}.call(false)); // true
Back to the previous chapter, a situation like this might mislead as well:
function setAsGreetings() {
this.greetings = true;
alert(this.greetings); // true
}
var s = "hello";
setAsGreetings.call(s);
alert(s.greetings); // undefined
Why This Is A Problem
Try to imagine this really simple piece of code:
function whichType() {
return typeof this;
}
// guess what ...
alert([
whichType.call(null), // "object"
whichType.call(false), // "object"
whichType.call(true), // "object"
whichType.call("hello"), // "object"
whichType.call(123), // "object"
whichType.call(undefined) // "object"
].join("\n"));
Now you can play adding
"use strict" to the very beginning of the whichType function.Doing the same with an argument, rather than context injection, will produce the same output, regardless the function has or not the strict directive.
function whichType(o) {
// pointless "use strict";
return typeof o;
}
// guess what ...
alert([
whichType(null), // "object"
whichType(false), // "boolean"
whichType(true), // "boolean"
whichType("hello"), // "string"
whichType(123), // "number"
whichType(undefined) // "undefined"
].join("\n"));
What If You Want Use new String/Number/Boolean
It's not only about context injection and thetypeof this, it's also about the ability to use collections of the same type as we need.As example, let's imagine we have a list of unique IDs, and we would like to flag them, relate them, or use them, as objects.
var ids = [
"a",
"b",
"c"
];
// an easy way to mirror strings as objects
var flagged = ids.map(Object);
// check if a generic input/id exists ...
var i = ids.indexOf("b");
// ... and check if it has been used/touched already
if (-1 < i && !flagged[i].touched) {
flagged[i].touched = true;
alert("touched");
}
// once again ... but it will never happen
if (-1 < i && !flagged[i].touched) {
flagged[i].touched = true;
alert("touched");
}
With above example we might use the variable
ids to simply filter existent and not existent input, and mirror these ids through they respective objects and eventually reuse these objects as we need, concatenating them, recycling them, etc etc ... I know, above example is not such common use case, right? But of course it's not since we have so many problems with typeof and nobody in JS world has ever suggested to use, when necessary, these constructors in a useful way...typeof In JS.Next
Since explicit should superset implicit behaviours, ECMAScript 6 and code under"use strict" directive will react like this.
function app(s) {"use strict";
alert(type.call(s));
}
function type() {"use strict";
return typeof this;
}
app("primitive"); // "string"
app(new String("object"));// "object"
This is actually awesome since we can always tell if that string/object has been created using
new Constructor or not ... which leads with less ambiguous code and the possibility to use objects as primitives whenever we find a case were it's needed.
function setGreetings() {
this.greetings = true;
}
var s = "hello";
setGreetings.call(s); // pointless
s.greetings; // undefined
// but if we want ...
s = new String(s);
setGreetings.call(s);
s.greetings; // true !!!
As summary, knowing in advance how an object has been created, will let us understand if whatever property/method changed or attached to a generic
this will make sense or not ... unless these operations are not simply used internally during the temporarily lifetime of that possible object ... where again we might need to know if we have to clean up after or not ... that's what I call control, isn't it?... And No Polyfill Will Do
Bad news here is ... there is no way to replicate the new and correct behaviour of the nexttypeof operator.If we remove
"use strict" directive from the latter example's type() function, we'll notice that the result will be "object" in both cases ... no matter how we pass the original argument.Reasonable + Inconsistent = Fail
If your only concern is thattypeof null should produce the string "null", you might realize that o === null is all you need, rather than creating and calling a function every time you want/need to understand the type of an object.As we have seen before, when
null is used as context, the typeof could return "object" in any case.When latter case happens, the check against the triple equality operator will fail as well.
If null is not the only problem, just consider that if an engineer created a variable using
new String(text) rather than using just text there must be a bloody reason: either the engineer does not know JavaScript OR, most likely, decided to use the possibility offered by an object that is wrapping a primitive value.If you use a framework that does this wrapping by default there's only one thing to do: change framework!
Strings are immutable while Objects are always freshly baked ... since a list of strings as objects cannot even use
Array#indexOf unless you don't hold and/or compare via Generic#valueOf() every time the list content, the amount of pointless RAM and CPU used to work with these kind of wrappers does not scale ... full stop.If you never use
new String and believe that nobody else will as well, your logic might be screwed in any case by the fact that newer browsers might implement a proper typeof and make your code/logic weak when the original constructor has been used as wrapper.How To Migrate, How To Not Fail
Unless both your code and your environment is frozen by respective versions, and it does not matter if it's client or server side, you cannot basically trust your own code because one day, in some browser, it might act differently.If you need
typeof so much and your code is for 3rd parties development, you might decide to create two slightly different versions of your code or simply normalize the old typeof behavior forgetting then returning "string" when you don't actually know if the developer meant string or new String.A feature detection like this one could help:
var NEW_TYPEOF = function(){
"use strict";
return typeof this == "string";
}.call("");
To simplify above code you might trust the generic strict directive behaviour, through undefined, via this snippet:
var USE_STRICT_COMPATIBLE = function(){
"use strict";
return !this;
}();
Followed by the rarely seen check:
var USE_STRICT_ENABLED = function(){
return !this;
}();
Above check does not simply tell us if the the browser can handle the strict directive, it also tells us if we are already under use strict.
If we wrap everything in our own closure we might not care in any case ... so, back to the topic, we might understand through these checks if we are under strict directive but what we cannot normalize in any case is something like:
function borrowedMethod() {
alert(yourTypeOfShim(this));
}
borrowedMethod.call("fail");
borrowedMethod.call(new String("fail"));
In ECMAScript 3rd Edition latest snippet will return
"object" while in ES5 and strict directive it will return "string".If your normalizer is "so cool" that transform any
instanceof String into "string", then you might realize that same code run under strict in ES5 will return "object" so either both ways, and as summary, your function is not reliable.Can we say now there's more mess than before? Oh well ...
Doesn't Matter, Had Type
If you wanna have a function that will never be able to compete with the real power of ES6 or"use strict" typeof operator, you might end up with something like this:
function type(o) {"use strict";
var type = typeof o;
if (type == "object") {
if (!o)
type = "null"
; else if (
o instanceof Boolean ||
o instanceof Number ||
o instanceof String
)
type = typeof o.valueOf()
;
}
return type;
}
However, all you gonna have in this case is a function that removes a new feature from the next version of JavaScript.
I have aded this script just to give you a chance if you wanna believe that using methods across primitive wrappers does not make sense ( subclassing anybody ? at that point you gonna have another problem ... oh well, again ... )
Tuesday, June 19, 2012
Dealing With Future Pointers
I have talked about this already in both JSConfEU and QCon - London and I have also blogged a couple of times about this problem that many developers keep ignoring ...
In JSConfEU I have showed with my slides this picture:

which is simply the reason most of the so called mobile websites won't work as expected.
Why that? Because
For this kind of situation/assumption, a lazy pointer detection is the only one we can rely.
With above example it becomes really easy to understand what's the user choice: either touch, or keyboard.
No matter what kind of device we are dealing with, the very first event will tell us what kind/group of events we should use.

The Microsoft Surface proposal looks great to me, but at the same time it might fail in most common mobile oriented websites.
First of all, MS has introduced kinda proprietary events to deal with pointers but I wonder how these events will behave once the user decide to switch between trackpad and screen.
I imagine that the mouse cursor will appear and disappear accordingly, at least that is what could make sense to me, so that the page could actually implement both :hover styles and still be based on touch events but the simple fact is that all this is a mess for web pages.
Here an example of how things could go wrong, assuming the classic trackpad in older laptop won't mean that msPointerEnabled is true ( being that screen not touchable )
So, unless Windows 8 does not prefer MS events regardless the hardware, the inline feature detection will fail in this case as well.
This is also not only about mouses, trackpads, and screens, this is related to virtual keyboards too, the most annoying thing could appear and without notification/control in a webpage screen.
What we could do is to create yet another library able to deal in a totally abstract way with all these cases and in real time.
But how big this overhead would be? Think how many times we attach events to single nodes, rather than into the document only, and think how many checks we need to do in order to normalize properly and cross platform user actions.
The ideal library should be able to switch runtime and handle combination of any sort of pointer ... maybe you scroll a page with fingers, then you draw on canvas with a USB pen ... then you type on the screen, then suddenly you press enter in the keyboard ... and so on ...

I am not a huge fun of too abstract architectures for the simple reason that these rarely have good performances but this is a problem that later we deal with, more problems we'll have.
If you have any library I am not aware of that is that smart, please let me know and I'll update the post linking to this library.
The Unexpected Input
In JSConfEU I have showed with my slides this picture:
which is simply the reason most of the so called mobile websites won't work as expected.
Why that? Because
"ontouchend" in window, the most pointless feature detection ever, will produce a positive result and if you decide which event should be attached to the document or any DOM node relying this check, the moment the device that exposes touch events BUT has a trackpad, mouse, or any other alternative pointer device connected, it will fail, it won't work, it will look broken!A Hybrid Solution
We could make the assumption that if the user is using fingers, the user will keep using fingers ... while if the user chooses the alternative pointer, there shouldn't be a case where fingers are again on the screen.For this kind of situation/assumption, a lazy pointer detection is the only one we can rely.
// useless/unoptimized code - used to explain and nothing else
function initPointerEvents(e) {
// decide what should be used later on
switch (e.type) {
case "touchstart": return useTouches();
// other possible cases
default: return useMouse();
}
document.removeEventListener("touchstart", initPointerEvents, true);
document.removeEventListener("mousedown", initPointerEvents, true);
document.removeEventListener("mousemove", initPointerEvents, true);
document.removeEventListener("mousewheel", initPointerEvents, true);
}
// note the usage of true, so that we can be sure these detections are performed
// before any other listener attached with "false" ( bubbling phase )
document.addEventListener("touchstart", initPointerEvents, true);
document.addEventListener("mousedown", initPointerEvents, true);
document.addEventListener("mousemove", initPointerEvents, true);
document.addEventListener("mousewheel", initPointerEvents, true);
With above example it becomes really easy to understand what's the user choice: either touch, or keyboard.
No matter what kind of device we are dealing with, the very first event will tell us what kind/group of events we should use.
Well ... Still Not Friendly
What if the user combines touches and trackpad?The Microsoft Surface proposal looks great to me, but at the same time it might fail in most common mobile oriented websites.
First of all, MS has introduced kinda proprietary events to deal with pointers but I wonder how these events will behave once the user decide to switch between trackpad and screen.
I imagine that the mouse cursor will appear and disappear accordingly, at least that is what could make sense to me, so that the page could actually implement both :hover styles and still be based on touch events but the simple fact is that all this is a mess for web pages.
Here an example of how things could go wrong, assuming the classic trackpad in older laptop won't mean that msPointerEnabled is true ( being that screen not touchable )
// the MS suggested feature detection
if (window.navigator.msPointerEnabled) {
// fails when the user uses the trackpad instead of the screen
} else {
// fails when the user uses the screen instead of the trackpad
}
So, unless Windows 8 does not prefer MS events regardless the hardware, the inline feature detection will fail in this case as well.
We Need A Better Interface
This call is mainly for W3C, everything we have right now does not scale with more complex, modern, hybrid, devices.This is also not only about mouses, trackpads, and screens, this is related to virtual keyboards too, the most annoying thing could appear and without notification/control in a webpage screen.
What we could do is to create yet another library able to deal in a totally abstract way with all these cases and in real time.
But how big this overhead would be? Think how many times we attach events to single nodes, rather than into the document only, and think how many checks we need to do in order to normalize properly and cross platform user actions.
The ideal library should be able to switch runtime and handle combination of any sort of pointer ... maybe you scroll a page with fingers, then you draw on canvas with a USB pen ... then you type on the screen, then suddenly you press enter in the keyboard ... and so on ...
One Problem At The Time
There is no library out there able to truly behave as expected and switch runtime all these possibilities ... so I might decide to write one but the architecture should be both simple and able to scale.I am not a huge fun of too abstract architectures for the simple reason that these rarely have good performances but this is a problem that later we deal with, more problems we'll have.
If you have any library I am not aware of that is that smart, please let me know and I'll update the post linking to this library.
Thursday, June 14, 2012
Ranting About Racing Engines
Update ... regardless this rant is still valid ... I have updated for both Web and node my es6-collections following stricter currently available specs.
This is happening right now, or better, since this race started a while ago between alternative browsers and the idea of bringing JavaScript every-bloody-where ...
N times the amount of money spent, N times the number of patents slightly different and potentially able to make better engines production slower/farer due patents lifecycle.
Almost zero joined effort ... same studies over and over with of course different solutions, and these are always welcome, but rarely a shared effort between teams able to bring the 0 emissions, ecologic and usable engine we are all dreaming about ( look at all these prototypes with batteries rather than gasoline ... look at the very first and only hybrid diesel engine, etc etc ... now ask yourself how long will it take before we can all afford these engines for real ... )
I believe is still good that there are different implementations such V8, Nitro, SpiderMonkey, Chakra, Whatever ... but when it comes to the race, all these engines are adopting early versions of specs that are still under definition and this is bad 'cause ...
Chrome Engineers are great and extremely fast, same is for all Webkit contributors, as well as SpiderMonkey and all other engines but if we find 2345678 different APIs that works inconsistently across all JavaScript engines I believe we are doing it wrong.
Here just a few examples:
Map, Set, and WeakMap respective prototypes are changing all the time ... oh well, this is a common side effect about adopting features that are under discussion on daily basis and not defined anywhere yet.
In any case, I would like to use the native constructor where available, and this is true for both Firefox (Aurora) and Chrome (Canary with enabled experimental features).
While updating my es6-collections code I have realized, after changing tests and implementing the desired behavior, that Aurora has a
Who is correct? Who is wrong? It doesn't actually matter because if these methods are frozen in the prototype, I cannot fix anything there and I need to create another subset with a different name in order to obtain a fixed and consistent version of these constructors across all platforms and most likely penalizing Aurora or Canary being unable to use respective native implementation ...
About working as expected once we deal with a native API ... I don't even want to start this conversation 'cause there are too many things to consider here ... my take on this is: don't fix browsers bugs unless it's IE that won't update automatically and only if IE is an interesting target browser for your app.
As easy as that ... if a browser vendor realize the gravity of a bug the team will fix it asap ... if we show easy work-arounds to a specific bug all over the place they won't consider that problem as a show stopper.
Even better, always file a bloody bug with proper description, a link to specs, and a use case that makes sense so that these guys can properly understand the gravity and what is this about ... OK? A bit more effort from the Web community itself about filing bugs can only bring a better Web for all of us.
In any case, if we cannot trust native behavior across platform, we need to create yet another boring library able to fix all these things for us ... and this is getting ridiculous, imho ... I don't want to re-fix the browser for every single native call I do from the JavaScript core ... I just would like to use the programming language and its native "things" and focus on something else, something more, something productive!
Today for a basic web page with a stupid form to submit, we add minimum 200Kb of fixes through any sort of "lightweight" library ... isn't it? Is this what the meaning of "JavaScript everywhere" is becoming day after day? If you don't use the library to fix native stuff you cannot do much?
Was my fault in first place to propose polyfills for something still that unstable and not properly implemented in these browsers developers channels? Probably yes, but many others are bringing few ES.Next things through libraries and polyfills so be aware that things might screw up without notice from a day to another one due automatic updates and if you don't follow all these libraries on daily basis you might find yourself in a situation where all your code needs to be rewritten ... and I guess none of us would like that much this situation ...
P.S. the current version has keys and values plus does not work with edge cases such NaN or -0 when it comes to Map keys ... the local version I have is green everywhere and implements specs properly so stay tuned if you want a closer ES6 version of these constructors API while start avoiding the usage of keys and values properties if you are using that code already ( about NaN and -0 I don't bother, I think using these values as keys is an error in any case ... however, next version will have a better indexOf to match NaN and -0 too so that specs, those we know today, will be respected, forcing the implementation to do not trust native Array#indexOf and its inconsistent result when it comes to those values that are not reflective).
Last, but not least, more than asking clarification in the ECMAScript group I could not do ... so, even filing a bug in this case is kinda pointless since I don't even know what to write there except that another engine does something different about something that's not fully defined yet:
This is happening right now, or better, since this race started a while ago between alternative browsers and the idea of bringing JavaScript every-bloody-where ...
On Engines Fragmentations
This happens since ever in vehicles engines and we can all see the difference in themes of both prices and CO2 emissions. Every major car/motorbike engine manufacturer is competing against others.N times the amount of money spent, N times the number of patents slightly different and potentially able to make better engines production slower/farer due patents lifecycle.
Almost zero joined effort ... same studies over and over with of course different solutions, and these are always welcome, but rarely a shared effort between teams able to bring the 0 emissions, ecologic and usable engine we are all dreaming about ( look at all these prototypes with batteries rather than gasoline ... look at the very first and only hybrid diesel engine, etc etc ... now ask yourself how long will it take before we can all afford these engines for real ... )
The Web Is Different ... But
Well, at least there are tons of groups trying to bring some Harmony between JavaScript engines.I believe is still good that there are different implementations such V8, Nitro, SpiderMonkey, Chakra, Whatever ... but when it comes to the race, all these engines are adopting early versions of specs that are still under definition and this is bad 'cause ...
The Side Effect
Works only in Google Chrome is the very first side effect of this fragmentation and while earlier/faster adoption of most recent standards and drafted specs can be considered one step forward, the idea that a Web page works only in a single browser, and no matter which one is it, bring us back to year 2000 ... have we learned anything since?Chrome Engineers are great and extremely fast, same is for all Webkit contributors, as well as SpiderMonkey and all other engines but if we find 2345678 different APIs that works inconsistently across all JavaScript engines I believe we are doing it wrong.
Here just a few examples:
- W3C effort to bring more HW access through the Web
- PhoneGap APIs to expose native access to JavaScript and Web Pages
- webOS APIs to expose native access to JavaScript Apps
- Boot 2 Gecko APIs to have HW access through JavaScript
- ChromeOS APIs to have lower level access
- Safari Mobile APIs not present in other mobile browsers
- Opera and Mobile proprietary namespace ( really guys, please drop that window.opera thingy to start with ... )
- Adobe APIs to interface Flash objects and JavaScript for Air or generic plugin content
- newest ES6 APIs ... so cool, and so unstable at the same time ...
The Curious Case Of Harmony Collections
Map, Set, and WeakMap respective prototypes are changing all the time ... oh well, this is a common side effect about adopting features that are under discussion on daily basis and not defined anywhere yet.
In any case, I would like to use the native constructor where available, and this is true for both Firefox (Aurora) and Chrome (Canary with enabled experimental features).
While updating my es6-collections code I have realized, after changing tests and implementing the desired behavior, that Aurora has a
size() method that does not exist in Canary and that Map#set(key, value) does not return the value as it does in Canary.Who is correct? Who is wrong? It doesn't actually matter because if these methods are frozen in the prototype, I cannot fix anything there and I need to create another subset with a different name in order to obtain a fixed and consistent version of these constructors across all platforms and most likely penalizing Aurora or Canary being unable to use respective native implementation ...
Why Native
Native is fast, native is good, native is the way to go and the reason we create polyfills: to be able to remove them once our current A grade target browsers support already this or that API and it works as expected and as fast as possible.About working as expected once we deal with a native API ... I don't even want to start this conversation 'cause there are too many things to consider here ... my take on this is: don't fix browsers bugs unless it's IE that won't update automatically and only if IE is an interesting target browser for your app.
As easy as that ... if a browser vendor realize the gravity of a bug the team will fix it asap ... if we show easy work-arounds to a specific bug all over the place they won't consider that problem as a show stopper.
Even better, always file a bloody bug with proper description, a link to specs, and a use case that makes sense so that these guys can properly understand the gravity and what is this about ... OK? A bit more effort from the Web community itself about filing bugs can only bring a better Web for all of us.
In any case, if we cannot trust native behavior across platform, we need to create yet another boring library able to fix all these things for us ... and this is getting ridiculous, imho ... I don't want to re-fix the browser for every single native call I do from the JavaScript core ... I just would like to use the programming language and its native "things" and focus on something else, something more, something productive!
Today for a basic web page with a stupid form to submit, we add minimum 200Kb of fixes through any sort of "lightweight" library ... isn't it? Is this what the meaning of "JavaScript everywhere" is becoming day after day? If you don't use the library to fix native stuff you cannot do much?
Not Only JavaScript
You don't need me to tell you that the CSS world is even more messed up than JavaScript one ... and the reason is basically the same: fragmentation of rules and new features using prefixes all over the place which results in 5 times bigger CS with repeated things all over the place ... the most distunging piece of "code" ever in the Web history that ... needs to be fixed with libraries, again? meh is the maximum expression I have for this without being vulgar ...What Can We Do
I have no idea ... and in my specific case, talking about es6-collections, I have to wait and nothing else. I have to wait in order to be sure one behavior is correct, while another one is not, and finally penalize browser A or browser B feature testing the inconsistency and throwing away native constructors in favor of shimmed one ... so that my tests, at least tests, will be consistently green across all supported engines/platforms.Was my fault in first place to propose polyfills for something still that unstable and not properly implemented in these browsers developers channels? Probably yes, but many others are bringing few ES.Next things through libraries and polyfills so be aware that things might screw up without notice from a day to another one due automatic updates and if you don't follow all these libraries on daily basis you might find yourself in a situation where all your code needs to be rewritten ... and I guess none of us would like that much this situation ...
Shim The Spec
To avoid misunderstanding, polyfills for already official and approved specs are always welcome. This is the case of ECMAScript 5 or 5.1, as example, where things are not going to change any soon while everything related to Harmony and ES6, if the shim is even possible, should be categorized as "experimental, might not work, I knew it was going to break somewhere" ... and this is true even for what I am proposing with es6-collections: it's cool! ... and be careful, even if the shim you are using is not mine.P.S. the current version has keys and values plus does not work with edge cases such NaN or -0 when it comes to Map keys ... the local version I have is green everywhere and implements specs properly so stay tuned if you want a closer ES6 version of these constructors API while start avoiding the usage of keys and values properties if you are using that code already ( about NaN and -0 I don't bother, I think using these values as keys is an error in any case ... however, next version will have a better indexOf to match NaN and -0 too so that specs, those we know today, will be respected, forcing the implementation to do not trust native Array#indexOf and its inconsistent result when it comes to those values that are not reflective).
Last, but not least, more than asking clarification in the ECMAScript group I could not do ... so, even filing a bug in this case is kinda pointless since I don't even know what to write there except that another engine does something different about something that's not fully defined yet:
Math.pow(MEH, 31)
Friday, June 08, 2012
Asynchronous Storage For All Browsers
I have finally implemented and successfully tested the IndexedDB fallback for Firefox so that now every browser, old or new, should be able to use this interface borrowed from localStorage API but made asynchronous.
As it is, usually, values are the bottleneck, RAM consumption speaking, while keys are rarely such big problem.
However, while keys are retrieved asynchronously and in a non-blocking way, but kept in memory, respective values are always retrieved asynchronously in order to do not fill the available amount of RAM for our Web Application.
Please note that if the item was there already, it's simply replaced with the new value.
Please note that if the item was not previously stored, the returned value will be exactly null as it is for localStorage.
However, this is how I would do this task:
Asynchronous Key/Value Pairs
The main purpose of this asyncStorage API is to store large amount of data as string, including base64 version of images or other files.As it is, usually, values are the bottleneck, RAM consumption speaking, while keys are rarely such big problem.
However, while keys are retrieved asynchronously and in a non-blocking way, but kept in memory, respective values are always retrieved asynchronously in order to do not fill the available amount of RAM for our Web Application.
Database Creation/Connection
Nothing more than ...
asyncStorage.create("my_db_name", function (db, numberOfItems) {
// do stuff with the asyncStorage
});
Storing An Item
As it is for localStorage, but async
asyncStorage.create("my_db_name", function (db, numberOfItems) {
db.setItem("a", "first entry", function () {
// done, item stored
});
});
Please note that if the item was there already, it's simply replaced with the new value.
Getting An Item
As it is for localStorage, but async
asyncStorage.create("my_db_name", function (db, numberOfItems) {
db.getItem("a", function (value) {
// done, value retrieved
});
});
Please note that if the item was not previously stored, the returned value will be exactly null as it is for localStorage.
Removing An Item
As it is for localStorage, but async
asyncStorage.create("my_db_name", function (db, numberOfItems) {
db.removeItem("a", function () {
// done, no key a is present anymore
// so length is decreased already here
// and db.get("a") will send a null value
});
});
Removing All Items
As it is for localStorage, but async, and considering that only values in the specified database name will be erased, rather than all of them.
asyncStorage.create("my_db_name", function (db, numberOfItems) {
db.clear(function () {
// done, database "my_db_name" is now empty
});
});
Getting All Items Keys
If this is really what you need to do, bear in mind the API is the same used in the localStorage where indeed there's no way to retrieve all keys if not doing something like:
for (var
keys = [],
i = db.length;
i--;
) {
keys[i] = db.key(i);
}
Getting All Items
Well, the thing here is that you can store an entire object through JSON so if you need to save and get back everything, it's kinda pointless to store different keys, just use one.However, this is how I would do this task:
for (var
object = {},
complete = function () {
alert("Done, all items in the object");
},
ongetitem = function (value, key) {
object[key] = value;
if (!--j) complete();
},
i = db.length,
j = i;
i--;
) {
db.getItem(db.key(i), ongetitem);
}
On Github, Of Course
You can find full API description in this repository. Please forgive me if the name was initially db.js, I believe the new one, asyncStorage.js, is much more appropriate (also another guy created a script called db.js so ... well, I have avoided conflicts with that library).That's Pretty Much It
And I hope you'll start using this API to avoid blocking mobile and desktop browsers when you store a lot of data ;)Monday, June 04, 2012
Working With Queues
Programming with queues is basically what we do in any case: it does not matter if we write code in that way, we simply think in that way.
This means that our logic flow is generally distributed in tasks where "on case X" we apply "logic/procedure Y" .. isn't it?
Nowadays, we can say the GOTO is not needed anymore thanks to functions, where rather than thinking "when this case occurs, goto this instruction" we call the required function in charge of that specific task providing arguments or context as we go.
We may then agree that GOTO is not really a must have while functions are, with all the power and flexibility we might need, and specially in JavaScript.
Blocks are cool for partially independent operations that should not affect at all the external scope/logic but if we think more about this, the usage of inline function expressions has replaced the block-scope concept for a while.
Even better, any function in JS could be considered a sort of equivalent of a block scope, with the advantage that we can re-call the same function as many times as we want, with limits in recursions, avoiding the GOTO and still using block-scopes.
This can be easily done with a queue system, like the one showed below:
The
While this example does not show real potentials of queues based programming approach, the next one could do it.
Above code is a factorial program: all logic blocks are known in advance and the queue is constantly re-populated until the condition in the middle is satisfied.
While performances are not the best, but generally speaking performances are never a problem when a queue logic is needed, since queues are awesome specially for asynchronous tasks that are rarely good for real-time programming, this factorial program does not use recursion, is quite easier to understand and debug, and it does not blow the RAM usage: functions are recycled as well as the queue which will never grow more than 3 indexes so just wait ... and the result at some point will appear ;-)
Any sort of stack/Array not representing data, is usually a queue we consume during our logic ... promises are queues too, and same is for events, these are all queues.
Should I explain more? Probably yes, but I'd prefer if you have a look at these examples, use the simple Queue function I have written, and create something awesome that makes the logic of your app cleaner and better organized.
Last, but not least, did I mention that logging a queue gives us instantly a logic workflow of what's going on and accordingly with where it's going on?
This means that our logic flow is generally distributed in tasks where "on case X" we apply "logic/procedure Y" .. isn't it?
The Good'ol GOTO
The goto statement has been historically criticized, as well as the switch one, and in both cases is about entry and exit points in a generic workflow.Nowadays, we can say the GOTO is not needed anymore thanks to functions, where rather than thinking "when this case occurs, goto this instruction" we call the required function in charge of that specific task providing arguments or context as we go.
We may then agree that GOTO is not really a must have while functions are, with all the power and flexibility we might need, and specially in JavaScript.
On Block-Scope
JavaScript has theoretically no block-scope concept, at least until very latest versions of ECMAScript where blocks can be written in the wild.Blocks are cool for partially independent operations that should not affect at all the external scope/logic but if we think more about this, the usage of inline function expressions has replaced the block-scope concept for a while.
Even better, any function in JS could be considered a sort of equivalent of a block scope, with the advantage that we can re-call the same function as many times as we want, with limits in recursions, avoiding the GOTO and still using block-scopes.
All Together
What if we use as many functions as we need, in order to complete our flow, without compromising the external environment and being able to re-call segments of our flow when something goes wrong?This can be easily done with a queue system, like the one showed below:
A Few Examples
Here a very basic example on how to use above queue system. There are two sequential things to do, waiting for some truish condition then do something.
Queue([
function (q) {
q.wait(document.body);
},
function onBodyPresent(q) {
document.body.innerHTML = "Hello queue!";
}
]);
The
wait() method calls next "block" to execute, as next function, if any, only if the condition passed as argument is true, waiting otherwise "0 ms", if not specified differently, before the same "wait for" block logic is re-executed.While this example does not show real potentials of queues based programming approach, the next one could do it.
!function () {
var
init = function (q) {
if (!result) {
number = Math.abs(prompt("factorial of:")) || 1;
result = 1;
}
q.next();
},
verify = function (q) {
if (1 < number) {
result *= number--;
q.unshift.apply(
q,
program.slice(
program.indexOf(init),
program.indexOf(verify) + 1
)
);
}
q.next();
},
showResult = function (q) {
alert(result);
q.next();
},
program = Queue([
init, verify, showResult
]).slice(),
result, number
;
}();
Above code is a factorial program: all logic blocks are known in advance and the queue is constantly re-populated until the condition in the middle is satisfied.
While performances are not the best, but generally speaking performances are never a problem when a queue logic is needed, since queues are awesome specially for asynchronous tasks that are rarely good for real-time programming, this factorial program does not use recursion, is quite easier to understand and debug, and it does not blow the RAM usage: functions are recycled as well as the queue which will never grow more than 3 indexes so just wait ... and the result at some point will appear ;-)
Asynchronous Example
As I have said already, queues are great for asynchronous tasks helping with indentation, never too many nested functions, logical workflow, each function does a little but it does it well, readability, functions are named in a semantic way but minifiers will simply shrink them once executed, and even if this does not look that OOP, I bet once we start getting use to this approach things will be easier than ever.
!function () {
// warning: this code is a proof of concept
// it won't work as it is ...
var
// query selector shortcut
$ = function (css) {
return document.querySelector(css);
},
// while user and pass fields are empty ...
login = function (q) {
q.wait(
$("#user").value.trim()
&&
$("#pass").value.trim()
);
},
// once user and pass are not empty anymore
verify = function (q) {
var xhr = new XMLHttpRequest;
xhr.open("post", "verify.php", true);
xhr.send([
"user=" + encodeURIComponent($("#user").value.trim()),
"pass=" + encodeURIComponent($("#pass").value.trim())
].join("&"));
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
q.result = xhr.responseText;
// call next function
q.next();
}
};
},
// verify if the user exists
authorized = function (q) {
if (q.result === "ok") {
q.push(ok);
} else {
// notify the error plus re-queue logic between
// login and authorized included
q.push.apply(q, [error].concat(program.slice(
program.indexOf(login),
program.indexOf(authorized) + 1
)));
}
q.next();
},
// end of the program
ok = function (q) {
alert("Welcome!");
// could go on with the same queue
// passing through a different program
},
// warning for the user
// plus resetting fields
error = function (q) {
alert("user or pass not recognized");
$("#user").value = "";
$("#pass").value = "";
q.next();
},
// clone of the whole program
// reused later to recycle segments
program = Queue([
login, verify, authorized
]).slice()
;
}();
Where Queues Are Used
Well, almost everywhere ... Testing Frameworks are usually based on queues, specially those with asynchronous support for different tests. Same is for JavaScript or CSS loaders, based on queues when it comes to order.Any sort of stack/Array not representing data, is usually a queue we consume during our logic ... promises are queues too, and same is for events, these are all queues.
Should I explain more? Probably yes, but I'd prefer if you have a look at these examples, use the simple Queue function I have written, and create something awesome that makes the logic of your app cleaner and better organized.
Last, but not least, did I mention that logging a queue gives us instantly a logic workflow of what's going on and accordingly with where it's going on?
console.log(q.slice()) anywhere you need and you'll see all named functions you gonna deal with after the one is executing in that moment.
Subscribe to:
Posts (Atom)