{"action":"created","issue":{"url":"https://api.github.com/repos/omcljs/ambly/issues/19","labels_url":"https://api.github.com/repos/omcljs/ambly/issues/19/labels{/name}","comments_url":"https://api.github.com/repos/omcljs/ambly/issues/19/comments","events_url":"https://api.github.com/repos/omcljs/ambly/issues/19/events","html_url":"https://github.com/omcljs/ambly/issues/19","id":57512847,"number":19,"title":"Stackframes for REPL-defined functions","user":{"login":"mfikes","id":1723464,"avatar_url":"https://avatars.githubusercontent.com/u/1723464?v=3","gravatar_id":"","url":"https://api.github.com/users/mfikes","html_url":"https://github.com/mfikes","followers_url":"https://api.github.com/users/mfikes/followers","following_url":"https://api.github.com/users/mfikes/following{/other_user}","gists_url":"https://api.github.com/users/mfikes/gists{/gist_id}","starred_url":"https://api.github.com/users/mfikes/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mfikes/subscriptions","organizations_url":"https://api.github.com/users/mfikes/orgs","repos_url":"https://api.github.com/users/mfikes/repos","events_url":"https://api.github.com/users/mfikes/events{/privacy}","received_events_url":"https://api.github.com/users/mfikes/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/omcljs/ambly/labels/enhancement","name":"enhancement","color":"84b6eb"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2015-02-12T20:12:00Z","updated_at":"2015-02-12T20:29:38Z","closed_at":null,"body":"@swannodette Considering a potential enhancement. Could use feedback. Low priority IMHO.\r\n\r\nA user could define functions in the REPL that call into functions that are defined in source and then call those REPL-defined functions. If an exception occurs, JSC will emit only the function names in frames for REPL-defined functions.\r\n\r\nThe Clojure REPL supports this, using `NO_SOURCE_FILE` and line 1.\r\n\r\nTo support this would require minor changes to Ambly, and some changes to the underlying ClojureScript REPL as well.\r\n\r\nHere is a concrete example showing that it almost works:\r\n\r\nIn actual source, I have:\r\n\r\n```clojure\r\n(ns hello-ambly.core)\r\n\r\n;; some lines have been deleted from here for brevity, \r\n;; so stack line numbers below are off\r\n\r\n(defn test-exception-two [] \r\n  (ffirst 1))\r\n\r\n(defn test-exception-one []\r\n  (test-exception-two))\r\n```\r\n\r\nAnd in the Ambly REPL:\r\n\r\n```clojure\r\n(require 'hello-ambly.core)\r\n(defn wrap-two [] (hello-ambly.core/test-exception-one))\r\n(defn wrap-one [] (wrap-two))\r\n```\r\n\r\nHere is it nearly working:\r\n\r\n```\r\nClojureScript:cljs.user> (wrap-one)\r\nError: 1 is not ISeqable\r\n\t cljs.core/seq (out/cljs/core.cljs:727:13)\r\n\t cljs.core/first (out/cljs/core.cljs:736:7)\r\n\t cljs.core/ffirst (out/cljs/core.cljs:1155:3)\r\n\t hello-ambly.core/test-exception-two (out/hello_ambly/core.cljs:16:3)\r\n\t hello-ambly.core/test-exception-one (out/hello_ambly/core.cljs:19:3)\r\n\t wrap_two (out/NO_SOURCE_FILE:1:1)\r\n\t wrap_one (out/NO_SOURCE_FILE:1:1)\r\nnil\r\n```\r\n\r\nThe two things wrong:\r\n1. `wrap_one` should be resolved to `cljs.user/wrap-one`\r\n2, `NO_SOURCE_FILE` needs a little special handling to prevent code assuming it is a file in the `:output-dir`: `out/NO_SOURCE_FILE`.\r\n\r\nI did the above by changing Ambly's parser a little to emit:\r\n\r\n```clojure\r\n[{:file \"cljs/core.js\", :function \"seq\", :line 4212, :column 17}\r\n {:file \"cljs/core.js\", :function \"first\", :line 4242, :column 22}\r\n {:file \"cljs/core.js\", :function \"ffirst\", :line 5292, :column 39} \r\n{:file \"hello_ambly/core.js\", :function \"test_exception_two\", :line 19, :column 29}\r\n {:file \"hello_ambly/core.js\", :function \"test_exception_one\", :line 22, :column 48} \r\n{:file \"NO_SOURCE_FILE\", :function \"wrap_two\", :line 1, :column 1} \r\n{:file \"NO_SOURCE_FILE\", :function \"wrap_one\", :line 1, :column 1}]\r\n```\r\n\r\n```clojure\r\n(defn stack-line->canonical-frame\r\n  \"Parses a stack line into a frame representation, returning nil\r\n  if parse failed.\"\r\n  [stack-line opts]\r\n  (let [[function file line column]\r\n        (rest (re-matches #\"(.*)@file://(.*):([0-9]+):([0-9]+)\"\r\n                stack-line))]\r\n    (if-not (#{\"\" \"global code\"} stack-line)\r\n      {:file     (if file\r\n                   (string/replace\r\n                     (.getCanonicalFile (io/file file))\r\n                     (str (System/getProperty \"user.dir\") File/separator\r\n                       (util/output-directory opts) File/separator)\r\n                     \"\")\r\n                   \"NO_SOURCE_FILE\")\r\n       :function (or function (string/trim stack-line))\r\n       :line     (if line (Long/parseLong line) 1)\r\n       :column   (if column (Long/parseLong column) 1)})))\r\n```\r\n\r\nThis is a fairly lengthy description and probably needs some hammock time on whether to even pursue it, so I figured I'd drop it in an enhancement ticket here.\r\n"},"comment":{"url":"https://api.github.com/repos/omcljs/ambly/issues/comments/74146500","html_url":"https://github.com/omcljs/ambly/issues/19#issuecomment-74146500","issue_url":"https://api.github.com/repos/omcljs/ambly/issues/19","id":74146500,"user":{"login":"swannodette","id":13516,"avatar_url":"https://avatars.githubusercontent.com/u/13516?v=3","gravatar_id":"","url":"https://api.github.com/users/swannodette","html_url":"https://github.com/swannodette","followers_url":"https://api.github.com/users/swannodette/followers","following_url":"https://api.github.com/users/swannodette/following{/other_user}","gists_url":"https://api.github.com/users/swannodette/gists{/gist_id}","starred_url":"https://api.github.com/users/swannodette/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/swannodette/subscriptions","organizations_url":"https://api.github.com/users/swannodette/orgs","repos_url":"https://api.github.com/users/swannodette/repos","events_url":"https://api.github.com/users/swannodette/events{/privacy}","received_events_url":"https://api.github.com/users/swannodette/received_events","type":"User","site_admin":false},"created_at":"2015-02-12T20:29:38Z","updated_at":"2015-02-12T20:29:38Z","body":"@mfikes ClojureScript enhancement ticket welcome"}}