30

I installed Titanium from appcelerator and built the "KitchenSink" example application.

All works well, I'm just wondering where does the javascript code ends up in a built app.

I grep-ed the Xcode project and also the result application as I found it in Library/Application Support/iPhone Simulator/....KitchenSink.app, but I can't find any function names from .js files, not even string texts used within the application.

Nearest information I found is an answer here : How Does Appcelerator Titanium Mobile Work? but I do not understand clearly how the process works.

Is the javascript code being compiled into a binary code (what compiler is used then?), or is it just transformed in some special data-format and interpreted in a running application ?

Update:

This is what I can see in a build/android directory of KitchenSink:

michal:bin mac$ find . -name table_view_layout\*
./assets/Resources/examples/table_view_layout.js
./assets/Resources/examples/table_view_layout_2.js
./assets/Resources/examples/table_view_layout_3.js
./assets/Resources/examples/table_view_layout_4.js
./assets/Resources/examples/table_view_layout_5.js
./classes/org/appcelerator/generated/examples/table_view_layout.class
./classes/org/appcelerator/generated/examples/table_view_layout_2.class
./classes/org/appcelerator/generated/examples/table_view_layout_3.class
./classes/org/appcelerator/generated/examples/table_view_layout_4.class
./classes/org/appcelerator/generated/examples/table_view_layout_5.class
michal:bin mac$ unzip -t app.apk | grep table_view_layout
    testing: assets/Resources/examples/table_view_layout.js   OK
    testing: assets/Resources/examples/table_view_layout_2.js   OK
    testing: assets/Resources/examples/table_view_layout_3.js   OK
    testing: assets/Resources/examples/table_view_layout_4.js   OK
    testing: assets/Resources/examples/table_view_layout_5.js   OK

I didn't look into app.apk before, all I could see were these class files corresponding to each of the javascript files. Therefore I assumed that on Android javascript is being compiled for JVM. Why can't these be found in app.apk ?

Community
  • 1
  • 1
Michal
  • 4,846
  • 3
  • 33
  • 25
  • 1
    I might be wrong here but when I tried Appcelerator for Android a few months back I got the impression the javascript code wasn't compiled at all. Instead it was shipped with the .apk-file together with a javascript-interpreter that ran the javascript code during run-time. Why else would they include the javascript code in the apk-file at all in the first place? – Fredrik Wallenius Nov 19 '10 at 22:04

2 Answers2

47

Titanium is not a wrapper around a web view as stated before (though that accurately explains how Phonegap works). Jeff's answer, linked in the question, is a technically correct explanation of how Titanium works, but here's the best version I've heard so far, from Marshall Culpepper:

It's true that Titanium Mobile used the WebView (in both Android and iOS) in the pre-1.0 days. However, this is no longer true and hasn't been since our 1.0 release is March 2010.

Since 1.0, we've shipped two separate Javascript runtimes with our apps, and we are running the Javascript code directly without a WebView. Your entire app from start to finish is now controlled by JS, and we provide a comprehensive set of Native APIs that enable this. Everything from UI widgets (yes, including WebView), Core APIs like Networking, Filesystem, Database, all the way to OS-specific things like JS Activities in Android. On the JS runtime front, we're shipping a forked version of WebKit's JavaScriptCore in iOS and a snapshot of Rhino 1.7 R3 CVS for Android. What we actually do with your javascript source is dependent on the platform, but generally it breaks up like this:

  • Source is statically analyzed to find references to Titanium modules
  • Localization strings (strings.xml), App metadata (tiapp.xml), and density specific images all generate platform specific analogs.
  • In iOS:
    • An XCode project / configuration is generated
    • JS Source is base64'd and inlined as a variable into a generated C file
    • xcodebuild is used to generate the final binaries
    • provisioning profiles, signing keys etc are applied
    • iTunes and some other glue are used to send the IPA to your iOS device
  • In Android:
    • An Android / Eclipse project is generated
    • In "Development" mode, JS source is packaged as APK assets
    • In "Distribution" (production) mode, when you're ready to ship the app, we compile the JS to Java bytecode using the Rhino JSC compiler. You can also enable this during development mode by setting "ti.android.compilejs" to "true" in tiapp.xml, see: http://developer.appcelerator.com/question/100201/enable-android-byte-code-compile
    • dex, aapt, and other Android SDK tools are used to build and generate the final APK
    • adb and keytool are used for pushing the APK out to the emulator and/or device

