binaryage / cljs-devtools Goto Github PK
View Code? Open in Web Editor NEWA collection of Chrome DevTools enhancements for ClojureScript developers
License: Other
A collection of Chrome DevTools enhancements for ClojureScript developers
License: Other
Hi,
unfortunately I can't try 0.2.0 because I don't have time to set up compiling Chrome myself and 0.2.0 doesn't work with aforementioned chrome version (I don't know how it relates to the revision / commit numbers in your README).
Thus I have to use 0.1.2. It works really great and is highly useful.
The only problem is namespaced keywords not being displayed correctly. Only their name is shown.
Kind regards,
Leon.
It looks like the formatter is changing symbolic values to null
during internal processing:
(pr-str ##NaN)
;; "##NaN"
(pr-str [##NaN])
;; "[##NaN]"
(. js/console log #js [##NaN ##Inf ##-Inf])
;; [NaN, Infinity, -Infinity]
(. js/console log [##NaN ##Inf ##-Inf])
;; [null null null]
This initial attempt seems to fix it - at least through inspection of the demo page with symbolic values added.
modified src/lib/devtools/formatters/helpers.cljs
@@ -62,6 +62,11 @@
(defn bool? [value]
(or (true? value) (false? value)))
+(defn symbolic-value? [value]
+ (or (js/Number.isNaN value)
+ (= js/Number.POSITIVE_INFINITY value)
+ (= js/Number.NEGATIVE_INFINITY value)))
+
(defn instance-of-a-well-known-type? [value]
(let [well-known-types (pref :well-known-types)
constructor-fn (get-constructor value)
@@ -76,7 +81,8 @@
(defn directly-printable? [value]
(or (string? value)
(number? value)
- (bool? value)))
+ (bool? value)
+ (symbolic-value? value)))
I had no success getting it to pass the whole test suite. Some issues were just phantomjs
/chrome differences[1], but others might indicate that this approach might conflict with other internal mechanisms.
[1] - e.g. Phantom seems to lack the safer Number.isNaN
, but has the old isNaN
.
We're running devtools with shadow-cljs:
thheller/shadow-cljs: "2.8.68"
binaryage/devtools: "0.9.10"
clojurescript: "1.10.520"
to help with #14
We use clj-devtools
within re-frame-10x
. We use clj-devtools
to render CLJS data to browse-able HTML and let the programmer inspect it. And it is really good, thanks!
(So, just to be crystal clear, our use is outside of Chrome devtools - we're using this library to render CLJS data structures in a normal HTML page setting)
When a user of re-frame10x
is browsing around the data structures, the user would like to be able to right-click on an arbitrary node (within the rendering) and obtain information about that node, specifically the path from the root of the data structure to the point they are clicking.
So, by right-clicking on some value in the rendering, they might get a popup menu and choose the "path to clipboard" option, which might put a string like this into the clipboard:
[:a :path :to 5 :the :item] ;; 5 is meant to indicate some index into a vector
Now, obviously this is not possible currently. And previously when this has come up we've just said "no" can't be done, end of story. But it came up again recently and in the process of saying "no", I had a further thought ...
Could this be achieved using the following technique:
data-clj-path
, which would carry the [:a :path :to 5 :the :item]
information as a string.data-clj-path
. Bingo, now we have the path and can write it to the clipboard ... or whatever else).I'd be prepared to have a go at making this happen, but before I take on the learning curve, I wanted to check in with you:
data-*
attribute? Or should I just stop right now and abandon all hope. :-)This is a placeholder issue for people who want to track the progress of this experimental feature.
The announcement from Slack:
Hi, just wanted to share with you a half-baked idea which enables long stack traces for core.async in ClojureScript:
You can get this[1] instead of this[2]:
[1] https://dl.dropboxusercontent.com/u/559047/core-async-long-stack-traces.png
[2] https://dl.dropboxusercontent.com/u/559047/core-async-normal-traces.png
The trick is to replace goog.async.nextTick with a promise-based implementation. ES6 promises participate in Chrome DevTools “async” feature. it is not super useful ATM, because maxAsyncStackChainDepth is currently hard-coded in DevTools and set to only 4, which is not enough for more complex core.async code:
https://github.com/binaryage/dirac/blob/devtools/front_end/sdk/DebuggerModel.js#L200
but in Dirac I can lift that number and maybe walk the call stack in a better way, so loops won’t create long stack traceshere is the implementation if anyone interested: 86dbbbb
here is an upstream proposal how to handle long async-task chains generated by core.async:
https://bugs.chromium.org/p/chromium/issues/detail?id=622506
So this is very neat; however, it only works in a browser right? Is there a test I can run to determine whether we are running in a browser (as opposed to node or something else) so that I can only enable cljs-devtools in that event. Basically, in cljs, I want to use cljs-devtools if I am logging to a browser and I want to just use pr-str if I am not in a browser or am in a browser but not one that supports custom formatters.
Currently, util tries to access js/window
and this variable is not set on Node by default.
I'm not sure this is a cljs-devtools problem, so sorry if it's not. But I think it is, since it started happening when I installed cljs-devtools.
I found that my .js output files sometimes have a strange line appended to them. For exampe:
~/game(master) » tail -n 4 target/public/cljs-out/game/game/stats_and_items.js
});
//# sourceMappingURL=stats_and_items.js.map
and_items.js.map
That and_items.js.map
should not be there, and is causing problems. Is this cljs-devtools' doing? Are you touching the .js files?
Chrome seems to have changed the setting for loading custom formatters, now (I'm using Chrome 84.0.4143.7).
Instead of 'Enable custom formatters', it's now called 'Temporarily enable deprecated custom formatters'.
The corresponding commit in Chrome DevTools included the comment:
TODO(1016755): remove custom formatters altogether.
which leads me to the Chrome bug petitioning to remove them altogether:
https://bugs.chromium.org/p/chromium/issues/detail?id=1016755
It might be worth chiming in there to petition to keep them, at least until a replacement is provided by the Dart team -- and especially in case it's a massive undertaking to port the current formatters should they remove the existing API...
I wrote a PR to change the cljs-devtools docs, but I wasn't sure if you wanted to include some language to explain to the user what's going on -- and also to let the user know that they're going to have to turn this setting on every time they restart Chrome, now.
Hello,
Just an idea: when stepping through the debugger, the values printed inline are not the nicely output values of cljs-devtools. Same when using React Dev Tools, the "props", "state" etc. aren't. It would be super cool if they were.
I'm almost sure it's a limitation of Chromium itself for not exposing the necessary APIs/hooks, but I just wanted to make it sure here before.
Thanks for your work by the way, I include in every CLJS project I use :)
I would like to open this issue so people like me that want to use cljs-devtools but don't want to use Chrome Canary can get notified when the necessary features are propagated to the standard Chrome. Thank you!
Hi,
Encountered the error when browsing through stacks at a break point. Below is the stack trace from that error. Chrome didn't output source map line numbers for a few frames at the bottom, not sure this stack trace are helpful or not.
core.cljs:65 CLJS DevTools internal error: TypeError: Cannot convert a Symbol value to a string
at Array.join (native)
at Function.cljs.core.str.cljs$core$IFn$_invoke$arity$1 (http://localhost:3450/js/compiled/test_out/cljs/core.js:9780:12)
at Object.cljs$core$str [as str] (http://localhost:3450/js/compiled/test_out/cljs/core.js:9762:22)
at cljs$core$pr_writer_impl (http://localhost:3450/js/compiled/test_out/cljs/core.js:31145:128)
at devtools$formatters$printing$alt_printer_job (http://localhost:3450/js/compiled/test_out/devtools/formatters/printing.js:233:21)
at devtools$formatters$printing$alt_printer_impl (http://localhost:3450/js/compiled/test_out/devtools/formatters/printing.js:248:46)
at cljs$core$pr_writer (http://localhost:3450/js/compiled/test_out/cljs/core.js:31172:128)
at http://localhost:3450/js/compiled/test_out/cljs/core.js:31613:131
at Object.cljs$core$pr_sequential_writer [as pr_sequential_writer] (http://localhost:3450/js/compiled/test_out/cljs/core.js:30903:142)
at cljs$core$print_map (http://localhost:3450/js/compiled/test_out/cljs/core.js:31602:18)
at cljs$core$pr_writer_impl (http://localhost:3450/js/compiled/test_out/cljs/core.js:31092:170)
at devtools$formatters$printing$alt_printer_job (http://localhost:3450/js/compiled/test_out/devtools/formatters/printing.js:233:21)
at devtools$formatters$printing$alt_printer_impl (http://localhost:3450/js/compiled/test_out/devtools/formatters/printing.js:248:46)
at cljs$core$pr_writer (http://localhost:3450/js/compiled/test_out/cljs/core.js:31172:128)
at Object.cljs$core$pr_sequential_writer [as pr_sequential_writer] (http://localhost:3450/js/compiled/test_out/cljs/core.js:30903:142)
at cljs.core.PersistentVector.cljs$core$IPrintWithWriter$_pr_writer$arity$3 (http://localhost:3450/js/compiled/test_out/cljs/core.js:31791:18)
at cljs$core$pr_writer_impl (http://localhost:3450/js/compiled/test_out/cljs/core.js:31078:12)
at devtools$formatters$printing$alt_printer_job (http://localhost:3450/js/compiled/test_out/devtools/formatters/printing.js:233:21)
at devtools$formatters$printing$alt_printer_impl (http://localhost:3450/js/compiled/test_out/devtools/formatters/printing.js:248:46)
at Object.cljs$core$pr_writer [as pr_writer] (http://localhost:3450/js/compiled/test_out/cljs/core.js:31172:128)
at cljs$core$pr_seq_writer (http://localhost:3450/js/compiled/test_out/cljs/core.js:31178:11)
at http://localhost:3450/js/compiled/test_out/devtools/formatters/printing.js:283:32
at http://localhost:3450/js/compiled/test_out/devtools/formatters/printing.js:258:16
at devtools$formatters$printing$managed_print (http://localhost:3450/js/compiled/test_out/devtools/formatters/printing.js:276:8)
at devtools$formatters$printing$managed_print_via_writer (http://localhost:3450/js/compiled/test_out/devtools/formatters/printing.js:282:51)
at http://localhost:3450/js/compiled/test_out/devtools/formatters/markup.js:34:15
at Function.devtools.formatters.markup.print_with.cljs$core$IFn$_invoke$arity$variadic (http://localhost:3450/js/compiled/test_out/devtools/formatters/markup.js:41:19)
at devtools$formatters$markup$print_with (http://localhost:3450/js/compiled/test_out/devtools/formatters/markup.js:26:46)
at Function.devtools.formatters.markup.print_via_writer.cljs$core$IFn$_invoke$arity$variadic (http://localhost:3450/js/compiled/test_out/devtools/formatters/markup.js:83:46)
at devtools$formatters$markup$print_via_writer (http://localhost:3450/js/compiled/test_out/devtools/formatters/markup.js:77:52)
at devtools$formatters$markup$_LT_preview_GT_ (http://localhost:3450/js/compiled/test_out/devtools/formatters/markup.js:400:52)
at devtools$formatters$markup$_LT_header_GT_ (http://localhost:3450/js/compiled/test_out/devtools/formatters/markup.js:1054:106)
at devtools$formatters$core$header_STAR_ (http://localhost:3450/js/compiled/test_out/devtools/formatters/core.js:56:149)
at devtools.formatters.core.config_wrapper (http://localhost:3450/js/compiled/test_out/devtools/formatters/core.js:156:19)
at Function.handler (http://localhost:3450/js/compiled/test_out/devtools/formatters/core.js:209:120)
at Function.cljs.core.apply.cljs$core$IFn$_invoke$arity$2 (http://localhost:3450/js/compiled/test_out/cljs/core.js:12983:10)
at cljs$core$apply (http://localhost:3450/js/compiled/test_out/cljs/core.js:12951:24)
at devtools.formatters.CLJSDevtoolsFormatter.G__54238__delegate (http://localhost:3450/js/compiled/test_out/devtools/formatters/core.js:167:28)
at devtools.formatters.CLJSDevtoolsFormatter.G__54238 [as header] (http://localhost:3450/js/compiled/test_out/devtools/formatters/core.js:180:27)
at InjectedScript.RemoteObject._customPreview (<anonymous>:147:82)
at InjectedScript.RemoteObject (<anonymous>:139:73)
at InjectedScript._wrapObject (<anonymous>:43:13)
at InjectedScript.getProperties (<anonymous>:51:23)
at Function.<anonymous> (http://localhost:3450/js/compiled/test_out/webapp/react.js?zx=d29fd3515wqx:75:9)
at Function.cljs.core.apply.cljs$core$IFn$_invoke$arity$3 (http://localhost:3450/js/compiled/test_out/cljs/core.js:12998:10)
at cljs$core$apply (http://localhost:3450/js/compiled/test_out/cljs/core.js:12955:24)
at render (http://localhost:3450/js/compiled/test_out/rum/core.js:209:107)
at http://localhost:3450/js/compiled/test_out/react/util.js:219:33
at Constructor.render (http://localhost:3450/js/compiled/test_out/rum/core.js:76:33)
at ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext (http://localhost:3450/js/compiled/test_out/lib.js:20139:34)
at ReactCompositeComponentWrapper._renderValidatedComponent (http://localhost:3450/js/compiled/test_out/lib.js:20166:34)
at ReactCompositeComponentWrapper.performInitialMount (http://localhost:3450/js/compiled/test_out/lib.js:19703:30)
at ReactCompositeComponentWrapper.mountComponent (http://localhost:3450/js/compiled/test_out/lib.js:19591:21)
at Object.mountComponent (http://localhost:3450/js/compiled/test_out/lib.js:27270:35)
at ReactDOMComponent.mountChildren (http://localhost:3450/js/compiled/test_out/lib.js:26012:44)
at ReactDOMComponent._createInitialChildren (http://localhost:3450/js/compiled/test_out/lib.js:21122:32)
at ReactDOMComponent.mountComponent (http://localhost:3450/js/compiled/test_out/lib.js:20947:12)
at Object.mountComponent (http://localhost:3450/js/compiled/test_out/lib.js:27270:35)
at ReactCompositeComponentWrapper.performInitialMount (http://localhost:3450/js/compiled/test_out/lib.js:19716:34)
at ReactCompositeComponentWrapper.mountComponent (http://localhost:3450/js/compiled/test_out/lib.js:19591:21)
at Object.mountComponent (http://localhost:3450/js/compiled/test_out/lib.js:27270:35)
at ReactCompositeComponentWrapper.performInitialMount (http://localhost:3450/js/compiled/test_out/lib.js:19716:34)
at ReactCompositeComponentWrapper.mountComponent (http://localhost:3450/js/compiled/test_out/lib.js:19591:21)
at Object.mountComponent (http://localhost:3450/js/compiled/test_out/lib.js:27270:35)
at ReactDOMComponent.mountChildren (http://localhost:3450/js/compiled/test_out/lib.js:26012:44)
at ReactDOMComponent._createInitialChildren (http://localhost:3450/js/compiled/test_out/lib.js:21122:32)
at ReactDOMComponent.mountComponent (http://localhost:3450/js/compiled/test_out/lib.js:20947:12)
at Object.mountComponent (http://localhost:3450/js/compiled/test_out/lib.js:27270:35)
at ReactDOMComponent.mountChildren (http://localhost:3450/js/compiled/test_out/lib.js:26012:44)
at ReactDOMComponent._createInitialChildren (http://localhost:3450/js/compiled/test_out/lib.js:21122:32)
at ReactDOMComponent.mountComponent (http://localhost:3450/js/compiled/test_out/lib.js:20947:12)
at Object.mountComponent (http://localhost:3450/js/compiled/test_out/lib.js:27270:35)
at ReactDOMComponent.mountChildren (http://localhost:3450/js/compiled/test_out/lib.js:26012:44)
at ReactDOMComponent._createInitialChildren (http://localhost:3450/js/compiled/test_out/lib.js:21122:32)
at ReactDOMComponent.mountComponent (http://localhost:3450/js/compiled/test_out/lib.js:20947:12)
at Object.mountComponent (http://localhost:3450/js/compiled/test_out/lib.js:27270:35)
at ReactCompositeComponentWrapper.performInitialMount (http://localhost:3450/js/compiled/test_out/lib.js:19716:34)
at ReactCompositeComponentWrapper.mountComponent (http://localhost:3450/js/compiled/test_out/lib.js:19591:21)
at Object.mountComponent (http://localhost:3450/js/compiled/test_out/lib.js:27270:35)
at ReactDOMComponent.mountChildren (http://localhost:3450/js/compiled/test_out/lib.js:26012:44)
at ReactDOMComponent._createInitialChildren (http://localhost:3450/js/compiled/test_out/lib.js:21122:32)
at ReactDOMComponent.mountComponent (http://localhost:3450/js/compiled/test_out/lib.js:20947:12)
at Object.mountComponent (http://localhost:3450/js/compiled/test_out/lib.js:27270:35)
at Object.updateChildren (http://localhost:3450/js/compiled/test_out/lib.js:17767:51)
at ReactDOMComponent._reconcilerUpdateChildren (http://localhost:3450/js/compiled/test_out/lib.js:25982:32)
at ReactDOMComponent._updateChildren (http://localhost:3450/js/compiled/test_out/lib.js:26086:31)
at ReactDOMComponent.updateChildren (http://localhost:3450/js/compiled/test_out/lib.js:26073:12)
at ReactDOMComponent._updateDOMChildren (http://localhost:3450/js/compiled/test_out/lib.js:21365:12)
at ReactDOMComponent.updateComponent (http://localhost:3450/js/compiled/test_out/lib.js:21183:10)
at ReactDOMComponent.receiveComponent (http://localhost:3450/js/compiled/test_out/lib.js:21141:10)
at Object.receiveComponent (http://localhost:3450/js/compiled/test_out/lib.js:27349:22)
at Object.updateChildren (http://localhost:3450/js/compiled/test_out/lib.js:17755:25)
at ReactDOMComponent._reconcilerUpdateChildren (http://localhost:3450/js/compiled/test_out/lib.js:25982:32)
at ReactDOMComponent._updateChildren (http://localhost:3450/js/compiled/test_out/lib.js:26086:31)
at ReactDOMComponent.updateChildren (http://localhost:3450/js/compiled/test_out/lib.js:26073:12)
at ReactDOMComponent._updateDOMChildren (http://localhost:3450/js/compiled/test_out/lib.js:21365:12)
at ReactDOMComponent.updateComponent (http://localhost:3450/js/compiled/test_out/lib.js:21183:10)
at ReactDOMComponent.receiveComponent (http://localhost:3450/js/compiled/test_out/lib.js:21141:10)
at Object.receiveComponent (http://localhost:3450/js/compiled/test_out/lib.js:27349:22)
at Object.updateChildren (http://localhost:3450/js/compiled/test_out/lib.js:17755:25)
at ReactDOMComponent._reconcilerUpdateChildren (http://localhost:3450/js/compiled/test_out/lib.js:25982:32)
at ReactDOMComponent._updateChildren (http://localhost:3450/js/compiled/test_out/lib.js:26086:31)
at ReactDOMComponent.updateChildren (http://localhost:3450/js/compiled/test_out/lib.js:26073:12)
at ReactDOMComponent._updateDOMChildren (http://localhost:3450/js/compiled/test_out/lib.js:21365:12)
at ReactDOMComponent.updateComponent (http://localhost:3450/js/compiled/test_out/lib.js:21183:10)
at ReactDOMComponent.receiveComponent (http://localhost:3450/js/compiled/test_out/lib.js:21141:10)
at Object.receiveComponent (http://localhost:3450/js/compiled/test_out/lib.js:27349:22)
at ReactCompositeComponentWrapper._updateRenderedComponent (http://localhost:3450/js/compiled/test_out/lib.js:20092:23)
at ReactCompositeComponentWrapper._performComponentUpdate (http://localhost:3450/js/compiled/test_out/lib.js:20070:10)
at ReactCompositeComponentWrapper.updateComponent (http://localhost:3450/js/compiled/test_out/lib.js:19989:12)
at ReactCompositeComponentWrapper.performUpdateIfNecessary (http://localhost:3450/js/compiled/test_out/lib.js:19897:12)
at Object.performUpdateIfNecessary (http://localhost:3450/js/compiled/test_out/lib.js:27381:22)
at runBatchedUpdates (http://localhost:3450/js/compiled/test_out/lib.js:28521:21)
at ReactReconcileTransaction.perform (http://localhost:3450/js/compiled/test_out/lib.js:30772:20)
at ReactUpdatesFlushTransaction.perform (http://localhost:3450/js/compiled/test_out/lib.js:30772:20)
at Object.flushBatchedUpdates (http://localhost:3450/js/compiled/test_out/lib.js:28543:19)
at ReactDefaultBatchingStrategyTransaction.closeAll (http://localhost:3450/js/compiled/test_out/lib.js:30838:25)
at ReactDefaultBatchingStrategyTransaction.perform (http://localhost:3450/js/compiled/test_out/lib.js:30785:16)
at Object.batchedUpdates (http://localhost:3450/js/compiled/test_out/lib.js:23778:19)
at Object.batchedUpdates (http://localhost:3450/js/compiled/test_out/lib.js:28468:20)
at dispatchEvent (http://localhost:3450/js/compiled/test_out/lib.js:24761:20)
G__54238__delegate @ core.cljs:65
G__54238 @ core.cljs:61
_customPreview
InjectedScript.RemoteObject
_wrapObject
getProperties
Hi cljs-devtools team
I was redirected here from day8/re-frame-template#82 (comment) in which I highlighted the issues with setting up the cljs-devtools using the template.
Could you please help me out?
It would be nice to have some way to customize the style (color..) of default formatters.
Is it possible to use somehow with mori?
I am getting this warning message in the console (have just updated to 0.7.0
):
"Custom formatters functionality does not seem to be active in your DevTools..."
I definitely have it checked. In fact, the installation message proves that:
"Installing CLJS DevTools 0.7.0 and enabling features :custom-formatters :sanity-hints"
I have tested this behaviour in Windows Chrome 51.0.2704.84 m
and Canary 53.0.2768.0
(Canary doesn't display the warning but still fails to show my lovely formatted data)
However, in all cases, if I simply refresh the browser, it initialises properly and I see formatted data.
I then went back to 0.6.0
and experienced the same behaviour. Didn't go back any further.
We could specify a structured format and a wire protocol for printing/expanding Clojure data structures in a similar way how cljs-devtools work for ClojureScript.
cljs-devtools could then connect to a backend library via websocket and act as a rich logging console for Clojure projects. With support from Dirac DevTools we could turn Chrome's DevTools into a nice REPL + logger for Clojure (not only for ClojureScript).
I personally do most of my work on client-side, so it is unlikely for me to spend time on it at this point. But I would be happy to help someone else who would be interested in implementing it to integrate it (I would do the JavaScript part on front-end).
Blocked by upstream: https://bugs.chromium.org/p/chromium/issues/detail?id=628731
if you try to (js/console.log (mapcat identity (range 10)))
, it doesn't fail at call-time b/c the value is lazy. It only errors when cljs-devtools tries to show it (specifically the header-api-call
function.
Currently I'm wrapping that in a try/catch, which might be the best way to do it. Do you think header-api-call should have the try/catch instead?
This:
(js/console.log {:a false})
Prints:
:a | null
Even though:
(js/console.log {:a true})
Prints:
:a | true
Am I missing something or is it weird to print null
for false and true
for true?
Is there a way of getting this to work with println
instead of just with the native console.log (or macros that compile down to it)?
To debug Node.js programs people invented node-inspector and devtool to use Chrome DevTools in Node.js and it looks good. I tried but cljs-devtools
is not able to run inside devtool. Any solution yet?
Hi @darwin!!
I have some code that fetches stuff in a reagent/cursor
and I am logging it using cljs-devtools
. What I have noticed and wanted to report is best explained with a screenshot:
Feel free to throw me any test/snapshot/alpha code and I am going to try it out.
Thanks a lot!
We have recently noticed the following rendering issue with the devtools scope tree.
js/console.log
does the right thing and expandable tree renders perfectly.This might be a cljs-devtools issue I see latest 0.9.10 was released over a year ago. I'm not sure but did dirac embed the devtools and is it possibly running a more up to date version ? (we don't use dirac at the moment, but if installing it instead of cljs-devtools would that solve it ?
We're using this very useful library as part of re-frame-trace. It would be helpful to be able to set the styling at a per API call level so that we don't overwrite anyone else's config that they're using in the console.
This is a feature idea.
I'm looking for a way to make my js/console.log display cleanly with and without cljs-devtools installed.
Today's job is a react native app. It's not always convenient to turn cljs-devtools on (e.g. two simulators) and it's helpful to look in the simulator logs sometimes (no cljs-devtool rendering).
Perhaps cljs-devtools could be adapted to look for metadata associated with a string (or string like) object.
Vaguely something like this could be used to prepare a "console.log friendly string" with some other protocol which cljs-devtools could detect...
(defn data-str [data]
(binding [*print-level* 3 *print-length* 5]
(specify! (pr-str data) IMeta (-meta [_] data)))))
(js/console.log (data-str {:a 1 :b (range 1000)}))
NOTE: this code doesn't work
Goal is to cover two cases
For example, map entries are elided after the first 5. This often causes very busy logging in my app. I'd like to be able to change it to 3. There's various things like that I'd like to do if it wasn't too difficult.
Is there any way to hook into this stuff?
Thanks very much for this project. So useful!
We were having trouble with spec errors in EventListeners. For example, spec errors thrown when handling the response to an ajax request were uncaught and printed badly.
There are Closure Library functions which can help with these cases. Possibly of use for cljs-devtools
(ns condense.preload
(:require [goog.debug.entryPointRegistry :as gepr])
(:import [goog.debug ErrorHandler]))
(defn handle-error [e]
(js/console.debug (.-stack e))
(js/console.debug (ex-data e)))
(def error-handler (doto (ErrorHandler. handle-error)
(.protectWindowSetTimeout)
(.protectWindowSetInterval)
(.protectWindowRequestAnimationFrame)))
(gepr/monitorAll error-handler)
I'm working on a clojure project, Zeal, that features an in-browser REPL and I'm wondering: can I could use cljs-devtools to format data-structures in the evaluation result.
In the best (most hands-off) case, I provide devtools with a dom node and a data-structure and let it to what it does so well in the console.
First off, thanks a lot for this project, it makes log-debugging in the browser a pleasure.
I noticed that I have a deftype that is being displayed in a weird way - the #<>
signifying JS objects nest excessively and a an following error message appears (also attached a screenshot):
Custom Formatter Failed: Too deep hierarchy of inlined custom previews
I would have to check, but I don't think that happened in older versions of cljs-devtools and/or Chromium.
I don't have a minimal reproduction of this right, but if the issue is not something immediately obvious from this behaviour I can produce one if it will be helpful.
I was helping debug a question about re-frame. The root cause was that a parameter was a string instead of an integer.
The devtools output for calling the function with a string and a number are quite similar, the only difference is slight syntax highlighting. When id
is a string (first image), it is darker coloured, but isn't wrapped in quotes. In the second one it is blue. Perhaps this is just the way devtools works, and a fix isn't easy/possible here, but I wonder if wrapping it in quotes could be helpful?
(def x [])
(alter-meta! x #(assoc % :ref x))
(.log js/console x)
CLJS DevTools Error Maximum call stack size exceeded
In CLJS DevTools 0.9.1, an exception was raised during value formatting.
RangeError: Maximum call stack size exceeded
at cljs.core.IndexedSeq.cljs$core$IIndexed$_nth$arity$3 (core.cljs:1479)
at Function.cljs.core.nth.cljs$core$IFn$_invoke$arity$3 (core.cljs:1796)
at cljs$core$nth (core.cljs:1752)
at Function.devtools.formatters.markup.print_with.cljs$core$IFn$_invoke$arity$variadic (markup.cljs:22)
at devtools$formatters$markup$print_with (markup.cljs:22)
at Function.devtools.formatters.markup.print_via_writer.cljs$core$IFn$_invoke$arity$variadic (markup.cljs:30)
at devtools$formatters$markup$print_via_writer (markup.cljs:29)
at devtools$formatters$markup$_LT_preview_GT_ (markup.cljs:111)
at devtools$formatters$markup$_LT_meta_GT_ (markup.cljs:207)
at Function.devtools.formatters.markup._LT_meta_wrapper_GT_.cljs$core$IFn$_invoke$arity$variadic (markup.cljs:212)
Another stack trace with (def x [:foo 1])
CLJS DevTools Error Maximum call stack size exceeded
In CLJS DevTools 0.9.1, an exception was raised during value formatting.
RangeError: Maximum call stack size exceeded
at Object.cljs$core$apply_to [as apply_to] (core.cljs:3719)
at Function.cljs.core.apply.cljs$core$IFn$_invoke$arity$3 (core.cljs:3738)
at cljs$core$apply (core.cljs:3722)
at Function.devtools.formatters.state.update_current_state_BANG_.cljs$core$IFn$_invoke$arity$variadic (state.cljs:32)
at devtools$formatters$state$update_current_state_BANG_ (state.cljs:30)
at devtools$formatters$state$push_object_to_current_history_BANG_ (state.cljs:37)
at devtools$formatters$printing$alt_printer_impl (printing.cljs:117)
at Object.cljs$core$pr_writer [as pr_writer] (core.cljs:9355)
at cljs$core$pr_seq_writer (core.cljs:9359)
at printing.cljs:141
The defaults.cljs file provides a :header-post-handelr
(sic) which presumedly is a typo.
I have implemented custom writers for goog.date.Date using IPrintWithWriter
. The #gdate
shows correctly but the actual parsed object does not show as it is supposed to. In the REPL it shows #gdate [2016 5 29]
but in cljs-devtools it shows #gdate [object Object]
. Is this working for others?
Currently it's quite tricky to get good output from cljs.spec. Reason being that the ex-info thrown includes the full spec commentary in ex-message. This includes the serialised val which failed. In my case this can fill the console many times over.
Alex Miller recommended catching these exceptions and using the ex-data to present the spec nicely. (e.g. don't print the ex-message to the console). This would be fine except it's difficult to catch all errors due to the nature of how UI code executes (react render loop, re-frame dispatch queue, callbacks)
How about automatically detecting and pretty formatting ex-info errors thrown by cljs.spec?
I can't seem to bring the code size down with a barely empty project through dead-code elimination alone, even when following the installation instructions to the letter.
The template used was reagent-figwheel with only devtools
and reagent
as dependencies. I've fiddled with the goog.DEBUG
flag, and then removed devtools
from the :require
and :dependencies
vectors.
Type | Size |
---|---|
:dependencies + :require + goog.DEBUG true |
1.9 MB |
:dependencies + :require + goog.DEBUG false |
1.5 MB |
:dependencies + :require + no mention at all |
1.6 MB |
:dependencies + no :require + no mention at all |
763 KB |
no :dependencies + no :require + no mention at all |
763 KB |
The first two rows followed the instructions from the release notes. There's a single mention of (devtools/install!)
within a (when ^boolean js/goog.DEBUG ...)
block. The other three had this line removed manually.
Google Closure's shaved 400kb of the build, but that's still a 800kb increase for a :require
without a single mention of devtools
! Is this the best I can expect from dead code elimination?
Here's the code used for the builds (e.g. lein new reagent-figwheel +devtools
):
;##################
;### profile.cljs
(defproject devtools-dce "0.1.0-SNAPSHOT"
:dependencies [[org.clojure/clojure "1.8.0"]
[org.clojure/clojurescript "1.9.229"]
[reagent "0.6.0"]
[binaryage/devtools "0.8.2"]]
[...]
:cljsbuild
{:builds
[{:id "min"
:source-paths ["src/cljs"]
:compiler {:main devtools-dce.core
:optimizations :advanced
:output-to "resources/public/js/compiled/app.js"
:output-dir "resources/public/js/compiled/min"
:closure-defines {goog.DEBUG false}
:pseudo-names true ;; added to exacerbate size difference
:pretty-print false}}
]})
;##############
;## core.cljs
(ns devtools-dce.core
(:require
[reagent.core :as reagent]
[devtools.core :as devtools]
))
[...]
(defn dev-setup [] ;; inlining into `main` made no difference
(when ^boolean js/goog.DEBUG
(enable-console-print!)
(println "dev mode")
(devtools/install!)
))
(defn ^:export main []
(dev-setup)
(reload))
If I am running Chrome in a fresh profile, I will sometimes forget to enable Custom Formatters and get confused for a bit when I see the raw JS objects being logged to the console. Is there any way for devtools to detect if custom formatters are enabled and print a big red warning if they aren't?
Firefox is gaining popularity since the Quantum release. I'm wondering what the best approach for implementing cljs-devtools in Firefox would be:
I'm happy to give this a try once a sketch for a way forward is made. And thank you so much for your work in cljs-devtools, it's super awesome!
In CLJS DevTools 0.9.9, an exception was raised during value formatting.
Error: No protocol method IDeref.-deref defined for type function: function (){
return re_frame.core.subscribe.call(null,new cljs.core.PersistentVector(null, 2, 5, cljs.core.PersistentVector.EMPTY_NODE, [new cljs.core.Keyword("form","cur-field","form/cur-field",-1263496756),arg], null));
}
at Object.cljs$core$missing_protocol [as missing_protocol] (core.cljs:316)
at Object.cljs$core$_deref [as _deref] (core.cljs:671)
at cljs$core$deref (core.cljs:1449)
at core.cljs:4680
at cljs.core.map.cljs$core$IFn$_invoke$arity$2 (core.cljs:4680)
at cljs.core.LazySeq.sval (core.cljs:3394)
at cljs.core.LazySeq.cljs$core$ISeqable$_seq$arity$1 (core.cljs:3448)
at Object.cljs$core$seq [as seq] (core.cljs:1210)
at Object.cljs$core$pr_sequential_writer [as pr_sequential_writer] (core.cljs:9856)
at cljs.core.LazySeq.cljs$core$IPrintWithWriter$_pr_writer$arity$3 (core.cljs:10139)
Hi, I wanted to try devtools today, but I get this exception:
clojure.lang.ExceptionInfo: No such namespace: cljs.stacktrace, could not locate cljs/stacktrace.cljs or cljs/stacktrace.cljc at line 1 file:/home/dario/.m2/repository/binaryage/devtools/0.4.1/devtools-0.4.1.jar!/devtools/sanity_hints.cljs {:file "file:/home/dario/.m2/repository/binaryage/devtools/0.4.1/devtools-0.4.1.jar!/devtools/sanity_hints.cljs", :line 1, :column 1, :tag :cljs/analysis-error}
at clojure.core$ex_info.invoke(core.clj:4593)
at cljs.analyzer$error.invoke(analyzer.clj:379)
at cljs.analyzer$error.invoke(analyzer.clj:377)
at cljs.analyzer$analyze_deps.invoke(analyzer.clj:1264)
at cljs.analyzer$eval1860$fn__1862.invoke(analyzer.clj:1516)
at clojure.lang.MultiFn.invoke(MultiFn.java:251)
at cljs.analyzer$analyze_seq.invoke(analyzer.clj:1861)
at cljs.analyzer$analyze$fn__2108.invoke(analyzer.clj:1953)
at cljs.analyzer$analyze.invoke(analyzer.clj:1946)
at cljs.analyzer$analyze_file$fn__2159.invoke(analyzer.clj:2190)
at cljs.analyzer$analyze_file.invoke(analyzer.clj:2185)
at cljs.analyzer$analyze_deps.invoke(analyzer.clj:1262)
at cljs.analyzer$eval1860$fn__1862.invoke(analyzer.clj:1516)
at clojure.lang.MultiFn.invoke(MultiFn.java:251)
at cljs.analyzer$analyze_seq.invoke(analyzer.clj:1861)
at cljs.analyzer$analyze$fn__2108.invoke(analyzer.clj:1953)
at cljs.analyzer$analyze.invoke(analyzer.clj:1946)
at cljs.analyzer$analyze_file$fn__2159.invoke(analyzer.clj:2190)
at cljs.analyzer$analyze_file.invoke(analyzer.clj:2185)
at cljs.analyzer$analyze_deps.invoke(analyzer.clj:1262)
at cljs.analyzer$eval1860$fn__1862.invoke(analyzer.clj:1516)
at clojure.lang.MultiFn.invoke(MultiFn.java:251)
at cljs.analyzer$analyze_seq.invoke(analyzer.clj:1861)
at cljs.analyzer$analyze$fn__2108.invoke(analyzer.clj:1953)
at cljs.analyzer$analyze.invoke(analyzer.clj:1946)
at cljs.analyzer$analyze_file$fn__2159.invoke(analyzer.clj:2190)
at cljs.analyzer$analyze_file.invoke(analyzer.clj:2185)
at figwheel_sidecar.repl$analyze_build.invoke(repl.clj:252)
at figwheel_sidecar.repl$analyze_builds.invoke(repl.clj:257)
at figwheel_sidecar.repl$run_autobuilder_helper.invoke(repl.clj:305)
at figwheel_sidecar.repl$start_autobuild.invoke(repl.clj:376)
at figwheel_sidecar.repl$run_autobuilder.invoke(repl.clj:535)
at user$eval17992.invoke(form-init4556655145684270557.clj:1)
at clojure.lang.Compiler.eval(Compiler.java:6782)
at clojure.lang.Compiler.eval(Compiler.java:6772)
at clojure.lang.Compiler.load(Compiler.java:7227)
at clojure.lang.Compiler.loadFile(Compiler.java:7165)
at clojure.main$load_script.invoke(main.clj:275)
at clojure.main$init_opt.invoke(main.clj:280)
at clojure.main$initialize.invoke(main.clj:308)
at clojure.main$null_opt.invoke(main.clj:343)
at clojure.main$main.doInvoke(main.clj:421)
at clojure.lang.RestFn.invoke(RestFn.java:421)
at clojure.lang.Var.invoke(Var.java:383)
at clojure.lang.AFn.applyToHelper(AFn.java:156)
at clojure.lang.Var.applyTo(Var.java:700)
at clojure.main.main(main.java:37)
Subprocess failed
CLJS DevTools Error target.addEventListener is not a function
TypeError: target.addEventListener is not a function
at listen (events.js:68)
at Feature.handleGeometryChanged_ (Feature.js:282)
at Feature.Target.dispatchEvent (Target.js:162)
at Feature.BaseObject.notify (Object.js:212)
at Feature.BaseObject.set (Object.js:233)
at Feature.BaseObject.setProperties (Object.js:248)
at new Feature (Feature.js:167)
at Object.tools$mapping$add_route [as add_route] (mapping.cljs:55)
at mapping.cljs:63
at Object.sval (core.cljs:3422)
---
Please report the issue here: https://github.com/binaryage/cljs-devtools/issues
What other information will be needed to report the bug properly?
I'm not sure how custom formatters work, but the logs are currently hard to read when devtools is in dark mode. I imagine the colors are customizable, but it would be nice if the default formatters had a config option for viewing in dark mode (any dark foreground colors would be swapped with lighter ones).
I'm trying to install cljs-devtools for the first time. If I do (devtools.core/install! [:formatters :hints])
and then try to evaluate something which gives an error, like just calling a function that does not exist, I get an error:
GET http://localhost:9500/null 404 (Not Found) @ hints.cljs:62
Did I do something wrong? I added devtools as a dependency in deps.edn. I'm using figwheel-main, and it installs formatters, but I haven't yet figured out how to get it to install :hints too automatically. I added :external-config {:devtools/config {:features-to-install [:formatters :hints]}}}
in my figwheel-main dev.cljs.edn
file, but when checking with (devtools.core/installed? :hints)
it's false. So I did install!
as above and got the error.
The full stack trace is:
devtools$hints$ajax_reader @ hints.cljs:62
devtools$hints$retrieve_javascript_source @ hints.cljs:67
devtools$hints$mark_null_call_site_location @ hints.cljs:88
devtools$hints$make_sense_of_the_error @ hints.cljs:97
devtools$hints$error_object_sense @ hints.cljs:109
devtools$hints$type_error_to_string @ hints.cljs:118
(anonymous) @ hints.cljs:136
(anonymous) @ core.cljs:2963
cljs$core$pr_writer_impl @ core.cljs:10174
cljs$core$pr_writer @ core.cljs:10183
cljs$core$pr_seq_writer @ core.cljs:10186
cljs$core$pr_sb_with_opts @ core.cljs:10194
cljs$core$pr_str_with_opts @ core.cljs:10204
(anonymous) @ core.cljs:10232
cljs$core$pr_str @ core.cljs:10229
figwheel$repl$eval_javascript_STAR__STAR_ @ repl.cljc:374
(anonymous) @ repl.cljc:384
G__13008__2 @ core.cljs:11039
G__13008 @ core.cljs:11025
(anonymous) @ repl.cljc:477
goog.events.EventTarget.fireListeners @ eventtarget.js:284
goog.events.EventTarget.dispatchEventInternal_ @ eventtarget.js:381
goog.events.EventTarget.dispatchEvent @ eventtarget.js:196
goog.net.WebSocket.onMessage_ @ websocket.js:426
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.