From this discussion: https://news.ycombinator.com/item?id=8854844
and related to this code: https://github.com/city41/bookends/blob/master/site/src/cljs/demo/knex.cljs#L6
Here is the relevant chunk of advanced compiled js when using set!
the ClojureScript:
(ns demo.knex
(:require [cljs.core.async :refer [put! chan]]))
(def knex (js/Knex. #js {:client "websql" :debug true}))
(defn init-chan []
(let [out (chan)]
(set! (.. knex -client -Runner -prototype -debug)
(fn [obj]
(put! out {:sql (.-sql obj)
:bindings (.-bindings obj)})))
out))
and the chunk of the JS that corresponds
(function $h(b) {
"undefined" === typeof lh && (lh = function(b, d, e) {
this.f = b;
this.Ob = d;
this.uc = e;
this.A = 0;
this.n = 393216
}, lh.prototype.$b = function() {
return !0
}, lh.prototype.ac = function() {
return this.f
}, lh.prototype.J = function() {
return this.uc
}, lh.prototype.M = function(b, d) {
return new lh(this.f, this.Ob, d)
}, lh.cb = !0, lh.bb = "cljs.core.async/t21578", lh.ub = function(b, d) {
return A(d, "cljs.core.async/t21578")
});
return new lh(b, $h, new s(null, 5, [ng, 20, Ug, 16, zg, 3, Jg, 13, kg, "/Users/matt/dev/bookends/site/target/cljsbuild-compiler-1/cljs/core/async.cljs"],
null))
})(function() {
return null
});
var ai = new Knex({debug: !0,client: "websql"});
var bi;
function di(a) {
var b = S.h(a, 0, null);
a = S.h(a, 1, null);
if (t(a))
throw a;
return b
}
Here is the same function, but using let instead.
(ns demo.knex
(:require [cljs.core.async :refer [put! chan]]))
(def knex (js/Knex. #js {:client "websql" :debug true}))
(defn init-chan []
(let [out (chan)
client (.-client knex)
Runner (.-Runner client)
proto (.-prototype Runner)]
(set! (.-debug proto)
(fn [obj]
(put! out {:sql (.-sql obj)
:bindings (.-bindings obj)})))
out))
and the resulting JS
function a(a, b, c, d) {
a = mh(a, b, ai(c));
return t(a) ? (b = O.d ? O.d(a) : O.call(null, a), t(d) ? c.d ? c.d(b) : c.call(null, b) : Hh(function(a) {
return function() {
return c.d ? c.d(a) : c.call(null, a)
}
}(b, a, a)), b) : !0
}
function b(a, b, c) {
return d.r(a, b, c, !0)
}
function c(a, b) {
var c = mh(a, b, ci);
return t(c) ? O.d ? O.d(c) : O.call(null, c) : !0
}
var d = null, d = function(d, f, g, k) {
switch (arguments.length) {
case 2:
return c.call(this,
d, f);
case 3:
return b.call(this, d, f, g);
case 4:
return a.call(this, d, f, g, k)
}
throw Error("Invalid arity: " + arguments.length);
};
d.c = c;
d.h = b;
d.r = a;
return d
}();
var ei = new Knex({debug: !0,client: "websql"});
function fi() {
var a = bi.v(), b = ei.client, c = b.Runner, d = c.prototype;
d.debug = function(a) {
return function(b) {
return di.c(a, new s(null, 2, [Gg, b.sql, eg, b.bindings], null))
}
}(a, b, c, d);
return a
}
;
var hi;
function ii(a) {
var b = S.h(a, 0, null);
a = S.h(a, 1, null);
if (t(a))
throw a;
return b
}
You can see in the second chunk after the creation of the knex object, it's successfully digging into it. But there is no equivalent to that in the set! version.
As Skinney requested, here is no optimizations and pretty printed
using set!
// Compiled by ClojureScript 0.0-2665 {}
if (!goog.isProvided_('demo.knex')) {
goog.provide('demo.knex');
}
goog.require('cljs.core');
goog.require('cljs.core.async');
demo.knex.knex = (new Knex({
"debug": true,
"client": "websql"
}));
demo.knex.init_chan = (function init_chan() {
var out = cljs.core.async.chan.call(null);
demo.knex.knex.client.Runner.prototype.debug = ((function(out) {
return (function(obj) {
return cljs.core.async.put_BANG_.call(null, out, new cljs.core.PersistentArrayMap(
null, 2, [new cljs.core.Keyword(null, "sql", "sql", 1251448786),
obj.sql, new cljs.core.Keyword(null, "bindings", "bindings",
1271397192), obj.bindings
], null));
});
})(out));
return out;
});
using let
// Compiled by ClojureScript 0.0-2665 {}
if (!goog.isProvided_('demo.knex')) {
goog.provide('demo.knex');
}
goog.require('cljs.core');
goog.require('cljs.core.async');
demo.knex.knex = (new Knex({
"debug": true,
"client": "websql"
}));
demo.knex.init_chan = (function init_chan() {
var out = cljs.core.async.chan.call(null);
var client = demo.knex.knex.client;
var Runner = client.Runner;
var proto = Runner.prototype;
proto.debug = ((function(out, client, Runner, proto) {
return (function(obj) {
return cljs.core.async.put_BANG_.call(null, out, new cljs.core.PersistentArrayMap(
null, 2, [new cljs.core.Keyword(null, "sql", "sql", 1251448786),
obj.sql, new cljs.core.Keyword(null, "bindings", "bindings",
1271397192), obj.bindings
], null));
});
})(out, client, Runner, proto));
return out;
});
(the only added changes I did was to format it even more than what :pretty-print did)
And for the heck of it, here is advanced mode, with pseudo-names turned on
(function $fn_handler$$2$$($f$$458$$) {
"undefined" === typeof $cljs$core$async$t21578$$ && ($cljs$core$async$t21578$$ = function($f$$458$$, $fn_handler$$3$$, $meta21579$$) {
this.f = $f$$458$$;
this.$fn_handler$ = $fn_handler$$3$$;
this.$meta21579$ = $meta21579$$;
this.$cljs$lang$protocol_mask$partition1$$ = 0;
this.$cljs$lang$protocol_mask$partition0$$ = 393216;
}, $cljs$core$async$t21578$$.prototype.$cljs$core$async$impl$protocols$Handler$active_QMARK_$arity$1$ = function() {
return!0;
}, $cljs$core$async$t21578$$.prototype.$cljs$core$async$impl$protocols$Handler$commit$arity$1$ = function() {
return this.f;
}, $cljs$core$async$t21578$$.prototype.$cljs$core$IMeta$_meta$arity$1$ = function() {
return this.$meta21579$;
}, $cljs$core$async$t21578$$.prototype.$cljs$core$IWithMeta$_with_meta$arity$2$ = function($f$$458$$, $meta21579__$1$$) {
return new $cljs$core$async$t21578$$(this.f, this.$fn_handler$, $meta21579__$1$$);
}, $cljs$core$async$t21578$$.$cljs$lang$type$ = !0, $cljs$core$async$t21578$$.$cljs$lang$ctorStr$ = "cljs.core.async/t21578", $cljs$core$async$t21578$$.$cljs$lang$ctorPrWriter$ = function($f$$458$$, $writer__4331__auto__$$78$$) {
return $cljs$core$_write$$($writer__4331__auto__$$78$$, "cljs.core.async/t21578");
});
return new $cljs$core$async$t21578$$($f$$458$$, $fn_handler$$2$$, new $cljs$core$PersistentArrayMap$$(null, 5, [$cljs$core$constant$0keyword$08$$, 20, $cljs$core$constant$0keyword$09$$, 16, $cljs$core$constant$0keyword$010$$, 3, $cljs$core$constant$0keyword$011$$, 13, $cljs$core$constant$0keyword$012$$, "/Users/matt/dev/bookends/site/target/cljsbuild-compiler-1/cljs/core/async.cljs"], null));
})(function() {
return null;
});
var $demo$knex$knex$$ = new Knex({debug:!0, client:"websql"});
var $cljs_promises$async$t25234$$;
function $cljs_promises$async$consume_pair$$($err$$3_p__25216$$) {
var $val$$113$$ = $cljs$core$nth$$.$cljs$core$IFn$_invoke$arity$3$($err$$3_p__25216$$, 0, null);
$err$$3_p__25216$$ = $cljs$core$nth$$.$cljs$core$IFn$_invoke$arity$3$($err$$3_p__25216$$, 1, null);
if ($cljs$core$truth_$$($err$$3_p__25216$$)) {
throw $err$$3_p__25216$$;
}
return $val$$113$$;
}
var $cljs_promises$async$pair_port$$ = function $pair_port$$($promise$$10$$) {
"undefined" === typeof $cljs_promises$async$t25234$$ && ($cljs_promises$async$t25234$$ = function($promise$$10$$, $pair_port$$1$$, $meta25235$$) {
this.promise = $promise$$10$$;
this.$pair_port$ = $pair_port$$1$$;
this.$meta25235$ = $meta25235$$;
this.$cljs$lang$protocol_mask$partition1$$ = 0;
this.$cljs$lang$protocol_mask$partition0$$ = 393216;
}, $cljs_promises$async$t25234$$.prototype.$cljs$core$async$impl$protocols$ReadPort$take_BANG_$arity$2$ = function($promise$$10$$, $handler$$10$$) {
this.promise.then(function($promise$$10$$) {
return function($_$$225$$) {
return $cljs$core$async$impl$dispatch$run$$(function() {
return function() {
return $cljs$core$async$impl$protocols$commit$$($handler$$10$$).call(null, new $cljs$core$PersistentVector$$(null, 2, 5, $cljs$core$PersistentVector$EMPTY_NODE$$, [$_$$225$$, null], null));
};
}($promise$$10$$));
};
@Skinney -- I added them above.
David Nolan has said the cause of this is an improper externs file for Knex. I was originally using the Knex js file itself as the extern file. I have been trying to create my own Knex externs file that makes the problem go away but so far no luck.
I also find it odd that in the optimized
set!
version, the channel went away too (ie theout
variable), the only thing left is the instantiation of the knex object. But I'm still a cljs newb, so very open to suggestions.