Hi all,

I have been trying to get Clojurescript working with QML and want to report how 
I have gotten a QML-based Clojurescript REPL working.

Although some minimal working examples have been posted - 
https://github.com/fehrenbach/qmcljs and 
https://github.com/halgari/qt_with_cljs - it has become evident that getting a 
working REPL is significantly more difficult.

I initially got a somewhat functional REPL working by porting Weasel and using 
Qt 5.3's Websockets: 
https://github.com/aaronc/weasel/blob/master/src/cljs/weasel/repl.cljs. Because 
of QML's unusual behavior with respect to scoping - the root cannot be modified 
and the value of this for the file from which Clojurescript was loaded cannot 
be modified after loading the file. As a result, QML usually throws type errors 
when you try to def most things from the REPL.

My solution to the scoping issue is somewhat of a hack and currently only works 
with :whitespace optimizations. One nice thing about the hack, however, is that 
it does allow Clojurescript to modify QML's global scope. Therefore any 
namespaces defined by Clojurescript will be available to the whole Qml 
environment. This may or may not be desirable, but it is the only way I've been 
able to get a REPL working and I would like to ^:export at least some 
Clojurescript var's globally to QML.

Anyway, this is what I had to do:

in C++:
QQmlApplicationEngine engine;
QObject* global = new QObject();
// reset the root context to my context object
engine.rootContext()->setContextObject(global); 
// and expose it globally as "global"
engine.rootContext()->setContextProperty("global", global); 

The following preamble is required to the generated javascript:
var goog = goog || {}; // make sure the goog object is created
                       // before base.js is loaded
goog.global = global; // set goog.global to point to my context property
                      // which is actually the QML root context!
global.goog = goog; // make sure goog is defined in my global context.


And line 47 in 
https://github.com/google/closure-library/blob/master/closure/goog/base.js, 
needs to be changed to:
goog.global = goog.global || this; // only redefine goog.global if it doesn't 
exist

I should mention that :simple optimizations almost work, but there are issues 
if you want to modify an already defined namespace because the Closure compiler 
converts a lot of google.provide("my_ns") into simply var my_ns = {}. This 
turns out to be an issue if you want to modify that ns from the REPL because of 
scoping issues. The good news is that, it looks like :simple work if you don't 
need a full REPL and will only expose the ^:export'ed vars. :advanced mode 
works partially is probably a matter of declaring the correct externs.

Would any of the Clojurescript maintainers want to comment on this approach... 
and on the possibility of patching base.js and adding a :qml compilation 
:target?

-- 
Note that posts from new members are moderated - please be patient with your 
first post.
--- 
You received this message because you are subscribed to the Google Groups 
"ClojureScript" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/clojurescript.

Reply via email to