[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-devel
Subject:    port of pyjamas to pykde / khtml - issues and observations with pykde
From:       "Luke Kenneth Casson Leighton" <lkcl () lkcl ! net>
Date:       2008-10-12 20:43:24
Message-ID: ced5f0f60810121343j1117e0d1wac9abd8d5db65bd6 () mail ! gmail ! com
[Download RAW message or body]

folks, hi,
last month or so i ported pyjamas (itself a port of google's web
toolkit to python) to the desktop, using python bindings to glib
bindings to webkit's DOM bindings, where, as you know, webkit is
derived from KHTML.  don't ask - and don't think about it too hard :)
the port was successful: http://pyjd.org - and, in honour of webkit's
origins, i decided to spend my sunday afternoon beginning a port of
pyjamas to KHTML (specifically, pykde).  although it's very obtuse, is
khtml.DOM and khtml.KHTMLPart, the port is going very well: aside from
no "alert" and that i haven't quite found out how to execute
javascript fragments, yet, i've got the pyjamas Hello World example
working perfectly, and i moved quickly on to the GridTest example.
in my rush to get a working example, i'd glossed over a couple of
issues which are beginning to sink in, and are reminiscent of the
issues i faced when creating the glib bindings to webkit.  remembering
what happened. and the absolute pain it caused, i thought it best to
describe to you what i'd encountered.
it's best illustrated like this (pseudo-code):

d = browser.document()

n = d.createTextNode("hello")
n.setElementId("hello_id") # assuming that's possible - might have to
use setAttribute()

b = d.getElementsByTagName("body").item(0)
b.appendChild(n)

hid = d.getElementById("hello_id")

assert hid == n # WARK, WARK! FAIL!! DANGER, WILL ROBINSON!

the reason is utterly, utterly straightforward: getElementById() only
returns objects of type "Node", whereas what we _actually_ want - in
the above example - is an object of type TextNode.

to cater for this, WebKit has, in the javascript bindings,
JSHTMLElementWrapperFactory.cpp and friends.  for the glib bindings, i
wrote GDOMBindings.cpp and GDOMHTMLElementWrapperFactory.cpp, the
purpose of which is to do a monster nested set of switch / case
statements, returning the right object type.

there is nooo escaping the necessity of this approach.  both the JS
and the glib bindings _and_ now that i remember it the ObjectiveC
bindings - all of them have a HashMap<...> which is used to map
between the underlying c++ object and the "binding" object that
represents and wraps the c++ object.  *everything* gets run past the
HashMap, first.

not having such a HashMap system in place causes developers *massive*
problems.  in the case of the python bindings around the glib
bindings, _before_ i'd added the HashMap, i couldn't even _get_ at the
functions in anything that was obtained via getElementByid()!  no, i
didn't have the equivalent of DOM::HTMLElement().  no, exposing
DOM::HTMLElement() is _not_ a good idea - as anyone who's tried to use
it will testify: you have to double-check the object type _before_
casting-up, otherwise you get a DOM.Exception thrown at you.

this double-checking of the object type is what really needs to be
done by pykde on behalf of the developers _using_ pykde.  it _has_ to
be done, so why are all the developers of each and every single pykde
application being forced, unnecessarily, to make these
DOM.{Typecasts}?

additionally, you're ending up with a _second_ python object kicking
around which represents the object. in the example above, one is a
python DOM.Node wrapper around a TextNode object; the other is a
python DOM.HTMLTextNode wrapper around the _same_ TextNode object.

that can't be good.

has anyone checked the refcounts on the objects?

what happens if you call removeChild on the python DOM.Node object (or
other manipulation) and then end up referencing the DOM.HTMLTextNode
on the same object?  (probably nothing - substitute appropriate evil
machinations which result in deletion of the c++ object... if
possible).

also - while i'm at it, what's with having to call isNull() on
objects?  that's evil and cruel!  and having to call hasChildren()
before calling firstChild()?  yukk, guys!

all of these things i can work around, _without_ doing any
modifications or programming at the KHTML c++ level.  i can even,
thanks to DOM.* typecast functions, make a workaround wrapper class
that does the equivalent of the JS, Glib and ObjC element wrapper
factory.  i'm not looking _forward_ to it, but i can do it.

how much better would it be to have the KHTML code - and pykde - do
the work for every single developer, already?

l.
 
>> Visit http://mail.kde.org/mailman/listinfo/kde-devel#unsub to unsubscribe <<
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic