Jump to content

Create lib in Smart for using from pure javascript?

Recommended Posts

Is that possible to to create some framework in smart, consisted of some classes, functions, ect.,


then compile-obfuscate it in single *.js file, and than use it as a library from another module written in pure javascript?


If so, how it can look like? Need special external difinition?

Is there a special type of project-library in smart?

Please answer - it is very important for me.

Link to post
Share on other sites
  • Administrators

Well. It depends on what you're planning, and what you're trying to achieve...


To me, it sounds like your going down the wrong path with this approach.


The generated JS code is pure JS, and thus it can be used in any web-framework. (The node.js solutions we run "in the labs" is an example of that). You need to do a bit of cut'n'paste, to extract the JS-code, but that's the easy part. Just look at the "Source code" tab when you run a solution in Smart. You'll recognize the classes and variables immediately.


The problems will emerge when you're trying to maintain the interface between the generated Smart JS code and the environment where you want to use this code. And if you compile with obfuscation, I would say that that is impossible. That's the whole point of obfuscation...


If you just want to run various Smart-widgets on your web-side, then you could simply use iFrames as container for your Smart-solution. Just like we have done here:

(Those "screen-shots" in the articles are interactive. Hit "Execute", "Toggle" and "Start demo" to see them in action.)

- http://smartmobilestudio.com/Smartdemo/AnimLogo/iframe.html

- http://smartmobilestudio.com/2013/02/08/design-patterns-observer/

- http://smartmobilestudio.com/2013/01/30/smart-graphics-part-4/


We're also working on a "Compile to DIV" solution which would compile the solution into a DIV-tag instead of a complete HTML-document. That would make it possible to include Smart widgets directly as an individual DIV-element...


Please send us an e-mail directly to support@smartmobilestudio.com if you want to discuss your needs in private...

Link to post
Share on other sites

Forget about obfuscation,


jast take a look at any js lib - they usualy comes in 2 types:  uncompressed -  for development, and minified  - for embedding  in any ready project.


I just want using Smart to DO:


1) Translate my existing delphi-freepascal framework  (like thousands others in internet) , then compile it in single javascript file, not *. html, just *.js - like it would be in delphi: *.dll - pure code.


2) After that any end-user using my standalone programm *.exe written in delphi, could do some job inside it and as result of this job will be 3 parts: custom JSON objects + js lib-framework + some user js code. User js code will be  responsible  for the behavior of elements in the processing of any events.


3) Or there is a third way not too good for me, but: to compile the final project on the fly from my program using the command compiler, which announced by you in roadmap.


Or better: can you also deliver Smart as a separate dll runtime library to do the same job.  Are some of this variants possible?


