One of the trickiest and most frustrating aspects of javascript coding has to be the async file-system. Where opening a file and looping through a read sequence sounds easy enough (and is in most languages) – being async means that everything is handled through events. Why you say? Because javascript is by nature single threaded, so the cpu time has to be divided between all the action that takes place inside the browser. And that includes accessing files and folders.
In short, when you open the filesystem – the actual object you get back is delivered through an event. When you want to read X number of bytes from a file, you invoke it in one place and handle the actual reading someplace else. So it’s not exactly linear and object pascal friendly to say the least.
Using the force, Sith style
To solve this I have come up with the concept of disk actions. A disk action in this case is basically an object that handles everything associated with the action you want to execute (loadfile, savefile, copy etc.) – this gives us the benefit of isolating the code that invokes the filesystem and it’s event handler(s) in one place. And those that want to access the filesystem through Smart Mobile Studio wont have to deal with the ridicules visions of the World Wide Web Consortium (WC3).
My wrapper aims at handling things like this:
[sourcecode language=”delphi”]
FFileSystem:=TW3FileSystem.Create;
try
FFileSystem.open(5 * CNT_MEGABYTE,fstPersistent);
try
FFileSystem.Execute(TW3OpenFileAction.Create
(‘prefs.ini’,IniFileRead);
finally
FFileSystem.close;
end;
finally
FFileSystem.free;
end;
Procedure IniFileRead(sender:TObject;aData:TW3Buffer;
aFilename:String);
Begin
//File is read into a buffer (actually a "blob"
//Use the methods of TW3Buffer and TW3View(ers) to
//access the data in "reader" style
w3_showmessage(aData.toString);
end;
[/sourcecode]
But due to the nature of the javascript callback system, we probably have to move several aspects of the above into events. But at least I will isolate the events in one object, making it a hell of a lot easier to work with than native javascript.
For example, “FFileSystem.Execute” wont be a legal call in the above example, because it will be executed before the event which delivers the file-system native object has called us back. To solve this I have some tricks up my sleeve – but I think it’s wise to play it safe when it comes to building a new RTL from scratch. So expect some event management.
The answere is 42
I also built in a fail-safe for error codes. As I was testing the same code in both Chrome, Safari and FireFox – i noticed that the error codes where different between two browsers (which shall remain anonymous but involves a fox and some iron). The error names were the same (e.g: FileError.QUOTA_EXCEEDED_ERR) but the integer values could differ.
So instead of just hard-coding the numbers I used the newly added TW3Dictionary object(s) to map the error codes in the browser to it’s Object Pascal type enumeration. So even if the browser alters the actual error code our code will work just fine.
[sourcecode language=”delphi”]
//Register known errors in the constructor
FErrors:=TW3IntDictionary.Create;
registerError(fseQuotaExceeded);
registerError(fseNotFound);
registerError(fseSecurity);
registerError(fseInvalidModification);
registerError(fseInvalidState);
registerError(fseUnknown);
//Do evil things with butter
Procedure TW3FileSystem.RegisterError(aKind:TW3FileSystemError);
var
mKey: String;
Begin
if supported then
Begin
try
mKey:=IntToStr(ErrorToNative(aKind));
FErrors.Values[mKey]:=ord(aKind);
except
on e: exception do
Raise EW3Exception.CreateFmt(CNT_ERR_METHOD,
[‘RegisterError’,ClassName,e.message]);
end;
end;
end;
[/sourcecode]
Thank god I only have the audio and video objects left to wrap, because I’m getting a bit tired of low level javascript. But the foundation is getting tweaked and polished (Primoz Gabrijelcic have really given it a run for it’s money, testing every avenue and tidbit in the framework. I dont think I have ever seen a person consume and adapt to information that fast. Also the wizard of code which is Eric Grange is ever watchfull and actually knocked out a full game in under a day after release), so when the foundation is done for version 1.0 – I can fully dedicate myself to high-level component writing.
Having said that — there is plenty of room for you guys to create your own units and start creating components for Smart Mobile Studio!
So far people have created games, advanced mandelbrot explorers, particle systems, hacker group demos and even classes that connect directly to RemObjects services (!) – and we aren’t even out of the alpha phase. Imagine what version 2.0 will look like. Buckle up dorothy because we’re just getting started (!)
Oh almost forgot.. Whenever I have the spare time, I will be implementing a converter for .mod music files (sound-tracker, pro-tracker: those old sample based music files). Im not sure the JS timer system is up for the challenge, perhaps we have to use web-workers (threads) to handle the dispatching – but I really want to add the frosting on the cake later on. No one has ever done anything like this in Javascript – so why not send a spartan to do it 😉
Fair play
And please. Try to avoid copying software. We are a two man company and have dedicated a lot of resources to polling this off. If you use it in some way – please support our work and buy a license when it’s released. If you want your friend to try it out then just ask us and he can register with the alpha team. We hear code written in Smart is already being used in production scenarios, and it’s sort of self-defeating for the community if what we hear is true.
Our prices will be very reasonable. Somewhere between $200 – $400 for the first version which is very humble concidering 6+ months of work has gone into research, figuring out how to do things, building a model and bridging technologies.
Smart Mobile Studio is becoming a weapon of mass construction – ok so let’s show those javascript punters what were made of 🙂