There are many more details that I could dive into specifically on each of these points, but the point I wanted to drive home is that we no longer use the WebView as our Javascript engine. You can however still embed WebViews, and we provide some simple integration that allows you to call Titanium APIs from an embedded WebView.

Kevin Whinnery
  • 1,209
  • 10
  • 11
  • Whether, the Source Code "HTML CSS & JS" of a "Appcelerator Desktop App" can be seen in "Windows OS"?? – cupcake Mar 09 '11 at 07:04
  • 1
    If the question is "Can the HTML/CSS/JS of a Titanium Desktop application be viewed on Windows (or any OS)" the answer is currently yes. We don't provide any automatic encryption or inclusion of source in the binary, but we may do so in the future. In the meantime we recommend that folks combine, minify, and obfuscate their JavaScript source. – Kevin Whinnery Mar 23 '11 at 14:25
4

What jhaynie is saying in your linked question is that Titanium interprets your JS code and converts it into something that is almost identical to Objective-C.

In a web application, the browser reads and interprets your Javascript and runs associated native code (perhaps C++) internally. For instance, the browser might say, "This script is executing getElementById(), so I'll run my own C++ methods to accomplish that." What Titanium is doing is figuring out what that JS->C++ (or in this case, JS->Objective-C) would be in advance, and compiling that. It still leaves an interpreter open where necessary for your dynamic code, but it will convert and compile what it can.

That means you won't find anything that looks similar to what you originally wrote in your script. Anything that must be left to an interpreter is still processed and converted, and your symbols will change (e.g. a call to myTestFunction() might be converted to A(), or 10001101001101 :P).


The usual use of Javascript is to have it interpreted real-time by a running program. That's not what's going on here, and that's why you can't see any trace of your script.

  • Javascript is pre-processed

    Titanium performs the interpretation of your script as any other program would do (such as a web browser). It figures out what dependencies your script has on the Titanium API and sets that stuff up. It then maps your symbols directly into (in the case of the iPhone) Objective-C.

    A program usually would read in your script (which is a simply a String), interprets it, and runs C code to accomplish what your script asked for. Titanium does this before-hand to figure out what C code should be run, and does the conversion in advance.

  • Code is compiled where possible

    Based on the interpretation of your code and its dependencies on the Titanium API, Titanium figures out what code can be directly compiled, and what must not be compiled in order to allow for they full dynamics of Javascript. I don't know how it chooses what does and doesn't get compiled, but you could check out the source if you want to know that much detail.

    Code that must still be interpretted (left as a script) is still converted into symbols that result in more efficient mapping to native code. So it's still an interpreted script, but that doesn't mean it's still Javascript. This means that these parts of your script will still run faster than usual Javascript.

    For iPhone, the compilable C is compiled with GCC to create a native binary.

  • You have a runnable app*

    Now you have an app that you can run on your mobile device. Your compilable code has been compiled and runs at lightning speed, while the rest is converted and still interpreted in a more efficient way which runs at near lightning speed. :P

  • I hope this makes sense now, because it's all I've got! :D

    Brendan
    • 1,853
    • 11
    • 18
    • 1
      This still is very confusing. Compilation is a process of converting source code written in a programming language into object code - executable code. How can a part be compiled and other part not. By what means is the compilation done, does it generate objective-c and compiles that with gcc ? Is the javascript converted into some structure which is then being interpreted in a running program ? – Michal Nov 19 '10 at 10:13
    • I'll try to add another simplified version to my answer above. Much of it will be redundant... – Brendan Nov 19 '10 at 20:01
    • Brendan, thank you for a useful explanation. Your answer might be good enough for people with background in web development, but it doesn't cut it for me coming from the other side of programming. I'm not aware of any javascript compiler so I doubt anything is really compiled. I checked what Titanium generates for Android and there I see a generated jvm `class` file for each `js` script. Well, java always gets interpreted, so on that platform that's a natural way of doing. I think they use `jsc` to compile it. But how does that work for iPhone - I do not see anything being generated there. – Michal Nov 20 '10 at 12:54
    • Peter Knego: I edited the question with explanation on how I came out with idea of compiled javascript. Anyway, you might be right that it's not used in final product - then why is it produced in the build ? – Michal Nov 23 '10 at 20:58