The main thing that I can think of off-hand that would need more work is more code to have methods that return, say, WebDOMElement, get translated to the proper WebDOMElement subclass when the Python object is returned. That could probably be automated as well, but I haven't yet looked at it.
ok, so, as promised, subject changed. first thing: are you _sure_
you want to do this, kevin? it depends on what your goal is. do you
want to get wxWebkit its python DOM bindings _quickly_, or do you want
to use this as an opportunity to learn extensively about webkit and
significantly improve your programming skills? personally, if i'm
given a short-cut route, i don't arse about i take it that's why
the GNU pythonwebkit bindings are such a mish-mash of what _should_ be
completely incompatible free software projects! so, if the former,
then i can help you to get GNU pythonwebkit into wxWebKit; if the
latter, then i can help advise you on how to do the other types of
HTMLElement and SVGElement objects, but as you'll see it's not for the
faint-hearted
ok. rright. where to begin. first take a deep breath...
begin with a description of the problem. the problem is this: objects
that are returned by e.g. the getElementsByTagName or getElementsById
function, or by enumerating e.g. an HTML Table's row/columns, can be
absolutely *any* type of object... but the specification says that the
objects returned are... yep, you guessed it: an HTMLElement.
and that HTMLElement is a *base class*.
in other words, the infrastructure that you're creating *must*
support Object-Orientated capabilities - i forget the exact compsci
term for this: opaque datatypes, some sort of bullshit like that.
example: if you call getElementsById, which you'll see its return type
is HTMLElement, you have to return the HTML "div" element (or whatever
it was) as a python object representing and wrapping that webkit
"HTMLDivElement" object *not* a python object which identifies itself
as an HTMLElement.
now with that in mind, i can describe some of the ways in which this
has been attempted with spectacular "fail" (but only accidentally).
the original code for Webkit is actually KDE's KHTMLPart. this code
has had, for some considerable time, python bindings. KHTMLPart (used
to create Konqueror) was actually fully W3C DOM TR2 compliant. the
python bindings *worked*... but *only* if the entire KHTMLPart source
code was built with c++ "RTTI" checking enabled... (yes you can
probably guess what happened but let me continue)
so, *if* you have the c++ RTTI checking enabled, the python bindings
to KHTMLPart utilised this information to identify the type of c++
WebKit (ok, KHTML) object being returned by each function e.g.
getElementsById, and to return the corresponding and correct type
Python object, but not only that, to return the correct and
corresponding python *object*.
to illustrate: the problem that occurs if you *do not* have c++ RTTI
checking enabled, is that you do something like this:
doc = wv.GetDOMDocument()
div = doc.createElement("div")
doc.body.appendChild(div)
div2 = doc.getElementsByTagName("div")[0]
assert div2 == div # this ***FAILS***
why does it fail??? what the bloody hell's going on?? well, you
probably guessed, but it's worth describing: the object returned from
the getElementsByTagName call is either the correct type of c++ object
but is a *new* type of python object, or is the correct type of c++
object but type-cast down to a c++ HTMLElement, and the python
"wrapper" object is... well, i think i illustrated it clearly enough.
in the Trident Engine, they got sick of this problem and added a non-
W3C-standards-compliant object property called "uniqueID". the reason
for this is that DCOM can work across multiple programming languages,
and even across the Internet. you *can't* do "==" across the
Internet! plus, in COM / DCOM, it's perfectly valid to return a DCOM
object which represents and wraps some remote object which is of "base
class" type, and then to perform some non-automated checking and then
"up-cast" the object to its *real* type. in python-comtypes, this non-
automated checking is so regular and monotonous that it's actually
possible to create a "lazy bindings" python class which performs all
this laborious checking on your behalf, with the end result being
that, although it's a dog's dinner underneath, the python objects that
you end up using are properly, properly representative of the Trident
DOM objects. with the exception of this "==" issue, where you're
forced to do "obj1.uniqueID == obj2.uniqueID" instead. whoops
anyway, that's the scope of the problem, and you have to solve it by
having and maintaining a Hash Table of *all* python-to-webkitc++
objects. the bindings developers typically use the function
"toWebKit" and "to{BindingsName}" to convert between the two. they
create auto-code-generators which create these "towxPython" functions,
using c++ overloading and make the c++ compiler do all the hard work.
so, the pseudo-code goes like this:
1) before returning the result (e.g. to getElementsByTagName) and
*before* creating a PyObject, perform a lookup (indexed by the c++
object) to see if has ever been created before.
2) if yes, perform a PyObject "incref" but *DO NOT* perform a WebKit c
++ "incref" operation, and return it as the result.
3) if no, *then* you create a new PyObject, hand the Webkit c++
object to it, perform a WebKit c++ "incref" operation *and* a PyObject
"incref" operation, and return it as the result.
the important thing here is that you are relying on the underlying
webkit c++ pointer to be the lookup in the Hash Table, and thus you
are guaranteed to always get - and return - the correct python
object. if you do this, then the above example code will NOT throw an
"assert". the other solution is of course to copy what the Trident
(Internet Explorer) Team did, but that does get you into a bit of
lairy hairy coding, puts a burden onto users, and it's not what any of
the other webkit bindings developers have done.
so.... with that background in mind (god, it's only
background...) it's possible to move on to doing the different types
of HTMLElement (HTMLTableElement, HTMLDivElement, HTMLButtonElement
etc.)
it's probably best if i describe how this is done in all the other
webkit bindings. what they do is they use a text file, and run it
through a perl program called ... ah yes here it is: Source/WebCore/
dom/make_names.pl. it's a dog's dinner (it's perl), but is extremely
flexible. it's coded basically to be able to create the wrappers you
were talking about, *but*, it's hard-coded to create stuff
*specifically* for the JS bindings (which, btw, have exactly the same
issues to deal with as i've described in excruciating detail, above...
irony).
you can see in make_names.pl that there is even a switch for enabling
Google V8 javascript bindings compatible code instead of webkit
javascript bindings compatible code. the code can also be asked to
auto-generate code for SVG HTML5 objects as well as plain HTML ones.
all of the code created basically is a *massive* switch statement,
which you pass in a webkit c++ object (type-cast to the webkit base
class HTMLElement or for the SVG version obviously typecast to the
webkit base class SVGHTMLElement) and it will go "switch (object-
nodeType)" if nodetype == WEBKIT_HTML_TABLE_TYPE { return
WEBKIT_JS_DOM_HTML_OBJECT(object); } else if .... blah blah
and that switch statement has, in the HTML auto-generated code,
something like 50 entries, and in the SVG case it's something like
120.
i have to say - it should be obvious - *do not* even *remotely*
consider doing this task by hand. adapt make_names.pl or, if you
prefer, adapt make_py_names.pl (which i wrote for the GNU pythonwebkit
- long story, not relevant here).
soooo, you have this whopping-great switch statement, and it creates
basically *one* function: "toJS(WebKitDOMHTMLElement* obj)" ok that'll
have to be "towxPython(WebKitDOMHTMLElement* obj)" and so, as you can
see, when you call that "towxPython" function on the c++ object, in
Stage 3) of the pseudo-code above, c++ *automatically*
DoesTheRightThing (tm) because that e.g. Webkit c++ function
getElementById returned a WebKitDOMHTMLElement, you don't have any
choice in the matter.
right now, the implementation of "towxPython(WebKitDOMHTMLElement*
obj)" is basically "wrap obj, shove it into a SWIG auto-generated
PyObject which tells the world that it's of type
PythonDOMHTMLElement", right? well, that's the code that needs to be
replaced with the above auto-generated code (created by make_names.pl
or equivalent).
_and_ you need to add in the Hash Table lookup, if you haven't
already done so. it's absolutely, absolutely essential that you do
so.
so this is just one of the technical issues that needs to be solved.
there are several others, such as event callbacks *including* Webkit
Timer object callbacks. no you *must* not expect wxWidgets timer
callbacks to work correctly: the webkit timers are designed to
interact correctly with the rest of the code, and they "pause" the
webkit engine in order to avoid race-conditions, whilst the code
inside the timer is being executed. if you do not have the webkit
engine correctly "paused", then all and any webkit timers (from
javascript or any other bindings) and all other operations being
executed will *also* be manipulating the DOM, so you will get race
conditions and, worse, data contention resulting in segfaults; at
best, users will have events that fire off code *simultaneously* as
the code being executed by a wxWidgets timer thread, and that could
lead to a runaway situation. the webkit engine is paused, and the
javascript code single-threaded, for _really_ good reasons.
i'm not "getting ahead" - i'm... just letting you know what you're
letting yourself in for. all these features - full and complete DOM
bindings to *all* Webkit HTML5 features _can_ be done - coded up,
entirely - in about 6-8 weeks (from scratch) but you have the
advantage that some code has already been written, which you may be
able to adapt, and shorten that timescale to about 10-14 days.
... orr, you could skip it entirely, help me add in the GNU
pythonwebkit bindings, which would probably take you about... 30
minutes, if that, to write about... 100 lines of code, if that (and 50
of those would be cut/paste from the pythonwebkit-gtk or pythonwebkit-
dfb ports), and then help me to improve and develop the GNU
pythonwebkit bindings.
two key things are needed in the GNU pythonwebkit bindings:
a) SVG Canvas objects. i did the HTML* objects, but the SVG Canvas
objects would have added an extra 120+ python objects and required
about another week of coding: i couldn't face it
b) CSS properties as python properties. backgroundColor etc. right
now, these have to be done via the "setProperty" function e.g.
div1.style.setProperty("backgroundColor", "#fffeee") rather than
div1.style.backgroundColor = "#fffeee". *again* these are done in
WebKit via a "make_names.pl" trick (that make_names.pl program is very
obtuse but very flexible) where instead it's handed a list of CSS
properties and a template that outputs JS-equivalent to
property(__get__ fn, __set__ fn) etc.
b) you'll _also_ have to tackle if you decide to continue
implementing python-wxWidgets using the present coding approach (with
SWIG)...
if i haven't convinced you to consider the GNU pythonwebkit approach
by now, i'm quite happy to give you some more reasons, but i think i'd
best leave it here and see how you react to the above, first!
l.
···
On May 24, 11:32 pm, Kevin Ollivier <kevin-li...@theolliviers.com> wrote: