|
46 | 46 |
|
47 | 47 | (defonce ns-first-segments (atom '#{"cljs" "clojure"}))
|
48 | 48 |
|
| 49 | +; Helper fn |
| 50 | +(defn shadow-depth [s] |
| 51 | + (let [{:keys [name info]} s] |
| 52 | + (loop [d 0, {:keys [shadow]} info] |
| 53 | + (cond |
| 54 | + shadow (recur (inc d) shadow) |
| 55 | + (@ns-first-segments (str name)) (inc d) |
| 56 | + :else d)))) |
| 57 | + |
49 | 58 | (defn munge
|
50 | 59 | ([s] (munge s js-reserved))
|
51 | 60 | ([s reserved]
|
52 | 61 | (if (map? s)
|
53 | 62 | ; Unshadowing
|
54 | 63 | (let [{:keys [name field] :as info} s
|
55 |
| - depth (loop [d 0, {:keys [shadow]} info] |
56 |
| - (cond |
57 |
| - shadow (recur (inc d) shadow) |
58 |
| - (@ns-first-segments (str name)) (inc d) |
59 |
| - :else d)) |
| 64 | + depth (shadow-depth s) |
60 | 65 | renamed (*lexical-renames* (System/identityHashCode s))
|
61 | 66 | munged-name (munge (cond field (str "self__." name)
|
62 | 67 | renamed renamed
|
|
220 | 225 | (let [minfo {:gcol @*cljs-gen-col*
|
221 | 226 | :gline @*cljs-gen-line*
|
222 | 227 | :name var-name}]
|
223 |
| - (update-in m [line] |
| 228 | + ; Dec the line number for 0-indexed line numbers. |
| 229 | + ; tools.reader has 0-indexed line number, chrome |
| 230 | + ; expects 1-indexed source maps. |
| 231 | + (update-in m [(dec line)] |
224 | 232 | (fnil (fn [m]
|
225 | 233 | (update-in m [(or column 0)]
|
226 | 234 | (fnil (fn [v] (conj v minfo)) [])))
|
227 | 235 | (sorted-map)))))))))
|
228 |
| - (when-not (= :statement (:context env)) |
229 |
| - (emit-wrap env (emits (munge info)))))) |
| 236 | + ; We need a way to write bindings out to source maps and javascript |
| 237 | + ; without getting wrapped in an emit-wrap calls, otherwise we get |
| 238 | + ; e.g. (function greet(return x, return y) {}). |
| 239 | + (if (:binding-form? arg) |
| 240 | + ; Emit the arg map so shadowing is properly handled when munging |
| 241 | + ; (prevents duplicate fn-param-names) |
| 242 | + (emits (munge arg)) |
| 243 | + (when-not (= :statement (:context env)) |
| 244 | + (emit-wrap env (emits (munge info))))))) |
230 | 245 |
|
231 | 246 | (defmethod emit :meta
|
232 | 247 | [{:keys [expr meta env]}]
|
|
364 | 379 | (defn emit-apply-to
|
365 | 380 | [{:keys [name params env]}]
|
366 | 381 | (let [arglist (gensym "arglist__")
|
367 |
| - delegate-name (str (munge name) "__delegate") |
368 |
| - params (map munge params)] |
| 382 | + delegate-name (str (munge name) "__delegate")] |
369 | 383 | (emitln "(function (" arglist "){")
|
370 | 384 | (doseq [[i param] (map-indexed vector (drop-last 2 params))]
|
371 |
| - (emits "var " param " = cljs.core.first(") |
| 385 | + (emits "var ") |
| 386 | + (emit param) |
| 387 | + (emits " = cljs.core.first(") |
372 | 388 | (emitln arglist ");")
|
373 | 389 | (emitln arglist " = cljs.core.next(" arglist ");"))
|
374 | 390 | (if (< 1 (count params))
|
375 | 391 | (do
|
376 |
| - (emitln "var " (last (butlast params)) " = cljs.core.first(" arglist ");") |
377 |
| - (emitln "var " (last params) " = cljs.core.rest(" arglist ");") |
378 |
| - (emitln "return " delegate-name "(" (string/join ", " params) ");")) |
| 392 | + (emits "var ") |
| 393 | + (emit (last (butlast params))) |
| 394 | + (emitln " = cljs.core.first(" arglist ");") |
| 395 | + (emits "var ") |
| 396 | + (emit (last params)) |
| 397 | + (emitln " = cljs.core.rest(" arglist ");") |
| 398 | + (emits "return " delegate-name "(") |
| 399 | + (doseq [param params] |
| 400 | + (emit param) |
| 401 | + (when-not (= param (last params)) (emits ","))) |
| 402 | + (emitln ");")) |
379 | 403 | (do
|
380 |
| - (emitln "var " (last params) " = cljs.core.seq(" arglist ");") |
381 |
| - (emitln "return " delegate-name "(" (string/join ", " params) ");"))) |
| 404 | + (emits "var ") |
| 405 | + (emit (last params)) |
| 406 | + (emitln " = cljs.core.seq(" arglist ");") |
| 407 | + (emits "return " delegate-name "(") |
| 408 | + (doseq [param params] |
| 409 | + (emit param) |
| 410 | + (when-not (= param (last params)) (emits ","))) |
| 411 | + (emitln ");"))) |
382 | 412 | (emits "})")))
|
383 | 413 |
|
| 414 | +(defn emit-fn-params [params] |
| 415 | + (doseq [param params] |
| 416 | + (emit param) |
| 417 | + ; Avoid extraneous comma (function greet(x, y, z,) |
| 418 | + (when-not (= param (last params)) |
| 419 | + (emits ",")))) |
| 420 | + |
384 | 421 | (defn emit-fn-method
|
385 | 422 | [{:keys [type name variadic params expr env recurs max-fixed-arity]}]
|
386 | 423 | (emit-wrap env
|
387 |
| - (emitln "(function " (munge name) "(" (comma-sep (map munge params)) "){") |
| 424 | + ; Should we emit source-map for this inner declaration? |
| 425 | + ; It may be unnecessary. |
| 426 | + ; hello.core.greet = (function greet(){}) |
| 427 | + ; e.g. Do we need a source-map entry for this? --^ |
| 428 | + |
| 429 | + ; If so, we can't just munge the name and spit out a string. |
| 430 | + (emits "(function " (munge name) "(") |
| 431 | + (emit-fn-params params) |
| 432 | + (emits "){") |
388 | 433 | (when type
|
389 | 434 | (emitln "var self__ = this;"))
|
390 | 435 | (when recurs (emitln "while(true){"))
|
|
399 | 444 | (emit-wrap env
|
400 | 445 | (let [name (or name (gensym))
|
401 | 446 | mname (munge name)
|
402 |
| - params (map munge params) |
403 | 447 | delegate-name (str mname "__delegate")]
|
404 | 448 | (emitln "(function() { ")
|
405 |
| - (emitln "var " delegate-name " = function (" (comma-sep params) "){") |
| 449 | + (emits "var " delegate-name " = function (") |
| 450 | + (doseq [param params] |
| 451 | + (emit param) |
| 452 | + (when-not (= param (last params)) (emits ","))) |
| 453 | + (emits "){") |
406 | 454 | (when recurs (emitln "while(true){"))
|
407 | 455 | (emits expr)
|
408 | 456 | (when recurs
|
|
417 | 465 | (when type
|
418 | 466 | (emitln "var self__ = this;"))
|
419 | 467 | (when variadic
|
420 |
| - (emitln "var " (last params) " = null;") |
| 468 | + (emits "var ") |
| 469 | + (emit (last params)) |
| 470 | + (emits " = null;") |
421 | 471 | (emitln "if (arguments.length > " (dec (count params)) ") {")
|
422 |
| - (emitln " " (last params) " = cljs.core.array_seq(Array.prototype.slice.call(arguments, " (dec (count params)) "),0);") |
| 472 | + (emits " ") |
| 473 | + (emit (last params)) |
| 474 | + (emits " = cljs.core.array_seq(Array.prototype.slice.call(arguments, " (dec (count params)) "),0);") |
423 | 475 | (emitln "} "))
|
424 |
| - (emitln "return " delegate-name ".call(" (string/join ", " (cons "this" params)) ");") |
| 476 | + (emits "return " delegate-name ".call(this,") |
| 477 | + (doseq [param params] |
| 478 | + (emit param) |
| 479 | + (when-not (= param (last params)) (emits ","))) |
| 480 | + (emits ");") |
425 | 481 | (emitln "};")
|
426 | 482 |
|
427 | 483 | (emitln mname ".cljs$lang$maxFixedArity = " max-fixed-arity ";")
|
|
453 | 509 | (let [has-name? (and name true)
|
454 | 510 | name (or name (gensym))
|
455 | 511 | mname (munge name)
|
456 |
| - maxparams (map munge (apply max-key count (map :params methods))) |
| 512 | + maxparams (apply max-key count (map :params methods)) |
457 | 513 | mmap (into {}
|
458 | 514 | (map (fn [method]
|
459 | 515 | [(munge (symbol (str mname "__" (count (:params method)))))
|
|
474 | 530 | (concat (butlast maxparams) ['var_args])
|
475 | 531 | maxparams)) "){")
|
476 | 532 | (when variadic
|
477 |
| - (emitln "var " (last maxparams) " = var_args;")) |
| 533 | + (emits "var ") |
| 534 | + (emit (last maxparams)) |
| 535 | + (emitln " = var_args;")) |
478 | 536 | (emitln "switch(arguments.length){")
|
479 | 537 | (doseq [[n meth] ms]
|
480 | 538 | (if (:variadic meth)
|
|
540 | 598 | (gensym (str (:name %) "-")))
|
541 | 599 | bindings)))]
|
542 | 600 | (doseq [{:keys [init] :as binding} bindings]
|
543 |
| - (emitln "var " (munge binding) " = " init ";")) |
| 601 | + (emits "var ") |
| 602 | + (emit binding) ; Binding will be treated as a var |
| 603 | + (emits " = " init ";")) |
544 | 604 | (when is-loop (emitln "while(true){"))
|
545 | 605 | (emits expr)
|
546 | 606 | (when is-loop
|
|
0 commit comments