Created
June 30, 2009 04:43
-
-
Save tav/137997 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| the basic idea is that we encapsulate Objects and primitive types into an API that allows dynamic binding of properties, methods, etc | |
| [09:28] marshall_law: our entire runtime uses the binding API for all exposing | |
| [09:28] marshall_law: so it's basically the common runtime model for Python, Ruby, and Javascript | |
| [09:28] marshall_law: the language runtimes entire job is to adapt their language runtime to our binding API | |
| [09:29] tav: is there any dom specific integration ? | |
| [09:29] marshall_law: we have some custom code that exposes the window object etc back into each language runtime yes | |
| [09:29] marshall_law: we expose window, and document i believe | |
| [09:30] marshall_law: and of course, Titanium) | |
| [09:36] tav: i was going to ask how you handle dom events | |
| [09:36] marshall_law: we don't do anything special for DOM events.. | |
| [09:36] marshall_law: (yet) | |
| [09:36] marshall_law: basically, users have access to the window object, so they have access to the event handling mechanisms | |
| [09:36] marshall_law: at least, some of them | |
| [09:37] marshall_law: one thing that would be interesting to try.. setting window.onload in python | |
| [09:37] marshall_law: i don't think i've ever tried it | |
| [09:38] tav: for example, let's say we want to interact with setting up onclick handler which calls a foo-lang function... | |
| [09:38] tav: with access to query the dom... | |
| [09:39] tav: how would that work through the binding api ? | |
| [09:40] marshall_law: well, everything is wrapped and delegated basically | |
| [09:41] marshall_law: so first thing that happens is user calls or includes some ruby code through our webkit binding | |
| [09:42] marshall_law: we subsequently boot up the ruby runtime, and we instantiate a special KJSObject, which is a wrapped javascript object that conforms to our binding API of the DOM's window context | |
| [09:43] marshall_law: we then have a ruby adapter that can take any KObject (our binding object type), and expose it to ruby | |
| [09:43] marshall_law: so our binding API is basically the lowest-commond-denominator | |
| [09:44] tav: the special object does some kind of automatic reflection ? | |
| [09:44] tav: how does it know how to handle the various types that may be passing through ? | |
| [09:44] marshall_law: well, the ruby runtime gives us type information about each object | |
| [09:45] marshall_law: which we use to intelligently decide what type of object we'll be wrapping | |
| [09:45] marshall_law: in general, we break everything down to it's basics | |
| [09:45] marshall_law: if it's an object, we don't care about the type, we just delegate to it's methods and properties | |
| [09:46] marshall_law: if it's a list, we give the language-dependent version of it | |
| [09:46] marshall_law: etc | |
| tav: hmz, i can kind of understand the ruby -> dom side, but i'm trying to understand the dom -> ruby side | |
| [09:47] tav: aren't there tons of dom calls that need to be mapped? | |
| [09:49] marshall_law: nope | |
| [09:49] marshall_law: everything is done on the fly at runtime | |
| [09:50] tav: but c++ isn't a dynamic language? | |
| [09:51] marshall_law: hehe | |
| [09:51] marshall_law: our binding API stores all the metadata | |
| [09:55] marshall_law: well, it starts off purely virtual in KObject (kroll/api/binding/kobject.h) | |
| [09:55] marshall_law: it's a pretty dynamic system | |
| [09:56] marshall_law: so KObject is an abstract class, basically you can write your own custom logic to implement your Object's model | |
| [09:56] marshall_law: basically there's 3 main methods | |
| [09:56] marshall_law: or, 4 | |
| [09:56] marshall_law: Get("property") | |
| [09:56] marshall_law: Set("property", Value) | |
| [09:57] marshall_law: Value Call(ValueList args) | |
| marshall_law: or actually, Call is added in KMethod | |
| [09:58] marshall_law: so a property can actually be a data type (i.e. a member variable) | |
| [09:58] marshall_law: or it can be a method | |
| [09:58] marshall_law: we have an aggregate type called Value that encapsulates all possible types in the binding API | |
| [09:58] marshall_law: Value is used in all of the APIs when expecting a value of some kind | |
| [09:58] marshall_law: and we use shared pointers everywhere | |
| [09:59] marshall_law: (for auto counting / freeing references etc) | |
| [10:00] tav: k, with you so far | |
| [10:02] marshall_law: so.. | |
| [10:02] marshall_law: hmm where to go from here | |
| [10:02] marshall_law: so to circle back around abit.. | |
| [10:02] marshall_law: each language runtime has it's own subclass of KObject | |
| marshall_law: which delegates directly into the native runtime | |
| [10:03] marshall_law: for instance RubyObject::Get(name) -> rb_iv_get(name) | |
| [10:05] marshall_law: and vice-versa | |
| [10:05] tav: vice-versa ? | |
| [10:05] marshall_law: when we pass in the window context to the ruby runtime, we construct a native object that delegates to KObject | |
| [10:05] marshall_law: well, we have a generic function that will wrap KObject with a ruby object | |
| [10:06] tav: aha | |
| [10:06] marshall_law: we just pass the window context into that guy, and then bind his value into a global variable | |
| [10:06] tav: so, the webkit api provides a direct window context (an object?), from which you can access the whole dom ? | |
| [10:06] marshall_law: yup, there's a javascript context that we deal with.. | |
| [10:06] marshall_law: JSContextRef is the type | |
| [10:07] marshall_law: it represents the javascript global context (also known as "window") | |
| [10:07] marshall_law: basically | |
| [10:07] marshall_law: we have these delegates in each platform | |
| [10:07] marshall_law: that we bind into webkit through the API | |
| [10:08] marshall_law: the delegates get called when the context for each page is ready | |
| [10:08] marshall_law: at that time we store the context, and bind ourselves into | |
| it | |
| marshall_law: then when the user loads up a script, our script evaluator patch passes back the context from which the script was loaded | |
| [10:09] marshall_law: and we in turn wrap him with the function i mentioned above, and then expose him before evaluating the language source | |
| [10:10] tav: nice -- i like the elegance of the approach! | |
| [10:10] marshall_law: | |
| [10:10] tav: but, doesn't this mean that every call has to go through the js interpreter? isn't there direct access to the dom? | |
| [10:11] marshall_law: everything goes through the runtime, not the interpreter | |
| [10:11] marshall_law: (the native runtime) | |
| [10:11] marshall_law: direct access to the DOM is just as direct as it is in Javascript | |
| [10:12] marshall_law: we delegate to the same functions that the javascript runtime binds to | |
| [10:12] marshall_law: or, their equivalents in public JavaScriptCore API | |
| [10:12] tav: ah | |
| [10:13] tav: alright, how do i write a binding? | |
| [10:13] marshall_law: that's the challenge! | |
| [10:13] marshall_law: | |
| [10:13] tav: damn your seductiveness | |
| [10:13] marshall_law: so you'll need to get started by first writing the module | |
| [10:14] marshall_law: which is pretty trivial, but it's the entry point for your shared library | |
| [10:14] marshall_law: basically i would follow the example laid out by python_module/ruby_module | |
| [10:14] marshall_law: one more thing i should mention | |
| [10:14] marshall_law: the other aspect of kroll is the module system | |
| [10:14] tav: this being how ti.Foo and all is created? | |
| [10:15] marshall_law: well.. | |
| [10:15] marshall_law: modules can really do anything | |
| [10:15] marshall_law: basically they're just shared libraries, with a lifecycle | |
| marshall_law: Start/Stop | |
| [10:16] marshall_law: that's exposed through the exports of the library | |
| [10:16] marshall_law: most of the hairy stuff is taken care of with the macros | |
| [10:16] marshall_law: KROLL_MODULE(MyModule) | |
| [10:16] marshall_law: KROLL_MODULE_CLASS() | |
| [10:16] marshall_law: etc | |
| [10:17] marshall_law: kroll has pretty good module resolution | |
| [10:17] marshall_law: the idea is that no matter what state your environment is in, kroll can figure out what it needs to do to resolve a specific module dependency | |
| [10:18] marshall_law: it can do net install, app-bundled, or system installed modules | |
| [10:18] marshall_law: but, i digress | |
| [10:18] marshall_law: really, the point of a module is to expose API through the binding layer | |
| [10:18] marshall_law: though it can practically do anything (it's just native code) | |
| [10:19] marshall_law: language modules however, are a little special | |
| [10:19] marshall_law: one other feature modules have, is they expose their own ModuleProviders | |
| [10:20] marshall_law: a ModuleProvider is exactly what it sounds like.. a class that can instantiate and run it's own custom modules | |
| [10:20] marshall_law: this concept was invented solely for the language runtimes | |
| [10:20] marshall_law: it allows us to expand the module system through the language runtimes | |
| [10:21] marshall_law: so all 3 runtimes we support , include language module support | |
| [10:21] marshall_law: i.e. you can write a module in javascript, or python, or ruby | |
| [10:21] tav: is there an example of this? | |
| [10:21] marshall_law: yup | |
| [10:22] marshall_law: the PythonModule class itself is a ModuleProvider (and a Module) | |
| [10:22] marshall_law: basically module provider exposes 2 functions | |
| [10:23] marshall_law: IsModle and CreateModule | |
| [10:23] marshall_law: isModule * | |
| [10:26] tav: CreateModule in python_module instantiates a new PythonModuleInstance defined in python_module_instance ? (it seems to be skeleton atm) | |
| [10:26] marshall_law: hahaha | |
| [10:26] marshall_law: so it is | |
| [10:26] marshall_law: oh man | |
| [10:27] marshall_law: that's funny | |
| [10:27] marshall_law: checkout javascript_module_instance | |
| [10:29] tav: cool | |
| [10:29] tav: so why is this separate to the script evaluator ? | |
| [10:29] marshall_law: well, modules have a different life cycle than scripts loaded in the page | |
| [10:29] tav: they seem to be similar -- or am i missing something | |
| [10:29] marshall_law: modules get started at microkernel boot time | |
| [10:30] marshall_law: i.e.. as the app is still starting | |
| [10:30] tav: ah | |
| [10:30] marshall_law: basically, a module's job is to expose API to your app | |
| [10:30] marshall_law: a user-script's job is to be logic for the app | |
| [10:31] marshall_law: of course, they can both be used however you like | |
| [10:31] tav: *nod* | |
| [10:31] marshall_law: there's nothing preventing users from exposing API in a script included from HTML | |
| [10:31] marshall_law: the beauty of modules though is there isn't a need for UI, which will be much more interesting when we get some more free time to explore some ideas we've had | |
| [10:32] tav: speaking of UI, can this be used to create a module for example which takes a "frame" from an mplayer frame server and "renders" it on a loaded page? | |
| [10:33] marshall_law: hahahhaa | |
| [10:33] marshall_law: well..... | |
| [10:33] marshall_law: i suppose yes, you could render using canvas | |
| [10:33] marshall_law: that would be a really neat proof of concept | |
| tav: presumably <video /> implementation uses some kind of internal webkit API ? | |
| [10:35] tav: if this could be exposed as a KObject ... ? | |
| [10:36] tav: or is it simply tied down to just the context object? | |
| [10:36] marshall_law: internal javascript API ? | |
| [10:36] marshall_law: or native? | |
| [10:36] tav: native | |
| [10:36] marshall_law: we'd have to expose it up then.. | |
| [10:36] tav: speaking of the context object, where exactly is it "exposed" ? | |
| [10:36] marshall_law: if it's not in javascript, we don't capture it | |
| [10:37] marshall_law: lemme see | |
| [10:37] tav: thx | |
| [10:37] marshall_law: oh. | |
| [10:37] tav: this has been really enlightening btw! | |
| [10:37] marshall_law: python_evaluator.cpp | |
| [10:37] marshall_law: PythonEvaluator::Call | |
| [10:38] tav: hmz, that's the webkit -> python call? | |
| [10:39] tav: sorry, i was wondering about the wrapping of context into a KObject | |
| [10:42] marshall_law: ooh | |
| [10:43] marshall_law: what platform you want it for ? | |
| [10:43] marshall_law: OSX? | |
| [10:44] tav: sure | |
| [10:44] marshall_law: basically you'll want to look at modules/ti.UI/osx/webview_delegate.mm WebFrameLoadDelegate::inject | |
| [10:44] marshall_law: it's an objective-c method | |
| [10:45] marshall_law: actually the win32 method might be a little more straight forward | |
| [10:45] tav: webkit has platform specific internal apis? | |
| [10:46] marshall_law: modules/ti.UI/win32/webkit_frame_load_delegate.cpp Win32WebKitFrameLoadDelegate::didFinishLoadForFrame | |
| [10:46] marshall_law: yeah, the public webkit APIs are all platform specific | |
| [10:46] marshall_law: this was one of the complaints i was mentioning last night | |
| [10:48] marshall_law: it's a little silly | |
| [10:48] marshall_law: the APIs all follow the same naming/lifecycle/standards | |
| [10:48] marshall_law: they just use platform-specific types instead of cross platform types | |
| [10:49] marshall_law: like COM and BSTR in windows, or NSString* in OSX | |
| [10:49] marshall_law: or pure C / glib in linux | |
| [10:49] marshall_law: looking forward to when google's cross platform webkit API gets stable | |
| [10:50] tav: where's KKJSObject defined ? | |
| [10:50] marshall_law: they just started on it | |
| [10:50] marshall_law: in the javascript module | |
| [10:51] marshall_law: i dunno why we called it KJS | |
| [10:51] marshall_law: i guess that's the old name for JavaScriptCore (KHTML/KJS) | |
| [11:00] tav: thanks marshall_law | |
| [11:00] tav: i think i have a pretty good idea now | |
| [11:01] marshall_law: sweet | |
| [11:01] marshall_law: glad i could help | |
| [11:47] CIA-67: titanium_desktop: Marshall master * r096d10f / apps/drillbit/Resources/tests/platform/platform.js : new ti.Platform tests - http://bit.ly/7SJV6 | |
| [11:47] CIA-67: titanium_desktop: Marshall master * r107b10b / modules/ti.App/Properties/properties_binding.cpp : more type tagging - http://bit.ly/K9mvf | |
| [11:47] CIA-67: kroll: Marshall master * rb7d6ec7 / (api/binding/blob.cpp api/binding/kmethod.h): yet more type tagging - http://bit.ly/utrN5 | |
| [12:16] CIA-67: titanium_desktop: Marshall master * rc04460c / (2 files): initial tests for ti.Media - http://bit.ly/18R1KZ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment