set!

special formsince v0.0-927 clojure.core/set!Edit
(set! var-symbol expr)
(set! (.- instance-expr instanceFieldName-symbol) expr)

Details:

Sets js-var to val using the JavaScript = operator.


See Also:


Source docstring:
Used to set vars and JavaScript object fields
Parser code @ clojurescript:src/main/clojure/cljs/analyzer.cljc
(defmethod parse 'set!
  [_ env [_ target val alt :as form] _ _]
  (let [[target val] (if (= 4 (count form))
                       ;; (set! o -prop val)
                       [`(. ~target ~val) alt]
                       [target val])]
    (disallowing-recur
      (binding [*private-var-access-nowarn* true]
        (let [enve  (assoc env :context :expr)
              texpr (cond
                      (symbol? target)
                      (do
                        (cond
                          (and (= target '*unchecked-if*)   ;; TODO: proper resolve
                               (or (true? val) (false? val)))
                          (set! *unchecked-if* val)

                          (and (= target '*unchecked-arrays*) ;; TODO: proper resolve
                               (or (true? val) (false? val)))
                          (set! *unchecked-arrays* val)

                          (and (= target '*warn-on-infer*)
                               (or (true? val) (false? val)))
                          (set! *cljs-warnings* (assoc *cljs-warnings* :infer-warning val)))
                        (when (some? (:const (resolve-var (dissoc env :locals) target)))
                          (throw (error env "Can't set! a constant")))
                        (let [local (handle-symbol-local target (-> env :locals target))]
                          (when-not (or (nil? local)
                                        (and (:field local)
                                             (or (:mutable local)
                                                 (:unsynchronized-mutable local)
                                                 (:volatile-mutable local))))
                            (throw (error env "Can't set! local var or non-mutable field"))))
                        (analyze-symbol enve target))

                      :else
                      (when (seq? target)
                        (let [texpr (if (-> target meta :extend-type)
                                      ;; we're setting a prototype via extend-type macro
                                      ;; nothing to warn
                                      (binding [*cljs-warnings*
                                                (assoc *cljs-warnings* :infer-warning false)]
                                        (analyze-seq enve target nil))
                                      (analyze-seq enve target nil))]
                          (when (:field texpr)
                            texpr))))
              vexpr (analyze enve val)]
          ;; as top level fns are decomposed for Closure cross-module code motion, we need to
          ;; restore their :methods information
          (when (seq? target)
            (let [sym  (some-> target second)
                  meta (meta sym)]
              (when-let [info (and (= :fn (:op vexpr)) (:top-fn meta))]
                (swap! env/*compiler* update-in
                  [::namespaces (-> env :ns :name) :defs sym :methods]
                  (fnil conj [])
                  ;; just use original fn meta, as the fn method is already desugared
                  ;; only get tag from analysis
                  (merge
                    (select-keys info [:fixed-arity :variadic?])
                    (select-keys (-> vexpr :methods first) [:tag]))))))
          (when-not texpr
            (throw (error env "set! target must be a field or a symbol naming a var")))
          (cond
            (and (not (:def-emits-var env))                 ;; non-REPL context
                 (some? ('#{*unchecked-if* *unchecked-arrays* *warn-on-infer*} target)))
            {:env env :op :no-op}

            :else
            {:env env :op :set! :form form :target texpr :val vexpr
             :children [:target :val]}))))))

Emitting code @ clojurescript:src/main/clojure/cljs/compiler.cljc
(defmethod emit* :set!
  [{:keys [target val env]}]
  (emit-wrap env (emits "(" target " = " val ")")))