My JavaScript book is out! Don't miss the opportunity to upgrade your beginner or average dev skills.
Showing posts with label check. Show all posts
Showing posts with label check. Show all posts

Friday, August 20, 2010

Object.defineProperty ... but Strict!

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

A new ES5( direction )

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

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

My Early Attempts

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

Production VS Deployment

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

Object.defineStrictProperty.production = true;

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

Object.defineStrictProperty / ies

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

How to declare a type

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

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

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

alert(myObject.name);

myObject.name = 123;

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



The meaning of "type"

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

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

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

The only exceptions are null and undefined.

How to declare a returned value

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

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

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

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

alert(myObject);

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


Multiple returns

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

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

// precedent example won't fail now


How to declare expected arguments

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

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

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

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

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

Unlimited arguments

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

Getters and Setters

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

As Summary

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

Thursday, February 05, 2009

Hunspell for JavaScript ? A quick and dirty one: BJSpell

Somebody asked me to implement a web based spell check without plug-ins or specific browsers requirement (we all know banks security policies, for example, every plug-in could be dangerous but maybe they are still using the most un-secure browser still available these days: Internet Explorer 6 ... )

My answer, straight on: Guys, there is nothing available in pure JavaScript, but I can investigate about it

That's it, a couple of searches via Google, and nothing as expected ... but hey, wait a minute: what's about FireFox spell checker plug in and Open Office project? Here we are, Hunspell is the answer!



BJSpell Project


In a full day of self brain storming, history background cases study, and code, plus debug and tests, I created BJSpell, a basic, fast, cross browser, and runtime implementation capable to underline bad words using a pre compiled Hunspell compatible dictionary (one or more).
The reason I avoided the usage of the classic "click here for the spell checker" is server stress, since the idea was to bring the spell check inside text-areas without polling with short of big texts the server and every N seconds or, the worst case scenario, on every "onkeyup" textarea event!

Pure JavaScript


To create the little speller I used JavaScript on both client and server side. In the project page you can browse the trunk branch and have a look to BJSpell.Jaxer.html page, based on Jaxer (ok, ok ... I know, just another excuse to test my PAMPA-J project ... )

A real world example page


I created a folder in my website with a BJSpell demonstration page ... wait for the cursor in the right area and try, for example, to write something like "... let's try some weirf word ..."

If you have FireFox spell check plugin with english dictionary, you will difficulty spot the difference between the left textarea and the produced output in the right div ... but what the plug-in does not do, is to show you a couple of alternatives, or close words, instead of the wrong one

What's next?


The project is in beta status, so I need your help to debug it and to understand if it has been worthy and if it is truly a good compromise between performances and result. The suggestion is not perfect, truly quick and dirty, just a basic and incomplete implementation, so we will see how and if the project will go on ;-)