Hi all,
I'd like to describe the current state and new features in the
dependencies branch.
It was derived from
MCB branch, and have a slightly different kernel organization:
http://joose-js.googlecode.com/svn/branches/dependencies/doc_images/Kernel%20Organization.pdfThe primary change is that Class becomes isa Namespace (refactored from Joose.Module).
The new features, which follows from that change are below:
================================
1) Module call now accept props as 2nd argument, the former function at this place is now default for "body" property
(Class also has now this property)
Module('Test', function(){})
eq
Module('Test', {
body : function(){}
})
================================
2) Module can be promoted to Class
Module('Test', {});...
Class('Test', {});================================
3) Class can have further Modules/Classes in namespace chain:
Class('Test', {});
...Module('Test.Testy',{});...
Class('Test.Testy.Testier',{});================================
4) Modules and Classes can be freely nested (the same as above in pseudo code):
Class('Test', {
Module('Testy',{
Class('Testier',{
...
}); });});
Collisions between namespace elements and class methods are detecting and exception throwing.
Generally speaking, the Module is a namespace, the Class operates as "default constructor" in its Module.
The actual dependency handling was implemented at Module level, via "use" property and works as follows:
Class('Test', {
use : [ 'Test.Testy', 'Test.Testy.Testier']
});...
Module('Test.Testy',{
use : 'Test.Testy.Testier'});
...
Class('Test.Testy.Testier',{});
The algorithm is based on Observable pattern and was already implemented in
jScout, so I just cleared it from Ext dependencies and integrated into Joose.
Dependencies are loaded asynchronously and simultaneously. The "body" property of each call to Module, will be executed after the all dependencies of module (even from multiple calls to Module) were loaded.
Also was implemented a simple versioning scheme (version numbers are compared using usual "<" operator without any assumptions about format).
Class('Test', {
version : 0.1,
use : [ { Module : 'Test.Testy', version : 0.2} , 'Test.Testy.Testier']
});
...
Module('Test.Testy',{
version : 0.2,
use : { Module : 'Test.Testy.Testier', version : 0.3}
});
...
Class('Test.Testy.Testier',{});
There is a stress testing suite for this, which passes FF, IE6,7 and Chrome. Safari passes also, but fails in another part of suite.
http://joose-js.googlecode.com/svn/branches/dependencies/tests/libroot/StressTest/
quick link to whole test suite:
http://joose-js.googlecode.com/svn/branches/dependencies/tests/test.htmlCurrently, implemented only loading via dynamic <script> tag. This approach benefit from being free from same-origin policy, but suffer from that fact, that its impossible to detect the errors (wrong URLs for example)
TODO:
- circular reference detections
- errors detections (seems possible not in all "transport mechanisms")
- more "transport mechanisms" (via async/sync Joose.SimpleRequest or external AJAX calls for example)
- "external" scripts support (3rd party apis, like GMap, etc)
- improved versioning? (possible including version in the URL, to avoid browser caching, when the version was increased)
- server-side librarian component, which will allow to load Class with any number of recursive dependencies in 2 http calls
There are probably more features to implement.
P.S. During work on this branch, I've encountered the issue with current Test.TAP.Class implementation. Test.TAP.Class execute all tests in the same global scope and clears it after each test.
This way the async tests, which relied on the presence of certain globals fails. This was fixed with dirty hack, and probably requires a better solution.
Regards, Nickolay