For now i deeply dig typescript, and start translate my lib to js with it, (it's hard, but not impossible :)


BUT i realy-realy would like to do it on dws-smart - and think in near future if my prog will be at least a little successful - it will can add mach popularity to Smart.

Link to post
Share on other sites

One way to such libraries is to declare the classes you want to expose to the outside as subclasses of JObject (for JObject, see http://delphitools.info/2012/10/03/re-rooting-object-pascal/), those can be consumed by other JS directly, and are immune to obfuscation (so you can have internal implementation details se Pascal classes and be completely obfuscated).


This however requires to "tweak" the main program (dpr equivalent) which currently is only autogenerated in the SMS IDE, basically to have something equivalent to the export clause in Delphi dpr for dlls, to list what classes & functions are visible to the outside, or attach them to an .existing namespace (f.i. you could attach them to jQuery to work as a jQuery plugin).


You'll also have to strip-down the default.html template to its bare-bones (just %appcode%), and rename it to ".js".


I'll try to whip up a demo.

Link to post
Share on other sites

Thanks for demos.


As you noted right, my framework don't need to use most or maybe even part of vjl rtl units, because the same ones already done in my framework as i need. But some of them i can use. Is that possible don't include in result js lib unnecessary modules? Or it will be done automaticaly by compiler-linker? If js module will be large - it will be uncompetitive compared to other frameworks, and there is no any reasons for me do it this way :(


Also is that possible to add to compiler next option: don't generate in result programm (lib) html tegs and other unnecessary things, to avoid cut it by hands every time after compiling?

Link to post
Share on other sites
  • Administrators

We don't have these issues explicitly in our Roadmap.


Regarding the "bloat" in the generated JS code, I think "Smart linking" would take care of this for you. I.e. the classes and methods you don't refer to won't be included.


If you further write the "JS interface" as an JObject based adapter around your library, it should be possible to compile with obfuscations as well. I.e. compress your library, but not the JS-API.


In general, we're always trying to make the compiler as smart and efficient as possible. If we experience (eg trough user feedback ;-)) some issues that could be optimized - we will try to optimize those issues.



W.r.t. your second suggestion: I don't it's necessary to add this as a compiler option. In v1.1 we have template-based project types. Thus, it should be possible to create a new custom project type that covers most of these issues regarding a "simple project". Further, we are working on the command-line compiler, and this will probably be ready for version 1.2. That means that it will be possible to include the Smart Compilation into any build-script and perform some automated post processing on the generated result.


(Btw, you can actually automate the compilation of Smart projects in v1.1, too. We've added three cmd switches /C /E /Q (Compile, Execute, Quit). So, if you run "SmartMS.exe %1 /C /Q", you will: Start SmartMS, Open project %1, Compile the project, and finally Quit the IDE)


We're planning to include a simple "build script tool" in the Smart IDE, but we haven't pinned this feature to any release yet...



What we do have in our roadmap, is full support for node.js. (http://smartmobilestudio.com/2013/01/04/updated-roadmap/). Even if this is something completely different, I think many the features you are need will be covered out-of-the-box in that release. :-)



I like your thoughts, but we never created Smart to solve such issues. I hope we can get it to work for you right now with some tweaking, and that we can fully support it within a few updates.

Link to post
Share on other sites

I would also find compiling into a js library very useful. it will allow smart to work with a lot of the existing js code base seamlessly. not that I need it right now but it could certainly be very helpful at some point. so in my opinion this feature definitely deserves a milestone on the roadmap.

Link to post
Share on other sites
  • 11 months later...



I have three rather extensive libraries written with SMS. I have been developing with obfuscation, packing and smart linking OFF. Using i am doing a little test with a JObject class as an "interface/exposer" between my TObject-based classes and the "JS World" in the html.


I can say that calling a function of an instantiated class from the JObject based class does not work with smart linking. Though it works with packing and obfuscation.


Having this work in 2.0 would be a boon. Smart linking shrinks stuff extremely.


What happens is that the compiler does not keep in mind that i'm calling "Instance.Function()" from the JObject class and "smartlinks" it away from the TObject based class.


Keep up the great work!

Link to post
Share on other sites

Thanks AndreM for the hint!


I was going to try your suggestion (i had/have the impression "published" should be used in the TObject descendant since that is the method that gets smart linked away and the JObject descendant is untouched by linking and obfuscation).


But unfortunately my licensce have expired this morning :(

Link to post
Share on other sites

Sorry AndreM, published does not cut it. Tried something like this with the latest beta;

TMyInner = class(TObject) 
  procedure Init; 

TMyInterface = class(JObject) 
  procedure Init; 

  MyInnerInstance:  TMyInner; 


procedure TMyInterface.Init; 

(FYI, Both classes are instantiated properly in the initialization section).


(Apologies for any typos, i wrote that into WordPress).


When running this code in the browser it fails with "Uncaught TypeError: Object #<Object> has no method 'Init'" when executing the following (IMHO correctly generated) JS:

/// procedure TMyInterface.Init() 
 "Init" : function() { 

so as i guessed it is not a problem i the JObject descendant. The Init procedure in the TObject descendant gets smartlinked away :(




Any ideas?



Link to post
Share on other sites

yeah, because the "Init" procedure isn't called (from the compiler view) the whole class is optimized away. I could get it working by referencing the class somewhere like this:


var dummy: TMyLib;

var inner: TMyInner;

so in the meantime you should reference all possible classes this way...


Note: this works too (but is never executed :) )


var dummy: TMyLib;

if (1=2) then


Link to post
Share on other sites

I might not express myself clearly enough :) I wrote "Both classes are instantiated properly in the initialization section" so the differences between your first suggestion (above) and my implementation as current is that i declare the TMyInner type variable in the interface section. I also do not declare any variable of type TMyInterface/TMyLib. I tried that and it does not work.


However, you second idea works (using the variable of type TMyInner declare in the interface section).


You write "yeah, because the “Init” procedure isn’t called (from the compiler view)" but the difference between the hack "if (1=2) then ..." and my code sample is that Init is referenced but from the TMyInterface/TMyLib.Init procedure body. Since TMyInterface/TMyLib is a JObject class i can understand why the compiler sees that as said procedure is not being referenced. But IMHO either the fact that this is a JObject descendent or the fact that i declared all of these procedures "published" should be enough.


Also; they way i got you hack to work for me was by referenceing the TMyInner set of procedure, not the TMyInterface/TMyLib members. The JObject descendant should not have to be instantiated from sms code. A library user might want to use JS new on that class.


Don't you think?


Anyway thanks for a working workaround!


Aside: My js file is 110770 bytes in "debug" mode, 44391 with packing and obfuscation and 18892 bytes with packing, obfuscation and smart linking. The last delta will of course vary a lot depending on what units are included and such - but it is clearly a big gain.

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Create New...