vouch-opensource / krell

Simple ClojureScript React Native Tooling
Eclipse Public License 1.0
675 stars 37 forks source link

Case statement breaking at REPL #64

Closed olivergeorge closed 4 years ago

olivergeorge commented 4 years ago

Steps to reproduce are based on the reagent tutorial.

AwesomeProject % cat deps.edn 
{:deps {io.vouch/krell                {:git/url "https://github.com/vouch-opensource/krell.git"
                                       :sha     "b24b3f1c236cf80dda8cd06d949d391b86308ae7"}
        io.vouch/reagent-react-native {:git/url "https://github.com/vouch-opensource/reagent-react-native.git"
                                       :sha     "54bf52788ab051920ed7641f386177374419e847"}
        reagent                       {:mvn/version "0.10.0"
                                       :exclusions  [cljsjs/react cljsjs/react-dom]}}}

AwesomeProject % cat src/awesome_project/core.cljs 
(ns awesome-project.core
  (:require [reagent.core :as r]
            [reagent.react-native :as rn]))

(js/console.log (pr-str ::hello))

(def fsm-state :idle)

(defn helper
  [state]
  (js/console.log (pr-str ::state state))
  (js/console.log (pr-str ::meta (meta state)))
  (js/console.log (pr-str ::eq(= state :idle)))
  (js/console.log (pr-str ::identical? (identical? state :idle)))
  (case state
    :idle (js/console.log "GOOD: Case statement matches :idle")
    (do (js/console.log (pr-str "BAD: Case statement didn't match :idle against " state))
        )))

(defprotocol IEventQueue
  (-fsm-trigger [this]))

(defrecord EventQueue []
  IEventQueue
  (-fsm-trigger
    [_]
    (helper :idle)
    (helper fsm-state)))

(def event-queue (->EventQueue))

(defn runtest [] (-fsm-trigger event-queue))

(defn ^:export -main [& args]
  (r/as-element
    [rn/view {:style {:flex 1 :align-items "center" :justify-content "center"}}
     [rn/text {:style {:font-size 50}} "Hello Krell!"]]))

Steps to repeat:

  1. Start Krell and iOS App
  2. In the REPL enter (awesome-project.core/runtest)

Expect: Metro log shows GOOD twice

Actual: Metro log shows GOOD once, and BAD once

e.g.

[Sun Apr 26 2020 13:25:01.529]  LOG      :awesome-project.core/state :idle
[Sun Apr 26 2020 13:25:01.530]  LOG      :awesome-project.core/meta nil
[Sun Apr 26 2020 13:25:01.530]  LOG      :awesome-project.core/eq true
[Sun Apr 26 2020 13:25:01.530]  LOG      :awesome-project.core/identical? false
[Sun Apr 26 2020 13:25:01.530]  LOG      GOOD: Case statement matches :idle
[Sun Apr 26 2020 13:25:01.531]  LOG      :awesome-project.core/state :idle
[Sun Apr 26 2020 13:25:01.531]  LOG      :awesome-project.core/meta nil
[Sun Apr 26 2020 13:25:01.531]  LOG      :awesome-project.core/eq true
[Sun Apr 26 2020 13:25:01.531]  LOG      :awesome-project.core/identical? false
[Sun Apr 26 2020 13:25:01.532]  LOG      "BAD: Case statement didn't match :idle against " :idle

The fail case seems to go away once the namespace is reloaded. To repeat the test :cljs/quit and restart the krell REPL (the app refreshes by itself).

Only repeatable on a freshly started REPL.

Infrequently doesn't fail on a freshly started REPL.

olivergeorge commented 4 years ago

Unable to reproduce without krell. Tried as via CLJS repl (based on ClojureScript Quick Start guide) and bundler REPL (based on ClojureScript with Webpack guide)

olivergeorge commented 4 years ago

Updated with simpler example:

Plus a more provocative pass/fail comparison.

olivergeorge commented 4 years ago

Okay, getting somewhere now by debugging execution of that code.

The case statement is testing if the expression is an instance of cljs.core.Keyword. It decides the newly created keyword is not and so the case statement uses nil as the value.

image

olivergeorge commented 4 years ago

Putting simple print statement in cljs.core proves that the (deftype Keyword...) code is run twice and that the awesome-project.core namespace is loaded inbetween them.

[Sun Apr 26 2020 15:37:54.600]  LOG      about to (deftype Keyword...)
[Sun Apr 26 2020 15:37:54.677]  LOG      :awesome-project.core/hello
[Sun Apr 26 2020 15:37:55.969]  LOG      about to (deftype Keyword...)

Ah, the verbose flag makes it clear that cljs.core is loaded twice.

swannodette commented 4 years ago

Give master a try, I made a small tweak so the client knows about these files pushed from the server and doesn't try to fetch them again. If it works for you feel free to close this one. Thanks!

olivergeorge commented 4 years ago

Looks good with master (15307ef).

Using verbose flag I can see Load file: target/cljs/core.js happens once.

Only a few namespaces loaded with the repl now.

Load file: target/goog/string/stringformat.js
Load file: target/cljs/spec/gen/alpha.js
Load file: target/cljs/spec/alpha.js
Load file: target/cljs/repl.js
Load file: target/cljs/pprint.js

Repro steps now pass.