cljs.core/print appends newline in Node-based REPLs

Description

In all cases below, the functions `print-things1`, `print-things2`, and `print-ints1` are defined as follows:

```

(defn print-things1 []

(print "a")

(print "b")

(print "c")

(println "d")

(print "e" "f")

(print "g"))

(defn print-things2 []

(println "x")

(println "y")

(println "z" "w"))

(defn print-ints1 []

(print 1)

(print 2)

(print 3 4 5))

```

Behavior with Clojure/Java 1.10.1 REPL (and many older Clojure versions):

```

$ clojure

Clojure 1.10.1

;; First define functions as shown above

user=> (print-things1)

abcd

e fgnil

user=> (print-things2)

x

y

z w

nil

user=> (print-ints1)

123 4 5nil

user=>

```

Note that `print` does not append a newline to the output at the end, whereas `println` does. Both `print` and `println` print a single space character between multiple arguments.

Current behavior with version 1.10.520 of CloureScript, and also with latest master as of 2019-Aug-08, which is this commit SHA: 3f5a60a31ac1aae9eb509da26249db51316c34e6

When starting a Node-based REPL from the terminal with the command below:

```

$ clojure -m cljs.main --repl-env node

ClojureScript 1.10.520

;; First define functions as shown above

cljs.user=> (print-things1)

a

b

c

d

e f

g

nil

cljs.user=> (print-things2)

x

y

z w

nil

cljs.user=> (print-ints1)

1

2

3 4 5

nil

cljs.user=>

```

Note that `print` always appends a newline after the values printed, and thus behaves the same as Clojure/Java and ClojureScript `println`.

You get exactly the same behavior when starting a Node-based ClojureScript REPL by connecting via a socket REPL using the `deps.edn` file below, starting Clojure using the command `clojure -A:socket`, and then `telnet localhost 50505` from another terminal.

```

{:aliases

{:socket {:jvm-opts ["-Dclojure.server.repl={:port,50505,:accept,cljs.server.node/repl}"]}}

:deps {org.clojure/clojurescript {:mvn/version "1.10.520"}}}

```

Implementation details I noticed while developing a proposed patch:

The `*print-fn*` in ClojureScript is always passed string arguments. A call like `(print 1 2)` causes `*print-fn*` to be called once with the string `"1 2"`. That seems perfectly reasonable to me.

I had some debug statements recording details during the execution of cljs.core/maybe-enable-print!, and whenever I started a Node-based REPL, the value of `*target*` at that time was always `"default"`. The condition `(exists? js/console)` is true when starting a Node-based REPL using the commands above, so `enable-console-print!` is the code being used to set up `*print-fn*` with today's ClojureScript. `enable-console-print!` sets `*print-fn*` to use the log method of js/console, which is documented to always append a newline after printing its arguments.

Environment

None

Activity

Show:
Andy Fingerhut
August 9, 2019, 1:54 AM

Same test results without the patch, and better results with the patch, tested with the following additional environment:

 

Andy Fingerhut
August 9, 2019, 2:21 AM

I was curious whether the JavaScript objects and methods used in the patch existed across multiple versions of Node.js or not. On a macOS 10.13.6 system, MacPorts made it quick for me to install each of the following versions of node, one at a time:

v6.17.1
v8.16.0
v10.13.0
v11.15.0
v12.7.0

All of them showed the same behavior when given the following statements to run in a Node REPL (JavaScript, not ClojureScript):

 

Andy Fingerhut
August 10, 2019, 12:34 AM

Note: The patch cljs-3153-fix-v1.patch is probably missing some ‘entry points’ for running on Node.js, because when I try out my locally modified version of ClojureScript with that patch, and use cljs-test-runner on the tools.cli project, with some print calls in one of the deftest forms, they still append a newline, unless I explicitly call the function enable-nodesj-print! added by that patch in the deftest. I don’t have a good guess where to look for that entry point right now.

Andy Fingerhut
August 10, 2019, 1:50 AM

I learned that cljs-test-runner is using a library called doo, and it calls enable-console-print! after cljs.core is evaluated, but before the deftest functions start being called. I will wait for this issue to be resolved however, and then can suggest to the doo library author to consider changing its behavior.

Andy Fingerhut
August 28, 2019, 9:32 PM

Attached patch cljs-3153-v2.patch seems a little bit better to me than cljs-3153-v1.patch. The v1 version kept an existing call in the Node REPL setup code to enable-console-print! that the v2 patch replaces with the new function enable-nodejs-print!

Otherwise it is identical, and works just as well.

Assignee

Unassigned

Reporter

Andy Fingerhut

Labels

None

Approval

None

Patch

None

Priority

Minor
Configure